mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-22 13:14:26 +02:00
UefiCpuPkg/MpInitLib: AP creation support under an SVSM
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4654 When running under an SVSM, the VMPL level of the APs that are started must match the VMPL level provided by the SVSM. Additionally, each AP must have a Calling Area for use with the SVSM protocol. Update the AP creation to properly support running under an SVSM. Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Laszlo Ersek <lersek@redhat.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Cc: Ray Ni <ray.ni@intel.com> Acked-by: Ray Ni <ray.ni@intel.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
This commit is contained in:
parent
28fecae8a3
commit
a010681f74
@ -44,7 +44,8 @@ SevSnpPerformApAction (
|
|||||||
|
|
||||||
if (Action == SVM_VMGEXIT_SNP_AP_CREATE) {
|
if (Action == SVM_VMGEXIT_SNP_AP_CREATE) {
|
||||||
//
|
//
|
||||||
// Turn the page into a recognized VMSA page.
|
// Turn the page into a recognized VMSA page. When an SVSM is present
|
||||||
|
// the page following the VMSA is the Calling Area page.
|
||||||
//
|
//
|
||||||
VmsaStatus = AmdSvsmSnpVmsaRmpAdjust (SaveArea, ApicId, TRUE);
|
VmsaStatus = AmdSvsmSnpVmsaRmpAdjust (SaveArea, ApicId, TRUE);
|
||||||
if (EFI_ERROR (VmsaStatus)) {
|
if (EFI_ERROR (VmsaStatus)) {
|
||||||
@ -56,6 +57,7 @@ SevSnpPerformApAction (
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExitInfo1 = (UINT64)ApicId << 32;
|
ExitInfo1 = (UINT64)ApicId << 32;
|
||||||
|
ExitInfo1 |= (UINT64)SaveArea->Vmpl << 16;
|
||||||
ExitInfo1 |= Action;
|
ExitInfo1 |= Action;
|
||||||
ExitInfo2 = (UINT64)(UINTN)SaveArea;
|
ExitInfo2 = (UINT64)(UINTN)SaveArea;
|
||||||
|
|
||||||
@ -87,8 +89,9 @@ SevSnpPerformApAction (
|
|||||||
|
|
||||||
if (Action == SVM_VMGEXIT_SNP_AP_DESTROY) {
|
if (Action == SVM_VMGEXIT_SNP_AP_DESTROY) {
|
||||||
//
|
//
|
||||||
// Make the current VMSA not runnable and accessible to be
|
// Make the current VMSA not runnable and accessible to be reprogrammed.
|
||||||
// reprogrammed.
|
// When an SVSM is present the page following the VMSA is the Calling Area
|
||||||
|
// page.
|
||||||
//
|
//
|
||||||
VmsaStatus = AmdSvsmSnpVmsaRmpAdjust (SaveArea, ApicId, FALSE);
|
VmsaStatus = AmdSvsmSnpVmsaRmpAdjust (SaveArea, ApicId, FALSE);
|
||||||
if (EFI_ERROR (VmsaStatus)) {
|
if (EFI_ERROR (VmsaStatus)) {
|
||||||
@ -116,6 +119,7 @@ SevSnpCreateSaveArea (
|
|||||||
UINT32 ApicId
|
UINT32 ApicId
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
UINTN PageCount;
|
||||||
UINT8 *Pages;
|
UINT8 *Pages;
|
||||||
SEV_ES_SAVE_AREA *SaveArea;
|
SEV_ES_SAVE_AREA *SaveArea;
|
||||||
IA32_CR0 ApCr0;
|
IA32_CR0 ApCr0;
|
||||||
@ -125,13 +129,19 @@ SevSnpCreateSaveArea (
|
|||||||
UINTN StartIp;
|
UINTN StartIp;
|
||||||
UINT8 SipiVector;
|
UINT8 SipiVector;
|
||||||
|
|
||||||
|
//
|
||||||
|
// When running under an SVSM, a Calling Area page is also needed and is
|
||||||
|
// always the page following the VMSA.
|
||||||
|
//
|
||||||
|
PageCount = AmdSvsmIsSvsmPresent () ? 2 : 1;
|
||||||
|
|
||||||
if (CpuData->SevEsSaveArea == NULL) {
|
if (CpuData->SevEsSaveArea == NULL) {
|
||||||
//
|
//
|
||||||
// Allocate a page for the SEV-ES Save Area and initialize it. Due to AMD
|
// Allocate a page for the SEV-ES Save Area and initialize it. Due to AMD
|
||||||
// erratum #1467 (VMSA cannot be on a 2MB boundary), allocate an extra page
|
// erratum #1467 (VMSA cannot be on a 2MB boundary), allocate an extra page
|
||||||
// to choose from to work around the issue.
|
// to choose from to work around the issue.
|
||||||
//
|
//
|
||||||
Pages = AllocateReservedPages (2);
|
Pages = AllocateReservedPages (PageCount + 1);
|
||||||
if (!Pages) {
|
if (!Pages) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -140,12 +150,12 @@ SevSnpCreateSaveArea (
|
|||||||
// Since page allocation works by allocating downward in the address space,
|
// Since page allocation works by allocating downward in the address space,
|
||||||
// try to always free the first (lower address) page to limit possible holes
|
// try to always free the first (lower address) page to limit possible holes
|
||||||
// in the memory map. So, if the address of the second page is 2MB aligned,
|
// in the memory map. So, if the address of the second page is 2MB aligned,
|
||||||
// then use the first page and free the second page. Otherwise, free the
|
// then use the first page and free the last page. Otherwise, free the
|
||||||
// first page and use the second page.
|
// first page and use the second page.
|
||||||
//
|
//
|
||||||
if (_IS_ALIGNED (Pages + EFI_PAGE_SIZE, SIZE_2MB)) {
|
if (_IS_ALIGNED (Pages + EFI_PAGE_SIZE, SIZE_2MB)) {
|
||||||
SaveArea = (SEV_ES_SAVE_AREA *)Pages;
|
SaveArea = (SEV_ES_SAVE_AREA *)Pages;
|
||||||
FreePages (Pages + EFI_PAGE_SIZE, 1);
|
FreePages (Pages + (EFI_PAGE_SIZE * PageCount), 1);
|
||||||
} else {
|
} else {
|
||||||
SaveArea = (SEV_ES_SAVE_AREA *)(Pages + EFI_PAGE_SIZE);
|
SaveArea = (SEV_ES_SAVE_AREA *)(Pages + EFI_PAGE_SIZE);
|
||||||
FreePages (Pages, 1);
|
FreePages (Pages, 1);
|
||||||
@ -163,7 +173,7 @@ SevSnpCreateSaveArea (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZeroMem (SaveArea, EFI_PAGE_SIZE);
|
ZeroMem (SaveArea, EFI_PAGE_SIZE * PageCount);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Propogate the CR0.NW and CR0.CD setting to the AP
|
// Propogate the CR0.NW and CR0.CD setting to the AP
|
||||||
@ -239,10 +249,10 @@ SevSnpCreateSaveArea (
|
|||||||
|
|
||||||
//
|
//
|
||||||
// Set the SEV-SNP specific fields for the save area:
|
// Set the SEV-SNP specific fields for the save area:
|
||||||
// VMPL - always VMPL0
|
// VMPL - based on current mode
|
||||||
// SEV_FEATURES - equivalent to the SEV_STATUS MSR right shifted 2 bits
|
// SEV_FEATURES - equivalent to the SEV_STATUS MSR right shifted 2 bits
|
||||||
//
|
//
|
||||||
SaveArea->Vmpl = 0;
|
SaveArea->Vmpl = AmdSvsmSnpGetVmpl ();
|
||||||
SaveArea->SevFeatures = AsmReadMsr64 (MSR_SEV_STATUS) >> 2;
|
SaveArea->SevFeatures = AsmReadMsr64 (MSR_SEV_STATUS) >> 2;
|
||||||
|
|
||||||
SevSnpPerformApAction (SaveArea, ApicId, SVM_VMGEXIT_SNP_AP_CREATE);
|
SevSnpPerformApAction (SaveArea, ApicId, SVM_VMGEXIT_SNP_AP_CREATE);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user