* Wed Aug 05 2026 Miroslav Rezanina <mrezanin@redhat.com> - 20241117-9
- edk2-UefiCpuPkg-MpInitLib-Fix-SNP-AP-creation-when-using-.patch [RHEL-140477] - Resolves: RHEL-140477 ([AMDSERVER 9.9 Bug] SEV-SNP: [OVMF] AP Creation using APIC ID list results in VMRUN exit with #VMEXIT_INVALID)
This commit is contained in:
parent
ec623498fa
commit
2d1308f3c0
252
edk2-UefiCpuPkg-MpInitLib-Fix-SNP-AP-creation-when-using-.patch
Normal file
252
edk2-UefiCpuPkg-MpInitLib-Fix-SNP-AP-creation-when-using-.patch
Normal file
@ -0,0 +1,252 @@
|
||||
From ef877f5f1ee8d8d71a982ad6b1ae4a5e1459ef22 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Lendacky <thomas.lendacky@amd.com>
|
||||
Date: Thu, 27 Mar 2025 14:30:58 -0500
|
||||
Subject: [PATCH] UefiCpuPkg/MpInitLib: Fix SNP AP creation when using known
|
||||
APIC IDs
|
||||
|
||||
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
|
||||
RH-MergeRequest: 114: UefiCpuPkg/MpInitLib: Fix SNP AP creation when using known APIC IDs
|
||||
RH-Jira: RHEL-140477
|
||||
RH-Acked-by: Luigi Leonardi <None>
|
||||
RH-Commit: [1/1] 2d36bd9c69464df23b0a5418ba970ef1667dac10 (kraxel.rh/centos-src-edk2)
|
||||
|
||||
A typical initial AP boot up will choose a CpuNumber based on the ApIndex
|
||||
value that it gets back after a locked increment of the ApIndex value.
|
||||
The ApIndex to APIC ID relationship is random, which is not an issue when
|
||||
a broadcast INIT-SIPI is performed.
|
||||
|
||||
With SNP and a hypervisor that supports retrieval of the known APIC IDs,
|
||||
the broadcast INIT-SIPI method is replaced by waking each individual vCPU.
|
||||
In this situation, a specific VMSA is associated with a specific APIC ID.
|
||||
However, random assignment of an ApIndex can break this association. This
|
||||
isn't typically an issue, because the AP bring-up finishes with the AP
|
||||
issuing a HLT instruction, which is intercepted by the hypervisor and the
|
||||
AP won't run again until the next INIT-SIPI. However, when HLT isn't
|
||||
intercepted by the hypervisor (Qemu '-overcommit cpu-pm=on' parameter),
|
||||
then the HLT does not exit to the hypervisor. On the next INIT-SIPI, it
|
||||
can happen that a VMRUN is executed with a different VMSA address than
|
||||
was originally used, and if that VMSA is still in a VMRUN on another AP,
|
||||
then the executing VMRUN will fail, crashing the guest.
|
||||
|
||||
To fix this issue, add a CPU exchange info field, SevSnpKnownInitApicId,
|
||||
that indicates the APs are starting with an already known initial APIC ID
|
||||
and set the initial APIC ID and APIC ID in the CPU_INFO_IN_HOB HOB.
|
||||
During AP boot, the SevSnpKnownInitApicId field will result in the
|
||||
CpuNumber being set to the index with a matching APIC ID (similar to AP
|
||||
booting when the InitFlag != ApInitConfig).
|
||||
|
||||
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
|
||||
(cherry picked from commit dca5d26bc57ef4a554448e41d302e732bca03d8a)
|
||||
|
||||
Resolves: https://redhat.atlassian.net/browse/RHEL-140477
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
UefiCpuPkg/Library/MpInitLib/AmdSev.c | 2 +
|
||||
UefiCpuPkg/Library/MpInitLib/MpEqu.inc | 1 +
|
||||
UefiCpuPkg/Library/MpInitLib/MpLib.h | 1 +
|
||||
UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c | 38 +++++++++---
|
||||
UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm | 60 ++++++++++++++++++-
|
||||
UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 4 ++
|
||||
6 files changed, 98 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/UefiCpuPkg/Library/MpInitLib/AmdSev.c b/UefiCpuPkg/Library/MpInitLib/AmdSev.c
|
||||
index 75429e3daec..5108873c3b3 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 317e627b58b..d8ba9ea1246 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 145538b6ee0..a63bb81bef8 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 a75e1e2018c..56cd7a11384 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.
|
||||
@@ -308,6 +325,13 @@ SevSnpCreateAP (
|
||||
if (CpuMpData->InitFlag == ApInitConfig) {
|
||||
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.
|
||||
//
|
||||
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm
|
||||
index 2efa3cb1048..66d63a2b90e 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 40e80ffab4e..95ee65e2882 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)
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -21,7 +21,7 @@ ExclusiveArch: x86_64 aarch64
|
||||
|
||||
Name: edk2
|
||||
Version: %{GITDATE}
|
||||
Release: 8%{?dist}
|
||||
Release: 9%{?dist}
|
||||
Summary: UEFI firmware for 64-bit virtual machines
|
||||
License: BSD-2-Clause-Patent and Apache-2.0 and MIT
|
||||
URL: http://www.tianocore.org
|
||||
@ -109,6 +109,8 @@ Patch44: edk2-MdePkg-Add-the-COHERENCY_SFW_NO-CPUID-bit-field.patch
|
||||
Patch45: edk2-OvmfPkg-ResetVector-Make-ReceivedVc-a-flag-in-SEV-ES.patch
|
||||
# For RHEL-121983 - [edk2] VM panic on booting SNP guest with large memory on Genoa
|
||||
Patch46: edk2-OvmfPkg-MemEncryptSevLib-Check-if-SEV-SNP-coherency-.patch
|
||||
# For RHEL-140477 - [AMDSERVER 9.9 Bug] SEV-SNP: [OVMF] AP Creation using APIC ID list results in VMRUN exit with #VMEXIT_INVALID
|
||||
Patch47: edk2-UefiCpuPkg-MpInitLib-Fix-SNP-AP-creation-when-using-.patch
|
||||
|
||||
# python3-devel and libuuid-devel are required for building tools.
|
||||
# python3-devel is also needed for varstore template generation and
|
||||
@ -444,6 +446,11 @@ install -m 0644 \
|
||||
|
||||
|
||||
%changelog
|
||||
* Wed Aug 05 2026 Miroslav Rezanina <mrezanin@redhat.com> - 20241117-9
|
||||
- edk2-UefiCpuPkg-MpInitLib-Fix-SNP-AP-creation-when-using-.patch [RHEL-140477]
|
||||
- Resolves: RHEL-140477
|
||||
([AMDSERVER 9.9 Bug] SEV-SNP: [OVMF] AP Creation using APIC ID list results in VMRUN exit with #VMEXIT_INVALID)
|
||||
|
||||
* Mon Nov 17 2025 Jon Maloy <jmaloy@redhat.com> - 20241117-8
|
||||
- edk2-openssl-flatten-contents-of-openssl-tarball.patch [RHEL-115922]
|
||||
- edk2-Bumped-openssl-submodule-to-version-3.0.7-29.1.patch [RHEL-115922]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user