Get AP wakeup buffer and copy AP reset code into it. Allocate APs' stack and CPU MP data buffer. Fill CPU MP data fields accordingly.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan <jeff....@intel.com> CC: Feng Tian <feng.t...@intel.com> CC: Jiewen Yao <jiewen....@intel.com> CC: Michael Kinney <michael.d.kin...@intel.com> --- UefiCpuPkg/CpuMpPei/CpuMpPei.c | 87 ++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuMpPei/CpuMpPei.h | 41 ++++++++++++++++++- UefiCpuPkg/CpuMpPei/CpuMpPei.inf | 9 ++++- 3 files changed, 135 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.c b/UefiCpuPkg/CpuMpPei/CpuMpPei.c index 0e34f26..45243d8 100644 --- a/UefiCpuPkg/CpuMpPei/CpuMpPei.c +++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.c @@ -111,6 +111,88 @@ GetWakeupBuffer ( } /** + Get available system memory below 1MB by specified size. + + @param PeiCpuMpData Pointer to PEI CPU MP Data +**/ +VOID +BackupAndPrepareWakeupBuffer( + IN PEI_CPU_MP_DATA *PeiCpuMpData + ) +{ + CopyMem ( + (VOID *) PeiCpuMpData->BackupBuffer, + (VOID *) PeiCpuMpData->WakeupBuffer, + PeiCpuMpData->BackupBufferSize + ); + CopyMem ( + (VOID *) PeiCpuMpData->WakeupBuffer, + (VOID *) PeiCpuMpData->AddressMap.RendezvousFunnelAddress, + PeiCpuMpData->AddressMap.RendezvousFunnelSize + ); +} +/** + Prepare for AP wakeup buffer and copy AP reset code into it. + + Get wakeup buffer below 1MB. Allocate memory for CPU MP Data and APs Stack. + + @return Pointer to PEI CPU MP Data +**/ +PEI_CPU_MP_DATA * +PrepareAPStartupVector ( + VOID + ) +{ + EFI_STATUS Status; + UINT32 MaxCpuCount; + PEI_CPU_MP_DATA *PeiCpuMpData; + EFI_PHYSICAL_ADDRESS Buffer; + UINTN BufferSize; + UINTN WakeupBuffer; + UINTN WakeupBufferSize; + MP_ASSEMBLY_ADDRESS_MAP AddressMap; + + AsmGetAddressMap (&AddressMap); + WakeupBufferSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO); + WakeupBuffer = GetWakeupBuffer ((WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1)); + DEBUG ((EFI_D_INFO, "CpuMpPei: WakeupBuffer = 0x%x\n", WakeupBuffer)); + + // + // Allocate Pages for APs stack, CPU MP Data and backup buffer for wakeup buffer + // + MaxCpuCount = PcdGet32(PcdCpuMaxLogicalProcessorNumber); + BufferSize = PcdGet32 (PcdCpuApStackSize) * MaxCpuCount + sizeof (PEI_CPU_MP_DATA) + + WakeupBufferSize + sizeof (PEI_CPU_DATA) * MaxCpuCount; + Status = PeiServicesAllocatePages ( + EfiBootServicesData, + EFI_SIZE_TO_PAGES (BufferSize), + &Buffer + ); + ASSERT_EFI_ERROR (Status); + + PeiCpuMpData = (PEI_CPU_MP_DATA *) (UINTN) (Buffer + PcdGet32 (PcdCpuApStackSize) * MaxCpuCount); + PeiCpuMpData->Buffer = (UINTN) Buffer; + PeiCpuMpData->CpuApStackSize = PcdGet32 (PcdCpuApStackSize); + PeiCpuMpData->WakeupBuffer = WakeupBuffer; + PeiCpuMpData->BackupBuffer = (UINTN)PeiCpuMpData + sizeof (PEI_CPU_MP_DATA); + PeiCpuMpData->BackupBufferSize = WakeupBufferSize; + PeiCpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeupBuffer + AddressMap.RendezvousFunnelSize); + + PeiCpuMpData->CpuCount = 1; + PeiCpuMpData->BspNumber = 0; + PeiCpuMpData->CpuData = (PEI_CPU_DATA *) (PeiCpuMpData->MpCpuExchangeInfo + 1); + PeiCpuMpData->CpuData[0].ApicId = GetInitialApicId (); + PeiCpuMpData->CpuData[0].Health.Uint32 = 0; + CopyMem (&PeiCpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP)); + + // + // Backup original data and copy AP reset code in it + // + BackupAndPrepareWakeupBuffer(PeiCpuMpData); + + return PeiCpuMpData; +} +/** The Entry point of the MP CPU PEIM. This function will wakeup APs and collect CPU AP count and install the @@ -130,11 +212,16 @@ CpuMpPeimInit ( ) { + PEI_CPU_MP_DATA *PeiCpuMpData; // // Load new GDT table on BSP // AsmInitializeGdt (&mGdt); + // + // Get wakeup buffer and copy AP reset code in it + // + PeiCpuMpData = PrepareAPStartupVector (); return EFI_SUCCESS; } diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.h b/UefiCpuPkg/CpuMpPei/CpuMpPei.h index 7c96084..1219e4e 100644 --- a/UefiCpuPkg/CpuMpPei/CpuMpPei.h +++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.h @@ -17,11 +17,25 @@ #include <PiPei.h> +#include <Ppi/SecPlatformInformation.h> #include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> #include <Library/HobLib.h> +#include <Library/LocalApicLib.h> +#include <Library/PcdLib.h> #include <Library/PeimEntryPoint.h> +#include <Library/PeiServicesLib.h> #include <Library/UefiCpuLib.h> +// +// AP state +// +typedef enum { + CpuStateIdle, + CpuStateBusy, + CpuStateDisabled +} CPU_STATE; // // AP reset code information @@ -33,7 +47,9 @@ typedef struct { UINTN RendezvousFunnelSize; } MP_ASSEMBLY_ADDRESS_MAP; -#pragma pack(1) +typedef struct _PEI_CPU_MP_DATA PEI_CPU_MP_DATA; + +#pragma pack() typedef union { struct { @@ -73,6 +89,29 @@ typedef struct { #pragma pack() +typedef struct { + UINT32 ApicId; + EFI_HEALTH_FLAGS Health; + CPU_STATE State; + BOOLEAN CpuHealthy; +} PEI_CPU_DATA; + +// +// PEI CPU MP Data save in memory +// +struct _PEI_CPU_MP_DATA { + UINT32 CpuCount; + UINT32 BspNumber; + UINTN Buffer; + UINTN CpuApStackSize; + MP_ASSEMBLY_ADDRESS_MAP AddressMap; + UINTN WakeupBuffer; + UINTN BackupBuffer; + UINTN BackupBufferSize; + PEI_CPU_DATA *CpuData; + volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo; +}; + /** Assembly code to get starting address and size of the rendezvous entry for APs. Information for fixing a jump instruction in the code is also returned. diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf index 9fb9e94..a04556f 100644 --- a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf +++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf @@ -49,12 +49,19 @@ [LibraryClasses] BaseLib + BaseMemoryLib + DebugLib HobLib + LocalApicLib + PcdLib PeimEntryPoint + PeiServicesLib UefiCpuLib - +[Pcd] + gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber + gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize [Depex] gEfiPeiMemoryDiscoveredPpiGuid -- 1.9.5.msysgit.0 ------------------------------------------------------------------------------ Don't Limit Your Business. Reach for the Cloud. GigeNET's Cloud Solutions provide you with the tools and support that you need to offload your IT needs and focus on growing your business. Configured For All Businesses. Start Your Cloud Today. https://www.gigenetcloud.com/ _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel