From 0c9fa6f2ce6d556ec39444c0307c3c9e20053663 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Wed, 2 Jun 2021 11:46:20 +0200 Subject: [PATCH] mb/emulation/qemu-q35: Fix running qemu-i386 with SMM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Depending on whether qemu emulates an amd64 or i386 machine the SMM save state will differ. The smbase offsets are incompatible between those save states. TESTED: Both qemu-system-i386 and qemu-system-x86_64 (v7.0.50) have a working smihandler, ASEG and TSEG. Change-Id: Ic6994c8d6e10fd06655129dbd801f1f9d5fd639f Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/55138 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki Reviewed-by: Angel Pons --- src/mainboard/emulation/qemu-q35/cpu.c | 42 ++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/mainboard/emulation/qemu-q35/cpu.c b/src/mainboard/emulation/qemu-q35/cpu.c index fe3a571021..2a2707a55f 100644 --- a/src/mainboard/emulation/qemu-q35/cpu.c +++ b/src/mainboard/emulation/qemu-q35/cpu.c @@ -2,9 +2,11 @@ #include #include +#include #include #include #include +#include #include static void get_smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, @@ -31,19 +33,47 @@ static void get_smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, * resides in the ramstage module. This occurs by trampolining from the default * SMRAM entry point to here. */ + +__packed union save_state { + amd64_smm_state_save_area_t amd64; + struct { + char _reserved[sizeof(amd64_smm_state_save_area_t) + - sizeof(legacy_smm_state_save_area_t)]; + legacy_smm_state_save_area_t legacy; + }; +}; + +_Static_assert(sizeof(union save_state) == sizeof(amd64_smm_state_save_area_t), + "Incorrect save state union size"); + +_Static_assert(offsetof(union save_state, amd64.smm_revision) + == offsetof(union save_state, legacy.smm_revision), + "Incompatible SMM save state revision offset"); + 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; + union save_state *save_state = + (void *)(curr_smbase + SMM_DEFAULT_SIZE - sizeof(*save_state)); + u32 smbase = staggered_smbase; - save_state = (void *)(curr_smbase + SMM_DEFAULT_SIZE - sizeof(*save_state)); - save_state->smbase = smbase; + /* The SMM save state revision is always at a compatible offset */ + const u32 revision = save_state->legacy.smm_revision; + switch (revision) { + case 0x00020000: + save_state->legacy.smbase = smbase; + break; + case 0x00020064: + save_state->amd64.smbase = smbase; + break; + default: + printk(BIOS_ERR, "Unknown SMM revision 0x%x, not relocating SMM\n", revision); + return; + }; printk(BIOS_DEBUG, "In relocation handler: cpu %d\n", cpu); - printk(BIOS_DEBUG, "SMM revision: 0x%08x\n", save_state->smm_revision); + printk(BIOS_DEBUG, "SMM revision: 0x%08x\n", revision); printk(BIOS_DEBUG, "New SMBASE=0x%08x\n", smbase); }