diff --git a/UefiCpuPkg/Library/MpInitLib/AmdSev.c b/UefiCpuPkg/Library/MpInitLib/AmdSev.c index 0e3c6e2310..b4a344ee6b 100644 --- a/UefiCpuPkg/Library/MpInitLib/AmdSev.c +++ b/UefiCpuPkg/Library/MpInitLib/AmdSev.c @@ -243,3 +243,24 @@ SevEsPlaceApHlt ( MpInitLibSevEsAPReset (Ghcb, CpuMpData); } + +/** + The function fills the exchange data for the AP. + + @param[in] ExchangeInfo The pointer to CPU Exchange Data structure +**/ +VOID +FillExchangeInfoDataSevEs ( + IN volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo + ) +{ + UINT32 StdRangeMax; + + AsmCpuid (CPUID_SIGNATURE, &StdRangeMax, NULL, NULL, NULL); + if (StdRangeMax >= CPUID_EXTENDED_TOPOLOGY) { + CPUID_EXTENDED_TOPOLOGY_EBX ExtTopoEbx; + + AsmCpuid (CPUID_EXTENDED_TOPOLOGY, NULL, &ExtTopoEbx.Uint32, NULL, NULL); + ExchangeInfo->ExtTopoAvail = !!ExtTopoEbx.Bits.LogicalProcessors; + } +} diff --git a/UefiCpuPkg/Library/MpInitLib/MpEqu.inc b/UefiCpuPkg/Library/MpInitLib/MpEqu.inc index 01668638f2..aba53f5720 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpEqu.inc +++ b/UefiCpuPkg/Library/MpInitLib/MpEqu.inc @@ -94,6 +94,7 @@ struc MP_CPU_EXCHANGE_INFO .SevEsIsEnabled: CTYPE_BOOLEAN 1 .SevSnpIsEnabled CTYPE_BOOLEAN 1 .GhcbBase: CTYPE_UINTN 1 + .ExtTopoAvail: CTYPE_BOOLEAN 1 endstruc MP_CPU_EXCHANGE_INFO_OFFSET equ (SwitchToRealProcEnd - RendezvousFunnelProcStart) diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index 44a011ba75..b73a6e9a0f 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -900,6 +900,13 @@ FillExchangeInfoData ( ExchangeInfo->SevSnpIsEnabled = CpuMpData->SevSnpIsEnabled; ExchangeInfo->GhcbBase = (UINTN)CpuMpData->GhcbBase; + // + // Populate SEV-ES specific exchange data. + // + if (ExchangeInfo->SevSnpIsEnabled) { + FillExchangeInfoDataSevEs (ExchangeInfo); + } + // // Get the BSP's data of GDT and IDT // diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index 56de3bfb1c..be67cd88ec 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -224,6 +224,7 @@ typedef struct { BOOLEAN SevEsIsEnabled; BOOLEAN SevSnpIsEnabled; UINTN GhcbBase; + BOOLEAN ExtTopoAvail; } MP_CPU_EXCHANGE_INFO; #pragma pack() @@ -788,4 +789,14 @@ ConfidentialComputingGuestHas ( CONFIDENTIAL_COMPUTING_GUEST_ATTR Attr ); +/** + The function fills the exchange data for the AP. + + @param[in] ExchangeInfo The pointer to CPU Exchange Data structure +**/ +VOID +FillExchangeInfoDataSevEs ( + IN volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo + ); + #endif diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm index 0034920b2f..8bb1161fa0 100644 --- a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm +++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm @@ -118,6 +118,32 @@ SevEsGetApicId: or rax, rdx mov rdi, rax ; RDI now holds the original GHCB GPA + ; + ; For SEV-SNP, the recommended handling for getting the x2APIC ID + ; would be to use the SNP CPUID table to fetch CPUID.00H:EAX and + ; CPUID:0BH:EBX[15:0] instead of the GHCB MSR protocol vmgexits + ; below. + ; + ; To avoid the unecessary ugliness to accomplish that here, the BSP + ; has performed these checks in advance (where #VC handler handles + ; the CPUID table lookups automatically) and cached them in a flag + ; so those checks can be skipped here. + ; + mov eax, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevSnpIsEnabled)] + cmp al, 1 + jne CheckExtTopoAvail + + ; + ; Even with SEV-SNP, the actual x2APIC ID in CPUID.0BH:EDX + ; fetched from the hypervisor the same way SEV-ES does it. + ; + mov eax, [esi + MP_CPU_EXCHANGE_INFO_FIELD (ExtTopoAvail)] + cmp al, 1 + je GetApicIdSevEs + ; The 8-bit APIC ID fallback is also the same as with SEV-ES + jmp NoX2ApicSevEs + +CheckExtTopoAvail: mov rdx, 0 ; CPUID function 0 mov rax, 0 ; RAX register requested or rax, 4 @@ -136,6 +162,7 @@ SevEsGetApicId: test edx, 0ffffh jz NoX2ApicSevEs ; CPUID.0BH:EBX[15:0] is zero +GetApicIdSevEs: mov rdx, 0bh ; CPUID function 0x0b mov rax, 0c0000000h ; RDX register requested or rax, 4