Skip to content

Commit

Permalink
UefiCpuPkg:Remove code to wakeup AP and relocate ap
Browse files Browse the repository at this point in the history
After the code to load mtrr setting, set register table,
handle APIC setting and Interrupt after INIT-SIPI-SIPI
is moved, the InitializeCpuProcedure() only contains
following code logic:
1.Bsp runs ExecuteFirstSmiInit().
2.Bsp transfers AP to safe hlt-loop

During S3 boot, since APs will be relocated to new safe
buffer by the callback of gEdkiiEndOfS3ResumeGuid in
PeiMpLib, Bsp doesn't need to transfer AP to safe hlt-loop
any more. SmmRestoreCpu() in CpuS3 only needs to runs the
ExecuteFirstSmiInit() on BSP. So remove code to wakeup
AP by INIT-SIPI-SIPI and remove code to relocate ap to
safe hlt-loop.

Signed-off-by: Dun Tan <[email protected]>
Reviewed-by: Ray Ni <[email protected]>
Cc: Rahul Kumar <[email protected]>
Cc: Gerd Hoffmann <[email protected]>
Reviewed-by: Jiaxin Wu <[email protected]>
  • Loading branch information
td36 authored and mergify[bot] committed Jun 4, 2024
1 parent 525578b commit 341ee5c
Show file tree
Hide file tree
Showing 6 changed files with 12 additions and 686 deletions.
292 changes: 9 additions & 283 deletions UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent

#include "PiSmmCpuDxeSmm.h"
#include <PiPei.h>
#include <Ppi/MpServices2.h>

#pragma pack(1)
typedef struct {
UINTN Lock;
VOID *StackStart;
UINTN StackSize;
VOID *ApFunction;
IA32_DESCRIPTOR GdtrProfile;
IA32_DESCRIPTOR IdtrProfile;
UINT32 BufferStart;
UINT32 Cr3;
UINTN InitializeFloatingPointUnitsAddress;
} MP_CPU_EXCHANGE_INFO;
#pragma pack()

typedef struct {
UINT8 *RendezvousFunnelAddress;
UINTN PModeEntryOffset;
UINTN FlatJumpOffset;
UINTN Size;
UINTN LModeEntryOffset;
UINTN LongJumpOffset;
} MP_ASSEMBLY_ADDRESS_MAP;

//
// Flags used when program the register.
Expand All @@ -44,31 +20,11 @@ typedef struct {
// package level semaphore.
} PROGRAM_CPU_REGISTER_FLAGS;

//
// Signal that SMM BASE relocation is complete.
//
volatile BOOLEAN mInitApsAfterSmmBaseReloc;

/**
Get starting address and size of the rendezvous entry for APs.
Information for fixing a jump instruction in the code is also returned.
@param AddressMap Output buffer for address map information.
**/
VOID *
EFIAPI
AsmGetAddressMap (
MP_ASSEMBLY_ADDRESS_MAP *AddressMap
);

#define LEGACY_REGION_SIZE (2 * 0x1000)
#define LEGACY_REGION_BASE (0xA0000 - LEGACY_REGION_SIZE)

PROGRAM_CPU_REGISTER_FLAGS mCpuFlags;
ACPI_CPU_DATA mAcpiCpuData;
volatile UINT32 mNumberToFinish;
MP_CPU_EXCHANGE_INFO *mExchangeInfo;
BOOLEAN mRestoreSmmConfigurationInS3 = FALSE;
ACPI_CPU_DATA mAcpiCpuData;
BOOLEAN mRestoreSmmConfigurationInS3 = FALSE;

//
// S3 boot flag
Expand All @@ -82,191 +38,6 @@ SMM_S3_RESUME_STATE *mSmmS3ResumeState = NULL;

BOOLEAN mAcpiS3Enable = TRUE;

UINT8 *mApHltLoopCode = NULL;
UINT8 mApHltLoopCodeTemplate[] = {
0x8B, 0x44, 0x24, 0x04, // mov eax, dword ptr [esp+4]
0xF0, 0xFF, 0x08, // lock dec dword ptr [eax]
0xFA, // cli
0xF4, // hlt
0xEB, 0xFC // jmp $-2
};

/**
The function is invoked before SMBASE relocation in S3 path to restores CPU status.
The function is invoked before SMBASE relocation in S3 path. It does first time microcode load
and restores MTRRs for both BSP and APs.
@param IsBsp The CPU this function executes on is BSP or not.
**/
VOID
InitializeCpuBeforeRebase (
IN BOOLEAN IsBsp
)
{
//
// Count down the number with lock mechanism.
//
InterlockedDecrement (&mNumberToFinish);

if (IsBsp) {
//
// Bsp wait here till all AP finish the initialization before rebase
//
while (mNumberToFinish > 0) {
CpuPause ();
}
}
}

