Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/48262 )
Change subject: mb/emulation/qemu-q35: Add support for SMM_TSEG with parallel MP init ......................................................................
mb/emulation/qemu-q35: Add support for SMM_TSEG with parallel MP init
Change-Id: I612cebcd2ddef809434eb9bfae9d8681cda112ef Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- M src/cpu/qemu-x86/Kconfig M src/mainboard/emulation/qemu-i440fx/northbridge.c M src/mainboard/emulation/qemu-q35/Makefile.inc A src/mainboard/emulation/qemu-q35/cpu.c M src/mainboard/emulation/qemu-q35/memmap.c 5 files changed, 92 insertions(+), 4 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/62/48262/1
diff --git a/src/cpu/qemu-x86/Kconfig b/src/cpu/qemu-x86/Kconfig index 641cea8..0f59b9c 100644 --- a/src/cpu/qemu-x86/Kconfig +++ b/src/cpu/qemu-x86/Kconfig @@ -36,9 +36,10 @@ depends on !PARALLEL_MP select SMM_ASEG
-#config CPU_QEMU_X86_TSEG_SMM -# bool "SMM in TSEG" -# select SMM_TSEG +config CPU_QEMU_X86_TSEG_SMM + bool "SMM in TSEG" + select SMM_TSEG + depends on PARALLEL_MP
endchoice
diff --git a/src/mainboard/emulation/qemu-i440fx/northbridge.c b/src/mainboard/emulation/qemu-i440fx/northbridge.c index f49d47da..7ee38d3 100644 --- a/src/mainboard/emulation/qemu-i440fx/northbridge.c +++ b/src/mainboard/emulation/qemu-i440fx/northbridge.c @@ -249,9 +249,15 @@ .get_cpu_count = fw_cfg_max_cpus, };
+extern const struct mp_ops mp_ops_with_smm; + void mp_init_cpus(struct bus *cpu_bus) { - if (mp_init_with_smm(cpu_bus, &mp_ops_no_smm)) + const struct mp_ops *ops = &mp_ops_no_smm; + if (CONFIG(SMM_TSEG)) + ops = &mp_ops_with_smm; + + if (mp_init_with_smm(cpu_bus, ops)) printk(BIOS_ERR, "MP initialization failure.\n"); }
diff --git a/src/mainboard/emulation/qemu-q35/Makefile.inc b/src/mainboard/emulation/qemu-q35/Makefile.inc index 4bd91f0..f717405 100644 --- a/src/mainboard/emulation/qemu-q35/Makefile.inc +++ b/src/mainboard/emulation/qemu-q35/Makefile.inc @@ -13,6 +13,7 @@ ramstage-y += ../qemu-i440fx/memmap.c ramstage-y += ../qemu-i440fx/northbridge.c ramstage-y += memmap.c +ramstage-y += cpu.c
verstage-$(CONFIG_CHROMEOS) += chromeos.c verstage-$(CONFIG_CHROMEOS) += ../qemu-i440fx/fw_cfg.c diff --git a/src/mainboard/emulation/qemu-q35/cpu.c b/src/mainboard/emulation/qemu-q35/cpu.c new file mode 100644 index 0000000..c0f4ee5 --- /dev/null +++ b/src/mainboard/emulation/qemu-q35/cpu.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <cpu/x86/mp.h> +#include <stdint.h> +#include <cpu/intel/smm_reloc.h> +#include <cpu/amd/amd64_save_state.h> +#include <mainboard/emulation/qemu-i440fx/fw_cfg.h> + +static void get_smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, + size_t *smm_save_state_size) +{ + printk(BIOS_DEBUG, "Setting up SMI for CPU\n"); + + smm_subregion(SMM_SUBREGION_HANDLER, perm_smbase, perm_smsize); + +// *smm_save_state_size = sizeof(amd64_smm_state_save_area_t); + *smm_save_state_size = 0x400; + printk(BIOS_DEBUG, "Save state size: 0x%lx bytes\n", *smm_save_state_size); +} + +static void per_cpu_smm_trigger(void) +{ + /* Relocate SMM space. */ + smm_initiate_relocation(); +} + +/* The relocation work is actually performed in SMM context, but the code + * resides in the ramstage module. This occurs by trampolining from the default + * SMRAM entry point to here. */ +static void relocation_handler(int cpu, uintptr_t curr_smbase, + uintptr_t staggered_smbase) +{ + /* The em64t101 save state is sufficiently compatible with older + save states with regards of smbase, smm_revision. */ + amd64_smm_state_save_area_t *save_state; + u32 smbase = staggered_smbase; + + save_state = (void *)(curr_smbase + SMM_DEFAULT_SIZE - sizeof(*save_state)); + save_state->smbase = smbase; + + printk(BIOS_DEBUG, "In relocation handler: cpu %d\n", cpu); + printk(BIOS_SPEW, "SMM revision: 0x%08x\n", save_state->smm_revision); + printk(BIOS_DEBUG, "New SMBASE=0x%08x\n", smbase); +} + +static void post_mp_init(void) +{ + /* Now that all APs have been relocated as well as the BSP let SMIs + * start flowing. */ + global_smi_enable(); + + /* Lock down the SMRAM space. */ + smm_lock(); +} + +const struct mp_ops mp_ops_with_smm = { + .get_cpu_count = fw_cfg_max_cpus, + .get_smm_info = get_smm_info, + .pre_mp_smm_init = smm_southbridge_clear_state, + .per_cpu_smm_trigger = per_cpu_smm_trigger, + .relocation_handler = relocation_handler, + .post_mp_init = post_mp_init, +}; diff --git a/src/mainboard/emulation/qemu-q35/memmap.c b/src/mainboard/emulation/qemu-q35/memmap.c index c288680..04cf285 100644 --- a/src/mainboard/emulation/qemu-q35/memmap.c +++ b/src/mainboard/emulation/qemu-q35/memmap.c @@ -2,14 +2,17 @@
#define __SIMPLE_DEVICE__
+#include <console/console.h> #include <cpu/x86/smm.h> #include <device/pci_ops.h> #include <mainboard/emulation/qemu-i440fx/memory.h> #include <mainboard/emulation/qemu-i440fx/fw_cfg.h> +#include <cpu/intel/smm_reloc.h>
#define EXT_TSEG_MBYTES 0x50
#define SMRAMC 0x9d +#define C_BASE_SEG ((0 << 2) | (1 << 1) | (0 << 0)) #define G_SMRAME (1 << 3) #define D_LCK (1 << 4) #define D_CLS (1 << 5) @@ -40,3 +43,16 @@ *start = qemu_get_memory_size() * KiB - *size; printk(BIOS_SPEW, "SMM_BASE: 0x%08lx, SMM_SIZE: %ld MiB\n", *start, *size / MiB); } + +void smm_lock(void) +{ + /* LOCK the SMM memory window and enable normal SMM. + * After running this function, only a full reset can + * make the SMM registers writable again. + */ + printk(BIOS_DEBUG, "Locking SMM.\n"); + + pci_or_config8(PCI_DEV(0, 0, 0), ESMRAMC, T_EN); + pci_write_config8(PCI_DEV(0, 0, 0), SMRAMC, D_LCK | G_SMRAME | C_BASE_SEG); +} +