X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=UefiCpuPkg%2FLibrary%2FMpInitLib%2FMpLib.c;h=924b9097f28e9a2a17f3be1e89df304ebe6eb7ae;hb=d5fdae96e2fc88c4efee2af12da1dbaa47d161a3;hp=735e099b32f28e934ca20603679574bf82a02a30;hpb=3b2928b46987693caaaeefbb7b799d1e1de803c0;p=mirror_edk2.git diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index 735e099b32..924b9097f2 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -451,6 +451,12 @@ CollectProcessorCount ( CpuPause (); } + if (CpuMpData->CpuCount > 255) { + // + // If there are more than 255 processor found, force to enable X2APIC + // + CpuMpData->X2ApicEnable = TRUE; + } if (CpuMpData->X2ApicEnable) { DEBUG ((DEBUG_INFO, "Force x2APIC mode!\n")); // @@ -547,6 +553,7 @@ ApWakeupFunction ( volatile UINT32 *ApStartupSignalBuffer; CPU_INFO_IN_HOB *CpuInfoInHob; UINT64 ApTopOfStack; + UINTN CurrentApicMode; // // AP finished assembly code and begin to execute C code @@ -560,6 +567,7 @@ ApWakeupFunction ( ProgramVirtualWireMode (); SyncLocalApicTimerSetting (CpuMpData); + CurrentApicMode = GetApicMode (); while (TRUE) { if (CpuMpData->InitFlag == ApInitConfig) { // @@ -627,11 +635,23 @@ ApWakeupFunction ( ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal; CpuInfoInHob[ProcessorNumber].ApTopOfStack = CpuInfoInHob[CpuMpData->NewBspNumber].ApTopOfStack; } else { - // - // Re-get the CPU APICID and Initial APICID - // - CpuInfoInHob[ProcessorNumber].ApicId = GetApicId (); - CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId (); + if (CpuInfoInHob[ProcessorNumber].ApicId != GetApicId () || + CpuInfoInHob[ProcessorNumber].InitialApicId != GetInitialApicId ()) { + if (CurrentApicMode != GetApicMode ()) { + // + // If APIC mode change happened during AP function execution, + // we do not support APIC ID value changed. + // + ASSERT (FALSE); + CpuDeadLoop (); + } else { + // + // Re-get the CPU APICID and Initial APICID if they are changed + // + CpuInfoInHob[ProcessorNumber].ApicId = GetApicId (); + CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId (); + } + } } } SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished); @@ -775,6 +795,81 @@ TimedWaitForApFinish ( IN UINT32 TimeLimit ); +/** + Get available system memory below 1MB by specified size. + + @param[in] CpuMpData The pointer to CPU MP Data structure. +**/ +VOID +BackupAndPrepareWakeupBuffer( + IN CPU_MP_DATA *CpuMpData + ) +{ + CopyMem ( + (VOID *) CpuMpData->BackupBuffer, + (VOID *) CpuMpData->WakeupBuffer, + CpuMpData->BackupBufferSize + ); + CopyMem ( + (VOID *) CpuMpData->WakeupBuffer, + (VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress, + CpuMpData->AddressMap.RendezvousFunnelSize + ); +} + +/** + Restore wakeup buffer data. + + @param[in] CpuMpData The pointer to CPU MP Data structure. +**/ +VOID +RestoreWakeupBuffer( + IN CPU_MP_DATA *CpuMpData + ) +{ + CopyMem ( + (VOID *) CpuMpData->WakeupBuffer, + (VOID *) CpuMpData->BackupBuffer, + CpuMpData->BackupBufferSize + ); +} + +/** + Allocate reset vector buffer. + + @param[in, out] CpuMpData The pointer to CPU MP Data structure. +**/ +VOID +AllocateResetVector ( + IN OUT CPU_MP_DATA *CpuMpData + ) +{ + UINTN ApResetVectorSize; + + if (CpuMpData->WakeupBuffer == (UINTN) -1) { + ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize + + sizeof (MP_CPU_EXCHANGE_INFO); + + CpuMpData->WakeupBuffer = GetWakeupBuffer (ApResetVectorSize); + CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) + (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize); + } + BackupAndPrepareWakeupBuffer (CpuMpData); +} + +/** + Free AP reset vector buffer. + + @param[in] CpuMpData The pointer to CPU MP Data structure. +**/ +VOID +FreeResetVector ( + IN CPU_MP_DATA *CpuMpData + ) +{ + RestoreWakeupBuffer (CpuMpData); +} + /** This function will be called by BSP to wakeup AP. @@ -906,6 +1001,9 @@ CalculateTimeout ( OUT UINT64 *CurrentTime ) { + UINT64 TimeoutInSeconds; + UINT64 TimestampCounterFreq; + // // Read the current value of the performance counter // @@ -921,16 +1019,36 @@ CalculateTimeout ( // // GetPerformanceCounterProperties () returns the timestamp counter's frequency - // in Hz. So multiply the return value with TimeoutInMicroseconds and then divide - // it by 1,000,000, to get the number of ticks for the timeout value. - // - return DivU64x32 ( - MultU64x64 ( - GetPerformanceCounterProperties (NULL, NULL), - TimeoutInMicroseconds - ), - 1000000 - ); + // in Hz. + // + TimestampCounterFreq = GetPerformanceCounterProperties (NULL, NULL); + + // + // Check the potential overflow before calculate the number of ticks for the timeout value. + // + if (DivU64x64Remainder (MAX_UINT64, TimeoutInMicroseconds, NULL) < TimestampCounterFreq) { + // + // Convert microseconds into seconds if direct multiplication overflows + // + TimeoutInSeconds = DivU64x32 (TimeoutInMicroseconds, 1000000); + // + // Assertion if the final tick count exceeds MAX_UINT64 + // + ASSERT (DivU64x64Remainder (MAX_UINT64, TimeoutInSeconds, NULL) >= TimestampCounterFreq); + return MultU64x64 (TimestampCounterFreq, TimeoutInSeconds); + } else { + // + // No overflow case, multiply the return value with TimeoutInMicroseconds and then divide + // it by 1,000,000, to get the number of ticks for the timeout value. + // + return DivU64x32 ( + MultU64x64 ( + TimestampCounterFreq, + TimeoutInMicroseconds + ), + 1000000 + ); + } } /** @@ -1333,7 +1451,6 @@ MpInitLibInitialize ( CpuMpData->CpuApStackSize = ApStackSize; CpuMpData->BackupBuffer = BackupBufferAddr; CpuMpData->BackupBufferSize = ApResetVectorSize; - CpuMpData->SaveRestoreFlag = FALSE; CpuMpData->WakeupBuffer = (UINTN) -1; CpuMpData->CpuCount = 1; CpuMpData->BspNumber = 0; @@ -1398,7 +1515,7 @@ MpInitLibInitialize ( CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; for (Index = 0; Index < CpuMpData->CpuCount; Index++) { InitializeSpinLock(&CpuMpData->CpuData[Index].ApLock); - if (CpuInfoInHob[Index].InitialApicId >= 255) { + if (CpuInfoInHob[Index].InitialApicId >= 255 || Index > 254) { CpuMpData->X2ApicEnable = TRUE; } CpuMpData->CpuData[Index].CpuHealthy = (CpuInfoInHob[Index].Health == 0)? TRUE:FALSE; @@ -1564,7 +1681,7 @@ SwitchBSPWorker ( // MpInitLibWhoAmI (&CallerNumber); if (CallerNumber != CpuMpData->BspNumber) { - return EFI_SUCCESS; + return EFI_DEVICE_ERROR; } if (ProcessorNumber >= CpuMpData->CpuCount) { @@ -1697,7 +1814,7 @@ EnableDisableApWorker ( if (!EnableAP) { SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateDisabled); } else { - SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle); + ResetProcessorToIdleState (ProcessorNumber); } if (HealthFlag != NULL) { @@ -2100,41 +2217,3 @@ GetCpuMpDataFromGuidedHob ( return CpuMpData; } -/** - Get available system memory below 1MB by specified size. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -BackupAndPrepareWakeupBuffer( - IN CPU_MP_DATA *CpuMpData - ) -{ - CopyMem ( - (VOID *) CpuMpData->BackupBuffer, - (VOID *) CpuMpData->WakeupBuffer, - CpuMpData->BackupBufferSize - ); - CopyMem ( - (VOID *) CpuMpData->WakeupBuffer, - (VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress, - CpuMpData->AddressMap.RendezvousFunnelSize - ); -} - -/** - Restore wakeup buffer data. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -RestoreWakeupBuffer( - IN CPU_MP_DATA *CpuMpData - ) -{ - CopyMem ( - (VOID *) CpuMpData->WakeupBuffer, - (VOID *) CpuMpData->BackupBuffer, - CpuMpData->BackupBufferSize - ); -}