/**
The function is invoked after SMBASE relocation in S3 path to restores CPU status.
The function is invoked after SMBASE relocation in S3 path. It restores configuration according to
data saved by normal boot path for both BSP and APs.
@param IsBsp The CPU this function executes on is BSP or not.
**/
VOID
InitializeCpuAfterRebase (
IN BOOLEAN IsBsp
)
{
UINTN TopOfStack;
UINT8 Stack[128];

if (mSmmS3ResumeState->MpService2Ppi == 0) {
if (IsBsp) {
while (mNumberToFinish > 0) {
CpuPause ();
}
} else {
//
// Place AP into the safe code, count down the number with lock mechanism in the safe code.
//
TopOfStack = (UINTN)Stack + sizeof (Stack);
TopOfStack &= ~(UINTN)(CPU_STACK_ALIGNMENT - 1);
CopyMem ((VOID *)(UINTN)mApHltLoopCode, mApHltLoopCodeTemplate, sizeof (mApHltLoopCodeTemplate));
TransferApToSafeState ((UINTN)mApHltLoopCode, TopOfStack, (UINTN)&mNumberToFinish);
}
}
}

/**
Cpu initialization procedure.
@param[in,out] Buffer The pointer to private data buffer.
**/
VOID
EFIAPI
InitializeCpuProcedure (
IN OUT VOID *Buffer
)
{
BOOLEAN IsBsp;

IsBsp = (BOOLEAN)(mBspApicId == GetApicId ());

//
// Skip initialization if mAcpiCpuData is not valid
//
if (mAcpiCpuData.NumberOfCpus > 0) {
//
// First time microcode load and restore MTRRs
//
InitializeCpuBeforeRebase (IsBsp);
}

if (IsBsp) {
//
// Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.
//
ExecuteFirstSmiInit ();
}

//
// Skip initialization if mAcpiCpuData is not valid
//
if (mAcpiCpuData.NumberOfCpus > 0) {
if (IsBsp) {
//
// mNumberToFinish should be set before AP executes InitializeCpuAfterRebase()
//
mNumberToFinish = (UINT32)(mNumberOfCpus - 1);
//
// Signal that SMM base relocation is complete and to continue initialization for all APs.
//
mInitApsAfterSmmBaseReloc = TRUE;
} else {
//
// AP Wait for BSP to signal SMM Base relocation done.
//
while (!mInitApsAfterSmmBaseReloc) {
CpuPause ();
}
}

//
// Restore MSRs for BSP and all APs
//
InitializeCpuAfterRebase (IsBsp);
}
}

/**
Prepares startup vector for APs.
This function prepares startup vector for APs.
@param WorkingBuffer The address of the work buffer.
**/
VOID
PrepareApStartupVector (
EFI_PHYSICAL_ADDRESS WorkingBuffer
)
{
EFI_PHYSICAL_ADDRESS StartupVector;
MP_ASSEMBLY_ADDRESS_MAP AddressMap;

//
// Get the address map of startup code for AP,
// including code size, and offset of long jump instructions to redirect.
//
ZeroMem (&AddressMap, sizeof (AddressMap));
AsmGetAddressMap (&AddressMap);

StartupVector = WorkingBuffer;

//
// Copy AP startup code to startup vector, and then redirect the long jump
// instructions for mode switching.
//
CopyMem ((VOID *)(UINTN)StartupVector, AddressMap.RendezvousFunnelAddress, AddressMap.Size);
*(UINT32 *)(UINTN)(StartupVector + AddressMap.FlatJumpOffset + 3) = (UINT32)(StartupVector + AddressMap.PModeEntryOffset);
if (AddressMap.LongJumpOffset != 0) {
*(UINT32 *)(UINTN)(StartupVector + AddressMap.LongJumpOffset + 2) = (UINT32)(StartupVector + AddressMap.LModeEntryOffset);
}

//
// Get the start address of exchange data between BSP and AP.
//
mExchangeInfo = (MP_CPU_EXCHANGE_INFO *)(UINTN)(StartupVector + AddressMap.Size);
ZeroMem ((VOID *)mExchangeInfo, sizeof (MP_CPU_EXCHANGE_INFO));

CopyMem ((VOID *)(UINTN)&mExchangeInfo->GdtrProfile, (VOID *)(UINTN)mAcpiCpuData.GdtrProfile, sizeof (IA32_DESCRIPTOR));
CopyMem ((VOID *)(UINTN)&mExchangeInfo->IdtrProfile, (VOID *)(UINTN)mAcpiCpuData.IdtrProfile, sizeof (IA32_DESCRIPTOR));

mExchangeInfo->StackStart = (VOID *)(UINTN)mAcpiCpuData.StackAddress;
mExchangeInfo->StackSize = mAcpiCpuData.StackSize;
mExchangeInfo->BufferStart = (UINT32)StartupVector;
mExchangeInfo->Cr3 = (UINT32)(AsmReadCr3 ());
mExchangeInfo->InitializeFloatingPointUnitsAddress = (UINTN)InitializeFloatingPointUnits;
mExchangeInfo->ApFunction = (VOID *)(UINTN)InitializeCpuProcedure;
}

