summaryrefslogtreecommitdiffstats
path: root/src/cpu
diff options
context:
space:
mode:
authorArthur Heymans <arthur@aheymans.xyz>2021-02-15 19:39:01 +0100
committerPatrick Georgi <pgeorgi@google.com>2021-03-19 11:33:28 +0000
commit478f3d8f5e5b5e506ca4c9644bfa97ad389cef7f (patch)
treeff42d0163c59c0f45bd297b362dc86fef4d80555 /src/cpu
parentad0116c0327f575f0af184a2f4861848a49a0e2a (diff)
downloadcoreboot-478f3d8f5e5b5e506ca4c9644bfa97ad389cef7f.tar.gz
coreboot-478f3d8f5e5b5e506ca4c9644bfa97ad389cef7f.tar.bz2
coreboot-478f3d8f5e5b5e506ca4c9644bfa97ad389cef7f.zip
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')
-rw-r--r--src/cpu/x86/mp_init.c35
-rw-r--r--src/cpu/x86/smm/smm_module_loader.c8
-rw-r--r--src/cpu/x86/smm/smm_module_loaderv2.c8
3 files changed, 32 insertions, 19 deletions
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c
index 6003c9745bf1..1acb22819a15 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 021d739f944f..39cd9101a5d4 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 c8b9fe689ab2..8354568b4b71 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();