Skip to content

Commit

Permalink
cpu/x86/smm: Introduce SMM module loader version 2
Browse files Browse the repository at this point in the history
Xeon-SP Skylake Scalable Processor can have 36 CPU threads (18 cores).
Current coreboot SMM is unable to handle more than ~32 CPU threads.
This patch introduces a version 2 of the SMM module loader which
addresses this problem. Having two versions of the SMM module loader
prevents any issues to current projects. Future Xeon-SP products will
be using this version of the SMM loader.  Subsequent patches will
enable board specific functionality for Xeon-SP.

The reason for moving to version 2 is the state save area begins to
encroach upon the SMI handling code when more than 32 CPU threads are
in the system. This can cause system hangs, reboots, etc. The second
change is related to staggered entry points with simple near jumps. In
the current loader, near jumps will not work because the CPU is jumping
within the same code segment. In version 2, "far" address jumps are
necessary therefore protected mode must be enabled first. The SMM
layout and how the CPUs are staggered are documented in the code.

By making the modifications above, this allows the smm module loader to
expand easily as more CPU threads are added.

TEST=build for Tiogapass platform under OCP mainboard. Enable the
following in Kconfig.
        select CPU_INTEL_COMMON_SMM
        select SOC_INTEL_COMMON_BLOCK_SMM
        select SMM_TSEG
        select HAVE_SMI_HANDLER
        select ACPI_INTEL_HARDWARE_SLEEP_VALUES

Debug console will show all 36 cores relocated. Further tested by
generating SMI's to port 0xb2 using XDP/ITP HW debugger and ensured all
cores entering and exiting SMM properly. In addition, booted to Linux
5.4 kernel and observed no issues during mp init.

Change-Id: I00a23a5f2a46110536c344254868390dbb71854c
Signed-off-by: Rocky Phagura <rphagura@fb.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/43684
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
  • Loading branch information
