aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/x86/smm/smm_module_loader.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/x86/smm/smm_module_loader.c')
-rw-r--r--src/cpu/x86/smm/smm_module_loader.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/src/cpu/x86/smm/smm_module_loader.c b/src/cpu/x86/smm/smm_module_loader.c
index a396b7df8f..b7de178bd9 100644
--- a/src/cpu/x86/smm/smm_module_loader.c
+++ b/src/cpu/x86/smm/smm_module_loader.c
@@ -19,6 +19,14 @@
#include <cpu/x86/cache.h>
#include <console/console.h>
+#define FXSAVE_SIZE 512
+
+/* FXSAVE area during relocation. While it may not be strictly needed the
+ SMM stub code relies on the FXSAVE area being non-zero to enable SSE
+ instructions within SMM mode. */
+static uint8_t fxsave_area_relocation[CONFIG_MAX_CPUS][FXSAVE_SIZE]
+__attribute__((aligned(16)));
+
/*
* Components that make up the SMRAM:
* 1. Save state - the total save state memory used
@@ -36,6 +44,8 @@ struct smm_stub_params {
u32 stack_top;
u32 c_handler;
u32 c_handler_arg;
+ u32 fxsave_area;
+ u32 fxsave_area_size;
struct smm_runtime runtime;
} __attribute__ ((packed));
@@ -164,7 +174,8 @@ static void smm_stub_place_staggered_entry_points(char *base,
* concurrent areas requested. The save state always lives at the top of SMRAM
* space, and the entry point is at offset 0x8000.
*/
-static int smm_module_setup_stub(void *smbase, struct smm_loader_params *params)
+static int smm_module_setup_stub(void *smbase, struct smm_loader_params *params,
+ void *fxsave_area)
{
size_t total_save_state_size;
size_t smm_stub_size;
@@ -253,6 +264,8 @@ static int smm_module_setup_stub(void *smbase, struct smm_loader_params *params)
stub_params->stack_size = params->per_cpu_stack_size;
stub_params->c_handler = (uintptr_t)params->handler;
stub_params->c_handler_arg = (uintptr_t)params->handler_arg;
+ stub_params->fxsave_area = (uintptr_t)fxsave_area;
+ stub_params->fxsave_area_size = FXSAVE_SIZE;
stub_params->runtime.smbase = (uintptr_t)smbase;
stub_params->runtime.save_state_size = params->per_cpu_save_state_size;
@@ -293,7 +306,7 @@ int smm_setup_relocation_handler(struct smm_loader_params *params)
if (params->num_concurrent_stacks == 0)
params->num_concurrent_stacks = CONFIG_MAX_CPUS;
- return smm_module_setup_stub(smram, params);
+ return smm_module_setup_stub(smram, params, fxsave_area_relocation);
}
/* The SMM module is placed within the provided region in the following
@@ -320,6 +333,9 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
size_t handler_size;
size_t module_alignment;
size_t alignment_size;
+ size_t fxsave_size;
+ void *fxsave_area;
+ size_t total_size;
char *base;
if (size <= SMM_DEFAULT_SIZE)
@@ -350,8 +366,19 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
base += alignment_size;
}
+ fxsave_size = 0;
+ fxsave_area = NULL;
+ if (IS_ENABLED(CONFIG_SSE)) {
+ fxsave_size = FXSAVE_SIZE * params->num_concurrent_stacks;
+ /* FXSAVE area below all the stacks stack. */
+ fxsave_area = params->stack_top;
+ fxsave_area -= total_stack_size + fxsave_size;
+ }
+
/* Does the required amount of memory exceed the SMRAM region size? */
- if ((total_stack_size + handler_size + SMM_DEFAULT_SIZE) > size)
+ total_size = total_stack_size + handler_size;
+ total_size += fxsave_size + SMM_DEFAULT_SIZE;
+ if (total_size > size)
return -1;
if (rmodule_load(base, &smm_mod))
@@ -360,5 +387,5 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
params->handler = rmodule_entry(&smm_mod);
params->handler_arg = rmodule_parameters(&smm_mod);
- return smm_module_setup_stub(smram, params);
+ return smm_module_setup_stub(smram, params, fxsave_area);
}