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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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