X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=UefiCpuPkg%2FLibrary%2FMpInitLib%2FDxeMpLib.c;h=d2bcef53d695ea828c795a854fdce1b9c15620b8;hp=733a9fb7be9401098ca959b0a57451971c8d3b76;hb=20737c2fe6895b2ce291c90596365e9d0ac467b0;hpb=a8d75a1802df015a79d929f45972de98b9a0a2d9 diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index 733a9fb7be..d2bcef53d6 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -17,6 +17,9 @@ #include #include #include +#include + +#include #define AP_CHECK_INTERVAL (EFI_TIMER_PERIOD_MILLISECONDS (100)) #define AP_SAFE_STACK_SIZE 128 @@ -73,72 +76,41 @@ SaveCpuMpData ( } /** - Allocate reset vector buffer. + Get available system memory below 1MB by specified size. - @param[in, out] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -AllocateResetVector ( - IN OUT CPU_MP_DATA *CpuMpData - ) -{ - EFI_STATUS Status; - UINTN ApResetVectorSize; - EFI_PHYSICAL_ADDRESS StartAddress; - - if (CpuMpData->SaveRestoreFlag) { - BackupAndPrepareWakeupBuffer (CpuMpData); - } else { - ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize + - sizeof (MP_CPU_EXCHANGE_INFO); - - StartAddress = BASE_1MB; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIMemoryNVS, - EFI_SIZE_TO_PAGES (ApResetVectorSize), - &StartAddress - ); - ASSERT_EFI_ERROR (Status); - - CpuMpData->WakeupBuffer = (UINTN) StartAddress; - CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) - (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize); - // - // copy AP reset code in it - // - CopyMem ( - (VOID *) CpuMpData->WakeupBuffer, - (VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress, - CpuMpData->AddressMap.RendezvousFunnelSize - ); - } -} + @param[in] WakeupBufferSize Wakeup buffer size required -/** - Free AP reset vector buffer. - - @param[in] CpuMpData The pointer to CPU MP Data structure. + @retval other Return wakeup buffer address below 1MB. + @retval -1 Cannot find free memory below 1MB. **/ -VOID -FreeResetVector ( - IN CPU_MP_DATA *CpuMpData +UINTN +GetWakeupBuffer ( + IN UINTN WakeupBufferSize ) { - EFI_STATUS Status; - UINTN ApResetVectorSize; - - if (CpuMpData->SaveRestoreFlag) { - RestoreWakeupBuffer (CpuMpData); - } else { - ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize + - sizeof (MP_CPU_EXCHANGE_INFO); + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS StartAddress; + + StartAddress = BASE_1MB; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + EFI_SIZE_TO_PAGES (WakeupBufferSize), + &StartAddress + ); + ASSERT_EFI_ERROR (Status); + if (!EFI_ERROR (Status)) { Status = gBS->FreePages( - (EFI_PHYSICAL_ADDRESS)CpuMpData->WakeupBuffer, - EFI_SIZE_TO_PAGES (ApResetVectorSize) + StartAddress, + EFI_SIZE_TO_PAGES (WakeupBufferSize) ); ASSERT_EFI_ERROR (Status); + DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n", + (UINTN) StartAddress, WakeupBufferSize)); + } else { + StartAddress = (EFI_PHYSICAL_ADDRESS) -1; } + return (UINTN) StartAddress; } /** @@ -297,7 +269,6 @@ MpInitChangeApLoopCallback ( CPU_MP_DATA *CpuMpData; CpuMpData = GetCpuMpData (); - CpuMpData->SaveRestoreFlag = TRUE; CpuMpData->PmCodeSegment = GetProtectedModeCS (); CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode); mNumberToFinish = CpuMpData->CpuCount - 1; @@ -318,9 +289,13 @@ InitMpGlobalData ( IN CPU_MP_DATA *CpuMpData ) { - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS Address; - UINTN ApSafeBufferSize; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Address; + UINTN ApSafeBufferSize; + UINTN Index; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc; + UINTN StackBase; + CPU_INFO_IN_HOB *CpuInfoInHob; SaveCpuMpData (CpuMpData); @@ -331,6 +306,46 @@ InitMpGlobalData ( return; } + if (PcdGetBool (PcdCpuStackGuard)) { + // + // One extra page at the bottom of the stack is needed for Guard page. + // + if (CpuMpData->CpuApStackSize <= EFI_PAGE_SIZE) { + DEBUG ((DEBUG_ERROR, "PcdCpuApStackSize is not big enough for Stack Guard!\n")); + ASSERT (FALSE); + } + + // + // DXE will reuse stack allocated for APs at PEI phase if it's available. + // Let's check it here. + // + // Note: BSP's stack guard is set at DxeIpl phase. But for the sake of + // BSP/AP exchange, stack guard for ApTopOfStack of cpu 0 will still be + // set here. + // + CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; + for (Index = 0; Index < CpuMpData->CpuCount; ++Index) { + if (CpuInfoInHob != NULL && CpuInfoInHob[Index].ApTopOfStack != 0) { + StackBase = (UINTN)CpuInfoInHob[Index].ApTopOfStack - CpuMpData->CpuApStackSize; + } else { + StackBase = CpuMpData->Buffer + Index * CpuMpData->CpuApStackSize; + } + + Status = gDS->GetMemorySpaceDescriptor (StackBase, &MemDesc); + ASSERT_EFI_ERROR (Status); + + Status = gDS->SetMemorySpaceAttributes ( + StackBase, + EFI_PAGES_TO_SIZE (1), + MemDesc.Attributes | EFI_MEMORY_RP + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "Stack Guard set at %lx [cpu%lu]!\n", + (UINT64)StackBase, (UINT64)Index)); + } + } + // // Avoid APs access invalid buffer data which allocated by BootServices, // so we will allocate reserved data for AP loop code. We also need to @@ -645,11 +660,39 @@ MpInitLibSwitchBSP ( IN BOOLEAN EnableOldBSP ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_TIMER_ARCH_PROTOCOL *Timer; + UINT64 TimerPeriod; + + TimerPeriod = 0; + // + // Locate Timer Arch Protocol + // + Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **) &Timer); + if (EFI_ERROR (Status)) { + Timer = NULL; + } + if (Timer != NULL) { + // + // Save current rate of DXE Timer + // + Timer->GetTimerPeriod (Timer, &TimerPeriod); + // + // Disable DXE Timer and drain pending interrupts + // + Timer->SetTimerPeriod (Timer, 0); + } Status = SwitchBSPWorker (ProcessorNumber, EnableOldBSP); + if (Timer != NULL) { + // + // Enable and restore rate of DXE Timer + // + Timer->SetTimerPeriod (Timer, TimerPeriod); + } + return Status; }