There is currently a fundamental flaw in the current cpu_info() implementation. It assumes that current stack is CONFIG_STACK_SIZE aligned. This assumption breaks down when performing SMM relocation. The first step in performing SMM relocation is changing the SMBASE. This is accomplished by installing the smmstub at 0x00038000, which is the default SMM entry point. The stub is configured to set up a new stack with the size of 1 KiB (CONFIG_SMM_STUB_STACK_SIZE), and an entry point of smm_do_relocation located in RAMSTAGE RAM. This means that when smm_do_relocation is executed, it is running in SMM with a different sized stack. When cpu_info() gets called it will be using CONFIG_STACK_SIZE to calculate the location of the cpu_info struct. This results in reading random memory. Since cpu_info() has to run in multiple environments, we can't use a compile time constant to locate the cpu_info struct. This CL introduces a new way of locating cpu_info. It uses a per-cpu segment descriptor that points to a per-cpu segment that is allocated on the stack. By using a segment descriptor to point to the per-cpu data, we no longer need to calculate the location of the cpu_info struct. This has the following advantages: * Stacks no longer need to be CONFIG_STACK_SIZE aligned. * Accessing an unconfigured segment will result in an exception. This ensures no one can call cpu_info() from an unsupported environment. * Segment selectors are cleared when entering SMM and restored when leaving SMM. * There is a 1:1 mapping between cpu and cpu_info. When using COOP_MULTITASKING, a new cpu_info is currently allocated at the top of each thread's stack. This no longer needs to happen. This CL guards most of the code with CONFIG(CPU_INFO_V2). I did this so reviewers can feel more comfortable knowing most of the CL is a no-op. I would eventually like to remove most of the guards though. This CL does not touch the LEGACY_SMP_INIT code path. I don't have any way of testing it. The %gs segment was chosen over the %fs segment because it's what the linux kernel uses for per-cpu data in x86_64 mode. BUG=b:194391185, b:179699789 TEST=Boot guybrush with CPU_INFO_V2 and verify BSP and APs have correct %gs segment. Verify cpu_info looks sane. Verify booting to the OS works correctly with COOP_MULTITASKING enabled. Signed-off-by: Raul E Rangel <rrangel@chromium.org> Change-Id: I79dce9597cb784acb39a96897fb3c2f2973bfd98 Reviewed-on: https://review.coreboot.org/c/coreboot/+/57627 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Eric Peers <epeers@google.com> Reviewed-by: Karthik Ramasubramanian <kramasub@google.com>
203 lines
4.4 KiB
Text
203 lines
4.4 KiB
Text
config PARALLEL_MP
|
|
def_bool y
|
|
depends on !LEGACY_SMP_INIT
|
|
depends on SMP
|
|
help
|
|
This option uses common MP infrastructure for bringing up APs
|
|
in parallel. It additionally provides a more flexible mechanism
|
|
for sequencing the steps of bringing up the APs.
|
|
|
|
config PARALLEL_MP_AP_WORK
|
|
def_bool n
|
|
depends on PARALLEL_MP
|
|
help
|
|
Allow APs to do other work after initialization instead of going
|
|
to sleep.
|
|
|
|
config LEGACY_SMP_INIT
|
|
bool
|
|
|
|
choice LAPIC_ACCESS_MODE
|
|
prompt "APIC operation mode"
|
|
default XAPIC_ONLY
|
|
|
|
config XAPIC_ONLY
|
|
prompt "Set XAPIC mode"
|
|
bool
|
|
|
|
config X2APIC_ONLY
|
|
prompt "Set X2APIC mode"
|
|
bool
|
|
depends on PARALLEL_MP
|
|
|
|
config X2APIC_RUNTIME
|
|
prompt "Support both XAPIC and X2APIC"
|
|
bool
|
|
depends on PARALLEL_MP
|
|
|
|
endchoice
|
|
|
|
config UDELAY_LAPIC
|
|
bool
|
|
default n
|
|
|
|
config LAPIC_MONOTONIC_TIMER
|
|
def_bool n
|
|
depends on UDELAY_LAPIC
|
|
help
|
|
Expose monotonic time using the local APIC.
|
|
|
|
config UDELAY_LAPIC_FIXED_FSB
|
|
int
|
|
|
|
config UDELAY_TSC
|
|
bool
|
|
default n
|
|
|
|
config UNKNOWN_TSC_RATE
|
|
bool
|
|
default y if LAPIC_MONOTONIC_TIMER
|
|
|
|
config TSC_MONOTONIC_TIMER
|
|
def_bool n
|
|
depends on UDELAY_TSC
|
|
help
|
|
Expose monotonic time using the TSC.
|
|
|
|
config TSC_SYNC_LFENCE
|
|
bool
|
|
default n
|
|
help
|
|
The CPU driver should select this if the CPU needs
|
|
to execute an lfence instruction in order to synchronize
|
|
rdtsc. This is true for all modern AMD CPUs.
|
|
|
|
config TSC_SYNC_MFENCE
|
|
bool
|
|
default n
|
|
help
|
|
The CPU driver should select this if the CPU needs
|
|
to execute an mfence instruction in order to synchronize
|
|
rdtsc. This is true for all modern Intel CPUs.
|
|
|
|
config SETUP_XIP_CACHE
|
|
bool
|
|
depends on !NO_XIP_EARLY_STAGES
|
|
help
|
|
Select this option to set up an MTRR to cache XIP stages loaded
|
|
from the bootblock. This is useful on platforms lacking a
|
|
non-eviction mode and therefore need to be careful to avoid
|
|
eviction.
|
|
|
|
config CPU_ADDR_BITS
|
|
int
|
|
default 36
|
|
|
|
config LOGICAL_CPUS
|
|
bool
|
|
default y
|
|
|
|
config HAVE_SMI_HANDLER
|
|
bool
|
|
default n
|
|
depends on (SMM_ASEG || SMM_TSEG)
|
|
|
|
config NO_SMM
|
|
bool
|
|
default n
|
|
|
|
config SMM_ASEG
|
|
bool
|
|
default n
|
|
depends on !NO_SMM
|
|
|
|
config SMM_TSEG
|
|
bool
|
|
default y
|
|
depends on !(NO_SMM || SMM_ASEG)
|
|
|
|
if SMM_TSEG
|
|
|
|
config SMM_MODULE_HEAP_SIZE
|
|
hex
|
|
default 0x4000
|
|
help
|
|
This option determines the size of the heap within the SMM handler
|
|
modules.
|
|
|
|
config SMM_MODULE_STACK_SIZE
|
|
hex
|
|
default 0x800 if ARCH_RAMSTAGE_X86_64
|
|
default 0x400
|
|
help
|
|
This option determines the size of the stack within the SMM handler
|
|
modules.
|
|
|
|
config SMM_STUB_STACK_SIZE
|
|
hex
|
|
default 0x400
|
|
help
|
|
This option determines the size of the stack within the SMM handler
|
|
modules.
|
|
|
|
endif
|
|
|
|
config SMM_LAPIC_REMAP_MITIGATION
|
|
bool
|
|
default y if NORTHBRIDGE_INTEL_I945
|
|
default y if NORTHBRIDGE_INTEL_GM45
|
|
default y if NORTHBRIDGE_INTEL_IRONLAKE
|
|
default n
|
|
|
|
config SERIALIZED_SMM_INITIALIZATION
|
|
bool
|
|
default n
|
|
help
|
|
On some CPUs, there is a race condition in SMM.
|
|
This can occur when both hyperthreads change SMM state
|
|
variables in parallel without coordination.
|
|
Setting this option serializes the SMM initialization
|
|
to avoid an ugly hang in the boot process at the cost
|
|
of a slightly longer boot time.
|
|
|
|
config X86_AMD_FIXED_MTRRS
|
|
bool
|
|
default n
|
|
help
|
|
This option informs the MTRR code to use the RdMem and WrMem fields
|
|
in the fixed MTRR MSRs.
|
|
|
|
config X86_AMD_INIT_SIPI
|
|
bool
|
|
default n
|
|
help
|
|
This option limits the number of SIPI signals sent during during the
|
|
common AP setup. Intel documentation specifies an INIT SIPI SIPI
|
|
sequence, however this doesn't work on some AMD platforms. These
|
|
newer AMD platforms don't need the 10ms wait between INIT and SIPI,
|
|
so skip that too to save some time.
|
|
|
|
config SOC_SETS_MSRS
|
|
bool
|
|
default n
|
|
help
|
|
The SoC requires different access methods for reading and writing
|
|
the MSRs. Use SoC specific routines to handle the MSR access.
|
|
|
|
config RESERVE_MTRRS_FOR_OS
|
|
bool
|
|
default n
|
|
help
|
|
This option allows a platform to reserve 2 MTRRs for the OS usage.
|
|
The Intel SDM documents that the the first 6 MTRRs are intended for
|
|
the system BIOS and the last 2 are to be reserved for OS usage.
|
|
However, modern OSes use PAT to control cacheability instead of
|
|
using MTRRs.
|
|
|
|
config CPU_INFO_V2
|
|
bool
|
|
depends on PARALLEL_MP
|
|
help
|
|
Enables the new method of locating struct cpu_info. This new method
|
|
uses the %gs segment to locate the cpu_info pointer. The old method
|
|
relied on the stack being CONFIG_STACK_SIZE aligned.
|