mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-26 23:24:03 +02:00
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:
parent
3fd56a2672
commit
ea0f431cec
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user