From: Jeff Fan Date: Fri, 22 Jul 2016 02:28:14 +0000 (+0800) Subject: UefiCpuPkg/CpuMpPei: Remove unused files and codes X-Git-Tag: edk2-stable201903~5991 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=4b0eeef313dbf8e5dc180f5b7bee2de901fbba7c UefiCpuPkg/CpuMpPei: Remove unused files and codes Cc: Michael Kinney Cc: Feng Tian Cc: Giri P Mudusuru Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan Reviewed-by: Michael Kinney Tested-by: Laszlo Ersek Tested-by: Michael Kinney --- 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,258 +21,20 @@ #include #include #include -#include - -#include -#include -#include #include -#include #include #include #include -#include -#include #include #include #include -#include -#include -#include -#include #include #include -#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. @@ -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.
-; 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.
-; 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.
-; 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.
- 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.
- 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 @@ -34,137 +34,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. 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.
-; 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.
-; 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.
-; 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