mb/emulation/qemu-q35: Add support for SMM_TSEG with parallel MP init
Tested with and without -enable-kvm, with -smp 1 2 and 32. Change-Id: I612cebcd2ddef809434eb9bfae9d8681cda112ef Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/c/coreboot/+/48262 Reviewed-by: Angel Pons <th3fanbus@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
ff485f2bce
commit
e69d2dfdb7
|
@ -36,9 +36,10 @@ config CPU_QEMU_X86_ASEG_SMM
|
|||
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
|
||||
|
||||
|
|
|
@ -249,9 +249,13 @@ static const struct mp_ops mp_ops_no_smm = {
|
|||
.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 = CONFIG(SMM_TSEG) ? &mp_ops_with_smm : &mp_ops_no_smm;
|
||||
|
||||
if (mp_init_with_smm(cpu_bus, ops))
|
||||
printk(BIOS_ERR, "MP initialization failure.\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ ramstage-y += ../qemu-i440fx/fw_cfg.c
|
|||
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
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/* 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);
|
||||
|
||||
/* FIXME: on X86_64 the save state size is smaller than the size of the SMM stub */
|
||||
*smm_save_state_size = sizeof(amd64_smm_state_save_area_t);
|
||||
printk(BIOS_DEBUG, "Save state size: 0x%lx bytes\n", *smm_save_state_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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_DEBUG, "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,
|
||||
.relocation_handler = relocation_handler,
|
||||
.post_mp_init = post_mp_init,
|
||||
};
|
|
@ -8,6 +8,7 @@
|
|||
#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>
|
||||
|
||||
#include "q35.h"
|
||||
|
||||
|
@ -35,6 +36,16 @@ void mainboard_machine_check(void)
|
|||
|
||||
/* QEMU-specific register */
|
||||
#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)
|
||||
#define D_OPEN (1 << 6)
|
||||
#define ESMRAMC 0x9e
|
||||
#define T_EN (1 << 0)
|
||||
#define TSEG_SZ_MASK (3 << 1)
|
||||
#define H_SMRAME (1 << 7)
|
||||
|
||||
void smm_region(uintptr_t *start, size_t *size)
|
||||
{
|
||||
|
@ -57,3 +68,16 @@ void smm_region(uintptr_t *start, size_t *size)
|
|||
*start = qemu_get_memory_size() * KiB - *size;
|
||||
printk(BIOS_SPEW, "SMM_BASE: 0x%08lx, SMM_SIZE: %zu 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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue