diff options
author | Arthur Heymans <arthur@aheymans.xyz> | 2021-06-02 11:46:20 +0200 |
---|---|---|
committer | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2022-11-12 10:27:09 +0000 |
commit | 0c9fa6f2ce6d556ec39444c0307c3c9e20053663 (patch) | |
tree | efc324bca68c8e7ad513e737b891c72aede9369c | |
parent | 4c4bd3cd973f3ec20c3a343a183af4a19b97a748 (diff) |
mb/emulation/qemu-q35: Fix running qemu-i386 with SMM
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 <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/55138
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
-rw-r--r-- | src/mainboard/emulation/qemu-q35/cpu.c | 42 |
1 files 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 <console/console.h> #include <cpu/x86/mp.h> +#include <stddef.h> #include <stdint.h> #include <cpu/intel/smm_reloc.h> #include <cpu/amd/amd64_save_state.h> +#include <cpu/x86/legacy_save_state.h> #include <mainboard/emulation/qemu-i440fx/fw_cfg.h> 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); } |