diff options
-rw-r--r-- | src/cpu/x86/Kconfig | 2 | ||||
-rw-r--r-- | src/cpu/x86/smm/Makefile.inc | 10 | ||||
-rw-r--r-- | src/cpu/x86/smm/smm_module_loader.c | 100 |
3 files changed, 109 insertions, 3 deletions
diff --git a/src/cpu/x86/Kconfig b/src/cpu/x86/Kconfig index 86f31e05c7..d5c688d40f 100644 --- a/src/cpu/x86/Kconfig +++ b/src/cpu/x86/Kconfig @@ -120,7 +120,7 @@ config SMM_LEGACY_ASEG help SMM support without PARALLEL_MP, to be deprecated. -if SMM_TSEG +if HAVE_SMI_HANDLER && !SMM_LEGACY_ASEG config SMM_MODULE_HEAP_SIZE hex diff --git a/src/cpu/x86/smm/Makefile.inc b/src/cpu/x86/smm/Makefile.inc index 36aa113443..cd920daf1a 100644 --- a/src/cpu/x86/smm/Makefile.inc +++ b/src/cpu/x86/smm/Makefile.inc @@ -35,6 +35,10 @@ ramstage-y += tseg_region.c romstage-y += tseg_region.c postcar-y += tseg_region.c +endif + +ifeq ($(CONFIG_PARALLEL_MP),y) + smmstub-y += smm_stub.S smm-y += smm_module_handler.c @@ -71,7 +75,9 @@ endif $(obj)/smm/smm: $(obj)/smm/smm.elf.rmod $(OBJCOPY_smm) -O binary $< $@ -else # CONFIG_SMM_TSEG +endif + +ifeq ($(CONFIG_SMM_LEGACY_ASEG),y) smm-y += smm.ld @@ -83,4 +89,4 @@ $(obj)/smm/smm: $(obj)/smm/smm.o $(call src-to-obj,smm,$(src)/cpu/x86/smm/smm.ld smm-y += smmhandler.S smm-y += smihandler.c -endif # CONFIG_SMM_TSEG +endif # CONFIG_SMM_LEGACY_ASEG diff --git a/src/cpu/x86/smm/smm_module_loader.c b/src/cpu/x86/smm/smm_module_loader.c index beddb3cd81..14e2aa3b74 100644 --- a/src/cpu/x86/smm/smm_module_loader.c +++ b/src/cpu/x86/smm/smm_module_loader.c @@ -437,6 +437,9 @@ 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); + /* *The SMM module is placed within the provided region in the following * manner: @@ -477,6 +480,9 @@ int smm_load_module(const uintptr_t smram_base, const size_t smram_size, size_t total_size = 0; uintptr_t base; /* The base for the permanent handler */ + if (CONFIG(SMM_ASEG)) + return smm_load_module_aseg(smram_base, smram_size, params); + if (smram_size <= SMM_DEFAULT_SIZE) return -1; @@ -592,3 +598,97 @@ int smm_load_module(const uintptr_t smram_base, const size_t smram_size, return smm_module_setup_stub(base, smram_size, params, fxsave_area); } + +/* + *The SMM module is placed within the provided region in the following + * manner: + * +-----------------+ <- smram + size == 0x10000 + * | save states | + * +-----------------+ + * | fxsave area | + * +-----------------+ + * | smi handler | + * | ... | + * +-----------------+ <- cpu0 + * | stub code | <- cpu1 + * | stub code | <- cpu2 + * | stub code | <- cpu3, etc + * | | + * | | + * | | + * | stacks | + * +-----------------+ <- smram start = 0xA0000 + */ +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)) + return -1; + + if (!smm_create_map(smram_base, params->num_concurrent_save_states, params)) { + printk(BIOS_ERR, "%s: Error creating CPU map\n", __func__); + 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); + 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); + + if (module_base <= entry0_end) { + printk(BIOS_ERR, "%s, module won't fit smram\n", __func__); + return -1; + } + + if (rmodule_load((void *)module_base, &smm_mod)) + 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; + } + + 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); +} |