diff options
author | Arthur Heymans <arthur@aheymans.xyz> | 2021-02-15 19:39:01 +0100 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2021-03-19 11:33:28 +0000 |
commit | 478f3d8f5e5b5e506ca4c9644bfa97ad389cef7f (patch) | |
tree | ff42d0163c59c0f45bd297b362dc86fef4d80555 /src/cpu/x86 | |
parent | ad0116c0327f575f0af184a2f4861848a49a0e2a (diff) |
cpu/x86/mp_init: Allow stub sizes larger than the save state size
The permanent handler module argument 'save_state_size' now holds the
meaning of the real save state size which is then substracted from the
CPUs save state 'top' to get the save state base.
TESTED with qemu Q35 on x86_64 where the stub size exceeds the AMD64
save state size.
Change-Id: I55d7611a17b6d0a39aee1c56318539232a9bb781
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/50770
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Diffstat (limited to 'src/cpu/x86')
-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 |
3 files changed, 32 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(); |