rphagura authored and dhendrix committed Aug 15, 2020
1 parent 5b52592 commit afb7a81
Show file tree
Hide file tree
Showing 6 changed files with 726 additions and 8 deletions.
10 changes: 10 additions & 0 deletions Documentation/releases/coreboot-4.13-relnotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,14 @@ attributes as per their datasheet and convert those attributes into SPD files fo
the platforms. More details about the tools are added in
[README.md](https://review.coreboot.org/plugins/gitiles/coreboot/+/refs/heads/master/util/spd_tools/intel/lp4x/README.md).

### New version of SMM loader

A new version of the SMM loader which accomodates platforms with over 32 CPU
CPU threads. The existing version of SMM loader uses a 64K code/data
segment and only a limited number of CPU threads can fit into one segment
(because of save state, STM, other features, etc). This loader extends beyond
the 64K segment to accomodate additional CPUs and in theory allows as many
CPU threads as possible limited only by SMRAM space and not by 64K. By default
this loader version is disabled. Please see cpu/x86/Kconfig for more info.

### Add significant changes here
8 changes: 8 additions & 0 deletions src/cpu/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ config SMM_STUB_STACK_SIZE

endif

config X86_SMM_LOADER_VERSION2
bool
default n
depends on HAVE_SMI_HANDLER
help
This option enables SMM module loader that works with server
platforms which may contain more than 32 CPU threads.

config SMM_LAPIC_REMAP_MITIGATION
bool
default y if NORTHBRIDGE_INTEL_I945
Expand Down
39 changes: 31 additions & 8 deletions src/cpu/x86/mp_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -726,12 +726,21 @@ static void asmlinkage smm_do_relocation(void *arg)
* the location of the new SMBASE. If using SMM modules then this
* calculation needs to match that of the module loader.
*/
#if CONFIG(X86_SMM_LOADER_VERSION2)
perm_smbase = smm_get_cpu_smbase(cpu);
mp_state.perm_smbase = perm_smbase;
if (!perm_smbase) {
printk(BIOS_ERR, "%s: bad SMBASE for CPU %d\n", __func__, cpu);
return;
}
#else
perm_smbase = mp_state.perm_smbase;
perm_smbase -= cpu * runtime->save_state_size;

printk(BIOS_DEBUG, "New SMBASE 0x%08lx\n", perm_smbase);
#endif

/* Setup code checks this callback for validity. */
printk(BIOS_INFO, "%s : curr_smbase 0x%x perm_smbase 0x%x, cpu = %d\n",
__func__, (int)curr_smbase, (int)perm_smbase, cpu);
mp_state.ops.relocation_handler(cpu, curr_smbase, perm_smbase);

if (CONFIG(STM)) {
Expand All @@ -758,9 +767,17 @@ static void adjust_smm_apic_id_map(struct smm_loader_params *smm_params)

static int install_relocation_handler(int num_cpus, size_t save_state_size)
{
int cpus = num_cpus;
#if CONFIG(X86_SMM_LOADER_VERSION2)
/* Default SMRAM size is not big enough to concurrently
* handle relocation for more than ~32 CPU threads
* therefore, relocate 1 by 1. */
cpus = 1;
#endif

struct smm_loader_params smm_params = {
.per_cpu_stack_size = CONFIG_SMM_STUB_STACK_SIZE,
.num_concurrent_stacks = num_cpus,
.num_concurrent_stacks = cpus,
.per_cpu_save_state_size = save_state_size,
.num_concurrent_save_states = 1,
.handler = smm_do_relocation,
Expand All @@ -770,9 +787,10 @@ static int install_relocation_handler(int num_cpus, size_t save_state_size)
if (mp_state.ops.adjust_smm_params != NULL)
mp_state.ops.adjust_smm_params(&smm_params, 0);

if (smm_setup_relocation_handler(&smm_params))
if (smm_setup_relocation_handler(&smm_params)) {
printk(BIOS_ERR, "%s: smm setup failed\n", __func__);
return -1;

}
adjust_smm_apic_id_map(&smm_params);

return 0;
Expand All @@ -781,8 +799,13 @@ static int install_relocation_handler(int num_cpus, size_t save_state_size)
static int install_permanent_handler(int num_cpus, uintptr_t smbase,
size_t smsize, size_t save_state_size)
{
/* There are num_cpus concurrent stacks and num_cpus concurrent save
* state areas. Lastly, set the stack size to 1KiB. */
/*
* All the CPUs will relocate to permanaent handler now. Set parameters
* needed for all CPUs. The placement of each CPUs entry point is
* determined by the loader. This code simply provides the beginning of
* SMRAM region, the number of CPUs who will use the handler, the stack
* size and save state size for each CPU.
*/
struct smm_loader_params smm_params = {
.per_cpu_stack_size = CONFIG_SMM_MODULE_STACK_SIZE,
.num_concurrent_stacks = num_cpus,
Expand All @@ -794,7 +817,7 @@ static int install_permanent_handler(int num_cpus, uintptr_t smbase,
if (mp_state.ops.adjust_smm_params != NULL)
mp_state.ops.adjust_smm_params(&smm_params, 1);

printk(BIOS_DEBUG, "Installing SMM handler to 0x%08lx\n", smbase);
printk(BIOS_DEBUG, "Installing permanent SMM handler to 0x%08lx\n", smbase);

if (smm_load_module((void *)smbase, smsize, &smm_params))
return -1;
Expand Down
4 changes: 4 additions & 0 deletions src/cpu/x86/smm/Makefile.inc
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
## SPDX-License-Identifier: GPL-2.0-only

ifeq ($(CONFIG_X86_SMM_LOADER_VERSION2),y)
ramstage-y += smm_module_loaderv2.c
else
ramstage-y += smm_module_loader.c
endif
ramstage-y += smi_trigger.c

ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y)
Expand Down
Loading

0 comments on commit afb7a81

Please sign in to comment.