diff options
Diffstat (limited to 'UefiCpuPkg/Library/MpInitLib')
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 75 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.uni | 22 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 743 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc | 43 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm | 339 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/Microcode.c | 218 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/MpLib.c | 2126 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/MpLib.h | 594 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 70 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.uni | 22 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/PeiMpLib.c | 624 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc | 43 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 398 |
13 files changed, 0 insertions, 5317 deletions
diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf deleted file mode 100644 index 9751ba1f0d..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ /dev/null @@ -1,75 +0,0 @@ -## @file
-# MP Initialize Library instance for DXE driver.
-#
-# Copyright (c) 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.
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = DxeMpInitLib
- MODULE_UNI_FILE = DxeMpInitLib.uni
- FILE_GUID = B88F7146-9834-4c55-BFAC-481CC0C33736
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.1
- LIBRARY_CLASS = MpInitLib|DXE_DRIVER
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64
-#
-
-[Sources.IA32]
- Ia32/MpEqu.inc
- Ia32/MpFuncs.nasm
-
-[Sources.X64]
- X64/MpEqu.inc
- X64/MpFuncs.nasm
-
-[Sources.common]
- DxeMpLib.c
- MpLib.c
- MpLib.h
- Microcode.c
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- UefiCpuPkg/UefiCpuPkg.dec
-
-[LibraryClasses]
- BaseLib
- LocalApicLib
- MemoryAllocationLib
- HobLib
- MtrrLib
- CpuLib
- UefiCpuLib
- UefiBootServicesTableLib
- DebugAgentLib
-
-[Protocols]
- gEfiTimerArchProtocolGuid ## SOMETIMES_CONSUMES
-
-[Guids]
- gEfiEventExitBootServicesGuid ## CONSUMES ## Event
- gEfiEventLegacyBootGuid ## CONSUMES ## Event
-
-[Pcd]
- gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## SOMETIMES_CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES
-
diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.uni b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.uni deleted file mode 100644 index 99d79974be..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.uni +++ /dev/null @@ -1,22 +0,0 @@ -// /** @file
-// MP Initialize Library instance for DXE driver.
-//
-// MP Initialize Library instance for DXE driver.
-//
-// Copyright (c) 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.
-//
-// **/
-
-
-#string STR_MODULE_ABSTRACT #language en-US "MP Initialize Library instance for DXE driver."
-
-#string STR_MODULE_DESCRIPTION #language en-US "MP Initialize Library instance for DXE driver."
-
diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c deleted file mode 100644 index b393244e05..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ /dev/null @@ -1,743 +0,0 @@ -/** @file
- MP initialize support functions for DXE phase.
-
- Copyright (c) 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 "MpLib.h"
-
-#include <Library/UefiLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/DebugAgentLib.h>
-
-#include <Protocol/Timer.h>
-
-#define AP_CHECK_INTERVAL (EFI_TIMER_PERIOD_MILLISECONDS (100))
-#define AP_SAFE_STACK_SIZE 128
-
-CPU_MP_DATA *mCpuMpData = NULL;
-EFI_EVENT mCheckAllApsEvent = NULL;
-EFI_EVENT mMpInitExitBootServicesEvent = NULL;
-EFI_EVENT mLegacyBootEvent = NULL;
-volatile BOOLEAN mStopCheckAllApsStatus = TRUE;
-VOID *mReservedApLoopFunc = NULL;
-UINTN mReservedTopOfApStack;
-volatile UINT32 mNumberToFinish = 0;
-
-/**
- Enable Debug Agent to support source debugging on AP function.
-
-**/
-VOID
-EnableDebugAgent (
- VOID
- )
-{
- //
- // Initialize Debug Agent to support source level debug in DXE phase
- //
- InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_AP, NULL, NULL);
-}
-
-/**
- Get the pointer to CPU MP Data structure.
-
- @return The pointer to CPU MP Data structure.
-**/
-CPU_MP_DATA *
-GetCpuMpData (
- VOID
- )
-{
- ASSERT (mCpuMpData != NULL);
- return mCpuMpData;
-}
-
-/**
- Save the pointer to CPU MP Data structure.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
-**/
-VOID
-SaveCpuMpData (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- mCpuMpData = CpuMpData;
-}
-
-/**
- Allocate reset vector buffer.
-
- @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
- );
- }
-}
-
-/**
- Free AP reset vector buffer.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure.
-**/
-VOID
-FreeResetVector (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- EFI_STATUS Status;
- UINTN ApResetVectorSize;
-
- if (CpuMpData->SaveRestoreFlag) {
- RestoreWakeupBuffer (CpuMpData);
- } else {
- ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +
- sizeof (MP_CPU_EXCHANGE_INFO);
- Status = gBS->FreePages(
- (EFI_PHYSICAL_ADDRESS)CpuMpData->WakeupBuffer,
- EFI_SIZE_TO_PAGES (ApResetVectorSize)
- );
- ASSERT_EFI_ERROR (Status);
- }
-}
-
-/**
- Checks APs status and updates APs status if needed.
-
-**/
-VOID
-CheckAndUpdateApsStatus (
- VOID
- )
-{
- UINTN ProcessorNumber;
- EFI_STATUS Status;
- CPU_MP_DATA *CpuMpData;
-
- CpuMpData = GetCpuMpData ();
-
- //
- // First, check whether pending StartupAllAPs() exists.
- //
- if (CpuMpData->WaitEvent != NULL) {
-
- Status = CheckAllAPs ();
- //
- // If all APs finish for StartupAllAPs(), signal the WaitEvent for it.
- //
- if (Status != EFI_NOT_READY) {
- Status = gBS->SignalEvent (CpuMpData->WaitEvent);
- CpuMpData->WaitEvent = NULL;
- }
- }
-
- //
- // Second, check whether pending StartupThisAPs() callings exist.
- //
- for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) {
-
- if (CpuMpData->CpuData[ProcessorNumber].WaitEvent == NULL) {
- continue;
- }
-
- Status = CheckThisAP (ProcessorNumber);
-
- if (Status != EFI_NOT_READY) {
- gBS->SignalEvent (CpuMpData->CpuData[ProcessorNumber].WaitEvent);
- CpuMpData->CpuData[ProcessorNumber].WaitEvent = NULL;
- }
- }
-}
-
-/**
- Checks APs' status periodically.
-
- This function is triggered by timer periodically to check the
- state of APs for StartupAllAPs() and StartupThisAP() executed
- in non-blocking mode.
-
- @param[in] Event Event triggered.
- @param[in] Context Parameter passed with the event.
-
-**/
-VOID
-EFIAPI
-CheckApsStatus (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- //
- // If CheckApsStatus() is not stopped, otherwise return immediately.
- //
- if (!mStopCheckAllApsStatus) {
- CheckAndUpdateApsStatus ();
- }
-}
-
-/**
- Get Protected mode code segment from current GDT table.
-
- @return Protected mode code segment value.
-**/
-UINT16
-GetProtectedModeCS (
- VOID
- )
-{
- IA32_DESCRIPTOR GdtrDesc;
- IA32_SEGMENT_DESCRIPTOR *GdtEntry;
- UINTN GdtEntryCount;
- UINT16 Index;
-
- Index = (UINT16) -1;
- AsmReadGdtr (&GdtrDesc);
- GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);
- GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
- for (Index = 0; Index < GdtEntryCount; Index++) {
- if (GdtEntry->Bits.L == 0) {
- if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.L == 0) {
- break;
- }
- }
- GdtEntry++;
- }
- ASSERT (Index != -1);
- return Index * 8;
-}
-
-/**
- Do sync on APs.
-
- @param[in, out] Buffer Pointer to private data buffer.
-**/
-VOID
-EFIAPI
-RelocateApLoop (
- IN OUT VOID *Buffer
- )
-{
- CPU_MP_DATA *CpuMpData;
- BOOLEAN MwaitSupport;
- ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc;
- UINTN ProcessorNumber;
-
- MpInitLibWhoAmI (&ProcessorNumber);
- CpuMpData = GetCpuMpData ();
- MwaitSupport = IsMwaitSupport ();
- AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP) (UINTN) mReservedApLoopFunc;
- AsmRelocateApLoopFunc (
- MwaitSupport,
- CpuMpData->ApTargetCState,
- CpuMpData->PmCodeSegment,
- mReservedTopOfApStack - ProcessorNumber * AP_SAFE_STACK_SIZE,
- (UINTN) &mNumberToFinish
- );
- //
- // It should never reach here
- //
- ASSERT (FALSE);
-}
-
-/**
- Callback function for ExitBootServices.
-
- @param[in] Event Event whose notification function is being invoked.
- @param[in] Context The pointer to the notification function's context,
- which is implementation-dependent.
-
-**/
-VOID
-EFIAPI
-MpInitChangeApLoopCallback (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- CPU_MP_DATA *CpuMpData;
-
- CpuMpData = GetCpuMpData ();
- CpuMpData->SaveRestoreFlag = TRUE;
- CpuMpData->PmCodeSegment = GetProtectedModeCS ();
- CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode);
- mNumberToFinish = CpuMpData->CpuCount - 1;
- WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL);
- while (mNumberToFinish > 0) {
- CpuPause ();
- }
- DEBUG ((DEBUG_INFO, "%a() done!\n", __FUNCTION__));
-}
-
-/**
- Initialize global data for MP support.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure.
-**/
-VOID
-InitMpGlobalData (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS Address;
- UINTN ApSafeBufferSize;
-
- SaveCpuMpData (CpuMpData);
-
- if (CpuMpData->CpuCount == 1) {
- //
- // If only BSP exists, return
- //
- return;
- }
-
- //
- // Avoid APs access invalid buffer data which allocated by BootServices,
- // so we will allocate reserved data for AP loop code. We also need to
- // allocate this buffer below 4GB due to APs may be transferred to 32bit
- // protected mode on long mode DXE.
- // Allocating it in advance since memory services are not available in
- // Exit Boot Services callback function.
- //
- ApSafeBufferSize = CpuMpData->AddressMap.RelocateApLoopFuncSize;
- ApSafeBufferSize += CpuMpData->CpuCount * AP_SAFE_STACK_SIZE;
-
- Address = BASE_4GB - 1;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiReservedMemoryType,
- EFI_SIZE_TO_PAGES (ApSafeBufferSize),
- &Address
- );
- ASSERT_EFI_ERROR (Status);
- mReservedApLoopFunc = (VOID *) (UINTN) Address;
- ASSERT (mReservedApLoopFunc != NULL);
- mReservedTopOfApStack = (UINTN) Address + EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (ApSafeBufferSize));
- ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);
- CopyMem (
- mReservedApLoopFunc,
- CpuMpData->AddressMap.RelocateApLoopFuncAddress,
- CpuMpData->AddressMap.RelocateApLoopFuncSize
- );
-
- Status = gBS->CreateEvent (
- EVT_TIMER | EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- CheckApsStatus,
- NULL,
- &mCheckAllApsEvent
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Set timer to check all APs status.
- //
- Status = gBS->SetTimer (
- mCheckAllApsEvent,
- TimerPeriodic,
- AP_CHECK_INTERVAL
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = gBS->CreateEvent (
- EVT_SIGNAL_EXIT_BOOT_SERVICES,
- TPL_CALLBACK,
- MpInitChangeApLoopCallback,
- NULL,
- &mMpInitExitBootServicesEvent
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- MpInitChangeApLoopCallback,
- NULL,
- &gEfiEventLegacyBootGuid,
- &mLegacyBootEvent
- );
- ASSERT_EFI_ERROR (Status);
-}
-
-/**
- This service executes a caller provided function on all enabled APs.
-
- @param[in] Procedure A pointer to the function to be run on
- enabled APs of the system. See type
- EFI_AP_PROCEDURE.
- @param[in] SingleThread If TRUE, then all the enabled APs execute
- the function specified by Procedure one by
- one, in ascending order of processor handle
- number. If FALSE, then all the enabled APs
- execute the function specified by Procedure
- simultaneously.
- @param[in] WaitEvent The event created by the caller with CreateEvent()
- service. If it is NULL, then execute in
- blocking mode. BSP waits until all APs finish
- or TimeoutInMicroSeconds expires. If it's
- not NULL, then execute in non-blocking mode.
- BSP requests the function specified by
- Procedure to be started on all the enabled
- APs, and go on executing immediately. If
- all return from Procedure, or TimeoutInMicroSeconds
- expires, this event is signaled. The BSP
- can use the CheckEvent() or WaitForEvent()
- services to check the state of event. Type
- EFI_EVENT is defined in CreateEvent() in
- the Unified Extensible Firmware Interface
- Specification.
- @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
- APs to return from Procedure, either for
- blocking or non-blocking mode. Zero means
- infinity. If the timeout expires before
- all APs return from Procedure, then Procedure
- on the failed APs is terminated. All enabled
- APs are available for next function assigned
- by MpInitLibStartupAllAPs() or
- MPInitLibStartupThisAP().
- If the timeout expires in blocking mode,
- BSP returns EFI_TIMEOUT. If the timeout
- expires in non-blocking mode, WaitEvent
- is signaled with SignalEvent().
- @param[in] ProcedureArgument The parameter passed into Procedure for
- all APs.
- @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
- if all APs finish successfully, then its
- content is set to NULL. If not all APs
- finish before timeout expires, then its
- content is set to address of the buffer
- holding handle numbers of the failed APs.
- The buffer is allocated by MP Initialization
- library, and it's the caller's responsibility to
- free the buffer with FreePool() service.
- In blocking mode, it is ready for consumption
- when the call returns. In non-blocking mode,
- it is ready when WaitEvent is signaled. The
- list of failed CPU is terminated by
- END_OF_CPU_LIST.
-
- @retval EFI_SUCCESS In blocking mode, all APs have finished before
- the timeout expired.
- @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
- to all enabled APs.
- @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
- UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
- signaled.
- @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
- supported.
- @retval EFI_DEVICE_ERROR Caller processor is AP.
- @retval EFI_NOT_STARTED No enabled APs exist in the system.
- @retval EFI_NOT_READY Any enabled APs are busy.
- @retval EFI_NOT_READY MP Initialize Library is not initialized.
- @retval EFI_TIMEOUT In blocking mode, the timeout expired before
- all enabled APs have finished.
- @retval EFI_INVALID_PARAMETER Procedure is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibStartupAllAPs (
- IN EFI_AP_PROCEDURE Procedure,
- IN BOOLEAN SingleThread,
- IN EFI_EVENT WaitEvent OPTIONAL,
- IN UINTN TimeoutInMicroseconds,
- IN VOID *ProcedureArgument OPTIONAL,
- OUT UINTN **FailedCpuList OPTIONAL
- )
-{
- EFI_STATUS Status;
-
- //
- // Temporarily stop checkAllApsStatus for avoid resource dead-lock.
- //
- mStopCheckAllApsStatus = TRUE;
-
- Status = StartupAllAPsWorker (
- Procedure,
- SingleThread,
- WaitEvent,
- TimeoutInMicroseconds,
- ProcedureArgument,
- FailedCpuList
- );
-
- //
- // Start checkAllApsStatus
- //
- mStopCheckAllApsStatus = FALSE;
-
- return Status;
-}
-
-/**
- This service lets the caller get one enabled AP to execute a caller-provided
- function.
-
- @param[in] Procedure A pointer to the function to be run on the
- designated AP of the system. See type
- EFI_AP_PROCEDURE.
- @param[in] ProcessorNumber The handle number of the AP. The range is
- from 0 to the total number of logical
- processors minus 1. The total number of
- logical processors can be retrieved by
- MpInitLibGetNumberOfProcessors().
- @param[in] WaitEvent The event created by the caller with CreateEvent()
- service. If it is NULL, then execute in
- blocking mode. BSP waits until this AP finish
- or TimeoutInMicroSeconds expires. If it's
- not NULL, then execute in non-blocking mode.
- BSP requests the function specified by
- Procedure to be started on this AP,
- and go on executing immediately. If this AP
- return from Procedure or TimeoutInMicroSeconds
- expires, this event is signaled. The BSP
- can use the CheckEvent() or WaitForEvent()
- services to check the state of event. Type
- EFI_EVENT is defined in CreateEvent() in
- the Unified Extensible Firmware Interface
- Specification.
- @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
- this AP to finish this Procedure, either for
- blocking or non-blocking mode. Zero means
- infinity. If the timeout expires before
- this AP returns from Procedure, then Procedure
- on the AP is terminated. The
- AP is available for next function assigned
- by MpInitLibStartupAllAPs() or
- MpInitLibStartupThisAP().
- If the timeout expires in blocking mode,
- BSP returns EFI_TIMEOUT. If the timeout
- expires in non-blocking mode, WaitEvent
- is signaled with SignalEvent().
- @param[in] ProcedureArgument The parameter passed into Procedure on the
- specified AP.
- @param[out] Finished If NULL, this parameter is ignored. In
- blocking mode, this parameter is ignored.
- In non-blocking mode, if AP returns from
- Procedure before the timeout expires, its
- content is set to TRUE. Otherwise, the
- value is set to FALSE. The caller can
- determine if the AP returned from Procedure
- by evaluating this value.
-
- @retval EFI_SUCCESS In blocking mode, specified AP finished before
- the timeout expires.
- @retval EFI_SUCCESS In non-blocking mode, the function has been
- dispatched to specified AP.
- @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
- UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
- signaled.
- @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
- supported.
- @retval EFI_DEVICE_ERROR The calling processor is an AP.
- @retval EFI_TIMEOUT In blocking mode, the timeout expired before
- the specified AP has finished.
- @retval EFI_NOT_READY The specified AP is busy.
- @retval EFI_NOT_READY MP Initialize Library is not initialized.
- @retval EFI_NOT_FOUND The processor with the handle specified by
- ProcessorNumber does not exist.
- @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
- @retval EFI_INVALID_PARAMETER Procedure is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibStartupThisAP (
- IN EFI_AP_PROCEDURE Procedure,
- IN UINTN ProcessorNumber,
- IN EFI_EVENT WaitEvent OPTIONAL,
- IN UINTN TimeoutInMicroseconds,
- IN VOID *ProcedureArgument OPTIONAL,
- OUT BOOLEAN *Finished OPTIONAL
- )
-{
- EFI_STATUS Status;
-
- //
- // temporarily stop checkAllApsStatus for avoid resource dead-lock.
- //
- mStopCheckAllApsStatus = TRUE;
-
- Status = StartupThisAPWorker (
- Procedure,
- ProcessorNumber,
- WaitEvent,
- TimeoutInMicroseconds,
- ProcedureArgument,
- Finished
- );
-
- mStopCheckAllApsStatus = FALSE;
-
- return Status;
-}
-
-/**
- This service switches the requested AP to be the BSP from that point onward.
- This service changes the BSP for all purposes. This call can only be performed
- by the current BSP.
-
- @param[in] ProcessorNumber The handle number of AP that is to become the new
- BSP. The range is from 0 to the total number of
- logical processors minus 1. The total number of
- logical processors can be retrieved by
- MpInitLibGetNumberOfProcessors().
- @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
- enabled AP. Otherwise, it will be disabled.
-
- @retval EFI_SUCCESS BSP successfully switched.
- @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
- this service returning.
- @retval EFI_UNSUPPORTED Switching the BSP is not supported.
- @retval EFI_DEVICE_ERROR The calling processor is an AP.
- @retval EFI_NOT_FOUND The processor with the handle specified by
- ProcessorNumber does not exist.
- @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
- a disabled AP.
- @retval EFI_NOT_READY The specified AP is busy.
- @retval EFI_NOT_READY MP Initialize Library is not initialized.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibSwitchBSP (
- IN UINTN ProcessorNumber,
- IN BOOLEAN EnableOldBSP
- )
-{
- 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;
-}
-
-/**
- This service lets the caller enable or disable an AP from this point onward.
- This service may only be called from the BSP.
-
- @param[in] ProcessorNumber The handle number of AP.
- The range is from 0 to the total number of
- logical processors minus 1. The total number of
- logical processors can be retrieved by
- MpInitLibGetNumberOfProcessors().
- @param[in] EnableAP Specifies the new state for the processor for
- enabled, FALSE for disabled.
- @param[in] HealthFlag If not NULL, a pointer to a value that specifies
- the new health status of the AP. This flag
- corresponds to StatusFlag defined in
- EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
- the PROCESSOR_HEALTH_STATUS_BIT is used. All other
- bits are ignored. If it is NULL, this parameter
- is ignored.
-
- @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
- @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
- prior to this service returning.
- @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
- @retval EFI_DEVICE_ERROR The calling processor is an AP.
- @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
- does not exist.
- @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
- @retval EFI_NOT_READY MP Initialize Library is not initialized.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibEnableDisableAP (
- IN UINTN ProcessorNumber,
- IN BOOLEAN EnableAP,
- IN UINT32 *HealthFlag OPTIONAL
- )
-{
- EFI_STATUS Status;
- BOOLEAN TempStopCheckState;
-
- TempStopCheckState = FALSE;
- //
- // temporarily stop checkAllAPsStatus for initialize parameters.
- //
- if (!mStopCheckAllApsStatus) {
- mStopCheckAllApsStatus = TRUE;
- TempStopCheckState = TRUE;
- }
-
- Status = EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);
-
- if (TempStopCheckState) {
- mStopCheckAllApsStatus = FALSE;
- }
-
- return Status;
-}
diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc b/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc deleted file mode 100644 index 62762308e2..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc +++ /dev/null @@ -1,43 +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
-NumApsExecutingLocation equ LockLocation + 24h
-CodeSegmentLocation equ LockLocation + 28h
-DataSegmentLocation equ LockLocation + 2Ch
-EnableExecuteDisableLocation equ LockLocation + 30h
-Cr3Location equ LockLocation + 34h
-InitFlagLocation equ LockLocation + 38h
-CpuInfoLocation equ LockLocation + 3Ch
-
diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm deleted file mode 100644 index 52363e6e08..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm +++ /dev/null @@ -1,339 +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, EnableExecuteDisableLocation
- cmp byte [edi], 0
- jz SkipEnableExecuteDisable
-
- ;
- ; Enable IA32 PAE execute disable
- ;
-
- mov ecx, 0xc0000080
- rdmsr
- bts eax, 11
- wrmsr
-
- mov edi, esi
- add edi, Cr3Location
- mov eax, dword [edi]
- mov cr3, eax
-
- mov eax, cr4
- bts eax, 5
- mov cr4, eax
-
- mov eax, cr0
- bts eax, 31
- mov cr0, eax
-
-SkipEnableExecuteDisable:
- mov edi, esi
- add edi, InitFlagLocation
- cmp dword [edi], 1 ; 1 == ApInitConfig
- jnz GetApicId
-
- ; AP init
- mov edi, esi
- add edi, LockLocation
- mov eax, NotVacantFlag
-
-TestLock:
- xchg [edi], eax
- cmp eax, NotVacantFlag
- jz TestLock
-
- mov ecx, esi
- add ecx, NumApsExecutingLocation
- inc dword [ecx]
- mov ebx, [ecx]
-
-Releaselock:
- mov eax, VacantFlag
- xchg [edi], eax
-
- mov edi, esi
- add edi, StackSizeLocation
- mov eax, [edi]
- mov ecx, ebx
- inc ecx
- mul ecx ; EAX = StackSize * (CpuNumber + 1)
- mov edi, esi
- add edi, StackStartAddressLocation
- add eax, [edi]
- mov esp, eax
- jmp CProcedureInvoke
-
-GetApicId:
- mov eax, 0
- cpuid
- cmp eax, 0bh
- jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
-
- mov eax, 0bh
- xor ecx, ecx
- cpuid
- test ebx, 0ffffh
- jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
-
- ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
- jmp GetProcessorNumber
-
-NoX2Apic:
- ; Processor is not x2APIC capable, so get 8-bit APIC ID
- mov eax, 1
- cpuid
- shr ebx, 24
- mov edx, ebx
-
-GetProcessorNumber:
- ;
- ; Get processor number for this AP
- ; Note that BSP may become an AP due to SwitchBsp()
- ;
- xor ebx, ebx
- lea eax, [esi + CpuInfoLocation]
- mov edi, [eax]
-
-GetNextProcNumber:
- cmp [edi], edx ; APIC ID match?
- jz ProgramStack
- add edi, 20
- inc ebx
- jmp GetNextProcNumber
-
-ProgramStack:
- mov esp, [edi + 12]
-
-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:
-
-;-------------------------------------------------------------------------------------
-; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish);
-;-------------------------------------------------------------------------------------
-global ASM_PFX(AsmRelocateApLoop)
-ASM_PFX(AsmRelocateApLoop):
-AsmRelocateApLoopStart:
- mov eax, esp
- mov esp, [eax + 16] ; TopOfApStack
- push dword [eax] ; push return address for stack trace
- push ebp
- mov ebp, esp
- mov ebx, [eax + 8] ; ApTargetCState
- mov ecx, [eax + 4] ; MwaitSupport
- mov eax, [eax + 20] ; CountTofinish
- lock dec dword [eax] ; (*CountTofinish)--
- cmp cl, 1 ; Check mwait-monitor support
- jnz HltLoop
-MwaitLoop:
- mov eax, esp
- xor ecx, ecx
- xor edx, edx
- monitor
- mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
- shl eax, 4
- mwait
- jmp MwaitLoop
-HltLoop:
- cli
- hlt
- jmp HltLoop
-AsmRelocateApLoopEnd:
-
-;-------------------------------------------------------------------------------------
-; 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
- mov dword [ebx + 0Ch], AsmRelocateApLoopStart
- mov dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
-
- 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/Library/MpInitLib/Microcode.c b/UefiCpuPkg/Library/MpInitLib/Microcode.c deleted file mode 100644 index 982995be7d..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/Microcode.c +++ /dev/null @@ -1,218 +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 "MpLib.h"
-
-/**
- Get microcode update signature of currently loaded microcode update.
-
- @return Microcode signature.
-**/
-UINT32
-GetCurrentMicrocodeSignature (
- VOID
- )
-{
- MSR_IA32_BIOS_SIGN_ID_REGISTER BiosSignIdMsr;
-
- AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
- BiosSignIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID);
- return BiosSignIdMsr.Bits.MicrocodeUpdateSignature;
-}
-
-/**
- Detect whether specified processor can find matching microcode patch and load it.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure.
-**/
-VOID
-MicrocodeDetect (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- UINT64 MicrocodePatchAddress;
- UINT64 MicrocodePatchRegionSize;
- UINT32 ExtendedTableLength;
- UINT32 ExtendedTableCount;
- CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;
- CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;
- CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
- UINTN MicrocodeEnd;
- UINTN Index;
- UINT8 PlatformId;
- CPUID_VERSION_INFO_EAX Eax;
- UINT32 CurrentRevision;
- UINT32 LatestRevision;
- UINTN TotalSize;
- UINT32 CheckSum32;
- BOOLEAN CorrectMicrocode;
- VOID *MicrocodeData;
- MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr;
-
- 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 sCPUID data.
- //
- AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);
-
- //
- // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID
- //
- PlatformIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);
- PlatformId = (UINT8) PlatformIdMsr.Bits.PlatformId;
-
- LatestRevision = 0;
- MicrocodeData = NULL;
- MicrocodeEnd = (UINTN) (MicrocodePatchAddress + MicrocodePatchRegionSize);
- MicrocodeEntryPoint = (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->ProcessorSignature.Uint32 == Eax.Uint32 &&
- MicrocodeEntryPoint->UpdateRevision > LatestRevision &&
- (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId))
- ) {
- if (MicrocodeEntryPoint->DataSize == 0) {
- CheckSum32 = CalculateSum32 ((UINT32 *) MicrocodeEntryPoint, 2048);
- } else {
- CheckSum32 = CalculateSum32 (
- (UINT32 *) MicrocodeEntryPoint,
- MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER)
- );
- }
- if (CheckSum32 == 0) {
- CorrectMicrocode = TRUE;
- }
- } else if ((MicrocodeEntryPoint->DataSize != 0) &&
- (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {
- ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize +
- sizeof (CPU_MICROCODE_HEADER));
- if (ExtendedTableLength != 0) {
- //
- // Extended Table exist, check if the CPU in support list
- //
- ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)
- + MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER));
- //
- // Calculate Extended Checksum
- //
- if ((ExtendedTableLength % 4) == 0) {
- CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTableHeader, ExtendedTableLength);
- if (CheckSum32 == 0) {
- //
- // Checksum correct
- //
- ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
- ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
- for (Index = 0; Index < ExtendedTableCount; Index ++) {
- CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTable, sizeof(CPU_MICROCODE_EXTENDED_TABLE));
- if (CheckSum32 == 0) {
- //
- // Verify Header
- //
- if ((ExtendedTable->ProcessorSignature.Uint32 == Eax.Uint32) &&
- (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 = (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;
- MicrocodeData = (VOID *) ((UINTN) MicrocodeEntryPoint + sizeof (CPU_MICROCODE_HEADER));
- }
-
- MicrocodeEntryPoint = (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.
- //
- ASSERT (MicrocodeData != NULL);
- AsmWriteMsr64 (
- MSR_IA32_BIOS_UPDT_TRIG,
- (UINT64) (UINTN) MicrocodeData
- );
- //
- // Get and check new microcode signature
- //
- CurrentRevision = GetCurrentMicrocodeSignature ();
- if (CurrentRevision != LatestRevision) {
- AcquireSpinLock(&CpuMpData->MpLock);
- DEBUG ((EFI_D_ERROR, "Updated microcode signature [0x%08x] does not match \
- loaded microcode signature [0x%08x]\n", CurrentRevision, LatestRevision));
- ReleaseSpinLock(&CpuMpData->MpLock);
- }
- }
-}
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c deleted file mode 100644 index 03d6c2d89e..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ /dev/null @@ -1,2126 +0,0 @@ -/** @file
- CPU MP Initialize Library common functions.
-
- Copyright (c) 2016 - 2017, 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 "MpLib.h"
-
-EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;
-
-/**
- The function will check if BSP Execute Disable is enabled.
-
- DxeIpl may have enabled Execute Disable for BSP, APs need to
- get the status and sync up the settings.
- If BSP's CR0.Paging is not set, BSP execute Disble feature is
- not working actually.
-
- @retval TRUE BSP Execute Disable is enabled.
- @retval FALSE BSP Execute Disable is not enabled.
-**/
-BOOLEAN
-IsBspExecuteDisableEnabled (
- VOID
- )
-{
- UINT32 Eax;
- CPUID_EXTENDED_CPU_SIG_EDX Edx;
- MSR_IA32_EFER_REGISTER EferMsr;
- BOOLEAN Enabled;
- IA32_CR0 Cr0;
-
- Enabled = FALSE;
- Cr0.UintN = AsmReadCr0 ();
- if (Cr0.Bits.PG != 0) {
- //
- // If CR0 Paging bit is set
- //
- AsmCpuid (CPUID_EXTENDED_FUNCTION, &Eax, NULL, NULL, NULL);
- if (Eax >= CPUID_EXTENDED_CPU_SIG) {
- AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &Edx.Uint32);
- //
- // CPUID 0x80000001
- // Bit 20: Execute Disable Bit available.
- //
- if (Edx.Bits.NX != 0) {
- EferMsr.Uint64 = AsmReadMsr64 (MSR_IA32_EFER);
- //
- // MSR 0xC0000080
- // Bit 11: Execute Disable Bit enable.
- //
- if (EferMsr.Bits.NXE != 0) {
- Enabled = TRUE;
- }
- }
- }
- }
-
- return Enabled;
-}
-
-/**
- Worker function for SwitchBSP().
-
- Worker function for SwitchBSP(), assigned to the AP which is intended
- to become BSP.
-
- @param[in] Buffer Pointer to CPU MP Data
-**/
-VOID
-EFIAPI
-FutureBSPProc (
- IN VOID *Buffer
- )
-{
- CPU_MP_DATA *DataInHob;
-
- DataInHob = (CPU_MP_DATA *) Buffer;
- AsmExchangeRole (&DataInHob->APInfo, &DataInHob->BSPInfo);
-}
-
-/**
- Get the Application Processors state.
-
- @param[in] CpuData The pointer to CPU_AP_DATA of specified AP
-
- @return The AP status
-**/
-CPU_STATE
-GetApState (
- IN CPU_AP_DATA *CpuData
- )
-{
- return CpuData->State;
-}
-
-/**
- Set the Application Processors state.
-
- @param[in] CpuData The pointer to CPU_AP_DATA of specified AP
- @param[in] State The AP status
-**/
-VOID
-SetApState (
- IN CPU_AP_DATA *CpuData,
- IN CPU_STATE State
- )
-{
- AcquireSpinLock (&CpuData->ApLock);
- CpuData->State = State;
- ReleaseSpinLock (&CpuData->ApLock);
-}
-
-/**
- Save BSP's local APIC timer setting.
-
- @param[in] CpuMpData Pointer to CPU MP Data
-**/
-VOID
-SaveLocalApicTimerSetting (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- //
- // Record the current local APIC timer setting of BSP
- //
- GetApicTimerState (
- &CpuMpData->DivideValue,
- &CpuMpData->PeriodicMode,
- &CpuMpData->Vector
- );
- CpuMpData->CurrentTimerCount = GetApicTimerCurrentCount ();
- CpuMpData->TimerInterruptState = GetApicTimerInterruptState ();
-}
-
-/**
- Sync local APIC timer setting from BSP to AP.
-
- @param[in] CpuMpData Pointer to CPU MP Data
-**/
-VOID
-SyncLocalApicTimerSetting (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- //
- // Sync local APIC timer setting from BSP to AP
- //
- InitializeApicTimer (
- CpuMpData->DivideValue,
- CpuMpData->CurrentTimerCount,
- CpuMpData->PeriodicMode,
- CpuMpData->Vector
- );
- //
- // Disable AP's local APIC timer interrupt
- //
- DisableApicTimerInterrupt ();
-}
-
-/**
- Save the volatile registers required to be restored following INIT IPI.
-
- @param[out] VolatileRegisters Returns buffer saved the volatile resisters
-**/
-VOID
-SaveVolatileRegisters (
- OUT CPU_VOLATILE_REGISTERS *VolatileRegisters
- )
-{
- CPUID_VERSION_INFO_EDX VersionInfoEdx;
-
- VolatileRegisters->Cr0 = AsmReadCr0 ();
- VolatileRegisters->Cr3 = AsmReadCr3 ();
- VolatileRegisters->Cr4 = AsmReadCr4 ();
-
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
- if (VersionInfoEdx.Bits.DE != 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[in] VolatileRegisters Pointer to volatile resisters
- @param[in] IsRestoreDr TRUE: Restore DRx if supported
- FALSE: Do not restore DRx
-**/
-VOID
-RestoreVolatileRegisters (
- IN CPU_VOLATILE_REGISTERS *VolatileRegisters,
- IN BOOLEAN IsRestoreDr
- )
-{
- CPUID_VERSION_INFO_EDX VersionInfoEdx;
-
- AsmWriteCr0 (VolatileRegisters->Cr0);
- AsmWriteCr3 (VolatileRegisters->Cr3);
- AsmWriteCr4 (VolatileRegisters->Cr4);
-
- if (IsRestoreDr) {
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
- if (VersionInfoEdx.Bits.DE != 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);
- }
- }
-}
-
-/**
- Detect whether Mwait-monitor feature is supported.
-
- @retval TRUE Mwait-monitor feature is supported.
- @retval FALSE Mwait-monitor feature is not supported.
-**/
-BOOLEAN
-IsMwaitSupport (
- VOID
- )
-{
- CPUID_VERSION_INFO_ECX VersionInfoEcx;
-
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &VersionInfoEcx.Uint32, NULL);
- return (VersionInfoEcx.Bits.MONITOR == 1) ? TRUE : FALSE;
-}
-
-/**
- Get AP loop mode.
-
- @param[out] MonitorFilterSize Returns the largest monitor-line size in bytes.
-
- @return The AP loop mode.
-**/
-UINT8
-GetApLoopMode (
- OUT UINT32 *MonitorFilterSize
- )
-{
- UINT8 ApLoopMode;
- CPUID_MONITOR_MWAIT_EBX MonitorMwaitEbx;
-
- ASSERT (MonitorFilterSize != NULL);
-
- ApLoopMode = PcdGet8 (PcdCpuApLoopMode);
- ASSERT (ApLoopMode >= ApInHltLoop && ApLoopMode <= ApInRunLoop);
- if (ApLoopMode == ApInMwaitLoop) {
- if (!IsMwaitSupport ()) {
- //
- // If processor does not support MONITOR/MWAIT feature,
- // force AP in Hlt-loop mode
- //
- ApLoopMode = ApInHltLoop;
- }
- }
-
- if (ApLoopMode != ApInMwaitLoop) {
- *MonitorFilterSize = sizeof (UINT32);
- } else {
- //
- // 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, &MonitorMwaitEbx.Uint32, NULL, NULL);
- *MonitorFilterSize = MonitorMwaitEbx.Bits.LargestMonitorLineSize;
- }
-
- return ApLoopMode;
-}
-
-/**
- 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[in] CpuMpData Pointer to PEI CPU MP Data
-**/
-VOID
-SortApicId (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- UINTN Index1;
- UINTN Index2;
- UINTN Index3;
- UINT32 ApicId;
- CPU_INFO_IN_HOB CpuInfo;
- UINT32 ApCount;
- CPU_INFO_IN_HOB *CpuInfoInHob;
-
- ApCount = CpuMpData->CpuCount - 1;
- CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;
- if (ApCount != 0) {
- for (Index1 = 0; Index1 < ApCount; Index1++) {
- Index3 = Index1;
- //
- // Sort key is the hardware default APIC ID
- //
- ApicId = CpuInfoInHob[Index1].ApicId;
- for (Index2 = Index1 + 1; Index2 <= ApCount; Index2++) {
- if (ApicId > CpuInfoInHob[Index2].ApicId) {
- Index3 = Index2;
- ApicId = CpuInfoInHob[Index2].ApicId;
- }
- }
- if (Index3 != Index1) {
- CopyMem (&CpuInfo, &CpuInfoInHob[Index3], sizeof (CPU_INFO_IN_HOB));
- CopyMem (
- &CpuInfoInHob[Index3],
- &CpuInfoInHob[Index1],
- sizeof (CPU_INFO_IN_HOB)
- );
- CopyMem (&CpuInfoInHob[Index1], &CpuInfo, sizeof (CPU_INFO_IN_HOB));
- }
- }
-
- //
- // Get the processor number for the BSP
- //
- ApicId = GetInitialApicId ();
- for (Index1 = 0; Index1 < CpuMpData->CpuCount; Index1++) {
- if (CpuInfoInHob[Index1].ApicId == ApicId) {
- CpuMpData->BspNumber = (UINT32) Index1;
- break;
- }
- }
- }
-}
-
-/**
- Enable x2APIC mode on APs.
-
- @param[in, out] Buffer Pointer to private data buffer.
-**/
-VOID
-EFIAPI
-ApFuncEnableX2Apic (
- IN OUT VOID *Buffer
- )
-{
- SetApicMode (LOCAL_APIC_MODE_X2APIC);
-}
-
-/**
- Do sync on APs.
-
- @param[in, out] Buffer Pointer to private data buffer.
-**/
-VOID
-EFIAPI
-ApInitializeSync (
- IN OUT VOID *Buffer
- )
-{
- CPU_MP_DATA *CpuMpData;
-
- CpuMpData = (CPU_MP_DATA *) Buffer;
- //
- // Load microcode on AP
- //
- MicrocodeDetect (CpuMpData);
- //
- // Sync BSP's MTRR table to AP
- //
- MtrrSetAllMtrrs (&CpuMpData->MtrrTable);
-}
-
-/**
- Find the current Processor number by APIC ID.
-
- @param[in] CpuMpData Pointer to PEI CPU MP Data
- @param[out] ProcessorNumber Return the pocessor number found
-
- @retval EFI_SUCCESS ProcessorNumber is found and returned.
- @retval EFI_NOT_FOUND ProcessorNumber is not found.
-**/
-EFI_STATUS
-GetProcessorNumber (
- IN CPU_MP_DATA *CpuMpData,
- OUT UINTN *ProcessorNumber
- )
-{
- UINTN TotalProcessorNumber;
- UINTN Index;
- CPU_INFO_IN_HOB *CpuInfoInHob;
-
- CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;
-
- TotalProcessorNumber = CpuMpData->CpuCount;
- for (Index = 0; Index < TotalProcessorNumber; Index ++) {
- if (CpuInfoInHob[Index].ApicId == GetApicId ()) {
- *ProcessorNumber = Index;
- return EFI_SUCCESS;
- }
- }
- return EFI_NOT_FOUND;
-}
-
-/**
- This function will get CPU count in the system.
-
- @param[in] CpuMpData Pointer to PEI CPU MP Data
-
- @return CPU count detected
-**/
-UINTN
-CollectProcessorCount (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- //
- // Send 1st broadcast IPI to APs to wakeup APs
- //
- CpuMpData->InitFlag = ApInitConfig;
- CpuMpData->X2ApicEnable = FALSE;
- WakeUpAP (CpuMpData, TRUE, 0, NULL, NULL);
- CpuMpData->InitFlag = ApInitDone;
- ASSERT (CpuMpData->CpuCount <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
- //
- // Wait for all APs finished the initialization
- //
- while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) {
- CpuPause ();
- }
-
- if (CpuMpData->X2ApicEnable) {
- DEBUG ((DEBUG_INFO, "Force x2APIC mode!\n"));
- //
- // Wakeup all APs to enable x2APIC mode
- //
- WakeUpAP (CpuMpData, TRUE, 0, ApFuncEnableX2Apic, NULL);
- //
- // Wait for all known APs finished
- //
- while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) {
- CpuPause ();
- }
- //
- // Enable x2APIC on BSP
- //
- SetApicMode (LOCAL_APIC_MODE_X2APIC);
- }
- DEBUG ((DEBUG_INFO, "APIC MODE is %d\n", GetApicMode ()));
- //
- // Sort BSP/Aps by CPU APIC ID in ascending order
- //
- SortApicId (CpuMpData);
-
- DEBUG ((DEBUG_INFO, "MpInitLib: Find %d processors in system.\n", CpuMpData->CpuCount));
-
- return CpuMpData->CpuCount;
-}
-
-/**
- Initialize CPU AP Data when AP is wakeup at the first time.
-
- @param[in, out] CpuMpData Pointer to PEI CPU MP Data
- @param[in] ProcessorNumber The handle number of processor
- @param[in] BistData Processor BIST data
- @param[in] ApTopOfStack Top of AP stack
-
-**/
-VOID
-InitializeApData (
- IN OUT CPU_MP_DATA *CpuMpData,
- IN UINTN ProcessorNumber,
- IN UINT32 BistData,
- IN UINT64 ApTopOfStack
- )
-{
- CPU_INFO_IN_HOB *CpuInfoInHob;
-
- CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;
- CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId ();
- CpuInfoInHob[ProcessorNumber].ApicId = GetApicId ();
- CpuInfoInHob[ProcessorNumber].Health = BistData;
- CpuInfoInHob[ProcessorNumber].ApTopOfStack = ApTopOfStack;
-
- CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
- CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;
- if (CpuInfoInHob[ProcessorNumber].InitialApicId >= 0xFF) {
- //
- // Set x2APIC mode if there are any logical processor reporting
- // an Initial APIC ID of 255 or greater.
- //
- AcquireSpinLock(&CpuMpData->MpLock);
- CpuMpData->X2ApicEnable = TRUE;
- ReleaseSpinLock(&CpuMpData->MpLock);
- }
-
- InitializeSpinLock(&CpuMpData->CpuData[ProcessorNumber].ApLock);
- SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
-}
-
-/**
- This function will be called from AP reset code if BSP uses WakeUpAP.
-
- @param[in] ExchangeInfo Pointer to the MP exchange info buffer
- @param[in] NumApsExecuting Number of current executing AP
-**/
-VOID
-EFIAPI
-ApWakeupFunction (
- IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,
- IN UINTN NumApsExecuting
- )
-{
- CPU_MP_DATA *CpuMpData;
- UINTN ProcessorNumber;
- EFI_AP_PROCEDURE Procedure;
- VOID *Parameter;
- UINT32 BistData;
- volatile UINT32 *ApStartupSignalBuffer;
- CPU_INFO_IN_HOB *CpuInfoInHob;
- UINT64 ApTopOfStack;
-
- //
- // AP finished assembly code and begin to execute C code
- //
- CpuMpData = ExchangeInfo->CpuMpData;
-
- //
- // AP's local APIC settings will be lost after received INIT IPI
- // We need to re-initialize them at here
- //
- ProgramVirtualWireMode ();
- SyncLocalApicTimerSetting (CpuMpData);
-
- while (TRUE) {
- if (CpuMpData->InitFlag == ApInitConfig) {
- //
- // Add CPU number
- //
- InterlockedIncrement ((UINT32 *) &CpuMpData->CpuCount);
- ProcessorNumber = NumApsExecuting;
- //
- // This is first time AP wakeup, get BIST information from AP stack
- //
- ApTopOfStack = CpuMpData->Buffer + (ProcessorNumber + 1) * CpuMpData->CpuApStackSize;
- BistData = *(UINT32 *) ((UINTN) ApTopOfStack - sizeof (UINTN));
- //
- // Do some AP initialize sync
- //
- ApInitializeSync (CpuMpData);
- //
- // Sync BSP's Control registers to APs
- //
- RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE);
- InitializeApData (CpuMpData, ProcessorNumber, BistData, ApTopOfStack);
- ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
- } else {
- //
- // Execute AP function if AP is ready
- //
- GetProcessorNumber (CpuMpData, &ProcessorNumber);
- //
- // Clear AP start-up signal when AP waken up
- //
- ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
- InterlockedCompareExchange32 (
- (UINT32 *) ApStartupSignalBuffer,
- WAKEUP_AP_SIGNAL,
- 0
- );
- if (CpuMpData->ApLoopMode == ApInHltLoop) {
- //
- // Restore AP's volatile registers saved
- //
- RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);
- }
-
- if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateReady) {
- Procedure = (EFI_AP_PROCEDURE)CpuMpData->CpuData[ProcessorNumber].ApFunction;
- Parameter = (VOID *) CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument;
- if (Procedure != NULL) {
- SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateBusy);
- //
- // Enable source debugging on AP function
- //
- EnableDebugAgent ();
- //
- // Invoke AP function here
- //
- Procedure (Parameter);
- CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;
- if (CpuMpData->SwitchBspFlag) {
- //
- // Re-get the processor number due to BSP/AP maybe exchange in AP function
- //
- GetProcessorNumber (CpuMpData, &ProcessorNumber);
- CpuMpData->CpuData[ProcessorNumber].ApFunction = 0;
- CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument = 0;
- 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 ();
- }
- }
- SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished);
- }
- }
-
- //
- // AP finished executing C code
- //
- InterlockedIncrement ((UINT32 *) &CpuMpData->FinishedCount);
-
- //
- // Place AP is specified loop mode
- //
- if (CpuMpData->ApLoopMode == ApInHltLoop) {
- //
- // Save AP volatile registers
- //
- SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
- //
- // Place AP in HLT-loop
- //
- while (TRUE) {
- DisableInterrupts ();
- CpuSleep ();
- CpuPause ();
- }
- }
- while (TRUE) {
- DisableInterrupts ();
- if (CpuMpData->ApLoopMode == ApInMwaitLoop) {
- //
- // Place AP in MWAIT-loop
- //
- AsmMonitor ((UINTN) ApStartupSignalBuffer, 0, 0);
- if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) {
- //
- // Check AP start-up signal again.
- // If AP start-up signal is not set, place AP into
- // the specified C-state
- //
- AsmMwait (CpuMpData->ApTargetCState << 4, 0);
- }
- } else if (CpuMpData->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) {
- break;
- }
- }
- }
-}
-
-/**
- Wait for AP wakeup and write AP start-up signal till AP is waken up.
-
- @param[in] ApStartupSignalBuffer Pointer to AP wakeup signal
-**/
-VOID
-WaitApWakeup (
- IN volatile UINT32 *ApStartupSignalBuffer
- )
-{
- //
- // 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 fill the exchange info structure.
-
- @param[in] CpuMpData Pointer to CPU MP Data
-
-**/
-VOID
-FillExchangeInfoData (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;
-
- ExchangeInfo = CpuMpData->MpCpuExchangeInfo;
- ExchangeInfo->Lock = 0;
- ExchangeInfo->StackStart = CpuMpData->Buffer;
- ExchangeInfo->StackSize = CpuMpData->CpuApStackSize;
- ExchangeInfo->BufferStart = CpuMpData->WakeupBuffer;
- ExchangeInfo->ModeOffset = CpuMpData->AddressMap.ModeEntryOffset;
-
- ExchangeInfo->CodeSegment = AsmReadCs ();
- ExchangeInfo->DataSegment = AsmReadDs ();
-
- ExchangeInfo->Cr3 = AsmReadCr3 ();
-
- ExchangeInfo->CFunction = (UINTN) ApWakeupFunction;
- ExchangeInfo->NumApsExecuting = 0;
- ExchangeInfo->InitFlag = (UINTN) CpuMpData->InitFlag;
- ExchangeInfo->CpuInfo = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;
- ExchangeInfo->CpuMpData = CpuMpData;
-
- ExchangeInfo->EnableExecuteDisable = IsBspExecuteDisableEnabled ();
-
- //
- // Get the BSP's data of GDT and IDT
- //
- AsmReadGdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->GdtrProfile);
- AsmReadIdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->IdtrProfile);
-}
-
-/**
- Helper function that waits until the finished AP count reaches the specified
- limit, or the specified timeout elapses (whichever comes first).
-
- @param[in] CpuMpData Pointer to CPU MP Data.
- @param[in] FinishedApLimit The number of finished APs to wait for.
- @param[in] TimeLimit The number of microseconds to wait for.
-**/
-VOID
-TimedWaitForApFinish (
- IN CPU_MP_DATA *CpuMpData,
- IN UINT32 FinishedApLimit,
- IN UINT32 TimeLimit
- );
-
-/**
- This function will be called by BSP to wakeup AP.
-
- @param[in] CpuMpData Pointer to CPU MP Data
- @param[in] Broadcast TRUE: Send broadcast IPI to all APs
- FALSE: Send IPI to AP by ApicId
- @param[in] ProcessorNumber The handle number of specified processor
- @param[in] Procedure The function to be invoked by AP
- @param[in] ProcedureArgument The argument to be passed into AP function
-**/
-VOID
-WakeUpAP (
- IN CPU_MP_DATA *CpuMpData,
- IN BOOLEAN Broadcast,
- IN UINTN ProcessorNumber,
- IN EFI_AP_PROCEDURE Procedure, OPTIONAL
- IN VOID *ProcedureArgument OPTIONAL
- )
-{
- volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;
- UINTN Index;
- CPU_AP_DATA *CpuData;
- BOOLEAN ResetVectorRequired;
- CPU_INFO_IN_HOB *CpuInfoInHob;
-
- CpuMpData->FinishedCount = 0;
- ResetVectorRequired = FALSE;
-
- if (CpuMpData->ApLoopMode == ApInHltLoop ||
- CpuMpData->InitFlag != ApInitDone) {
- ResetVectorRequired = TRUE;
- AllocateResetVector (CpuMpData);
- FillExchangeInfoData (CpuMpData);
- SaveLocalApicTimerSetting (CpuMpData);
- } else if (CpuMpData->ApLoopMode == ApInMwaitLoop) {
- //
- // Get AP target C-state each time when waking up AP,
- // for it maybe updated by platform again
- //
- CpuMpData->ApTargetCState = PcdGet8 (PcdCpuApTargetCstate);
- }
-
- ExchangeInfo = CpuMpData->MpCpuExchangeInfo;
-
- if (Broadcast) {
- for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
- if (Index != CpuMpData->BspNumber) {
- CpuData = &CpuMpData->CpuData[Index];
- CpuData->ApFunction = (UINTN) Procedure;
- CpuData->ApFunctionArgument = (UINTN) ProcedureArgument;
- SetApState (CpuData, CpuStateReady);
- if (CpuMpData->InitFlag != ApInitConfig) {
- *(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
- }
- }
- }
- if (ResetVectorRequired) {
- //
- // Wakeup all APs
- //
- SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart);
- }
- if (CpuMpData->InitFlag == ApInitConfig) {
- //
- // Wait for all potential APs waken up in one specified period
- //
- TimedWaitForApFinish (
- CpuMpData,
- PcdGet32 (PcdCpuMaxLogicalProcessorNumber) - 1,
- PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds)
- );
- } else {
- //
- // Wait all APs waken up if this is not the 1st broadcast of SIPI
- //
- for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
- CpuData = &CpuMpData->CpuData[Index];
- if (Index != CpuMpData->BspNumber) {
- WaitApWakeup (CpuData->StartupApSignal);
- }
- }
- }
- } else {
- CpuData = &CpuMpData->CpuData[ProcessorNumber];
- CpuData->ApFunction = (UINTN) Procedure;
- CpuData->ApFunctionArgument = (UINTN) ProcedureArgument;
- SetApState (CpuData, CpuStateReady);
- //
- // Wakeup specified AP
- //
- ASSERT (CpuMpData->InitFlag != ApInitConfig);
- *(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
- if (ResetVectorRequired) {
- CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;
- SendInitSipiSipi (
- CpuInfoInHob[ProcessorNumber].ApicId,
- (UINT32) ExchangeInfo->BufferStart
- );
- }
- //
- // Wait specified AP waken up
- //
- WaitApWakeup (CpuData->StartupApSignal);
- }
-
- if (ResetVectorRequired) {
- FreeResetVector (CpuMpData);
- }
-}
-
-/**
- Calculate timeout value and return the current performance counter value.
-
- Calculate the number of performance counter ticks required for a timeout.
- If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
- as infinity.
-
- @param[in] TimeoutInMicroseconds Timeout value in microseconds.
- @param[out] CurrentTime Returns the current value of the performance counter.
-
- @return Expected time stamp counter for timeout.
- If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
- as infinity.
-
-**/
-UINT64
-CalculateTimeout (
- IN UINTN TimeoutInMicroseconds,
- OUT UINT64 *CurrentTime
- )
-{
- //
- // Read the current value of the performance counter
- //
- *CurrentTime = GetPerformanceCounter ();
-
- //
- // If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
- // as infinity.
- //
- if (TimeoutInMicroseconds == 0) {
- return 0;
- }
-
- //
- // 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
- );
-}
-
-/**
- Checks whether timeout expires.
-
- Check whether the number of elapsed performance counter ticks required for
- a timeout condition has been reached.
- If Timeout is zero, which means infinity, return value is always FALSE.
-
- @param[in, out] PreviousTime On input, the value of the performance counter
- when it was last read.
- On output, the current value of the performance
- counter
- @param[in] TotalTime The total amount of elapsed time in performance
- counter ticks.
- @param[in] Timeout The number of performance counter ticks required
- to reach a timeout condition.
-
- @retval TRUE A timeout condition has been reached.
- @retval FALSE A timeout condition has not been reached.
-
-**/
-BOOLEAN
-CheckTimeout (
- IN OUT UINT64 *PreviousTime,
- IN UINT64 *TotalTime,
- IN UINT64 Timeout
- )
-{
- UINT64 Start;
- UINT64 End;
- UINT64 CurrentTime;
- INT64 Delta;
- INT64 Cycle;
-
- if (Timeout == 0) {
- return FALSE;
- }
- GetPerformanceCounterProperties (&Start, &End);
- Cycle = End - Start;
- if (Cycle < 0) {
- Cycle = -Cycle;
- }
- Cycle++;
- CurrentTime = GetPerformanceCounter();
- Delta = (INT64) (CurrentTime - *PreviousTime);
- if (Start > End) {
- Delta = -Delta;
- }
- if (Delta < 0) {
- Delta += Cycle;
- }
- *TotalTime += Delta;
- *PreviousTime = CurrentTime;
- if (*TotalTime > Timeout) {
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- Helper function that waits until the finished AP count reaches the specified
- limit, or the specified timeout elapses (whichever comes first).
-
- @param[in] CpuMpData Pointer to CPU MP Data.
- @param[in] FinishedApLimit The number of finished APs to wait for.
- @param[in] TimeLimit The number of microseconds to wait for.
-**/
-VOID
-TimedWaitForApFinish (
- IN CPU_MP_DATA *CpuMpData,
- IN UINT32 FinishedApLimit,
- IN UINT32 TimeLimit
- )
-{
- //
- // CalculateTimeout() and CheckTimeout() consider a TimeLimit of 0
- // "infinity", so check for (TimeLimit == 0) explicitly.
- //
- if (TimeLimit == 0) {
- return;
- }
-
- CpuMpData->TotalTime = 0;
- CpuMpData->ExpectedTime = CalculateTimeout (
- TimeLimit,
- &CpuMpData->CurrentTime
- );
- while (CpuMpData->FinishedCount < FinishedApLimit &&
- !CheckTimeout (
- &CpuMpData->CurrentTime,
- &CpuMpData->TotalTime,
- CpuMpData->ExpectedTime
- )) {
- CpuPause ();
- }
-
- if (CpuMpData->FinishedCount >= FinishedApLimit) {
- DEBUG ((
- DEBUG_VERBOSE,
- "%a: reached FinishedApLimit=%u in %Lu microseconds\n",
- __FUNCTION__,
- FinishedApLimit,
- DivU64x64Remainder (
- MultU64x32 (CpuMpData->TotalTime, 1000000),
- GetPerformanceCounterProperties (NULL, NULL),
- NULL
- )
- ));
- }
-}
-
-/**
- Reset an AP to Idle state.
-
- Any task being executed by the AP will be aborted and the AP
- will be waiting for a new task in Wait-For-SIPI state.
-
- @param[in] ProcessorNumber The handle number of processor.
-**/
-VOID
-ResetProcessorToIdleState (
- IN UINTN ProcessorNumber
- )
-{
- CPU_MP_DATA *CpuMpData;
-
- CpuMpData = GetCpuMpData ();
-
- CpuMpData->InitFlag = ApInitReconfig;
- WakeUpAP (CpuMpData, FALSE, ProcessorNumber, NULL, NULL);
- while (CpuMpData->FinishedCount < 1) {
- CpuPause ();
- }
- CpuMpData->InitFlag = ApInitDone;
-
- SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
-}
-
-/**
- Searches for the next waiting AP.
-
- Search for the next AP that is put in waiting state by single-threaded StartupAllAPs().
-
- @param[out] NextProcessorNumber Pointer to the processor number of the next waiting AP.
-
- @retval EFI_SUCCESS The next waiting AP has been found.
- @retval EFI_NOT_FOUND No waiting AP exists.
-
-**/
-EFI_STATUS
-GetNextWaitingProcessorNumber (
- OUT UINTN *NextProcessorNumber
- )
-{
- UINTN ProcessorNumber;
- CPU_MP_DATA *CpuMpData;
-
- CpuMpData = GetCpuMpData ();
-
- for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) {
- if (CpuMpData->CpuData[ProcessorNumber].Waiting) {
- *NextProcessorNumber = ProcessorNumber;
- return EFI_SUCCESS;
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/** Checks status of specified AP.
-
- This function checks whether the specified AP has finished the task assigned
- by StartupThisAP(), and whether timeout expires.
-
- @param[in] ProcessorNumber The handle number of processor.
-
- @retval EFI_SUCCESS Specified AP has finished task assigned by StartupThisAPs().
- @retval EFI_TIMEOUT The timeout expires.
- @retval EFI_NOT_READY Specified AP has not finished task and timeout has not expired.
-**/
-EFI_STATUS
-CheckThisAP (
- IN UINTN ProcessorNumber
- )
-{
- CPU_MP_DATA *CpuMpData;
- CPU_AP_DATA *CpuData;
-
- CpuMpData = GetCpuMpData ();
- CpuData = &CpuMpData->CpuData[ProcessorNumber];
-
- //
- // Check the CPU state of AP. If it is CpuStateFinished, then the AP has finished its task.
- // Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the
- // value of state after setting the it to CpuStateFinished, so BSP can safely make use of its value.
- //
- //
- // If the AP finishes for StartupThisAP(), return EFI_SUCCESS.
- //
- if (GetApState(CpuData) == CpuStateFinished) {
- if (CpuData->Finished != NULL) {
- *(CpuData->Finished) = TRUE;
- }
- SetApState (CpuData, CpuStateIdle);
- return EFI_SUCCESS;
- } else {
- //
- // If timeout expires for StartupThisAP(), report timeout.
- //
- if (CheckTimeout (&CpuData->CurrentTime, &CpuData->TotalTime, CpuData->ExpectedTime)) {
- if (CpuData->Finished != NULL) {
- *(CpuData->Finished) = FALSE;
- }
- //
- // Reset failed AP to idle state
- //
- ResetProcessorToIdleState (ProcessorNumber);
-
- return EFI_TIMEOUT;
- }
- }
- return EFI_NOT_READY;
-}
-
-/**
- Checks status of all APs.
-
- This function checks whether all APs have finished task assigned by StartupAllAPs(),
- and whether timeout expires.
-
- @retval EFI_SUCCESS All APs have finished task assigned by StartupAllAPs().
- @retval EFI_TIMEOUT The timeout expires.
- @retval EFI_NOT_READY APs have not finished task and timeout has not expired.
-**/
-EFI_STATUS
-CheckAllAPs (
- VOID
- )
-{
- UINTN ProcessorNumber;
- UINTN NextProcessorNumber;
- UINTN ListIndex;
- EFI_STATUS Status;
- CPU_MP_DATA *CpuMpData;
- CPU_AP_DATA *CpuData;
-
- CpuMpData = GetCpuMpData ();
-
- NextProcessorNumber = 0;
-
- //
- // Go through all APs that are responsible for the StartupAllAPs().
- //
- for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) {
- if (!CpuMpData->CpuData[ProcessorNumber].Waiting) {
- continue;
- }
-
- CpuData = &CpuMpData->CpuData[ProcessorNumber];
- //
- // Check the CPU state of AP. If it is CpuStateFinished, then the AP has finished its task.
- // Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the
- // value of state after setting the it to CpuStateFinished, so BSP can safely make use of its value.
- //
- if (GetApState(CpuData) == CpuStateFinished) {
- CpuMpData->RunningCount ++;
- CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
- SetApState(CpuData, CpuStateIdle);
-
- //
- // If in Single Thread mode, then search for the next waiting AP for execution.
- //
- if (CpuMpData->SingleThread) {
- Status = GetNextWaitingProcessorNumber (&NextProcessorNumber);
-
- if (!EFI_ERROR (Status)) {
- WakeUpAP (
- CpuMpData,
- FALSE,
- (UINT32) NextProcessorNumber,
- CpuMpData->Procedure,
- CpuMpData->ProcArguments
- );
- }
- }
- }
- }
-
- //
- // If all APs finish, return EFI_SUCCESS.
- //
- if (CpuMpData->RunningCount == CpuMpData->StartCount) {
- return EFI_SUCCESS;
- }
-
- //
- // If timeout expires, report timeout.
- //
- if (CheckTimeout (
- &CpuMpData->CurrentTime,
- &CpuMpData->TotalTime,
- CpuMpData->ExpectedTime)
- ) {
- //
- // If FailedCpuList is not NULL, record all failed APs in it.
- //
- if (CpuMpData->FailedCpuList != NULL) {
- *CpuMpData->FailedCpuList =
- AllocatePool ((CpuMpData->StartCount - CpuMpData->FinishedCount + 1) * sizeof (UINTN));
- ASSERT (*CpuMpData->FailedCpuList != NULL);
- }
- ListIndex = 0;
-
- for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) {
- //
- // Check whether this processor is responsible for StartupAllAPs().
- //
- if (CpuMpData->CpuData[ProcessorNumber].Waiting) {
- //
- // Reset failed APs to idle state
- //
- ResetProcessorToIdleState (ProcessorNumber);
- CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
- if (CpuMpData->FailedCpuList != NULL) {
- (*CpuMpData->FailedCpuList)[ListIndex++] = ProcessorNumber;
- }
- }
- }
- if (CpuMpData->FailedCpuList != NULL) {
- (*CpuMpData->FailedCpuList)[ListIndex] = END_OF_CPU_LIST;
- }
- return EFI_TIMEOUT;
- }
- return EFI_NOT_READY;
-}
-
-/**
- MP Initialize Library initialization.
-
- This service will allocate AP reset vector and wakeup all APs to do APs
- initialization.
-
- This service must be invoked before all other MP Initialize Library
- service are invoked.
-
- @retval EFI_SUCCESS MP initialization succeeds.
- @retval Others MP initialization fails.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibInitialize (
- VOID
- )
-{
- CPU_MP_DATA *OldCpuMpData;
- CPU_INFO_IN_HOB *CpuInfoInHob;
- UINT32 MaxLogicalProcessorNumber;
- UINT32 ApStackSize;
- MP_ASSEMBLY_ADDRESS_MAP AddressMap;
- UINTN BufferSize;
- UINT32 MonitorFilterSize;
- VOID *MpBuffer;
- UINTN Buffer;
- CPU_MP_DATA *CpuMpData;
- UINT8 ApLoopMode;
- UINT8 *MonitorBuffer;
- UINTN Index;
- UINTN ApResetVectorSize;
- UINTN BackupBufferAddr;
-
- OldCpuMpData = GetCpuMpDataFromGuidedHob ();
- if (OldCpuMpData == NULL) {
- MaxLogicalProcessorNumber = PcdGet32(PcdCpuMaxLogicalProcessorNumber);
- } else {
- MaxLogicalProcessorNumber = OldCpuMpData->CpuCount;
- }
- ASSERT (MaxLogicalProcessorNumber != 0);
-
- AsmGetAddressMap (&AddressMap);
- ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO);
- ApStackSize = PcdGet32(PcdCpuApStackSize);
- ApLoopMode = GetApLoopMode (&MonitorFilterSize);
-
- BufferSize = ApStackSize * MaxLogicalProcessorNumber;
- BufferSize += MonitorFilterSize * MaxLogicalProcessorNumber;
- BufferSize += sizeof (CPU_MP_DATA);
- BufferSize += ApResetVectorSize;
- BufferSize += (sizeof (CPU_AP_DATA) + sizeof (CPU_INFO_IN_HOB))* MaxLogicalProcessorNumber;
- MpBuffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));
- ASSERT (MpBuffer != NULL);
- ZeroMem (MpBuffer, BufferSize);
- Buffer = (UINTN) MpBuffer;
-
- MonitorBuffer = (UINT8 *) (Buffer + ApStackSize * MaxLogicalProcessorNumber);
- BackupBufferAddr = (UINTN) MonitorBuffer + MonitorFilterSize * MaxLogicalProcessorNumber;
- CpuMpData = (CPU_MP_DATA *) (BackupBufferAddr + ApResetVectorSize);
- CpuMpData->Buffer = Buffer;
- CpuMpData->CpuApStackSize = ApStackSize;
- CpuMpData->BackupBuffer = BackupBufferAddr;
- CpuMpData->BackupBufferSize = ApResetVectorSize;
- CpuMpData->SaveRestoreFlag = FALSE;
- CpuMpData->WakeupBuffer = (UINTN) -1;
- CpuMpData->CpuCount = 1;
- CpuMpData->BspNumber = 0;
- CpuMpData->WaitEvent = NULL;
- CpuMpData->SwitchBspFlag = FALSE;
- CpuMpData->CpuData = (CPU_AP_DATA *) (CpuMpData + 1);
- CpuMpData->CpuInfoInHob = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber);
- InitializeSpinLock(&CpuMpData->MpLock);
- //
- // Save BSP's Control registers to APs
- //
- SaveVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters);
- //
- // Set BSP basic information
- //
- InitializeApData (CpuMpData, 0, 0, CpuMpData->Buffer);
- //
- // Save assembly code information
- //
- CopyMem (&CpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP));
- //
- // Finally set AP loop mode
- //
- CpuMpData->ApLoopMode = ApLoopMode;
- DEBUG ((DEBUG_INFO, "AP Loop Mode is %d\n", CpuMpData->ApLoopMode));
- //
- // Set up APs wakeup signal buffer
- //
- for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) {
- CpuMpData->CpuData[Index].StartupApSignal =
- (UINT32 *)(MonitorBuffer + MonitorFilterSize * Index);
- }
- //
- // Load Microcode on BSP
- //
- MicrocodeDetect (CpuMpData);
- //
- // Store BSP's MTRR setting
- //
- MtrrGetAllMtrrs (&CpuMpData->MtrrTable);
-
- if (OldCpuMpData == NULL) {
- if (MaxLogicalProcessorNumber > 1) {
- //
- // Wakeup all APs and calculate the processor count in system
- //
- CollectProcessorCount (CpuMpData);
- }
- } else {
- //
- // APs have been wakeup before, just get the CPU Information
- // from HOB
- //
- CpuMpData->CpuCount = OldCpuMpData->CpuCount;
- CpuMpData->BspNumber = OldCpuMpData->BspNumber;
- CpuMpData->InitFlag = ApInitReconfig;
- CpuMpData->CpuInfoInHob = OldCpuMpData->CpuInfoInHob;
- 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) {
- CpuMpData->X2ApicEnable = TRUE;
- }
- CpuMpData->CpuData[Index].CpuHealthy = (CpuInfoInHob[Index].Health == 0)? TRUE:FALSE;
- CpuMpData->CpuData[Index].ApFunction = 0;
- CopyMem (
- &CpuMpData->CpuData[Index].VolatileRegisters,
- &CpuMpData->CpuData[0].VolatileRegisters,
- sizeof (CPU_VOLATILE_REGISTERS)
- );
- }
- if (MaxLogicalProcessorNumber > 1) {
- //
- // Wakeup APs to do some AP initialize sync
- //
- WakeUpAP (CpuMpData, TRUE, 0, ApInitializeSync, CpuMpData);
- //
- // Wait for all APs finished initialization
- //
- while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) {
- CpuPause ();
- }
- CpuMpData->InitFlag = ApInitDone;
- for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
- SetApState (&CpuMpData->CpuData[Index], CpuStateIdle);
- }
- }
- }
-
- //
- // Initialize global data for MP support
- //
- InitMpGlobalData (CpuMpData);
-
- return EFI_SUCCESS;
-}
-
-/**
- Gets detailed MP-related information on the requested processor at the
- instant this call is made. This service may only be called from the BSP.
-
- @param[in] ProcessorNumber The handle number of processor.
- @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
- the requested processor is deposited.
- @param[out] HealthData Return processor health data.
-
- @retval EFI_SUCCESS Processor information was returned.
- @retval EFI_DEVICE_ERROR The calling processor is an AP.
- @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
- @retval EFI_NOT_FOUND The processor with the handle specified by
- ProcessorNumber does not exist in the platform.
- @retval EFI_NOT_READY MP Initialize Library is not initialized.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibGetProcessorInfo (
- IN UINTN ProcessorNumber,
- OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer,
- OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL
- )
-{
- CPU_MP_DATA *CpuMpData;
- UINTN CallerNumber;
- CPU_INFO_IN_HOB *CpuInfoInHob;
-
- CpuMpData = GetCpuMpData ();
- CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;
-
- //
- // Check whether caller processor is BSP
- //
- MpInitLibWhoAmI (&CallerNumber);
- if (CallerNumber != CpuMpData->BspNumber) {
- return EFI_DEVICE_ERROR;
- }
-
- if (ProcessorInfoBuffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (ProcessorNumber >= CpuMpData->CpuCount) {
- return EFI_NOT_FOUND;
- }
-
- ProcessorInfoBuffer->ProcessorId = (UINT64) CpuInfoInHob[ProcessorNumber].ApicId;
- ProcessorInfoBuffer->StatusFlag = 0;
- if (ProcessorNumber == CpuMpData->BspNumber) {
- ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;
- }
- if (CpuMpData->CpuData[ProcessorNumber].CpuHealthy) {
- ProcessorInfoBuffer->StatusFlag |= PROCESSOR_HEALTH_STATUS_BIT;
- }
- if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateDisabled) {
- ProcessorInfoBuffer->StatusFlag &= ~PROCESSOR_ENABLED_BIT;
- } else {
- ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT;
- }
-
- //
- // Get processor location information
- //
- GetProcessorLocationByApicId (
- CpuInfoInHob[ProcessorNumber].ApicId,
- &ProcessorInfoBuffer->Location.Package,
- &ProcessorInfoBuffer->Location.Core,
- &ProcessorInfoBuffer->Location.Thread
- );
-
- if (HealthData != NULL) {
- HealthData->Uint32 = CpuInfoInHob[ProcessorNumber].Health;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Worker function to switch the requested AP to be the BSP from that point onward.
-
- @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
- @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
- enabled AP. Otherwise, it will be disabled.
-
- @retval EFI_SUCCESS BSP successfully switched.
- @retval others Failed to switch BSP.
-
-**/
-EFI_STATUS
-SwitchBSPWorker (
- IN UINTN ProcessorNumber,
- IN BOOLEAN EnableOldBSP
- )
-{
- CPU_MP_DATA *CpuMpData;
- UINTN CallerNumber;
- CPU_STATE State;
- MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;
- BOOLEAN OldInterruptState;
- BOOLEAN OldTimerInterruptState;
-
- //
- // Save and Disable Local APIC timer interrupt
- //
- OldTimerInterruptState = GetApicTimerInterruptState ();
- DisableApicTimerInterrupt ();
- //
- // Before send both BSP and AP to a procedure to exchange their roles,
- // interrupt must be disabled. This is because during the exchange role
- // process, 2 CPU may use 1 stack. If interrupt happens, the stack will
- // be corrupted, since interrupt return address will be pushed to stack
- // by hardware.
- //
- OldInterruptState = SaveAndDisableInterrupts ();
-
- //
- // Mask LINT0 & LINT1 for the old BSP
- //
- DisableLvtInterrupts ();
-
- CpuMpData = GetCpuMpData ();
-
- //
- // Check whether caller processor is BSP
- //
- MpInitLibWhoAmI (&CallerNumber);
- if (CallerNumber != CpuMpData->BspNumber) {
- return EFI_SUCCESS;
- }
-
- if (ProcessorNumber >= CpuMpData->CpuCount) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Check whether specified AP is disabled
- //
- State = GetApState (&CpuMpData->CpuData[ProcessorNumber]);
- if (State == CpuStateDisabled) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Check whether ProcessorNumber specifies the current BSP
- //
- if (ProcessorNumber == CpuMpData->BspNumber) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Check whether specified AP is busy
- //
- if (State == CpuStateBusy) {
- return EFI_NOT_READY;
- }
-
- CpuMpData->BSPInfo.State = CPU_SWITCH_STATE_IDLE;
- CpuMpData->APInfo.State = CPU_SWITCH_STATE_IDLE;
- CpuMpData->SwitchBspFlag = TRUE;
- CpuMpData->NewBspNumber = ProcessorNumber;
-
- //
- // Clear the BSP bit of MSR_IA32_APIC_BASE
- //
- ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
- ApicBaseMsr.Bits.BSP = 0;
- AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);
-
- //
- // Need to wakeUp AP (future BSP).
- //
- WakeUpAP (CpuMpData, FALSE, ProcessorNumber, FutureBSPProc, CpuMpData);
-
- AsmExchangeRole (&CpuMpData->BSPInfo, &CpuMpData->APInfo);
-
- //
- // Set the BSP bit of MSR_IA32_APIC_BASE on new BSP
- //
- ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
- ApicBaseMsr.Bits.BSP = 1;
- AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);
-
- //
- // Wait for old BSP finished AP task
- //
- while (GetApState (&CpuMpData->CpuData[CallerNumber]) != CpuStateFinished) {
- CpuPause ();
- }
-
- CpuMpData->SwitchBspFlag = FALSE;
- //
- // Set old BSP enable state
- //
- if (!EnableOldBSP) {
- SetApState (&CpuMpData->CpuData[CallerNumber], CpuStateDisabled);
- } else {
- SetApState (&CpuMpData->CpuData[CallerNumber], CpuStateIdle);
- }
- //
- // Save new BSP number
- //
- CpuMpData->BspNumber = (UINT32) ProcessorNumber;
-
- //
- // Restore interrupt state.
- //
- SetInterruptState (OldInterruptState);
-
- if (OldTimerInterruptState) {
- EnableApicTimerInterrupt ();
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Worker function to let the caller enable or disable an AP from this point onward.
- This service may only be called from the BSP.
-
- @param[in] ProcessorNumber The handle number of AP.
- @param[in] EnableAP Specifies the new state for the processor for
- enabled, FALSE for disabled.
- @param[in] HealthFlag If not NULL, a pointer to a value that specifies
- the new health status of the AP.
-
- @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
- @retval others Failed to Enable/Disable AP.
-
-**/
-EFI_STATUS
-EnableDisableApWorker (
- IN UINTN ProcessorNumber,
- IN BOOLEAN EnableAP,
- IN UINT32 *HealthFlag OPTIONAL
- )
-{
- CPU_MP_DATA *CpuMpData;
- UINTN CallerNumber;
-
- CpuMpData = GetCpuMpData ();
-
- //
- // Check whether caller processor is BSP
- //
- MpInitLibWhoAmI (&CallerNumber);
- if (CallerNumber != CpuMpData->BspNumber) {
- return EFI_DEVICE_ERROR;
- }
-
- if (ProcessorNumber == CpuMpData->BspNumber) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (ProcessorNumber >= CpuMpData->CpuCount) {
- return EFI_NOT_FOUND;
- }
-
- if (!EnableAP) {
- SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateDisabled);
- } else {
- SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
- }
-
- if (HealthFlag != NULL) {
- CpuMpData->CpuData[ProcessorNumber].CpuHealthy =
- (BOOLEAN) ((*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT) != 0);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This return the handle number for the calling processor. This service may be
- called from the BSP and APs.
-
- @param[out] ProcessorNumber Pointer to the handle number of AP.
- The range is from 0 to the total number of
- logical processors minus 1. The total number of
- logical processors can be retrieved by
- MpInitLibGetNumberOfProcessors().
-
- @retval EFI_SUCCESS The current processor handle number was returned
- in ProcessorNumber.
- @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
- @retval EFI_NOT_READY MP Initialize Library is not initialized.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibWhoAmI (
- OUT UINTN *ProcessorNumber
- )
-{
- CPU_MP_DATA *CpuMpData;
-
- if (ProcessorNumber == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- CpuMpData = GetCpuMpData ();
-
- return GetProcessorNumber (CpuMpData, ProcessorNumber);
-}
-
-/**
- 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.
-
- @param[out] NumberOfProcessors Pointer to the total number of logical
- processors in the system, including the BSP
- and disabled APs.
- @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
- processors that exist in system, including
- the BSP.
-
- @retval EFI_SUCCESS The number of logical processors and enabled
- logical processors was retrieved.
- @retval EFI_DEVICE_ERROR The calling processor is an AP.
- @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors
- is NULL.
- @retval EFI_NOT_READY MP Initialize Library is not initialized.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibGetNumberOfProcessors (
- OUT UINTN *NumberOfProcessors, OPTIONAL
- OUT UINTN *NumberOfEnabledProcessors OPTIONAL
- )
-{
- CPU_MP_DATA *CpuMpData;
- UINTN CallerNumber;
- UINTN ProcessorNumber;
- UINTN EnabledProcessorNumber;
- UINTN Index;
-
- CpuMpData = GetCpuMpData ();
-
- if ((NumberOfProcessors == NULL) && (NumberOfEnabledProcessors == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Check whether caller processor is BSP
- //
- MpInitLibWhoAmI (&CallerNumber);
- if (CallerNumber != CpuMpData->BspNumber) {
- return EFI_DEVICE_ERROR;
- }
-
- ProcessorNumber = CpuMpData->CpuCount;
- EnabledProcessorNumber = 0;
- for (Index = 0; Index < ProcessorNumber; Index++) {
- if (GetApState (&CpuMpData->CpuData[Index]) != CpuStateDisabled) {
- EnabledProcessorNumber ++;
- }
- }
-
- if (NumberOfProcessors != NULL) {
- *NumberOfProcessors = ProcessorNumber;
- }
- if (NumberOfEnabledProcessors != NULL) {
- *NumberOfEnabledProcessors = EnabledProcessorNumber;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Worker function to execute a caller provided function on all enabled APs.
-
- @param[in] Procedure A pointer to the function to be run on
- enabled APs of the system.
- @param[in] SingleThread If TRUE, then all the enabled APs execute
- the function specified by Procedure one by
- one, in ascending order of processor handle
- number. If FALSE, then all the enabled APs
- execute the function specified by Procedure
- simultaneously.
- @param[in] WaitEvent The event created by the caller with CreateEvent()
- service.
- @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
- APs to return from Procedure, either for
- blocking or non-blocking mode.
- @param[in] ProcedureArgument The parameter passed into Procedure for
- all APs.
- @param[out] FailedCpuList If all APs finish successfully, then its
- content is set to NULL. If not all APs
- finish before timeout expires, then its
- content is set to address of the buffer
- holding handle numbers of the failed APs.
-
- @retval EFI_SUCCESS In blocking mode, all APs have finished before
- the timeout expired.
- @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
- to all enabled APs.
- @retval others Failed to Startup all APs.
-
-**/
-EFI_STATUS
-StartupAllAPsWorker (
- IN EFI_AP_PROCEDURE Procedure,
- IN BOOLEAN SingleThread,
- IN EFI_EVENT WaitEvent OPTIONAL,
- IN UINTN TimeoutInMicroseconds,
- IN VOID *ProcedureArgument OPTIONAL,
- OUT UINTN **FailedCpuList OPTIONAL
- )
-{
- EFI_STATUS Status;
- CPU_MP_DATA *CpuMpData;
- UINTN ProcessorCount;
- UINTN ProcessorNumber;
- UINTN CallerNumber;
- CPU_AP_DATA *CpuData;
- BOOLEAN HasEnabledAp;
- CPU_STATE ApState;
-
- CpuMpData = GetCpuMpData ();
-
- if (FailedCpuList != NULL) {
- *FailedCpuList = NULL;
- }
-
- if (CpuMpData->CpuCount == 1) {
- return EFI_NOT_STARTED;
- }
-
- if (Procedure == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Check whether caller processor is BSP
- //
- MpInitLibWhoAmI (&CallerNumber);
- if (CallerNumber != CpuMpData->BspNumber) {
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Update AP state
- //
- CheckAndUpdateApsStatus ();
-
- ProcessorCount = CpuMpData->CpuCount;
- HasEnabledAp = FALSE;
- //
- // Check whether all enabled APs are idle.
- // If any enabled AP is not idle, return EFI_NOT_READY.
- //
- for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {
- CpuData = &CpuMpData->CpuData[ProcessorNumber];
- if (ProcessorNumber != CpuMpData->BspNumber) {
- ApState = GetApState (CpuData);
- if (ApState != CpuStateDisabled) {
- HasEnabledAp = TRUE;
- if (ApState != CpuStateIdle) {
- //
- // If any enabled APs are busy, return EFI_NOT_READY.
- //
- return EFI_NOT_READY;
- }
- }
- }
- }
-
- if (!HasEnabledAp) {
- //
- // If no enabled AP exists, return EFI_NOT_STARTED.
- //
- return EFI_NOT_STARTED;
- }
-
- CpuMpData->StartCount = 0;
- for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {
- CpuData = &CpuMpData->CpuData[ProcessorNumber];
- CpuData->Waiting = FALSE;
- if (ProcessorNumber != CpuMpData->BspNumber) {
- if (CpuData->State == CpuStateIdle) {
- //
- // Mark this processor as responsible for current calling.
- //
- CpuData->Waiting = TRUE;
- CpuMpData->StartCount++;
- }
- }
- }
-
- CpuMpData->Procedure = Procedure;
- CpuMpData->ProcArguments = ProcedureArgument;
- CpuMpData->SingleThread = SingleThread;
- CpuMpData->FinishedCount = 0;
- CpuMpData->RunningCount = 0;
- CpuMpData->FailedCpuList = FailedCpuList;
- CpuMpData->ExpectedTime = CalculateTimeout (
- TimeoutInMicroseconds,
- &CpuMpData->CurrentTime
- );
- CpuMpData->TotalTime = 0;
- CpuMpData->WaitEvent = WaitEvent;
-
- if (!SingleThread) {
- WakeUpAP (CpuMpData, TRUE, 0, Procedure, ProcedureArgument);
- } else {
- for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {
- if (ProcessorNumber == CallerNumber) {
- continue;
- }
- if (CpuMpData->CpuData[ProcessorNumber].Waiting) {
- WakeUpAP (CpuMpData, FALSE, ProcessorNumber, Procedure, ProcedureArgument);
- break;
- }
- }
- }
-
- Status = EFI_SUCCESS;
- if (WaitEvent == NULL) {
- do {
- Status = CheckAllAPs ();
- } while (Status == EFI_NOT_READY);
- }
-
- return Status;
-}
-
-/**
- Worker function to let the caller get one enabled AP to execute a caller-provided
- function.
-
- @param[in] Procedure A pointer to the function to be run on
- enabled APs of the system.
- @param[in] ProcessorNumber The handle number of the AP.
- @param[in] WaitEvent The event created by the caller with CreateEvent()
- service.
- @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
- APs to return from Procedure, either for
- blocking or non-blocking mode.
- @param[in] ProcedureArgument The parameter passed into Procedure for
- all APs.
- @param[out] Finished If AP returns from Procedure before the
- timeout expires, its content is set to TRUE.
- Otherwise, the value is set to FALSE.
-
- @retval EFI_SUCCESS In blocking mode, specified AP finished before
- the timeout expires.
- @retval others Failed to Startup AP.
-
-**/
-EFI_STATUS
-StartupThisAPWorker (
- IN EFI_AP_PROCEDURE Procedure,
- IN UINTN ProcessorNumber,
- IN EFI_EVENT WaitEvent OPTIONAL,
- IN UINTN TimeoutInMicroseconds,
- IN VOID *ProcedureArgument OPTIONAL,
- OUT BOOLEAN *Finished OPTIONAL
- )
-{
- EFI_STATUS Status;
- CPU_MP_DATA *CpuMpData;
- CPU_AP_DATA *CpuData;
- UINTN CallerNumber;
-
- CpuMpData = GetCpuMpData ();
-
- if (Finished != NULL) {
- *Finished = FALSE;
- }
-
- //
- // Check whether caller processor is BSP
- //
- MpInitLibWhoAmI (&CallerNumber);
- if (CallerNumber != CpuMpData->BspNumber) {
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Check whether processor with the handle specified by ProcessorNumber exists
- //
- if (ProcessorNumber >= CpuMpData->CpuCount) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Check whether specified processor is BSP
- //
- if (ProcessorNumber == CpuMpData->BspNumber) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Check parameter Procedure
- //
- if (Procedure == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Update AP state
- //
- CheckAndUpdateApsStatus ();
-
- //
- // Check whether specified AP is disabled
- //
- if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateDisabled) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // If WaitEvent is not NULL, execute in non-blocking mode.
- // BSP saves data for CheckAPsStatus(), and returns EFI_SUCCESS.
- // CheckAPsStatus() will check completion and timeout periodically.
- //
- CpuData = &CpuMpData->CpuData[ProcessorNumber];
- CpuData->WaitEvent = WaitEvent;
- CpuData->Finished = Finished;
- CpuData->ExpectedTime = CalculateTimeout (TimeoutInMicroseconds, &CpuData->CurrentTime);
- CpuData->TotalTime = 0;
-
- WakeUpAP (CpuMpData, FALSE, ProcessorNumber, Procedure, ProcedureArgument);
-
- //
- // If WaitEvent is NULL, execute in blocking mode.
- // BSP checks AP's state until it finishes or TimeoutInMicrosecsond expires.
- //
- Status = EFI_SUCCESS;
- if (WaitEvent == NULL) {
- do {
- Status = CheckThisAP (ProcessorNumber);
- } while (Status == EFI_NOT_READY);
- }
-
- return Status;
-}
-
-/**
- Get pointer to CPU MP Data structure from GUIDed HOB.
-
- @return The pointer to CPU MP Data structure.
-**/
-CPU_MP_DATA *
-GetCpuMpDataFromGuidedHob (
- VOID
- )
-{
- EFI_HOB_GUID_TYPE *GuidHob;
- VOID *DataInHob;
- CPU_MP_DATA *CpuMpData;
-
- CpuMpData = NULL;
- GuidHob = GetFirstGuidHob (&mCpuInitMpLibHobGuid);
- if (GuidHob != NULL) {
- DataInHob = GET_GUID_HOB_DATA (GuidHob);
- CpuMpData = (CPU_MP_DATA *) (*(UINTN *) DataInHob);
- }
- 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
- );
-}
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h deleted file mode 100644 index 7a272d78ec..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ /dev/null @@ -1,594 +0,0 @@ -/** @file
- Common header file for MP Initialize Library.
-
- Copyright (c) 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.
-
-**/
-
-#ifndef _MP_LIB_H_
-#define _MP_LIB_H_
-
-#include <PiPei.h>
-
-#include <Register/Cpuid.h>
-#include <Register/Msr.h>
-#include <Register/LocalApic.h>
-#include <Register/Microcode.h>
-
-#include <Library/MpInitLib.h>
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/DebugLib.h>
-#include <Library/LocalApicLib.h>
-#include <Library/CpuLib.h>
-#include <Library/UefiCpuLib.h>
-#include <Library/TimerLib.h>
-#include <Library/SynchronizationLib.h>
-#include <Library/MtrrLib.h>
-#include <Library/HobLib.h>
-
-#define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')
-
-#define CPU_INIT_MP_LIB_HOB_GUID \
- { \
- 0x58eb6a19, 0x3699, 0x4c68, { 0xa8, 0x36, 0xda, 0xcd, 0x8e, 0xdc, 0xad, 0x4a } \
- }
-
-//
-// The MP data for switch BSP
-//
-#define CPU_SWITCH_STATE_IDLE 0
-#define CPU_SWITCH_STATE_STORED 1
-#define CPU_SWITCH_STATE_LOADED 2
-
-//
-// 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;
-
-//
-// AP loop state when APs are in idle state
-// It's value is the same with PcdCpuApLoopMode
-//
-typedef enum {
- ApInHltLoop = 1,
- ApInMwaitLoop = 2,
- ApInRunLoop = 3
-} AP_LOOP_MODE;
-
-//
-// AP initialization state during APs wakeup
-//
-typedef enum {
- ApInitConfig = 1,
- ApInitReconfig = 2,
- ApInitDone = 3
-} AP_INIT_STATE;
-
-//
-// AP state
-//
-typedef enum {
- CpuStateIdle,
- CpuStateReady,
- CpuStateBusy,
- CpuStateFinished,
- CpuStateDisabled
-} CPU_STATE;
-
-//
-// CPU volatile registers around INIT-SIPI-SIPI
-//
-typedef struct {
- UINTN Cr0;
- UINTN Cr3;
- UINTN Cr4;
- UINTN Dr0;
- UINTN Dr1;
- UINTN Dr2;
- UINTN Dr3;
- UINTN Dr6;
- UINTN Dr7;
-} CPU_VOLATILE_REGISTERS;
-
-//
-// AP related data
-//
-typedef struct {
- SPIN_LOCK ApLock;
- volatile UINT32 *StartupApSignal;
- volatile UINTN ApFunction;
- volatile UINTN ApFunctionArgument;
- BOOLEAN CpuHealthy;
- volatile CPU_STATE State;
- CPU_VOLATILE_REGISTERS VolatileRegisters;
- BOOLEAN Waiting;
- BOOLEAN *Finished;
- UINT64 ExpectedTime;
- UINT64 CurrentTime;
- UINT64 TotalTime;
- EFI_EVENT WaitEvent;
-} CPU_AP_DATA;
-
-//
-// Basic CPU information saved in Guided HOB.
-// Because the contents will be shard between PEI and DXE,
-// we need to make sure the each fields offset same in different
-// architecture.
-//
-#pragma pack (1)
-typedef struct {
- UINT32 InitialApicId;
- UINT32 ApicId;
- UINT32 Health;
- UINT64 ApTopOfStack;
-} CPU_INFO_IN_HOB;
-#pragma pack ()
-
-//
-// AP reset code information including code address and size,
-// this structure will be shared be C code and assembly code.
-// It is natural aligned by design.
-//
-typedef struct {
- UINT8 *RendezvousFunnelAddress;
- UINTN ModeEntryOffset;
- UINTN RendezvousFunnelSize;
- UINT8 *RelocateApLoopFuncAddress;
- UINTN RelocateApLoopFuncSize;
-} MP_ASSEMBLY_ADDRESS_MAP;
-
-typedef struct _CPU_MP_DATA 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 EnableExecuteDisable;
- UINTN Cr3;
- UINTN InitFlag;
- CPU_INFO_IN_HOB *CpuInfo;
- CPU_MP_DATA *CpuMpData;
-} MP_CPU_EXCHANGE_INFO;
-
-#pragma pack()
-
-//
-// CPU MP Data save in memory
-//
-struct _CPU_MP_DATA {
- UINT64 CpuInfoInHob;
- UINT32 CpuCount;
- UINT32 BspNumber;
- //
- // The above fields data will be passed from PEI to DXE
- // Please make sure the fields offset same in the different
- // architecture.
- //
- SPIN_LOCK MpLock;
- UINTN Buffer;
- UINTN CpuApStackSize;
- MP_ASSEMBLY_ADDRESS_MAP AddressMap;
- UINTN WakeupBuffer;
- UINTN BackupBuffer;
- UINTN BackupBufferSize;
- BOOLEAN SaveRestoreFlag;
-
- volatile UINT32 StartCount;
- volatile UINT32 FinishedCount;
- volatile UINT32 RunningCount;
- BOOLEAN SingleThread;
- EFI_AP_PROCEDURE Procedure;
- VOID *ProcArguments;
- BOOLEAN *Finished;
- UINT64 ExpectedTime;
- UINT64 CurrentTime;
- UINT64 TotalTime;
- EFI_EVENT WaitEvent;
- UINTN **FailedCpuList;
-
- AP_INIT_STATE InitFlag;
- BOOLEAN X2ApicEnable;
- BOOLEAN SwitchBspFlag;
- UINTN NewBspNumber;
- CPU_EXCHANGE_ROLE_INFO BSPInfo;
- CPU_EXCHANGE_ROLE_INFO APInfo;
- MTRR_SETTINGS MtrrTable;
- UINT8 ApLoopMode;
- UINT8 ApTargetCState;
- UINT16 PmCodeSegment;
- CPU_AP_DATA *CpuData;
- volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo;
-
- UINT32 CurrentTimerCount;
- UINTN DivideValue;
- UINT8 Vector;
- BOOLEAN PeriodicMode;
- BOOLEAN TimerInterruptState;
-};
-
-extern EFI_GUID mCpuInitMpLibHobGuid;
-
-/**
- Assembly code to place AP into safe loop mode.
-
- Place AP into targeted C-State if MONITOR is supported, otherwise
- place AP into hlt state.
- Place AP in protected mode if the current is long mode. Due to AP maybe
- wakeup by some hardware event. It could avoid accessing page table that
- may not available during booting to OS.
-
- @param[in] MwaitSupport TRUE indicates MONITOR is supported.
- FALSE indicates MONITOR is not supported.
- @param[in] ApTargetCState Target C-State value.
- @param[in] PmCodeSegment Protected mode code segment value.
-**/
-typedef
-VOID
-(EFIAPI * ASM_RELOCATE_AP_LOOP) (
- IN BOOLEAN MwaitSupport,
- IN UINTN ApTargetCState,
- IN UINTN PmCodeSegment,
- IN UINTN TopOfApStack,
- IN UINTN NumberToFinish
- );
-
-/**
- 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[out] AddressMap Output buffer for address map information.
-**/
-VOID
-EFIAPI
-AsmGetAddressMap (
- OUT MP_ASSEMBLY_ADDRESS_MAP *AddressMap
- );
-
-/**
- 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[in] MyInfo Pointer to buffer holding the exchanging information for the executing processor.
- @param[in] 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
- );
-
-/**
- Get the pointer to CPU MP Data structure.
-
- @return The pointer to CPU MP Data structure.
-**/
-CPU_MP_DATA *
-GetCpuMpData (
- VOID
- );
-
-/**
- Save the pointer to CPU MP Data structure.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
-**/
-VOID
-SaveCpuMpData (
- IN CPU_MP_DATA *CpuMpData
- );
-
-/**
- Allocate reset vector buffer.
-
- @param[in, out] CpuMpData The pointer to CPU MP Data structure.
-**/
-VOID
-AllocateResetVector (
- IN OUT CPU_MP_DATA *CpuMpData
- );
-
-/**
- Free AP reset vector buffer.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure.
-**/
-VOID
-FreeResetVector (
- IN CPU_MP_DATA *CpuMpData
- );
-
-/**
- This function will be called by BSP to wakeup AP.
-
- @param[in] CpuMpData Pointer to CPU MP Data
- @param[in] Broadcast TRUE: Send broadcast IPI to all APs
- FALSE: Send IPI to AP by ApicId
- @param[in] ProcessorNumber The handle number of specified processor
- @param[in] Procedure The function to be invoked by AP
- @param[in] ProcedureArgument The argument to be passed into AP function
-**/
-VOID
-WakeUpAP (
- IN CPU_MP_DATA *CpuMpData,
- IN BOOLEAN Broadcast,
- IN UINTN ProcessorNumber,
- IN EFI_AP_PROCEDURE Procedure, OPTIONAL
- IN VOID *ProcedureArgument OPTIONAL
- );
-
-/**
- Initialize global data for MP support.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure.
-**/
-VOID
-InitMpGlobalData (
- IN CPU_MP_DATA *CpuMpData
- );
-
-/**
- Worker function to execute a caller provided function on all enabled APs.
-
- @param[in] Procedure A pointer to the function to be run on
- enabled APs of the system.
- @param[in] SingleThread If TRUE, then all the enabled APs execute
- the function specified by Procedure one by
- one, in ascending order of processor handle
- number. If FALSE, then all the enabled APs
- execute the function specified by Procedure
- simultaneously.
- @param[in] WaitEvent The event created by the caller with CreateEvent()
- service.
- @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
- APs to return from Procedure, either for
- blocking or non-blocking mode.
- @param[in] ProcedureArgument The parameter passed into Procedure for
- all APs.
- @param[out] FailedCpuList If all APs finish successfully, then its
- content is set to NULL. If not all APs
- finish before timeout expires, then its
- content is set to address of the buffer
- holding handle numbers of the failed APs.
-
- @retval EFI_SUCCESS In blocking mode, all APs have finished before
- the timeout expired.
- @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
- to all enabled APs.
- @retval others Failed to Startup all APs.
-
-**/
-EFI_STATUS
-StartupAllAPsWorker (
- IN EFI_AP_PROCEDURE Procedure,
- IN BOOLEAN SingleThread,
- IN EFI_EVENT WaitEvent OPTIONAL,
- IN UINTN TimeoutInMicroseconds,
- IN VOID *ProcedureArgument OPTIONAL,
- OUT UINTN **FailedCpuList OPTIONAL
- );
-
-/**
- Worker function to let the caller get one enabled AP to execute a caller-provided
- function.
-
- @param[in] Procedure A pointer to the function to be run on
- enabled APs of the system.
- @param[in] ProcessorNumber The handle number of the AP.
- @param[in] WaitEvent The event created by the caller with CreateEvent()
- service.
- @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
- APs to return from Procedure, either for
- blocking or non-blocking mode.
- @param[in] ProcedureArgument The parameter passed into Procedure for
- all APs.
- @param[out] Finished If AP returns from Procedure before the
- timeout expires, its content is set to TRUE.
- Otherwise, the value is set to FALSE.
-
- @retval EFI_SUCCESS In blocking mode, specified AP finished before
- the timeout expires.
- @retval others Failed to Startup AP.
-
-**/
-EFI_STATUS
-StartupThisAPWorker (
- IN EFI_AP_PROCEDURE Procedure,
- IN UINTN ProcessorNumber,
- IN EFI_EVENT WaitEvent OPTIONAL,
- IN UINTN TimeoutInMicroseconds,
- IN VOID *ProcedureArgument OPTIONAL,
- OUT BOOLEAN *Finished OPTIONAL
- );
-
-/**
- Worker function to switch the requested AP to be the BSP from that point onward.
-
- @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
- @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
- enabled AP. Otherwise, it will be disabled.
-
- @retval EFI_SUCCESS BSP successfully switched.
- @retval others Failed to switch BSP.
-
-**/
-EFI_STATUS
-SwitchBSPWorker (
- IN UINTN ProcessorNumber,
- IN BOOLEAN EnableOldBSP
- );
-
-/**
- Worker function to let the caller enable or disable an AP from this point onward.
- This service may only be called from the BSP.
-
- @param[in] ProcessorNumber The handle number of AP.
- @param[in] EnableAP Specifies the new state for the processor for
- enabled, FALSE for disabled.
- @param[in] HealthFlag If not NULL, a pointer to a value that specifies
- the new health status of the AP.
-
- @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
- @retval others Failed to Enable/Disable AP.
-
-**/
-EFI_STATUS
-EnableDisableApWorker (
- IN UINTN ProcessorNumber,
- IN BOOLEAN EnableAP,
- IN UINT32 *HealthFlag OPTIONAL
- );
-
-/**
- Get pointer to CPU MP Data structure from GUIDed HOB.
-
- @return The pointer to CPU MP Data structure.
-**/
-CPU_MP_DATA *
-GetCpuMpDataFromGuidedHob (
- VOID
- );
-
-/** Checks status of specified AP.
-
- This function checks whether the specified AP has finished the task assigned
- by StartupThisAP(), and whether timeout expires.
-
- @param[in] ProcessorNumber The handle number of processor.
-
- @retval EFI_SUCCESS Specified AP has finished task assigned by StartupThisAPs().
- @retval EFI_TIMEOUT The timeout expires.
- @retval EFI_NOT_READY Specified AP has not finished task and timeout has not expired.
-**/
-EFI_STATUS
-CheckThisAP (
- IN UINTN ProcessorNumber
- );
-
-/**
- Checks status of all APs.
-
- This function checks whether all APs have finished task assigned by StartupAllAPs(),
- and whether timeout expires.
-
- @retval EFI_SUCCESS All APs have finished task assigned by StartupAllAPs().
- @retval EFI_TIMEOUT The timeout expires.
- @retval EFI_NOT_READY APs have not finished task and timeout has not expired.
-**/
-EFI_STATUS
-CheckAllAPs (
- VOID
- );
-
-/**
- Checks APs status and updates APs status if needed.
-
-**/
-VOID
-CheckAndUpdateApsStatus (
- VOID
- );
-
-/**
- Detect whether specified processor can find matching microcode patch and load it.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure.
-**/
-VOID
-MicrocodeDetect (
- IN CPU_MP_DATA *CpuMpData
- );
-
-/**
- Detect whether Mwait-monitor feature is supported.
-
- @retval TRUE Mwait-monitor feature is supported.
- @retval FALSE Mwait-monitor feature is not supported.
-**/
-BOOLEAN
-IsMwaitSupport (
- VOID
- );
-
-/**
- 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[in] PeiServices The pointer to the PEI Services Table.
- @param[in] NotifyDescriptor Address of the notification descriptor data structure.
- @param[in] Ppi Address of the PPI that was installed.
-
- @retval EFI_SUCCESS When everything is OK.
-**/
-EFI_STATUS
-EFIAPI
-CpuMpEndOfPeiCallback (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
- IN VOID *Ppi
- );
-
-/**
- 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
- );
-
-/**
- Restore wakeup buffer data.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure.
-**/
-VOID
-RestoreWakeupBuffer(
- IN CPU_MP_DATA *CpuMpData
- );
-
-/**
- Enable Debug Agent to support source debugging on AP function.
-
-**/
-VOID
-EnableDebugAgent (
- VOID
- );
-
-#endif
-
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf deleted file mode 100644 index 0c6873da79..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf +++ /dev/null @@ -1,70 +0,0 @@ -## @file
-# MP Initialize Library instance for PEI driver.
-#
-# Copyright (c) 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.
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = PeiMpInitLib
- MODULE_UNI_FILE = PeiMpInitLib.uni
- FILE_GUID = B00F6090-7739-4830-B906-E0032D388987
- MODULE_TYPE = PEIM
- VERSION_STRING = 1.1
- LIBRARY_CLASS = MpInitLib|PEIM
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64
-#
-
-[Sources.IA32]
- Ia32/MpEqu.inc
- Ia32/MpFuncs.nasm
-
-[Sources.X64]
- X64/MpEqu.inc
- X64/MpFuncs.nasm
-
-[Sources.common]
- PeiMpLib.c
- MpLib.c
- MpLib.h
- Microcode.c
-
-[Packages]
- MdePkg/MdePkg.dec
- UefiCpuPkg/UefiCpuPkg.dec
-
-[LibraryClasses]
- BaseLib
- LocalApicLib
- MemoryAllocationLib
- HobLib
- PeiServicesLib
- MtrrLib
- CpuLib
- UefiCpuLib
- SynchronizationLib
-
-[Ppis]
- gEfiEndOfPeiSignalPpiGuid ## NOTIFY
-
-[Pcd]
- gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES
-
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.uni b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.uni deleted file mode 100644 index d16f306685..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.uni +++ /dev/null @@ -1,22 +0,0 @@ -// /** @file
-// MP Initialize Library instance for PEI driver.
-//
-// MP Initialize Library instance for PEI driver.
-//
-// Copyright (c) 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.
-//
-// **/
-
-
-#string STR_MODULE_ABSTRACT #language en-US "MP Initialize Library instance for PEI driver."
-
-#string STR_MODULE_DESCRIPTION #language en-US "MP Initialize Library instance for PEI driver."
-
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c deleted file mode 100644 index fb1d48fad8..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c +++ /dev/null @@ -1,624 +0,0 @@ -/** @file
- MP initialize support functions for PEI phase.
-
- Copyright (c) 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 "MpLib.h"
-#include <Ppi/EndOfPeiPhase.h>
-#include <Library/PeiServicesLib.h>
-
-//
-// Global PEI notify function descriptor on EndofPei event
-//
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_NOTIFY_DESCRIPTOR mMpInitLibNotifyList = {
- (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiEndOfPeiSignalPpiGuid,
- CpuMpEndOfPeiCallback
-};
-
-
-/**
- Enable Debug Agent to support source debugging on AP function.
-
-**/
-VOID
-EnableDebugAgent (
- VOID
- )
-{
-}
-
-/**
- Get pointer to CPU MP Data structure.
-
- @return The pointer to CPU MP Data structure.
-**/
-CPU_MP_DATA *
-GetCpuMpData (
- VOID
- )
-{
- CPU_MP_DATA *CpuMpData;
-
- CpuMpData = GetCpuMpDataFromGuidedHob ();
- ASSERT (CpuMpData != NULL);
- return CpuMpData;
-}
-
-/**
- Save the pointer to CPU MP Data structure.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
-**/
-VOID
-SaveCpuMpData (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- UINT64 Data64;
- //
- // Build location of CPU MP DATA buffer in HOB
- //
- Data64 = (UINT64) (UINTN) CpuMpData;
- BuildGuidDataHob (
- &mCpuInitMpLibHobGuid,
- (VOID *) &Data64,
- sizeof (UINT64)
- );
-}
-
-/**
- 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[in] PeiServices The pointer to the PEI Services Table.
- @param[in] NotifyDescriptor Address of the notification descriptor data structure.
- @param[in] Ppi Address of the PPI that was installed.
-
- @retval EFI_SUCCESS When everything is OK.
-**/
-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;
- CPU_MP_DATA *CpuMpData;
- EFI_PEI_HOB_POINTERS Hob;
- EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
-
- DEBUG ((DEBUG_INFO, "PeiMpInitLib: CpuMpEndOfPeiCallback () invoked\n"));
-
- Status = PeiServicesGetBootMode (&BootMode);
- ASSERT_EFI_ERROR (Status);
-
- CpuMpData = GetCpuMpData ();
- 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 == CpuMpData->WakeupBuffer) {
- //
- // Flag this HOB type to un-used
- //
- GET_HOB_TYPE (Hob) = EFI_HOB_TYPE_UNUSED;
- break;
- }
- }
- Hob.Raw = GET_NEXT_HOB (Hob);
- }
- } else {
- CpuMpData->SaveRestoreFlag = TRUE;
- RestoreWakeupBuffer (CpuMpData);
- }
- return EFI_SUCCESS;
-}
-
-/**
- Check if AP wakeup buffer is overlapped with existing allocated buffer.
-
- @param[in] WakeupBufferStart AP wakeup buffer start address.
- @param[in] WakeupBufferEnd AP wakeup buffer end address.
-
- @retval TRUE There is overlap.
- @retval FALSE There is no overlap.
-**/
-BOOLEAN
-CheckOverlapWithAllocatedBuffer (
- IN UINTN WakeupBufferStart,
- IN UINTN WakeupBufferEnd
- )
-{
- EFI_PEI_HOB_POINTERS Hob;
- EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
- BOOLEAN Overlapped;
- UINTN MemoryStart;
- UINTN MemoryEnd;
-
- Overlapped = FALSE;
- //
- // 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;
- MemoryStart = (UINTN) MemoryHob->AllocDescriptor.MemoryBaseAddress;
- MemoryEnd = (UINTN) (MemoryHob->AllocDescriptor.MemoryBaseAddress +
- MemoryHob->AllocDescriptor.MemoryLength);
- if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {
- Overlapped = TRUE;
- break;
- }
- }
- Hob.Raw = GET_NEXT_HOB (Hob);
- }
- return Overlapped;
-}
-
-/**
- Get available system memory below 1MB by specified size.
-
- @param[in] WakeupBufferSize Wakeup buffer size required
-
- @retval other Return wakeup buffer address below 1MB.
- @retval -1 Cannot find free memory below 1MB.
-**/
-UINTN
-GetWakeupBuffer (
- IN UINTN WakeupBufferSize
- )
-{
- EFI_PEI_HOB_POINTERS Hob;
- UINTN WakeupBufferStart;
- UINTN WakeupBufferEnd;
-
- WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);
-
- //
- // 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;
- }
- while (WakeupBufferEnd > WakeupBufferSize) {
- //
- // Wakeup buffer should be aligned on 4KB
- //
- WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);
- if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {
- break;
- }
- if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {
- //
- // If this range is overlapped with existing allocated buffer, skip it
- // and find the next range
- //
- WakeupBufferEnd -= WakeupBufferSize;
- continue;
- }
- DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
- WakeupBufferStart, WakeupBufferSize));
- //
- // Create a memory allocation HOB.
- //
- BuildMemoryAllocationHob (
- WakeupBufferStart,
- WakeupBufferSize,
- EfiBootServicesData
- );
- return WakeupBufferStart;
- }
- }
- }
- //
- // Find the next HOB
- //
- Hob.Raw = GET_NEXT_HOB (Hob);
- }
-
- return (UINTN) -1;
-}
-
-/**
- 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);
- }
-
- if (CpuMpData->SaveRestoreFlag) {
- BackupAndPrepareWakeupBuffer (CpuMpData);
- }
-}
-
-/**
- Free AP reset vector buffer.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure.
-**/
-VOID
-FreeResetVector (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- if (CpuMpData->SaveRestoreFlag) {
- RestoreWakeupBuffer (CpuMpData);
- }
-}
-
-/**
- Checks APs status and updates APs status if needed.
-
-**/
-VOID
-CheckAndUpdateApsStatus (
- VOID
- )
-{
-}
-
-/**
- Initialize global data for MP support.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure.
-**/
-VOID
-InitMpGlobalData (
- IN CPU_MP_DATA *CpuMpData
- )
-{
- EFI_STATUS Status;
-
- SaveCpuMpData (CpuMpData);
-
- if (CpuMpData->CpuCount == 1) {
- //
- // If only BSP exists, return
- //
- return;
- }
-
- //
- // Register an event for EndOfPei
- //
- Status = PeiServicesNotifyPpi (&mMpInitLibNotifyList);
- ASSERT_EFI_ERROR (Status);
-}
-
-/**
- This service executes a caller provided function on all enabled APs.
-
- @param[in] Procedure A pointer to the function to be run on
- enabled APs of the system. See type
- EFI_AP_PROCEDURE.
- @param[in] SingleThread If TRUE, then all the enabled APs execute
- the function specified by Procedure one by
- one, in ascending order of processor handle
- number. If FALSE, then all the enabled APs
- execute the function specified by Procedure
- simultaneously.
- @param[in] WaitEvent The event created by the caller with CreateEvent()
- service. If it is NULL, then execute in
- blocking mode. BSP waits until all APs finish
- or TimeoutInMicroSeconds expires. If it's
- not NULL, then execute in non-blocking mode.
- BSP requests the function specified by
- Procedure to be started on all the enabled
- APs, and go on executing immediately. If
- all return from Procedure, or TimeoutInMicroSeconds
- expires, this event is signaled. The BSP
- can use the CheckEvent() or WaitForEvent()
- services to check the state of event. Type
- EFI_EVENT is defined in CreateEvent() in
- the Unified Extensible Firmware Interface
- Specification.
- @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
- APs to return from Procedure, either for
- blocking or non-blocking mode. Zero means
- infinity. If the timeout expires before
- all APs return from Procedure, then Procedure
- on the failed APs is terminated. All enabled
- APs are available for next function assigned
- by MpInitLibStartupAllAPs() or
- MPInitLibStartupThisAP().
- If the timeout expires in blocking mode,
- BSP returns EFI_TIMEOUT. If the timeout
- expires in non-blocking mode, WaitEvent
- is signaled with SignalEvent().
- @param[in] ProcedureArgument The parameter passed into Procedure for
- all APs.
- @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
- if all APs finish successfully, then its
- content is set to NULL. If not all APs
- finish before timeout expires, then its
- content is set to address of the buffer
- holding handle numbers of the failed APs.
- The buffer is allocated by MP Initialization
- library, and it's the caller's responsibility to
- free the buffer with FreePool() service.
- In blocking mode, it is ready for consumption
- when the call returns. In non-blocking mode,
- it is ready when WaitEvent is signaled. The
- list of failed CPU is terminated by
- END_OF_CPU_LIST.
-
- @retval EFI_SUCCESS In blocking mode, all APs have finished before
- the timeout expired.
- @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
- to all enabled APs.
- @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
- UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
- signaled.
- @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
- supported.
- @retval EFI_DEVICE_ERROR Caller processor is AP.
- @retval EFI_NOT_STARTED No enabled APs exist in the system.
- @retval EFI_NOT_READY Any enabled APs are busy.
- @retval EFI_NOT_READY MP Initialize Library is not initialized.
- @retval EFI_TIMEOUT In blocking mode, the timeout expired before
- all enabled APs have finished.
- @retval EFI_INVALID_PARAMETER Procedure is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibStartupAllAPs (
- IN EFI_AP_PROCEDURE Procedure,
- IN BOOLEAN SingleThread,
- IN EFI_EVENT WaitEvent OPTIONAL,
- IN UINTN TimeoutInMicroseconds,
- IN VOID *ProcedureArgument OPTIONAL,
- OUT UINTN **FailedCpuList OPTIONAL
- )
-{
- if (WaitEvent != NULL) {
- return EFI_UNSUPPORTED;
- }
-
- return StartupAllAPsWorker (
- Procedure,
- SingleThread,
- NULL,
- TimeoutInMicroseconds,
- ProcedureArgument,
- FailedCpuList
- );
-}
-
-/**
- This service lets the caller get one enabled AP to execute a caller-provided
- function.
-
- @param[in] Procedure A pointer to the function to be run on the
- designated AP of the system. See type
- EFI_AP_PROCEDURE.
- @param[in] ProcessorNumber The handle number of the AP. The range is
- from 0 to the total number of logical
- processors minus 1. The total number of
- logical processors can be retrieved by
- MpInitLibGetNumberOfProcessors().
- @param[in] WaitEvent The event created by the caller with CreateEvent()
- service. If it is NULL, then execute in
- blocking mode. BSP waits until this AP finish
- or TimeoutInMicroSeconds expires. If it's
- not NULL, then execute in non-blocking mode.
- BSP requests the function specified by
- Procedure to be started on this AP,
- and go on executing immediately. If this AP
- return from Procedure or TimeoutInMicroSeconds
- expires, this event is signaled. The BSP
- can use the CheckEvent() or WaitForEvent()
- services to check the state of event. Type
- EFI_EVENT is defined in CreateEvent() in
- the Unified Extensible Firmware Interface
- Specification.
- @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
- this AP to finish this Procedure, either for
- blocking or non-blocking mode. Zero means
- infinity. If the timeout expires before
- this AP returns from Procedure, then Procedure
- on the AP is terminated. The
- AP is available for next function assigned
- by MpInitLibStartupAllAPs() or
- MpInitLibStartupThisAP().
- If the timeout expires in blocking mode,
- BSP returns EFI_TIMEOUT. If the timeout
- expires in non-blocking mode, WaitEvent
- is signaled with SignalEvent().
- @param[in] ProcedureArgument The parameter passed into Procedure on the
- specified AP.
- @param[out] Finished If NULL, this parameter is ignored. In
- blocking mode, this parameter is ignored.
- In non-blocking mode, if AP returns from
- Procedure before the timeout expires, its
- content is set to TRUE. Otherwise, the
- value is set to FALSE. The caller can
- determine if the AP returned from Procedure
- by evaluating this value.
-
- @retval EFI_SUCCESS In blocking mode, specified AP finished before
- the timeout expires.
- @retval EFI_SUCCESS In non-blocking mode, the function has been
- dispatched to specified AP.
- @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
- UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
- signaled.
- @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
- supported.
- @retval EFI_DEVICE_ERROR The calling processor is an AP.
- @retval EFI_TIMEOUT In blocking mode, the timeout expired before
- the specified AP has finished.
- @retval EFI_NOT_READY The specified AP is busy.
- @retval EFI_NOT_READY MP Initialize Library is not initialized.
- @retval EFI_NOT_FOUND The processor with the handle specified by
- ProcessorNumber does not exist.
- @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
- @retval EFI_INVALID_PARAMETER Procedure is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibStartupThisAP (
- IN EFI_AP_PROCEDURE Procedure,
- IN UINTN ProcessorNumber,
- IN EFI_EVENT WaitEvent OPTIONAL,
- IN UINTN TimeoutInMicroseconds,
- IN VOID *ProcedureArgument OPTIONAL,
- OUT BOOLEAN *Finished OPTIONAL
- )
-{
- if (WaitEvent != NULL) {
- return EFI_UNSUPPORTED;
- }
-
- return StartupThisAPWorker (
- Procedure,
- ProcessorNumber,
- NULL,
- TimeoutInMicroseconds,
- ProcedureArgument,
- Finished
- );
-}
-
-/**
- This service switches the requested AP to be the BSP from that point onward.
- This service changes the BSP for all purposes. This call can only be performed
- by the current BSP.
-
- @param[in] ProcessorNumber The handle number of AP that is to become the new
- BSP. The range is from 0 to the total number of
- logical processors minus 1. The total number of
- logical processors can be retrieved by
- MpInitLibGetNumberOfProcessors().
- @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
- enabled AP. Otherwise, it will be disabled.
-
- @retval EFI_SUCCESS BSP successfully switched.
- @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
- this service returning.
- @retval EFI_UNSUPPORTED Switching the BSP is not supported.
- @retval EFI_DEVICE_ERROR The calling processor is an AP.
- @retval EFI_NOT_FOUND The processor with the handle specified by
- ProcessorNumber does not exist.
- @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
- a disabled AP.
- @retval EFI_NOT_READY The specified AP is busy.
- @retval EFI_NOT_READY MP Initialize Library is not initialized.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibSwitchBSP (
- IN UINTN ProcessorNumber,
- IN BOOLEAN EnableOldBSP
- )
-{
- return SwitchBSPWorker (ProcessorNumber, EnableOldBSP);
-}
-
-/**
- This service lets the caller enable or disable an AP from this point onward.
- This service may only be called from the BSP.
-
- @param[in] ProcessorNumber The handle number of AP.
- The range is from 0 to the total number of
- logical processors minus 1. The total number of
- logical processors can be retrieved by
- MpInitLibGetNumberOfProcessors().
- @param[in] EnableAP Specifies the new state for the processor for
- enabled, FALSE for disabled.
- @param[in] HealthFlag If not NULL, a pointer to a value that specifies
- the new health status of the AP. This flag
- corresponds to StatusFlag defined in
- EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
- the PROCESSOR_HEALTH_STATUS_BIT is used. All other
- bits are ignored. If it is NULL, this parameter
- is ignored.
-
- @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
- @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
- prior to this service returning.
- @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
- @retval EFI_DEVICE_ERROR The calling processor is an AP.
- @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
- does not exist.
- @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
- @retval EFI_NOT_READY MP Initialize Library is not initialized.
-
-**/
-EFI_STATUS
-EFIAPI
-MpInitLibEnableDisableAP (
- IN UINTN ProcessorNumber,
- IN BOOLEAN EnableAP,
- IN UINT32 *HealthFlag OPTIONAL
- )
-{
- return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);
-}
-
-
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc b/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc deleted file mode 100644 index a63cd23a40..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc +++ /dev/null @@ -1,43 +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
-NumApsExecutingLocation equ LockLocation + 44h
-CodeSegmentLocation equ LockLocation + 4Ch
-DataSegmentLocation equ LockLocation + 54h
-EnableExecuteDisableLocation equ LockLocation + 5Ch
-Cr3Location equ LockLocation + 64h
-InitFlagLocation equ LockLocation + 6Ch
-CpuInfoLocation equ LockLocation + 74h
-
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm deleted file mode 100644 index fa54d01542..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm +++ /dev/null @@ -1,398 +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 si, EnableExecuteDisableLocation
- cmp byte [si], 0
- jz SkipEnableExecuteDisableBit
-
- ;
- ; Enable execute disable bit
- ;
- mov ecx, 0c0000080h ; EFER MSR number
- rdmsr ; Read EFER
- bts eax, 11 ; Enable Execute Disable Bit
- wrmsr ; Write EFER
-
-SkipEnableExecuteDisableBit:
-
- 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
- lea edi, [esi + InitFlagLocation]
- cmp qword [edi], 1 ; ApInitConfig
- jnz GetApicId
-
- ; AP init
- mov edi, esi
- add edi, LockLocation
- mov rax, NotVacantFlag
-
-TestLock:
- xchg qword [edi], rax
- cmp rax, NotVacantFlag
- jz TestLock
-
- lea ecx, [esi + NumApsExecutingLocation]
- inc dword [ecx]
- mov ebx, [ecx]
-
-Releaselock:
- mov rax, VacantFlag
- xchg qword [edi], rax
- ; program stack
- mov edi, esi
- add edi, StackSizeLocation
- mov eax, dword [edi]
- mov ecx, ebx
- inc ecx
- mul ecx ; EAX = StackSize * (CpuNumber + 1)
- mov edi, esi
- add edi, StackStartAddressLocation
- add rax, qword [edi]
- mov rsp, rax
- jmp CProcedureInvoke
-
-GetApicId:
- mov eax, 0
- cpuid
- cmp eax, 0bh
- jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
-
- mov eax, 0bh
- xor ecx, ecx
- cpuid
- test ebx, 0ffffh
- jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
-
- ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
- jmp GetProcessorNumber
-
-NoX2Apic:
- ; Processor is not x2APIC capable, so get 8-bit APIC ID
- mov eax, 1
- cpuid
- shr ebx, 24
- mov edx, ebx
-
-GetProcessorNumber:
- ;
- ; Get processor number for this AP
- ; Note that BSP may become an AP due to SwitchBsp()
- ;
- xor ebx, ebx
- lea eax, [esi + CpuInfoLocation]
- mov edi, [eax]
-
-GetNextProcNumber:
- cmp dword [edi], edx ; APIC ID match?
- jz ProgramStack
- add edi, 20
- inc ebx
- jmp GetNextProcNumber
-
-ProgramStack:
- mov rsp, qword [edi + 12]
-
-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 $ ; Should never reach here
-
-RendezvousFunnelProcEnd:
-
-;-------------------------------------------------------------------------------------
-; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish);
-;-------------------------------------------------------------------------------------
-global ASM_PFX(AsmRelocateApLoop)
-ASM_PFX(AsmRelocateApLoop):
-AsmRelocateApLoopStart:
- mov rax, [rsp + 40] ; CountTofinish
- lock dec dword [rax] ; (*CountTofinish)--
- mov rsp, r9
- push rcx
- push rdx
-
- lea rsi, [PmEntry] ; rsi <- The start address of transition code
-
- push r8
- push rsi
- DB 0x48
- retf
-BITS 32
-PmEntry:
- mov eax, cr0
- btr eax, 31 ; Clear CR0.PG
- mov cr0, eax ; Disable paging and caches
-
- mov ebx, edx ; Save EntryPoint to rbx, for rdmsr will overwrite rdx
- mov ecx, 0xc0000080
- rdmsr
- and ah, ~ 1 ; Clear LME
- wrmsr
- mov eax, cr4
- and al, ~ (1 << 5) ; Clear PAE
- mov cr4, eax
-
- pop edx
- add esp, 4
- pop ecx,
- add esp, 4
- cmp cl, 1 ; Check mwait-monitor support
- jnz HltLoop
- mov ebx, edx ; Save C-State to ebx
-MwaitLoop:
- mov eax, esp ; Set Monitor Address
- xor ecx, ecx ; ecx = 0
- xor edx, edx ; edx = 0
- monitor
- mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
- shl eax, 4
- mwait
- jmp MwaitLoop
-HltLoop:
- cli
- hlt
- jmp HltLoop
-BITS 64
-AsmRelocateApLoopEnd:
-
-;-------------------------------------------------------------------------------------
-; 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
- mov rax, ASM_PFX(AsmRelocateApLoop)
- mov qword [rcx + 18h], rax
- mov qword [rcx + 20h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
- ret
-
-;-------------------------------------------------------------------------------------
-;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
-;about to become an AP. It switches its 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
|