/**
Restore SMM Configuration in S3 boot path.
Expand Down Expand Up @@ -315,12 +86,11 @@ SmmRestoreCpu (
VOID
)
{
SMM_S3_RESUME_STATE *SmmS3ResumeState;
IA32_DESCRIPTOR Ia32Idtr;
IA32_DESCRIPTOR X64Idtr;
IA32_IDT_GATE_DESCRIPTOR IdtEntryTable[EXCEPTION_VECTOR_NUMBER];
EFI_STATUS Status;
EDKII_PEI_MP_SERVICES2_PPI *Mp2ServicePpi;
SMM_S3_RESUME_STATE *SmmS3ResumeState;
IA32_DESCRIPTOR Ia32Idtr;
IA32_DESCRIPTOR X64Idtr;
IA32_IDT_GATE_DESCRIPTOR IdtEntryTable[EXCEPTION_VECTOR_NUMBER];
EFI_STATUS Status;

DEBUG ((DEBUG_INFO, "SmmRestoreCpu()\n"));

Expand Down Expand Up @@ -369,38 +139,10 @@ SmmRestoreCpu (
}
}

mBspApicId = GetApicId ();
//
// Skip AP initialization if mAcpiCpuData is not valid
// Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.
//
if (mAcpiCpuData.NumberOfCpus > 0) {
if (FeaturePcdGet (PcdCpuHotPlugSupport)) {
ASSERT (mNumberOfCpus <= mAcpiCpuData.NumberOfCpus);
} else {
ASSERT (mNumberOfCpus == mAcpiCpuData.NumberOfCpus);
}

mNumberToFinish = (UINT32)mNumberOfCpus;

//
// Execute code for before SmmBaseReloc. Note: This flag is maintained across S3 boots.
//
mInitApsAfterSmmBaseReloc = FALSE;

if (mSmmS3ResumeState->MpService2Ppi != 0) {
Mp2ServicePpi = (EDKII_PEI_MP_SERVICES2_PPI *)(UINTN)mSmmS3ResumeState->MpService2Ppi;
Mp2ServicePpi->StartupAllCPUs (Mp2ServicePpi, InitializeCpuProcedure, 0, NULL);
} else {
PrepareApStartupVector (mAcpiCpuData.StartupVector);
//
// Send INIT IPI - SIPI to all APs
//
SendInitSipiSipiAllExcludingSelf ((UINT32)mAcpiCpuData.StartupVector);
InitializeCpuProcedure (NULL);
}
} else {
InitializeCpuProcedure (NULL);
}
ExecuteFirstSmiInit ();

//
// Set a flag to restore SMM configuration in S3 path.
Expand Down Expand Up @@ -471,8 +213,6 @@ InitSmmS3ResumeState (
VOID *GuidHob;
EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
SMM_S3_RESUME_STATE *SmmS3ResumeState;
EFI_PHYSICAL_ADDRESS Address;
EFI_STATUS Status;

if (!mAcpiS3Enable) {
return;
Expand Down Expand Up @@ -524,20 +264,6 @@ InitSmmS3ResumeState (
//
InitSmmS3Cr3 ();
}

//
// Allocate safe memory in ACPI NVS for AP to execute hlt loop in
// protected mode on S3 path
//
Address = BASE_4GB - 1;
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiACPIMemoryNVS,
EFI_SIZE_TO_PAGES (sizeof (mApHltLoopCodeTemplate)),
&Address
);
ASSERT_EFI_ERROR (Status);
mApHltLoopCode = (UINT8 *)(UINTN)Address;
}

/**
Expand Down
Loading

0 comments on commit 341ee5c

Please sign in to comment.