UefiCpuPkg/CpuMpPei: Update files format to DOS

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18168 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Jeff Fan 2015-08-06 06:57:47 +00:00 committed by vanjeff
parent 3fd56a2672
commit ea0f431cec
14 changed files with 4082 additions and 4082 deletions

View File

@ -1,260 +1,260 @@
/** @file /** @file
Update and publish processors' BIST information. Update and publish processors' BIST information.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/ **/
#include "CpuMpPei.h" #include "CpuMpPei.h"
EFI_SEC_PLATFORM_INFORMATION2_PPI mSecPlatformInformation2Ppi = { EFI_SEC_PLATFORM_INFORMATION2_PPI mSecPlatformInformation2Ppi = {
SecPlatformInformation2 SecPlatformInformation2
}; };
EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformation2Ppi = { EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformation2Ppi = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiSecPlatformInformation2PpiGuid, &gEfiSecPlatformInformation2PpiGuid,
&mSecPlatformInformation2Ppi &mSecPlatformInformation2Ppi
}; };
/** /**
Implementation of the PlatformInformation2 service in EFI_SEC_PLATFORM_INFORMATION2_PPI. Implementation of the PlatformInformation2 service in EFI_SEC_PLATFORM_INFORMATION2_PPI.
@param PeiServices The pointer to the PEI Services Table. @param PeiServices The pointer to the PEI Services Table.
@param StructureSize The pointer to the variable describing size of the input buffer. @param StructureSize The pointer to the variable describing size of the input buffer.
@param PlatformInformationRecord2 The pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD2. @param PlatformInformationRecord2 The pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD2.
@retval EFI_SUCCESS The data was successfully returned. @retval EFI_SUCCESS The data was successfully returned.
@retval EFI_BUFFER_TOO_SMALL The buffer was too small. The current buffer size needed to @retval EFI_BUFFER_TOO_SMALL The buffer was too small. The current buffer size needed to
hold the record is returned in StructureSize. hold the record is returned in StructureSize.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
SecPlatformInformation2 ( SecPlatformInformation2 (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN OUT UINT64 *StructureSize, IN OUT UINT64 *StructureSize,
OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2 OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2
) )
{ {
PEI_CPU_MP_DATA *PeiCpuMpData; PEI_CPU_MP_DATA *PeiCpuMpData;
UINTN BistInformationSize; UINTN BistInformationSize;
UINTN CpuIndex; UINTN CpuIndex;
EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstance; EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstance;
PeiCpuMpData = GetMpHobData (); PeiCpuMpData = GetMpHobData ();
BistInformationSize = sizeof (EFI_SEC_PLATFORM_INFORMATION_RECORD2) + BistInformationSize = sizeof (EFI_SEC_PLATFORM_INFORMATION_RECORD2) +
sizeof (EFI_SEC_PLATFORM_INFORMATION_CPU) * PeiCpuMpData->CpuCount; sizeof (EFI_SEC_PLATFORM_INFORMATION_CPU) * PeiCpuMpData->CpuCount;
// //
// return the information size if input buffer size is too small // return the information size if input buffer size is too small
// //
if ((*StructureSize) < (UINT64) BistInformationSize) { if ((*StructureSize) < (UINT64) BistInformationSize) {
*StructureSize = (UINT64) BistInformationSize; *StructureSize = (UINT64) BistInformationSize;
return EFI_BUFFER_TOO_SMALL; return EFI_BUFFER_TOO_SMALL;
} }
PlatformInformationRecord2->NumberOfCpus = PeiCpuMpData->CpuCount; PlatformInformationRecord2->NumberOfCpus = PeiCpuMpData->CpuCount;
CpuInstance = PlatformInformationRecord2->CpuInstance; CpuInstance = PlatformInformationRecord2->CpuInstance;
for (CpuIndex = 0; CpuIndex < PeiCpuMpData->CpuCount; CpuIndex ++) { for (CpuIndex = 0; CpuIndex < PeiCpuMpData->CpuCount; CpuIndex ++) {
CpuInstance[CpuIndex].CpuLocation = PeiCpuMpData->CpuData[CpuIndex].ApicId; CpuInstance[CpuIndex].CpuLocation = PeiCpuMpData->CpuData[CpuIndex].ApicId;
CpuInstance[CpuIndex].InfoRecord.IA32HealthFlags = PeiCpuMpData->CpuData[CpuIndex].Health; CpuInstance[CpuIndex].InfoRecord.IA32HealthFlags = PeiCpuMpData->CpuData[CpuIndex].Health;
} }
return EFI_SUCCESS; return EFI_SUCCESS;
} }
/** /**
Worker function to get CPUs' BIST by calling SecPlatformInformationPpi Worker function to get CPUs' BIST by calling SecPlatformInformationPpi
or SecPlatformInformation2Ppi. or SecPlatformInformation2Ppi.
@param PeiServices Pointer to PEI Services Table @param PeiServices Pointer to PEI Services Table
@param Guid PPI Guid @param Guid PPI Guid
@param PpiDescriptor Return a pointer to instance of the @param PpiDescriptor Return a pointer to instance of the
EFI_PEI_PPI_DESCRIPTOR EFI_PEI_PPI_DESCRIPTOR
@param BistInformationData Pointer to BIST information data @param BistInformationData Pointer to BIST information data
@retval EFI_SUCCESS Retrieve of the BIST data successfully @retval EFI_SUCCESS Retrieve of the BIST data successfully
@retval EFI_NOT_FOUND No sec platform information(2) ppi export @retval EFI_NOT_FOUND No sec platform information(2) ppi export
@retval EFI_DEVICE_ERROR Failed to get CPU Information @retval EFI_DEVICE_ERROR Failed to get CPU Information
**/ **/
EFI_STATUS EFI_STATUS
GetBistInfoFromPpi ( GetBistInfoFromPpi (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN CONST EFI_GUID *Guid, IN CONST EFI_GUID *Guid,
OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
OUT VOID **BistInformationData OUT VOID **BistInformationData
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
EFI_SEC_PLATFORM_INFORMATION2_PPI *SecPlatformInformation2Ppi; EFI_SEC_PLATFORM_INFORMATION2_PPI *SecPlatformInformation2Ppi;
EFI_SEC_PLATFORM_INFORMATION_RECORD2 *SecPlatformInformation2; EFI_SEC_PLATFORM_INFORMATION_RECORD2 *SecPlatformInformation2;
UINT64 InformationSize; UINT64 InformationSize;
Status = PeiServicesLocatePpi ( Status = PeiServicesLocatePpi (
Guid, // GUID Guid, // GUID
0, // INSTANCE 0, // INSTANCE
PpiDescriptor, // EFI_PEI_PPI_DESCRIPTOR PpiDescriptor, // EFI_PEI_PPI_DESCRIPTOR
(VOID **)&SecPlatformInformation2Ppi // PPI (VOID **)&SecPlatformInformation2Ppi // PPI
); );
if (Status == EFI_NOT_FOUND) { if (Status == EFI_NOT_FOUND) {
return EFI_NOT_FOUND; return EFI_NOT_FOUND;
} }
if (Status == EFI_SUCCESS) { if (Status == EFI_SUCCESS) {
// //
// Get the size of the sec platform information2(BSP/APs' BIST data) // Get the size of the sec platform information2(BSP/APs' BIST data)
// //
InformationSize = 0; InformationSize = 0;
SecPlatformInformation2 = NULL; SecPlatformInformation2 = NULL;
Status = SecPlatformInformation2Ppi->PlatformInformation2 ( Status = SecPlatformInformation2Ppi->PlatformInformation2 (
PeiServices, PeiServices,
&InformationSize, &InformationSize,
SecPlatformInformation2 SecPlatformInformation2
); );
if (Status == EFI_BUFFER_TOO_SMALL) { if (Status == EFI_BUFFER_TOO_SMALL) {
Status = PeiServicesAllocatePool ( Status = PeiServicesAllocatePool (
(UINTN) InformationSize, (UINTN) InformationSize,
(VOID **) &SecPlatformInformation2 (VOID **) &SecPlatformInformation2
); );
if (Status == EFI_SUCCESS) { if (Status == EFI_SUCCESS) {
// //
// Retrieve BIST data // Retrieve BIST data
// //
Status = SecPlatformInformation2Ppi->PlatformInformation2 ( Status = SecPlatformInformation2Ppi->PlatformInformation2 (
PeiServices, PeiServices,
&InformationSize, &InformationSize,
SecPlatformInformation2 SecPlatformInformation2
); );
if (Status == EFI_SUCCESS) { if (Status == EFI_SUCCESS) {
*BistInformationData = SecPlatformInformation2; *BistInformationData = SecPlatformInformation2;
return EFI_SUCCESS; return EFI_SUCCESS;
} }
} }
} }
} }
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
/** /**
Collects BIST data from PPI. Collects BIST data from PPI.
This function collects BIST data from Sec Platform Information2 PPI This function collects BIST data from Sec Platform Information2 PPI
or SEC Platform Information PPI. or SEC Platform Information PPI.
@param PeiServices Pointer to PEI Services Table @param PeiServices Pointer to PEI Services Table
@param PeiCpuMpData Pointer to PEI CPU MP Data @param PeiCpuMpData Pointer to PEI CPU MP Data
**/ **/
VOID VOID
CollectBistDataFromPpi ( CollectBistDataFromPpi (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN PEI_CPU_MP_DATA *PeiCpuMpData IN PEI_CPU_MP_DATA *PeiCpuMpData
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
EFI_PEI_PPI_DESCRIPTOR *SecInformationDescriptor; EFI_PEI_PPI_DESCRIPTOR *SecInformationDescriptor;
EFI_SEC_PLATFORM_INFORMATION_RECORD2 *SecPlatformInformation2; EFI_SEC_PLATFORM_INFORMATION_RECORD2 *SecPlatformInformation2;
EFI_SEC_PLATFORM_INFORMATION_RECORD *SecPlatformInformation; EFI_SEC_PLATFORM_INFORMATION_RECORD *SecPlatformInformation;
UINTN NumberOfData; UINTN NumberOfData;
EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstance; EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstance;
EFI_SEC_PLATFORM_INFORMATION_CPU BspCpuInstance; EFI_SEC_PLATFORM_INFORMATION_CPU BspCpuInstance;
UINTN ProcessorNumber; UINTN ProcessorNumber;
UINTN CpuIndex; UINTN CpuIndex;
PEI_CPU_DATA *CpuData; PEI_CPU_DATA *CpuData;
SecPlatformInformation2 = NULL; SecPlatformInformation2 = NULL;
SecPlatformInformation = NULL; SecPlatformInformation = NULL;
NumberOfData = 0; NumberOfData = 0;
CpuInstance = NULL; CpuInstance = NULL;
// //
// Get BIST information from Sec Platform Information2 Ppi firstly // Get BIST information from Sec Platform Information2 Ppi firstly
// //
Status = GetBistInfoFromPpi ( Status = GetBistInfoFromPpi (
PeiServices, PeiServices,
&gEfiSecPlatformInformation2PpiGuid, &gEfiSecPlatformInformation2PpiGuid,
&SecInformationDescriptor, &SecInformationDescriptor,
(VOID *) &SecPlatformInformation2 (VOID *) &SecPlatformInformation2
); );
if (Status == EFI_SUCCESS) { if (Status == EFI_SUCCESS) {
// //
// Sec Platform Information2 PPI includes BSP/APs' BIST information // Sec Platform Information2 PPI includes BSP/APs' BIST information
// //
NumberOfData = SecPlatformInformation2->NumberOfCpus; NumberOfData = SecPlatformInformation2->NumberOfCpus;
CpuInstance = SecPlatformInformation2->CpuInstance; CpuInstance = SecPlatformInformation2->CpuInstance;
} else { } else {
// //
// Otherwise, get BIST information from Sec Platform Information Ppi // Otherwise, get BIST information from Sec Platform Information Ppi
// //
Status = GetBistInfoFromPpi ( Status = GetBistInfoFromPpi (
PeiServices, PeiServices,
&gEfiSecPlatformInformationPpiGuid, &gEfiSecPlatformInformationPpiGuid,
&SecInformationDescriptor, &SecInformationDescriptor,
(VOID *) &SecPlatformInformation (VOID *) &SecPlatformInformation
); );
if (Status == EFI_SUCCESS) { if (Status == EFI_SUCCESS) {
NumberOfData = 1; NumberOfData = 1;
// //
// SEC Platform Information only includes BSP's BIST information // SEC Platform Information only includes BSP's BIST information
// and does not have BSP's APIC ID // and does not have BSP's APIC ID
// //
BspCpuInstance.CpuLocation = GetInitialApicId (); BspCpuInstance.CpuLocation = GetInitialApicId ();
BspCpuInstance.InfoRecord.IA32HealthFlags.Uint32 = SecPlatformInformation->IA32HealthFlags.Uint32; BspCpuInstance.InfoRecord.IA32HealthFlags.Uint32 = SecPlatformInformation->IA32HealthFlags.Uint32;
CpuInstance = &BspCpuInstance; CpuInstance = &BspCpuInstance;
} else { } else {
DEBUG ((EFI_D_INFO, "Does not find any stored CPU BIST information from PPI!\n")); DEBUG ((EFI_D_INFO, "Does not find any stored CPU BIST information from PPI!\n"));
} }
} }
for (ProcessorNumber = 0; ProcessorNumber < PeiCpuMpData->CpuCount; ProcessorNumber ++) { for (ProcessorNumber = 0; ProcessorNumber < PeiCpuMpData->CpuCount; ProcessorNumber ++) {
CpuData = &PeiCpuMpData->CpuData[ProcessorNumber]; CpuData = &PeiCpuMpData->CpuData[ProcessorNumber];
for (CpuIndex = 0; CpuIndex < NumberOfData; CpuIndex ++) { for (CpuIndex = 0; CpuIndex < NumberOfData; CpuIndex ++) {
ASSERT (CpuInstance != NULL); ASSERT (CpuInstance != NULL);
if (CpuData->ApicId == CpuInstance[CpuIndex].CpuLocation) { if (CpuData->ApicId == CpuInstance[CpuIndex].CpuLocation) {
// //
// Update processor's BIST data if it is already stored before // Update processor's BIST data if it is already stored before
// //
CpuData->Health = CpuInstance[CpuIndex].InfoRecord.IA32HealthFlags; CpuData->Health = CpuInstance[CpuIndex].InfoRecord.IA32HealthFlags;
} }
} }
if (CpuData->Health.Uint32 != 0) { if (CpuData->Health.Uint32 != 0) {
// //
// Report Status Code that self test is failed // Report Status Code that self test is failed
// //
REPORT_STATUS_CODE ( REPORT_STATUS_CODE (
EFI_ERROR_CODE | EFI_ERROR_MAJOR, EFI_ERROR_CODE | EFI_ERROR_MAJOR,
(EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST) (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)
); );
} }
DEBUG ((EFI_D_INFO, " APICID - 0x%08x, BIST - 0x%08x\n", DEBUG ((EFI_D_INFO, " APICID - 0x%08x, BIST - 0x%08x\n",
PeiCpuMpData->CpuData[ProcessorNumber].ApicId, PeiCpuMpData->CpuData[ProcessorNumber].ApicId,
PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32 PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32
)); ));
} }
if (SecPlatformInformation2 != NULL && NumberOfData < PeiCpuMpData->CpuCount) { if (SecPlatformInformation2 != NULL && NumberOfData < PeiCpuMpData->CpuCount) {
// //
// Reinstall SecPlatformInformation2 PPI to include new BIST inforamtion // Reinstall SecPlatformInformation2 PPI to include new BIST inforamtion
// //
Status = PeiServicesReInstallPpi ( Status = PeiServicesReInstallPpi (
SecInformationDescriptor, SecInformationDescriptor,
&mPeiSecPlatformInformation2Ppi &mPeiSecPlatformInformation2Ppi
); );
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
} else { } else {
// //
// Install SecPlatformInformation2 PPI to include new BIST inforamtion // Install SecPlatformInformation2 PPI to include new BIST inforamtion
// //
Status = PeiServicesInstallPpi (&mPeiSecPlatformInformation2Ppi); Status = PeiServicesInstallPpi (&mPeiSecPlatformInformation2Ppi);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,302 +1,302 @@
/** @file /** @file
Definitions to install Multiple Processor PPI. Definitions to install Multiple Processor PPI.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/ **/
#ifndef _CPU_MP_PEI_H_ #ifndef _CPU_MP_PEI_H_
#define _CPU_MP_PEI_H_ #define _CPU_MP_PEI_H_
#include <PiPei.h> #include <PiPei.h>
#include <Ppi/MpServices.h> #include <Ppi/MpServices.h>
#include <Ppi/SecPlatformInformation.h> #include <Ppi/SecPlatformInformation.h>
#include <Ppi/SecPlatformInformation2.h> #include <Ppi/SecPlatformInformation2.h>
#include <Ppi/EndOfPeiPhase.h> #include <Ppi/EndOfPeiPhase.h>
#include <Register/LocalApic.h> #include <Register/LocalApic.h>
#include <Library/BaseLib.h> #include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h> #include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h> #include <Library/DebugLib.h>
#include <Library/HobLib.h> #include <Library/HobLib.h>
#include <Library/LocalApicLib.h> #include <Library/LocalApicLib.h>
#include <Library/MtrrLib.h> #include <Library/MtrrLib.h>
#include <Library/PcdLib.h> #include <Library/PcdLib.h>
#include <Library/PeimEntryPoint.h> #include <Library/PeimEntryPoint.h>
#include <Library/PeiServicesLib.h> #include <Library/PeiServicesLib.h>
#include <Library/ReportStatusCodeLib.h> #include <Library/ReportStatusCodeLib.h>
#include <Library/SynchronizationLib.h> #include <Library/SynchronizationLib.h>
#include <Library/TimerLib.h> #include <Library/TimerLib.h>
#include <Library/UefiCpuLib.h> #include <Library/UefiCpuLib.h>
#include "Microcode.h" #include "Microcode.h"
// //
// AP state // AP state
// //
typedef enum { typedef enum {
CpuStateIdle, CpuStateIdle,
CpuStateBusy, CpuStateBusy,
CpuStateDisabled CpuStateDisabled
} CPU_STATE; } CPU_STATE;
// //
// AP reset code information // AP reset code information
// //
typedef struct { typedef struct {
UINT8 *RendezvousFunnelAddress; UINT8 *RendezvousFunnelAddress;
UINTN PModeEntryOffset; UINTN PModeEntryOffset;
UINTN LModeEntryOffset; UINTN LModeEntryOffset;
UINTN RendezvousFunnelSize; UINTN RendezvousFunnelSize;
} MP_ASSEMBLY_ADDRESS_MAP; } MP_ASSEMBLY_ADDRESS_MAP;
// //
// CPU exchange information for switch BSP // CPU exchange information for switch BSP
// //
typedef struct { typedef struct {
UINT8 State; // offset 0 UINT8 State; // offset 0
UINTN StackPointer; // offset 4 / 8 UINTN StackPointer; // offset 4 / 8
IA32_DESCRIPTOR Gdtr; // offset 8 / 16 IA32_DESCRIPTOR Gdtr; // offset 8 / 16
IA32_DESCRIPTOR Idtr; // offset 14 / 26 IA32_DESCRIPTOR Idtr; // offset 14 / 26
} CPU_EXCHANGE_ROLE_INFO; } CPU_EXCHANGE_ROLE_INFO;
typedef struct _PEI_CPU_MP_DATA PEI_CPU_MP_DATA; typedef struct _PEI_CPU_MP_DATA PEI_CPU_MP_DATA;
#pragma pack() #pragma pack()
typedef union { typedef union {
struct { struct {
UINT32 LimitLow : 16; UINT32 LimitLow : 16;
UINT32 BaseLow : 16; UINT32 BaseLow : 16;
UINT32 BaseMid : 8; UINT32 BaseMid : 8;
UINT32 Type : 4; UINT32 Type : 4;
UINT32 System : 1; UINT32 System : 1;
UINT32 Dpl : 2; UINT32 Dpl : 2;
UINT32 Present : 1; UINT32 Present : 1;
UINT32 LimitHigh : 4; UINT32 LimitHigh : 4;
UINT32 Software : 1; UINT32 Software : 1;
UINT32 Reserved : 1; UINT32 Reserved : 1;
UINT32 DefaultSize : 1; UINT32 DefaultSize : 1;
UINT32 Granularity : 1; UINT32 Granularity : 1;
UINT32 BaseHigh : 8; UINT32 BaseHigh : 8;
} Bits; } Bits;
UINT64 Uint64; UINT64 Uint64;
} IA32_GDT; } IA32_GDT;
// //
// MP CPU exchange information for AP reset code // MP CPU exchange information for AP reset code
// //
typedef struct { typedef struct {
UINTN Lock; UINTN Lock;
UINTN StackStart; UINTN StackStart;
UINTN StackSize; UINTN StackSize;
UINTN CFunction; UINTN CFunction;
IA32_DESCRIPTOR GdtrProfile; IA32_DESCRIPTOR GdtrProfile;
IA32_DESCRIPTOR IdtrProfile; IA32_DESCRIPTOR IdtrProfile;
UINTN BufferStart; UINTN BufferStart;
UINTN PmodeOffset; UINTN PmodeOffset;
UINTN NumApsExecuting; UINTN NumApsExecuting;
UINTN LmodeOffset; UINTN LmodeOffset;
UINTN Cr3; UINTN Cr3;
PEI_CPU_MP_DATA *PeiCpuMpData; PEI_CPU_MP_DATA *PeiCpuMpData;
} MP_CPU_EXCHANGE_INFO; } MP_CPU_EXCHANGE_INFO;
#pragma pack() #pragma pack()
typedef struct { typedef struct {
UINT32 ApicId; UINT32 ApicId;
EFI_HEALTH_FLAGS Health; EFI_HEALTH_FLAGS Health;
CPU_STATE State; CPU_STATE State;
BOOLEAN CpuHealthy; BOOLEAN CpuHealthy;
} PEI_CPU_DATA; } PEI_CPU_DATA;
// //
// PEI CPU MP Data save in memory // PEI CPU MP Data save in memory
// //
struct _PEI_CPU_MP_DATA { struct _PEI_CPU_MP_DATA {
UINT32 CpuCount; UINT32 CpuCount;
UINT32 BspNumber; UINT32 BspNumber;
UINTN Buffer; UINTN Buffer;
UINTN CpuApStackSize; UINTN CpuApStackSize;
MP_ASSEMBLY_ADDRESS_MAP AddressMap; MP_ASSEMBLY_ADDRESS_MAP AddressMap;
UINTN WakeupBuffer; UINTN WakeupBuffer;
UINTN BackupBuffer; UINTN BackupBuffer;
UINTN BackupBufferSize; UINTN BackupBufferSize;
UINTN ApFunction; UINTN ApFunction;
UINTN ApFunctionArgument; UINTN ApFunctionArgument;
volatile UINT32 FinishedCount; volatile UINT32 FinishedCount;
BOOLEAN EndOfPeiFlag; BOOLEAN EndOfPeiFlag;
BOOLEAN InitFlag; BOOLEAN InitFlag;
CPU_EXCHANGE_ROLE_INFO BSPInfo; CPU_EXCHANGE_ROLE_INFO BSPInfo;
CPU_EXCHANGE_ROLE_INFO APInfo; CPU_EXCHANGE_ROLE_INFO APInfo;
MTRR_SETTINGS MtrrTable; MTRR_SETTINGS MtrrTable;
PEI_CPU_DATA *CpuData; PEI_CPU_DATA *CpuData;
volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo; volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo;
}; };
extern EFI_PEI_PPI_DESCRIPTOR mPeiCpuMpPpiDesc; extern EFI_PEI_PPI_DESCRIPTOR mPeiCpuMpPpiDesc;
/** /**
Assembly code to get starting address and size of the rendezvous entry for APs. 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. Information for fixing a jump instruction in the code is also returned.
@param AddressMap Output buffer for address map information. @param AddressMap Output buffer for address map information.
**/ **/
VOID VOID
EFIAPI EFIAPI
AsmGetAddressMap ( AsmGetAddressMap (
OUT MP_ASSEMBLY_ADDRESS_MAP *AddressMap OUT MP_ASSEMBLY_ADDRESS_MAP *AddressMap
); );
/** /**
Assembly code to load GDT table and update segment accordingly. Assembly code to load GDT table and update segment accordingly.
@param Gdtr Pointer to GDT descriptor @param Gdtr Pointer to GDT descriptor
**/ **/
VOID VOID
EFIAPI EFIAPI
AsmInitializeGdt ( AsmInitializeGdt (
IN IA32_DESCRIPTOR *Gdtr IN IA32_DESCRIPTOR *Gdtr
); );
/** /**
Assembly code to do CLI-HALT loop. Assembly code to do CLI-HALT loop.
**/ **/
VOID VOID
EFIAPI EFIAPI
AsmCliHltLoop ( AsmCliHltLoop (
VOID VOID
); );
/** /**
Get available system memory below 1MB by specified size. Get available system memory below 1MB by specified size.
@param PeiCpuMpData Pointer to PEI CPU MP Data @param PeiCpuMpData Pointer to PEI CPU MP Data
**/ **/
VOID VOID
BackupAndPrepareWakeupBuffer( BackupAndPrepareWakeupBuffer(
IN PEI_CPU_MP_DATA *PeiCpuMpData IN PEI_CPU_MP_DATA *PeiCpuMpData
); );
/** /**
Restore wakeup buffer data. Restore wakeup buffer data.
@param PeiCpuMpData Pointer to PEI CPU MP Data @param PeiCpuMpData Pointer to PEI CPU MP Data
**/ **/
VOID VOID
RestoreWakeupBuffer( RestoreWakeupBuffer(
IN PEI_CPU_MP_DATA *PeiCpuMpData IN PEI_CPU_MP_DATA *PeiCpuMpData
); );
/** /**
Notify function on End Of Pei PPI. Notify function on End Of Pei PPI.
On S3 boot, this function will restore wakeup buffer data. On S3 boot, this function will restore wakeup buffer data.
On normal boot, this function will flag wakeup buffer to be un-used type. On normal boot, this function will flag wakeup buffer to be un-used type.
@param PeiServices The pointer to the PEI Services Table. @param PeiServices The pointer to the PEI Services Table.
@param NotifyDescriptor Address of the notification descriptor data structure. @param NotifyDescriptor Address of the notification descriptor data structure.
@param Ppi Address of the PPI that was installed. @param Ppi Address of the PPI that was installed.
@retval EFI_SUCCESS When everything is OK. @retval EFI_SUCCESS When everything is OK.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
CpuMpEndOfPeiCallback ( CpuMpEndOfPeiCallback (
IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi IN VOID *Ppi
); );
/** /**
This function will be called by BSP to wakeup AP. This function will be called by BSP to wakeup AP.
@param PeiCpuMpData Pointer to PEI CPU MP Data @param PeiCpuMpData Pointer to PEI CPU MP Data
@param Broadcast TRUE: Send broadcast IPI to all APs @param Broadcast TRUE: Send broadcast IPI to all APs
FALSE: Send IPI to AP by ApicId FALSE: Send IPI to AP by ApicId
@param ApicId Apic ID for the processor to be waked @param ApicId Apic ID for the processor to be waked
@param Procedure The function to be invoked by AP @param Procedure The function to be invoked by AP
@param ProcedureArgument The argument to be passed into AP function @param ProcedureArgument The argument to be passed into AP function
**/ **/
VOID VOID
WakeUpAP ( WakeUpAP (
IN PEI_CPU_MP_DATA *PeiCpuMpData, IN PEI_CPU_MP_DATA *PeiCpuMpData,
IN BOOLEAN Broadcast, IN BOOLEAN Broadcast,
IN UINT32 ApicId, IN UINT32 ApicId,
IN EFI_AP_PROCEDURE Procedure, OPTIONAL IN EFI_AP_PROCEDURE Procedure, OPTIONAL
IN VOID *ProcedureArgument OPTIONAL IN VOID *ProcedureArgument OPTIONAL
); );
/** /**
Get CPU MP Data pointer from the Guided HOB. Get CPU MP Data pointer from the Guided HOB.
@return Pointer to Pointer to PEI CPU MP Data @return Pointer to Pointer to PEI CPU MP Data
**/ **/
PEI_CPU_MP_DATA * PEI_CPU_MP_DATA *
GetMpHobData ( GetMpHobData (
VOID VOID
); );
/** /**
Find the current Processor number by APIC ID. Find the current Processor number by APIC ID.
@param PeiCpuMpData Pointer to PEI CPU MP Data @param PeiCpuMpData Pointer to PEI CPU MP Data
@param ProcessorNumber Return the pocessor number found @param ProcessorNumber Return the pocessor number found
@retval EFI_SUCCESS ProcessorNumber is found and returned. @retval EFI_SUCCESS ProcessorNumber is found and returned.
@retval EFI_NOT_FOUND ProcessorNumber is not found. @retval EFI_NOT_FOUND ProcessorNumber is not found.
**/ **/
EFI_STATUS EFI_STATUS
GetProcessorNumber ( GetProcessorNumber (
IN PEI_CPU_MP_DATA *PeiCpuMpData, IN PEI_CPU_MP_DATA *PeiCpuMpData,
OUT UINTN *ProcessorNumber OUT UINTN *ProcessorNumber
); );
/** /**
Collects BIST data from PPI. Collects BIST data from PPI.
This function collects BIST data from Sec Platform Information2 PPI This function collects BIST data from Sec Platform Information2 PPI
or SEC Platform Information PPI. or SEC Platform Information PPI.
@param PeiServices Pointer to PEI Services Table @param PeiServices Pointer to PEI Services Table
@param PeiCpuMpData Pointer to PEI CPU MP Data @param PeiCpuMpData Pointer to PEI CPU MP Data
**/ **/
VOID VOID
CollectBistDataFromPpi ( CollectBistDataFromPpi (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN PEI_CPU_MP_DATA *PeiCpuMpData IN PEI_CPU_MP_DATA *PeiCpuMpData
); );
/** /**
Implementation of the PlatformInformation2 service in EFI_SEC_PLATFORM_INFORMATION2_PPI. Implementation of the PlatformInformation2 service in EFI_SEC_PLATFORM_INFORMATION2_PPI.
@param PeiServices The pointer to the PEI Services Table. @param PeiServices The pointer to the PEI Services Table.
@param StructureSize The pointer to the variable describing size of the input buffer. @param StructureSize The pointer to the variable describing size of the input buffer.
@param PlatformInformationRecord2 The pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD2. @param PlatformInformationRecord2 The pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD2.
@retval EFI_SUCCESS The data was successfully returned. @retval EFI_SUCCESS The data was successfully returned.
@retval EFI_BUFFER_TOO_SMALL The buffer was too small. The current buffer size needed to @retval EFI_BUFFER_TOO_SMALL The buffer was too small. The current buffer size needed to
hold the record is returned in StructureSize. hold the record is returned in StructureSize.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
SecPlatformInformation2 ( SecPlatformInformation2 (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN OUT UINT64 *StructureSize, IN OUT UINT64 *StructureSize,
OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2 OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2
); );
#endif #endif

View File

@ -1,90 +1,90 @@
## @file ## @file
# CPU driver installs CPU PI Multi-processor PPI. # CPU driver installs CPU PI Multi-processor PPI.
# #
# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials # This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License # 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 # which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php # http://opensource.org/licenses/bsd-license.php
# #
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
# #
## ##
[Defines] [Defines]
INF_VERSION = 0x00010005 INF_VERSION = 0x00010005
BASE_NAME = CpuMpPei BASE_NAME = CpuMpPei
MODULE_UNI_FILE = CpuMpPei.uni MODULE_UNI_FILE = CpuMpPei.uni
FILE_GUID = EDADEB9D-DDBA-48BD-9D22-C1C169C8C5C6 FILE_GUID = EDADEB9D-DDBA-48BD-9D22-C1C169C8C5C6
MODULE_TYPE = PEIM MODULE_TYPE = PEIM
VERSION_STRING = 1.0 VERSION_STRING = 1.0
ENTRY_POINT = CpuMpPeimInit ENTRY_POINT = CpuMpPeimInit
# #
# The following information is for reference only and not required by the build tools. # The following information is for reference only and not required by the build tools.
# #
# VALID_ARCHITECTURES = IA32 X64 # VALID_ARCHITECTURES = IA32 X64
# #
[Sources] [Sources]
CpuMpPei.h CpuMpPei.h
CpuMpPei.c CpuMpPei.c
CpuBist.c CpuBist.c
Microcode.h Microcode.h
Microcode.c Microcode.c
PeiMpServices.h PeiMpServices.h
PeiMpServices.c PeiMpServices.c
[Sources.IA32] [Sources.IA32]
Ia32/MpEqu.inc Ia32/MpEqu.inc
Ia32/MpFuncs.asm | MSFT Ia32/MpFuncs.asm | MSFT
Ia32/MpFuncs.asm | INTEL Ia32/MpFuncs.asm | INTEL
Ia32/MpFuncs.nasm | GCC Ia32/MpFuncs.nasm | GCC
[Sources.X64] [Sources.X64]
X64/MpEqu.inc X64/MpEqu.inc
X64/MpFuncs.asm | MSFT X64/MpFuncs.asm | MSFT
X64/MpFuncs.asm | INTEL X64/MpFuncs.asm | INTEL
X64/MpFuncs.nasm | GCC X64/MpFuncs.nasm | GCC
[Packages] [Packages]
MdePkg/MdePkg.dec MdePkg/MdePkg.dec
UefiCpuPkg/UefiCpuPkg.dec UefiCpuPkg/UefiCpuPkg.dec
[LibraryClasses] [LibraryClasses]
BaseLib BaseLib
BaseMemoryLib BaseMemoryLib
DebugLib DebugLib
HobLib HobLib
LocalApicLib LocalApicLib
MtrrLib MtrrLib
PcdLib PcdLib
PeimEntryPoint PeimEntryPoint
PeiServicesLib PeiServicesLib
ReportStatusCodeLib ReportStatusCodeLib
SynchronizationLib SynchronizationLib
TimerLib TimerLib
UefiCpuLib UefiCpuLib
[Ppis] [Ppis]
gEfiPeiMpServicesPpiGuid ## PRODUCES gEfiPeiMpServicesPpiGuid ## PRODUCES
gEfiEndOfPeiSignalPpiGuid ## NOTIFY gEfiEndOfPeiSignalPpiGuid ## NOTIFY
gEfiSecPlatformInformationPpiGuid ## SOMETIMES_CONSUMES gEfiSecPlatformInformationPpiGuid ## SOMETIMES_CONSUMES
## SOMETIMES_CONSUMES ## SOMETIMES_CONSUMES
## SOMETIMES_PRODUCES ## SOMETIMES_PRODUCES
gEfiSecPlatformInformation2PpiGuid gEfiSecPlatformInformation2PpiGuid
[Pcd] [Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES
[Depex] [Depex]
gEfiPeiMemoryDiscoveredPpiGuid gEfiPeiMemoryDiscoveredPpiGuid
[UserExtensions.TianoCore."ExtraFiles"] [UserExtensions.TianoCore."ExtraFiles"]
CpuMpPeiExtra.uni CpuMpPeiExtra.uni

View File

@ -1,40 +1,40 @@
;------------------------------------------------------------------------------ ; ;------------------------------------------------------------------------------ ;
; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> ; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
; This program and the accompanying materials ; This program and the accompanying materials
; are licensed and made available under the terms and conditions of the BSD License ; 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 ; which accompanies this distribution. The full text of the license may be found at
; http://opensource.org/licenses/bsd-license.php. ; http://opensource.org/licenses/bsd-license.php.
; ;
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
; ;
; Module Name: ; Module Name:
; ;
; MpEqu.inc ; MpEqu.inc
; ;
; Abstract: ; Abstract:
; ;
; This is the equates file for Multiple Processor support ; This is the equates file for Multiple Processor support
; ;
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
PROTECT_MODE_CS equ 10h PROTECT_MODE_CS equ 10h
PROTECT_MODE_DS equ 18h PROTECT_MODE_DS equ 18h
VacantFlag equ 00h VacantFlag equ 00h
NotVacantFlag equ 0ffh NotVacantFlag equ 0ffh
CPU_SWITCH_STATE_IDLE equ 0 CPU_SWITCH_STATE_IDLE equ 0
CPU_SWITCH_STATE_STORED equ 1 CPU_SWITCH_STATE_STORED equ 1
CPU_SWITCH_STATE_LOADED equ 2 CPU_SWITCH_STATE_LOADED equ 2
LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart) LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)
StackStartAddressLocation equ LockLocation + 04h StackStartAddressLocation equ LockLocation + 04h
StackSizeLocation equ LockLocation + 08h StackSizeLocation equ LockLocation + 08h
ApProcedureLocation equ LockLocation + 0Ch ApProcedureLocation equ LockLocation + 0Ch
GdtrLocation equ LockLocation + 10h GdtrLocation equ LockLocation + 10h
IdtrLocation equ LockLocation + 16h IdtrLocation equ LockLocation + 16h
BufferStartLocation equ LockLocation + 1Ch BufferStartLocation equ LockLocation + 1Ch
PmodeOffsetLocation equ LockLocation + 20h PmodeOffsetLocation equ LockLocation + 20h
NumApsExecutingLoction equ LockLocation + 24h NumApsExecutingLoction equ LockLocation + 24h

View File

@ -1,276 +1,276 @@
;------------------------------------------------------------------------------ ; ;------------------------------------------------------------------------------ ;
; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> ; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
; This program and the accompanying materials ; This program and the accompanying materials
; are licensed and made available under the terms and conditions of the BSD License ; 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 ; which accompanies this distribution. The full text of the license may be found at
; http://opensource.org/licenses/bsd-license.php. ; http://opensource.org/licenses/bsd-license.php.
; ;
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
; ;
; Module Name: ; Module Name:
; ;
; MpFuncs32.asm ; MpFuncs32.asm
; ;
; Abstract: ; Abstract:
; ;
; This is the assembly code for MP support ; This is the assembly code for MP support
; ;
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
.686p .686p
.model flat .model flat
include MpEqu.inc include MpEqu.inc
InitializeFloatingPointUnits PROTO C InitializeFloatingPointUnits PROTO C
.code .code
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
;RendezvousFunnelProc procedure follows. All APs execute their procedure. This ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
;procedure serializes all the AP processors through an Init sequence. It must be ;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. ;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 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
;IS IN MACHINE CODE. ;IS IN MACHINE CODE.
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
RendezvousFunnelProc PROC PUBLIC RendezvousFunnelProc PROC PUBLIC
RendezvousFunnelProcStart:: RendezvousFunnelProcStart::
; At this point CS = 0x(vv00) and ip= 0x0. ; At this point CS = 0x(vv00) and ip= 0x0.
; Save BIST information to ebp firstly ; Save BIST information to ebp firstly
db 66h, 08bh, 0e8h ; mov ebp, eax ; save BIST information db 66h, 08bh, 0e8h ; mov ebp, eax ; save BIST information
db 8ch,0c8h ; mov ax,cs db 8ch,0c8h ; mov ax,cs
db 8eh,0d8h ; mov ds,ax db 8eh,0d8h ; mov ds,ax
db 8eh,0c0h ; mov es,ax db 8eh,0c0h ; mov es,ax
db 8eh,0d0h ; mov ss,ax db 8eh,0d0h ; mov ss,ax
db 33h,0c0h ; xor ax,ax db 33h,0c0h ; xor ax,ax
db 8eh,0e0h ; mov fs,ax db 8eh,0e0h ; mov fs,ax
db 8eh,0e8h ; mov gs,ax db 8eh,0e8h ; mov gs,ax
db 0BEh ; opcode of mov si, mem16 db 0BEh ; opcode of mov si, mem16
dw BufferStartLocation ; mov si, BufferStartLocation dw BufferStartLocation ; mov si, BufferStartLocation
db 66h, 8Bh, 1Ch ; mov ebx,dword ptr [si] db 66h, 8Bh, 1Ch ; mov ebx,dword ptr [si]
db 0BFh ; opcode of mov di, mem16 db 0BFh ; opcode of mov di, mem16
dw PmodeOffsetLocation ; mov di, PmodeOffsetLocation dw PmodeOffsetLocation ; mov di, PmodeOffsetLocation
db 66h, 8Bh, 05h ; mov eax,dword ptr [di] db 66h, 8Bh, 05h ; mov eax,dword ptr [di]
db 8Bh, 0F8h ; mov di, ax db 8Bh, 0F8h ; mov di, ax
db 83h, 0EFh,06h ; sub di, 06h db 83h, 0EFh,06h ; sub di, 06h
db 66h, 03h, 0C3h ; add eax, ebx db 66h, 03h, 0C3h ; add eax, ebx
db 66h, 89h, 05h ; mov dword ptr [di],eax db 66h, 89h, 05h ; mov dword ptr [di],eax
db 0BEh ; opcode of mov si, mem16 db 0BEh ; opcode of mov si, mem16
dw GdtrLocation ; mov si, GdtrLocation dw GdtrLocation ; mov si, GdtrLocation
db 66h ; db 66h db 66h ; db 66h
db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si] db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
db 0BEh db 0BEh
dw IdtrLocation ; mov si, IdtrLocation dw IdtrLocation ; mov si, IdtrLocation
db 66h ; db 66h db 66h ; db 66h
db 2Eh,0Fh, 01h, 1Ch ; lidt fword ptr cs:[si] db 2Eh,0Fh, 01h, 1Ch ; lidt fword ptr cs:[si]
db 33h, 0C0h ; xor ax, ax db 33h, 0C0h ; xor ax, ax
db 8Eh, 0D8h ; mov ds, ax db 8Eh, 0D8h ; mov ds, ax
db 0Fh, 20h, 0C0h ; mov eax, cr0 ;Get control register 0 db 0Fh, 20h, 0C0h ; mov eax, cr0 ;Get control register 0
db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ;Set PE bit (bit #0) & MP db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ;Set PE bit (bit #0) & MP
db 0Fh, 22h, 0C0h ; mov cr0, eax db 0Fh, 22h, 0C0h ; mov cr0, eax
db 66h, 67h, 0EAh ; far jump db 66h, 67h, 0EAh ; far jump
dd 0h ; 32-bit offset dd 0h ; 32-bit offset
dw PROTECT_MODE_CS ; 16-bit selector dw PROTECT_MODE_CS ; 16-bit selector
Flat32Start:: ; protected mode entry point Flat32Start:: ; protected mode entry point
mov ax, PROTECT_MODE_DS mov ax, PROTECT_MODE_DS
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
mov esi, ebx mov esi, ebx
mov edi, esi mov edi, esi
add edi, LockLocation add edi, LockLocation
mov eax, NotVacantFlag mov eax, NotVacantFlag
TestLock: TestLock:
xchg dword ptr [edi], eax xchg dword ptr [edi], eax
cmp eax, NotVacantFlag cmp eax, NotVacantFlag
jz TestLock jz TestLock
mov edi, esi mov edi, esi
add edi, NumApsExecutingLoction add edi, NumApsExecutingLoction
inc dword ptr [edi] inc dword ptr [edi]
mov ebx, dword ptr [edi] mov ebx, dword ptr [edi]
ProgramStack: ProgramStack:
mov edi, esi mov edi, esi
add edi, StackSizeLocation add edi, StackSizeLocation
mov eax, dword ptr [edi] mov eax, dword ptr [edi]
mov edi, esi mov edi, esi
add edi, StackStartAddressLocation add edi, StackStartAddressLocation
add eax, dword ptr [edi] add eax, dword ptr [edi]
mov esp, eax mov esp, eax
mov dword ptr [edi], eax mov dword ptr [edi], eax
Releaselock: Releaselock:
mov eax, VacantFlag mov eax, VacantFlag
mov edi, esi mov edi, esi
add edi, LockLocation add edi, LockLocation
xchg dword ptr [edi], eax xchg dword ptr [edi], eax
CProcedureInvoke: CProcedureInvoke:
push ebp ; push BIST data at top of AP stack push ebp ; push BIST data at top of AP stack
xor ebp, ebp ; clear ebp for call stack trace xor ebp, ebp ; clear ebp for call stack trace
push ebp push ebp
mov ebp, esp mov ebp, esp
mov eax, InitializeFloatingPointUnits mov eax, InitializeFloatingPointUnits
call eax ; Call assembly function to initialize FPU per UEFI spec call eax ; Call assembly function to initialize FPU per UEFI spec
push ebx ; Push NumApsExecuting push ebx ; Push NumApsExecuting
mov eax, esi mov eax, esi
add eax, LockLocation add eax, LockLocation
push eax ; push address of exchange info data buffer push eax ; push address of exchange info data buffer
mov edi, esi mov edi, esi
add edi, ApProcedureLocation add edi, ApProcedureLocation
mov eax, dword ptr [edi] mov eax, dword ptr [edi]
call eax ; invoke C function call eax ; invoke C function
jmp $ ; never reach here jmp $ ; never reach here
RendezvousFunnelProc ENDP RendezvousFunnelProc ENDP
RendezvousFunnelProcEnd:: RendezvousFunnelProcEnd::
AsmCliHltLoop PROC near C PUBLIC AsmCliHltLoop PROC near C PUBLIC
cli cli
hlt hlt
jmp $-2 jmp $-2
AsmCliHltLoop ENDP AsmCliHltLoop ENDP
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
; AsmGetAddressMap (&AddressMap); ; AsmGetAddressMap (&AddressMap);
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
AsmGetAddressMap PROC near C PUBLIC AsmGetAddressMap PROC near C PUBLIC
pushad pushad
mov ebp,esp mov ebp,esp
mov ebx, dword ptr [ebp+24h] mov ebx, dword ptr [ebp+24h]
mov dword ptr [ebx], RendezvousFunnelProcStart mov dword ptr [ebx], RendezvousFunnelProcStart
mov dword ptr [ebx + 4h], Flat32Start - RendezvousFunnelProcStart mov dword ptr [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
mov dword ptr [ebx + 8h], 0 mov dword ptr [ebx + 8h], 0
mov dword ptr [ebx + 0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart mov dword ptr [ebx + 0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
popad popad
ret ret
AsmGetAddressMap ENDP AsmGetAddressMap ENDP
PAUSE32 MACRO PAUSE32 MACRO
DB 0F3h DB 0F3h
DB 090h DB 090h
ENDM ENDM
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
;about to become an AP. It switches it'stack with the current AP. ;about to become an AP. It switches it'stack with the current AP.
;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo); ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
AsmExchangeRole PROC near C PUBLIC AsmExchangeRole PROC near C PUBLIC
; DO NOT call other functions in this function, since 2 CPU may use 1 stack ; 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. ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
pushad pushad
mov ebp,esp mov ebp,esp
; esi contains MyInfo pointer ; esi contains MyInfo pointer
mov esi, dword ptr [ebp+24h] mov esi, dword ptr [ebp+24h]
; edi contains OthersInfo pointer ; edi contains OthersInfo pointer
mov edi, dword ptr [ebp+28h] mov edi, dword ptr [ebp+28h]
;Store EFLAGS, GDTR and IDTR register to stack ;Store EFLAGS, GDTR and IDTR register to stack
pushfd pushfd
mov eax, cr4 mov eax, cr4
push eax ; push cr4 firstly push eax ; push cr4 firstly
mov eax, cr0 mov eax, cr0
push eax push eax
sgdt fword ptr [esi+8] sgdt fword ptr [esi+8]
sidt fword ptr [esi+14] sidt fword ptr [esi+14]
; Store the its StackPointer ; Store the its StackPointer
mov dword ptr [esi+4],esp mov dword ptr [esi+4],esp
; update its switch state to STORED ; update its switch state to STORED
mov byte ptr [esi], CPU_SWITCH_STATE_STORED mov byte ptr [esi], CPU_SWITCH_STATE_STORED
WaitForOtherStored: WaitForOtherStored:
; wait until the other CPU finish storing its state ; wait until the other CPU finish storing its state
cmp byte ptr [edi], CPU_SWITCH_STATE_STORED cmp byte ptr [edi], CPU_SWITCH_STATE_STORED
jz OtherStored jz OtherStored
PAUSE32 PAUSE32
jmp WaitForOtherStored jmp WaitForOtherStored
OtherStored: OtherStored:
; Since another CPU already stored its state, load them ; Since another CPU already stored its state, load them
; load GDTR value ; load GDTR value
lgdt fword ptr [edi+8] lgdt fword ptr [edi+8]
; load IDTR value ; load IDTR value
lidt fword ptr [edi+14] lidt fword ptr [edi+14]
; load its future StackPointer ; load its future StackPointer
mov esp, dword ptr [edi+4] mov esp, dword ptr [edi+4]
; update the other CPU's switch state to LOADED ; update the other CPU's switch state to LOADED
mov byte ptr [edi], CPU_SWITCH_STATE_LOADED mov byte ptr [edi], CPU_SWITCH_STATE_LOADED
WaitForOtherLoaded: WaitForOtherLoaded:
; wait until the other CPU finish loading new state, ; wait until the other CPU finish loading new state,
; otherwise the data in stack may corrupt ; otherwise the data in stack may corrupt
cmp byte ptr [esi], CPU_SWITCH_STATE_LOADED cmp byte ptr [esi], CPU_SWITCH_STATE_LOADED
jz OtherLoaded jz OtherLoaded
PAUSE32 PAUSE32
jmp WaitForOtherLoaded jmp WaitForOtherLoaded
OtherLoaded: OtherLoaded:
; since the other CPU already get the data it want, leave this procedure ; since the other CPU already get the data it want, leave this procedure
pop eax pop eax
mov cr0, eax mov cr0, eax
pop eax pop eax
mov cr4, eax mov cr4, eax
popfd popfd
popad popad
ret ret
AsmExchangeRole ENDP AsmExchangeRole ENDP
AsmInitializeGdt PROC near C PUBLIC AsmInitializeGdt PROC near C PUBLIC
push ebp push ebp
mov ebp, esp mov ebp, esp
pushad pushad
mov edi, [ebp + 8] ; Load GDT register mov edi, [ebp + 8] ; Load GDT register
mov ax,cs ; Get the selector data from our code image mov ax,cs ; Get the selector data from our code image
mov es,ax mov es,ax
lgdt FWORD PTR es:[edi] ; and update the GDTR lgdt FWORD PTR es:[edi] ; and update the GDTR
push PROTECT_MODE_CS push PROTECT_MODE_CS
lea eax, SetCodeSelectorFarJump lea eax, SetCodeSelectorFarJump
push eax push eax
retf retf
SetCodeSelectorFarJump: SetCodeSelectorFarJump:
mov ax, PROTECT_MODE_DS ; Update the Base for the new selectors, too mov ax, PROTECT_MODE_DS ; Update the Base for the new selectors, too
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
popad popad
pop ebp pop ebp
ret ret
AsmInitializeGdt ENDP AsmInitializeGdt ENDP
END END

View File

@ -1,255 +1,255 @@
;------------------------------------------------------------------------------ ; ;------------------------------------------------------------------------------ ;
; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> ; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
; This program and the accompanying materials ; This program and the accompanying materials
; are licensed and made available under the terms and conditions of the BSD License ; 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 ; which accompanies this distribution. The full text of the license may be found at
; http://opensource.org/licenses/bsd-license.php. ; http://opensource.org/licenses/bsd-license.php.
; ;
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
; ;
; Module Name: ; Module Name:
; ;
; MpFuncs.nasm ; MpFuncs.nasm
; ;
; Abstract: ; Abstract:
; ;
; This is the assembly code for MP support ; This is the assembly code for MP support
; ;
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
%include "MpEqu.inc" %include "MpEqu.inc"
extern ASM_PFX(InitializeFloatingPointUnits) extern ASM_PFX(InitializeFloatingPointUnits)
SECTION .text SECTION .text
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
;RendezvousFunnelProc procedure follows. All APs execute their procedure. This ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
;procedure serializes all the AP processors through an Init sequence. It must be ;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. ;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 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
;IS IN MACHINE CODE. ;IS IN MACHINE CODE.
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
global ASM_PFX(RendezvousFunnelProc) global ASM_PFX(RendezvousFunnelProc)
ASM_PFX(RendezvousFunnelProc): ASM_PFX(RendezvousFunnelProc):
RendezvousFunnelProcStart: RendezvousFunnelProcStart:
; At this point CS = 0x(vv00) and ip= 0x0. ; At this point CS = 0x(vv00) and ip= 0x0.
BITS 16 BITS 16
mov ebp, eax ; save BIST information mov ebp, eax ; save BIST information
mov ax, cs mov ax, cs
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov ss, ax mov ss, ax
xor ax, ax xor ax, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov si, BufferStartLocation mov si, BufferStartLocation
mov ebx, [si] mov ebx, [si]
mov di, PmodeOffsetLocation mov di, PmodeOffsetLocation
mov eax, [di] mov eax, [di]
mov di, ax mov di, ax
sub di, 06h sub di, 06h
add eax, ebx add eax, ebx
mov [di],eax mov [di],eax
mov si, GdtrLocation mov si, GdtrLocation
o32 lgdt [cs:si] o32 lgdt [cs:si]
mov si, IdtrLocation mov si, IdtrLocation
o32 lidt [cs:si] o32 lidt [cs:si]
xor ax, ax xor ax, ax
mov ds, ax mov ds, ax
mov eax, cr0 ;Get control register 0 mov eax, cr0 ;Get control register 0
or eax, 000000003h ;Set PE bit (bit #0) & MP or eax, 000000003h ;Set PE bit (bit #0) & MP
mov cr0, eax mov cr0, eax
jmp PROTECT_MODE_CS:strict dword 0 ; far jump to protected mode jmp PROTECT_MODE_CS:strict dword 0 ; far jump to protected mode
BITS 32 BITS 32
Flat32Start: ; protected mode entry point Flat32Start: ; protected mode entry point
mov ax, PROTECT_MODE_DS mov ax, PROTECT_MODE_DS
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
mov esi, ebx mov esi, ebx
mov edi, esi mov edi, esi
add edi, LockLocation add edi, LockLocation
mov eax, NotVacantFlag mov eax, NotVacantFlag
TestLock: TestLock:
xchg [edi], eax xchg [edi], eax
cmp eax, NotVacantFlag cmp eax, NotVacantFlag
jz TestLock jz TestLock
mov edi, esi mov edi, esi
add edi, NumApsExecutingLoction add edi, NumApsExecutingLoction
inc dword [edi] inc dword [edi]
mov ebx, [edi] mov ebx, [edi]
ProgramStack: ProgramStack:
mov edi, esi mov edi, esi
add edi, StackSizeLocation add edi, StackSizeLocation
mov eax, [edi] mov eax, [edi]
mov edi, esi mov edi, esi
add edi, StackStartAddressLocation add edi, StackStartAddressLocation
add eax, [edi] add eax, [edi]
mov esp, eax mov esp, eax
mov [edi], eax mov [edi], eax
Releaselock: Releaselock:
mov eax, VacantFlag mov eax, VacantFlag
mov edi, esi mov edi, esi
add edi, LockLocation add edi, LockLocation
xchg [edi], eax xchg [edi], eax
CProcedureInvoke: CProcedureInvoke:
push ebp ; push BIST data at top of AP stack push ebp ; push BIST data at top of AP stack
xor ebp, ebp ; clear ebp for call stack trace xor ebp, ebp ; clear ebp for call stack trace
push ebp push ebp
mov ebp, esp mov ebp, esp
mov eax, ASM_PFX(InitializeFloatingPointUnits) mov eax, ASM_PFX(InitializeFloatingPointUnits)
call eax ; Call assembly function to initialize FPU per UEFI spec call eax ; Call assembly function to initialize FPU per UEFI spec
push ebx ; Push NumApsExecuting push ebx ; Push NumApsExecuting
mov eax, esi mov eax, esi
add eax, LockLocation add eax, LockLocation
push eax ; push address of exchange info data buffer push eax ; push address of exchange info data buffer
mov edi, esi mov edi, esi
add edi, ApProcedureLocation add edi, ApProcedureLocation
mov eax, [edi] mov eax, [edi]
call eax ; invoke C function call eax ; invoke C function
jmp $ ; never reach here jmp $ ; never reach here
RendezvousFunnelProcEnd: RendezvousFunnelProcEnd:
global ASM_PFX(AsmCliHltLoop) global ASM_PFX(AsmCliHltLoop)
ASM_PFX(AsmCliHltLoop): ASM_PFX(AsmCliHltLoop):
cli cli
hlt hlt
jmp $-2 jmp $-2
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
; AsmGetAddressMap (&AddressMap); ; AsmGetAddressMap (&AddressMap);
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
global ASM_PFX(AsmGetAddressMap) global ASM_PFX(AsmGetAddressMap)
ASM_PFX(AsmGetAddressMap): ASM_PFX(AsmGetAddressMap):
pushad pushad
mov ebp,esp mov ebp,esp
mov ebx, [ebp + 24h] mov ebx, [ebp + 24h]
mov dword [ebx], RendezvousFunnelProcStart mov dword [ebx], RendezvousFunnelProcStart
mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
mov dword [ebx + 8h], 0 mov dword [ebx + 8h], 0
mov dword [ebx + 0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart mov dword [ebx + 0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
popad popad
ret ret
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
;about to become an AP. It switches it'stack with the current AP. ;about to become an AP. It switches it'stack with the current AP.
;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo); ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
global ASM_PFX(AsmExchangeRole) global ASM_PFX(AsmExchangeRole)
ASM_PFX(AsmExchangeRole): ASM_PFX(AsmExchangeRole):
; DO NOT call other functions in this function, since 2 CPU may use 1 stack ; 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. ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
pushad pushad
mov ebp,esp mov ebp,esp
; esi contains MyInfo pointer ; esi contains MyInfo pointer
mov esi, [ebp + 24h] mov esi, [ebp + 24h]
; edi contains OthersInfo pointer ; edi contains OthersInfo pointer
mov edi, [ebp + 28h] mov edi, [ebp + 28h]
;Store EFLAGS, GDTR and IDTR register to stack ;Store EFLAGS, GDTR and IDTR register to stack
pushfd pushfd
mov eax, cr4 mov eax, cr4
push eax ; push cr4 firstly push eax ; push cr4 firstly
mov eax, cr0 mov eax, cr0
push eax push eax
sgdt [esi + 8] sgdt [esi + 8]
sidt [esi + 14] sidt [esi + 14]
; Store the its StackPointer ; Store the its StackPointer
mov [esi + 4],esp mov [esi + 4],esp
; update its switch state to STORED ; update its switch state to STORED
mov byte [esi], CPU_SWITCH_STATE_STORED mov byte [esi], CPU_SWITCH_STATE_STORED
WaitForOtherStored: WaitForOtherStored:
; wait until the other CPU finish storing its state ; wait until the other CPU finish storing its state
cmp byte [edi], CPU_SWITCH_STATE_STORED cmp byte [edi], CPU_SWITCH_STATE_STORED
jz OtherStored jz OtherStored
pause pause
jmp WaitForOtherStored jmp WaitForOtherStored
OtherStored: OtherStored:
; Since another CPU already stored its state, load them ; Since another CPU already stored its state, load them
; load GDTR value ; load GDTR value
lgdt [edi + 8] lgdt [edi + 8]
; load IDTR value ; load IDTR value
lidt [edi + 14] lidt [edi + 14]
; load its future StackPointer ; load its future StackPointer
mov esp, [edi + 4] mov esp, [edi + 4]
; update the other CPU's switch state to LOADED ; update the other CPU's switch state to LOADED
mov byte [edi], CPU_SWITCH_STATE_LOADED mov byte [edi], CPU_SWITCH_STATE_LOADED
WaitForOtherLoaded: WaitForOtherLoaded:
; wait until the other CPU finish loading new state, ; wait until the other CPU finish loading new state,
; otherwise the data in stack may corrupt ; otherwise the data in stack may corrupt
cmp byte [esi], CPU_SWITCH_STATE_LOADED cmp byte [esi], CPU_SWITCH_STATE_LOADED
jz OtherLoaded jz OtherLoaded
pause pause
jmp WaitForOtherLoaded jmp WaitForOtherLoaded
OtherLoaded: OtherLoaded:
; since the other CPU already get the data it want, leave this procedure ; since the other CPU already get the data it want, leave this procedure
pop eax pop eax
mov cr0, eax mov cr0, eax
pop eax pop eax
mov cr4, eax mov cr4, eax
popfd popfd
popad popad
ret ret
global ASM_PFX(AsmInitializeGdt) global ASM_PFX(AsmInitializeGdt)
ASM_PFX(AsmInitializeGdt): ASM_PFX(AsmInitializeGdt):
push ebp push ebp
mov ebp, esp mov ebp, esp
pushad pushad
mov edi, [ebp + 8] ; Load GDT register mov edi, [ebp + 8] ; Load GDT register
lgdt [edi] ; and update the GDTR lgdt [edi] ; and update the GDTR
push PROTECT_MODE_CS push PROTECT_MODE_CS
mov eax, ASM_PFX(SetCodeSelectorFarJump) mov eax, ASM_PFX(SetCodeSelectorFarJump)
push eax push eax
retf retf
ASM_PFX(SetCodeSelectorFarJump): ASM_PFX(SetCodeSelectorFarJump):
mov ax, PROTECT_MODE_DS ; Update the Base for the new selectors, too mov ax, PROTECT_MODE_DS ; Update the Base for the new selectors, too
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
popad popad
pop ebp pop ebp
ret ret

View File

@ -1,200 +1,200 @@
/** @file /** @file
Implementation of loading microcode on processors. Implementation of loading microcode on processors.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/ **/
#include "CpuMpPei.h" #include "CpuMpPei.h"
/** /**
Get microcode update signature of currently loaded microcode update. Get microcode update signature of currently loaded microcode update.
@return Microcode signature. @return Microcode signature.
**/ **/
UINT32 UINT32
GetCurrentMicrocodeSignature ( GetCurrentMicrocodeSignature (
VOID VOID
) )
{ {
UINT64 Signature; UINT64 Signature;
AsmWriteMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID, 0); AsmWriteMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID, 0);
AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL); AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
Signature = AsmReadMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID); Signature = AsmReadMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID);
return (UINT32) RShiftU64 (Signature, 32); return (UINT32) RShiftU64 (Signature, 32);
} }
/** /**
Detect whether specified processor can find matching microcode patch and load it. Detect whether specified processor can find matching microcode patch and load it.
**/ **/
VOID VOID
MicrocodeDetect ( MicrocodeDetect (
VOID VOID
) )
{ {
UINT64 MicrocodePatchAddress; UINT64 MicrocodePatchAddress;
UINT64 MicrocodePatchRegionSize; UINT64 MicrocodePatchRegionSize;
UINT32 ExtendedTableLength; UINT32 ExtendedTableLength;
UINT32 ExtendedTableCount; UINT32 ExtendedTableCount;
EFI_CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable; EFI_CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;
EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader; EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;
EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint; EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
UINTN MicrocodeEnd; UINTN MicrocodeEnd;
UINTN Index; UINTN Index;
UINT8 PlatformId; UINT8 PlatformId;
UINT32 RegEax; UINT32 RegEax;
UINT32 LatestRevision; UINT32 LatestRevision;
UINTN TotalSize; UINTN TotalSize;
UINT32 CheckSum32; UINT32 CheckSum32;
BOOLEAN CorrectMicrocode; BOOLEAN CorrectMicrocode;
INT32 CurrentSignature; INT32 CurrentSignature;
MICROCODE_INFO MicrocodeInfo; MICROCODE_INFO MicrocodeInfo;
ZeroMem (&MicrocodeInfo, sizeof (MICROCODE_INFO)); ZeroMem (&MicrocodeInfo, sizeof (MICROCODE_INFO));
MicrocodePatchAddress = PcdGet64 (PcdCpuMicrocodePatchAddress); MicrocodePatchAddress = PcdGet64 (PcdCpuMicrocodePatchAddress);
MicrocodePatchRegionSize = PcdGet64 (PcdCpuMicrocodePatchRegionSize); MicrocodePatchRegionSize = PcdGet64 (PcdCpuMicrocodePatchRegionSize);
if (MicrocodePatchRegionSize == 0) { if (MicrocodePatchRegionSize == 0) {
// //
// There is no microcode patches // There is no microcode patches
// //
return; return;
} }
ExtendedTableLength = 0; ExtendedTableLength = 0;
// //
// Here data of CPUID leafs have not been collected into context buffer, so // Here data of CPUID leafs have not been collected into context buffer, so
// GetProcessorCpuid() cannot be used here to retrieve CPUID data. // GetProcessorCpuid() cannot be used here to retrieve CPUID data.
// //
AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL); AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
// //
// The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID
// //
PlatformId = (UINT8) AsmMsrBitFieldRead64 (EFI_MSR_IA32_PLATFORM_ID, 50, 52); PlatformId = (UINT8) AsmMsrBitFieldRead64 (EFI_MSR_IA32_PLATFORM_ID, 50, 52);
LatestRevision = 0; LatestRevision = 0;
MicrocodeEnd = (UINTN) (MicrocodePatchAddress + MicrocodePatchRegionSize); MicrocodeEnd = (UINTN) (MicrocodePatchAddress + MicrocodePatchRegionSize);
MicrocodeEntryPoint = (EFI_CPU_MICROCODE_HEADER *) (UINTN) MicrocodePatchAddress; MicrocodeEntryPoint = (EFI_CPU_MICROCODE_HEADER *) (UINTN) MicrocodePatchAddress;
do { do {
// //
// Check if the microcode is for the Cpu and the version is newer // Check if the microcode is for the Cpu and the version is newer
// and the update can be processed on the platform // and the update can be processed on the platform
// //
CorrectMicrocode = FALSE; CorrectMicrocode = FALSE;
if (MicrocodeEntryPoint->HeaderVersion == 0x1) { if (MicrocodeEntryPoint->HeaderVersion == 0x1) {
// //
// It is the microcode header. It is not the padding data between microcode patches // It is the microcode header. It is not the padding data between microcode patches
// becasue the padding data should not include 0x00000001 and it should be the repeated // becasue the padding data should not include 0x00000001 and it should be the repeated
// byte format (like 0xXYXYXYXY....). // byte format (like 0xXYXYXYXY....).
// //
if (MicrocodeEntryPoint->ProcessorId == RegEax && if (MicrocodeEntryPoint->ProcessorId == RegEax &&
MicrocodeEntryPoint->UpdateRevision > LatestRevision && MicrocodeEntryPoint->UpdateRevision > LatestRevision &&
(MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId)) (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId))
) { ) {
if (MicrocodeEntryPoint->DataSize == 0) { if (MicrocodeEntryPoint->DataSize == 0) {
CheckSum32 = CalculateSum32 ((UINT32 *)MicrocodeEntryPoint, 2048); CheckSum32 = CalculateSum32 ((UINT32 *)MicrocodeEntryPoint, 2048);
} else { } else {
CheckSum32 = CalculateSum32 ((UINT32 *)MicrocodeEntryPoint, MicrocodeEntryPoint->DataSize + sizeof(EFI_CPU_MICROCODE_HEADER)); CheckSum32 = CalculateSum32 ((UINT32 *)MicrocodeEntryPoint, MicrocodeEntryPoint->DataSize + sizeof(EFI_CPU_MICROCODE_HEADER));
} }
if (CheckSum32 == 0) { if (CheckSum32 == 0) {
CorrectMicrocode = TRUE; CorrectMicrocode = TRUE;
} }
} else if ((MicrocodeEntryPoint->DataSize != 0) && } else if ((MicrocodeEntryPoint->DataSize != 0) &&
(MicrocodeEntryPoint->UpdateRevision > LatestRevision)) { (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {
ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize + sizeof (EFI_CPU_MICROCODE_HEADER)); ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize + sizeof (EFI_CPU_MICROCODE_HEADER));
if (ExtendedTableLength != 0) { if (ExtendedTableLength != 0) {
// //
// Extended Table exist, check if the CPU in support list // Extended Table exist, check if the CPU in support list
// //
ExtendedTableHeader = (EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *)((UINT8 *)(MicrocodeEntryPoint) + MicrocodeEntryPoint->DataSize + sizeof (EFI_CPU_MICROCODE_HEADER)); ExtendedTableHeader = (EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *)((UINT8 *)(MicrocodeEntryPoint) + MicrocodeEntryPoint->DataSize + sizeof (EFI_CPU_MICROCODE_HEADER));
// //
// Calculate Extended Checksum // Calculate Extended Checksum
// //
if ((ExtendedTableLength % 4) == 0) { if ((ExtendedTableLength % 4) == 0) {
CheckSum32 = CalculateSum32 ((UINT32 *)ExtendedTableHeader, ExtendedTableLength); CheckSum32 = CalculateSum32 ((UINT32 *)ExtendedTableHeader, ExtendedTableLength);
if (CheckSum32 == 0) { if (CheckSum32 == 0) {
// //
// Checksum correct // Checksum correct
// //
ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount; ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
ExtendedTable = (EFI_CPU_MICROCODE_EXTENDED_TABLE *)(ExtendedTableHeader + 1); ExtendedTable = (EFI_CPU_MICROCODE_EXTENDED_TABLE *)(ExtendedTableHeader + 1);
for (Index = 0; Index < ExtendedTableCount; Index ++) { for (Index = 0; Index < ExtendedTableCount; Index ++) {
CheckSum32 = CalculateSum32 ((UINT32 *)ExtendedTable, sizeof(EFI_CPU_MICROCODE_EXTENDED_TABLE)); CheckSum32 = CalculateSum32 ((UINT32 *)ExtendedTable, sizeof(EFI_CPU_MICROCODE_EXTENDED_TABLE));
if (CheckSum32 == 0) { if (CheckSum32 == 0) {
// //
// Verify Header // Verify Header
// //
if ((ExtendedTable->ProcessorSignature == RegEax) && if ((ExtendedTable->ProcessorSignature == RegEax) &&
(ExtendedTable->ProcessorFlag & (1 << PlatformId)) ) { (ExtendedTable->ProcessorFlag & (1 << PlatformId)) ) {
// //
// Find one // Find one
// //
CorrectMicrocode = TRUE; CorrectMicrocode = TRUE;
break; break;
} }
} }
ExtendedTable ++; ExtendedTable ++;
} }
} }
} }
} }
} }
} else { } else {
// //
// It is the padding data between the microcode patches for microcode patches alignment. // 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 // 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 // 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 // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
// find the next possible microcode patch header. // find the next possible microcode patch header.
// //
MicrocodeEntryPoint = (EFI_CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB); MicrocodeEntryPoint = (EFI_CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
continue; continue;
} }
// //
// Get the next patch. // Get the next patch.
// //
if (MicrocodeEntryPoint->DataSize == 0) { if (MicrocodeEntryPoint->DataSize == 0) {
TotalSize = 2048; TotalSize = 2048;
} else { } else {
TotalSize = MicrocodeEntryPoint->TotalSize; TotalSize = MicrocodeEntryPoint->TotalSize;
} }
if (CorrectMicrocode) { if (CorrectMicrocode) {
LatestRevision = MicrocodeEntryPoint->UpdateRevision; LatestRevision = MicrocodeEntryPoint->UpdateRevision;
MicrocodeInfo.MicrocodeData = (VOID *)((UINTN)MicrocodeEntryPoint + sizeof (EFI_CPU_MICROCODE_HEADER)); MicrocodeInfo.MicrocodeData = (VOID *)((UINTN)MicrocodeEntryPoint + sizeof (EFI_CPU_MICROCODE_HEADER));
MicrocodeInfo.MicrocodeSize = TotalSize; MicrocodeInfo.MicrocodeSize = TotalSize;
MicrocodeInfo.ProcessorId = RegEax; MicrocodeInfo.ProcessorId = RegEax;
} }
MicrocodeEntryPoint = (EFI_CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize); MicrocodeEntryPoint = (EFI_CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);
} while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd)); } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));
if (LatestRevision > 0) { if (LatestRevision > 0) {
// //
// Get microcode update signature of currently loaded microcode update // Get microcode update signature of currently loaded microcode update
// //
CurrentSignature = GetCurrentMicrocodeSignature (); CurrentSignature = GetCurrentMicrocodeSignature ();
// //
// If no microcode update has been loaded, then trigger microcode load. // If no microcode update has been loaded, then trigger microcode load.
// //
if (CurrentSignature == 0) { if (CurrentSignature == 0) {
AsmWriteMsr64 ( AsmWriteMsr64 (
EFI_MSR_IA32_BIOS_UPDT_TRIG, EFI_MSR_IA32_BIOS_UPDT_TRIG,
(UINT64) (UINTN) MicrocodeInfo.MicrocodeData (UINT64) (UINTN) MicrocodeInfo.MicrocodeData
); );
MicrocodeInfo.Load = TRUE; MicrocodeInfo.Load = TRUE;
} else { } else {
MicrocodeInfo.Load = FALSE; MicrocodeInfo.Load = FALSE;
} }
} }
} }

