aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/x86/smm/smm_module_loader.c311
1 files changed, 135 insertions, 176 deletions
diff --git a/src/cpu/x86/smm/smm_module_loader.c b/src/cpu/x86/smm/smm_module_loader.c
index 5b87a9fe1a..071b33673d 100644
--- a/src/cpu/x86/smm/smm_module_loader.c
+++ b/src/cpu/x86/smm/smm_module_loader.c
@@ -414,8 +414,30 @@ int smm_setup_relocation_handler(struct smm_loader_params *params)
params, fxsave_area_relocation);
}
-static int smm_load_module_aseg(const uintptr_t smram_base, const size_t smram_size,
- struct smm_loader_params *params);
+static void setup_smihandler_params(struct smm_runtime *mod_params,
+ uintptr_t smram_base,
+ uintptr_t smram_size,
+ struct smm_loader_params *loader_params)
+{
+ mod_params->smbase = smram_base;
+ mod_params->smm_size = smram_size;
+ mod_params->save_state_size = loader_params->real_cpu_save_state_size;
+ mod_params->num_cpus = loader_params->num_cpus;
+ mod_params->gnvs_ptr = (uint32_t)(uintptr_t)acpi_get_gnvs();
+ const struct cbmem_entry *cbmemc;
+ if (CONFIG(CONSOLE_CBMEM) && (cbmemc = cbmem_entry_find(CBMEM_ID_CONSOLE))) {
+ mod_params->cbmemc = cbmem_entry_start(cbmemc);
+ mod_params->cbmemc_size = cbmem_entry_size(cbmemc);
+ } else {
+ mod_params->cbmemc = 0;
+ mod_params->cbmemc_size = 0;
+ }
+
+ for (int i = 0; i < loader_params->num_cpus; i++) {
+ mod_params->save_state_top[i] = cpus[i].ss_start
+ + loader_params->per_cpu_save_state_size;
+ }
+}
/*
*The SMM module is placed within the provided region in the following
@@ -443,159 +465,83 @@ static int smm_load_module_aseg(const uintptr_t smram_base, const size_t smram_s
* expects a region large enough to encompass the handler and stacks
* as well as the SMM_DEFAULT_SIZE.
*/
-int smm_load_module(const uintptr_t smram_base, const size_t smram_size,
- struct smm_loader_params *params)
+static int smm_load_module_tseg(const uintptr_t smram_base, const size_t smram_size,
+ struct smm_loader_params *params)
{
- struct rmodule smm_mod;
- struct smm_runtime *handler_mod_params;
- size_t total_stack_size;
- size_t handler_size;
- size_t module_alignment;
- size_t alignment_size;
- size_t fxsave_size;
- void *fxsave_area;
- size_t total_size = 0;
- uintptr_t base; /* The base for the permanent handler */
- const struct cbmem_entry *cbmemc;
-
- if (CONFIG(SMM_ASEG))
- return smm_load_module_aseg(smram_base, smram_size, params);
-
if (smram_size <= SMM_DEFAULT_SIZE)
return -1;
- /* Load main SMI handler at the top of SMRAM
- * everything else will go below
- */
- base = smram_base;
- base += smram_size;
-
- /* Fail if can't parse the smm rmodule. */
- if (rmodule_parse(&_binary_smm_start, &smm_mod))
+ struct rmodule smi_handler;
+ if (rmodule_parse(&_binary_smm_start, &smi_handler))
return -1;
- /* Clear SMM region */
- if (CONFIG(DEBUG_SMI))
- memset((void *)smram_base, 0xcd, smram_size);
+ const uintptr_t smram_top = smram_base + smram_size;
- total_stack_size = stack_top - smram_base;
- total_size += total_stack_size;
- /* Stacks are the base of SMRAM */
+ const size_t stm_size =
+ CONFIG(STM) ? CONFIG_MSEG_SIZE - CONFIG_BIOS_RESOURCE_LIST_SIZE : 0;
+ const uintptr_t stm_base = CONFIG(STM) ? smram_top - stm_size : 0;
+ if (stm_size) {
+ printk(BIOS_DEBUG, "STM [0x%lx-0x%lx[\n", stm_base,
+ stm_base + stm_size);
- /* MSEG starts at the top of SMRAM and works down */
- if (CONFIG(STM)) {
- base -= CONFIG_MSEG_SIZE + CONFIG_BIOS_RESOURCE_LIST_SIZE;
- total_size += CONFIG_MSEG_SIZE + CONFIG_BIOS_RESOURCE_LIST_SIZE;
+ printk(BIOS_DEBUG, "MSEG size 0x%x\n", CONFIG_MSEG_SIZE);
+ printk(BIOS_DEBUG, "BIOS res list 0x%x\n", CONFIG_BIOS_RESOURCE_LIST_SIZE);
}
-
- /* FXSAVE goes below MSEG */
- if (CONFIG(SSE)) {
- fxsave_size = FXSAVE_SIZE * params->num_cpus;
- fxsave_area = (char *)base - fxsave_size;
- base -= fxsave_size;
- total_size += fxsave_size;
- } else {
- fxsave_size = 0;
- fxsave_area = NULL;
- }
-
- handler_size = rmodule_memory_size(&smm_mod);
- base -= handler_size;
- total_size += handler_size;
- module_alignment = rmodule_load_alignment(&smm_mod);
- alignment_size = module_alignment - (base % module_alignment);
- if (alignment_size != module_alignment) {
- handler_size += alignment_size;
- base += alignment_size;
- }
-
- printk(BIOS_DEBUG,
- "%s: total_smm_space_needed %zx, available -> %zx\n",
- __func__, total_size, smram_size);
-
- /* Does the required amount of memory exceed the SMRAM region size? */
- if (total_size > smram_size) {
- printk(BIOS_ERR, "%s: need more SMRAM\n", __func__);
+ const size_t fx_save_area_size = CONFIG(SSE) ? FXSAVE_SIZE * params->num_cpus : 0;
+ const uintptr_t fx_save_area_base =
+ CONFIG(SSE) ? smram_top - stm_size - fx_save_area_size : 0;
+ if (fx_save_area_size)
+ printk(BIOS_DEBUG, "fx_save [0x%lx-0x%lx[\n", fx_save_area_base,
+ fx_save_area_base + fx_save_area_size);
+ const size_t handler_size = rmodule_memory_size(&smi_handler);
+ const size_t handler_alignment = rmodule_load_alignment(&smi_handler);
+ const uintptr_t handler_base =
+ ALIGN_DOWN(smram_top - stm_size - fx_save_area_size - handler_size,
+ handler_alignment);
+ printk(BIOS_DEBUG, "smihandler [0x%lx-0x%lx[\n", handler_base,
+ handler_base + handler_size);
+
+ if (handler_base <= smram_base) {
+ printk(BIOS_ERR, "Permanent handler won't FIT smram\n");
return -1;
}
- if (handler_size > SMM_CODE_SEGMENT_SIZE) {
- printk(BIOS_ERR, "%s: increase SMM_CODE_SEGMENT_SIZE: handler_size = %zx\n",
- __func__, handler_size);
+
+ const uintptr_t stub_segment_base = handler_base - SMM_CODE_SEGMENT_SIZE;
+ if (!smm_create_map(stub_segment_base, params->num_concurrent_save_states, params)) {
+ printk(BIOS_ERR, "%s: Error creating CPU map\n", __func__);
return -1;
}
- if (rmodule_load((void *)base, &smm_mod))
+ const uintptr_t lowest_stub = cpus[params->num_concurrent_save_states - 1].code_start;
+ const uintptr_t smm_stack_top =
+ smram_base + params->num_concurrent_save_states * CONFIG_SMM_MODULE_STACK_SIZE;
+ printk(BIOS_DEBUG, "cpu stacks [0x%lx-0x%lx[\n", smram_base, smm_stack_top);
+ if (lowest_stub < smm_stack_top) {
+ printk(BIOS_ERR, "SMM stubs won't fit in SMRAM 0x%lx\n",
+ cpus[params->num_concurrent_save_states - 1].code_start);
return -1;
-
- params->handler = rmodule_entry(&smm_mod);
- handler_mod_params = rmodule_parameters(&smm_mod);
- handler_mod_params->smbase = smram_base;
- handler_mod_params->smm_size = smram_size;
- handler_mod_params->save_state_size = params->real_cpu_save_state_size;
- handler_mod_params->num_cpus = params->num_cpus;
- handler_mod_params->gnvs_ptr = (uintptr_t)acpi_get_gnvs();
-
- if (CONFIG(CONSOLE_CBMEM) && (cbmemc = cbmem_entry_find(CBMEM_ID_CONSOLE))) {
- handler_mod_params->cbmemc = cbmem_entry_start(cbmemc);
- handler_mod_params->cbmemc_size = cbmem_entry_size(cbmemc);
- } else {
- handler_mod_params->cbmemc = 0;
- handler_mod_params->cbmemc_size = 0;
}
- printk(BIOS_DEBUG, "%s: smram_start: 0x%lx\n", __func__, smram_base);
- printk(BIOS_DEBUG, "%s: smram_end: %lx\n", __func__, smram_base + smram_size);
- printk(BIOS_DEBUG, "%s: handler start %p\n",
- __func__, params->handler);
- printk(BIOS_DEBUG, "%s: handler_size %zx\n",
- __func__, handler_size);
- printk(BIOS_DEBUG, "%s: fxsave_area %p\n",
- __func__, fxsave_area);
- printk(BIOS_DEBUG, "%s: fxsave_size %zx\n",
- __func__, fxsave_size);
- printk(BIOS_DEBUG, "%s: CONFIG_MSEG_SIZE 0x%x\n",
- __func__, CONFIG_MSEG_SIZE);
- printk(BIOS_DEBUG, "%s: CONFIG_BIOS_RESOURCE_LIST_SIZE 0x%x\n",
- __func__, CONFIG_BIOS_RESOURCE_LIST_SIZE);
-
- printk(BIOS_DEBUG, "%s: handler_mod_params.smbase = 0x%x\n", __func__,
- handler_mod_params->smbase);
- printk(BIOS_DEBUG, "%s: per_cpu_save_state_size = 0x%x\n", __func__,
- handler_mod_params->save_state_size);
- printk(BIOS_DEBUG, "%s: num_cpus = 0x%x\n", __func__, handler_mod_params->num_cpus);
- printk(BIOS_DEBUG, "%s: cbmemc = %p, cbmemc_size = %#x\n", __func__,
- handler_mod_params->cbmemc, handler_mod_params->cbmemc_size);
- printk(BIOS_DEBUG, "%s: total_save_state_size = 0x%x\n", __func__,
- (handler_mod_params->save_state_size * handler_mod_params->num_cpus));
-
- /* CPU 0 smbase goes first, all other CPUs
- * will be staggered below
- */
- base -= SMM_CODE_SEGMENT_SIZE;
- printk(BIOS_DEBUG, "%s: cpu0 entry: %lx\n", __func__, base);
-
- if (!smm_create_map(base, params->num_concurrent_save_states, params)) {
- printk(BIOS_ERR, "%s: Error creating CPU map\n", __func__);
+ if (rmodule_load((void *)handler_base, &smi_handler))
return -1;
- }
- for (int i = 0; i < params->num_cpus; i++) {
- handler_mod_params->save_state_top[i] =
- cpus[i].ss_start + params->per_cpu_save_state_size;
- }
+ struct smm_runtime *smihandler_params = rmodule_parameters(&smi_handler);
+ params->handler = rmodule_entry(&smi_handler);
+ setup_smihandler_params(smihandler_params, smram_base, smram_size, params);
- return smm_module_setup_stub(base, smram_size, params, fxsave_area);
+ return smm_module_setup_stub(stub_segment_base, smram_size, params,
+ (void *)fx_save_area_base);
}
/*
*The SMM module is placed within the provided region in the following
* manner:
- * +-----------------+ <- smram + size == 0x10000
+ * +-----------------+ <- smram + size == 0xB0000
* | save states |
* +-----------------+
* | fxsave area |
* +-----------------+
- * | smi handler |
+ * | smi handler | (or below the stubs if there is more space there)
* | ... |
* +-----------------+ <- cpu0
* | stub code | <- cpu1
@@ -610,17 +556,11 @@ int smm_load_module(const uintptr_t smram_base, const size_t smram_size,
static int smm_load_module_aseg(const uintptr_t smram_base, const size_t smram_size,
struct smm_loader_params *params)
{
- struct rmodule smm_mod;
- struct smm_runtime *handler_mod_params;
-
if (smram_size != SMM_DEFAULT_SIZE)
return -1;
- if (smram_base != SMM_BASE)
- return -1;
-
- /* Fail if can't parse the smm rmodule. */
- if (rmodule_parse(&_binary_smm_start, &smm_mod))
+ struct rmodule smi_handler;
+ if (rmodule_parse(&_binary_smm_start, &smi_handler))
return -1;
if (!smm_create_map(smram_base, params->num_concurrent_save_states, params)) {
@@ -628,55 +568,74 @@ static int smm_load_module_aseg(const uintptr_t smram_base, const size_t smram_s
return -1;
}
- const uintptr_t entry0_end = cpus[0].code_end;
- const uintptr_t save_state_base = cpus[params->num_cpus - 1].ss_start;
- const size_t fxsave_size = FXSAVE_SIZE * params->num_cpus;
- const uintptr_t fxsave_base = ALIGN_DOWN(save_state_base - fxsave_size, 16);
-
- if (fxsave_base <= entry0_end) {
- printk(BIOS_ERR, "%s, fxsave %lx won't fit smram\n", __func__, fxsave_base);
+ const uintptr_t smm_stack_top =
+ smram_base + params->num_concurrent_save_states * CONFIG_SMM_MODULE_STACK_SIZE;
+ printk(BIOS_DEBUG, "cpu stacks [0x%lx-0x%lx[\n", smram_base, smm_stack_top);
+ if (smm_stack_top > cpus[params->num_concurrent_save_states - 1].code_start) {
+ printk(BIOS_ERR, "stack won't fit in smram\n");
return -1;
}
- const size_t handler_size = rmodule_memory_size(&smm_mod);
- const size_t module_alignment = rmodule_load_alignment(&smm_mod);
- const uintptr_t module_base = ALIGN_DOWN(fxsave_base - handler_size, module_alignment);
+ const uintptr_t save_state_bottom =
+ cpus[params->num_concurrent_save_states - 1].ss_start;
+ const size_t fx_save_area_size = CONFIG(SSE) ? FXSAVE_SIZE * params->num_cpus : 0;
+ const uintptr_t fx_save_area_base =
+ CONFIG(SSE) ? save_state_bottom - fx_save_area_size : 0;
+ if (fx_save_area_size) {
+ printk(BIOS_DEBUG, "fx_save [0x%lx-0x%lx[\n", fx_save_area_base,
+ fx_save_area_base + fx_save_area_size);
+
+ if (fx_save_area_base < cpus[0].code_end) {
+ printk(BIOS_ERR, "fxsave won't fit in smram\n");
+ return -1;
+ }
+ }
- if (module_base <= entry0_end) {
- printk(BIOS_ERR, "%s, module won't fit smram\n", __func__);
- return -1;
+ const size_t top_space = save_state_bottom - fx_save_area_size - cpus[0].code_end;
+ const size_t bottom_space =
+ cpus[params->num_concurrent_save_states - 1].code_start - smm_stack_top;
+ const bool use_top = top_space >= bottom_space;
+
+ const size_t handler_size = rmodule_memory_size(&smi_handler);
+ const size_t handler_alignment = rmodule_load_alignment(&smi_handler);
+ uintptr_t handler_base;
+ if (use_top) {
+ handler_base = ALIGN_DOWN(save_state_bottom - fx_save_area_size - handler_size,
+ handler_alignment);
+ if (handler_base < cpus[0].code_end) {
+ printk(BIOS_ERR, "handler won't fit in top of smram\n");
+ return -1;
+ }
+ } else {
+ handler_base = ALIGN_UP(stack_top, handler_alignment);
+ const uintptr_t handler_top = handler_base + handler_size;
+ if (handler_top > cpus[params->num_concurrent_save_states - 1].code_start) {
+ printk(BIOS_ERR, "handler won't fit in bottom of smram\n");
+ return -1;
+ }
}
+ printk(BIOS_DEBUG, "handler [0x%lx-0x%lx[\n", handler_base,
+ handler_base + handler_size);
- if (rmodule_load((void *)module_base, &smm_mod))
+ if (rmodule_load((void *)handler_base, &smi_handler))
return -1;
- params->handler = rmodule_entry(&smm_mod);
- handler_mod_params = rmodule_parameters(&smm_mod);
- handler_mod_params->smbase = smram_base;
- handler_mod_params->smm_size = smram_size;
- handler_mod_params->save_state_size = params->real_cpu_save_state_size;
- handler_mod_params->num_cpus = params->num_cpus;
- handler_mod_params->gnvs_ptr = (uintptr_t)acpi_get_gnvs();
-
- for (int i = 0; i < params->num_cpus; i++) {
- handler_mod_params->save_state_top[i] =
- cpus[i].ss_start + params->per_cpu_save_state_size;
- }
+ struct smm_runtime *smihandler_params = rmodule_parameters(&smi_handler);
+ params->handler = rmodule_entry(&smi_handler);
+ setup_smihandler_params(smihandler_params, smram_base, smram_size, params);
+
+ return smm_module_setup_stub(smram_base, smram_size, params,
+ (void *)fx_save_area_base);
+}
+
+
+int smm_load_module(const uintptr_t smram_base, const size_t smram_size,
+ struct smm_loader_params *params)
+{
+ if (CONFIG(SMM_ASEG))
+ return smm_load_module_aseg(smram_base, smram_size, params);
+ else if (CONFIG(SMM_TSEG))
+ return smm_load_module_tseg(smram_base, smram_size, params);
- printk(BIOS_DEBUG, "%s: smram_start: 0x%lx\n", __func__, smram_base);
- printk(BIOS_DEBUG, "%s: smram_end: %lx\n", __func__, smram_base + smram_size);
- printk(BIOS_DEBUG, "%s: handler start %p\n", __func__, params->handler);
- printk(BIOS_DEBUG, "%s: handler_size %zx\n", __func__, handler_size);
- printk(BIOS_DEBUG, "%s: fxsave_area %lx\n", __func__, fxsave_base);
- printk(BIOS_DEBUG, "%s: fxsave_size %zx\n", __func__, fxsave_size);
-
- printk(BIOS_DEBUG, "%s: handler_mod_params.smbase = 0x%x\n", __func__,
- handler_mod_params->smbase);
- printk(BIOS_DEBUG, "%s: per_cpu_save_state_size = 0x%x\n", __func__,
- handler_mod_params->save_state_size);
- printk(BIOS_DEBUG, "%s: num_cpus = 0x%x\n", __func__, handler_mod_params->num_cpus);
- printk(BIOS_DEBUG, "%s: total_save_state_size = 0x%x\n", __func__,
- (handler_mod_params->save_state_size * handler_mod_params->num_cpus));
-
- return smm_module_setup_stub(smram_base, smram_size, params, (void *)fxsave_base);
+ return -1;
}