cpu/x86/smm_loaderv2: Use the permanent stack top during relocation

Use the same stack location during relocation as for the permanent
handler.

When the number of CPUs is too large the stacks during relocation
don't fit inside the default SMRAM segment at 0x30000. Currently the
code would just let the CPU stack base grow downwards outside of the
default SMM segment which would corrupt lower memory if S3 is
implemented.

Also update the comment on smm_module_setup_stub().

Change-Id: I6a0a890e8b1c2408301564c22772032cfee4d296
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/51186
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
Arthur Heymans 2021-02-16 13:19:18 +01:00 committed by Patrick Georgi
parent 110c47699a
commit e6c3523b1b
4 changed files with 19 additions and 26 deletions

View File

@ -796,19 +796,11 @@ static void adjust_smm_apic_id_map(struct smm_loader_params *smm_params)
}
static int install_relocation_handler(int num_cpus, size_t real_save_state_size,
size_t save_state_size)
size_t save_state_size, uintptr_t perm_smbase)
{
int cpus = num_cpus;
#if CONFIG(X86_SMM_LOADER_VERSION2)
/* Default SMRAM size is not big enough to concurrently
* handle relocation for more than ~32 CPU threads
* therefore, relocate 1 by 1. */
cpus = 1;
#endif
struct smm_loader_params smm_params = {
.per_cpu_stack_size = CONFIG_SMM_STUB_STACK_SIZE,
.num_concurrent_stacks = cpus,
.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 = 1,
@ -819,7 +811,7 @@ static int install_relocation_handler(int num_cpus, size_t real_save_state_size,
if (mp_state.ops.adjust_smm_params != NULL)
mp_state.ops.adjust_smm_params(&smm_params, 0);
if (smm_setup_relocation_handler(&smm_params)) {
if (smm_setup_relocation_handler((void *)perm_smbase, &smm_params)) {
printk(BIOS_ERR, "%s: smm setup failed\n", __func__);
return -1;
}
@ -874,9 +866,8 @@ static void load_smm_handlers(void)
return;
/* Install handlers. */
if (install_relocation_handler(mp_state.cpu_count,
real_save_state_size,
smm_save_state_size) < 0) {
if (install_relocation_handler(mp_state.cpu_count, real_save_state_size,
smm_save_state_size, mp_state.perm_smbase) < 0) {
printk(BIOS_ERR, "Unable to install SMM relocation handler.\n");
smm_disable();
}

View File

@ -266,7 +266,7 @@ static int smm_module_setup_stub(void *smbase, size_t smm_size,
* assumption is that the stub will be entered from the default SMRAM
* location: 0x30000 -> 0x40000.
*/
int smm_setup_relocation_handler(struct smm_loader_params *params)
int smm_setup_relocation_handler(void *const perm_smram, struct smm_loader_params *params)
{
void *smram = (void *)SMM_DEFAULT_BASE;

View File

@ -295,20 +295,22 @@ static int smm_stub_place_staggered_entry_points(char *base,
* 0x30000), but no assumption should be made for the permanent SMI handler.
* The placement of CPU entry points for permanent handler are determined
* by the number of CPUs in the system and the amount of SMRAM.
* There are potentially 3 regions to place
* There are potentially 2 regions to place
* within the default SMRAM size:
* 1. Save state areas
* 2. Stub code
* 3. Stack areas
*
* The save state and smm stack are treated as contiguous for the number of
* concurrent areas requested. The save state always lives at the top of the
* CPUS smbase (and the entry point is at offset 0x8000). This allows only a certain
* number of CPUs with staggered entry points until the save state area comes
* down far enough to overwrite/corrupt the entry code (stub code). Therefore,
* an SMM map is created to avoid this corruption, see smm_create_map() above.
* The save state always lives at the top of the CPUS smbase (and the entry
* point is at offset 0x8000). This allows only a certain number of CPUs with
* staggered entry points until the save state area comes down far enough to
* overwrite/corrupt the entry code (stub code). Therefore, an SMM map is
* created to avoid this corruption, see smm_create_map() above.
* This module setup code works for the default (0x30000) SMM handler setup and the
* permanent SMM handler.
* The CPU stack is decided at runtime in the stub and is treaded as a continuous
* region. As this might not fit the default SMRAM region, the same region used
* by the permanent handler can be used during relocation. This is done via the
* smram_start argument.
*/
static int smm_module_setup_stub(void *const smbase, const size_t smm_size,
struct smm_loader_params *params,
@ -438,7 +440,7 @@ static int smm_module_setup_stub(void *const smbase, const size_t smm_size,
* assumption is that the stub will be entered from the default SMRAM
* location: 0x30000 -> 0x40000.
*/
int smm_setup_relocation_handler(struct smm_loader_params *params)
int smm_setup_relocation_handler(void * const perm_smram, struct smm_loader_params *params)
{
void *smram = (void *)(SMM_DEFAULT_BASE);
printk(BIOS_SPEW, "%s: enter\n", __func__);
@ -457,7 +459,7 @@ int smm_setup_relocation_handler(struct smm_loader_params *params)
params->num_concurrent_stacks = CONFIG_MAX_CPUS;
return smm_module_setup_stub(smram, SMM_DEFAULT_SIZE,
params, fxsave_area_relocation, smram);
params, fxsave_area_relocation, perm_smram);
printk(BIOS_SPEW, "%s: exit\n", __func__);
}

View File

@ -148,7 +148,7 @@ struct smm_loader_params {
};
/* Both of these return 0 on success, < 0 on failure. */
int smm_setup_relocation_handler(struct smm_loader_params *params);
int smm_setup_relocation_handler(void * const perm_smram, struct smm_loader_params *params);
int smm_load_module(void *smram, size_t size, struct smm_loader_params *params);
u32 smm_get_cpu_smbase(unsigned int cpu_num);