View File

@ -1,68 +1,68 @@
/** @file /** @file
Definitions for loading microcode on processors. Definitions for loading microcode on processors.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/ **/
#ifndef _CPU_MICROCODE_H_ #ifndef _CPU_MICROCODE_H_
#define _CPU_MICROCODE_H_ #define _CPU_MICROCODE_H_
#define EFI_MSR_IA32_PLATFORM_ID 0x17 #define EFI_MSR_IA32_PLATFORM_ID 0x17
#define EFI_MSR_IA32_BIOS_UPDT_TRIG 0x79 #define EFI_MSR_IA32_BIOS_UPDT_TRIG 0x79
#define EFI_MSR_IA32_BIOS_SIGN_ID 0x8b #define EFI_MSR_IA32_BIOS_SIGN_ID 0x8b
#define MAX_MICROCODE_DESCRIPTOR_LENGTH 100 #define MAX_MICROCODE_DESCRIPTOR_LENGTH 100
typedef struct { typedef struct {
VOID *MicrocodeData; VOID *MicrocodeData;
UINTN MicrocodeSize; UINTN MicrocodeSize;
UINT32 ProcessorId; UINT32 ProcessorId;
BOOLEAN Load; BOOLEAN Load;
} MICROCODE_INFO; } MICROCODE_INFO;
// //
// Definition for IA32 microcode format // Definition for IA32 microcode format
// //
typedef struct { typedef struct {
UINT32 HeaderVersion; UINT32 HeaderVersion;
UINT32 UpdateRevision; UINT32 UpdateRevision;
UINT32 Date; UINT32 Date;
UINT32 ProcessorId; UINT32 ProcessorId;
UINT32 Checksum; UINT32 Checksum;
UINT32 LoaderRevision; UINT32 LoaderRevision;
UINT32 ProcessorFlags; UINT32 ProcessorFlags;
UINT32 DataSize; UINT32 DataSize;
UINT32 TotalSize; UINT32 TotalSize;
UINT8 Reserved[12]; UINT8 Reserved[12];
} EFI_CPU_MICROCODE_HEADER; } EFI_CPU_MICROCODE_HEADER;
typedef struct { typedef struct {
UINT32 ExtendedSignatureCount; UINT32 ExtendedSignatureCount;
UINT32 ExtendedTableChecksum; UINT32 ExtendedTableChecksum;
UINT8 Reserved[12]; UINT8 Reserved[12];
} EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER; } EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER;
typedef struct { typedef struct {
UINT32 ProcessorSignature; UINT32 ProcessorSignature;
UINT32 ProcessorFlag; UINT32 ProcessorFlag;
UINT32 ProcessorChecksum; UINT32 ProcessorChecksum;
} EFI_CPU_MICROCODE_EXTENDED_TABLE; } EFI_CPU_MICROCODE_EXTENDED_TABLE;
/** /**
Detect whether specified processor can find matching microcode patch and load it. Detect whether specified processor can find matching microcode patch and load it.
**/ **/
VOID VOID
MicrocodeDetect ( MicrocodeDetect (
VOID VOID
); );
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,377 +1,377 @@
/** @file /** @file
Functions prototype of Multiple Processor PPI services. Functions prototype of Multiple Processor PPI services.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/ **/
#ifndef _PEI_MP_SERVICES_H_ #ifndef _PEI_MP_SERVICES_H_
#define _PEI_MP_SERVICES_H_ #define _PEI_MP_SERVICES_H_
#include "CpuMpPei.h" #include "CpuMpPei.h"
// //
// The MP data for switch BSP // The MP data for switch BSP
// //
#define CPU_SWITCH_STATE_IDLE 0 #define CPU_SWITCH_STATE_IDLE 0
#define CPU_SWITCH_STATE_STORED 1 #define CPU_SWITCH_STATE_STORED 1
#define CPU_SWITCH_STATE_LOADED 2 #define CPU_SWITCH_STATE_LOADED 2
#define CPU_CHECK_AP_INTERVAL 0x100 // 100 microseconds #define CPU_CHECK_AP_INTERVAL 0x100 // 100 microseconds
/** /**
This function is called by both the BSP and the AP which is to become the BSP to 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 Exchange execution context including stack between them. After return from this
function, the BSP becomes AP and the AP becomes the BSP. function, the BSP becomes AP and the AP becomes the BSP.
@param MyInfo Pointer to buffer holding the exchanging information for the executing processor. @param MyInfo Pointer to buffer holding the exchanging information for the executing processor.
@param OthersInfo Pointer to buffer holding the exchanging information for the peer. @param OthersInfo Pointer to buffer holding the exchanging information for the peer.
**/ **/
VOID VOID
EFIAPI EFIAPI
AsmExchangeRole ( AsmExchangeRole (
IN CPU_EXCHANGE_ROLE_INFO *MyInfo, IN CPU_EXCHANGE_ROLE_INFO *MyInfo,
IN CPU_EXCHANGE_ROLE_INFO *OthersInfo IN CPU_EXCHANGE_ROLE_INFO *OthersInfo
); );
/** /**
This service retrieves the number of logical processor in the platform This service retrieves the number of logical processor in the platform
and the number of those logical processors that are enabled on this boot. and the number of those logical processors that are enabled on this boot.
This service may only be called from the BSP. This service may only be called from the BSP.
This function is used to retrieve the following information: This function is used to retrieve the following information:
- The number of logical processors that are present in the system. - The number of logical processors that are present in the system.
- The number of enabled logical processors in the system at the instant - The number of enabled logical processors in the system at the instant
this call is made. this call is made.
Because MP Service Ppi provides services to enable and disable processors Because MP Service Ppi provides services to enable and disable processors
dynamically, the number of enabled logical processors may vary during the dynamically, the number of enabled logical processors may vary during the
course of a boot session. course of a boot session.
If this service is called from an AP, then EFI_DEVICE_ERROR is returned. If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
is returned in NumberOfProcessors, the number of currently enabled processor is returned in NumberOfProcessors, the number of currently enabled processor
is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned. is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
@param[in] PeiServices An indirect pointer to the PEI Services Table @param[in] PeiServices An indirect pointer to the PEI Services Table
published by the PEI Foundation. published by the PEI Foundation.
@param[in] This Pointer to this instance of the PPI. @param[in] This Pointer to this instance of the PPI.
@param[out] NumberOfProcessors Pointer to the total number of logical processors in @param[out] NumberOfProcessors Pointer to the total number of logical processors in
the system, including the BSP and disabled APs. the system, including the BSP and disabled APs.
@param[out] NumberOfEnabledProcessors @param[out] NumberOfEnabledProcessors
Number of processors in the system that are enabled. Number of processors in the system that are enabled.
@retval EFI_SUCCESS The number of logical processors and enabled @retval EFI_SUCCESS The number of logical processors and enabled
logical processors was retrieved. logical processors was retrieved.
@retval EFI_DEVICE_ERROR The calling processor is an AP. @retval EFI_DEVICE_ERROR The calling processor is an AP.
@retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL. @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.
NumberOfEnabledProcessors is NULL. NumberOfEnabledProcessors is NULL.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
PeiGetNumberOfProcessors ( PeiGetNumberOfProcessors (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_MP_SERVICES_PPI *This, IN EFI_PEI_MP_SERVICES_PPI *This,
OUT UINTN *NumberOfProcessors, OUT UINTN *NumberOfProcessors,
OUT UINTN *NumberOfEnabledProcessors OUT UINTN *NumberOfEnabledProcessors
); );
/** /**
Gets detailed MP-related information on the requested processor at the 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. instant this call is made. This service may only be called from the BSP.
This service retrieves detailed MP-related information about any processor This service retrieves detailed MP-related information about any processor
on the platform. Note the following: on the platform. Note the following:
- The processor information may change during the course of a boot session. - The processor information may change during the course of a boot session.
- The information presented here is entirely MP related. - The information presented here is entirely MP related.
Information regarding the number of caches and their sizes, frequency of operation, Information regarding the number of caches and their sizes, frequency of operation,
slot numbers is all considered platform-related information and is not provided slot numbers is all considered platform-related information and is not provided
by this service. by this service.
@param[in] PeiServices An indirect pointer to the PEI Services Table @param[in] PeiServices An indirect pointer to the PEI Services Table
published by the PEI Foundation. published by the PEI Foundation.
@param[in] This Pointer to this instance of the PPI. @param[in] This Pointer to this instance of the PPI.
@param[in] ProcessorNumber Pointer to the total number of logical processors in @param[in] ProcessorNumber Pointer to the total number of logical processors in
the system, including the BSP and disabled APs. the system, including the BSP and disabled APs.
@param[out] ProcessorInfoBuffer Number of processors in the system that are enabled. @param[out] ProcessorInfoBuffer Number of processors in the system that are enabled.
@retval EFI_SUCCESS Processor information was returned. @retval EFI_SUCCESS Processor information was returned.
@retval EFI_DEVICE_ERROR The calling processor is an AP. @retval EFI_DEVICE_ERROR The calling processor is an AP.
@retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL. @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
@retval EFI_NOT_FOUND The processor with the handle specified by @retval EFI_NOT_FOUND The processor with the handle specified by
ProcessorNumber does not exist in the platform. ProcessorNumber does not exist in the platform.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
PeiGetProcessorInfo ( PeiGetProcessorInfo (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_MP_SERVICES_PPI *This, IN EFI_PEI_MP_SERVICES_PPI *This,
IN UINTN ProcessorNumber, IN UINTN ProcessorNumber,
OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
); );
/** /**
This service executes a caller provided function on all enabled APs. APs can This service executes a caller provided function on all enabled APs. APs can
run either simultaneously or one at a time in sequence. This service supports run either simultaneously or one at a time in sequence. This service supports
both blocking requests only. This service may only both blocking requests only. This service may only
be called from the BSP. be called from the BSP.
This function is used to dispatch all the enabled APs to the function specified This function is used to dispatch all the enabled APs to the function specified
by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned
immediately and Procedure is not started on any AP. immediately and Procedure is not started on any AP.
If SingleThread is TRUE, all the enabled APs execute the function specified by If SingleThread is TRUE, all the enabled APs execute the function specified by
Procedure one by one, in ascending order of processor handle number. Otherwise, Procedure one by one, in ascending order of processor handle number. Otherwise,
all the enabled APs execute the function specified by Procedure simultaneously. all the enabled APs execute the function specified by Procedure simultaneously.
If the timeout specified by TimeoutInMicroSeconds expires before all APs return If the timeout specified by TimeoutInMicroSeconds expires before all APs return
from Procedure, then Procedure on the failed APs is terminated. All enabled APs from Procedure, then Procedure on the failed APs is terminated. All enabled APs
are always available for further calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() are always available for further calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
and EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If FailedCpuList is not NULL, its and EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If FailedCpuList is not NULL, its
content points to the list of processor handle numbers in which Procedure was content points to the list of processor handle numbers in which Procedure was
terminated. terminated.
Note: It is the responsibility of the consumer of the EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() Note: It is the responsibility of the consumer of the EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
to make sure that the nature of the code that is executed on the BSP and the to make sure that the nature of the code that is executed on the BSP and the
dispatched APs is well controlled. The MP Services Ppi does not guarantee dispatched APs is well controlled. The MP Services Ppi does not guarantee
that the Procedure function is MP-safe. Hence, the tasks that can be run in that the Procedure function is MP-safe. Hence, the tasks that can be run in
parallel are limited to certain independent tasks and well-controlled exclusive parallel are limited to certain independent tasks and well-controlled exclusive
code. PEI services and Ppis may not be called by APs unless otherwise code. PEI services and Ppis may not be called by APs unless otherwise
specified. specified.
In blocking execution mode, BSP waits until all APs finish or In blocking execution mode, BSP waits until all APs finish or
TimeoutInMicroSeconds expires. TimeoutInMicroSeconds expires.
@param[in] PeiServices An indirect pointer to the PEI Services Table @param[in] PeiServices An indirect pointer to the PEI Services Table
published by the PEI Foundation. published by the PEI Foundation.
@param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
@param[in] Procedure A pointer to the function to be run on enabled APs of @param[in] Procedure A pointer to the function to be run on enabled APs of
the system. the system.
@param[in] SingleThread If TRUE, then all the enabled APs execute the function @param[in] SingleThread If TRUE, then all the enabled APs execute the function
specified by Procedure one by one, in ascending order specified by Procedure one by one, in ascending order
of processor handle number. If FALSE, then all the of processor handle number. If FALSE, then all the
enabled APs execute the function specified by Procedure enabled APs execute the function specified by Procedure
simultaneously. simultaneously.
@param[in] TimeoutInMicroSeconds @param[in] TimeoutInMicroSeconds
Indicates the time limit in microseconds for APs to Indicates the time limit in microseconds for APs to
return from Procedure, for blocking mode only. Zero return from Procedure, for blocking mode only. Zero
means infinity. If the timeout expires before all APs means infinity. If the timeout expires before all APs
return from Procedure, then Procedure on the failed APs return from Procedure, then Procedure on the failed APs
is terminated. All enabled APs are available for next is terminated. All enabled APs are available for next
function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
timeout expires in blocking mode, BSP returns timeout expires in blocking mode, BSP returns
EFI_TIMEOUT. EFI_TIMEOUT.
@param[in] ProcedureArgument The parameter passed into Procedure for all APs. @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
@retval EFI_SUCCESS In blocking mode, all APs have finished before the @retval EFI_SUCCESS In blocking mode, all APs have finished before the
timeout expired. timeout expired.
@retval EFI_DEVICE_ERROR Caller processor is AP. @retval EFI_DEVICE_ERROR Caller processor is AP.
@retval EFI_NOT_STARTED No enabled APs exist in the system. @retval EFI_NOT_STARTED No enabled APs exist in the system.
@retval EFI_NOT_READY Any enabled APs are busy. @retval EFI_NOT_READY Any enabled APs are busy.
@retval EFI_TIMEOUT In blocking mode, the timeout expired before all @retval EFI_TIMEOUT In blocking mode, the timeout expired before all
enabled APs have finished. enabled APs have finished.
@retval EFI_INVALID_PARAMETER Procedure is NULL. @retval EFI_INVALID_PARAMETER Procedure is NULL.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
PeiStartupAllAPs ( PeiStartupAllAPs (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_MP_SERVICES_PPI *This, IN EFI_PEI_MP_SERVICES_PPI *This,
IN EFI_AP_PROCEDURE Procedure, IN EFI_AP_PROCEDURE Procedure,
IN BOOLEAN SingleThread, IN BOOLEAN SingleThread,
IN UINTN TimeoutInMicroSeconds, IN UINTN TimeoutInMicroSeconds,
IN VOID *ProcedureArgument OPTIONAL IN VOID *ProcedureArgument OPTIONAL
); );
/** /**
This service lets the caller get one enabled AP to execute a caller-provided This service lets the caller get one enabled AP to execute a caller-provided
function. The caller can request the BSP to wait for the completion function. The caller can request the BSP to wait for the completion
of the AP. This service may only be called from the BSP. of the AP. This service may only be called from the BSP.
This function is used to dispatch one enabled AP to the function specified by This function is used to dispatch one enabled AP to the function specified by
Procedure passing in the argument specified by ProcedureArgument. Procedure passing in the argument specified by ProcedureArgument.
The execution is in blocking mode. The BSP waits until the AP finishes or The execution is in blocking mode. The BSP waits until the AP finishes or
TimeoutInMicroSecondss expires. TimeoutInMicroSecondss expires.
If the timeout specified by TimeoutInMicroseconds expires before the AP returns If the timeout specified by TimeoutInMicroseconds expires before the AP returns
from Procedure, then execution of Procedure by the AP is terminated. The AP is from Procedure, then execution of Procedure by the AP is terminated. The AP is
available for subsequent calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() and available for subsequent calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() and
EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). EFI_PEI_MP_SERVICES_PPI.StartupThisAP().
@param[in] PeiServices An indirect pointer to the PEI Services Table @param[in] PeiServices An indirect pointer to the PEI Services Table
published by the PEI Foundation. published by the PEI Foundation.
@param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
@param[in] Procedure A pointer to the function to be run on enabled APs of @param[in] Procedure A pointer to the function to be run on enabled APs of
the system. the system.
@param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the @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 total number of logical processors minus 1. The total
number of logical processors can be retrieved by number of logical processors can be retrieved by
EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
@param[in] TimeoutInMicroseconds @param[in] TimeoutInMicroseconds
Indicates the time limit in microseconds for APs to Indicates the time limit in microseconds for APs to
return from Procedure, for blocking mode only. Zero return from Procedure, for blocking mode only. Zero
means infinity. If the timeout expires before all APs means infinity. If the timeout expires before all APs
return from Procedure, then Procedure on the failed APs return from Procedure, then Procedure on the failed APs
is terminated. All enabled APs are available for next is terminated. All enabled APs are available for next
function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
timeout expires in blocking mode, BSP returns timeout expires in blocking mode, BSP returns
EFI_TIMEOUT. EFI_TIMEOUT.
@param[in] ProcedureArgument The parameter passed into Procedure for all APs. @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
@retval EFI_SUCCESS In blocking mode, specified AP finished before the @retval EFI_SUCCESS In blocking mode, specified AP finished before the
timeout expires. timeout expires.
@retval EFI_DEVICE_ERROR The calling processor is an AP. @retval EFI_DEVICE_ERROR The calling processor is an AP.
@retval EFI_TIMEOUT In blocking mode, the timeout expired before the @retval EFI_TIMEOUT In blocking mode, the timeout expired before the
specified AP has finished. specified AP has finished.
@retval EFI_NOT_FOUND The processor with the handle specified by @retval EFI_NOT_FOUND The processor with the handle specified by
ProcessorNumber does not exist. ProcessorNumber does not exist.
@retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP. @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
@retval EFI_INVALID_PARAMETER Procedure is NULL. @retval EFI_INVALID_PARAMETER Procedure is NULL.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
PeiStartupThisAP ( PeiStartupThisAP (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_MP_SERVICES_PPI *This, IN EFI_PEI_MP_SERVICES_PPI *This,
IN EFI_AP_PROCEDURE Procedure, IN EFI_AP_PROCEDURE Procedure,
IN UINTN ProcessorNumber, IN UINTN ProcessorNumber,
IN UINTN TimeoutInMicroseconds, IN UINTN TimeoutInMicroseconds,
IN VOID *ProcedureArgument OPTIONAL IN VOID *ProcedureArgument OPTIONAL
); );
/** /**
This service switches the requested AP to be the BSP from that point onward. 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 This service changes the BSP for all purposes. This call can only be performed
by the current BSP. by the current BSP.
This service switches the requested AP to be the BSP from that point onward. This service switches the requested AP to be the BSP from that point onward.
This service changes the BSP for all purposes. The new BSP can take over the This service changes the BSP for all purposes. The new BSP can take over the
execution of the old BSP and continue seamlessly from where the old one left execution of the old BSP and continue seamlessly from where the old one left
off. off.
If the BSP cannot be switched prior to the return from this service, then If the BSP cannot be switched prior to the return from this service, then
EFI_UNSUPPORTED must be returned. EFI_UNSUPPORTED must be returned.
@param[in] PeiServices An indirect pointer to the PEI Services Table @param[in] PeiServices An indirect pointer to the PEI Services Table
published by the PEI Foundation. published by the PEI Foundation.
@param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
@param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the @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 total number of logical processors minus 1. The total
number of logical processors can be retrieved by number of logical processors can be retrieved by
EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
@param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an enabled @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an enabled
AP. Otherwise, it will be disabled. AP. Otherwise, it will be disabled.
@retval EFI_SUCCESS BSP successfully switched. @retval EFI_SUCCESS BSP successfully switched.
@retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to this @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to this
service returning. service returning.
@retval EFI_UNSUPPORTED Switching the BSP is not supported. @retval EFI_UNSUPPORTED Switching the BSP is not supported.
@retval EFI_SUCCESS The calling processor is an AP. @retval EFI_SUCCESS The calling processor is an AP.
@retval EFI_NOT_FOUND The processor with the handle specified by @retval EFI_NOT_FOUND The processor with the handle specified by
ProcessorNumber does not exist. ProcessorNumber does not exist.
@retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or a disabled @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or a disabled
AP. AP.
@retval EFI_NOT_READY The specified AP is busy. @retval EFI_NOT_READY The specified AP is busy.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
PeiSwitchBSP ( PeiSwitchBSP (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_MP_SERVICES_PPI *This, IN EFI_PEI_MP_SERVICES_PPI *This,
IN UINTN ProcessorNumber, IN UINTN ProcessorNumber,
IN BOOLEAN EnableOldBSP IN BOOLEAN EnableOldBSP
); );
/** /**
This service lets the caller enable or disable an AP from this point onward. This service lets the caller enable or disable an AP from this point onward.
This service may only be called from the BSP. This service may only be called from the BSP.
This service allows the caller enable or disable an AP from this point onward. This service allows the caller enable or disable an AP from this point onward.
The caller can optionally specify the health status of the AP by Health. If The caller can optionally specify the health status of the AP by Health. If
an AP is being disabled, then the state of the disabled AP is implementation an AP is being disabled, then the state of the disabled AP is implementation
dependent. If an AP is enabled, then the implementation must guarantee that a dependent. If an AP is enabled, then the implementation must guarantee that a
complete initialization sequence is performed on the AP, so the AP is in a state complete initialization sequence is performed on the AP, so the AP is in a state
that is compatible with an MP operating system. that is compatible with an MP operating system.
If the enable or disable AP operation cannot be completed prior to the return If the enable or disable AP operation cannot be completed prior to the return
from this service, then EFI_UNSUPPORTED must be returned. from this service, then EFI_UNSUPPORTED must be returned.
@param[in] PeiServices An indirect pointer to the PEI Services Table @param[in] PeiServices An indirect pointer to the PEI Services Table
published by the PEI Foundation. published by the PEI Foundation.
@param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
@param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the @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 total number of logical processors minus 1. The total
number of logical processors can be retrieved by number of logical processors can be retrieved by
EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
@param[in] EnableAP Specifies the new state for the processor for enabled, @param[in] EnableAP Specifies the new state for the processor for enabled,
FALSE for disabled. FALSE for disabled.
@param[in] HealthFlag If not NULL, a pointer to a value that specifies the @param[in] HealthFlag If not NULL, a pointer to a value that specifies the
new health status of the AP. This flag corresponds to new health status of the AP. This flag corresponds to
StatusFlag defined in EFI_PEI_MP_SERVICES_PPI.GetProcessorInfo(). StatusFlag defined in EFI_PEI_MP_SERVICES_PPI.GetProcessorInfo().
Only the PROCESSOR_HEALTH_STATUS_BIT is used. All other Only the PROCESSOR_HEALTH_STATUS_BIT is used. All other
bits are ignored. If it is NULL, this parameter is bits are ignored. If it is NULL, this parameter is
ignored. ignored.
@retval EFI_SUCCESS The specified AP was enabled or disabled successfully. @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
@retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed prior @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed prior
to this service returning. to this service returning.
@retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported. @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
@retval EFI_DEVICE_ERROR The calling processor is an AP. @retval EFI_DEVICE_ERROR The calling processor is an AP.
@retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
does not exist. does not exist.
@retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP. @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
PeiEnableDisableAP ( PeiEnableDisableAP (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_MP_SERVICES_PPI *This, IN EFI_PEI_MP_SERVICES_PPI *This,
IN UINTN ProcessorNumber, IN UINTN ProcessorNumber,
IN BOOLEAN EnableAP, IN BOOLEAN EnableAP,
IN UINT32 *HealthFlag OPTIONAL IN UINT32 *HealthFlag OPTIONAL
); );
/** /**
This return the handle number for the calling processor. This service may be This return the handle number for the calling processor. This service may be
called from the BSP and APs. called from the BSP and APs.
This service returns the processor handle number for the calling processor. This service returns the processor handle number for the calling processor.
The returned value is in the range from 0 to the total number of logical The returned value is in the range from 0 to the total number of logical
processors minus 1. The total number of logical processors can be retrieved processors minus 1. The total number of logical processors can be retrieved
with EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). This service may be with EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). This service may be
called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
is returned. Otherwise, the current processors handle number is returned in is returned. Otherwise, the current processors handle number is returned in
ProcessorNumber, and EFI_SUCCESS is returned. ProcessorNumber, and EFI_SUCCESS is returned.
@param[in] PeiServices An indirect pointer to the PEI Services Table @param[in] PeiServices An indirect pointer to the PEI Services Table
published by the PEI Foundation. published by the PEI Foundation.
@param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
@param[out] ProcessorNumber The handle number of the AP. The range is from 0 to the @param[out] ProcessorNumber The handle number of the AP. The range is from 0 to the
total number of logical processors minus 1. The total total number of logical processors minus 1. The total
number of logical processors can be retrieved by number of logical processors can be retrieved by
EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
@retval EFI_SUCCESS The current processor handle number was returned in @retval EFI_SUCCESS The current processor handle number was returned in
ProcessorNumber. ProcessorNumber.
@retval EFI_INVALID_PARAMETER ProcessorNumber is NULL. @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
PeiWhoAmI ( PeiWhoAmI (
IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_MP_SERVICES_PPI *This, IN EFI_PEI_MP_SERVICES_PPI *This,
OUT UINTN *ProcessorNumber OUT UINTN *ProcessorNumber
); );
#endif #endif

View File

@ -1,45 +1,45 @@
;------------------------------------------------------------------------------ ; ;------------------------------------------------------------------------------ ;
; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> ; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
; This program and the accompanying materials ; This program and the accompanying materials
; are licensed and made available under the terms and conditions of the BSD License ; 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 ; which accompanies this distribution. The full text of the license may be found at
; http://opensource.org/licenses/bsd-license.php. ; http://opensource.org/licenses/bsd-license.php.
; ;
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
; ;
; Module Name: ; Module Name:
; ;
; MpEqu.inc ; MpEqu.inc
; ;
; Abstract: ; Abstract:
; ;
; This is the equates file for Multiple Processor support ; This is the equates file for Multiple Processor support
; ;
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
PROTECT_MODE_CS equ 10h PROTECT_MODE_CS equ 10h
PROTECT_MODE_DS equ 18h PROTECT_MODE_DS equ 18h
LONG_MODE_CS equ 38h LONG_MODE_CS equ 38h
LONG_MODE_DS equ 30h LONG_MODE_DS equ 30h
VacantFlag equ 00h VacantFlag equ 00h
NotVacantFlag equ 0ffh NotVacantFlag equ 0ffh
CPU_SWITCH_STATE_IDLE equ 0 CPU_SWITCH_STATE_IDLE equ 0
CPU_SWITCH_STATE_STORED equ 1 CPU_SWITCH_STATE_STORED equ 1
CPU_SWITCH_STATE_LOADED equ 2 CPU_SWITCH_STATE_LOADED equ 2
LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart) LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)
StackStartAddressLocation equ LockLocation + 08h StackStartAddressLocation equ LockLocation + 08h
StackSizeLocation equ LockLocation + 10h StackSizeLocation equ LockLocation + 10h
ApProcedureLocation equ LockLocation + 18h ApProcedureLocation equ LockLocation + 18h
GdtrLocation equ LockLocation + 20h GdtrLocation equ LockLocation + 20h
IdtrLocation equ LockLocation + 2Ah IdtrLocation equ LockLocation + 2Ah
BufferStartLocation equ LockLocation + 34h BufferStartLocation equ LockLocation + 34h
PmodeOffsetLocation equ LockLocation + 3Ch PmodeOffsetLocation equ LockLocation + 3Ch
NumApsExecutingLoction equ LockLocation + 44h NumApsExecutingLoction equ LockLocation + 44h
LmodeOffsetLocation equ LockLocation + 4Ch LmodeOffsetLocation equ LockLocation + 4Ch
Cr3Location equ LockLocation + 54h Cr3Location equ LockLocation + 54h
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------

View File

@ -1,334 +1,334 @@
;------------------------------------------------------------------------------ ; ;------------------------------------------------------------------------------ ;
; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> ; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
; This program and the accompanying materials ; This program and the accompanying materials
; are licensed and made available under the terms and conditions of the BSD License ; 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 ; which accompanies this distribution. The full text of the license may be found at
; http://opensource.org/licenses/bsd-license.php. ; http://opensource.org/licenses/bsd-license.php.
; ;
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
; ;
; Module Name: ; Module Name:
; ;
; MpFuncs32.asm ; MpFuncs32.asm
; ;
; Abstract: ; Abstract:
; ;
; This is the assembly code for MP support ; This is the assembly code for MP support
; ;
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
include MpEqu.inc include MpEqu.inc
extern InitializeFloatingPointUnits:PROC extern InitializeFloatingPointUnits:PROC
.code .code
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
;RendezvousFunnelProc procedure follows. All APs execute their procedure. This ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
;procedure serializes all the AP processors through an Init sequence. It must be ;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. ;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 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
;IS IN MACHINE CODE. ;IS IN MACHINE CODE.
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
RendezvousFunnelProc PROC PUBLIC RendezvousFunnelProc PROC PUBLIC
RendezvousFunnelProcStart:: RendezvousFunnelProcStart::
; At this point CS = 0x(vv00) and ip= 0x0. ; At this point CS = 0x(vv00) and ip= 0x0.
; Save BIST information to ebp firstly ; Save BIST information to ebp firstly
db 66h, 08bh, 0e8h ; mov ebp, eax ; save BIST information db 66h, 08bh, 0e8h ; mov ebp, eax ; save BIST information
db 8ch,0c8h ; mov ax,cs db 8ch,0c8h ; mov ax,cs
db 8eh,0d8h ; mov ds,ax db 8eh,0d8h ; mov ds,ax
db 8eh,0c0h ; mov es,ax db 8eh,0c0h ; mov es,ax
db 8eh,0d0h ; mov ss,ax db 8eh,0d0h ; mov ss,ax
db 33h,0c0h ; xor ax,ax db 33h,0c0h ; xor ax,ax
db 8eh,0e0h ; mov fs,ax db 8eh,0e0h ; mov fs,ax
db 8eh,0e8h ; mov gs,ax db 8eh,0e8h ; mov gs,ax
db 0BEh ; opcode of mov si, mem16 db 0BEh ; opcode of mov si, mem16
dw BufferStartLocation ; mov si, BufferStartLocation dw BufferStartLocation ; mov si, BufferStartLocation
db 66h, 8Bh, 1Ch ; mov ebx,dword ptr [si] db 66h, 8Bh, 1Ch ; mov ebx,dword ptr [si]
db 0BFh ; opcode of mov di, mem16 db 0BFh ; opcode of mov di, mem16
dw PmodeOffsetLocation ; mov di, PmodeOffsetLocation dw PmodeOffsetLocation ; mov di, PmodeOffsetLocation
db 66h, 8Bh, 05h ; mov eax,dword ptr [di] db 66h, 8Bh, 05h ; mov eax,dword ptr [di]
db 8Bh, 0F8h ; mov di, ax db 8Bh, 0F8h ; mov di, ax
db 83h, 0EFh,06h ; sub di, 06h db 83h, 0EFh,06h ; sub di, 06h
db 66h, 03h, 0C3h ; add eax, ebx db 66h, 03h, 0C3h ; add eax, ebx
db 66h, 89h, 05h ; mov dword ptr [di],eax db 66h, 89h, 05h ; mov dword ptr [di],eax
db 0BFh ; opcode of mov di, mem16 db 0BFh ; opcode of mov di, mem16
dw LmodeOffsetLocation ; mov di, LmodeOffsetLocation dw LmodeOffsetLocation ; mov di, LmodeOffsetLocation
db 66h, 8Bh, 05h ; mov eax,dword ptr [di] db 66h, 8Bh, 05h ; mov eax,dword ptr [di]
db 8Bh, 0F8h ; mov di, ax db 8Bh, 0F8h ; mov di, ax
db 83h, 0EFh,06h ; sub di, 06h db 83h, 0EFh,06h ; sub di, 06h
db 66h, 03h, 0C3h ; add eax, ebx db 66h, 03h, 0C3h ; add eax, ebx
db 66h, 89h, 05h ; mov dword ptr [di],eax db 66h, 89h, 05h ; mov dword ptr [di],eax
db 0BEh db 0BEh
dw Cr3Location ; mov si, Cr3Location dw Cr3Location ; mov si, Cr3Location
db 66h, 8Bh, 0Ch ; mov ecx,dword ptr [si] ; ECX is keeping the value of CR3 db 66h, 8Bh, 0Ch ; mov ecx,dword ptr [si] ; ECX is keeping the value of CR3
db 0BEh ; opcode of mov si, mem16 db 0BEh ; opcode of mov si, mem16
dw GdtrLocation ; mov si, GdtrLocation dw GdtrLocation ; mov si, GdtrLocation
db 66h ; db 66h db 66h ; db 66h
db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si] db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
db 0BEh db 0BEh
dw IdtrLocation ; mov si, IdtrLocation dw IdtrLocation ; mov si, IdtrLocation
db 66h ; db 66h db 66h ; db 66h
db 2Eh,0Fh, 01h, 1Ch ; lidt fword ptr cs:[si] db 2Eh,0Fh, 01h, 1Ch ; lidt fword ptr cs:[si]
db 33h, 0C0h ; xor ax, ax db 33h, 0C0h ; xor ax, ax
db 8Eh, 0D8h ; mov ds, ax db 8Eh, 0D8h ; mov ds, ax
db 0Fh, 20h, 0C0h ; mov eax, cr0 ;Get control register 0 db 0Fh, 20h, 0C0h ; mov eax, cr0 ;Get control register 0
db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ;Set PE bit (bit #0) & MP db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ;Set PE bit (bit #0) & MP
db 0Fh, 22h, 0C0h ; mov cr0, eax db 0Fh, 22h, 0C0h ; mov cr0, eax
db 66h, 67h, 0EAh ; far jump db 66h, 67h, 0EAh ; far jump
dd 0h ; 32-bit offset dd 0h ; 32-bit offset
dw PROTECT_MODE_CS ; 16-bit selector dw PROTECT_MODE_CS ; 16-bit selector
Flat32Start:: ; protected mode entry point Flat32Start:: ; protected mode entry point
mov ax, PROTECT_MODE_DS mov ax, PROTECT_MODE_DS
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
db 0Fh, 20h, 0E0h ; mov eax, cr4 db 0Fh, 20h, 0E0h ; mov eax, cr4
db 0Fh, 0BAh, 0E8h, 05h ; bts eax, 5 db 0Fh, 0BAh, 0E8h, 05h ; bts eax, 5
db 0Fh, 22h, 0E0h ; mov cr4, eax db 0Fh, 22h, 0E0h ; mov cr4, eax
db 0Fh, 22h, 0D9h ; mov cr3, ecx db 0Fh, 22h, 0D9h ; mov cr3, ecx
db 0B9h db 0B9h
dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number. dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number.
db 0Fh, 32h ; rdmsr ; Read EFER. db 0Fh, 32h ; rdmsr ; Read EFER.
db 0Fh, 0BAh, 0E8h, 08h ; bts eax, 8 ; Set LME=1. db 0Fh, 0BAh, 0E8h, 08h ; bts eax, 8 ; Set LME=1.
db 0Fh, 30h ; wrmsr ; Write EFER. db 0Fh, 30h ; wrmsr ; Write EFER.
db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0. db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0.
db 0Fh, 0BAh, 0E8h, 1Fh ; bts eax, 31 ; Set PG=1. db 0Fh, 0BAh, 0E8h, 1Fh ; bts eax, 31 ; Set PG=1.
db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0. db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0.
LONG_JUMP: LONG_JUMP:
db 67h, 0EAh ; far jump db 67h, 0EAh ; far jump
dd 0h ; 32-bit offset dd 0h ; 32-bit offset
dw LONG_MODE_CS ; 16-bit selector dw LONG_MODE_CS ; 16-bit selector
LongModeStart:: LongModeStart::
mov ax, LONG_MODE_DS mov ax, LONG_MODE_DS
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov ss, ax mov ss, ax
mov esi, ebx mov esi, ebx
mov edi, esi mov edi, esi
add edi, LockLocation add edi, LockLocation
mov rax, NotVacantFlag mov rax, NotVacantFlag
TestLock: TestLock:
xchg qword ptr [edi], rax xchg qword ptr [edi], rax
cmp rax, NotVacantFlag cmp rax, NotVacantFlag
jz TestLock jz TestLock
mov edi, esi mov edi, esi
add edi, NumApsExecutingLoction add edi, NumApsExecutingLoction
inc dword ptr [edi] inc dword ptr [edi]
mov ebx, dword ptr [edi] mov ebx, dword ptr [edi]
ProgramStack: ProgramStack:
mov edi, esi mov edi, esi
add edi, StackSizeLocation add edi, StackSizeLocation
mov rax, qword ptr [edi] mov rax, qword ptr [edi]
mov edi, esi mov edi, esi
add edi, StackStartAddressLocation add edi, StackStartAddressLocation
add rax, qword ptr [edi] add rax, qword ptr [edi]
mov rsp, rax mov rsp, rax
mov qword ptr [edi], rax mov qword ptr [edi], rax
Releaselock: Releaselock:
mov rax, VacantFlag mov rax, VacantFlag
mov edi, esi mov edi, esi
add edi, LockLocation add edi, LockLocation
xchg qword ptr [edi], rax xchg qword ptr [edi], rax
CProcedureInvoke: CProcedureInvoke:
push rbp ; push BIST data push rbp ; push BIST data
xor rbp, rbp ; clear ebp for call stack trace xor rbp, rbp ; clear ebp for call stack trace
push rbp push rbp
mov rbp, rsp mov rbp, rsp
mov rax, InitializeFloatingPointUnits mov rax, InitializeFloatingPointUnits
sub rsp, 20h sub rsp, 20h
call rax ; Call assembly function to initialize FPU per UEFI spec call rax ; Call assembly function to initialize FPU per UEFI spec
add rsp, 20h add rsp, 20h
mov edx, ebx ; edx is NumApsExecuting mov edx, ebx ; edx is NumApsExecuting
mov ecx, esi mov ecx, esi
add ecx, LockLocation ; rcx is address of exchange info data buffer add ecx, LockLocation ; rcx is address of exchange info data buffer
mov edi, esi mov edi, esi
add edi, ApProcedureLocation add edi, ApProcedureLocation
mov rax, qword ptr [edi] mov rax, qword ptr [edi]
sub rsp, 20h sub rsp, 20h
call rax ; invoke C function call rax ; invoke C function
add rsp, 20h add rsp, 20h
jmp $ jmp $
RendezvousFunnelProc ENDP RendezvousFunnelProc ENDP
RendezvousFunnelProcEnd:: RendezvousFunnelProcEnd::
AsmCliHltLoop PROC AsmCliHltLoop PROC
cli cli
hlt hlt
jmp $-2 jmp $-2
AsmCliHltLoop ENDP AsmCliHltLoop ENDP
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
; AsmGetAddressMap (&AddressMap); ; AsmGetAddressMap (&AddressMap);
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
AsmGetAddressMap PROC AsmGetAddressMap PROC
mov rax, offset RendezvousFunnelProcStart mov rax, offset RendezvousFunnelProcStart
mov qword ptr [rcx], rax mov qword ptr [rcx], rax
mov qword ptr [rcx + 8h], Flat32Start - RendezvousFunnelProcStart mov qword ptr [rcx + 8h], Flat32Start - RendezvousFunnelProcStart
mov qword ptr [rcx + 10h], LongModeStart - RendezvousFunnelProcStart mov qword ptr [rcx + 10h], LongModeStart - RendezvousFunnelProcStart
mov qword ptr [rcx + 18h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart mov qword ptr [rcx + 18h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
ret ret
AsmGetAddressMap ENDP AsmGetAddressMap ENDP
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
;about to become an AP. It switches it'stack with the current AP. ;about to become an AP. It switches it'stack with the current AP.
;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo); ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
AsmExchangeRole PROC AsmExchangeRole PROC
; DO NOT call other functions in this function, since 2 CPU may use 1 stack ; 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. ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
push rax push rax
push rbx push rbx
push rcx push rcx
push rdx push rdx
push rsi push rsi
push rdi push rdi
push rbp push rbp
push r8 push r8
push r9 push r9
push r10 push r10
push r11 push r11
push r12 push r12
push r13 push r13
push r14 push r14
push r15 push r15
mov rax, cr0 mov rax, cr0
push rax push rax
mov rax, cr4 mov rax, cr4
push rax push rax
; rsi contains MyInfo pointer ; rsi contains MyInfo pointer
mov rsi, rcx mov rsi, rcx
; rdi contains OthersInfo pointer ; rdi contains OthersInfo pointer
mov rdi, rdx mov rdi, rdx
;Store EFLAGS, GDTR and IDTR regiter to stack ;Store EFLAGS, GDTR and IDTR regiter to stack
pushfq pushfq
sgdt fword ptr [rsi + 16] sgdt fword ptr [rsi + 16]
sidt fword ptr [rsi + 26] sidt fword ptr [rsi + 26]
; Store the its StackPointer ; Store the its StackPointer
mov qword ptr [rsi + 8], rsp mov qword ptr [rsi + 8], rsp
; update its switch state to STORED ; update its switch state to STORED
mov byte ptr [rsi], CPU_SWITCH_STATE_STORED mov byte ptr [rsi], CPU_SWITCH_STATE_STORED
WaitForOtherStored: WaitForOtherStored:
; wait until the other CPU finish storing its state ; wait until the other CPU finish storing its state
cmp byte ptr [rdi], CPU_SWITCH_STATE_STORED cmp byte ptr [rdi], CPU_SWITCH_STATE_STORED
jz OtherStored jz OtherStored
pause pause
jmp WaitForOtherStored jmp WaitForOtherStored
OtherStored: OtherStored:
; Since another CPU already stored its state, load them ; Since another CPU already stored its state, load them
; load GDTR value ; load GDTR value
lgdt fword ptr [rdi + 16] lgdt fword ptr [rdi + 16]
; load IDTR value ; load IDTR value
lidt fword ptr [rdi + 26] lidt fword ptr [rdi + 26]
; load its future StackPointer ; load its future StackPointer
mov rsp, qword ptr [rdi + 8] mov rsp, qword ptr [rdi + 8]
; update the other CPU's switch state to LOADED ; update the other CPU's switch state to LOADED
mov byte ptr [rdi], CPU_SWITCH_STATE_LOADED mov byte ptr [rdi], CPU_SWITCH_STATE_LOADED
WaitForOtherLoaded: WaitForOtherLoaded:
; wait until the other CPU finish loading new state, ; wait until the other CPU finish loading new state,
; otherwise the data in stack may corrupt ; otherwise the data in stack may corrupt
cmp byte ptr [rsi], CPU_SWITCH_STATE_LOADED cmp byte ptr [rsi], CPU_SWITCH_STATE_LOADED
jz OtherLoaded jz OtherLoaded
pause pause
jmp WaitForOtherLoaded jmp WaitForOtherLoaded
OtherLoaded: OtherLoaded:
; since the other CPU already get the data it want, leave this procedure ; since the other CPU already get the data it want, leave this procedure
popfq popfq
pop rax pop rax
mov cr4, rax mov cr4, rax
pop rax pop rax
mov cr0, rax mov cr0, rax
pop r15 pop r15
pop r14 pop r14
pop r13 pop r13
pop r12 pop r12
pop r11 pop r11
pop r10 pop r10
pop r9 pop r9
pop r8 pop r8
pop rbp pop rbp
pop rdi pop rdi
pop rsi pop rsi
pop rdx pop rdx
pop rcx pop rcx
pop rbx pop rbx
pop rax pop rax
ret ret
AsmExchangeRole ENDP AsmExchangeRole ENDP
AsmInitializeGdt PROC AsmInitializeGdt PROC
push rbp push rbp
mov rbp, rsp mov rbp, rsp
lgdt fword PTR [rcx] ; update the GDTR lgdt fword PTR [rcx] ; update the GDTR
sub rsp, 0x10 sub rsp, 0x10
lea rax, SetCodeSelectorFarJump lea rax, SetCodeSelectorFarJump
mov [rsp], rax mov [rsp], rax
mov rdx, LONG_MODE_CS mov rdx, LONG_MODE_CS
mov [rsp + 4], dx ; get new CS mov [rsp + 4], dx ; get new CS
jmp fword ptr [rsp] jmp fword ptr [rsp]
SetCodeSelectorFarJump: SetCodeSelectorFarJump:
add rsp, 0x10 add rsp, 0x10
mov rax, LONG_MODE_DS ; get new DS mov rax, LONG_MODE_DS ; get new DS
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
pop rbp pop rbp
ret ret
AsmInitializeGdt ENDP AsmInitializeGdt ENDP
END END

View File

@ -1,327 +1,327 @@
;------------------------------------------------------------------------------ ; ;------------------------------------------------------------------------------ ;
; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> ; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
; This program and the accompanying materials ; This program and the accompanying materials
; are licensed and made available under the terms and conditions of the BSD License ; 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 ; which accompanies this distribution. The full text of the license may be found at
; http://opensource.org/licenses/bsd-license.php. ; http://opensource.org/licenses/bsd-license.php.
; ;
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
; ;
; Module Name: ; Module Name:
; ;
; MpFuncs.nasm ; MpFuncs.nasm
; ;
; Abstract: ; Abstract:
; ;
; This is the assembly code for MP support ; This is the assembly code for MP support
; ;
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
%include "MpEqu.inc" %include "MpEqu.inc"
extern ASM_PFX(InitializeFloatingPointUnits) extern ASM_PFX(InitializeFloatingPointUnits)
DEFAULT REL DEFAULT REL
SECTION .text SECTION .text
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
;RendezvousFunnelProc procedure follows. All APs execute their procedure. This ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
;procedure serializes all the AP processors through an Init sequence. It must be ;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. ;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 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
;IS IN MACHINE CODE. ;IS IN MACHINE CODE.
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
global ASM_PFX(RendezvousFunnelProc) global ASM_PFX(RendezvousFunnelProc)
ASM_PFX(RendezvousFunnelProc): ASM_PFX(RendezvousFunnelProc):
RendezvousFunnelProcStart: RendezvousFunnelProcStart:
; At this point CS = 0x(vv00) and ip= 0x0. ; At this point CS = 0x(vv00) and ip= 0x0.
; Save BIST information to ebp firstly ; Save BIST information to ebp firstly
BITS 16 BITS 16
mov eax, 1234h mov eax, 1234h
mov ebp, eax ; save BIST information mov ebp, eax ; save BIST information
mov ax, cs mov ax, cs
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov ss, ax mov ss, ax
xor ax, ax xor ax, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov si, BufferStartLocation mov si, BufferStartLocation
mov ebx, [si] mov ebx, [si]
mov di, PmodeOffsetLocation mov di, PmodeOffsetLocation
mov eax, [di] mov eax, [di]
mov di, ax mov di, ax
sub di, 06h sub di, 06h
add eax, ebx add eax, ebx
mov [di],eax mov [di],eax
mov di, LmodeOffsetLocation mov di, LmodeOffsetLocation
mov eax, [di] mov eax, [di]
mov di, ax mov di, ax
sub di, 06h sub di, 06h
add eax, ebx add eax, ebx
mov [di],eax mov [di],eax
mov si, Cr3Location mov si, Cr3Location
mov ecx,[si] ; ECX is keeping the value of CR3 mov ecx,[si] ; ECX is keeping the value of CR3
mov si, GdtrLocation mov si, GdtrLocation
o32 lgdt [cs:si] o32 lgdt [cs:si]
mov si, IdtrLocation mov si, IdtrLocation
o32 lidt [cs:si] o32 lidt [cs:si]
xor ax, ax xor ax, ax
mov ds, ax mov ds, ax
mov eax, cr0 ;Get control register 0 mov eax, cr0 ;Get control register 0
or eax, 000000003h ;Set PE bit (bit #0) & MP or eax, 000000003h ;Set PE bit (bit #0) & MP
mov cr0, eax mov cr0, eax
jmp PROTECT_MODE_CS:strict dword 0 ; far jump to protected mode jmp PROTECT_MODE_CS:strict dword 0 ; far jump to protected mode
BITS 32 BITS 32
Flat32Start: ; protected mode entry point Flat32Start: ; protected mode entry point
mov ax, PROTECT_MODE_DS mov ax, PROTECT_MODE_DS
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
mov eax, cr4 mov eax, cr4
bts eax, 5 bts eax, 5
mov cr4, eax mov cr4, eax
mov cr3, ecx mov cr3, ecx
mov ecx, 0c0000080h ; EFER MSR number. mov ecx, 0c0000080h ; EFER MSR number.
rdmsr ; Read EFER. rdmsr ; Read EFER.
bts eax, 8 ; Set LME=1. bts eax, 8 ; Set LME=1.
wrmsr ; Write EFER. wrmsr ; Write EFER.
mov eax, cr0 ; Read CR0. mov eax, cr0 ; Read CR0.
bts eax, 31 ; Set PG=1. bts eax, 31 ; Set PG=1.
mov cr0, eax ; Write CR0. mov cr0, eax ; Write CR0.
jmp LONG_MODE_CS:strict dword 0 ; far jump to long mode jmp LONG_MODE_CS:strict dword 0 ; far jump to long mode
BITS 64 BITS 64
LongModeStart: LongModeStart:
mov ax, LONG_MODE_DS mov ax, LONG_MODE_DS
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov ss, ax mov ss, ax
mov esi, ebx mov esi, ebx
mov edi, esi mov edi, esi
add edi, LockLocation add edi, LockLocation
mov rax, NotVacantFlag mov rax, NotVacantFlag
TestLock: TestLock:
xchg qword [edi], rax xchg qword [edi], rax
cmp rax, NotVacantFlag cmp rax, NotVacantFlag
jz TestLock jz TestLock
mov edi, esi mov edi, esi
add edi, NumApsExecutingLoction add edi, NumApsExecutingLoction
inc dword [edi] inc dword [edi]
mov ebx, [edi] mov ebx, [edi]
ProgramStack: ProgramStack:
mov edi, esi mov edi, esi
add edi, StackSizeLocation add edi, StackSizeLocation
mov rax, qword [edi] mov rax, qword [edi]
mov edi, esi mov edi, esi
add edi, StackStartAddressLocation add edi, StackStartAddressLocation
add rax, qword [edi] add rax, qword [edi]
mov rsp, rax mov rsp, rax
mov qword [edi], rax mov qword [edi], rax
Releaselock: Releaselock:
mov rax, VacantFlag mov rax, VacantFlag
mov edi, esi mov edi, esi
add edi, LockLocation add edi, LockLocation
xchg qword [edi], rax xchg qword [edi], rax
CProcedureInvoke: CProcedureInvoke:
push rbp ; push BIST data at top of AP stack push rbp ; push BIST data at top of AP stack
xor rbp, rbp ; clear ebp for call stack trace xor rbp, rbp ; clear ebp for call stack trace
push rbp push rbp
mov rbp, rsp mov rbp, rsp
mov rax, ASM_PFX(InitializeFloatingPointUnits) mov rax, ASM_PFX(InitializeFloatingPointUnits)
sub rsp, 20h sub rsp, 20h
call rax ; Call assembly function to initialize FPU per UEFI spec call rax ; Call assembly function to initialize FPU per UEFI spec
add rsp, 20h add rsp, 20h
mov edx, ebx ; edx is NumApsExecuting mov edx, ebx ; edx is NumApsExecuting
mov ecx, esi mov ecx, esi
add ecx, LockLocation ; rcx is address of exchange info data buffer add ecx, LockLocation ; rcx is address of exchange info data buffer
mov edi, esi mov edi, esi
add edi, ApProcedureLocation add edi, ApProcedureLocation
mov rax, qword [edi] mov rax, qword [edi]
sub rsp, 20h sub rsp, 20h
call rax ; invoke C function call rax ; invoke C function
add rsp, 20h add rsp, 20h
RendezvousFunnelProcEnd: RendezvousFunnelProcEnd:
global ASM_PFX(AsmCliHltLoop) global ASM_PFX(AsmCliHltLoop)
ASM_PFX(AsmCliHltLoop): ASM_PFX(AsmCliHltLoop):
cli cli
hlt hlt
jmp $-2 jmp $-2
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
; AsmGetAddressMap (&AddressMap); ; AsmGetAddressMap (&AddressMap);
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
global ASM_PFX(AsmGetAddressMap) global ASM_PFX(AsmGetAddressMap)
ASM_PFX(AsmGetAddressMap): ASM_PFX(AsmGetAddressMap):
mov rax, ASM_PFX(RendezvousFunnelProc) mov rax, ASM_PFX(RendezvousFunnelProc)
mov qword [rcx], rax mov qword [rcx], rax
mov qword [rcx + 8h], Flat32Start - RendezvousFunnelProcStart mov qword [rcx + 8h], Flat32Start - RendezvousFunnelProcStart
mov qword [rcx + 10h], LongModeStart - RendezvousFunnelProcStart mov qword [rcx + 10h], LongModeStart - RendezvousFunnelProcStart
mov qword [rcx + 18h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart mov qword [rcx + 18h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
ret ret
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
;about to become an AP. It switches it'stack with the current AP. ;about to become an AP. It switches it'stack with the current AP.
;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo); ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
global ASM_PFX(AsmExchangeRole) global ASM_PFX(AsmExchangeRole)
ASM_PFX(AsmExchangeRole): ASM_PFX(AsmExchangeRole):
; DO NOT call other functions in this function, since 2 CPU may use 1 stack ; 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. ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
push rax push rax
push rbx push rbx
push rcx push rcx
push rdx push rdx
push rsi push rsi
push rdi push rdi
push rbp push rbp
push r8 push r8
push r9 push r9
push r10 push r10
push r11 push r11
push r12 push r12
push r13 push r13
push r14 push r14
push r15 push r15
mov rax, cr0 mov rax, cr0
push rax push rax
mov rax, cr4 mov rax, cr4
push rax push rax
; rsi contains MyInfo pointer ; rsi contains MyInfo pointer
mov rsi, rcx mov rsi, rcx
; rdi contains OthersInfo pointer ; rdi contains OthersInfo pointer
mov rdi, rdx mov rdi, rdx
;Store EFLAGS, GDTR and IDTR regiter to stack ;Store EFLAGS, GDTR and IDTR regiter to stack
pushfq pushfq
sgdt [rsi + 16] sgdt [rsi + 16]
sidt [rsi + 26] sidt [rsi + 26]
; Store the its StackPointer ; Store the its StackPointer
mov [rsi + 8], rsp mov [rsi + 8], rsp
; update its switch state to STORED ; update its switch state to STORED
mov byte [rsi], CPU_SWITCH_STATE_STORED mov byte [rsi], CPU_SWITCH_STATE_STORED
WaitForOtherStored: WaitForOtherStored:
; wait until the other CPU finish storing its state ; wait until the other CPU finish storing its state
cmp byte [rdi], CPU_SWITCH_STATE_STORED cmp byte [rdi], CPU_SWITCH_STATE_STORED
jz OtherStored jz OtherStored
pause pause
jmp WaitForOtherStored jmp WaitForOtherStored
OtherStored: OtherStored:
; Since another CPU already stored its state, load them ; Since another CPU already stored its state, load them
; load GDTR value ; load GDTR value
lgdt [rdi + 16] lgdt [rdi + 16]
; load IDTR value ; load IDTR value
lidt [rdi + 26] lidt [rdi + 26]
; load its future StackPointer ; load its future StackPointer
mov rsp, [rdi + 8] mov rsp, [rdi + 8]
; update the other CPU's switch state to LOADED ; update the other CPU's switch state to LOADED
mov byte [rdi], CPU_SWITCH_STATE_LOADED mov byte [rdi], CPU_SWITCH_STATE_LOADED
WaitForOtherLoaded: WaitForOtherLoaded:
; wait until the other CPU finish loading new state, ; wait until the other CPU finish loading new state,
; otherwise the data in stack may corrupt ; otherwise the data in stack may corrupt
cmp byte [rsi], CPU_SWITCH_STATE_LOADED cmp byte [rsi], CPU_SWITCH_STATE_LOADED
jz OtherLoaded jz OtherLoaded
pause pause
jmp WaitForOtherLoaded jmp WaitForOtherLoaded
OtherLoaded: OtherLoaded:
; since the other CPU already get the data it want, leave this procedure ; since the other CPU already get the data it want, leave this procedure
popfq popfq
pop rax pop rax
mov cr4, rax mov cr4, rax
pop rax pop rax
mov cr0, rax mov cr0, rax
pop r15 pop r15
pop r14 pop r14
pop r13 pop r13
pop r12 pop r12
pop r11 pop r11
pop r10 pop r10
pop r9 pop r9
pop r8 pop r8
pop rbp pop rbp
pop rdi pop rdi
pop rsi pop rsi
pop rdx pop rdx
pop rcx pop rcx
pop rbx pop rbx
pop rax pop rax
ret ret
global ASM_PFX(AsmInitializeGdt) global ASM_PFX(AsmInitializeGdt)
ASM_PFX(AsmInitializeGdt): ASM_PFX(AsmInitializeGdt):
push rbp push rbp
mov rbp, rsp mov rbp, rsp
lgdt [rcx] ; update the GDTR lgdt [rcx] ; update the GDTR
sub rsp, 0x10 sub rsp, 0x10
mov rax, ASM_PFX(SetCodeSelectorFarJump) mov rax, ASM_PFX(SetCodeSelectorFarJump)
mov [rsp], rax mov [rsp], rax
mov rdx, LONG_MODE_CS mov rdx, LONG_MODE_CS
mov [rsp + 4], dx ; get new CS mov [rsp + 4], dx ; get new CS
jmp far dword [rsp] ; far jump with new CS jmp far dword [rsp] ; far jump with new CS
ASM_PFX(SetCodeSelectorFarJump): ASM_PFX(SetCodeSelectorFarJump):
add rsp, 0x10 add rsp, 0x10
mov rax, LONG_MODE_DS ; get new DS mov rax, LONG_MODE_DS ; get new DS
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
pop rbp pop rbp
ret ret