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:
		
				
					committed by
					
						
						Patrick Georgi
					
				
			
			
				
	
			
			
			
						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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										58
									
								
								src/mainboard/emulation/qemu-q35/cpu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/mainboard/emulation/qemu-q35/cpu.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user