summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xBaseTools/Conf/tools_def.template10
-rw-r--r--MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c210
-rw-r--r--UefiCpuPkg/Library/MpInitLib/AmdSev.c2
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpEqu.inc1
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.h1
-rw-r--r--UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c38
-rw-r--r--UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm60
-rw-r--r--UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm4
8 files changed, 268 insertions, 58 deletions
diff --git a/BaseTools/Conf/tools_def.template b/BaseTools/Conf/tools_def.template
index 04a39e268d..cca699c4a8 100755
--- a/BaseTools/Conf/tools_def.template
+++ b/BaseTools/Conf/tools_def.template
@@ -868,7 +868,7 @@ RELEASE_VS2022_ARM_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4
NOOPT_VS2022_ARM_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:ARM /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG /WX /IGNORE:4210
# BaseTools cannot handle XIP modules with different section and file alignment
-*_VS2022_ARM_DLINK_XIPFLAGS = /ALIGN:32
+*_VS2022_ARM_DLINK_XIPFLAGS = /ALIGN:64
#####################
# AARCH64 definitions
@@ -896,12 +896,12 @@ NOOPT_VS2022_AARCH64_ASM_FLAGS = /nologo
# Linker warning 4210 is disabled globally, because it checks if static initializers are present and the VCRuntime is
# linked. We do not link the VCRuntime (except for HOST_APPLICATIONs) so this warning can be generated erroneously
# whenever there are static initializers, because we will always fail the VCRuntime linking check
- DEBUG_VS2022_AARCH64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:ARM64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /DRIVER /DEBUG /WX /IGNORE:4210
-RELEASE_VS2022_AARCH64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:ARM64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /DRIVER /MERGE:.rdata=.data /WX /IGNORE:4210
-NOOPT_VS2022_AARCH64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:ARM64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /DRIVER /DEBUG /WX /IGNORE:4210
+ DEBUG_VS2022_AARCH64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4226 /OPT:REF /OPT:ICF=10 /MAP /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:ARM64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /DRIVER /DEBUG /WX /IGNORE:4210
+RELEASE_VS2022_AARCH64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4226 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:ARM64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /DRIVER /MERGE:.rdata=.data /WX /IGNORE:4210
+NOOPT_VS2022_AARCH64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4226 /OPT:REF /OPT:ICF=10 /MAP /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:ARM64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /DRIVER /DEBUG /WX /IGNORE:4210
# BaseTools cannot handle XIP modules with different section and file alignment
-*_VS2022_AARCH64_DLINK_XIPFLAGS = /ALIGN:32
+*_VS2022_AARCH64_DLINK_XIPFLAGS = /ALIGN:64
####################################################################################
# GCC Common
diff --git a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
index f2a7be5778..56f3c8bc65 100644
--- a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
+++ b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
@@ -1968,10 +1968,18 @@ InstallAcpiTableFromAcpiSiliconHob (
EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *SiAcpiHobRsdp;
EFI_ACPI_DESCRIPTION_HEADER *SiCommonAcpiTable;
EFI_STATUS Status;
- UINT8 *TempBuffer;
UINTN NumOfTblEntries;
+ EFI_ACPI_TABLE_VERSION Version;
+ UINT64 SocTablePtr;
+ EFI_ACPI_DESCRIPTION_HEADER *SocEntryTable;
+ UINTN Index;
+ UINTN TableKey;
+ VOID *NeedToInstallTable;
+ UINT8 *Buffer;
+ EFI_PHYSICAL_ADDRESS PageAddress;
+ UINTN TotalSocTablesize;
- DEBUG ((DEBUG_INFO, "InstallAcpiTableFromAcpiSiliconHob\n"));
+ DEBUG ((DEBUG_INFO, "InstallAcpiTableFromAcpiSiliconHob - Start\n"));
//
// Initial variable.
//
@@ -1979,6 +1987,8 @@ InstallAcpiTableFromAcpiSiliconHob (
SiCommonAcpiTable = NULL;
AcpiSiliconHob = GET_GUID_HOB_DATA (GuidHob);
Status = EFI_SUCCESS;
+ Version = PcdGet32 (PcdAcpiExposedTableVersions);
+ TableKey = 0;
//
// Got RSDP table from ACPI Silicon Hob.
//
@@ -1988,63 +1998,173 @@ InstallAcpiTableFromAcpiSiliconHob (
return EFI_NOT_FOUND;
}
- DEBUG ((DEBUG_INFO, "Silicon ACPI RSDP address : 0x%lx\n", SiAcpiHobRsdp));
+ DEBUG ((DEBUG_INFO, "Silicon ACPI RSDP address : 0x%016lx\n", SiAcpiHobRsdp));
AcpiTableInstance->Rsdp3 = SiAcpiHobRsdp;
- if (SiAcpiHobRsdp->RsdtAddress != 0x00000000) {
- //
- // Initial RSDT.
- //
- TempBuffer = (UINT8 *)(UINTN)(SiAcpiHobRsdp->RsdtAddress);
- SiCommonAcpiTable = (EFI_ACPI_DESCRIPTION_HEADER *)TempBuffer;
- AcpiTableInstance->Rsdt3 = SiCommonAcpiTable;
+ //
+ // Got XSDT address from RSDP table.
+ //
+ Buffer = (UINT8 *)(UINTN)(SiAcpiHobRsdp->XsdtAddress);
+ SiCommonAcpiTable = (EFI_ACPI_DESCRIPTION_HEADER *)Buffer;
- if (SiCommonAcpiTable->Length <= sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
- DEBUG ((DEBUG_ERROR, "RSDT length is incorrect\n"));
- return EFI_ABORTED;
- }
+ DEBUG ((DEBUG_INFO, "Silicon ACPI XSDT address : 0x%016lx\n", SiCommonAcpiTable));
+ if (SiCommonAcpiTable->Length <= sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
+ DEBUG ((DEBUG_ERROR, "XSDT length is incorrect\n"));
+ return EFI_ABORTED;
+ }
+
+ //
+ // Calcaue 64bit Acpi table number.
+ //
+ NumOfTblEntries = (SiCommonAcpiTable->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT64);
+ DEBUG ((DEBUG_ERROR, "64bit NumOfTblEntries : 0x%x\n", NumOfTblEntries));
+ //
+ // Reserved the ACPI reclaim memory for XSDT.
+ //
+ //
+ TotalSocTablesize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + sizeof (UINT64);
+ PageAddress = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (
+ mAcpiTableAllocType,
+ EfiACPIReclaimMemory,
+ EFI_SIZE_TO_PAGES (TotalSocTablesize),
+ &PageAddress
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to allocate EfiACPIReclaimMemory for XSDT. Status : %r\n", Status));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (&PageAddress, TotalSocTablesize);
+ AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)PageAddress;
+
+ //
+ // Initial XSDT table content.
+ //
+ AcpiTableInstance->Xsdt->Signature = SiCommonAcpiTable->Signature;
+ //
+ // Always reserve first one for FADT table.
+ //
+ AcpiTableInstance->Xsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + sizeof (UINT64);
+ AcpiTableInstance->Xsdt->Revision = SiCommonAcpiTable->Revision;
+ CopyMem (
+ &AcpiTableInstance->Xsdt->OemId,
+ SiCommonAcpiTable->OemId,
+ sizeof (AcpiTableInstance->Xsdt->OemId)
+ );
+ CopyMem (
+ &AcpiTableInstance->Xsdt->OemTableId,
+ &SiCommonAcpiTable->OemTableId,
+ sizeof (UINT64)
+ );
+ AcpiTableInstance->Xsdt->OemRevision = SiCommonAcpiTable->OemRevision;
+ AcpiTableInstance->Xsdt->CreatorId = SiCommonAcpiTable->CreatorId;
+ AcpiTableInstance->Xsdt->CreatorRevision = SiCommonAcpiTable->CreatorRevision;
+ AcpiTableInstance->NumberOfTableEntries3 = 1;
+ //
+ // Extract ACPI table from AcpiSiliconHob XSDT.
+ //
+ for (Index = 0; Index < NumOfTblEntries; Index++) {
+ CopyMem (&SocTablePtr, (((UINT8 *)(SiCommonAcpiTable + 1)) + ((sizeof (UINT64)) * Index)), sizeof (UINT64));
+ SocEntryTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)SocTablePtr;
//
- // Calcaue 32bit Acpi table number.
+ // Display table information.
//
- NumOfTblEntries = (SiCommonAcpiTable->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT32);
- AcpiTableInstance->NumberOfTableEntries1 = NumOfTblEntries;
- DEBUG ((DEBUG_INFO, "32bit NumOfTblEntries : 0x%x\n", NumOfTblEntries));
+ DEBUG ((DEBUG_INFO, "[%x] Table address : 0x%016lx\n", Index, SocTablePtr));
+
+ Buffer = (UINT8 *)&SocEntryTable->Signature;
+ DEBUG ((DEBUG_INFO, "Table signature = %c%c%c%c\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3]));
+
+ DEBUG ((DEBUG_INFO, "Table Length : 0x%x\n", SocEntryTable->Length));
+
+ Buffer = (UINT8 *)&SocEntryTable->OemId;
+ DEBUG (
+ (DEBUG_INFO, "Table OemId = %c%c%c%c%c%c\n",
+ Buffer[0],
+ Buffer[1],
+ Buffer[2],
+ Buffer[3],
+ Buffer[4],
+ Buffer[5]
+ )
+ );
+
+ Buffer = (UINT8 *)&SocEntryTable->OemTableId;
+ DEBUG (
+ (DEBUG_INFO, "Table OemTableId = %c%c%c%c%c%c%c%c\n",
+ Buffer[0],
+ Buffer[1],
+ Buffer[2],
+ Buffer[3],
+ Buffer[4],
+ Buffer[5],
+ Buffer[6],
+ Buffer[7]
+ )
+ );
+ DEBUG ((DEBUG_INFO, "\n"));
//
- // Enlarge the max table number from mEfiAcpiMaxNumTables to current ACPI tables + EFI_ACPI_MAX_NUM_TABLES
+ // Add ACPI table in the DXE AcpiTableInstance.
//
- if (AcpiTableInstance->NumberOfTableEntries1 >= EFI_ACPI_MAX_NUM_TABLES) {
- mEfiAcpiMaxNumTables = AcpiTableInstance->NumberOfTableEntries1 + EFI_ACPI_MAX_NUM_TABLES;
- DEBUG ((DEBUG_ERROR, "mEfiAcpiMaxNumTables : 0x%x\n", mEfiAcpiMaxNumTables));
+ Status = AddTableToList (AcpiTableInstance, SocEntryTable, TRUE, Version, TRUE, &TableKey);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "InstallAcpiTableFromAcpiSiliconHob: Fail to add ACPI table at 0x%p\n", SocEntryTable));
+ ASSERT_EFI_ERROR (Status);
+ break;
}
- } else {
- //
- // Initial XSDT.
- //
- TempBuffer = (UINT8 *)(UINTN)(SiAcpiHobRsdp->XsdtAddress);
- SiCommonAcpiTable = (EFI_ACPI_DESCRIPTION_HEADER *)TempBuffer;
- AcpiTableInstance->Xsdt = SiCommonAcpiTable;
- if (SiCommonAcpiTable->Length <= sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
- DEBUG ((DEBUG_ERROR, "XSDT length is incorrect\n"));
- return EFI_ABORTED;
- }
+ if (SocEntryTable->Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
+ //
+ // According ACPI spec, if XDsdt field contains a nonzero value which can be used by the OSPM, then the Dsdt field must be ignored by the OSPM.
+ //
+ if (((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->XDsdt != 0) {
+ NeedToInstallTable = (VOID *)(UINTN)((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->XDsdt;
+ } else if (((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->Dsdt != 0) {
+ NeedToInstallTable = (VOID *)(UINTN)((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->Dsdt;
+ }
- //
- // Calcaue 64bit Acpi table number.
- //
- NumOfTblEntries = (SiCommonAcpiTable->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT64);
- AcpiTableInstance->NumberOfTableEntries3 = NumOfTblEntries;
- DEBUG ((DEBUG_ERROR, "64bit NumOfTblEntries : 0x%x\n", NumOfTblEntries));
- //
- // Enlarge the max table number from mEfiAcpiMaxNumTables to current ACPI tables + EFI_ACPI_MAX_NUM_TABLES
- //
- if (AcpiTableInstance->NumberOfTableEntries3 >= EFI_ACPI_MAX_NUM_TABLES) {
- mEfiAcpiMaxNumTables = AcpiTableInstance->NumberOfTableEntries3 + EFI_ACPI_MAX_NUM_TABLES;
- DEBUG ((DEBUG_ERROR, "mEfiAcpiMaxNumTables : 0x%x\n", mEfiAcpiMaxNumTables));
+ //
+ // if signature can not be found from the XDsdt / Dsdt field then skip it.
+ //
+ if (((EFI_ACPI_DESCRIPTION_HEADER *)NeedToInstallTable)->Signature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ Status = AddTableToList (AcpiTableInstance, NeedToInstallTable, TRUE, Version, TRUE, &TableKey);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to add DSDT in the DXE Table list!\n"));
+ ASSERT_EFI_ERROR (Status);
+ break;
+ } else {
+ DEBUG ((DEBUG_ERROR, "Installed DSDT in the DXE Table list!\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "The DSDT content is not correct, then skip it!\n"));
+ }
+
+ //
+ // According ACPI spec, if XFirmwareCtrl field contains a nonzero value which can be used by the OSPM, then the FirmwareCtrl field must be ignored by the OSPM.
+ //
+ if (((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->XFirmwareCtrl != 0) {
+ NeedToInstallTable = (VOID *)(UINTN)((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->XFirmwareCtrl;
+ } else if (((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->FirmwareCtrl != 0) {
+ NeedToInstallTable = (VOID *)(UINTN)((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->FirmwareCtrl;
+ }
+
+ if (((EFI_ACPI_DESCRIPTION_HEADER *)NeedToInstallTable)->Signature == EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
+ Status = AddTableToList (AcpiTableInstance, NeedToInstallTable, TRUE, Version, TRUE, &TableKey);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to add FACS in the DXE Table list!\n"));
+ ASSERT_EFI_ERROR (Status);
+ break;
+ } else {
+ DEBUG ((DEBUG_ERROR, "Installed FACS in the DXE Table list!\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "The FACS content is not correct, then skip it!\n"));
+ }
}
}
+ DEBUG ((DEBUG_INFO, "InstallAcpiTableFromAcpiSiliconHob - End\n"));
return Status;
}
diff --git a/UefiCpuPkg/Library/MpInitLib/AmdSev.c b/UefiCpuPkg/Library/MpInitLib/AmdSev.c
index 75429e3dae..5108873c3b 100644
--- a/UefiCpuPkg/Library/MpInitLib/AmdSev.c
+++ b/UefiCpuPkg/Library/MpInitLib/AmdSev.c
@@ -293,6 +293,8 @@ FillExchangeInfoDataSevEs (
);
ExchangeInfo->ExtTopoAvail = !!ExtTopoEbx.Bits.LogicalProcessors;
}
+
+ ExchangeInfo->SevSnpKnownInitApicId = FALSE;
}
/**
diff --git a/UefiCpuPkg/Library/MpInitLib/MpEqu.inc b/UefiCpuPkg/Library/MpInitLib/MpEqu.inc
index 317e627b58..d8ba9ea124 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpEqu.inc
+++ b/UefiCpuPkg/Library/MpInitLib/MpEqu.inc
@@ -97,6 +97,7 @@ struc MP_CPU_EXCHANGE_INFO
.SevSnpIsEnabled CTYPE_BOOLEAN 1
.GhcbBase: CTYPE_UINTN 1
.ExtTopoAvail: CTYPE_BOOLEAN 1
+ .SevSnpKnownInitApicId: CTYPE_BOOLEAN 1
endstruc
MP_CPU_EXCHANGE_INFO_OFFSET equ (Flat32Start - RendezvousFunnelProcStart)
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h
index 145538b6ee..a63bb81bef 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -239,6 +239,7 @@ typedef struct {
BOOLEAN SevSnpIsEnabled;
UINTN GhcbBase;
BOOLEAN ExtTopoAvail;
+ BOOLEAN SevSnpKnownInitApicId;
} MP_CPU_EXCHANGE_INFO;
#pragma pack()
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
index a75e1e2018..56cd7a1138 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
+++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
@@ -271,18 +271,27 @@ SevSnpCreateAP (
IN INTN ProcessorNumber
)
{
- CPU_INFO_IN_HOB *CpuInfoInHob;
- CPU_AP_DATA *CpuData;
- UINTN Index;
- UINTN MaxIndex;
- UINT32 ApicId;
- EFI_HOB_GUID_TYPE *GuidHob;
- GHCB_APIC_IDS *GhcbApicIds;
+ CPU_INFO_IN_HOB *CpuInfoInHob;
+ CPU_AP_DATA *CpuData;
+ UINTN Index;
+ UINTN MaxIndex;
+ UINT32 ApicId;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ GHCB_APIC_IDS *GhcbApicIds;
+ volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;
ASSERT (CpuMpData->MpCpuExchangeInfo->BufferStart < 0x100000);
+ ExchangeInfo = CpuMpData->MpCpuExchangeInfo;
CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
+ //
+ // Set to FALSE by default. This is only set to TRUE when the InitFlag
+ // is equal to ApInitConfig and the GHCB APIC ID List NAE event has
+ // been called.
+ //
+ ExchangeInfo->SevSnpKnownInitApicId = FALSE;
+
if (ProcessorNumber < 0) {
if (CpuMpData->InitFlag == ApInitConfig) {
//
@@ -294,6 +303,14 @@ SevSnpCreateAP (
GuidHob = GetFirstGuidHob (&gGhcbApicIdsGuid);
GhcbApicIds = (GHCB_APIC_IDS *)(*(UINTN *)GET_GUID_HOB_DATA (GuidHob));
MaxIndex = MIN (GhcbApicIds->NumEntries, PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
+
+ //
+ // Set to TRUE so that ApicId and SEV-SNP SaveArea stay in sync. When
+ // the InitFlag is ApInitConfig, the random order of AP initialization
+ // can end up with an Index / ApicId mismatch (see X64/AmdSev.nasm).
+ //
+ ExchangeInfo->SevSnpKnownInitApicId = TRUE;
+ DEBUG ((DEBUG_INFO, "SEV-SNP: Using known initial APIC IDs\n"));
} else {
//
// APs have been previously started.
@@ -309,6 +326,13 @@ SevSnpCreateAP (
ApicId = GhcbApicIds->ApicIds[Index];
//
+ // Set the ApicId values so that the proper AP data structure
+ // can be found during boot.
+ //
+ CpuInfoInHob[Index].InitialApicId = ApicId;
+ CpuInfoInHob[Index].ApicId = ApicId;
+
+ //
// For the first boot, use the BSP register information.
//
CopyMem (
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm
index 2efa3cb104..66d63a2b90 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm
@@ -15,6 +15,57 @@
%define SIZE_4KB 0x1000
+;
+; This function will ensure that CpuNumber and ApicId are in sync when using
+; the ApicIds retrieved via the GHCB APIC ID List NAE event to start the APs
+; when the InitFlag is ApInitConfig. If this is not done, the CpuNumber to
+; ApicId relationship may not hold, which would result in the ApicId to VSMA
+; relationship getting out of sync after the first AP boot.
+;
+SevSnpGetInitCpuNumber:
+ ;
+ ; If not an SNP guest, leave EBX (CpuNumber) as is
+ ;
+ lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevSnpIsEnabled)]
+ cmp byte [edi], 1 ; SevSnpIsEnabled
+ jne SevSnpGetCpuNumberDone
+
+ ;
+ ; If not starting the AP with a specific ApicId, leave EBX (CpuNumber) as is
+ ;
+ lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevSnpKnownInitApicId)]
+ cmp byte [edi], 1 ; SevSnpKnownInitApicId
+ jne SevSnpGetCpuNumberDone
+
+ ;
+ ; Use existing code to retrieve the ApicId. SevEsGetApicId will return to
+ ; the SevSnpGetInitApicId label if SevSnpKnownInitApicId is set.
+ ;
+ jmp SevEsGetApicId
+
+SevSnpGetInitApicId:
+ ;
+ ; EDX holds the ApicId, get processor number for this AP
+ ;
+ xor ebx, ebx
+ lea eax, [esi + MP_CPU_EXCHANGE_INFO_FIELD (CpuInfo)]
+ mov rdi, [eax]
+
+SevSnpGetNextProcNumber:
+ cmp dword [rdi + CPU_INFO_IN_HOB.InitialApicId], edx ; APIC ID match?
+ jz SevSnpGetCpuNumberDone
+ add rdi, CPU_INFO_IN_HOB_size
+ inc ebx
+ jmp SevSnpGetNextProcNumber
+
+SevSnpGetCpuNumberDone:
+ ;
+ ; If SevSnpKnownInitApicId is set, EBX now holds the CpuNumber for this
+ ; ApicId, which matches how it was started in SevSnpCreateAP(). Otherwise,
+ ; EBX is unchanged and holds the CpuNumber based on the startup order.
+ ;
+ OneTimeCallRet SevSnpGetInitCpuNumber
+
RegisterGhcbGpa:
;
; Register GHCB GPA when SEV-SNP is enabled
@@ -193,7 +244,14 @@ RestoreGhcb:
mov rdx, rbx
- ; x2APIC ID or APIC ID is in EDX
+ ;
+ ; x2APIC ID or APIC ID is in EDX. If SevSnpKnownInitApicId is set, then
+ ; return to SevSnpGetInitApicId, otherwise return to GetProcessorNumber.
+ ;
+ lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevSnpKnownInitApicId)]
+ cmp byte [edi], 1 ; SevSnpKnownInitApicId
+ je SevSnpGetInitApicId
+
jmp GetProcessorNumber
SevEsGetApicIdExit:
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
index 40e80ffab4..95ee65e288 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
@@ -173,6 +173,10 @@ LongModeStart:
lock xadd dword [edi], ebx ; EBX = ApIndex++
inc ebx ; EBX is CpuNumber
+ ; If running under AMD SEV-SNP and starting with a known ApicId,
+ ; adjust EBX to be the actual CpuNumber
+ OneTimeCall SevSnpGetInitCpuNumber
+
; program stack
mov edi, esi
add edi, MP_CPU_EXCHANGE_INFO_FIELD (StackSize)