diff options
-rw-r--r-- | UefiCpuPkg/CpuMpPei/CpuMpPei.c | 837 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/CpuMpPei.h | 248 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/CpuMpPei.inf | 29 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/Ia32/MpEqu.inc | 39 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.asm | 250 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.nasm | 229 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/Microcode.c | 213 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/Microcode.h | 58 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/PeiMpServices.c | 131 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/PeiMpServices.h | 23 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/X64/MpEqu.inc | 41 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/X64/MpFuncs.asm | 290 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/X64/MpFuncs.nasm | 281 |
13 files changed, 0 insertions, 2669 deletions
diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.c b/UefiCpuPkg/CpuMpPei/CpuMpPei.c index b5f8887007..a36adf6345 100644 --- a/UefiCpuPkg/CpuMpPei/CpuMpPei.c +++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.c @@ -13,843 +13,6 @@ **/
#include "CpuMpPei.h"
-
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = {
- (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiEndOfPeiSignalPpiGuid,
- CpuMpEndOfPeiCallback
-};
-
-/**
- Sort the APIC ID of all processors.
-
- This function sorts the APIC ID of all processors so that processor number is
- assigned in the ascending order of APIC ID which eases MP debugging.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
-**/
-STATIC
-VOID
-SortApicId (
- IN PEI_CPU_MP_DATA *PeiCpuMpData
- )
-{
- UINTN Index1;
- UINTN Index2;
- UINTN Index3;
- UINT32 ApicId;
- PEI_CPU_DATA CpuData;
- UINT32 ApCount;
-
- ApCount = PeiCpuMpData->CpuCount - 1;
-
- if (ApCount != 0) {
- for (Index1 = 0; Index1 < ApCount; Index1++) {
- Index3 = Index1;
- //
- // Sort key is the hardware default APIC ID
- //
- ApicId = PeiCpuMpData->CpuData[Index1].ApicId;
- for (Index2 = Index1 + 1; Index2 <= ApCount; Index2++) {
- if (ApicId > PeiCpuMpData->CpuData[Index2].ApicId) {
- Index3 = Index2;
- ApicId = PeiCpuMpData->CpuData[Index2].ApicId;
- }
- }
- if (Index3 != Index1) {
- CopyMem (&CpuData, &PeiCpuMpData->CpuData[Index3], sizeof (PEI_CPU_DATA));
- CopyMem (
- &PeiCpuMpData->CpuData[Index3],
- &PeiCpuMpData->CpuData[Index1],
- sizeof (PEI_CPU_DATA)
- );
- CopyMem (&PeiCpuMpData->CpuData[Index1], &CpuData, sizeof (PEI_CPU_DATA));
- }
- }
-
- //
- // Get the processor number for the BSP
- //
- ApicId = GetInitialApicId ();
- for (Index1 = 0; Index1 < PeiCpuMpData->CpuCount; Index1++) {
- if (PeiCpuMpData->CpuData[Index1].ApicId == ApicId) {
- PeiCpuMpData->BspNumber = (UINT32) Index1;
- break;
- }
- }
- }
-}
-
-/**
- Enable x2APIC mode on APs.
-
- @param Buffer Pointer to private data buffer.
-**/
-STATIC
-VOID
-EFIAPI
-ApFuncEnableX2Apic (
- IN OUT VOID *Buffer
- )
-{
- SetApicMode (LOCAL_APIC_MODE_X2APIC);
-}
-
-/**
- Get AP loop mode.
-
- @param MonitorFilterSize Returns the largest monitor-line size in bytes.
-
- @return The AP loop mode.
-**/
-STATIC
-UINT8
-GetApLoopMode (
- OUT UINT16 *MonitorFilterSize
- )
-{
- UINT8 ApLoopMode;
- UINT32 RegEbx;
- UINT32 RegEcx;
- UINT32 RegEdx;
-
- ASSERT (MonitorFilterSize != NULL);
-
- ApLoopMode = PcdGet8 (PcdCpuApLoopMode);
- ASSERT (ApLoopMode >= ApInHltLoop && ApLoopMode <= ApInRunLoop);
- if (ApLoopMode == ApInMwaitLoop) {
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &RegEcx, NULL);
- if ((RegEcx & BIT3) == 0) {
- //
- // If processor does not support MONITOR/MWAIT feature
- // by CPUID.[EAX=01H]:ECX.BIT3, force AP in Hlt-loop mode
- //
- ApLoopMode = ApInHltLoop;
- }
- }
-
- if (ApLoopMode == ApInHltLoop) {
- *MonitorFilterSize = 0;
- } else if (ApLoopMode == ApInRunLoop) {
- *MonitorFilterSize = sizeof (UINT32);
- } else if (ApLoopMode == ApInMwaitLoop) {
- //
- // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes
- // CPUID.[EAX=05H].EDX: C-states supported using MWAIT
- //
- AsmCpuid (CPUID_MONITOR_MWAIT, NULL, &RegEbx, NULL, &RegEdx);
- *MonitorFilterSize = RegEbx & 0xFFFF;
- }
-
- return ApLoopMode;
-}
-
-/**
- Get CPU MP Data pointer from the Guided HOB.
-
- @return Pointer to Pointer to PEI CPU MP Data
-**/
-PEI_CPU_MP_DATA *
-GetMpHobData (
- VOID
- )
-{
- EFI_HOB_GUID_TYPE *GuidHob;
- VOID *DataInHob;
- PEI_CPU_MP_DATA *CpuMpData;
-
- CpuMpData = NULL;
- GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
- if (GuidHob != NULL) {
- DataInHob = GET_GUID_HOB_DATA (GuidHob);
- CpuMpData = (PEI_CPU_MP_DATA *)(*(UINTN *)DataInHob);
- }
- ASSERT (CpuMpData != NULL);
- return CpuMpData;
-}
-
-/**
- Save the volatile registers required to be restored following INIT IPI.
-
- @param VolatileRegisters Returns buffer saved the volatile resisters
-**/
-STATIC
-VOID
-SaveVolatileRegisters (
- OUT CPU_VOLATILE_REGISTERS *VolatileRegisters
- )
-{
- UINT32 RegEdx;
-
- VolatileRegisters->Cr0 = AsmReadCr0 ();
- VolatileRegisters->Cr3 = AsmReadCr3 ();
- VolatileRegisters->Cr4 = AsmReadCr4 ();
-
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & BIT2) != 0) {
- //
- // If processor supports Debugging Extensions feature
- // by CPUID.[EAX=01H]:EDX.BIT2
- //
- VolatileRegisters->Dr0 = AsmReadDr0 ();
- VolatileRegisters->Dr1 = AsmReadDr1 ();
- VolatileRegisters->Dr2 = AsmReadDr2 ();
- VolatileRegisters->Dr3 = AsmReadDr3 ();
- VolatileRegisters->Dr6 = AsmReadDr6 ();
- VolatileRegisters->Dr7 = AsmReadDr7 ();
- }
-}
-
-/**
- Restore the volatile registers following INIT IPI.
-
- @param VolatileRegisters Pointer to volatile resisters
- @param IsRestoreDr TRUE: Restore DRx if supported
- FALSE: Do not restore DRx
-**/
-STATIC
-VOID
-RestoreVolatileRegisters (
- IN CPU_VOLATILE_REGISTERS *VolatileRegisters,
- IN BOOLEAN IsRestoreDr
- )
-{
- UINT32 RegEdx;
-
- AsmWriteCr0 (VolatileRegisters->Cr0);
- AsmWriteCr3 (VolatileRegisters->Cr3);
- AsmWriteCr4 (VolatileRegisters->Cr4);
-
- if (IsRestoreDr) {
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & BIT2) != 0) {
- //
- // If processor supports Debugging Extensions feature
- // by CPUID.[EAX=01H]:EDX.BIT2
- //
- AsmWriteDr0 (VolatileRegisters->Dr0);
- AsmWriteDr1 (VolatileRegisters->Dr1);
- AsmWriteDr2 (VolatileRegisters->Dr2);
- AsmWriteDr3 (VolatileRegisters->Dr3);
- AsmWriteDr6 (VolatileRegisters->Dr6);
- AsmWriteDr7 (VolatileRegisters->Dr7);
- }
- }
-}
-
-/**
- Find the current Processor number by APIC ID.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
- @param ProcessorNumber Return the pocessor number found
-
- @retval EFI_SUCCESS ProcessorNumber is found and returned.
- @retval EFI_NOT_FOUND ProcessorNumber is not found.
-**/
-STATIC
-EFI_STATUS
-GetProcessorNumber (
- IN PEI_CPU_MP_DATA *PeiCpuMpData,
- OUT UINTN *ProcessorNumber
- )
-{
- UINTN TotalProcessorNumber;
- UINTN Index;
-
- TotalProcessorNumber = PeiCpuMpData->CpuCount;
- for (Index = 0; Index < TotalProcessorNumber; Index ++) {
- if (PeiCpuMpData->CpuData[Index].ApicId == GetInitialApicId ()) {
- *ProcessorNumber = Index;
- return EFI_SUCCESS;
- }
- }
- return EFI_NOT_FOUND;
-}
-
-/**
- This function will be called from AP reset code if BSP uses WakeUpAP.
-
- @param ExchangeInfo Pointer to the MP exchange info buffer
- @param NumApsExecuting Number of current executing AP
-**/
-STATIC
-VOID
-EFIAPI
-ApCFunction (
- IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,
- IN UINTN NumApsExecuting
- )
-{
- PEI_CPU_MP_DATA *PeiCpuMpData;
- UINTN ProcessorNumber;
- EFI_AP_PROCEDURE Procedure;
- UINTN BistData;
- volatile UINT32 *ApStartupSignalBuffer;
-
- PeiCpuMpData = ExchangeInfo->PeiCpuMpData;
- while (TRUE) {
- if (PeiCpuMpData->InitFlag) {
- ProcessorNumber = NumApsExecuting;
- //
- // Sync BSP's Control registers to APs
- //
- RestoreVolatileRegisters (&PeiCpuMpData->CpuData[0].VolatileRegisters, FALSE);
- //
- // This is first time AP wakeup, get BIST information from AP stack
- //
- BistData = *(UINTN *) (PeiCpuMpData->Buffer + ProcessorNumber * PeiCpuMpData->CpuApStackSize - sizeof (UINTN));
- PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32 = (UINT32) BistData;
- PeiCpuMpData->CpuData[ProcessorNumber].ApicId = GetInitialApicId ();
- if (PeiCpuMpData->CpuData[ProcessorNumber].ApicId >= 0xFF) {
- //
- // Set x2APIC mode if there are any logical processor reporting
- // an APIC ID of 255 or greater.
- //
- AcquireSpinLock(&PeiCpuMpData->MpLock);
- PeiCpuMpData->X2ApicEnable = TRUE;
- ReleaseSpinLock(&PeiCpuMpData->MpLock);
- }
- //
- // Sync BSP's Mtrr table to all wakeup APs and load microcode on APs.
- //
- MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);
- MicrocodeDetect (PeiCpuMpData);
- PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
- } else {
- //
- // Execute AP function if AP is not disabled
- //
- GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);
- if (PeiCpuMpData->ApLoopMode == ApInHltLoop) {
- //
- // Restore AP's volatile registers saved
- //
- RestoreVolatileRegisters (&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);
- }
-
- if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&
- (PeiCpuMpData->ApFunction != 0)) {
- PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;
- Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;
- //
- // Invoke AP function here
- //
- Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);
- //
- // Re-get the processor number due to BSP/AP maybe exchange in AP function
- //
- GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);
- PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
- }
- }
-
- //
- // AP finished executing C code
- //
- InterlockedIncrement ((UINT32 *)&PeiCpuMpData->FinishedCount);
-
- //
- // Place AP is specified loop mode
- //
- if (PeiCpuMpData->ApLoopMode == ApInHltLoop) {
- //
- // Save AP volatile registers
- //
- SaveVolatileRegisters (&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
- //
- // Place AP in Hlt-loop
- //
- while (TRUE) {
- DisableInterrupts ();
- CpuSleep ();
- CpuPause ();
- }
- }
- ApStartupSignalBuffer = PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal;
- while (TRUE) {
- DisableInterrupts ();
- if (PeiCpuMpData->ApLoopMode == ApInMwaitLoop) {
- //
- // Place AP in Mwait-loop
- //
- AsmMonitor ((UINTN)ApStartupSignalBuffer, 0, 0);
- if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) {
- //
- // If AP start-up signal is not set, place AP into
- // the maximum C-state
- //
- AsmMwait (PeiCpuMpData->ApTargetCState << 4, 0);
- }
- } else if (PeiCpuMpData->ApLoopMode == ApInRunLoop) {
- //
- // Place AP in Run-loop
- //
- CpuPause ();
- } else {
- ASSERT (FALSE);
- }
-
- //
- // If AP start-up signal is written, AP is waken up
- // otherwise place AP in loop again
- //
- if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) {
- //
- // Clear AP start-up signal when AP waken up
- //
- InterlockedCompareExchange32 (
- (UINT32 *)ApStartupSignalBuffer,
- WAKEUP_AP_SIGNAL,
- 0
- );
- break;
- }
- }
- }
-}
-
-/**
- Write AP start-up signal to wakeup AP.
-
- @param ApStartupSignalBuffer Pointer to AP wakeup signal
-**/
-VOID
-WriteStartupSignal (
- IN volatile UINT32 *ApStartupSignalBuffer
- )
-{
- *ApStartupSignalBuffer = WAKEUP_AP_SIGNAL;
- //
- // If AP is waken up, StartupApSignal should be cleared.
- // Otherwise, write StartupApSignal again till AP waken up.
- //
- while (InterlockedCompareExchange32 (
- (UINT32 *)ApStartupSignalBuffer,
- WAKEUP_AP_SIGNAL,
- WAKEUP_AP_SIGNAL
- ) != 0) {
- CpuPause ();
- }
-}
-
-/**
- This function will be called by BSP to wakeup AP.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
- @param Broadcast TRUE: Send broadcast IPI to all APs
- FALSE: Send IPI to AP by ApicId
- @param ProcessorNumber The handle number of specified processor
- @param Procedure The function to be invoked by AP
- @param ProcedureArgument The argument to be passed into AP function
-**/
-STATIC
-VOID
-WakeUpAP (
- IN PEI_CPU_MP_DATA *PeiCpuMpData,
- IN BOOLEAN Broadcast,
- IN UINTN ProcessorNumber,
- IN EFI_AP_PROCEDURE Procedure, OPTIONAL
- IN VOID *ProcedureArgument OPTIONAL
- )
-{
- volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;
- UINTN Index;
-
- PeiCpuMpData->ApFunction = (UINTN) Procedure;
- PeiCpuMpData->ApFunctionArgument = (UINTN) ProcedureArgument;
- PeiCpuMpData->FinishedCount = 0;
-
- ExchangeInfo = PeiCpuMpData->MpCpuExchangeInfo;
- ExchangeInfo->Lock = 0;
- ExchangeInfo->StackStart = PeiCpuMpData->Buffer;
- ExchangeInfo->StackSize = PeiCpuMpData->CpuApStackSize;
- ExchangeInfo->BufferStart = PeiCpuMpData->WakeupBuffer;
- ExchangeInfo->ModeOffset = PeiCpuMpData->AddressMap.ModeEntryOffset;
- ExchangeInfo->Cr3 = AsmReadCr3 ();
- ExchangeInfo->CodeSegment = AsmReadCs ();
- ExchangeInfo->DataSegment = AsmReadDs ();
- ExchangeInfo->CFunction = (UINTN) ApCFunction;
- ExchangeInfo->NumApsExecuting = 0;
- ExchangeInfo->PeiCpuMpData = PeiCpuMpData;
-
- //
- // Get the BSP's data of GDT and IDT
- //
- AsmReadGdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->GdtrProfile);
- AsmReadIdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->IdtrProfile);
-
- if (PeiCpuMpData->ApLoopMode == ApInMwaitLoop) {
- //
- // Get AP target C-state each time when waking up AP,
- // for it maybe updated by platform again
- //
- PeiCpuMpData->ApTargetCState = PcdGet8 (PcdCpuApTargetCstate);
- }
-
- //
- // Wakeup APs per AP loop state
- //
- if (PeiCpuMpData->ApLoopMode == ApInHltLoop || PeiCpuMpData->InitFlag) {
- if (Broadcast) {
- SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart);
- } else {
- SendInitSipiSipi (
- PeiCpuMpData->CpuData[ProcessorNumber].ApicId,
- (UINT32) ExchangeInfo->BufferStart
- );
- }
- } else if ((PeiCpuMpData->ApLoopMode == ApInMwaitLoop) ||
- (PeiCpuMpData->ApLoopMode == ApInRunLoop)) {
- if (Broadcast) {
- for (Index = 0; Index < PeiCpuMpData->CpuCount; Index++) {
- if (Index != PeiCpuMpData->BspNumber) {
- WriteStartupSignal (PeiCpuMpData->CpuData[Index].StartupApSignal);
- }
- }
- } else {
- WriteStartupSignal (PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal);
- }
- } else {
- ASSERT (FALSE);
- }
- return ;
-}
-
-/**
- Get available system memory below 1MB by specified size.
-
- @param WakeupBufferSize Wakeup buffer size required
-
- @retval other Return wakeup buffer address below 1MB.
- @retval -1 Cannot find free memory below 1MB.
-**/
-STATIC
-UINTN
-GetWakeupBuffer (
- IN UINTN WakeupBufferSize
- )
-{
- EFI_PEI_HOB_POINTERS Hob;
- UINTN WakeupBufferStart;
- UINTN WakeupBufferEnd;
-
- //
- // Get the HOB list for processing
- //
- Hob.Raw = GetHobList ();
-
- //
- // Collect memory ranges
- //
- while (!END_OF_HOB_LIST (Hob)) {
- if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
- if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&
- (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
- ((Hob.ResourceDescriptor->ResourceAttribute &
- (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |
- EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |
- EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
- )) == 0)
- ) {
- //
- // Need memory under 1MB to be collected here
- //
- WakeupBufferEnd = (UINTN) (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength);
- if (WakeupBufferEnd > BASE_1MB) {
- //
- // Wakeup buffer should be under 1MB
- //
- WakeupBufferEnd = BASE_1MB;
- }
- //
- // Wakeup buffer should be aligned on 4KB
- //
- WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);
- if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {
- continue;
- }
- //
- // Create a memory allocation HOB.
- //
- BuildMemoryAllocationHob (
- WakeupBufferStart,
- WakeupBufferSize,
- EfiBootServicesData
- );
- return WakeupBufferStart;
- }
- }
- //
- // Find the next HOB
- //
- Hob.Raw = GET_NEXT_HOB (Hob);
- }
-
- return (UINTN) -1;
-}
-
-/**
- Get available system memory below 1MB by specified size.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
-**/
-STATIC
-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
- );
-}
-
-/**
- Restore wakeup buffer data.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
-**/
-STATIC
-VOID
-RestoreWakeupBuffer(
- IN PEI_CPU_MP_DATA *PeiCpuMpData
- )
-{
- CopyMem ((VOID *) PeiCpuMpData->WakeupBuffer, (VOID *) PeiCpuMpData->BackupBuffer, PeiCpuMpData->BackupBufferSize);
-}
-
-/**
- This function will get CPU count in the system.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
-
- @return AP processor count
-**/
-UINT32
-CountProcessorNumber (
- IN PEI_CPU_MP_DATA *PeiCpuMpData
- )
-{
- //
- // Load Microcode on BSP
- //
- MicrocodeDetect (PeiCpuMpData);
- //
- // Store BSP's MTRR setting
- //
- MtrrGetAllMtrrs (&PeiCpuMpData->MtrrTable);
-
- //
- // Only perform AP detection if PcdCpuMaxLogicalProcessorNumber is greater than 1
- //
- if (PcdGet32 (PcdCpuMaxLogicalProcessorNumber) > 1) {
- //
- // Send 1st broadcast IPI to APs to wakeup APs
- //
- PeiCpuMpData->InitFlag = TRUE;
- PeiCpuMpData->X2ApicEnable = FALSE;
- WakeUpAP (PeiCpuMpData, TRUE, 0, NULL, NULL);
- //
- // Wait for AP task to complete and then exit.
- //
- MicroSecondDelay (PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));
- PeiCpuMpData->InitFlag = FALSE;
- PeiCpuMpData->CpuCount += (UINT32)PeiCpuMpData->MpCpuExchangeInfo->NumApsExecuting;
- ASSERT (PeiCpuMpData->CpuCount <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
- //
- // Wait for all APs finished the initialization
- //
- while (PeiCpuMpData->FinishedCount < (PeiCpuMpData->CpuCount - 1)) {
- CpuPause ();
- }
-
- if (PeiCpuMpData->X2ApicEnable) {
- DEBUG ((EFI_D_INFO, "Force x2APIC mode!\n"));
- //
- // Wakeup all APs to enable x2APIC mode
- //
- WakeUpAP (PeiCpuMpData, TRUE, 0, ApFuncEnableX2Apic, NULL);
- //
- // Wait for all known APs finished
- //
- while (PeiCpuMpData->FinishedCount < (PeiCpuMpData->CpuCount - 1)) {
- CpuPause ();
- }
- //
- // Enable x2APIC on BSP
- //
- SetApicMode (LOCAL_APIC_MODE_X2APIC);
- }
- DEBUG ((EFI_D_INFO, "APIC MODE is %d\n", GetApicMode ()));
- //
- // Sort BSP/Aps by CPU APIC ID in ascending order
- //
- SortApicId (PeiCpuMpData);
- }
-
- DEBUG ((EFI_D_INFO, "CpuMpPei: Find %d processors in system.\n", PeiCpuMpData->CpuCount));
- return PeiCpuMpData->CpuCount;
-}
-
-/**
- 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;
- UINT8 ApLoopMode;
- UINT16 MonitorFilterSize;
- UINT8 *MonitorBuffer;
- UINTN Index;
-
- AsmGetAddressMap (&AddressMap);
- WakeupBufferSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO);
- WakeupBuffer = GetWakeupBuffer ((WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1));
- ASSERT (WakeupBuffer != (UINTN) -1);
- DEBUG ((EFI_D_INFO, "CpuMpPei: WakeupBuffer = 0x%x\n", WakeupBuffer));
-
- //
- // Allocate Pages for APs stack, CPU MP Data, backup buffer for wakeup buffer,
- // and monitor buffer if required.
- //
- MaxCpuCount = PcdGet32(PcdCpuMaxLogicalProcessorNumber);
- BufferSize = PcdGet32 (PcdCpuApStackSize) * MaxCpuCount + sizeof (PEI_CPU_MP_DATA)
- + WakeupBufferSize + sizeof (PEI_CPU_DATA) * MaxCpuCount;
- ApLoopMode = GetApLoopMode (&MonitorFilterSize);
- BufferSize += MonitorFilterSize * 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->BackupBuffer +
- PeiCpuMpData->BackupBufferSize);
- PeiCpuMpData->CpuData[0].ApicId = GetInitialApicId ();
- PeiCpuMpData->CpuData[0].Health.Uint32 = 0;
- PeiCpuMpData->EndOfPeiFlag = FALSE;
- InitializeSpinLock(&PeiCpuMpData->MpLock);
- SaveVolatileRegisters (&PeiCpuMpData->CpuData[0].VolatileRegisters);
- CopyMem (&PeiCpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP));
- //
- // Initialize AP loop mode
- //
- PeiCpuMpData->ApLoopMode = ApLoopMode;
- DEBUG ((EFI_D_INFO, "AP Loop Mode is %d\n", PeiCpuMpData->ApLoopMode));
- MonitorBuffer = (UINT8 *)(PeiCpuMpData->CpuData + MaxCpuCount);
- if (PeiCpuMpData->ApLoopMode != ApInHltLoop) {
- //
- // Set up APs wakeup signal buffer
- //
- for (Index = 0; Index < MaxCpuCount; Index++) {
- PeiCpuMpData->CpuData[Index].StartupApSignal =
- (UINT32 *)(MonitorBuffer + MonitorFilterSize * Index);
- }
- }
- //
- // Backup original data and copy AP reset code in it
- //
- BackupAndPrepareWakeupBuffer(PeiCpuMpData);
-
- return PeiCpuMpData;
-}
-
-/**
- Notify function on End Of Pei PPI.
-
- On S3 boot, this function will restore wakeup buffer data.
- On normal boot, this function will flag wakeup buffer to be un-used type.
-
- @param PeiServices The pointer to the PEI Services Table.
- @param NotifyDescriptor Address of the notification descriptor data structure.
- @param Ppi Address of the PPI that was installed.
-
- @retval EFI_SUCCESS When everything is OK.
-
-**/
-STATIC
-EFI_STATUS
-EFIAPI
-CpuMpEndOfPeiCallback (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
- IN VOID *Ppi
- )
-{
- EFI_STATUS Status;
- EFI_BOOT_MODE BootMode;
- PEI_CPU_MP_DATA *PeiCpuMpData;
- EFI_PEI_HOB_POINTERS Hob;
- EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
-
- DEBUG ((EFI_D_INFO, "CpuMpPei: CpuMpEndOfPeiCallback () invoked\n"));
-
- Status = PeiServicesGetBootMode (&BootMode);
- ASSERT_EFI_ERROR (Status);
-
- PeiCpuMpData = GetMpHobData ();
- ASSERT (PeiCpuMpData != NULL);
-
- if (BootMode != BOOT_ON_S3_RESUME) {
- //
- // Get the HOB list for processing
- //
- Hob.Raw = GetHobList ();
- //
- // Collect memory ranges
- //
- while (!END_OF_HOB_LIST (Hob)) {
- if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
- MemoryHob = Hob.MemoryAllocation;
- if(MemoryHob->AllocDescriptor.MemoryBaseAddress == PeiCpuMpData->WakeupBuffer) {
- //
- // Flag this HOB type to un-used
- //
- GET_HOB_TYPE (Hob) = EFI_HOB_TYPE_UNUSED;
- break;
- }
- }
- Hob.Raw = GET_NEXT_HOB (Hob);
- }
- } else {
- RestoreWakeupBuffer (PeiCpuMpData);
- PeiCpuMpData->EndOfPeiFlag = TRUE;
- }
- return EFI_SUCCESS;
-}
-
/**
The Entry point of the MP CPU PEIM.
diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.h b/UefiCpuPkg/CpuMpPei/CpuMpPei.h index fb57669de5..5a422b2315 100644 --- a/UefiCpuPkg/CpuMpPei/CpuMpPei.h +++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.h @@ -21,259 +21,21 @@ #include <Ppi/SecPlatformInformation.h>
#include <Ppi/SecPlatformInformation2.h>
#include <Ppi/EndOfPeiPhase.h>
-#include <Ppi/VectorHandoffInfo.h>
-
-#include <Register/Cpuid.h>
-#include <Register/LocalApic.h>
-#include <Register/Msr.h>
#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/LocalApicLib.h>
-#include <Library/MtrrLib.h>
-#include <Library/PcdLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/PeiServicesLib.h>
#include <Library/ReportStatusCodeLib.h>
-#include <Library/SynchronizationLib.h>
-#include <Library/TimerLib.h>
-#include <Library/UefiCpuLib.h>
-#include <Library/CpuLib.h>
#include <Library/CpuExceptionHandlerLib.h>
#include <Library/MpInitLib.h>
-#include "Microcode.h"
-
-//
-// AP state
-//
-typedef enum {
- CpuStateIdle,
- CpuStateBusy,
- CpuStateDisabled
-} CPU_STATE;
-
-#define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')
-
-typedef enum {
- ApInHltLoop = 1,
- ApInMwaitLoop = 2,
- ApInRunLoop = 3
-} AP_LOOP_MODE;
-
-//
-// AP reset code information
-//
-typedef struct {
- UINT8 *RendezvousFunnelAddress;
- UINTN ModeEntryOffset;
- UINTN RendezvousFunnelSize;
-} MP_ASSEMBLY_ADDRESS_MAP;
-
-//
-// CPU exchange information for switch BSP
-//
-typedef struct {
- UINT8 State; // offset 0
- UINTN StackPointer; // offset 4 / 8
- IA32_DESCRIPTOR Gdtr; // offset 8 / 16
- IA32_DESCRIPTOR Idtr; // offset 14 / 26
-} CPU_EXCHANGE_ROLE_INFO;
-
-typedef struct _PEI_CPU_MP_DATA PEI_CPU_MP_DATA;
-
-#pragma pack(1)
-
-//
-// MP CPU exchange information for AP reset code
-// This structure is required to be packed because fixed field offsets
-// into this structure are used in assembly code in this module
-//
-typedef struct {
- UINTN Lock;
- UINTN StackStart;
- UINTN StackSize;
- UINTN CFunction;
- IA32_DESCRIPTOR GdtrProfile;
- IA32_DESCRIPTOR IdtrProfile;
- UINTN BufferStart;
- UINTN ModeOffset;
- UINTN NumApsExecuting;
- UINTN CodeSegment;
- UINTN DataSegment;
- UINTN Cr3;
- PEI_CPU_MP_DATA *PeiCpuMpData;
-} MP_CPU_EXCHANGE_INFO;
-
-#pragma pack()
-
-typedef struct {
- UINTN Cr0;
- UINTN Cr3;
- UINTN Cr4;
- UINTN Dr0;
- UINTN Dr1;
- UINTN Dr2;
- UINTN Dr3;
- UINTN Dr6;
- UINTN Dr7;
-} CPU_VOLATILE_REGISTERS;
-
-typedef struct {
- volatile UINT32 *StartupApSignal;
- UINT32 ApicId;
- EFI_HEALTH_FLAGS Health;
- CPU_STATE State;
- BOOLEAN CpuHealthy;
- CPU_VOLATILE_REGISTERS VolatileRegisters;
-} PEI_CPU_DATA;
-
-//
-// PEI CPU MP Data save in memory
-//
-struct _PEI_CPU_MP_DATA {
- SPIN_LOCK MpLock;
- UINT32 CpuCount;
- UINT32 BspNumber;
- UINTN Buffer;
- UINTN CpuApStackSize;
- MP_ASSEMBLY_ADDRESS_MAP AddressMap;
- UINTN WakeupBuffer;
- UINTN BackupBuffer;
- UINTN BackupBufferSize;
- UINTN ApFunction;
- UINTN ApFunctionArgument;
- volatile UINT32 FinishedCount;
- BOOLEAN EndOfPeiFlag;
- BOOLEAN InitFlag;
- BOOLEAN X2ApicEnable;
- CPU_EXCHANGE_ROLE_INFO BSPInfo;
- CPU_EXCHANGE_ROLE_INFO APInfo;
- MTRR_SETTINGS MtrrTable;
- UINT8 ApLoopMode;
- UINT8 ApTargetCState;
- PEI_CPU_DATA *CpuData;
- volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo;
-};
extern EFI_PEI_PPI_DESCRIPTOR mPeiCpuMpPpiDesc;
/**
- 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.
-
- @param AddressMap Output buffer for address map information.
-**/
-VOID
-EFIAPI
-AsmGetAddressMap (
- OUT MP_ASSEMBLY_ADDRESS_MAP *AddressMap
- );
-
-/**
- Assembly code to load GDT table and update segment accordingly.
-
- @param Gdtr Pointer to GDT descriptor
-**/
-VOID
-EFIAPI
-AsmInitializeGdt (
- IN IA32_DESCRIPTOR *Gdtr
- );
-
-/**
- Get available system memory below 1MB by specified size.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
-**/
-STATIC
-VOID
-BackupAndPrepareWakeupBuffer(
- IN PEI_CPU_MP_DATA *PeiCpuMpData
- );
-
-/**
- Restore wakeup buffer data.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
-**/
-STATIC
-VOID
-RestoreWakeupBuffer(
- IN PEI_CPU_MP_DATA *PeiCpuMpData
- );
-
-/**
- Notify function on End Of Pei PPI.
-
- On S3 boot, this function will restore wakeup buffer data.
- On normal boot, this function will flag wakeup buffer to be un-used type.
-
- @param PeiServices The pointer to the PEI Services Table.
- @param NotifyDescriptor Address of the notification descriptor data structure.
- @param Ppi Address of the PPI that was installed.
-
- @retval EFI_SUCCESS When everything is OK.
-
-**/
-STATIC
-EFI_STATUS
-EFIAPI
-CpuMpEndOfPeiCallback (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
- IN VOID *Ppi
- );
-
-/**
- This function will be called by BSP to wakeup AP.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
- @param Broadcast TRUE: Send broadcast IPI to all APs
- FALSE: Send IPI to AP by ApicId
- @param ProcessorNumber The handle number of specified processor
- @param Procedure The function to be invoked by AP
- @param ProcedureArgument The argument to be passed into AP function
-**/
-STATIC
-VOID
-WakeUpAP (
- IN PEI_CPU_MP_DATA *PeiCpuMpData,
- IN BOOLEAN Broadcast,
- IN UINTN ProcessorNumber,
- IN EFI_AP_PROCEDURE Procedure, OPTIONAL
- IN VOID *ProcedureArgument OPTIONAL
- );
-
-/**
- Get CPU MP Data pointer from the Guided HOB.
-
- @return Pointer to Pointer to PEI CPU MP Data
-**/
-PEI_CPU_MP_DATA *
-GetMpHobData (
- VOID
- );
-
-/**
- Find the current Processor number by APIC ID.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
- @param ProcessorNumber Return the pocessor number found
-
- @retval EFI_SUCCESS ProcessorNumber is found and returned.
- @retval EFI_NOT_FOUND ProcessorNumber is not found.
-**/
-STATIC
-EFI_STATUS
-GetProcessorNumber (
- IN PEI_CPU_MP_DATA *PeiCpuMpData,
- OUT UINTN *ProcessorNumber
- );
-
-/**
Collects BIST data from PPI.
This function collects BIST data from Sec Platform Information2 PPI
@@ -307,14 +69,4 @@ SecPlatformInformation2 ( OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2
);
-/**
- Detect whether specified processor can find matching microcode patch and load it.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
-**/
-VOID
-MicrocodeDetect (
- IN PEI_CPU_MP_DATA *PeiCpuMpData
- );
-
#endif
diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf index 532e8a7f6b..3bf9a8b261 100644 --- a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf +++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf @@ -31,21 +31,9 @@ CpuMpPei.h
CpuMpPei.c
CpuBist.c
- Microcode.h
- Microcode.c
PeiMpServices.h
PeiMpServices.c
-[Sources.IA32]
- Ia32/MpEqu.inc
- Ia32/MpFuncs.asm
- Ia32/MpFuncs.nasm
-
-[Sources.X64]
- X64/MpEqu.inc
- X64/MpFuncs.asm
- X64/MpFuncs.nasm
-
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
@@ -53,40 +41,23 @@ [LibraryClasses]
BaseLib
- BaseMemoryLib
DebugLib
HobLib
LocalApicLib
- MtrrLib
- PcdLib
PeimEntryPoint
PeiServicesLib
ReportStatusCodeLib
- SynchronizationLib
- TimerLib
- UefiCpuLib
- CpuLib
CpuExceptionHandlerLib
MpInitLib
[Ppis]
gEfiPeiMpServicesPpiGuid ## PRODUCES
- gEfiEndOfPeiSignalPpiGuid ## NOTIFY
gEfiSecPlatformInformationPpiGuid ## SOMETIMES_CONSUMES
## SOMETIMES_CONSUMES
## SOMETIMES_PRODUCES
gEfiSecPlatformInformation2PpiGuid
gEfiVectorHandoffInfoPpiGuid ## SOMETIMES_CONSUMES
-[Pcd]
- gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES
-
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid
diff --git a/UefiCpuPkg/CpuMpPei/Ia32/MpEqu.inc b/UefiCpuPkg/CpuMpPei/Ia32/MpEqu.inc deleted file mode 100644 index 773eab3a4d..0000000000 --- a/UefiCpuPkg/CpuMpPei/Ia32/MpEqu.inc +++ /dev/null @@ -1,39 +0,0 @@ -;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
-; This program and the accompanying materials
-; are licensed and made available under the terms and conditions of the BSD License
-; which accompanies this distribution. The full text of the license may be found at
-; http://opensource.org/licenses/bsd-license.php.
-;
-; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-;
-; Module Name:
-;
-; MpEqu.inc
-;
-; Abstract:
-;
-; This is the equates file for Multiple Processor support
-;
-;-------------------------------------------------------------------------------
-
-VacantFlag equ 00h
-NotVacantFlag equ 0ffh
-
-CPU_SWITCH_STATE_IDLE equ 0
-CPU_SWITCH_STATE_STORED equ 1
-CPU_SWITCH_STATE_LOADED equ 2
-
-LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)
-StackStartAddressLocation equ LockLocation + 04h
-StackSizeLocation equ LockLocation + 08h
-ApProcedureLocation equ LockLocation + 0Ch
-GdtrLocation equ LockLocation + 10h
-IdtrLocation equ LockLocation + 16h
-BufferStartLocation equ LockLocation + 1Ch
-ModeOffsetLocation equ LockLocation + 20h
-NumApsExecutingLoction equ LockLocation + 24h
-CodeSegmentLocation equ LockLocation + 28h
-DataSegmentLocation equ LockLocation + 2Ch
-
diff --git a/UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.asm b/UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.asm deleted file mode 100644 index 27e16c66f4..0000000000 --- a/UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.asm +++ /dev/null @@ -1,250 +0,0 @@ -;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
-; This program and the accompanying materials
-; are licensed and made available under the terms and conditions of the BSD License
-; which accompanies this distribution. The full text of the license may be found at
-; http://opensource.org/licenses/bsd-license.php.
-;
-; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-;
-; Module Name:
-;
-; MpFuncs32.asm
-;
-; Abstract:
-;
-; This is the assembly code for MP support
-;
-;-------------------------------------------------------------------------------
-
-.686p
-.model flat
-
-include MpEqu.inc
-InitializeFloatingPointUnits PROTO C
-
-.code
-
-;-------------------------------------------------------------------------------------
-;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
-;procedure serializes all the AP processors through an Init sequence. It must be
-;noted that APs arrive here very raw...ie: real mode, no stack.
-;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
-;IS IN MACHINE CODE.
-;-------------------------------------------------------------------------------------
-RendezvousFunnelProc PROC PUBLIC
-RendezvousFunnelProcStart::
-; At this point CS = 0x(vv00) and ip= 0x0.
-; Save BIST information to ebp firstly
- db 66h, 08bh, 0e8h ; mov ebp, eax ; save BIST information
-
- db 8ch,0c8h ; mov ax, cs
- db 8eh,0d8h ; mov ds, ax
- db 8eh,0c0h ; mov es, ax
- db 8eh,0d0h ; mov ss, ax
- db 33h,0c0h ; xor ax, ax
- db 8eh,0e0h ; mov fs, ax
- db 8eh,0e8h ; mov gs, ax
-
- db 0BEh ; opcode of mov si, mem16
- dw BufferStartLocation ; mov si, BufferStartLocation
- db 66h, 8Bh, 1Ch ; mov ebx, dword ptr [si]
-
- db 0BEh ; opcode of mov si, mem16
- dw ModeOffsetLocation ; mov si, ModeOffsetLocation
- db 66h, 8Bh, 04h ; mov eax, [si]
- db 0BEh ; opcode of mov si, mem16
- dw CodeSegmentLocation ; mov si, CodeSegmentLocation
- db 66h, 8Bh, 14h ; mov edx, [si]
- db 89h, 0C7h ; mov di, ax
- db 83h, 0EFh, 02h ; sub di, 02h
- db 89h, 15h ; mov [di], dx
- db 83h, 0EFh, 04h ; sub di, 04h
- db 66h, 01h, 0D8h ; add eax, ebx
- db 66h, 89h, 05h ; mov [di], eax
-
- db 0BEh ; opcode of mov si, mem16
- dw DataSegmentLocation ; mov si, DataSegmentLocation
- db 66h, 8Bh, 14h ; mov edx, [si]
-
- db 0BEh ; opcode of mov si, mem16
- dw GdtrLocation ; mov si, GdtrLocation
- db 66h ; db 66h
- db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
-
- db 0BEh
- dw IdtrLocation ; mov si, IdtrLocation
- db 66h ; db 66h
- db 2Eh,0Fh, 01h, 1Ch ; lidt fword ptr cs:[si]
-
- db 33h, 0C0h ; xor ax, ax
- db 8Eh, 0D8h ; mov ds, ax
-
- db 0Fh, 20h, 0C0h ; mov eax, cr0 ;Get control register 0
- db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ;Set PE bit (bit #0) & MP
- db 0Fh, 22h, 0C0h ; mov cr0, eax
-
- db 66h, 67h, 0EAh ; far jump
- dd 0h ; 32-bit offset
- dw 0h ; 16-bit selector
-
-Flat32Start:: ; protected mode entry point
- mov ds, dx
- mov es, dx
- mov fs, dx
- mov gs, dx
- mov ss, dx
-
- mov esi, ebx
- mov edi, esi
- add edi, LockLocation
- mov eax, NotVacantFlag
-
-TestLock:
- xchg dword ptr [edi], eax
- cmp eax, NotVacantFlag
- jz TestLock
-
- mov edi, esi
- add edi, NumApsExecutingLoction
- inc dword ptr [edi]
- mov ebx, dword ptr [edi]
-
-ProgramStack:
- mov edi, esi
- add edi, StackSizeLocation
- mov eax, dword ptr [edi]
- mov edi, esi
- add edi, StackStartAddressLocation
- add eax, dword ptr [edi]
- mov esp, eax
- mov dword ptr [edi], eax
-
-Releaselock:
- mov eax, VacantFlag
- mov edi, esi
- add edi, LockLocation
- xchg dword ptr [edi], eax
-
-CProcedureInvoke:
- push ebp ; push BIST data at top of AP stack
- xor ebp, ebp ; clear ebp for call stack trace
- push ebp
- mov ebp, esp
-
- mov eax, InitializeFloatingPointUnits
- call eax ; Call assembly function to initialize FPU per UEFI spec
-
- push ebx ; Push NumApsExecuting
- mov eax, esi
- add eax, LockLocation
- push eax ; push address of exchange info data buffer
-
- mov edi, esi
- add edi, ApProcedureLocation
- mov eax, dword ptr [edi]
-
- call eax ; invoke C function
-
- jmp $ ; never reach here
-
-RendezvousFunnelProc ENDP
-RendezvousFunnelProcEnd::
-
-;-------------------------------------------------------------------------------------
-; AsmGetAddressMap (&AddressMap);
-;-------------------------------------------------------------------------------------
-AsmGetAddressMap PROC near C PUBLIC
- pushad
- mov ebp,esp
-
- mov ebx, dword ptr [ebp+24h]
- mov dword ptr [ebx], RendezvousFunnelProcStart
- mov dword ptr [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
- mov dword ptr [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
-
- popad
- ret
-AsmGetAddressMap ENDP
-
-PAUSE32 MACRO
- DB 0F3h
- DB 090h
- ENDM
-
-;-------------------------------------------------------------------------------------
-;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
-;about to become an AP. It switches it'stack with the current AP.
-;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
-;-------------------------------------------------------------------------------------
-AsmExchangeRole PROC near C PUBLIC
- ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
- ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
- pushad
- mov ebp,esp
-
- ; esi contains MyInfo pointer
- mov esi, dword ptr [ebp+24h]
-
- ; edi contains OthersInfo pointer
- mov edi, dword ptr [ebp+28h]
-
- ;Store EFLAGS, GDTR and IDTR register to stack
- pushfd
- mov eax, cr4
- push eax ; push cr4 firstly
- mov eax, cr0
- push eax
-
- sgdt fword ptr [esi+8]
- sidt fword ptr [esi+14]
-
- ; Store the its StackPointer
- mov dword ptr [esi+4],esp
-
- ; update its switch state to STORED
- mov byte ptr [esi], CPU_SWITCH_STATE_STORED
-
-WaitForOtherStored:
- ; wait until the other CPU finish storing its state
- cmp byte ptr [edi], CPU_SWITCH_STATE_STORED
- jz OtherStored
- PAUSE32
- jmp WaitForOtherStored
-
-OtherStored:
- ; Since another CPU already stored its state, load them
- ; load GDTR value
- lgdt fword ptr [edi+8]
-
- ; load IDTR value
- lidt fword ptr [edi+14]
-
- ; load its future StackPointer
- mov esp, dword ptr [edi+4]
-
- ; update the other CPU's switch state to LOADED
- mov byte ptr [edi], CPU_SWITCH_STATE_LOADED
-
-WaitForOtherLoaded:
- ; wait until the other CPU finish loading new state,
- ; otherwise the data in stack may corrupt
- cmp byte ptr [esi], CPU_SWITCH_STATE_LOADED
- jz OtherLoaded
- PAUSE32
- jmp WaitForOtherLoaded
-
-OtherLoaded:
- ; since the other CPU already get the data it want, leave this procedure
- pop eax
- mov cr0, eax
- pop eax
- mov cr4, eax
- popfd
-
- popad
- ret
-AsmExchangeRole ENDP
-
-END
diff --git a/UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.nasm b/UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.nasm deleted file mode 100644 index 0852a5bc84..0000000000 --- a/UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.nasm +++ /dev/null @@ -1,229 +0,0 @@ -;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
-; This program and the accompanying materials
-; are licensed and made available under the terms and conditions of the BSD License
-; which accompanies this distribution. The full text of the license may be found at
-; http://opensource.org/licenses/bsd-license.php.
-;
-; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-;
-; Module Name:
-;
-; MpFuncs.nasm
-;
-; Abstract:
-;
-; This is the assembly code for MP support
-;
-;-------------------------------------------------------------------------------
-
-%include "MpEqu.inc"
-extern ASM_PFX(InitializeFloatingPointUnits)
-
-SECTION .text
-
-;-------------------------------------------------------------------------------------
-;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
-;procedure serializes all the AP processors through an Init sequence. It must be
-;noted that APs arrive here very raw...ie: real mode, no stack.
-;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
-;IS IN MACHINE CODE.
-;-------------------------------------------------------------------------------------
-global ASM_PFX(RendezvousFunnelProc)
-ASM_PFX(RendezvousFunnelProc):
-RendezvousFunnelProcStart:
-; At this point CS = 0x(vv00) and ip= 0x0.
-BITS 16
- mov ebp, eax ; save BIST information
-
- mov ax, cs
- mov ds, ax
- mov es, ax
- mov ss, ax
- xor ax, ax
- mov fs, ax
- mov gs, ax
-
- mov si, BufferStartLocation
- mov ebx, [si]
-
- mov si, ModeOffsetLocation
- mov eax, [si]
- mov si, CodeSegmentLocation
- mov edx, [si]
- mov di, ax
- sub di, 02h
- mov [di], dx
- sub di, 04h
- add eax, ebx
- mov [di],eax
-
- mov si, DataSegmentLocation
- mov edx, [si]
-
- mov si, GdtrLocation
-o32 lgdt [cs:si]
-
- mov si, IdtrLocation
-o32 lidt [cs:si]
-
- xor ax, ax
- mov ds, ax
-
- mov eax, cr0 ;Get control register 0
- or eax, 000000003h ;Set PE bit (bit #0) & MP
- mov cr0, eax
-
- jmp 0:strict dword 0 ; far jump to protected mode
-BITS 32
-Flat32Start: ; protected mode entry point
- mov ds, dx
- mov es, dx
- mov fs, dx
- mov gs, dx
- mov ss, dx
-
- mov esi, ebx
- mov edi, esi
- add edi, LockLocation
- mov eax, NotVacantFlag
-
-TestLock:
- xchg [edi], eax
- cmp eax, NotVacantFlag
- jz TestLock
-
- mov edi, esi
- add edi, NumApsExecutingLoction
- inc dword [edi]
- mov ebx, [edi]
-
-ProgramStack:
- mov edi, esi
- add edi, StackSizeLocation
- mov eax, [edi]
- mov edi, esi
- add edi, StackStartAddressLocation
- add eax, [edi]
- mov esp, eax
- mov [edi], eax
-
-Releaselock:
- mov eax, VacantFlag
- mov edi, esi
- add edi, LockLocation
- xchg [edi], eax
-
-CProcedureInvoke:
- push ebp ; push BIST data at top of AP stack
- xor ebp, ebp ; clear ebp for call stack trace
- push ebp
- mov ebp, esp
-
- mov eax, ASM_PFX(InitializeFloatingPointUnits)
- call eax ; Call assembly function to initialize FPU per UEFI spec
-
- push ebx ; Push NumApsExecuting
- mov eax, esi
- add eax, LockLocation
- push eax ; push address of exchange info data buffer
-
- mov edi, esi
- add edi, ApProcedureLocation
- mov eax, [edi]
-
- call eax ; invoke C function
-
- jmp $ ; never reach here
-RendezvousFunnelProcEnd:
-
-;-------------------------------------------------------------------------------------
-; AsmGetAddressMap (&AddressMap);
-;-------------------------------------------------------------------------------------
-global ASM_PFX(AsmGetAddressMap)
-ASM_PFX(AsmGetAddressMap):
- pushad
- mov ebp,esp
-
- mov ebx, [ebp + 24h]
- mov dword [ebx], RendezvousFunnelProcStart
- mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
- mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
-
- popad
- ret
-
-;-------------------------------------------------------------------------------------
-;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
-;about to become an AP. It switches it'stack with the current AP.
-;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
-;-------------------------------------------------------------------------------------
-global ASM_PFX(AsmExchangeRole)
-ASM_PFX(AsmExchangeRole):
- ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
- ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
- pushad
- mov ebp,esp
-
- ; esi contains MyInfo pointer
- mov esi, [ebp + 24h]
-
- ; edi contains OthersInfo pointer
- mov edi, [ebp + 28h]
-
- ;Store EFLAGS, GDTR and IDTR register to stack
- pushfd
- mov eax, cr4
- push eax ; push cr4 firstly
- mov eax, cr0
- push eax
-
- sgdt [esi + 8]
- sidt [esi + 14]
-
- ; Store the its StackPointer
- mov [esi + 4],esp
-
- ; update its switch state to STORED
- mov byte [esi], CPU_SWITCH_STATE_STORED
-
-WaitForOtherStored:
- ; wait until the other CPU finish storing its state
- cmp byte [edi], CPU_SWITCH_STATE_STORED
- jz OtherStored
- pause
- jmp WaitForOtherStored
-
-OtherStored:
- ; Since another CPU already stored its state, load them
- ; load GDTR value
- lgdt [edi + 8]
-
- ; load IDTR value
- lidt [edi + 14]
-
- ; load its future StackPointer
- mov esp, [edi + 4]
-
- ; update the other CPU's switch state to LOADED
- mov byte [edi], CPU_SWITCH_STATE_LOADED
-
-WaitForOtherLoaded:
- ; wait until the other CPU finish loading new state,
- ; otherwise the data in stack may corrupt
- cmp byte [esi], CPU_SWITCH_STATE_LOADED
- jz OtherLoaded
- pause
- jmp WaitForOtherLoaded
-
-OtherLoaded:
- ; since the other CPU already get the data it want, leave this procedure
- pop eax
- mov cr0, eax
- pop eax
- mov cr4, eax
- popfd
-
- popad
- ret
diff --git a/UefiCpuPkg/CpuMpPei/Microcode.c b/UefiCpuPkg/CpuMpPei/Microcode.c deleted file mode 100644 index 4fe6f2d8db..0000000000 --- a/UefiCpuPkg/CpuMpPei/Microcode.c +++ /dev/null @@ -1,213 +0,0 @@ -/** @file
- Implementation of loading microcode on processors.
-
- Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "CpuMpPei.h"
-
-/**
- Get microcode update signature of currently loaded microcode update.
-
- @return Microcode signature.
-
-**/
-UINT32
-GetCurrentMicrocodeSignature (
- VOID
- )
-{
- UINT64 Signature;
-
- AsmWriteMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID, 0);
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
- Signature = AsmReadMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID);
- return (UINT32) RShiftU64 (Signature, 32);
-}
-
-/**
- Detect whether specified processor can find matching microcode patch and load it.
-
- @param PeiCpuMpData Pointer to PEI CPU MP Data
-**/
-VOID
-MicrocodeDetect (
- IN PEI_CPU_MP_DATA *PeiCpuMpData
- )
-{
- UINT64 MicrocodePatchAddress;
- UINT64 MicrocodePatchRegionSize;
- UINT32 ExtendedTableLength;
- UINT32 ExtendedTableCount;
- EFI_CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;
- EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;
- EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
- UINTN MicrocodeEnd;
- UINTN Index;
- UINT8 PlatformId;
- UINT32 RegEax;
- UINT32 CurrentRevision;
- UINT32 LatestRevision;
- UINTN TotalSize;
- UINT32 CheckSum32;
- BOOLEAN CorrectMicrocode;
- MICROCODE_INFO MicrocodeInfo;
-
- ZeroMem (&MicrocodeInfo, sizeof (MICROCODE_INFO));
- MicrocodePatchAddress = PcdGet64 (PcdCpuMicrocodePatchAddress);
- MicrocodePatchRegionSize = PcdGet64 (PcdCpuMicrocodePatchRegionSize);
- if (MicrocodePatchRegionSize == 0) {
- //
- // There is no microcode patches
- //
- return;
- }
-
- CurrentRevision = GetCurrentMicrocodeSignature ();
- if (CurrentRevision != 0) {
- //
- // Skip loading microcode if it has been loaded successfully
- //
- return;
- }
-
- ExtendedTableLength = 0;
- //
- // Here data of CPUID leafs have not been collected into context buffer, so
- // GetProcessorCpuid() cannot be used here to retrieve CPUID data.
- //
- AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
-
- //
- // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID
- //
- PlatformId = (UINT8) AsmMsrBitFieldRead64 (EFI_MSR_IA32_PLATFORM_ID, 50, 52);
-
- LatestRevision = 0;
- MicrocodeEnd = (UINTN) (MicrocodePatchAddress + MicrocodePatchRegionSize);
- MicrocodeEntryPoint = (EFI_CPU_MICROCODE_HEADER *) (UINTN) MicrocodePatchAddress;
- do {
- //
- // Check if the microcode is for the Cpu and the version is newer
- // and the update can be processed on the platform
- //
- CorrectMicrocode = FALSE;
- if (MicrocodeEntryPoint->HeaderVersion == 0x1) {
- //
- // It is the microcode header. It is not the padding data between microcode patches
- // because the padding data should not include 0x00000001 and it should be the repeated
- // byte format (like 0xXYXYXYXY....).
- //
- if (MicrocodeEntryPoint->ProcessorId == RegEax &&
- MicrocodeEntryPoint->UpdateRevision > LatestRevision &&
- (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId))
- ) {
- if (MicrocodeEntryPoint->DataSize == 0) {
- CheckSum32 = CalculateSum32 ((UINT32 *)MicrocodeEntryPoint, 2048);
- } else {
- CheckSum32 = CalculateSum32 ((UINT32 *)MicrocodeEntryPoint, MicrocodeEntryPoint->DataSize + sizeof(EFI_CPU_MICROCODE_HEADER));
- }
- if (CheckSum32 == 0) {
- CorrectMicrocode = TRUE;
- }
- } else if ((MicrocodeEntryPoint->DataSize != 0) &&
- (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {
- ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize + sizeof (EFI_CPU_MICROCODE_HEADER));
- if (ExtendedTableLength != 0) {
- //
- // Extended Table exist, check if the CPU in support list
- //
- ExtendedTableHeader = (EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *)((UINT8 *)(MicrocodeEntryPoint) + MicrocodeEntryPoint->DataSize + sizeof (EFI_CPU_MICROCODE_HEADER));
- //
- // Calculate Extended Checksum
- //
- if ((ExtendedTableLength % 4) == 0) {
- CheckSum32 = CalculateSum32 ((UINT32 *)ExtendedTableHeader, ExtendedTableLength);
- if (CheckSum32 == 0) {
- //
- // Checksum correct
- //
- ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
- ExtendedTable = (EFI_CPU_MICROCODE_EXTENDED_TABLE *)(ExtendedTableHeader + 1);
- for (Index = 0; Index < ExtendedTableCount; Index ++) {
- CheckSum32 = CalculateSum32 ((UINT32 *)ExtendedTable, sizeof(EFI_CPU_MICROCODE_EXTENDED_TABLE));
- if (CheckSum32 == 0) {
- //
- // Verify Header
- //
- if ((ExtendedTable->ProcessorSignature == RegEax) &&
- (ExtendedTable->ProcessorFlag & (1 << PlatformId)) ) {
- //
- // Find one
- //
- CorrectMicrocode = TRUE;
- break;
- }
- }
- ExtendedTable ++;
- }
- }
- }
- }
- }
- } else {
- //
- // It is the padding data between the microcode patches for microcode patches alignment.
- // Because the microcode patch is the multiple of 1-KByte, the padding data should not
- // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
- // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
- // find the next possible microcode patch header.
- //
- MicrocodeEntryPoint = (EFI_CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
- continue;
- }
- //
- // Get the next patch.
- //
- if (MicrocodeEntryPoint->DataSize == 0) {
- TotalSize = 2048;
- } else {
- TotalSize = MicrocodeEntryPoint->TotalSize;
- }
-
- if (CorrectMicrocode) {
- LatestRevision = MicrocodeEntryPoint->UpdateRevision;
- MicrocodeInfo.MicrocodeData = (VOID *)((UINTN)MicrocodeEntryPoint + sizeof (EFI_CPU_MICROCODE_HEADER));
- MicrocodeInfo.MicrocodeSize = TotalSize;
- MicrocodeInfo.ProcessorId = RegEax;
- }
-
- MicrocodeEntryPoint = (EFI_CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);
- } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));
-
- if (LatestRevision > CurrentRevision) {
- //
- // BIOS only authenticate updates that contain a numerically larger revision
- // than the currently loaded revision, where Current Signature < New Update
- // Revision. A processor with no loaded update is considered to have a
- // revision equal to zero.
- //
- AsmWriteMsr64 (
- EFI_MSR_IA32_BIOS_UPDT_TRIG,
- (UINT64) (UINTN) MicrocodeInfo.MicrocodeData
- );
- //
- // Get and check new microcode signature
- //
- CurrentRevision = GetCurrentMicrocodeSignature ();
- if (CurrentRevision != LatestRevision) {
- AcquireSpinLock(&PeiCpuMpData->MpLock);
- DEBUG ((EFI_D_ERROR, "Updated microcode signature [0x%08x] does not match \
- loaded microcode signature [0x%08x]\n", CurrentRevision, LatestRevision));
- ReleaseSpinLock(&PeiCpuMpData->MpLock);
- }
- }
-}
diff --git a/UefiCpuPkg/CpuMpPei/Microcode.h b/UefiCpuPkg/CpuMpPei/Microcode.h deleted file mode 100644 index 965604522a..0000000000 --- a/UefiCpuPkg/CpuMpPei/Microcode.h +++ /dev/null @@ -1,58 +0,0 @@ -/** @file
- Definitions for loading microcode on processors.
-
- Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#ifndef _CPU_MICROCODE_H_
-#define _CPU_MICROCODE_H_
-
-#define EFI_MSR_IA32_PLATFORM_ID 0x17
-#define EFI_MSR_IA32_BIOS_UPDT_TRIG 0x79
-#define EFI_MSR_IA32_BIOS_SIGN_ID 0x8b
-
-#define MAX_MICROCODE_DESCRIPTOR_LENGTH 100
-
-typedef struct {
- VOID *MicrocodeData;
- UINTN MicrocodeSize;
- UINT32 ProcessorId;
-} MICROCODE_INFO;
-
-//
-// Definition for IA32 microcode format
-//
-typedef struct {
- UINT32 HeaderVersion;
- UINT32 UpdateRevision;
- UINT32 Date;
- UINT32 ProcessorId;
- UINT32 Checksum;
- UINT32 LoaderRevision;
- UINT32 ProcessorFlags;
- UINT32 DataSize;
- UINT32 TotalSize;
- UINT8 Reserved[12];
-} EFI_CPU_MICROCODE_HEADER;
-
-typedef struct {
- UINT32 ExtendedSignatureCount;
- UINT32 ExtendedTableChecksum;
- UINT8 Reserved[12];
-} EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER;
-
-typedef struct {
- UINT32 ProcessorSignature;
- UINT32 ProcessorFlag;
- UINT32 ProcessorChecksum;
-} EFI_CPU_MICROCODE_EXTENDED_TABLE;
-
-#endif
diff --git a/UefiCpuPkg/CpuMpPei/PeiMpServices.c b/UefiCpuPkg/CpuMpPei/PeiMpServices.c index 44e8f211c7..c9b2ad466b 100644 --- a/UefiCpuPkg/CpuMpPei/PeiMpServices.c +++ b/UefiCpuPkg/CpuMpPei/PeiMpServices.c @@ -35,137 +35,6 @@ EFI_PEI_PPI_DESCRIPTOR mPeiCpuMpPpiDesc = { /**
- Get CPU Package/Core/Thread location information.
-
- @param InitialApicId CPU APIC ID
- @param Location Pointer to CPU location information
-**/
-STATIC
-VOID
-ExtractProcessorLocation (
- IN UINT32 InitialApicId,
- OUT EFI_CPU_PHYSICAL_LOCATION *Location
- )
-{
- BOOLEAN TopologyLeafSupported;
- UINTN ThreadBits;
- UINTN CoreBits;
- UINT32 RegEax;
- UINT32 RegEbx;
- UINT32 RegEcx;
- UINT32 RegEdx;
- UINT32 MaxCpuIdIndex;
- UINT32 SubIndex;
- UINTN LevelType;
- UINT32 MaxLogicProcessorsPerPackage;
- UINT32 MaxCoresPerPackage;
-
- //
- // Check if the processor is capable of supporting more than one logical processor.
- //
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & BIT28) == 0) {
- Location->Thread = 0;
- Location->Core = 0;
- Location->Package = 0;
- return;
- }
-
- ThreadBits = 0;
- CoreBits = 0;
-
- //
- // Assume three-level mapping of APIC ID: Package:Core:SMT.
- //
-
- TopologyLeafSupported = FALSE;
- //
- // Get the max index of basic CPUID
- //
- AsmCpuid (CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL);
-
- //
- // If the extended topology enumeration leaf is available, it
- // is the preferred mechanism for enumerating topology.
- //
- if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) {
- AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, &RegEax, &RegEbx, &RegEcx, NULL);
- //
- // If CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for
- // basic CPUID information is greater than 0BH, then CPUID.0BH leaf is not
- // supported on that processor.
- //
- if (RegEbx != 0) {
- TopologyLeafSupported = TRUE;
-
- //
- // Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract
- // the SMT sub-field of x2APIC ID.
- //
- LevelType = (RegEcx >> 8) & 0xff;
- ASSERT (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT);
- ThreadBits = RegEax & 0x1f;
-
- //
- // Software must not assume any "level type" encoding
- // value to be related to any sub-leaf index, except sub-leaf 0.
- //
- SubIndex = 1;
- do {
- AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, SubIndex, &RegEax, NULL, &RegEcx, NULL);
- LevelType = (RegEcx >> 8) & 0xff;
- if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) {
- CoreBits = (RegEax & 0x1f) - ThreadBits;
- break;
- }
- SubIndex++;
- } while (LevelType != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID);
- }
- }
-
- if (!TopologyLeafSupported) {
- AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
- MaxLogicProcessorsPerPackage = (RegEbx >> 16) & 0xff;
- if (MaxCpuIdIndex >= CPUID_CACHE_PARAMS) {
- AsmCpuidEx (CPUID_CACHE_PARAMS, 0, &RegEax, NULL, NULL, NULL);
- MaxCoresPerPackage = (RegEax >> 26) + 1;
- } else {
- //
- // Must be a single-core processor.
- //
- MaxCoresPerPackage = 1;
- }
-
- ThreadBits = (UINTN) (HighBitSet32 (MaxLogicProcessorsPerPackage / MaxCoresPerPackage - 1) + 1);
- CoreBits = (UINTN) (HighBitSet32 (MaxCoresPerPackage - 1) + 1);
- }
-
- Location->Thread = InitialApicId & ~((-1) << ThreadBits);
- Location->Core = (InitialApicId >> ThreadBits) & ~((-1) << CoreBits);
- Location->Package = (InitialApicId >> (ThreadBits + CoreBits));
-}
-
-/**
- Worker function for SwitchBSP().
-
- Worker function for SwitchBSP(), assigned to the AP which is intended to become BSP.
-
- @param Buffer Pointer to CPU MP Data
-**/
-STATIC
-VOID
-EFIAPI
-FutureBSPProc (
- IN VOID *Buffer
- )
-{
- PEI_CPU_MP_DATA *DataInHob;
-
- DataInHob = (PEI_CPU_MP_DATA *) Buffer;
- AsmExchangeRole (&DataInHob->APInfo, &DataInHob->BSPInfo);
-}
-
-/**
This service retrieves the number of logical processor in the platform
and the number of those logical processors that are enabled on this boot.
This service may only be called from the BSP.
diff --git a/UefiCpuPkg/CpuMpPei/PeiMpServices.h b/UefiCpuPkg/CpuMpPei/PeiMpServices.h index 57f7691161..036d12e57a 100644 --- a/UefiCpuPkg/CpuMpPei/PeiMpServices.h +++ b/UefiCpuPkg/CpuMpPei/PeiMpServices.h @@ -17,29 +17,6 @@ #include "CpuMpPei.h"
-//
-// The MP data for switch BSP
-//
-#define CPU_SWITCH_STATE_IDLE 0
-#define CPU_SWITCH_STATE_STORED 1
-#define CPU_SWITCH_STATE_LOADED 2
-
-#define CPU_CHECK_AP_INTERVAL 0x100 // 100 microseconds
-
-/**
- This function is called by both the BSP and the AP which is to become the BSP to
- Exchange execution context including stack between them. After return from this
- function, the BSP becomes AP and the AP becomes the BSP.
-
- @param MyInfo Pointer to buffer holding the exchanging information for the executing processor.
- @param OthersInfo Pointer to buffer holding the exchanging information for the peer.
-**/
-VOID
-EFIAPI
-AsmExchangeRole (
- IN CPU_EXCHANGE_ROLE_INFO *MyInfo,
- IN CPU_EXCHANGE_ROLE_INFO *OthersInfo
- );
/**
This service retrieves the number of logical processor in the platform
diff --git a/UefiCpuPkg/CpuMpPei/X64/MpEqu.inc b/UefiCpuPkg/CpuMpPei/X64/MpEqu.inc deleted file mode 100644 index 00f57ce549..0000000000 --- a/UefiCpuPkg/CpuMpPei/X64/MpEqu.inc +++ /dev/null @@ -1,41 +0,0 @@ -;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
-; This program and the accompanying materials
-; are licensed and made available under the terms and conditions of the BSD License
-; which accompanies this distribution. The full text of the license may be found at
-; http://opensource.org/licenses/bsd-license.php.
-;
-; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-;
-; Module Name:
-;
-; MpEqu.inc
-;
-; Abstract:
-;
-; This is the equates file for Multiple Processor support
-;
-;-------------------------------------------------------------------------------
-
-VacantFlag equ 00h
-NotVacantFlag equ 0ffh
-
-CPU_SWITCH_STATE_IDLE equ 0
-CPU_SWITCH_STATE_STORED equ 1
-CPU_SWITCH_STATE_LOADED equ 2
-
-LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)
-StackStartAddressLocation equ LockLocation + 08h
-StackSizeLocation equ LockLocation + 10h
-ApProcedureLocation equ LockLocation + 18h
-GdtrLocation equ LockLocation + 20h
-IdtrLocation equ LockLocation + 2Ah
-BufferStartLocation equ LockLocation + 34h
-ModeOffsetLocation equ LockLocation + 3Ch
-NumApsExecutingLoction equ LockLocation + 44h
-CodeSegmentLocation equ LockLocation + 4Ch
-DataSegmentLocation equ LockLocation + 54h
-Cr3Location equ LockLocation + 5Ch
-
-;-------------------------------------------------------------------------------
diff --git a/UefiCpuPkg/CpuMpPei/X64/MpFuncs.asm b/UefiCpuPkg/CpuMpPei/X64/MpFuncs.asm deleted file mode 100644 index 4adfff3c1c..0000000000 --- a/UefiCpuPkg/CpuMpPei/X64/MpFuncs.asm +++ /dev/null @@ -1,290 +0,0 @@ -;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
-; This program and the accompanying materials
-; are licensed and made available under the terms and conditions of the BSD License
-; which accompanies this distribution. The full text of the license may be found at
-; http://opensource.org/licenses/bsd-license.php.
-;
-; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-;
-; Module Name:
-;
-; MpFuncs32.asm
-;
-; Abstract:
-;
-; This is the assembly code for MP support
-;
-;-------------------------------------------------------------------------------
-
-include MpEqu.inc
-extern InitializeFloatingPointUnits:PROC
-
-.code
-;-------------------------------------------------------------------------------------
-;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
-;procedure serializes all the AP processors through an Init sequence. It must be
-;noted that APs arrive here very raw...ie: real mode, no stack.
-;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
-;IS IN MACHINE CODE.
-;-------------------------------------------------------------------------------------
-RendezvousFunnelProc PROC PUBLIC
-RendezvousFunnelProcStart::
-; At this point CS = 0x(vv00) and ip= 0x0.
-; Save BIST information to ebp firstly
- db 66h, 08bh, 0e8h ; mov ebp, eax ; save BIST information
-
- db 8ch,0c8h ; mov ax, cs
- db 8eh,0d8h ; mov ds, ax
- db 8eh,0c0h ; mov es, ax
- db 8eh,0d0h ; mov ss, ax
- db 33h,0c0h ; xor ax, ax
- db 8eh,0e0h ; mov fs, ax
- db 8eh,0e8h ; mov gs, ax
-
- db 0BEh ; opcode of mov si, mem16
- dw BufferStartLocation ; mov si, BufferStartLocation
- db 66h, 8Bh, 1Ch ; mov ebx, dword ptr [si]
-
- db 0BFh ; opcode of mov di, mem16
- dw ModeOffsetLocation ; mov di, ModeOffsetLocation
- db 66h, 8Bh, 05h ; mov eax, [di]
- db 0BFh ; opcode of mov di, mem16
- dw CodeSegmentLocation ; mov di, CodeSegmentLocation
- db 66h, 8Bh, 15h ; mov edx, [di]
- db 89h, 0C7h ; mov di, ax
- db 83h, 0EFh, 02h ; sub di, 02h
- db 89h, 15h ; mov [di], dx ; Patch long mode CS
- db 83h, 0EFh, 04h ; sub di, 04h
- db 66h, 01h, 0D8h ; add eax, ebx
- db 66h, 89h, 05h ; mov [di], eax ; Patch address
-
- db 0BEh ; opcode of mov si, mem16
- dw GdtrLocation ; mov si, GdtrLocation
- db 66h ; db 66h
- db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
-
- db 0BEh
- dw IdtrLocation ; mov si, IdtrLocation
- db 66h ; db 66h
- db 2Eh,0Fh, 01h, 1Ch ; lidt fword ptr cs:[si]
-
- db 0BFh ; opcode of mov di, mem16
- dw DataSegmentLocation ; mov di, DataSegmentLocation
- db 66h, 8Bh, 3Dh ; mov edi, [di] ; Save long mode DS in edi
-
- db 0BEh
- dw Cr3Location ; mov si, Cr3Location
- db 66h, 8Bh, 0Ch ; mov ecx, dword ptr [si] ; ECX is keeping the value of CR3
-
- db 31h, 0C0h ; xor ax, ax
- db 8Eh, 0D8h ; mov ds, ax ; Clear data segment
-
- db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Get control register 0
- db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ; Set PE bit (bit #0) & MP
- db 0Fh, 22h, 0C0h ; mov cr0, eax
-
- db 0Fh, 20h, 0E0h ; mov eax, cr4
- db 66h, 0Fh, 0BAh, 0E8h, 05h ; bts eax, 5
- db 0Fh, 22h, 0E0h ; mov cr4, eax
-
- db 0Fh, 22h, 0D9h ; mov cr3, ecx
-
- db 66h, 0B9h
- dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number.
- db 0Fh, 32h ; rdmsr ; Read EFER.
- db 66h, 0Fh, 0BAh, 0E8h, 08h; bts eax, 8 ; Set LME=1.
- db 0Fh, 30h ; wrmsr ; Write EFER.
-
- db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0.
- db 66h, 0Fh, 0BAh, 0E8h, 1Fh; bts eax, 31 ; Set PG=1.
- db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0.
-
-LONG_JUMP:
- db 66h, 0EAh ; far jump
- dd 0h ; 32-bit offset
- dw 0h ; 16-bit selector
-
-LongModeStart::
- mov eax, edi
- mov ds, ax
- mov es, ax
- mov ss, ax
-
- mov esi, ebx
- mov edi, esi
- add edi, LockLocation
- mov rax, NotVacantFlag
-
-TestLock:
- xchg qword ptr [edi], rax
- cmp rax, NotVacantFlag
- jz TestLock
-
- mov edi, esi
- add edi, NumApsExecutingLoction
- inc dword ptr [edi]
- mov ebx, dword ptr [edi]
-
-ProgramStack:
- mov edi, esi
- add edi, StackSizeLocation
- mov rax, qword ptr [edi]
- mov edi, esi
- add edi, StackStartAddressLocation
- add rax, qword ptr [edi]
- mov rsp, rax
- mov qword ptr [edi], rax
-
-Releaselock:
- mov rax, VacantFlag
- mov edi, esi
- add edi, LockLocation
- xchg qword ptr [edi], rax
-
-CProcedureInvoke:
- push rbp ; push BIST data
- xor rbp, rbp ; clear ebp for call stack trace
- push rbp
- mov rbp, rsp
-
- mov rax, InitializeFloatingPointUnits
- sub rsp, 20h
- call rax ; Call assembly function to initialize FPU per UEFI spec
- add rsp, 20h
-
- mov edx, ebx ; edx is NumApsExecuting
- mov ecx, esi
- add ecx, LockLocation ; rcx is address of exchange info data buffer
-
- mov edi, esi
- add edi, ApProcedureLocation
- mov rax, qword ptr [edi]
-
- sub rsp, 20h
- call rax ; invoke C function
- add rsp, 20h
- jmp $
-
-RendezvousFunnelProc ENDP
-RendezvousFunnelProcEnd::
-
-;-------------------------------------------------------------------------------------
-; AsmGetAddressMap (&AddressMap);
-;-------------------------------------------------------------------------------------
-AsmGetAddressMap PROC
- mov rax, offset RendezvousFunnelProcStart
- mov qword ptr [rcx], rax
- mov qword ptr [rcx + 8h], LongModeStart - RendezvousFunnelProcStart
- mov qword ptr [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
- ret
-AsmGetAddressMap ENDP
-
-;-------------------------------------------------------------------------------------
-;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
-;about to become an AP. It switches it'stack with the current AP.
-;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
-;-------------------------------------------------------------------------------------
-AsmExchangeRole PROC
- ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
- ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
-
- push rax
- push rbx
- push rcx
- push rdx
- push rsi
- push rdi
- push rbp
- push r8
- push r9
- push r10
- push r11
- push r12
- push r13
- push r14
- push r15
-
- mov rax, cr0
- push rax
-
- mov rax, cr4
- push rax
-
- ; rsi contains MyInfo pointer
- mov rsi, rcx
-
- ; rdi contains OthersInfo pointer
- mov rdi, rdx
-
- ;Store EFLAGS, GDTR and IDTR regiter to stack
- pushfq
- sgdt fword ptr [rsi + 16]
- sidt fword ptr [rsi + 26]
-
- ; Store the its StackPointer
- mov qword ptr [rsi + 8], rsp
-
- ; update its switch state to STORED
- mov byte ptr [rsi], CPU_SWITCH_STATE_STORED
-
-WaitForOtherStored:
- ; wait until the other CPU finish storing its state
- cmp byte ptr [rdi], CPU_SWITCH_STATE_STORED
- jz OtherStored
- pause
- jmp WaitForOtherStored
-
-OtherStored:
- ; Since another CPU already stored its state, load them
- ; load GDTR value
- lgdt fword ptr [rdi + 16]
-
- ; load IDTR value
- lidt fword ptr [rdi + 26]
-
- ; load its future StackPointer
- mov rsp, qword ptr [rdi + 8]
-
- ; update the other CPU's switch state to LOADED
- mov byte ptr [rdi], CPU_SWITCH_STATE_LOADED
-
-WaitForOtherLoaded:
- ; wait until the other CPU finish loading new state,
- ; otherwise the data in stack may corrupt
- cmp byte ptr [rsi], CPU_SWITCH_STATE_LOADED
- jz OtherLoaded
- pause
- jmp WaitForOtherLoaded
-
-OtherLoaded:
- ; since the other CPU already get the data it want, leave this procedure
- popfq
-
- pop rax
- mov cr4, rax
-
- pop rax
- mov cr0, rax
-
- pop r15
- pop r14
- pop r13
- pop r12
- pop r11
- pop r10
- pop r9
- pop r8
- pop rbp
- pop rdi
- pop rsi
- pop rdx
- pop rcx
- pop rbx
- pop rax
-
- ret
-AsmExchangeRole ENDP
-
-END
diff --git a/UefiCpuPkg/CpuMpPei/X64/MpFuncs.nasm b/UefiCpuPkg/CpuMpPei/X64/MpFuncs.nasm deleted file mode 100644 index f19c75f913..0000000000 --- a/UefiCpuPkg/CpuMpPei/X64/MpFuncs.nasm +++ /dev/null @@ -1,281 +0,0 @@ -;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
-; This program and the accompanying materials
-; are licensed and made available under the terms and conditions of the BSD License
-; which accompanies this distribution. The full text of the license may be found at
-; http://opensource.org/licenses/bsd-license.php.
-;
-; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-;
-; Module Name:
-;
-; MpFuncs.nasm
-;
-; Abstract:
-;
-; This is the assembly code for MP support
-;
-;-------------------------------------------------------------------------------
-
-%include "MpEqu.inc"
-extern ASM_PFX(InitializeFloatingPointUnits)
-
-DEFAULT REL
-
-SECTION .text
-
-;-------------------------------------------------------------------------------------
-;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
-;procedure serializes all the AP processors through an Init sequence. It must be
-;noted that APs arrive here very raw...ie: real mode, no stack.
-;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
-;IS IN MACHINE CODE.
-;-------------------------------------------------------------------------------------
-global ASM_PFX(RendezvousFunnelProc)
-ASM_PFX(RendezvousFunnelProc):
-RendezvousFunnelProcStart:
-; At this point CS = 0x(vv00) and ip= 0x0.
-; Save BIST information to ebp firstly
-
-BITS 16
- mov ebp, eax ; Save BIST information
-
- mov ax, cs
- mov ds, ax
- mov es, ax
- mov ss, ax
- xor ax, ax
- mov fs, ax
- mov gs, ax
-
- mov si, BufferStartLocation
- mov ebx, [si]
-
- mov di, ModeOffsetLocation
- mov eax, [di]
- mov di, CodeSegmentLocation
- mov edx, [di]
- mov di, ax
- sub di, 02h
- mov [di],dx ; Patch long mode CS
- sub di, 04h
- add eax, ebx
- mov [di],eax ; Patch address
-
- mov si, GdtrLocation
-o32 lgdt [cs:si]
-
- mov si, IdtrLocation
-o32 lidt [cs:si]
-
-
- mov di, DataSegmentLocation
- mov edi, [di] ; Save long mode DS in edi
-
- mov si, Cr3Location ; Save CR3 in ecx
- mov ecx, [si]
-
- xor ax, ax
- mov ds, ax ; Clear data segment
-
- mov eax, cr0 ; Get control register 0
- or eax, 000000003h ; Set PE bit (bit #0) & MP
- mov cr0, eax
-
- mov eax, cr4
- bts eax, 5
- mov cr4, eax
-
- mov cr3, ecx ; Load CR3
-
- mov ecx, 0c0000080h ; EFER MSR number
- rdmsr ; Read EFER
- bts eax, 8 ; Set LME=1
- wrmsr ; Write EFER
-
- mov eax, cr0 ; Read CR0
- bts eax, 31 ; Set PG=1
- mov cr0, eax ; Write CR0
-
- jmp 0:strict dword 0 ; far jump to long mode
-BITS 64
-LongModeStart:
- mov eax, edi
- mov ds, ax
- mov es, ax
- mov ss, ax
-
- mov esi, ebx
- mov edi, esi
- add edi, LockLocation
- mov rax, NotVacantFlag
-
-TestLock:
- xchg qword [edi], rax
- cmp rax, NotVacantFlag
- jz TestLock
-
- mov edi, esi
- add edi, NumApsExecutingLoction
- inc dword [edi]
- mov ebx, [edi]
-
-ProgramStack:
- mov edi, esi
- add edi, StackSizeLocation
- mov rax, qword [edi]
- mov edi, esi
- add edi, StackStartAddressLocation
- add rax, qword [edi]
- mov rsp, rax
- mov qword [edi], rax
-
-Releaselock:
- mov rax, VacantFlag
- mov edi, esi
- add edi, LockLocation
- xchg qword [edi], rax
-
-CProcedureInvoke:
- push rbp ; push BIST data at top of AP stack
- xor rbp, rbp ; clear ebp for call stack trace
- push rbp
- mov rbp, rsp
-
- mov rax, ASM_PFX(InitializeFloatingPointUnits)
- sub rsp, 20h
- call rax ; Call assembly function to initialize FPU per UEFI spec
- add rsp, 20h
-
- mov edx, ebx ; edx is NumApsExecuting
- mov ecx, esi
- add ecx, LockLocation ; rcx is address of exchange info data buffer
-
- mov edi, esi
- add edi, ApProcedureLocation
- mov rax, qword [edi]
-
- sub rsp, 20h
- call rax ; invoke C function
- add rsp, 20h
- jmp $
-
-RendezvousFunnelProcEnd:
-
-;-------------------------------------------------------------------------------------
-; AsmGetAddressMap (&AddressMap);
-;-------------------------------------------------------------------------------------
-global ASM_PFX(AsmGetAddressMap)
-ASM_PFX(AsmGetAddressMap):
- mov rax, ASM_PFX(RendezvousFunnelProc)
- mov qword [rcx], rax
- mov qword [rcx + 8h], LongModeStart - RendezvousFunnelProcStart
- mov qword [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
- ret
-
-;-------------------------------------------------------------------------------------
-;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
-;about to become an AP. It switches it'stack with the current AP.
-;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
-;-------------------------------------------------------------------------------------
-global ASM_PFX(AsmExchangeRole)
-ASM_PFX(AsmExchangeRole):
- ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
- ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
-
- push rax
- push rbx
- push rcx
- push rdx
- push rsi
- push rdi
- push rbp
- push r8
- push r9
- push r10
- push r11
- push r12
- push r13
- push r14
- push r15
-
- mov rax, cr0
- push rax
-
- mov rax, cr4
- push rax
-
- ; rsi contains MyInfo pointer
- mov rsi, rcx
-
- ; rdi contains OthersInfo pointer
- mov rdi, rdx
-
- ;Store EFLAGS, GDTR and IDTR regiter to stack
- pushfq
- sgdt [rsi + 16]
- sidt [rsi + 26]
-
- ; Store the its StackPointer
- mov [rsi + 8], rsp
-
- ; update its switch state to STORED
- mov byte [rsi], CPU_SWITCH_STATE_STORED
-
-WaitForOtherStored:
- ; wait until the other CPU finish storing its state
- cmp byte [rdi], CPU_SWITCH_STATE_STORED
- jz OtherStored
- pause
- jmp WaitForOtherStored
-
-OtherStored:
- ; Since another CPU already stored its state, load them
- ; load GDTR value
- lgdt [rdi + 16]
-
- ; load IDTR value
- lidt [rdi + 26]
-
- ; load its future StackPointer
- mov rsp, [rdi + 8]
-
- ; update the other CPU's switch state to LOADED
- mov byte [rdi], CPU_SWITCH_STATE_LOADED
-
-WaitForOtherLoaded:
- ; wait until the other CPU finish loading new state,
- ; otherwise the data in stack may corrupt
- cmp byte [rsi], CPU_SWITCH_STATE_LOADED
- jz OtherLoaded
- pause
- jmp WaitForOtherLoaded
-
-OtherLoaded:
- ; since the other CPU already get the data it want, leave this procedure
- popfq
-
- pop rax
- mov cr4, rax
-
- pop rax
- mov cr0, rax
-
- pop r15
- pop r14
- pop r13
- pop r12
- pop r11
- pop r10
- pop r9
- pop r8
- pop rbp
- pop rdi
- pop rsi
- pop rdx
- pop rcx
- pop rbx
- pop rax
-
- ret
|