TR is used to enable a separate safe stack when a stack overflow occurs.
When PEI starts up the APs, TR is non-zero and so each processor has its
own GDT. TR is an offset into the GDT and so points to a different TSS
entry in each AP.
There is a small window in early DXE after MpInitLibInitialize() is
called where:
- TR is non-zero because it has been inherited from the PEI phase
- TR is not restored to 0
- The APs are all switched to using the BSP's GDT
- SaveVolatileRegisters() is called from ApWakeupFunction() before the
APs go to sleep, which saves the non-zero TR value to
CpuMpData->CpuData[].VolatileRegisters.Tr, cause TR to point to the
same TSS entry in the BSP's GDT
- The next time the APs are woken up, RestoreVolatileRegisters() is
called from ApWakeupFunction() which would attempt to load the non-zero
TR value into the actual task register, which creates a race condition
to a #GP fault because loading the task register sets the busy bit in
the TSS descriptor and a #GP fault occurs if the busy bit is already
set when loading the task register.
To avoid this issue, the task register is only loaded if TR is non-zero
and the TSS descriptor is valid and not busy. HW sets the busy bit and
does not clear it. edk2 does not clear the busy bit, so the BSP's TSS
descriptor will be marked busy forever and the APs will not load the
task register until they have their own GDT/TSS set up.
Co-authored-by: Ray Ni <ray.ni@intel.com>
Signed-off-by: Oliver Smith-Denny <osde@microsoft.com>
Today, CpuMpPei and CpuDxe only initialize separate exception
stacks for the APs when PcdCpuStackGuard is enabled so that
if a stack overflow occurs, hitting the guard page, the exception
can be handler with a separate stack.
However, this operation also creates a separate GDT for each AP.
This is a safer option than all APs sharing the BSP's GDT because
there are issues with concurrent access to the structures contained
within. Furthermore, even when a stack guard page is not present,
stack overflows can still occur and corrupt the stack; if an
exception is taken here, it is still valuable to have a separate
exception stack for sanity.
This commit updates CpuMpPei and CpuDxe to always create separate
exception stacks for the APs (and therefore separate GDTs).
Signed-off-by: Oliver Smith-Denny <osde@microsoft.com>
`PageStartAddress` variable was not set correctly because the encryption bit
was not considered, which broke the page walk logic.
Get the bitmask and mask the encryption bit.
Signed-off-by: Luigi Leonardi <leonardi@redhat.com>
This commit allocated an ACPI NVS buffer in PEI:
cdc1a88272
This is a RT visible memory type that remains fragmented against the
overall `EfiACPIMemoryNVS` memory bucket allocated by the DXE Core.
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
edk2 is dropping support for the ARM32 architecture. This commit
removes ARM32 code from UefiCpuPkg. It drops irrelevant
VALID_ARCHITECTURES fields from infs that are not arch
specific.
Signed-off-by: Oliver Smith-Denny <osde@microsoft.com>
Update [BuildOptions] so CLANGPDB matches MSFT to support
Windows/clang builds of MtrrLib host-based unit tests.
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
If AP loop mode is not Halt loop, it is found that the AP in ApInitDone
state exits the loop mode immediately when WAKEUP_AP_SIGNAL is signaled
at the first step of AP wake up. When WakeUpByInitSipiSipi is enabled,
it is possible that the AP could clear StartupApSignal buffer before the
BSP sends Init-Startup IPI to the AP. In the case, it causes that the BSP
frees AP reset vector buffer even though AP wake up is in process. This
results in an exception error. To ensure AP wake up, it is expected that
the AP is in the known non-executable state before the AP wakeup signal.
The issue happens when the AP is disabled through the MP service of
gEfiMpServiceProtocolGuid->EnableDisableAP(FALSE) and enabled later
through gEfiMpServiceProtocolGuid->EnableDisableAP(TRUE). In the flow,
the AP that in MINOTOR-MWAIT-Loop or Run-Loop can respond to the
WAKEUP_AP_SIGNAL before the BSP sends the INIT-SIPI-SIPI.
Signed-off-by: Phil Noh <Phil.Noh@amd.com>
In early boot phases (SEC/PEI), CpuTimerLib may be used before
GetPerformanceCounterProperties() is called, leaving mTimeBase
uninitialized. This can result in divide-by-zero errors or incorrect
timeouts.
To fix this, check if mTimeBase is set before using it and initialize it
via GetPerformanceCounterProperties() if necessary.
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
Signed-off-by: Tuan Phan <tphan@ventanamicro.com>
Mitigates CVE-2025-3770
Do not assume that IDT.limit is loaded with a zero value upon SMM entry.
Delay enabling Machine Check Exceptions in SMM until after the SMM IDT
has been reloaded.
Signed-off-by: John Mathews <john.mathews@intel.com>
The FillExchangeInfoDataSevEs() is only called for SEV-SNP guests, but
the name (and comment in MpLib.c) implies that it is also called for
SEV-ES guests. Rename the function to FillExchangeInfoDataSevSnp() to
avoid confusion.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
The SevSnpKnownInitApicId field within the MP_CPU_EXCHANGE_INFO structure
is not guaranteed to be zero when booting an SEV-ES guest. While the check
in SevSnpGetInitCpuNumber() is conditionally guarded by verifying if the
guest is an SEV-SNP guest, the check in SevEsGetApicId() is not similarly
guarded.
This lack of protection can cause SevEsGetApicId() to return to the wrong
location. If the value of the SevSnpKnownInitApicId field contains the
exact random value of 1, the guest will be treated as an SEV-SNP guest
rather than an SEV-ES guest and return to the wrong location in the code
which will lead to a crash.
Ensure that all SEV related fields in MP_CPU_EXCHANGE_INFO structure are
properly initialized, thus removing the need for guarding access to the
SevSnpKnownInitApicId field.
Fixes: dca5d26bc5 ("UefiCpuPkg/MpInitLib: Fix SNP AP creation when using known APIC IDs")
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Update AllApArrivedWithException if the 1st timeout sync is skipped
but all APs have arrived.
Example:
If IsCpuSyncAlwaysNeeded() returns false, LMCE is enabled and
triggered, and another SMI source combined with LMCE causes all APs
to enter SMI. Then 2nd timeout sync will be also skipped, but all APs
have arrived, so AllApArrivedWithException should be updated before
using.
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
Encapsulate IA32 and X64 code under preprocessor directives to enable
module compatibility with other architectures.
Signed-off-by: Tuan Phan <tphan@ventanamicro.com>
In the MpInitLib, pages are allocated for
the APs, and data is copied into them. Depending
on the allocation type, Nx needs to be removed
from the pages to allow the processors to execute.
Additionally, ReadOnly needs to be applied to the
pages after they have been filled with the
instructions that the APs need to execute.
Signed-off-by: Aaron Pop <aaronpop@microsoft.com>
Co-authored-by: Oliver Smith-Denny <osde@microsoft.com>
There is GetPerformanceCounterProperties() that relies
on Device Tree to fetch timer frequency and removes the
dependency from the PCDs, use that instead.
Signed-off-by: Akshay Behl <cap2k4@rivosinc.com>
Co-authored-by: Dhaval Sharma <dhaval@rivosinc.com>
There is GetPerformanceCounterProperties() that relies
on Device Tree to fetch timer frequency and removes the
dependency from the PCDs, use that instead.
Signed-off-by: Akshay Behl <cap2k4@rivosinc.com>
Co-authored-by: Dhaval Sharma <dhaval@rivosinc.com>
On RISC-V platforms, just like other platforms, we need to pass various
information from one stage to another (hartid/cmo operations etc).
Also there are some settings like Timer freq which are platform dependent
which use PCDs. Today hartid is extracted through Firmware Context
(custom in mem structure passed from one stage to another). For CMO we
have a features HOB. Going forward we would like to have a standard
mechanism to pass on such information and DT is handy as it can easily
carry all this information (in some cases nodes already exists). This
patch implement timebase frequency extraction from DT.
Signed-off-by: Akshay Behl <cap2k4@rivosinc.com>
Co-authored-by: Dhaval Sharma <dhaval@rivosinc.com>
Move ArmMmuLib from ArmPkg to UefiCpuPkg for easy maintaining.
Continuous-integration-options: PatchCheck.ignore-multi-package
Signed-off-by: Ajan Zhong <ajan.zhong@newfw.com>
Move the ArmMmuLib interface definition to UefiCpuPkg, with this change,
MMU libraries for ARM, AARCH64, RiscV, LongArch64 architectures all
reside in UefiCpuPkg.
Continuous-integration-options: PatchCheck.ignore-multi-package
Signed-off-by: Ajan Zhong <ajan.zhong@newfw.com>
This patch introduces a synchronization point between the BSP and APs to
ensure all APs have entered their SMM wait-loop (while (TRUE) in APHandler
()) before the BSP calls into the SMI handler logic via gSmmCpuPrivate
->SmmCoreEntry().
Previously, the BSP would invoke ReleaseAllAPs() and immediately proceed
to SmmCoreEntry() without confirming whether APs had reached the stable
waiting state. If SmmStartupThisAp() was called inside the SMI handler
shortly after ReleaseAllAPs(), it might lead to a race condition:
APs are issued two consecutive wait signals (SmmCpuSyncWaitForBsp()).
BSP sends two consecutive releases (ReleaseAllAPs() + SmmStartupThisAp())
If an AP has not yet responded to the first release, the second release may
overwrite the semaphore state, and the AP might miss the notification,
causing it to hang or behave unpredictably.
To address this:
A SmmCpuSyncWaitForAPs() is added in BSP after
mmCpuPlatformHookBeforeMmiHandler() and before entering SmmCoreEntry().
A matching SmmCpuSyncReleaseBsp() is added in AP immediately after its own
SmmCpuPlatformHookBeforeMmiHandler()
This ensures that BSP does not enter SMI handler logic or dispatch any
AP-related requests before all APs are confirmed to be idle and ready.
Debug sync point markers (e.g., /// #6, #7) are updated accordingly.
This change eliminates a subtle but critical race condition in
multi-processor/multi-socket systems during SMM entry and improves overall
synchronization safety.
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
This patch introduces a synchronization point between the BSP and APs to
ensure all APs have entered their SMM wait-loop (while (TRUE) in APHandler
()) before the BSP calls into the SMI handler logic via gSmmCpuPrivate
->SmmCoreEntry().
Previously, the BSP would invoke ReleaseAllAPs() and immediately proceed
to SmmCoreEntry() without confirming whether APs had reached the stable
waiting state. If SmmStartupThisAp() was called inside the SMI handler
shortly after ReleaseAllAPs(), it might lead to a race condition:
APs are issued two consecutive wait signals (SmmCpuSyncWaitForBsp()).
BSP sends two consecutive releases (ReleaseAllAPs() + SmmStartupThisAp())
If an AP has not yet responded to the first release, the second release may
overwrite the semaphore state, and the AP might miss the notification,
causing it to hang or behave unpredictably.
To address this:
A SmmCpuSyncWaitForAPs() is added in BSP after
mmCpuPlatformHookBeforeMmiHandler() and before entering SmmCoreEntry().
A matching SmmCpuSyncReleaseBsp() is added in AP immediately after its own
SmmCpuPlatformHookBeforeMmiHandler()
This ensures that BSP does not enter SMI handler logic or dispatch any
AP-related requests before all APs are confirmed to be idle and ready.
Debug sync point markers (e.g., /// #6, #7) are updated accordingly.
This change eliminates a subtle but critical race condition in
multi-processor/multi-socket systems during SMM entry and improves overall
synchronization safety.
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
Add missing EFIAPI calling convention to all EFI_AP_PROCEDURE functions
in the EfiMpServicesPpiProtocol unit tests.
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
A split-lock violation in OVMF was discovered due to the
NumApsExecuting field of the MP_CPU_EXCHANGE_INFO
struct (which is used atomically by the AP Reset Vector
assembly code) crossing a cacheline boundary.
Since the MP_CPU_EXCHANGE_INFO struct is unaligned and
the NumApsExecuting field resides after other non-UINTN aligned
fields in the struct (i.e. GdtrProfile/IdtrProfile), the
NumApsExecuting field was allocated at a non-UINTN aligned
address (crossing a cache-line) resulting in the split-lock
violation.
Therefore, align the MP_CPU_EXCHANGE_INFO struct (on a UINTN
boundary) and move the NumApsExecuting field to before the
GdtrProfile/IdtrProfile fields to ensure it is UINTN aligned and
thus resides within a single cacheline avoiding the split-lock.
Do the same for the ApIndex field as it is also used atomically
and thus subject to a split-lock violation.
Cc: Ray Ni <ray.ni@intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Dun Tan <dun.tan@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Star Zeng <star.zeng@intel.com>
Signed-off-by: Aaron Young <aaron.young@oracle.com>
Currently if PcdCpuSmmRestrictedMemoryAccess is a DynamicPcd
it will be accessed during SMM entry causing an error since code
outside of SMM will be called (PcdGetBool).
To fix that PcdCpuSmmRestrictedMemoryAccess is retrieved during
SMM initialization and cached value is used at runtime
Signed-off-by: Sienski Piotr <piotr.sienski@intel.com>
SyncContext of SMM_DISPATCHER_MP_SYNC_DATA was dynamically allocated from
SMRAM. The memory was not freed before reallocation in S3 resume path.
This could lead to:
1. Memory leak in SMRAM.
2. Potential S3 resume failure after repeated S3 tests due to SMRAM
exhaustion.
This change releases the SyncContext memory before reallocating it
Signed-off-by: Zhou Jianfeng <jianfeng.zhou@intel.com>
A typical initial AP boot up will choose a CpuNumber based on the ApIndex
value that it gets back after a locked increment of the ApIndex value.
The ApIndex to APIC ID relationship is random, which is not an issue when
a broadcast INIT-SIPI is performed.
With SNP and a hypervisor that supports retrieval of the known APIC IDs,
the broadcast INIT-SIPI method is replaced by waking each individual vCPU.
In this situation, a specific VMSA is associated with a specific APIC ID.
However, random assignment of an ApIndex can break this association. This
isn't typically an issue, because the AP bring-up finishes with the AP
issuing a HLT instruction, which is intercepted by the hypervisor and the
AP won't run again until the next INIT-SIPI. However, when HLT isn't
intercepted by the hypervisor (Qemu '-overcommit cpu-pm=on' parameter),
then the HLT does not exit to the hypervisor. On the next INIT-SIPI, it
can happen that a VMRUN is executed with a different VMSA address than
was originally used, and if that VMSA is still in a VMRUN on another AP,
then the executing VMRUN will fail, crashing the guest.
To fix this issue, add a CPU exchange info field, SevSnpKnownInitApicId,
that indicates the APs are starting with an already known initial APIC ID
and set the initial APIC ID and APIC ID in the CPU_INFO_IN_HOB HOB.
During AP boot, the SevSnpKnownInitApicId field will result in the
CpuNumber being set to the index with a matching APIC ID (similar to AP
booting when the InitFlag != ApInitConfig).
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Commit aef50446ce
removed gEdkiiPeiMpServices2PpiGuid from UefiCpuPkg.dec
which causes build breaks if an INF [Ppis] section
lists gEdkiiPeiMpServices2PpiGuid. There is no method
for a DEC file for conditionally declare a PPI.
In order to support the migration from use of
gEdkiiPeiMpServices2PpiGuid to the preferred use of the
gPeiMpServices2Ppi, add gEdkiiPeiMpServices2PpiGuid back
to the UefiCpuPkg.dec.
All references to the EDK II PEI MP Services 2 PPI can be
removed after all downstream consumers have had a chance
to perform the migration.
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
EDKII_PEI_MP_SERVICES2_PPI has been renamed to EFI_PEI_MP_SERVICES2_PPI
and moved to MdePkg.
Relevant changes have been made here.
Signed-off-by: Sachin Ganesh <sachinganesh@ami.com>
EDKII_PEI_MP_SERVICES2_PPI has been renamed to EFI_PEI_MP_SERVICES2_PPI
and moved to MdePkg.
Relevant changes have been made here.
Signed-off-by: Sachin Ganesh <sachinganesh@ami.com>
EDKII_PEI_MP_SERVICES2_PPI has been renamed to EFI_PEI_MP_SERVICES2_PPI
and moved to MdePkg.
Relevant changes have been made here.
Signed-off-by: Sachin Ganesh <sachinganesh@ami.com>
EDKII_PEI_MP_SERVICES2_PPI has been renamed to EFI_PEI_MP_SERVICES2_PPI
and moved to MdePkg.
Relevant changes have been made here.
Signed-off-by: Sachin Ganesh <sachinganesh@ami.com>
EDKII_PEI_MP_SERVICES2_PPI has been renamed to EFI_PEI_MP_SERVICES2_PPI
and moved to MdePkg.
Relevant changes have been made here.
Signed-off-by: Sachin Ganesh <sachinganesh@ami.com>
EDKII_PEI_MP_SERVICES2_PPI has been renamed to EFI_PEI_MP_SERVICES2_PPI
and moved to MdePkg.
The related header and PPI GUID has been removed from UefiCpuPkg
Signed-off-by: Sachin Ganesh <sachinganesh@ami.com>
IntelMmSaveStateLib and SmmCpuPlatformHookLibNull were limited to
DXE_SMM_DRIVER MM_STANDALONE, where as previously not supported module
types were listed.
Add MM_CORE_STANDALONE as a supported module type for these libraries.
Signed-off-by: Aaron Pop <aaronpop@microsoft.com>
There will be build failure because of EFI_AP_PROCEDURE definition
not found if MpInformation2.h is included by base type library.
MpInformation2.h depends on MpService.h because of
EFI_PROCESSOR_INFORMATION definition, and then MpService.h
depends on PiMultiPhase.h because of EFI_AP_PROCEDURE definition.
This patch updates MpInformation2.h to include PiMultiPhase.h instead
of PiPei.h and also removes SecPlatformInformation.h including.
It also does minor refinement to file header description.
Signed-off-by: Star Zeng <star.zeng@intel.com>