diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cpu/x86/mp_init.c | 35 | ||||
-rw-r--r-- | src/cpu/x86/smm/smm_module_loader.c | 8 | ||||
-rw-r--r-- | src/cpu/x86/smm/smm_module_loaderv2.c | 8 | ||||
-rw-r--r-- | src/include/cpu/x86/smm.h | 1 |
4 files changed, 33 insertions, 19 deletions
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c index 6003c9745b..1acb22819a 100644 --- a/src/cpu/x86/mp_init.c +++ b/src/cpu/x86/mp_init.c @@ -685,6 +685,9 @@ struct mp_state { int cpu_count; uintptr_t perm_smbase; size_t perm_smsize; + /* Size of the real CPU save state */ + size_t smm_real_save_state_size; + /* Size of allocated CPU save state, MAX(real save state size, stub size) */ size_t smm_save_state_size; uintptr_t reloc_start32_offset; int do_smm; @@ -766,7 +769,8 @@ static void adjust_smm_apic_id_map(struct smm_loader_params *smm_params) stub_params->apic_id_to_cpu[i] = cpu_get_apic_id(i); } -static int install_relocation_handler(int num_cpus, size_t save_state_size) +static int install_relocation_handler(int num_cpus, size_t real_save_state_size, + size_t save_state_size) { int cpus = num_cpus; #if CONFIG(X86_SMM_LOADER_VERSION2) @@ -779,6 +783,7 @@ static int install_relocation_handler(int num_cpus, size_t save_state_size) struct smm_loader_params smm_params = { .per_cpu_stack_size = CONFIG_SMM_STUB_STACK_SIZE, .num_concurrent_stacks = cpus, + .real_cpu_save_state_size = real_save_state_size, .per_cpu_save_state_size = save_state_size, .num_concurrent_save_states = 1, .handler = smm_do_relocation, @@ -800,7 +805,8 @@ static int install_relocation_handler(int num_cpus, size_t save_state_size) } static int install_permanent_handler(int num_cpus, uintptr_t smbase, - size_t smsize, size_t save_state_size) + size_t smsize, size_t real_save_state_size, + size_t save_state_size) { /* * All the CPUs will relocate to permanaent handler now. Set parameters @@ -812,6 +818,7 @@ static int install_permanent_handler(int num_cpus, uintptr_t smbase, struct smm_loader_params smm_params = { .per_cpu_stack_size = CONFIG_SMM_MODULE_STACK_SIZE, .num_concurrent_stacks = num_cpus, + .real_cpu_save_state_size = real_save_state_size, .per_cpu_save_state_size = save_state_size, .num_concurrent_save_states = num_cpus, }; @@ -833,6 +840,7 @@ static int install_permanent_handler(int num_cpus, uintptr_t smbase, /* Load SMM handlers as part of MP flight record. */ static void load_smm_handlers(void) { + size_t real_save_state_size = mp_state.smm_real_save_state_size; size_t smm_save_state_size = mp_state.smm_save_state_size; /* Do nothing if SMM is disabled.*/ @@ -841,13 +849,15 @@ static void load_smm_handlers(void) /* Install handlers. */ if (install_relocation_handler(mp_state.cpu_count, - smm_save_state_size) < 0) { + real_save_state_size, + smm_save_state_size) < 0) { printk(BIOS_ERR, "Unable to install SMM relocation handler.\n"); smm_disable(); } if (install_permanent_handler(mp_state.cpu_count, mp_state.perm_smbase, - mp_state.perm_smsize, smm_save_state_size) < 0) { + mp_state.perm_smsize, real_save_state_size, + smm_save_state_size) < 0) { printk(BIOS_ERR, "Unable to install SMM permanent handler.\n"); smm_disable(); } @@ -1057,6 +1067,19 @@ static struct mp_flight_record mp_steps[] = { MP_FR_BLOCK_APS(ap_wait_for_instruction, NULL), }; +static size_t smm_stub_size(void) +{ + extern unsigned char _binary_smmstub_start[]; + struct rmodule smm_stub; + + if (rmodule_parse(&_binary_smmstub_start, &smm_stub)) { + printk(BIOS_ERR, "%s: unable to get SMM module size\n", __func__); + return 0; + } + + return rmodule_memory_size(&smm_stub); +} + static void fill_mp_state(struct mp_state *state, const struct mp_ops *ops) { /* @@ -1070,7 +1093,9 @@ static void fill_mp_state(struct mp_state *state, const struct mp_ops *ops) if (ops->get_smm_info != NULL) ops->get_smm_info(&state->perm_smbase, &state->perm_smsize, - &state->smm_save_state_size); + &state->smm_real_save_state_size); + + state->smm_save_state_size = MAX(state->smm_real_save_state_size, smm_stub_size()); /* * Make sure there is enough room for the SMM descriptor diff --git a/src/cpu/x86/smm/smm_module_loader.c b/src/cpu/x86/smm/smm_module_loader.c index 021d739f94..39cd9101a5 100644 --- a/src/cpu/x86/smm/smm_module_loader.c +++ b/src/cpu/x86/smm/smm_module_loader.c @@ -198,12 +198,6 @@ static int smm_module_setup_stub(void *smbase, size_t smm_size, smm_stub_size = rmodule_memory_size(&smm_stub); stub_entry_offset = rmodule_entry_offset(&smm_stub); - if (smm_stub_size > params->per_cpu_save_state_size) { - printk(BIOS_ERR, "SMM Module: SMM stub size larger than save state size\n"); - printk(BIOS_ERR, "SMM Module: Staggered entry points will overlap stub\n"); - return -1; - } - /* Assume the stub is always small enough to live within upper half of * SMRAM region after the save state space has been allocated. */ smm_stub_loc = &base[SMM_ENTRY_OFFSET]; @@ -389,7 +383,7 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params) handler_mod_params = rmodule_parameters(&smm_mod); handler_mod_params->smbase = (uintptr_t)smram; handler_mod_params->smm_size = size; - handler_mod_params->save_state_size = params->per_cpu_save_state_size; + handler_mod_params->save_state_size = params->real_cpu_save_state_size; handler_mod_params->num_cpus = params->num_concurrent_stacks; handler_mod_params->gnvs_ptr = (uintptr_t)acpi_get_gnvs(); diff --git a/src/cpu/x86/smm/smm_module_loaderv2.c b/src/cpu/x86/smm/smm_module_loaderv2.c index c8b9fe689a..8354568b4b 100644 --- a/src/cpu/x86/smm/smm_module_loaderv2.c +++ b/src/cpu/x86/smm/smm_module_loaderv2.c @@ -123,12 +123,6 @@ static int smm_create_map(uintptr_t smbase, unsigned int num_cpus, return 0; } - if (stub_size > ss_size) { - printk(BIOS_ERR, "%s: Save state larger than SMM stub size\n", __func__); - printk(BIOS_ERR, " Decrease stub size or increase the size allocated for the save state\n"); - return 0; - } - for (i = 0; i < num_cpus; i++) { cpus[i].smbase = base; cpus[i].entry = base + smm_entry_offset; @@ -588,7 +582,7 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params) handler_mod_params = rmodule_parameters(&smm_mod); handler_mod_params->smbase = (uintptr_t)smram; handler_mod_params->smm_size = size; - handler_mod_params->save_state_size = params->per_cpu_save_state_size; + handler_mod_params->save_state_size = params->real_cpu_save_state_size; handler_mod_params->num_cpus = params->num_concurrent_stacks; handler_mod_params->gnvs_ptr = (uintptr_t)acpi_get_gnvs(); diff --git a/src/include/cpu/x86/smm.h b/src/include/cpu/x86/smm.h index 3375f4a144..4f3db291ac 100644 --- a/src/include/cpu/x86/smm.h +++ b/src/include/cpu/x86/smm.h @@ -138,6 +138,7 @@ struct smm_loader_params { size_t per_cpu_stack_size; size_t num_concurrent_stacks; + size_t real_cpu_save_state_size; size_t per_cpu_save_state_size; size_t num_concurrent_save_states; |