diff --git a/0001-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch b/0001-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch new file mode 100644 index 0000000000000000000000000000000000000000..12580572f9a877f48a36e6cbf15e1d282e4d10b5 --- /dev/null +++ b/0001-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch @@ -0,0 +1,80 @@ +From fc57d77c576bd808a0a7fdb30a3ea3ff0a01c064 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Thu, 16 May 2024 16:56:47 +0800 +Subject: [PATCH 01/19] anolis: UefiCpuPkg/LocalApicLib: Exclude second SendIpi + sequence on HYGON hardware + +On HYGON processors the second SendIpi in the SendInitSipiSipi and +SendInitSipiSipiAllExcludingSelf routines is not required, and may cause +undesired side-effects during MP initialization. + +This patch leverages the StandardSignatureIsHygonGenuine check to exclude +the second SendIpi and its associated MicroSecondDelay (200). +--- + UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c | 5 +++-- + UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c | 5 +++-- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c +index c4457d9..d816f03 100644 +--- a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c ++++ b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + // + // Library internal functions +@@ -555,7 +556,7 @@ SendInitSipiSipi ( + IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; + IcrLow.Bits.Level = 1; + SendIpi (IcrLow.Uint32, ApicId); +- if (!StandardSignatureIsAuthenticAMD ()) { ++ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { + MicroSecondDelay (200); + SendIpi (IcrLow.Uint32, ApicId); + } +@@ -581,7 +582,7 @@ SendInitSipiSipiAllExcludingSelf ( + SendInitIpiAllExcludingSelf (); + MicroSecondDelay (PcdGet32 (PcdCpuInitIpiDelayInMicroSeconds)); + SendStartupIpiAllExcludingSelf (StartupRoutine); +- if (!StandardSignatureIsAuthenticAMD ()) { ++ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { + MicroSecondDelay (200); + SendStartupIpiAllExcludingSelf (StartupRoutine); + } +diff --git a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c +index 0560d38..ea13cba 100644 +--- a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c ++++ b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + // + // Library internal functions +@@ -794,7 +795,7 @@ SendInitSipiSipi ( + IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; + IcrLow.Bits.Level = 1; + SendIpi (IcrLow.Uint32, ApicId); +- if (!StandardSignatureIsAuthenticAMD ()) { ++ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { + MicroSecondDelay (200); + SendIpi (IcrLow.Uint32, ApicId); + } +@@ -820,7 +821,7 @@ SendInitSipiSipiAllExcludingSelf ( + SendInitIpiAllExcludingSelf (); + MicroSecondDelay (PcdGet32 (PcdCpuInitIpiDelayInMicroSeconds)); + SendStartupIpiAllExcludingSelf (StartupRoutine); +- if (!StandardSignatureIsAuthenticAMD ()) { ++ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { + MicroSecondDelay (200); + SendStartupIpiAllExcludingSelf (StartupRoutine); + } +-- +2.31.1 + diff --git a/0002-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch b/0002-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch new file mode 100644 index 0000000000000000000000000000000000000000..ae7fbe7ecc95294bf334256c5d81f1e03af696dd --- /dev/null +++ b/0002-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch @@ -0,0 +1,760 @@ +From bd3775b6a55712110893c4f133431775d32a65fc Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Thu, 16 May 2024 17:24:31 +0800 +Subject: [PATCH 02/19] anolis: OvmfPkg: Add CSV secure call library on Hygon + CPU + +CSV is the secure virtualization feature on Hygon CPU. +A CSV virtual machine is composed of private memory and shared memory. +The private memory or shared memory can be converted to the other by +the following steps: + - guest clear/set the c-bit in the guest page table + - guest send a update command to Hygon Secure Processor + +While the update command has to be forwarded by the VMM to the Secure +Processor, to prevent the malicious VMM from attacking the update +command, a reliable command channel is required between the CSV VM +and the Hygon Secure Processor. + +The secure call library is created to build a secure command channel +between the VM and the Secure Processor by #NPF on a special private +page which the VMM is not able to access. +This special page is called secure call page. +The VM puts command in the secure call page and triggers a #NPF +to reach the Secure Processor. +The Secure Processor then puts the response in the same page and +finishes the #NPF. +The information is protected in the secure call page all the way. + +CsvLib is added to implement the functionality and new PCDs are added +accordingly. +--- + OvmfPkg/AmdSev/AmdSevX64.dsc | 2 + + OvmfPkg/AmdSev/AmdSevX64.fdf | 5 +- + OvmfPkg/Include/Library/CsvLib.h | 84 +++++++ + OvmfPkg/IntelTdx/IntelTdxX64.dsc | 2 + + OvmfPkg/IntelTdx/IntelTdxX64.fdf | 9 +- + OvmfPkg/Library/CsvLib/CsvLib.c | 82 ++++++ + OvmfPkg/Library/CsvLib/CsvLib.inf | 55 ++++ + .../Library/CsvLib/Ia32/UpdateMemoryCsvLib.c | 53 ++++ + .../Library/CsvLib/X64/UpdateMemoryCsvLib.c | 238 ++++++++++++++++++ + OvmfPkg/OvmfPkg.dec | 8 + + OvmfPkg/OvmfPkgIa32.dsc | 2 + + OvmfPkg/OvmfPkgIa32X64.dsc | 2 + + OvmfPkg/OvmfPkgX64.dsc | 1 + + OvmfPkg/OvmfPkgX64.fdf | 5 +- + 14 files changed, 545 insertions(+), 3 deletions(-) + create mode 100644 OvmfPkg/Include/Library/CsvLib.h + create mode 100644 OvmfPkg/Library/CsvLib/CsvLib.c + create mode 100644 OvmfPkg/Library/CsvLib/CsvLib.inf + create mode 100644 OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c + create mode 100644 OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c + +diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc +index a31a893..0dfadbd 100644 +--- a/OvmfPkg/AmdSev/AmdSevX64.dsc ++++ b/OvmfPkg/AmdSev/AmdSevX64.dsc +@@ -172,6 +172,7 @@ + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf + DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf + ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf ++ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf + + !if $(SOURCE_DEBUG_ENABLE) == TRUE + PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf +@@ -764,6 +765,7 @@ + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + } + OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++ OvmfPkg/CsvDxe/CsvDxe.inf + + # + # Variable driver stack (non-SMM) +diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf +index 9dd4095..23fd529 100644 +--- a/OvmfPkg/AmdSev/AmdSevX64.fdf ++++ b/OvmfPkg/AmdSev/AmdSevX64.fdf +@@ -74,7 +74,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.Pcd + 0x00FC00|0x000400 + gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableSize + +-0x010000|0x010000 ++0x010000|0x002000 ++gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize ++ ++0x012000|0x00E000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + + 0x020000|0x0E0000 +diff --git a/OvmfPkg/Include/Library/CsvLib.h b/OvmfPkg/Include/Library/CsvLib.h +new file mode 100644 +index 0000000..ceeab7d +--- /dev/null ++++ b/OvmfPkg/Include/Library/CsvLib.h +@@ -0,0 +1,84 @@ ++/** @file ++ ++ CSV base library helper function ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ 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 _CSV_LIB_H_ ++#define _CSV_LIB_H_ ++ ++#include ++ ++typedef struct { ++ IN UINT64 BaseAddress; ++ IN UINT64 Size; ++} CSV_SECURE_CMD_SHARED_REGION; ++ ++typedef enum { ++ CsvSecureCmdEnc = 1, ++ CsvSecureCmdDec, ++ CsvSecureCmdReset, ++ CsvSecureCmdUpdateSecureCallTable, ++ CsvSecureCmdMapLowerMemory, //secure memory range below 4G ++ CsvSecureCmdMapUpperMemory //secure memory range above 4G ++} CSV_SECURE_COMMAND_TYPE; ++ ++/** ++ Returns a boolean to indicate whether CSV is enabled ++ ++ @retval TRUE CSV is enabled ++ @retval FALSE CSV is not enabled ++**/ ++BOOLEAN ++EFIAPI ++CsvIsEnabled ( ++ VOID ++ ); ++ ++#define CSV_SHARED_MEMORY_SIGNATURE SIGNATURE_32('C','S','V',' ') ++ ++typedef struct { ++ UINTN Signature; ++ LIST_ENTRY Link; ++ UINT64 Start; ++ UINT64 Length; ++} CsvSharedMemoryEntry; ++ ++VOID ++EFIAPI ++CsvUpdateMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages, ++ IN BOOLEAN Dec ++); ++ ++VOID ++EFIAPI ++CsvResetMemory ( ++ VOID ++); ++ ++VOID ++EFIAPI ++CsvUpdateMapLowerMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++); ++ ++VOID ++EFIAPI ++CsvUpdateMapUpperMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++); ++#endif // _CSV_LIB_H_ +diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.dsc b/OvmfPkg/IntelTdx/IntelTdxX64.dsc +index 82e3e41..1d74c25 100644 +--- a/OvmfPkg/IntelTdx/IntelTdxX64.dsc ++++ b/OvmfPkg/IntelTdx/IntelTdxX64.dsc +@@ -172,6 +172,7 @@ + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf + DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf + ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf ++ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf + + LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf + CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf +@@ -753,6 +754,7 @@ + OvmfPkg/IoMmuDxe/IoMmuDxe.inf + + OvmfPkg/TdxDxe/TdxDxe.inf ++ OvmfPkg/CsvDxe/CsvDxe.inf + + # + # Variable driver stack (non-SMM) +diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.fdf b/OvmfPkg/IntelTdx/IntelTdxX64.fdf +index e844a09..c3e759f 100644 +--- a/OvmfPkg/IntelTdx/IntelTdxX64.fdf ++++ b/OvmfPkg/IntelTdx/IntelTdxX64.fdf +@@ -94,7 +94,13 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase|gUefiOvmfPkgTokenSpaceGuid.PcdO + 0x00E000|0x001000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize + +-0x010000|0x010000 ++0x00F000|0x002000 ++gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize ++ ++0x011000|0x001000 ++gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize ++ ++0x012000|0x00E000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + + 0x100000|0x700000 +@@ -243,6 +249,7 @@ INF FatPkg/EnhancedFatDxe/Fat.inf + INF OvmfPkg/TdxDxe/TdxDxe.inf + + INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++INF OvmfPkg/CsvDxe/CsvDxe.inf + + # + # Variable driver stack (non-SMM) +diff --git a/OvmfPkg/Library/CsvLib/CsvLib.c b/OvmfPkg/Library/CsvLib/CsvLib.c +new file mode 100644 +index 0000000..2a1f903 +--- /dev/null ++++ b/OvmfPkg/Library/CsvLib/CsvLib.c +@@ -0,0 +1,82 @@ ++/** @file ++ ++ CSV library helper function ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++STATIC BOOLEAN mCsvStatus = FALSE; ++STATIC BOOLEAN mCsvStatusChecked = FALSE; ++ ++/** ++ ++ Reads and sets the status of CSV features ++ **/ ++STATIC ++VOID ++EFIAPI ++InternalCsvStatus ( ++ VOID ++ ) ++{ ++ UINT32 RegEax; ++ ++ // ++ // Check if memory encryption leaf exist ++ // ++ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); ++ if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) { ++ if(StandardSignatureIsHygonGenuine ()){ ++ // ++ // Check MSR_0xC0010131 Bit 30 (Csv Enabled) ++ // ++ MSR_SEV_STATUS_REGISTER Msr; ++ Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS); ++ if (Msr.Uint32 & (1 << 30)) { ++ mCsvStatus = TRUE; ++ DEBUG ((EFI_D_INFO, "CSV is enabled\n")); ++ } ++ } ++ } ++ mCsvStatusChecked = TRUE; ++} ++ ++/** ++ Returns a boolean to indicate whether CSV is enabled ++ ++ @retval TRUE CSV is enabled ++ @retval FALSE CSV is not enabled ++**/ ++BOOLEAN ++EFIAPI ++CsvIsEnabled ( ++ VOID ++ ) ++{ ++ if (!mCsvStatusChecked) { ++ InternalCsvStatus (); ++ } ++ ++ return MemEncryptSevEsIsEnabled () && mCsvStatus; ++} +diff --git a/OvmfPkg/Library/CsvLib/CsvLib.inf b/OvmfPkg/Library/CsvLib/CsvLib.inf +new file mode 100644 +index 0000000..0575d67 +--- /dev/null ++++ b/OvmfPkg/Library/CsvLib/CsvLib.inf +@@ -0,0 +1,55 @@ ++## @file ++# Library provides the helper functions for CSV guest ++# ++# Copyright (c) 2022 HYGON. All rights reserved.
++# ++# 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 = 1.25 ++ BASE_NAME = CsvLib ++ FILE_GUID = 9460ef3a-b9c3-11e9-8324-7371ac35e1e3 ++ MODULE_TYPE = BASE ++ VERSION_STRING = 1.0 ++ LIBRARY_CLASS = CsvLib|PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER ++ ++# ++# The following information is for reference only and not required by the build ++# tools. ++# ++# VALID_ARCHITECTURES = Ia32 X64 ++# ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ OvmfPkg/OvmfPkg.dec ++ UefiCpuPkg/UefiCpuPkg.dec ++ ++[Sources] ++ CsvLib.c ++ ++[Sources.X64] ++ X64/UpdateMemoryCsvLib.c ++[Sources.IA32] ++ Ia32/UpdateMemoryCsvLib.c ++ ++[LibraryClasses] ++ BaseLib ++ CpuLib ++ DebugLib ++ MemEncryptSevLib ++ UefiCpuLib ++ ++[Pcd] ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize +diff --git a/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c b/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c +new file mode 100644 +index 0000000..15d3aa8 +--- /dev/null ++++ b/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c +@@ -0,0 +1,53 @@ ++/** @file ++ ++ CSV library helper function ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ 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 ++ ++VOID ++EFIAPI ++CsvUpdateMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages, ++ IN BOOLEAN Dec ++) ++{ ++} ++ ++VOID ++EFIAPI ++CsvResetMemory ( ++ VOID ++) ++{ ++} ++ ++VOID ++EFIAPI ++CsvUpdateMapLowerMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++} ++ ++VOID ++EFIAPI ++CsvUpdateMapUpperMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++} +diff --git a/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c b/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c +new file mode 100644 +index 0000000..13d06d7 +--- /dev/null ++++ b/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c +@@ -0,0 +1,238 @@ ++/** @file ++ ++ CSV library helper function ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ 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 ++#include ++#include ++#include ++#include ++#include ++ ++#define SECURE_CALL_ENTRY_MAX (254) ++ ++ ++typedef struct { ++ union { ++ UINT8 Guid[16]; ++ UINT64 Guid64[2]; ++ }; ++ UINT32 CmdType; ++ UINT32 Nums; ++ UINT64 Unused; ++ struct { ++ UINT64 BaseAddress; ++ UINT64 Size; ++ } Entry[SECURE_CALL_ENTRY_MAX]; ++} CSV_SECURE_CALL_CMD; ++ ++STATIC UINT32 SecureCallPageIdx = 0; ++ ++STATIC UINTN MemorySizeBelow4G = (UINTN)-1; ++STATIC UINTN MemorySizeAbove4G = (UINTN)-1; ++ ++STATIC ++VOID ++EFIAPI ++CsvSecureCall( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages, ++ IN CSV_SECURE_COMMAND_TYPE CmdType ++) ++{ ++ volatile CSV_SECURE_COMMAND_TYPE CmdAck = 0; ++ ++ CSV_SECURE_CALL_CMD *SecureCallPageRead; ++ CSV_SECURE_CALL_CMD *SecureCallPageWrite; ++ UINTN SecureCallBase = 0; ++ ++ if (CsvIsEnabled () == FALSE) { ++ return ; ++ } ++ ++ SecureCallBase = FixedPcdGet32 (PcdCsvDefaultSecureCallBase); ++ ++ SecureCallPageRead = ++ (CSV_SECURE_CALL_CMD *)(UINT64) ++ (EFI_PAGE_SIZE * SecureCallPageIdx + SecureCallBase); ++ ++ SecureCallPageWrite = ++ (CSV_SECURE_CALL_CMD *) ++ (UINT64)(EFI_PAGE_SIZE * (1 - SecureCallPageIdx) + SecureCallBase); ++ ++ while(1) { ++ SecureCallPageWrite->CmdType = (UINT32)CmdType; ++ SecureCallPageWrite->Nums = 1; ++ SecureCallPageWrite->Entry[0].BaseAddress = (UINT64)BaseAddress; ++ SecureCallPageWrite->Entry[0].Size = (UINT64)NumPages << EFI_PAGE_SHIFT; ++ ++ MemoryFence (); ++ ++ CmdAck = SecureCallPageRead->CmdType; ++ if (CmdAck != CmdType) ++ break; ++ } ++ SecureCallPageIdx = 1 - SecureCallPageIdx; ++} ++ ++STATIC ++UINT8 ++CmosRead8 ( ++ IN UINTN Index ++ ) ++{ ++ IoWrite8 (0x70, (UINT8) Index); ++ return IoRead8 (0x71); ++} ++ ++ ++STATIC ++VOID ++EFIAPI ++CsvGetSystemMemory( ++ VOID ++ ) ++{ ++ UINT8 Cmos0x34; ++ UINT8 Cmos0x35; ++ UINT32 Size; ++ UINTN CmosIndex; ++ ++ // ++ // system memory below 4GB MB ++ // ++ ++ Cmos0x34 = (UINT8) CmosRead8 (0x34); ++ Cmos0x35 = (UINT8) CmosRead8 (0x35); ++ ++ MemorySizeBelow4G = ++ (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB); ++ ++ // ++ // system memory above 4GB MB ++ // ++ ++ Size = 0; ++ for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) { ++ Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex); ++ } ++ ++ MemorySizeAbove4G = LShiftU64 (Size, 16); ++} ++ ++STATIC ++BOOLEAN ++EFIAPI ++CsvIsDRAM( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++ ) ++{ ++ UINTN Size = EFI_PAGES_TO_SIZE (NumPages); ++ PHYSICAL_ADDRESS EndAddress; ++ ++ Size = EFI_PAGES_TO_SIZE (NumPages); ++ EndAddress = BaseAddress + Size; ++ ++ if (MemorySizeBelow4G == (UINTN)-1 || ++ MemorySizeAbove4G == (UINTN)-1) { ++ CsvGetSystemMemory (); ++ } ++ ++ if (BaseAddress < MemorySizeBelow4G) { ++ return TRUE; ++ } else if (BaseAddress >= BASE_4GB && ++ BaseAddress < (BASE_4GB + MemorySizeAbove4G)) { ++ return TRUE; ++ } else if (EndAddress > BASE_4GB && ++ EndAddress <= (BASE_4GB + MemorySizeAbove4G)) { ++ return TRUE; ++ } else { ++ return FALSE; ++ } ++} ++ ++STATIC ++VOID ++EFIAPI ++CsvUpdateEncryptMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++ PHYSICAL_ADDRESS PageAddress = BaseAddress & ~EFI_PAGE_MASK; ++ ++ if (CsvIsDRAM (PageAddress, NumPages)) { ++ CsvSecureCall (PageAddress, NumPages, CsvSecureCmdEnc); ++ } ++} ++ ++STATIC ++VOID ++EFIAPI ++CsvUpdateDecryptMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++ PHYSICAL_ADDRESS PageAddress = BaseAddress & ~EFI_PAGE_MASK; ++ ++ if (CsvIsDRAM (PageAddress, NumPages)) { ++ CsvSecureCall (PageAddress, NumPages, CsvSecureCmdDec); ++ } ++} ++ ++VOID ++EFIAPI ++CsvUpdateMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages, ++ IN BOOLEAN Dec ++ ) ++{ ++ if (Dec) ++ CsvUpdateDecryptMemory (BaseAddress, NumPages); ++ else ++ CsvUpdateEncryptMemory (BaseAddress, NumPages); ++} ++ ++VOID ++EFIAPI ++CsvResetMemory ( ++ VOID ++) ++{ ++ CsvSecureCall (0, 0, CsvSecureCmdReset); ++} ++ ++VOID ++EFIAPI ++CsvUpdateMapLowerMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++ CsvSecureCall (BaseAddress, NumPages, CsvSecureCmdMapLowerMemory); ++} ++ ++VOID ++EFIAPI ++CsvUpdateMapUpperMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++ CsvSecureCall (BaseAddress, NumPages, CsvSecureCmdMapUpperMemory); ++} +diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec +index fbc81e4..b17d5c3 100644 +--- a/OvmfPkg/OvmfPkg.dec ++++ b/OvmfPkg/OvmfPkg.dec +@@ -148,6 +148,10 @@ + # + HardwareInfoLib|Include/Library/HardwareInfoLib.h + ++ ## @libraryclass CSV Library ++ # ++ CsvLib|Include/Library/CsvLib.h ++ + [Guids] + gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}} + gEfiXenInfoGuid = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}} +@@ -338,6 +342,10 @@ + ## Restrict boot to EFI applications in firmware volumes. + gUefiOvmfPkgTokenSpaceGuid.PcdBootRestrictToFirmware|FALSE|BOOLEAN|0x6c + ++ ## the base address of the secure call pages used by CSV. ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|0|UINT32|0x70 ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize|0|UINT32|0x71 ++ + [PcdsDynamic, PcdsDynamicEx] + gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 +diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc +index 2837996..2b96026 100644 +--- a/OvmfPkg/OvmfPkgIa32.dsc ++++ b/OvmfPkg/OvmfPkgIa32.dsc +@@ -188,6 +188,8 @@ + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf + DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf + ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf ++ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf ++ + !if $(SMM_REQUIRE) == FALSE + LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf + !endif +diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc +index 5e9eee6..a88b61b 100644 +--- a/OvmfPkg/OvmfPkgIa32X64.dsc ++++ b/OvmfPkg/OvmfPkgIa32X64.dsc +@@ -193,6 +193,8 @@ + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf + DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf + ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf ++ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf^ ++ + !if $(SMM_REQUIRE) == FALSE + LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf + !endif +diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc +index bf4c790..a6691af 100644 +--- a/OvmfPkg/OvmfPkgX64.dsc ++++ b/OvmfPkg/OvmfPkgX64.dsc +@@ -205,6 +205,7 @@ + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf + DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf + ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf ++ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf + + !if $(SMM_REQUIRE) == FALSE + LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf +diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf +index f47ab17..f6fd7a0 100644 +--- a/OvmfPkg/OvmfPkgX64.fdf ++++ b/OvmfPkg/OvmfPkgX64.fdf +@@ -94,7 +94,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase|gUefiOvmfPkgTokenSpaceGuid.PcdO + 0x00E000|0x001000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize + +-0x010000|0x010000 ++0x00F000|0x002000 ++gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize ++ ++0x011000|0x00F000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + + 0x020000|0x0E0000 +-- +2.31.1 + diff --git a/0003-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch b/0003-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch new file mode 100644 index 0000000000000000000000000000000000000000..cbba1e727fbf216a122f20c54f62b980a207cfb3 --- /dev/null +++ b/0003-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch @@ -0,0 +1,27 @@ +From 16a2a83c1e41f050e76ef9c907dd6c1304e3b14c Mon Sep 17 00:00:00 2001 +From: Xin Jiang +Date: Fri, 18 Aug 2023 17:17:28 +0800 +Subject: [PATCH 03/19] anolis: OvmfPkg/Tcg: Add CsvLib for + TpmMmioSevDecryptPei + +Signed-off-by: Xin Jiang +Change-Id: Ia5b694d8cf01e8eac9446c919ffc6e2c7cd6820a +--- + OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf +index 51ad6d0..402e4c9 100644 +--- a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf ++++ b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf +@@ -29,6 +29,7 @@ + PcdLib + PeimEntryPoint + PeiServicesLib ++ CsvLib + + [Ppis] + gOvmfTpmMmioAccessiblePpiGuid ## PRODUCES +-- +2.31.1 + diff --git a/0004-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch b/0004-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch new file mode 100644 index 0000000000000000000000000000000000000000..3dee07efda25a7be1d20d1250e1892f9f349985e --- /dev/null +++ b/0004-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch @@ -0,0 +1,221 @@ +From f959be1b942d00bac93cc40159be234e88a72fda Mon Sep 17 00:00:00 2001 +From: Liu Zixing +Date: Fri, 25 Feb 2022 15:55:44 +0800 +Subject: [PATCH 04/19] anolis: OvmfPkg/ResetVector: Support CSV in ResetVector + phase + +- A GUID is written along with the first secure call page address, +by which the Secure Processor can locate the first secure call page +address. + +- Check whether the VM is a CSV VM when setting the first page table + +- CSV VM will update first shared GHCB page address to Secure Processor +by secure call page + +Signed-off-by: Xin Jiang +Change-Id: Ib932af85578628a0a4a78c8316b541a4c10423cc +--- + OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 15 +++ + OvmfPkg/ResetVector/Ia32/AmdSev.asm | 9 ++ + OvmfPkg/ResetVector/Ia32/CsvInit.asm | 107 +++++++++++++++++++ + OvmfPkg/ResetVector/ResetVector.inf | 2 + + OvmfPkg/ResetVector/ResetVector.nasmb | 4 + + 5 files changed, 137 insertions(+) + create mode 100644 OvmfPkg/ResetVector/Ia32/CsvInit.asm + +diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm +index 8f94da8..49a84a5 100644 +--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm ++++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm +@@ -48,6 +48,21 @@ TIMES (15 - ((guidedStructureEnd - guidedStructureStart + 15) % 16)) DB 0 + guidedStructureStart: + + %ifdef ARCH_X64 ++; ++; CSV secure call table ++; ++; Provide secure call pages when boot up for CSV guest. ++; ++; GUID : 9a5d926f-2fa5-ceba-ab21-6b275d5556a5 ++; ++csvSecureCallBase: ++ DD CSV_DEFAULT_SECURE_CALL_SIZE ++ DD CSV_DEFAULT_SECURE_CALL_BASE ++ DW csvSecureCallEnd - csvSecureCallBase ++ DB 0x6F, 0x92, 0x5D, 0x9A, 0xA5, 0x2F, 0xBA, 0xCE ++ DB 0xAB, 0x21, 0x6B, 0x27, 0x5D, 0x55, 0x56, 0xA5 ++csvSecureCallEnd: ++ + ; + ; TDX Metadata offset block + ; +diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm +index 043c88a..e0433ce 100644 +--- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm ++++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm +@@ -192,6 +192,15 @@ pageTableEntries4kLoop: + mov ecx, (GHCB_BASE & 0x1F_FFFF) >> 12 + mov [ecx * 8 + GHCB_PT_ADDR + 4], strict dword 0 + ++ OneTimeCall CheckCsvFeature ++ test eax, eax ++ jz SevClearPageEncMaskForGhcbPageExit ++ ++ OneTimeCall CsvInit ++ mov eax, 1 ++ test ecx, ecx ++ jz SevEsUnexpectedRespTerminate ++ + SevClearPageEncMaskForGhcbPageExit: + OneTimeCallRet SevClearPageEncMaskForGhcbPage + +diff --git a/OvmfPkg/ResetVector/Ia32/CsvInit.asm b/OvmfPkg/ResetVector/Ia32/CsvInit.asm +new file mode 100644 +index 0000000..0744a35 +--- /dev/null ++++ b/OvmfPkg/ResetVector/Ia32/CsvInit.asm +@@ -0,0 +1,107 @@ ++;------------------------------------------------------------------------------ ++; @file ++; Provide the functions to check whether CSV is enabled. ++; ++; Copyright (c) 2022, HYGON. All rights reserved.
++; SPDX-License-Identifier: BSD-2-Clause-Patent ++; ++;------------------------------------------------------------------------------ ++ ++BITS 32 ++ ++; If Secure Command returns ok then ECX will be non-zero. ++; If Secure Command returns error then ECX will be zero. ++CsvInit: ++ mov esp, SEV_ES_VC_TOP_OF_STACK ++ push esi ++ push edi ++ ++ ; copy SECURE_CALL_GUID to CSV_DEFAULT_SECURE_CALL_BASE + 4096 ++ cld ++ mov esi, ADDR_OF(SECURE_CALL_GUID) ++ mov edi, CSV_DEFAULT_SECURE_CALL_BASE ++ add edi, 4096 ++ mov ecx, 4 ++ rep movsd ++ ++ ; secure call begin ++ mov esi, CSV_DEFAULT_SECURE_CALL_BASE ++ ; write secure cmd to page B ++ ; 16 bytes of page A/B is GUID, just ignore ++ mov [esi + 4096 + 16], DWORD 2 ; dec command ++ mov [esi + 4096 + 20], DWORD 1 ; 1 entry ++ ; 8 bytes is unused ++ mov [esi + 4096 + 32], DWORD GHCB_BASE; lower address ++ mov [esi + 4096 + 36], DWORD 0 ; upper address ++ mov [esi + 4096 + 40], DWORD 4096 ; lower 32 bit of page size ++ mov [esi + 4096 + 44], DWORD 0 ; upper 32 bit of page size ++ mfence ++ ; read from page A ++ mov ecx, [esi + 16] ++ ; check if the response comes ++ cmp ecx, 2 ++ jne SecureCommandDone ++ ; no secure command response, clean ecx ++ xor ecx, ecx ++ ; secure call end ++ ++SecureCommandDone: ++ pop edi ++ pop esi ++ mov esp, 0 ++ ++ OneTimeCallRet CsvInit ++ ++; Check if CSV feature is enabled. ++; ++; Modified: EAX, EBX, ECX, EDX ++; ++; If CSV is enabled then EAX will be non-zero. ++; If CSV is disabled then EAX will be zero. ++; ++CheckCsvFeature: ++ mov esp, SEV_ES_VC_TOP_OF_STACK ++ mov eax, ADDR_OF(Idtr) ++ lidt [cs:eax] ++ ++ ; Check if vendor Hygon CPUID_SIGNATURE(0x0) ++ ; CPUID raises a #VC exception if running as an SEV-ES guest ++ mov eax, 0 ++ cpuid ++ ++ cmp ebx, 0x6f677948 ++ jne NoCsv ++ cmp ecx, 0x656e6975 ++ jne NoCsv ++ cmp edx, 0x6e65476e ++ jne NoCsv ++ ++ ; Check if CSV is enabled ++ ; MSR_0xC0010131 - Bit 30 (CSV enabled) ++ mov ecx, 0xc0010131 ++ rdmsr ++ and eax, 0x40000000 ++ jmp CsvExit ++ ++NoCsv: ++ xor eax, eax ++ ++CsvExit: ++ ; ++ ; Clear exception handlers and stack ++ ; ++ push eax ++ mov eax, ADDR_OF(IdtrClear) ++ lidt [cs:eax] ++ pop eax ++ mov esp, 0 ++ ++ OneTimeCallRet CheckCsvFeature ++ ++SECURE_CALL_GUID: ++; low 0xceba2fa59a5d926f ++; high 0xa556555d276b21ab ++ dd 0x9a5d926f ++ dd 0xceba2fa5 ++ dd 0x276b21ab ++ dd 0xa556555d +diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf +index a4154ca..e4adedb 100644 +--- a/OvmfPkg/ResetVector/ResetVector.inf ++++ b/OvmfPkg/ResetVector/ResetVector.inf +@@ -35,6 +35,8 @@ + + [Pcd] + gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase +diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb +index 366a70f..50325dd 100644 +--- a/OvmfPkg/ResetVector/ResetVector.nasmb ++++ b/OvmfPkg/ResetVector/ResetVector.nasmb +@@ -136,11 +136,15 @@ + %define TDX_WORK_AREA_PGTBL_READY (FixedPcdGet32 (PcdOvmfWorkAreaBase) + 4) + %define TDX_WORK_AREA_GPAW (FixedPcdGet32 (PcdOvmfWorkAreaBase) + 8) + ++ %define CSV_DEFAULT_SECURE_CALL_BASE FixedPcdGet32 (PcdCsvDefaultSecureCallBase) ++ %define CSV_DEFAULT_SECURE_CALL_SIZE FixedPcdGet32 (PcdCsvDefaultSecureCallSize) ++ + %include "X64/IntelTdxMetadata.asm" + %include "Ia32/Flat32ToFlat64.asm" + %include "Ia32/PageTables64.asm" + %include "Ia32/IntelTdx.asm" + %include "X64/OvmfSevMetadata.asm" ++ %include "Ia32/CsvInit.asm" + %endif + + %include "Ia32/AmdSev.asm" +-- +2.31.1 + diff --git a/0005-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch b/0005-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch new file mode 100644 index 0000000000000000000000000000000000000000..171860ae56c73eddae4fb81e933175138d463c95 --- /dev/null +++ b/0005-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch @@ -0,0 +1,122 @@ +From 253257e9503f09aeae8d7ae443087243a4d49db2 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Thu, 16 May 2024 17:26:00 +0800 +Subject: [PATCH 05/19] anolis: OvmfPkg/PlatformPei: Initialize CSV VM's memory + +For CSV VM, the Secure Processor builds a temporary nested +page table to help the guest to run into the PEI phase. + +In PEI phase, CSV VM detects the start address and size of the +guest physical memory. + +The CSV VM sends the memory information to the Secure Processor +to build the permanent nested page table. +--- + OvmfPkg/Include/Library/PlatformInitLib.h | 5 +++++ + OvmfPkg/Library/PlatformInitLib/MemDetect.c | 2 +- + OvmfPkg/PlatformPei/Platform.c | 2 ++ + OvmfPkg/PlatformPei/Platform.h | 10 ++++++++++ + OvmfPkg/PlatformPei/PlatformPei.inf | 4 ++++ + 5 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/OvmfPkg/Include/Library/PlatformInitLib.h b/OvmfPkg/Include/Library/PlatformInitLib.h +index 57b18b9..6c28c7f 100644 +--- a/OvmfPkg/Include/Library/PlatformInitLib.h ++++ b/OvmfPkg/Include/Library/PlatformInitLib.h +@@ -151,6 +151,11 @@ PlatformGetSystemMemorySizeBelow4gb ( + IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob + ); + ++UINT64 ++EFIAPI ++PlatformGetSystemMemorySizeAbove4gb ( ++ ); ++ + /** + Initialize the PhysMemAddressWidth field in PlatformInfoHob based on guest RAM size. + **/ +diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/MemDetect.c +index f042517..01e01a7 100644 +--- a/OvmfPkg/Library/PlatformInitLib/MemDetect.c ++++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c +@@ -437,8 +437,8 @@ PlatformGetSystemMemorySizeBelow4gb ( + PlatformInfoHob->LowMemory = (UINT32)(((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB); + } + +-STATIC + UINT64 ++EFIAPI + PlatformGetSystemMemorySizeAbove4gb ( + ) + { +diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c +index f5dc41c..34d764e 100644 +--- a/OvmfPkg/PlatformPei/Platform.c ++++ b/OvmfPkg/PlatformPei/Platform.c +@@ -345,6 +345,7 @@ InitializePlatform ( + PlatformQemuUc32BaseInitialization (PlatformInfoHob); + + InitializeRamRegions (PlatformInfoHob); ++ CsvInitializeMemInfo (PlatformInfoHob); + + if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) { + if (!PlatformInfoHob->SmmSmramRequire) { +@@ -364,6 +365,7 @@ InitializePlatform ( + } else { + MiscInitialization (PlatformInfoHob); + } ++ CsvInitializeGhcb(); + + IntelTdxInitialize (); + InstallFeatureControlCallback (PlatformInfoHob); +diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h +index 1cf4484..1893f3f 100644 +--- a/OvmfPkg/PlatformPei/Platform.h ++++ b/OvmfPkg/PlatformPei/Platform.h +@@ -106,4 +106,14 @@ SevInitializeRam ( + VOID + ); + ++VOID ++CsvInitializeMemInfo ( ++ IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob ++ ); ++ ++VOID ++CsvInitializeGhcb ( ++ VOID ++ ); ++ + #endif // _PLATFORM_PEI_H_INCLUDED_ +diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf +index ad52be3..66dfdd4 100644 +--- a/OvmfPkg/PlatformPei/PlatformPei.inf ++++ b/OvmfPkg/PlatformPei/PlatformPei.inf +@@ -32,6 +32,7 @@ + Platform.c + Platform.h + IntelTdx.c ++ Csv.c + + [Packages] + EmbeddedPkg/EmbeddedPkg.dec +@@ -65,6 +66,7 @@ + PcdLib + CcExitLib + PlatformInitLib ++ CsvLib + + [Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase +@@ -131,6 +133,8 @@ + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize + + [FeaturePcd] + gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire +-- +2.31.1 + diff --git a/0006-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch b/0006-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch new file mode 100644 index 0000000000000000000000000000000000000000..32a4bf1229ffbfe2a96caed0bc8ce48407e4d1be --- /dev/null +++ b/0006-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch @@ -0,0 +1,75 @@ +From 367430e7f05e47724766b8ca68f77030307dd6c1 Mon Sep 17 00:00:00 2001 +From: Liu Zixing +Date: Sat, 26 Feb 2022 14:39:06 +0800 +Subject: [PATCH 06/19] anolis: OvmfPkg/BaseMemcryptSevLib: update page status + to Secure Processor for CSV + +For CSV VM, when encrypting/decrypting a shared/private memory region, +guest needs to + - set/clear the c-bit in guest page table + - the Secure Processor should be updated accordingly + +The BaseMemcryptSevLib has done the first step. +Calling the secure call library for second step. + +Signed-off-by: Xin Jiang +Change-Id: Ia80155fe2d17255e5bfddf8e64c053c6a3925fcd +--- + .../BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf | 1 + + .../BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +index cc24961..3a1d308 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +@@ -52,6 +52,7 @@ + MemoryAllocationLib + PcdLib + CcExitLib ++ CsvLib + + [FeaturePcd] + gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +index dee3fb8..a49cf12 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +@@ -19,6 +19,8 @@ + #include "VirtualMemory.h" + #include "SnpPageStateChange.h" + ++#include ++ + STATIC BOOLEAN mAddressEncMaskChecked = FALSE; + STATIC UINT64 mAddressEncMask; + STATIC PAGE_TABLE_POOL *mPageTablePool = NULL; +@@ -727,6 +729,11 @@ SetMemoryEncDec ( + BOOLEAN IsWpEnabled; + UINTN OrigLength; + RETURN_STATUS Status; ++ PHYSICAL_ADDRESS PageAddress; ++ UINTN PageNum; ++ ++ PageAddress = PhysicalAddress; ++ PageNum = EFI_SIZE_TO_PAGES (Length); + + // + // Set PageMapLevel4Entry to suppress incorrect compiler/analyzer warnings. +@@ -991,6 +998,13 @@ Done: + EnableReadOnlyPageWriteProtect (); + } + ++ if (CsvIsEnabled () && Status == EFI_SUCCESS) { ++ if (Mode == ClearCBit) ++ CsvUpdateMemory (PageAddress, PageNum, TRUE); ++ else ++ CsvUpdateMemory (PageAddress, PageNum, FALSE); ++ } ++ + return Status; + } + +-- +2.31.1 + diff --git a/0007-anolis-OvmfPkg-Add-CsvDxe-driver.patch b/0007-anolis-OvmfPkg-Add-CsvDxe-driver.patch new file mode 100644 index 0000000000000000000000000000000000000000..eea3bd3f9a0fda3ad40d2f091e43fb16d9fcb82e --- /dev/null +++ b/0007-anolis-OvmfPkg-Add-CsvDxe-driver.patch @@ -0,0 +1,616 @@ +From 78144835b6aeacb3fe5dbdddd3b58bae76bac197 Mon Sep 17 00:00:00 2001 +From: Liu Zixing +Date: Fri, 25 Feb 2022 16:34:25 +0800 +Subject: [PATCH 07/19] anolis: OvmfPkg: Add CsvDxe driver + +CsvDxe creates and installs the CsvSharedMemory protocol. + +CSV VM needs the shared memory to exchange data with external devices. + +To improve the performance, CsvSharedMemory protocol pre-allocates +huge shared memory chunk as a pool. + +When reqeusted, it allocates small pieces of shared memory from the +pool and records the allocated memory in a list. + +When finished, the shared memory pieces are returned to the pool and +removed from the record list. + +Signed-off-by: Xin Jiang +Change-Id: I24540228e5c74eac8141c9e97edf9b0bff215e20 +--- + OvmfPkg/CsvDxe/CsvDxe.c | 104 +++++++++++ + OvmfPkg/CsvDxe/CsvDxe.inf | 45 +++++ + OvmfPkg/CsvDxe/CsvSharedMemory.c | 208 +++++++++++++++++++++ + OvmfPkg/CsvDxe/CsvSharedMemory.h | 29 +++ + OvmfPkg/Include/Protocol/CsvSharedMemory.h | 99 ++++++++++ + OvmfPkg/OvmfPkg.dec | 1 + + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + + OvmfPkg/OvmfPkgIa32X64.fdf | 1 + + OvmfPkg/OvmfPkgX64.dsc | 1 + + OvmfPkg/OvmfPkgX64.fdf | 1 + + 10 files changed, 490 insertions(+) + create mode 100644 OvmfPkg/CsvDxe/CsvDxe.c + create mode 100644 OvmfPkg/CsvDxe/CsvDxe.inf + create mode 100644 OvmfPkg/CsvDxe/CsvSharedMemory.c + create mode 100644 OvmfPkg/CsvDxe/CsvSharedMemory.h + create mode 100644 OvmfPkg/Include/Protocol/CsvSharedMemory.h + +diff --git a/OvmfPkg/CsvDxe/CsvDxe.c b/OvmfPkg/CsvDxe/CsvDxe.c +new file mode 100644 +index 0000000..d7edf3b +--- /dev/null ++++ b/OvmfPkg/CsvDxe/CsvDxe.c +@@ -0,0 +1,104 @@ ++/** @file ++ ++ Hygon CSV DXE. ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "CsvSharedMemory.h" ++ ++ ++#define HUGE_PAGE_SIZE 0x200000ULL ++ ++EFI_STATUS ++EFIAPI ++CsvDxeEntryPoint ( ++ IN EFI_HANDLE ImageHandle, ++ IN EFI_SYSTEM_TABLE *SystemTable ++ ) ++{ ++ EFI_STATUS Status; ++ RETURN_STATUS DecryptStatus; ++ CSV_SHARED_MEMORY_PROTOCOL *SharedMemory; ++ EFI_PHYSICAL_ADDRESS Memory; ++ EFI_PHYSICAL_ADDRESS EndMemory; ++ EFI_ALLOCATE_TYPE AllocateType; ++ UINT64 Size; ++ ++ Status = CsvInstallSharedMemoryProtocol (); ++ ++ if (EFI_ERROR (Status)) { ++ DEBUG ((EFI_D_ERROR, "fail to install CsvSharedMemory protocol\n")); ++ return Status; ++ } ++ ++ // ++ // Do nothing more when CSV is not enabled ++ // ++ if (!CsvIsEnabled ()) { ++ return EFI_SUCCESS; ++ } ++ ++ Status = gBS->LocateProtocol ( ++ &gCsvSharedMemoryProtocolGuid, ++ NULL, ++ (VOID**)&SharedMemory ++ ); ++ ++ if (Status == EFI_SUCCESS) { ++ ++ AllocateType = AllocateMaxAddress; ++ Memory = BASE_4GB - 1; ++ ++ Status = gBS->AllocatePages ( ++ AllocateType, ++ EfiBootServicesData, ++ CSV_SHARED_MEMORY_PAGE_NUMBER, ++ &Memory ++ ); ++ ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "fail to allocate CsvSharedMemory\n", SharedMemory)); ++ } else { ++ //Align to huge page ++ EndMemory = (Memory + CSV_SHARED_MEMORY_SIZE) & (~(HUGE_PAGE_SIZE - 1)); ++ Memory = ALIGN_VALUE(Memory, HUGE_PAGE_SIZE); ++ Size = (EndMemory > Memory) ? EndMemory - Memory : 0; ++ DecryptStatus = MemEncryptSevClearPageEncMask ( ++ 0, ++ Memory, ++ Size >> EFI_PAGE_SHIFT ++ ); ++ ASSERT_RETURN_ERROR (DecryptStatus); ++ ++ SharedMemory->CsvInitializeSharedMemoryList ( ++ SharedMemory, ++ (UINT64)Memory, ++ Size ++ ); ++ } ++ } else { ++ DEBUG ((DEBUG_ERROR, "fail to LocateProtocol gCsvSharedMemoryProtocolGuid\n")); ++ } ++ ++ return EFI_SUCCESS; ++} +diff --git a/OvmfPkg/CsvDxe/CsvDxe.inf b/OvmfPkg/CsvDxe/CsvDxe.inf +new file mode 100644 +index 0000000..0dc8860 +--- /dev/null ++++ b/OvmfPkg/CsvDxe/CsvDxe.inf +@@ -0,0 +1,45 @@ ++#/** @file ++# ++# Secure Isolated Virtualization ++# ++# Copyright (c) 2022, HYGON Inc. All rights reserved.
++# ++# 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 = 1.25 ++ BASE_NAME = CsvDxe ++ FILE_GUID = 829310c0-b9c4-11e9-9e16-9b10d744f884 ++ MODULE_TYPE = DXE_DRIVER ++ VERSION_STRING = 1.0 ++ ENTRY_POINT = CsvDxeEntryPoint ++ ++[Sources] ++ CsvDxe.c ++ CsvSharedMemory.c ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ OvmfPkg/OvmfPkg.dec ++ ++[LibraryClasses] ++ BaseLib ++ BaseMemoryLib ++ DebugLib ++ CsvLib ++ UefiDriverEntryPoint ++ ++[Depex] ++ TRUE ++ ++[Protocols] ++ gCsvSharedMemoryProtocolGuid +diff --git a/OvmfPkg/CsvDxe/CsvSharedMemory.c b/OvmfPkg/CsvDxe/CsvSharedMemory.c +new file mode 100644 +index 0000000..fbebc61 +--- /dev/null ++++ b/OvmfPkg/CsvDxe/CsvSharedMemory.c +@@ -0,0 +1,208 @@ ++/** @file ++ ++ The protocol provides allocate, free the CSV shared memory. ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++STATIC LIST_ENTRY CsvSharedMemoryList = INITIALIZE_LIST_HEAD_VARIABLE (CsvSharedMemoryList); ++ ++// ++// Insert the initial shared memory address and length to list. ++// ++ ++EFI_STATUS ++EFIAPI ++CsvInitializeSharedMemoryList ( ++ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol, ++ IN UINT64 Address, ++ IN UINT64 Length ++ ) ++{ ++ CsvSharedMemoryEntry *Entry; ++ ++ if (Length == 0) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ Entry = AllocatePool (sizeof (*Entry)); ++ if (Entry == NULL) { ++ DEBUG((DEBUG_ERROR, "CsvInitializeSharedMemoryList AllocatePool error\n")); ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ Entry->Start = Address; ++ Entry->Length = Length; ++ Entry->Signature = CSV_SHARED_MEMORY_SIGNATURE; ++ ++ InsertTailList (&CsvSharedMemoryList, &Entry->Link); ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++CsvAllocateSharedMemory ( ++ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol, ++ IN UINTN NumberOfPages, ++ OUT UINT64 *Memory ++ ) ++{ ++ LIST_ENTRY *Link; ++ CsvSharedMemoryEntry *Entry; ++ UINT64 MemoryLength; ++ ++ MemoryLength = (UINT64)NumberOfPages << EFI_PAGE_SHIFT; ++ ++ for (Link = CsvSharedMemoryList.ForwardLink; Link != &CsvSharedMemoryList; Link = Link->ForwardLink) { ++ Entry = CR (Link, CsvSharedMemoryEntry, Link, CSV_SHARED_MEMORY_SIGNATURE); ++ if (Entry->Length > MemoryLength) { ++ *Memory = (EFI_PHYSICAL_ADDRESS)Entry->Start; ++ Entry->Start = *Memory + MemoryLength; ++ Entry->Length -= MemoryLength; ++ break; ++ } else if (Entry->Length == MemoryLength) { ++ *Memory = (EFI_PHYSICAL_ADDRESS)Entry->Start; ++ RemoveEntryList (&Entry->Link); ++ FreePool (Entry); ++ break; ++ } ++ } ++ ++ ++ ++ if (Link == &CsvSharedMemoryList) { ++ DEBUG ((EFI_D_ERROR, "CsvAllocateSharedMemory fail to allocate %u pages\n", NumberOfPages)); ++ return EFI_NOT_FOUND; ++ } ++ else { ++ return EFI_SUCCESS; ++ } ++} ++ ++ ++ ++EFI_STATUS ++EFIAPI ++CsvFreeSharedMemory ( ++ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol, ++ IN UINTN Pages, ++ IN UINT64 HostAddress ++ ) ++{ ++ LIST_ENTRY *Link; ++ CsvSharedMemoryEntry *Entry; ++ CsvSharedMemoryEntry *NewEntry; ++ UINT64 Memory; ++ UINT64 MemoryLength; ++ CsvSharedMemoryEntry *Previous = NULL; ++ BOOLEAN Inserted = FALSE; ++ ++ Memory = (UINT64)HostAddress; ++ MemoryLength = (UINT64)Pages << EFI_PAGE_SHIFT; ++ ++ for (Link = CsvSharedMemoryList.ForwardLink; ++ Link != &CsvSharedMemoryList; ++ Link = Link->ForwardLink) { ++ Entry = CR (Link, CsvSharedMemoryEntry, Link, CSV_SHARED_MEMORY_SIGNATURE); ++ if (Inserted) ++ goto Merge; ++ if (Entry->Start + Entry->Length == Memory) { ++ Entry->Length += MemoryLength; ++ Inserted = TRUE; ++ goto Merge; ++ } else if (Memory + MemoryLength < Entry->Start) { ++ NewEntry = AllocatePool (sizeof *NewEntry); ++ if (NewEntry == NULL) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ NewEntry->Start = Memory; ++ NewEntry->Length = MemoryLength; ++ NewEntry->Signature = CSV_SHARED_MEMORY_SIGNATURE; ++ ++ InsertTailList (&Entry->Link, &NewEntry->Link); ++ break; ++ } else if (Memory + MemoryLength == Entry->Start) { ++ Entry->Start = Memory; ++ Entry->Length += MemoryLength; ++ break; ++ } else if (Link->ForwardLink == &CsvSharedMemoryList) { ++ // ++ // Insert to tail ++ // ++ NewEntry = AllocatePool (sizeof *NewEntry); ++ if (NewEntry == NULL) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ NewEntry->Start = Memory; ++ NewEntry->Length = MemoryLength; ++ NewEntry->Signature = CSV_SHARED_MEMORY_SIGNATURE; ++ InsertHeadList (Link, &NewEntry->Link); ++ break; ++ } ++ ++Merge: ++ if (Previous) { ++ if (Previous->Start + Previous->Length == Entry->Start) { ++ Entry->Start = Previous->Start; ++ Entry->Length += Previous->Length; ++ RemoveEntryList (&Previous->Link); ++ FreePool (Previous); ++ } ++ break; ++ } else { ++ Previous = Entry; ++ } ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++CSV_SHARED_MEMORY_PROTOCOL mCsvSharedMemory = { ++ CsvInitializeSharedMemoryList, ++ CsvAllocateSharedMemory, ++ CsvFreeSharedMemory ++}; ++ ++/** ++ Initialize CsvSharedMemory Protocol. ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvInstallSharedMemoryProtocol ( ++ VOID ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_HANDLE Handle; ++ ++ Handle = NULL; ++ Status = gBS->InstallMultipleProtocolInterfaces ( ++ &Handle, ++ &gCsvSharedMemoryProtocolGuid, ++ &mCsvSharedMemory, ++ NULL ++ ); ++ return Status; ++} +diff --git a/OvmfPkg/CsvDxe/CsvSharedMemory.h b/OvmfPkg/CsvDxe/CsvSharedMemory.h +new file mode 100644 +index 0000000..1634818 +--- /dev/null ++++ b/OvmfPkg/CsvDxe/CsvSharedMemory.h +@@ -0,0 +1,29 @@ ++/** @file ++ CSV shared memory management protocol ++ ++ Copyright (C) 2022 HYGON. ++ ++ 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 _CSV_SHARED_MEMORY_H_ ++#define _CSV_SHARED_MEMORY_H_ ++ ++// ++// Install SHARED_MEMORY protocol . ++// ++ ++EFI_STATUS ++EFIAPI ++CsvInstallSharedMemoryProtocol ( ++ VOID ++ ); ++ ++#endif +diff --git a/OvmfPkg/Include/Protocol/CsvSharedMemory.h b/OvmfPkg/Include/Protocol/CsvSharedMemory.h +new file mode 100644 +index 0000000..ba62f3a +--- /dev/null ++++ b/OvmfPkg/Include/Protocol/CsvSharedMemory.h +@@ -0,0 +1,99 @@ ++/** @file ++ CSV shared memory management protocol ++ ++ Copyright (C) 2022 HYGON. ++ ++ 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 __PROTOCOL_CSV_SHARED_MEMORY_H__ ++#define __PROTOCOL_CSV_SHARED_MEMORY_H__ ++ ++#define CSV_SHARED_MEMORY_PAGE_NUMBER (16384ULL) ++#define CSV_SHARED_MEMORY_SIZE ((CSV_SHARED_MEMORY_PAGE_NUMBER)*(SIZE_4KB)) ++ ++/// ++/// Forward declaration ++/// ++typedef struct _CSV_SHARED_MEMORY_PROTOCOL CSV_SHARED_MEMORY_PROTOCOL; ++ ++ ++/// ++/// Function prototypes ++/// ++ ++/** ++ Initialize the list to manage the CSV shared memory. ++ Insert the start address and length. ++ ++ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance. ++ @param Address The start address of the shared memory. ++ @param Length The length of the shared memory. ++ ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *CSV_INITIALIZE_SHARED_MEMORY_LIST)( ++ IN CSV_SHARED_MEMORY_PROTOCOL *This, ++ IN UINT64 Address, ++ IN UINT64 Length ++ ); ++ ++/** ++ Allocate buffer from the shared memory. ++ ++ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance. ++ @param NumberOfPages The length of page number. ++ @param Memory When success, allocated memory will be stored in. ++ ++ @return On success, EFI_SUCCESS. Otherwise an errno value ++ indicating the type of failure. ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *CSV_ALLOCATE_SHARED_MEMORY)( ++ IN CSV_SHARED_MEMORY_PROTOCOL *This, ++ IN UINTN NumberOfPages, ++ OUT UINT64 *Memory ++ ); ++ ++/** ++ Free buffer to the shared memory. ++ ++ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance. ++ @param NumberOfPages The page number. ++ @param Memory The allocated memory to be freed. ++ ++ @return On success, EFI_SUCCESS. Otherwise an errno value ++ indicating the type of failure. ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *CSV_FREE_SHARED_MEMORY)( ++ IN CSV_SHARED_MEMORY_PROTOCOL *This, ++ IN UINTN NumberOfPages, ++ IN UINT64 Memory ++ ); ++ ++/// ++/// Protocol structure ++/// ++struct _CSV_SHARED_MEMORY_PROTOCOL { ++ // ++ // Protocol data fields ++ // ++ CSV_INITIALIZE_SHARED_MEMORY_LIST CsvInitializeSharedMemoryList; ++ CSV_ALLOCATE_SHARED_MEMORY CsvAllocateSharedMemory; ++ CSV_FREE_SHARED_MEMORY CsvFreeSharedMemory; ++}; ++ ++extern EFI_GUID gCsvSharedMemoryProtocolGuid; ++ ++#endif +diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec +index b17d5c3..e468d6c 100644 +--- a/OvmfPkg/OvmfPkg.dec ++++ b/OvmfPkg/OvmfPkg.dec +@@ -194,6 +194,7 @@ + gQemuAcpiTableNotifyProtocolGuid = {0x928939b2, 0x4235, 0x462f, {0x95, 0x80, 0xf6, 0xa2, 0xb2, 0xc2, 0x1a, 0x4f}} + gEfiMpInitLibMpDepProtocolGuid = {0xbb00a5ca, 0x8ce, 0x462f, {0xa5, 0x37, 0x43, 0xc7, 0x4a, 0x82, 0x5c, 0xa4}} + gEfiMpInitLibUpDepProtocolGuid = {0xa9e7cef1, 0x5682, 0x42cc, {0xb1, 0x23, 0x99, 0x30, 0x97, 0x3f, 0x4a, 0x9f}} ++ gCsvSharedMemoryProtocolGuid = {0x0c795ed0, 0xbf0a, 0x11e9, {0x99, 0xbe, 0x50, 0x9a, 0x4c, 0x01, 0x1e, 0xd1}} + + [PcdsFixedAtBuild] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0 +diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc +index a88b61b..aab02bb 100644 +--- a/OvmfPkg/OvmfPkgIa32X64.dsc ++++ b/OvmfPkg/OvmfPkgIa32X64.dsc +@@ -944,6 +944,7 @@ + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + } + OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++ OvmfPkg/CsvDxe/CsvDxe.inf + + !if $(SMM_REQUIRE) == TRUE + OvmfPkg/SmmAccess/SmmAccess2Dxe.inf +diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf +index 74cfb58..191c82f 100644 +--- a/OvmfPkg/OvmfPkgIa32X64.fdf ++++ b/OvmfPkg/OvmfPkgIa32X64.fdf +@@ -332,6 +332,7 @@ INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf + INF OvmfPkg/PlatformDxe/Platform.inf + INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf + INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++INF OvmfPkg/CsvDxe/CsvDxe.inf + + !if $(SMM_REQUIRE) == TRUE + INF OvmfPkg/SmmAccess/SmmAccess2Dxe.inf +diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc +index a6691af..de4b9a1 100644 +--- a/OvmfPkg/OvmfPkgX64.dsc ++++ b/OvmfPkg/OvmfPkgX64.dsc +@@ -1011,6 +1011,7 @@ + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + } + OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++ OvmfPkg/CsvDxe/CsvDxe.inf + + OvmfPkg/TdxDxe/TdxDxe.inf + +diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf +index f6fd7a0..0c58f75 100644 +--- a/OvmfPkg/OvmfPkgX64.fdf ++++ b/OvmfPkg/OvmfPkgX64.fdf +@@ -362,6 +362,7 @@ INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf + INF OvmfPkg/PlatformDxe/Platform.inf + INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf + INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++INF OvmfPkg/CsvDxe/CsvDxe.inf + + !if $(SMM_REQUIRE) == TRUE + INF OvmfPkg/SmmAccess/SmmAccess2Dxe.inf +-- +2.31.1 + diff --git a/0008-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch b/0008-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch new file mode 100644 index 0000000000000000000000000000000000000000..d804435ac1ffb404c74d575193c004e208dd71ea --- /dev/null +++ b/0008-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch @@ -0,0 +1,813 @@ +From 7f832b6c6aad168d3a4e5b7f9ab140f2f4ff87b3 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Thu, 16 May 2024 17:27:46 +0800 +Subject: [PATCH 08/19] anolis: OvmfPkg/IoMmuDxe: Add CsvIoMmu protocol + +Create the dedicated IoMmu protocol for CSV virtual machine. +And Install it during CSV VM boots up. + +It calls the CsvSharedMemoryProtocol to allocate shared memory +for DMA operations. + +- AllocateBuffer() allocates the shared memory. + +- FreeBuffer() frees the shared memory. + +- Map() does nothing when BusMasterCommonBuffer[64] is requested + Otherwise, Map() allocates shared memory. + +- Unmap() does nothing when cleaning up a BusMasterCommonBuffer[64] + operation. Otherwise, Unmap() frees the shared memory. +--- + OvmfPkg/IoMmuDxe/CsvIoMmu.c | 592 ++++++++++++++++++++++++++++++++++ + OvmfPkg/IoMmuDxe/CsvIoMmu.h | 29 ++ + OvmfPkg/IoMmuDxe/IoMmuDxe.c | 10 + + OvmfPkg/IoMmuDxe/IoMmuDxe.inf | 6 +- + OvmfPkg/PlatformPei/Csv.c | 82 +++++ + 5 files changed, 718 insertions(+), 1 deletion(-) + create mode 100644 OvmfPkg/IoMmuDxe/CsvIoMmu.c + create mode 100644 OvmfPkg/IoMmuDxe/CsvIoMmu.h + create mode 100644 OvmfPkg/PlatformPei/Csv.c + +diff --git a/OvmfPkg/IoMmuDxe/CsvIoMmu.c b/OvmfPkg/IoMmuDxe/CsvIoMmu.c +new file mode 100644 +index 0000000..2a46e98 +--- /dev/null ++++ b/OvmfPkg/IoMmuDxe/CsvIoMmu.c +@@ -0,0 +1,592 @@ ++/** @file ++ ++ The protocol provides support to allocate, free, map and umap a DMA buffer ++ for bus master (e.g PciHostBridge). When CSV is enabled, the DMA operations ++ must be performed on non-secure memory so we have to allocate the DMA buffer ++ from non-secure memory. ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ 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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "CsvIoMmu.h" ++ ++#define MAP_INFO_SIG SIGNATURE_64 ('M', 'A', 'P', '_', 'I', 'N', 'F', 'O') ++ ++typedef struct { ++ UINT64 Signature; ++ LIST_ENTRY Link; ++ EDKII_IOMMU_OPERATION Operation; ++ UINTN NumberOfBytes; ++ UINTN NumberOfPages; ++ EFI_PHYSICAL_ADDRESS SecureAddress; ++ EFI_PHYSICAL_ADDRESS UnSecureAddress; ++} MAP_INFO; ++ ++// ++// List of the MAP_INFO structures that have been set up by IoMmuMap() and not ++// yet torn down by IoMmuUnmap(). The list represents the full set of mappings ++// currently in effect. ++// ++STATIC LIST_ENTRY mMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (mMapInfos); ++ ++// ++// ASCII names for EDKII_IOMMU_OPERATION constants, for debug logging. ++// ++STATIC CONST CHAR8 * CONST ++mBusMasterOperationName[EdkiiIoMmuOperationMaximum] = { ++ "Read", ++ "Write", ++ "CommonBuffer", ++ "Read64", ++ "Write64", ++ "CommonBuffer64" ++}; ++ ++STATIC CSV_SHARED_MEMORY_PROTOCOL *SharedMemory; ++STATIC ++EFI_STATUS ++EFIAPI ++CsvAllocSharedPage( ++ IN UINTN Pages, ++ OUT EFI_PHYSICAL_ADDRESS *Address ++ ) ++{ ++ EFI_STATUS Status; ++ ++ Status = SharedMemory->CsvAllocateSharedMemory ( ++ SharedMemory, ++ Pages, ++ (UINT64*)Address ++ ); ++ ++ return Status; ++} ++ ++STATIC ++EFI_STATUS ++EFIAPI ++CsvFreeSharedPage( ++ IN UINTN Pages, ++ IN VOID *HostAddress ++ ) ++{ ++ EFI_STATUS Status; ++ ++ Status = SharedMemory->CsvFreeSharedMemory ( ++ SharedMemory, ++ Pages, ++ (UINTN)HostAddress ++ ); ++ ++ return Status; ++} ++ ++/** ++ Provides the controller-specific addresses required to access system memory ++ from a DMA bus master. ++ On CSV guest, the DMA openerations must be done on non-secure memory which ++ is the shared memory between the guest and QEMU. ++ ++ @param This The protocol instance pointer. ++ @param Operation Indicates if the bus master is going to read or ++ write to system memory. ++ @param HostAddress The system memory address to map to the PCI ++ controller. ++ @param NumberOfBytes On input the number of bytes to map. On output ++ the number of bytes that were mapped. ++ @param DeviceAddress The resulting map address for the bus master ++ PCI controller to use to access the hosts ++ HostAddress. ++ @param Mapping A resulting value to pass to Unmap(). ++ ++ @retval EFI_SUCCESS The range was mapped for the returned ++ NumberOfBytes. ++ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common ++ buffer. ++ @retval EFI_INVALID_PARAMETER One or more parameters are invalid. ++ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a ++ lack of resources. ++ @retval EFI_DEVICE_ERROR The system hardware could not map the requested ++ address. ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvIoMmuMap ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN EDKII_IOMMU_OPERATION Operation, ++ IN VOID *HostAddress, ++ IN OUT UINTN *NumberOfBytes, ++ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, ++ OUT VOID **Mapping ++ ) ++{ ++ EFI_STATUS Status; ++ MAP_INFO *MapInfo; ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: Operation=%a Operation=%u Host=0x%p Bytes=0x%Lx\n", ++ __FUNCTION__, ++ ((Operation >= 0 && ++ Operation < ARRAY_SIZE (mBusMasterOperationName)) ? ++ mBusMasterOperationName[Operation] : ++ "Invalid"), ++ Operation, ++ HostAddress, ++ (UINT64)((NumberOfBytes == NULL) ? 0 : *NumberOfBytes) ++ )); ++ ++ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || ++ Mapping == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is ++ // called later. ++ // ++ MapInfo = AllocatePool (sizeof (MAP_INFO)); ++ if (MapInfo == NULL) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto Failed; ++ } ++ ++ ZeroMem (&MapInfo->Link, sizeof MapInfo->Link); ++ MapInfo->Operation = Operation; ++ MapInfo->NumberOfBytes = *NumberOfBytes; ++ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes); ++ MapInfo->Signature = MAP_INFO_SIG; ++ ++ switch (Operation) { ++ // ++ // For BusMasterRead[64] and BusMasterWrite[64] operations, a bounce buffer ++ // is necessary regardless of whether the original (crypted) buffer crosses ++ // the 4GB limit or not -- we have to allocate a separate plaintext buffer. ++ // The only variable is whether the plaintext buffer should be under 4GB. ++ // ++ case EdkiiIoMmuOperationBusMasterRead: ++ case EdkiiIoMmuOperationBusMasterWrite: ++ // ++ // fall through ++ // ++ case EdkiiIoMmuOperationBusMasterRead64: ++ case EdkiiIoMmuOperationBusMasterWrite64: ++ // ++ // Allocate the implicit plaintext bounce buffer. ++ // ++ Status = CsvAllocSharedPage ( ++ MapInfo->NumberOfPages, ++ &MapInfo->UnSecureAddress ++ ); ++ if (EFI_ERROR (Status)) { ++ goto FreeMapInfo; ++ } ++ MapInfo->SecureAddress = (UINTN)HostAddress; ++ if (Operation == EdkiiIoMmuOperationBusMasterRead || ++ Operation == EdkiiIoMmuOperationBusMasterRead64) { ++ CopyMem ( ++ (VOID *) (UINTN) MapInfo->UnSecureAddress, ++ (VOID *) (UINTN) MapInfo->SecureAddress, ++ MapInfo->NumberOfBytes ++ ); ++ } ++ break; ++ ++ // ++ // For BusMasterCommonBuffer[64] operations, ++ // AllocateBuffer already returns the plain-text, ++ // No need to decrypt the data. ++ // ++ case EdkiiIoMmuOperationBusMasterCommonBuffer: ++ case EdkiiIoMmuOperationBusMasterCommonBuffer64: ++ MapInfo->UnSecureAddress = (UINTN)HostAddress; ++ MapInfo->SecureAddress = (UINTN)HostAddress; ++ break; ++ ++ default: ++ // ++ // Operation is invalid ++ // ++ Status = EFI_INVALID_PARAMETER; ++ goto FreeMapInfo; ++ } ++ ++ // ++ // Track all MAP_INFO structures. ++ // ++ InsertHeadList (&mMapInfos, &MapInfo->Link); ++ // ++ // Populate output parameters. ++ // ++ *DeviceAddress = MapInfo->UnSecureAddress; ++ *Mapping = MapInfo; ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: Mapping=0x%p Device=0x%Lx Host=0x%Lx Pages=0x%Lx\n", ++ __FUNCTION__, ++ MapInfo, ++ MapInfo->UnSecureAddress, ++ MapInfo->SecureAddress, ++ (UINT64)MapInfo->NumberOfPages ++ )); ++ ++ return EFI_SUCCESS; ++ ++FreeMapInfo: ++ FreePool (MapInfo); ++ ++Failed: ++ *NumberOfBytes = 0; ++ return Status; ++} ++ ++/** ++ Completes the Map() operation and releases any corresponding resources. ++ ++ This is an internal worker function that only extends the Map() API with ++ the MemoryMapLocked parameter. ++ ++ @param This The protocol instance pointer. ++ @param Mapping The mapping value returned from Map(). ++ @param MemoryMapLocked The function is executing on the stack of ++ gBS->ExitBootServices(); changes to the UEFI ++ memory map are forbidden. ++ ++ @retval EFI_SUCCESS The range was unmapped. ++ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by ++ Map(). ++ @retval EFI_DEVICE_ERROR The data was not committed to the target system ++ memory. ++**/ ++STATIC ++EFI_STATUS ++EFIAPI ++CsvIoMmuUnmapWorker ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN VOID *Mapping, ++ IN BOOLEAN MemoryMapLocked ++ ) ++{ ++ MAP_INFO *MapInfo; ++ EDKII_IOMMU_OPERATION Operation; ++ ++ if (Mapping == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ MapInfo = (MAP_INFO *)Mapping; ++ Operation = MapInfo->Operation; ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: Mapping=0x%p MemoryMapLocked=%d Operation %a Operation %d\n", ++ __FUNCTION__, ++ Mapping, ++ MemoryMapLocked, ++ ((Operation >= 0 && ++ Operation < ARRAY_SIZE (mBusMasterOperationName)) ? ++ mBusMasterOperationName[Operation] : ++ "Invalid"), ++ Operation ++ )); ++ ++ switch (MapInfo->Operation) { ++ case EdkiiIoMmuOperationBusMasterWrite: ++ case EdkiiIoMmuOperationBusMasterWrite64: ++ CopyMem ( ++ (VOID *) (UINTN) MapInfo->SecureAddress, ++ (VOID *) (UINTN) MapInfo->UnSecureAddress, ++ MapInfo->NumberOfBytes ++ ); ++ case EdkiiIoMmuOperationBusMasterRead: ++ case EdkiiIoMmuOperationBusMasterRead64: ++ ZeroMem ( ++ (VOID *)(UINTN)MapInfo->UnSecureAddress, ++ EFI_PAGES_TO_SIZE (MapInfo->NumberOfPages) ++ ); ++ CsvFreeSharedPage( ++ MapInfo->NumberOfPages, ++ (VOID*)(UINTN)MapInfo->UnSecureAddress ++ ); ++ ++ default: ++ break; ++ } ++ ++ // ++ // Forget the MAP_INFO structure, then free it (unless the UEFI memory map is ++ // locked). ++ // ++ RemoveEntryList (&MapInfo->Link); ++ if (!MemoryMapLocked) { ++ FreePool (MapInfo); ++ } ++ ++ return EFI_SUCCESS; ++ ++} ++ ++/** ++ Completes the Map() operation and releases any corresponding resources. ++ ++ @param This The protocol instance pointer. ++ @param Mapping The mapping value returned from Map(). ++ ++ @retval EFI_SUCCESS The range was unmapped. ++ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by ++ Map(). ++ @retval EFI_DEVICE_ERROR The data was not committed to the target system ++ memory. ++**/ ++EFI_STATUS ++EFIAPI ++CsvIoMmuUnmap ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN VOID *Mapping ++ ) ++{ ++ return CsvIoMmuUnmapWorker ( ++ This, ++ Mapping, ++ FALSE // MemoryMapLocked ++ ); ++} ++ ++/** ++ Allocates pages that are suitable for an OperationBusMasterCommonBuffer or ++ OperationBusMasterCommonBuffer64 mapping. ++ ++ @param This The protocol instance pointer. ++ @param Type This parameter is not used and must be ignored. ++ @param MemoryType The type of memory to allocate, ++ EfiBootServicesData or EfiRuntimeServicesData. ++ @param Pages The number of pages to allocate. ++ @param HostAddress A pointer to store the base system memory ++ address of the allocated range. ++ @param Attributes The requested bit mask of attributes for the ++ allocated range. ++ ++ @retval EFI_SUCCESS The requested memory pages were allocated. ++ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal ++ attribute bits are MEMORY_WRITE_COMBINE and ++ MEMORY_CACHED. ++ @retval EFI_INVALID_PARAMETER One or more parameters are invalid. ++ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvIoMmuAllocateBuffer ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN EFI_ALLOCATE_TYPE Type, ++ IN EFI_MEMORY_TYPE MemoryType, ++ IN UINTN Pages, ++ IN OUT VOID **HostAddress, ++ IN UINT64 Attributes ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_PHYSICAL_ADDRESS PhysicalAddress; ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: MemoryType=%u Pages=0x%Lx Attributes=0x%Lx\n", ++ __FUNCTION__, ++ (UINT32)MemoryType, ++ (UINT64)Pages, ++ Attributes ++ )); ++ ++ // ++ // Validate Attributes ++ // ++ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) { ++ return EFI_UNSUPPORTED; ++ } ++ ++ // ++ // Check for invalid inputs ++ // ++ if (HostAddress == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // The only valid memory types are EfiBootServicesData and ++ // EfiRuntimeServicesData ++ // ++ if (MemoryType != EfiBootServicesData && ++ MemoryType != EfiRuntimeServicesData) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // We'll need a header page for the COMMON_BUFFER_HEADER structure. ++ // ++ if (Pages > MAX_UINTN - 1) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ Status = CsvAllocSharedPage (Pages,&PhysicalAddress); ++ if (Status != EFI_SUCCESS){ ++ goto error; ++ } ++ ++ ++ *HostAddress = (VOID *)(UINTN)PhysicalAddress; ++ ++ return EFI_SUCCESS; ++ ++error: ++ return Status; ++} ++ ++/** ++ Frees memory that was allocated with AllocateBuffer(). ++ ++ @param This The protocol instance pointer. ++ @param Pages The number of pages to free. ++ @param HostAddress The base system memory address of the allocated ++ range. ++ ++ @retval EFI_SUCCESS The requested memory pages were freed. ++ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and ++ Pages was not allocated with AllocateBuffer(). ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvIoMmuFreeBuffer ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN UINTN Pages, ++ IN VOID *HostAddress ++ ) ++{ ++ ++ EFI_STATUS Status; ++ ++ if (HostAddress == NULL || Pages == 0) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: Host=0x%p Pages=0x%Lx\n", ++ __FUNCTION__, ++ HostAddress, ++ (UINT64)Pages ++ )); ++ ++ Status = CsvFreeSharedPage (Pages, HostAddress); ++ ++ return Status; ++} ++ ++ ++/** ++ Set IOMMU attribute for a system memory. ++ ++ @param[in] This The protocol instance pointer. ++ @param[in] DeviceHandle The device who initiates the DMA access ++ request. ++ @param[in] Mapping The mapping value returned from Map(). ++ @param[in] IoMmuAccess The IOMMU access. ++ ++ @retval EFI_SUCCESS The IoMmuAccess is set for the memory range ++ specified by DeviceAddress and Length. ++ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle. ++ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by ++ Map(). ++ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination ++ of access. ++ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU. ++ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported ++ by the IOMMU. ++ @retval EFI_UNSUPPORTED The IOMMU does not support the memory range ++ specified by Mapping. ++ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to ++ modify the IOMMU access. ++ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while ++ attempting the operation. ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvIoMmuSetAttribute ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN EFI_HANDLE DeviceHandle, ++ IN VOID *Mapping, ++ IN UINT64 IoMmuAccess ++ ) ++{ ++ return EFI_UNSUPPORTED; ++} ++ ++EDKII_IOMMU_PROTOCOL mCsv = { ++ EDKII_IOMMU_PROTOCOL_REVISION, ++ CsvIoMmuSetAttribute, ++ CsvIoMmuMap, ++ CsvIoMmuUnmap, ++ CsvIoMmuAllocateBuffer, ++ CsvIoMmuFreeBuffer, ++}; ++ ++/** ++ Initialize Iommu Protocol. ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvInstallIoMmuProtocol ( ++ VOID ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_HANDLE Handle; ++ ++ Status = gBS->LocateProtocol ( ++ &gCsvSharedMemoryProtocolGuid, ++ NULL, ++ (VOID**)&SharedMemory ++ ); ++ ++ if (EFI_ERROR (Status)) { ++ goto error; ++ } ++ ++ Handle = NULL; ++ Status = gBS->InstallMultipleProtocolInterfaces ( ++ &Handle, ++ &gEdkiiIoMmuProtocolGuid, ++ &mCsv, ++ NULL ++ ); ++ if (EFI_ERROR (Status)) { ++ goto error; ++ } ++ ++ return EFI_SUCCESS; ++ ++error: ++ return Status; ++} +diff --git a/OvmfPkg/IoMmuDxe/CsvIoMmu.h b/OvmfPkg/IoMmuDxe/CsvIoMmu.h +new file mode 100644 +index 0000000..431d284 +--- /dev/null ++++ b/OvmfPkg/IoMmuDxe/CsvIoMmu.h +@@ -0,0 +1,29 @@ ++/** @file ++ ++ The protocol provides support to allocate, free, map and umap a DMA buffer ++ for bus master (e.g PciHostBridge). When CSV is enabled, the DMA operations ++ must be performed on unencrypted buffer hence protocol clear the encryption ++ bit from the DMA buffer. ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ 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 _CSV_IOMMU_H_ ++#define _CSV_IOMMU_H_ ++ ++EFI_STATUS ++EFIAPI ++CsvInstallIoMmuProtocol ( ++ VOID ++ ); ++ ++#endif +diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.c b/OvmfPkg/IoMmuDxe/IoMmuDxe.c +index aab6d8b..cd03ca9 100644 +--- a/OvmfPkg/IoMmuDxe/IoMmuDxe.c ++++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.c +@@ -10,6 +10,8 @@ + **/ + + #include "CcIoMmu.h" ++#include ++#include "CsvIoMmu.h" + + EFI_STATUS + EFIAPI +@@ -21,6 +23,14 @@ IoMmuDxeEntryPoint ( + EFI_STATUS Status; + EFI_HANDLE Handle; + ++ if (CsvIsEnabled ()) { ++ Status = CsvInstallIoMmuProtocol (); ++ if (Status != EFI_SUCCESS) { ++ DEBUG((EFI_D_ERROR, "fail to install CSV IOMMU\n")); ++ } ++ return Status; ++ } ++ + // + // When SEV or TDX is enabled, install IoMmu protocol otherwise install the + // placeholder protocol so that other dependent module can run. +diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf +index d08f7e5..d16e940 100644 +--- a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf +@@ -22,6 +22,8 @@ + CcIoMmu.h + IoMmuDxe.c + IoMmuBuffer.c ++ CsvIoMmu.c ++ CsvIoMmu.h + + [Packages] + MdePkg/MdePkg.dec +@@ -38,6 +40,7 @@ + SynchronizationLib + UefiBootServicesTableLib + UefiDriverEntryPoint ++ CsvLib + + [Pcd] + gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr +@@ -45,6 +48,7 @@ + [Protocols] + gEdkiiIoMmuProtocolGuid ## SOMETIME_PRODUCES + gIoMmuAbsentProtocolGuid ## SOMETIME_PRODUCES ++ gCsvSharedMemoryProtocolGuid + + [Depex] +- TRUE ++ gCsvSharedMemoryProtocolGuid +diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c +new file mode 100644 +index 0000000..5ab8331 +--- /dev/null ++++ b/OvmfPkg/PlatformPei/Csv.c +@@ -0,0 +1,82 @@ ++/** @file ++ ++ CSV initialization in PEI ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "Platform.h" ++ ++VOID ++CsvInitializeMemInfo ( ++ IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob ++ ) ++{ ++ UINT64 LowerMemorySize; ++ UINT64 UpperMemorySize; ++ ++ if (!CsvIsEnabled ()) { ++ return ; ++ } ++ ++ LowerMemorySize = PlatformInfoHob->LowMemory; ++ UpperMemorySize = PlatformGetSystemMemorySizeAbove4gb (); ++ ++ CsvUpdateMapLowerMemory ( ++ 0, ++ LowerMemorySize >> EFI_PAGE_SHIFT ++ ); ++ ++ if (UpperMemorySize > 0) { ++ CsvUpdateMapUpperMemory ( ++ BASE_4GB, ++ UpperMemorySize >> EFI_PAGE_SHIFT ++ ); ++ } ++ ++ BuildMemoryAllocationHob ( ++ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallBase), ++ (UINT64)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallSize), ++ EfiReservedMemoryType ++ ); ++} ++ ++VOID ++CsvInitializeGhcb ( ++ VOID ++ ) ++{ ++ RETURN_STATUS EncryptStatus; ++ ++ if (!CsvIsEnabled ()) { ++ return ; ++ } ++ ++ // ++ // Encrypt the SecGhcb as it's not a Ghcb any more ++ // ++ EncryptStatus = MemEncryptSevSetPageEncMask( ++ 0, ++ PcdGet32 (PcdOvmfSecGhcbBase), ++ 1 ++ ); ++ ASSERT_RETURN_ERROR (EncryptStatus); ++} +-- +2.31.1 + diff --git a/0009-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch b/0009-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch new file mode 100644 index 0000000000000000000000000000000000000000..d429bef147e6b9d365450544a5aa2d6c920e10ed --- /dev/null +++ b/0009-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch @@ -0,0 +1,153 @@ +From 9a5c1e7bc14e66cf58fd0fda4afda25996f2e322 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Thu, 16 May 2024 17:29:08 +0800 +Subject: [PATCH 09/19] anolis: OvmfPkg: Reserve a CPUID table page for CSV + guest + +Reserve a page for CPUID table which will be initialized by firmware. +In future, A CSV guest should get CPUID value from a CPUID table +which has been validated by firmware rather than requesting them from +hypervisor via a VMGEXIT. +--- + OvmfPkg/AmdSev/AmdSevX64.fdf | 5 ++++- + OvmfPkg/OvmfPkg.dec | 4 ++++ + OvmfPkg/OvmfPkgX64.fdf | 5 ++++- + OvmfPkg/PlatformPei/Csv.c | 6 ++++++ + OvmfPkg/PlatformPei/PlatformPei.inf | 2 ++ + OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 15 +++++++++++++++ + OvmfPkg/ResetVector/ResetVector.inf | 2 ++ + OvmfPkg/ResetVector/ResetVector.nasmb | 2 ++ + 8 files changed, 39 insertions(+), 2 deletions(-) + +diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf +index 23fd529..a704cae 100644 +--- a/OvmfPkg/AmdSev/AmdSevX64.fdf ++++ b/OvmfPkg/AmdSev/AmdSevX64.fdf +@@ -77,7 +77,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdQe + 0x010000|0x002000 + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize + +-0x012000|0x00E000 ++0x012000|0x001000 ++gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize ++ ++0x013000|0x00D000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + + 0x020000|0x0E0000 +diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec +index e468d6c..b3fd44d 100644 +--- a/OvmfPkg/OvmfPkg.dec ++++ b/OvmfPkg/OvmfPkg.dec +@@ -347,6 +347,10 @@ + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|0|UINT32|0x70 + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize|0|UINT32|0x71 + ++ ## the base address of the cpuid table page used by CSV. ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|0|UINT32|0x72 ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize|0|UINT32|0x73 ++ + [PcdsDynamic, PcdsDynamicEx] + gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 +diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf +index 0c58f75..6c8c8cc 100644 +--- a/OvmfPkg/OvmfPkgX64.fdf ++++ b/OvmfPkg/OvmfPkgX64.fdf +@@ -97,7 +97,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp + 0x00F000|0x002000 + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize + +-0x011000|0x00F000 ++0x011000|0x001000 ++gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize ++ ++0x012000|0x00E000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + + 0x020000|0x0E0000 +diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c +index 5ab8331..a52112d 100644 +--- a/OvmfPkg/PlatformPei/Csv.c ++++ b/OvmfPkg/PlatformPei/Csv.c +@@ -57,6 +57,12 @@ CsvInitializeMemInfo ( + (UINT64)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallSize), + EfiReservedMemoryType + ); ++ ++ BuildMemoryAllocationHob ( ++ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdOvmfCsvCpuidBase), ++ (UINT64)(UINTN) FixedPcdGet32 (PcdOvmfCsvCpuidSize), ++ EfiReservedMemoryType ++ ); + } + + VOID +diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf +index 66dfdd4..5fb0882 100644 +--- a/OvmfPkg/PlatformPei/PlatformPei.inf ++++ b/OvmfPkg/PlatformPei/PlatformPei.inf +@@ -135,6 +135,8 @@ + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize + + [FeaturePcd] + gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire +diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm +index 49a84a5..dd02a41 100644 +--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm ++++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm +@@ -63,6 +63,21 @@ csvSecureCallBase: + DB 0xAB, 0x21, 0x6B, 0x27, 0x5D, 0x55, 0x56, 0xA5 + csvSecureCallEnd: + ++; ++; CSV cpuid table ++; ++; Provide cpuid table page when boot up for CSV guest ++; ++; GUID : 1b4c70e6-07e6-4e4e-8f28-0eaf871a0752 ++; ++csvCpuidTableBase: ++ DD CSV_CPUID_TABLE_SIZE ++ DD CSV_CPUID_TABLE_BASE ++ DW csvCpuidTableEnd - csvCpuidTableBase ++ DB 0xE6, 0x70, 0x4C, 0x1B, 0xE6, 0x07, 0x4E, 0x4E ++ DB 0x8F, 0x28, 0x0E, 0xAF, 0x87, 0x1A, 0x07, 0x52 ++csvCpuidTableEnd: ++ + ; + ; TDX Metadata offset block + ; +diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf +index e4adedb..5dfba88 100644 +--- a/OvmfPkg/ResetVector/ResetVector.inf ++++ b/OvmfPkg/ResetVector/ResetVector.inf +@@ -37,6 +37,8 @@ + gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase +diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb +index 50325dd..d5ed1e1 100644 +--- a/OvmfPkg/ResetVector/ResetVector.nasmb ++++ b/OvmfPkg/ResetVector/ResetVector.nasmb +@@ -138,6 +138,8 @@ + + %define CSV_DEFAULT_SECURE_CALL_BASE FixedPcdGet32 (PcdCsvDefaultSecureCallBase) + %define CSV_DEFAULT_SECURE_CALL_SIZE FixedPcdGet32 (PcdCsvDefaultSecureCallSize) ++ %define CSV_CPUID_TABLE_BASE FixedPcdGet32 (PcdOvmfCsvCpuidBase) ++ %define CSV_CPUID_TABLE_SIZE FixedPcdGet32 (PcdOvmfCsvCpuidSize) + + %include "X64/IntelTdxMetadata.asm" + %include "Ia32/Flat32ToFlat64.asm" +-- +2.31.1 + diff --git a/0010-anolis-OvmfPkg-Use-classic-mmio-window-for-CSV-guest.patch b/0010-anolis-OvmfPkg-Use-classic-mmio-window-for-CSV-guest.patch new file mode 100644 index 0000000000000000000000000000000000000000..f6489f8414cb289e05ea8151e0af3798fd194e40 --- /dev/null +++ b/0010-anolis-OvmfPkg-Use-classic-mmio-window-for-CSV-guest.patch @@ -0,0 +1,68 @@ +From ed8e9e19a1a2b59f8c4c8891c7d7ab89ff952f15 Mon Sep 17 00:00:00 2001 +From: lilu +Date: Thu, 7 Sep 2023 14:44:59 +0800 +Subject: [PATCH 10/19] anolis: OvmfPkg: Use classic mmio window for CSV guest + +For CSV guest, firmware restricts gpa range. Dynamic mmio window +sets Mmio64Base exceeding firmware restriction. Use classic mmio +window for CSV guest. Classic mmio window is less than firmware +restriction under real circumstances. + +Change-Id: I006cb2f834c4d18bf31f6b179952fa0993ba6542 +Signed-off-by: Xin Jiang +--- + OvmfPkg/Library/CsvLib/CsvLib.inf | 2 +- + OvmfPkg/Library/PlatformInitLib/MemDetect.c | 4 +++- + OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf | 1 + + 3 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/OvmfPkg/Library/CsvLib/CsvLib.inf b/OvmfPkg/Library/CsvLib/CsvLib.inf +index 0575d67..a53d1a7 100644 +--- a/OvmfPkg/Library/CsvLib/CsvLib.inf ++++ b/OvmfPkg/Library/CsvLib/CsvLib.inf +@@ -21,7 +21,7 @@ + FILE_GUID = 9460ef3a-b9c3-11e9-8324-7371ac35e1e3 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 +- LIBRARY_CLASS = CsvLib|PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER ++ LIBRARY_CLASS = CsvLib|SEC PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER + + # + # The following information is for reference only and not required by the build +diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/MemDetect.c +index 01e01a7..9972f37 100644 +--- a/OvmfPkg/Library/PlatformInitLib/MemDetect.c ++++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c +@@ -40,6 +40,7 @@ Module Name: + #include + #include + #include ++#include + + #include + +@@ -722,7 +723,8 @@ PlatformDynamicMmioWindow ( + AddrSpace = LShiftU64 (1, PlatformInfoHob->PhysMemAddressWidth); + MmioSpace = LShiftU64 (1, PlatformInfoHob->PhysMemAddressWidth - 3); + +- if ((PlatformInfoHob->PcdPciMmio64Size < MmioSpace) && ++ if (!CsvIsEnabled() && ++ (PlatformInfoHob->PcdPciMmio64Size < MmioSpace) && + (PlatformInfoHob->PcdPciMmio64Base + MmioSpace < AddrSpace)) + { + DEBUG ((DEBUG_INFO, "%a: using dynamic mmio window\n", __func__)); +diff --git a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf +index 5a79d95..8fc80f4 100644 +--- a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf ++++ b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf +@@ -52,6 +52,7 @@ + PcdLib + PciLib + PeiHardwareInfoLib ++ CsvLib + + [LibraryClasses.X64] + TdxLib +-- +2.31.1 + diff --git a/0011-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch b/0011-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch new file mode 100644 index 0000000000000000000000000000000000000000..4b77fbe94c97071d44c32cf8b900909d14e1f118 --- /dev/null +++ b/0011-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch @@ -0,0 +1,329 @@ +From 53b710aae2bdbb9ee518e64b5aa797d308dfb70c Mon Sep 17 00:00:00 2001 +From: Ashish Kalra +Date: Tue, 5 Apr 2022 16:09:28 +0000 +Subject: [PATCH 11/19] OvmfPkg/BaseMemEncryptLib: Detect SEV live migration + feature. + +Add support to check if we are running inside KVM HVM and +KVM HVM supports SEV Live Migration feature. + +Cc: Jordan Justen +Cc: Ard Biesheuvel +Signed-off-by: Ashish Kalra +Change-Id: Ib947f6be92bfb3c7bd20170b8af490f9fc2d77be +--- + OvmfPkg/Include/Library/MemEncryptSevLib.h | 12 ++++ + .../DxeMemEncryptSevLibInternal.c | 49 ++++++++++++++-- + .../PeiDxeMemEncryptSevLibInternal.c | 58 +++++++++++++++++++ + .../PeiDxeMemEncryptSevLibInternal.h | 31 ++++++++++ + .../PeiMemEncryptSevLibInternal.c | 42 ++++++++++++++ + .../SecMemEncryptSevLibInternal.c | 18 ++++++ + 6 files changed, 206 insertions(+), 4 deletions(-) + create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h + +diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h +index 4fa9c0d..babec60 100644 +--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h ++++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h +@@ -83,6 +83,18 @@ MemEncryptSevIsEnabled ( + VOID + ); + ++/** ++ Returns a boolean to indicate whether SEV live migration is enabled. ++ ++ @retval TRUE SEV live migration is enabled ++ @retval FALSE SEV live migration is not enabled ++**/ ++BOOLEAN ++EFIAPI ++MemEncryptSevLiveMigrationIsEnabled ( ++ VOID ++ ); ++ + /** + This function clears memory encryption bit for the memory region specified by + BaseAddress and NumPages from the current page table context. +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c +index 4aba007..d80ebe2 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c +@@ -18,10 +18,14 @@ + #include + #include + +-STATIC UINT64 mCurrentAttr = 0; +-STATIC BOOLEAN mCurrentAttrRead = FALSE; +-STATIC UINT64 mSevEncryptionMask = 0; +-STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE; ++#include "PeiDxeMemEncryptSevLibInternal.h" ++ ++STATIC UINT64 mCurrentAttr = 0; ++STATIC BOOLEAN mCurrentAttrRead = FALSE; ++STATIC UINT64 mSevEncryptionMask = 0; ++STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE; ++STATIC BOOLEAN mSevLiveMigrationStatus = FALSE; ++STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE; + + /** + The function check if the specified Attr is set. +@@ -111,6 +115,24 @@ MemEncryptSevSnpIsEnabled ( + return ConfidentialComputingGuestHas (CCAttrAmdSevSnp); + } + ++/** ++ Figures out if we are running inside KVM HVM and ++ KVM HVM supports SEV Live Migration feature. ++**/ ++STATIC ++VOID ++EFIAPI ++InternalDetectSevLiveMigrationFeature ( ++ VOID ++ ) ++{ ++ if (KvmDetectSevLiveMigrationFeature ()) { ++ mSevLiveMigrationStatus = TRUE; ++ } ++ ++ mSevLiveMigrationStatusChecked = TRUE; ++} ++ + /** + Returns a boolean to indicate whether SEV-ES is enabled. + +@@ -141,6 +163,25 @@ MemEncryptSevIsEnabled ( + return ConfidentialComputingGuestHas (CCAttrAmdSev); + } + ++/** ++ Returns a boolean to indicate whether SEV live migration is enabled. ++ ++ @retval TRUE SEV live migration is enabled ++ @retval FALSE SEV live migration is not enabled ++**/ ++BOOLEAN ++EFIAPI ++MemEncryptSevLiveMigrationIsEnabled ( ++ VOID ++ ) ++{ ++ if (!mSevLiveMigrationStatusChecked) { ++ InternalDetectSevLiveMigrationFeature (); ++ } ++ ++ return mSevLiveMigrationStatus; ++} ++ + /** + Returns the SEV encryption mask. + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c +index 43a2a3e..30e1d8d 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c +@@ -16,6 +16,8 @@ + #include + #include + ++#include "PeiDxeMemEncryptSevLibInternal.h" ++ + /** + Locate the page range that covers the initial (pre-SMBASE-relocation) SMRAM + Save State Map. +@@ -61,3 +63,59 @@ MemEncryptSevLocateInitialSmramSaveStateMapPages ( + + return RETURN_SUCCESS; + } ++ ++/** ++ Figures out if we are running inside KVM HVM and ++ KVM HVM supports SEV Live Migration feature. ++ ++ @retval TRUE SEV live migration is supported. ++ @retval FALSE SEV live migration is not supported. ++**/ ++BOOLEAN ++EFIAPI ++KvmDetectSevLiveMigrationFeature ( ++ VOID ++ ) ++{ ++ CHAR8 Signature[13]; ++ UINT32 mKvmLeaf; ++ UINT32 RegEax; ++ UINT32 RegEbx; ++ UINT32 RegEcx; ++ UINT32 RegEdx; ++ ++ Signature[12] = '\0'; ++ for (mKvmLeaf = 0x40000000; mKvmLeaf < 0x40010000; mKvmLeaf += 0x100) { ++ AsmCpuid ( ++ mKvmLeaf, ++ NULL, ++ (UINT32 *)&Signature[0], ++ (UINT32 *)&Signature[4], ++ (UINT32 *)&Signature[8] ++ ); ++ ++ if (AsciiStrCmp (Signature, "KVMKVMKVM") == 0) { ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: KVM Detected, signature = %a\n", ++ __FUNCTION__, ++ Signature ++ )); ++ ++ RegEax = mKvmLeaf + 1; ++ RegEcx = 0; ++ AsmCpuid (mKvmLeaf + 1, &RegEax, &RegEbx, &RegEcx, &RegEdx); ++ if ((RegEax & KVM_FEATURE_MIGRATION_CONTROL) != 0) { ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: SEV Live Migration feature supported\n", ++ __FUNCTION__ ++ )); ++ ++ return TRUE; ++ } ++ } ++ } ++ ++ return FALSE; ++} +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h +new file mode 100644 +index 0000000..b0ef053 +--- /dev/null ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h +@@ -0,0 +1,31 @@ ++/** @file ++ ++ Secure Encrypted Virtualization (SEV) library helper function ++ ++ Copyright (c) 2021, AMD Incorporated. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#ifndef PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_ ++#define PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_ ++ ++#include ++ ++#define KVM_FEATURE_MIGRATION_CONTROL BIT17 ++ ++/** ++ Figures out if we are running inside KVM HVM and ++ KVM HVM supports SEV Live Migration feature. ++ ++ @retval TRUE SEV live migration is supported. ++ @retval FALSE SEV live migration is not supported. ++**/ ++BOOLEAN ++EFIAPI ++KvmDetectSevLiveMigrationFeature ( ++ VOID ++ ); ++ ++#endif // PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_ +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c +index 41d1246..307087a 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c +@@ -17,6 +17,11 @@ + #include + #include + ++#include "PeiDxeMemEncryptSevLibInternal.h" ++ ++STATIC BOOLEAN mSevLiveMigrationStatus = FALSE; ++STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE; ++ + /** + Read the workarea to determine whether SEV is enabled. If enabled, + then return the SevEsWorkArea pointer. +@@ -83,6 +88,24 @@ MemEncryptSevSnpIsEnabled ( + return Msr.Bits.SevSnpBit ? TRUE : FALSE; + } + ++/** ++ Figures out if we are running inside KVM HVM and ++ KVM HVM supports SEV Live Migration feature. ++**/ ++STATIC ++VOID ++EFIAPI ++InternalDetectSevLiveMigrationFeature ( ++ VOID ++ ) ++{ ++ if (KvmDetectSevLiveMigrationFeature ()) { ++ mSevLiveMigrationStatus = TRUE; ++ } ++ ++ mSevLiveMigrationStatusChecked = TRUE; ++} ++ + /** + Returns a boolean to indicate whether SEV-ES is enabled. + +@@ -121,6 +144,25 @@ MemEncryptSevIsEnabled ( + return Msr.Bits.SevBit ? TRUE : FALSE; + } + ++/** ++ Returns a boolean to indicate whether SEV live migration is enabled. ++ ++ @retval TRUE SEV live migration is enabled ++ @retval FALSE SEV live migration is not enabled ++**/ ++BOOLEAN ++EFIAPI ++MemEncryptSevLiveMigrationIsEnabled ( ++ VOID ++ ) ++{ ++ if (!mSevLiveMigrationStatusChecked) { ++ InternalDetectSevLiveMigrationFeature (); ++ } ++ ++ return mSevLiveMigrationStatus; ++} ++ + /** + Returns the SEV encryption mask. + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c +index 27148c7..9142ac4 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c +@@ -121,6 +121,24 @@ MemEncryptSevIsEnabled ( + return Msr.Bits.SevBit ? TRUE : FALSE; + } + ++/** ++ Returns a boolean to indicate whether SEV live migration is enabled. ++ ++ @retval TRUE SEV live migration is enabled ++ @retval FALSE SEV live migration is not enabled ++**/ ++BOOLEAN ++EFIAPI ++MemEncryptSevLiveMigrationIsEnabled ( ++ VOID ++ ) ++{ ++ // ++ // Not used in SEC phase. ++ // ++ return FALSE; ++} ++ + /** + Returns the SEV encryption mask. + +-- +2.31.1 + diff --git a/0012-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch b/0012-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch new file mode 100644 index 0000000000000000000000000000000000000000..3b8eeb191a54b981523bc7436cb7ada570e5c5c3 --- /dev/null +++ b/0012-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch @@ -0,0 +1,300 @@ +From ae6a83efa6a5271f895da93350c3687eaa2f3fe5 Mon Sep 17 00:00:00 2001 +From: Ashish Kalra +Date: Tue, 5 Apr 2022 16:23:53 +0000 +Subject: [PATCH 12/19] OvmfPkg/BaseMemEncryptLib: Hypercall API for page + encryption state change + +Add API to issue hypercall on page encryption state change. + +By default all the SEV guest memory regions are considered encrypted, +if a guest changes the encryption attribute of the page (e.g mark a +page as decrypted) then notify hypervisor. Hypervisor will need to +track the unencrypted pages. The information will be used during +guest live migration, guest page migration and guest debugging. + +This hypercall is used to notify hypervisor when the page's +encryption state changes. + +Cc: Jordan Justen +Cc: Ard Biesheuvel +Signed-off-by: Brijesh Singh +Signed-off-by: Ashish Kalra +Change-Id: I9fe2860bcc700da2e981964e7fe8d00e030d9aa5 +--- + OvmfPkg/Include/Library/MemEncryptSevLib.h | 52 +++++++++++++++ + .../DxeMemEncryptSevLib.inf | 1 + + .../Ia32/MemEncryptSevLib.c | 27 ++++++++ + .../PeiMemEncryptSevLib.inf | 1 + + .../SecMemEncryptSevLibInternal.c | 20 ++++++ + .../X64/AsmHelperStub.nasm | 33 ++++++++++ + .../X64/MemEncryptSevLib.c | 66 +++++++++++++++++++ + 7 files changed, 200 insertions(+) + create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm + +diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h +index babec60..b60496c 100644 +--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h ++++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h +@@ -240,4 +240,56 @@ MemEncryptSevSnpPreValidateSystemRam ( + IN UINTN NumPages + ); + ++/** ++ This hypercall is used to notify hypervisor when the page's encryption ++ state changes. ++ ++ @param[in] PhysicalAddress The physical address that is the start address ++ of a memory region. ++ @param[in] Pages Number of pages in memory region. ++ @param[in] IsEncrypted Encrypted or Decrypted. ++ ++ @retval RETURN_SUCCESS Hypercall returned success. ++ @retval RETURN_UNSUPPORTED Hypercall not supported. ++ @retval RETURN_NO_MAPPING Hypercall returned error. ++**/ ++RETURN_STATUS ++EFIAPI ++SetMemoryEncDecHypercall3 ( ++ IN UINTN PhysicalAddress, ++ IN UINTN Pages, ++ IN BOOLEAN IsEncrypted ++ ); ++ ++#define KVM_HC_MAP_GPA_RANGE 12 ++#define KVM_MAP_GPA_RANGE_PAGE_SZ_4K 0 ++#define KVM_MAP_GPA_RANGE_PAGE_SZ_2M BIT0 ++#define KVM_MAP_GPA_RANGE_PAGE_SZ_1G BIT1 ++#define KVM_MAP_GPA_RANGE_ENC_STATE(n) ((n) << 4) ++#define KVM_MAP_GPA_RANGE_ENCRYPTED KVM_MAP_GPA_RANGE_ENC_STATE(1) ++#define KVM_MAP_GPA_RANGE_DECRYPTED KVM_MAP_GPA_RANGE_ENC_STATE(0) ++ ++/** ++ Interface exposed by the ASM implementation of the core hypercall ++ ++ @param[in] HypercallNum KVM_HC_MAP_GPA_RANGE hypercall. ++ @param[in] PhysicalAddress The physical address that is the start address ++ of a memory region. ++ @param[in] Pages Number of pages in memory region. ++ @param[in] Attributes Bits 3:0 - preferred page size encoding, ++ 0 = 4kb, 1 = 2mb, 2 = 1gb, etc... ++ Bit 4 - plaintext = 0, encrypted = 1 ++ Bits 63:5 - reserved (must be zero) ++ ++ @retval Hypercall returned status. ++**/ ++UINTN ++EFIAPI ++SetMemoryEncDecHypercall3AsmStub ( ++ IN UINTN HypercallNum, ++ IN UINTN PhysicalAddress, ++ IN UINTN Pages, ++ IN UINTN Attributes ++ ); ++ + #endif // _MEM_ENCRYPT_SEV_LIB_H_ +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +index 3a1d308..4d32fae 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +@@ -40,6 +40,7 @@ + X64/SnpPageStateChangeInternal.c + X64/VirtualMemory.c + X64/VirtualMemory.h ++ X64/AsmHelperStub.nasm + + [Sources.IA32] + Ia32/MemEncryptSevLib.c +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c +index f92299f..c1c10a6 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c +@@ -153,3 +153,30 @@ MemEncryptSevSnpPreValidateSystemRam ( + { + ASSERT (FALSE); + } ++ ++/** ++ This hyercall is used to notify hypervisor when the page's encryption ++ state changes. ++ ++ @param[in] PhysicalAddress The physical address that is the start address ++ of a memory region. ++ @param[in] Pages Number of Pages in the memory region. ++ @param[in] IsEncrypted Encrypted or Decrypted. ++ ++ @retval RETURN_SUCCESS Hypercall returned success. ++ @retval RETURN_UNSUPPORTED Hypercall not supported. ++ @retval RETURN_NO_MAPPING Hypercall returned error. ++**/ ++RETURN_STATUS ++EFIAPI ++SetMemoryEncDecHypercall3 ( ++ IN UINTN PhysicalAddress, ++ IN UINTN Pages, ++ IN BOOLEAN IsEncrypted ++ ) ++{ ++ // ++ // Memory encryption bit is not accessible in 32-bit mode ++ // ++ return RETURN_UNSUPPORTED; ++} +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf +index 8f56783..3f11f06 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf +@@ -40,6 +40,7 @@ + X64/SnpPageStateChangeInternal.c + X64/VirtualMemory.c + X64/VirtualMemory.h ++ X64/AsmHelperStub.nasm + + [Sources.IA32] + Ia32/MemEncryptSevLib.c +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c +index 9142ac4..ffb22a0 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c +@@ -139,6 +139,26 @@ MemEncryptSevLiveMigrationIsEnabled ( + return FALSE; + } + ++/** ++ Interface exposed by the ASM implementation of the core hypercall ++ ++ @retval Hypercall returned status. ++**/ ++UINTN ++EFIAPI ++SetMemoryEncDecHypercall3AsmStub ( ++ IN UINTN HypercallNum, ++ IN UINTN PhysicalAddress, ++ IN UINTN Pages, ++ IN UINTN Attributes ++ ) ++{ ++ // ++ // Not used in SEC phase. ++ // ++ return RETURN_UNSUPPORTED; ++} ++ + /** + Returns the SEV encryption mask. + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm +new file mode 100644 +index 0000000..0ec35dd +--- /dev/null ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm +@@ -0,0 +1,33 @@ ++/** @file ++ ++ ASM helper stub to invoke hypercall ++ ++ Copyright (c) 2021, AMD Incorporated. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++DEFAULT REL ++SECTION .text ++ ++; UINTN ++; EFIAPI ++; SetMemoryEncDecHypercall3AsmStub ( ++; IN UINTN HypercallNum, ++; IN UINTN Arg1, ++; IN UINTN Arg2, ++; IN UINTN Arg3 ++; ); ++global ASM_PFX(SetMemoryEncDecHypercall3AsmStub) ++ASM_PFX(SetMemoryEncDecHypercall3AsmStub): ++ ; UEFI calling conventions require RBX to ++ ; be nonvolatile/callee-saved. ++ push rbx ++ mov rax, rcx ; Copy HypercallNumber to rax ++ mov rbx, rdx ; Copy Arg1 to the register expected by KVM ++ mov rcx, r8 ; Copy Arg2 to register expected by KVM ++ mov rdx, r9 ; Copy Arg3 to register expected by KVM ++ vmmcall ; Call VMMCALL ++ pop rbx ++ ret +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c +index e7c703b..a64ff2a 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c +@@ -142,3 +142,69 @@ MemEncryptSevClearMmioPageEncMask ( + EFI_PAGES_TO_SIZE (NumPages) + ); + } ++ ++/** ++ This hyercall is used to notify hypervisor when the page's encryption ++ state changes. ++ ++ @param[in] PhysicalAddress The physical address that is the start address ++ of a memory region. ++ @param[in] Pages Number of Pages in the memory region. ++ @param[in] IsEncrypted Encrypted or Decrypted. ++ ++ @retval RETURN_SUCCESS Hypercall returned success. ++ @retval RETURN_UNSUPPORTED Hypercall not supported. ++ @retval RETURN_NO_MAPPING Hypercall returned error. ++**/ ++RETURN_STATUS ++EFIAPI ++SetMemoryEncDecHypercall3 ( ++ IN UINTN PhysicalAddress, ++ IN UINTN Pages, ++ IN BOOLEAN IsEncrypted ++ ) ++{ ++ RETURN_STATUS Ret; ++ UINTN Error; ++ UINTN EncryptState; ++ ++ Ret = RETURN_UNSUPPORTED; ++ ++ if (MemEncryptSevLiveMigrationIsEnabled ()) { ++ Ret = RETURN_SUCCESS; ++ // ++ // The encryption bit is set/clear on the smallest page size, hence ++ // use the 4k page size in MAP_GPA_RANGE hypercall below. ++ // ++ // Also, when the GCD map is being walked and the c-bit being cleared ++ // from MMIO and NonExistent memory spaces, the physical address ++ // range being passed may not be page-aligned and adding an assert ++ // here prevents booting. Hence, rounding it down when calling ++ // SetMemoryEncDecHypercall3AsmStub below. ++ // ++ ++ EncryptState = IsEncrypted ? KVM_MAP_GPA_RANGE_ENCRYPTED : ++ KVM_MAP_GPA_RANGE_DECRYPTED; ++ ++ Error = SetMemoryEncDecHypercall3AsmStub ( ++ KVM_HC_MAP_GPA_RANGE, ++ PhysicalAddress & ~EFI_PAGE_MASK, ++ Pages, ++ KVM_MAP_GPA_RANGE_PAGE_SZ_4K | EncryptState ++ ); ++ ++ if (Error != 0) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "SetMemoryEncDecHypercall3 failed, Phys = %x, Pages = %d, Err = %Ld\n", ++ PhysicalAddress, ++ Pages, ++ (INT64)Error ++ )); ++ ++ Ret = RETURN_NO_MAPPING; ++ } ++ } ++ ++ return Ret; ++} +-- +2.31.1 + diff --git a/0013-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch b/0013-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch new file mode 100644 index 0000000000000000000000000000000000000000..d835ed4d33afef892a560c9586f5e63bf4868534 --- /dev/null +++ b/0013-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch @@ -0,0 +1,83 @@ +From caffd871bee56196b09c3125ea86498fe2087d49 Mon Sep 17 00:00:00 2001 +From: Ashish Kalra +Date: Tue, 5 Apr 2022 16:26:02 +0000 +Subject: [PATCH 13/19] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state + change hypercall + +Invoke the hypercall API to notify hypervisor when the page's +encryption state changes. + +Cc: Jordan Justen +Cc: Ard Biesheuvel +Signed-off-by: Brijesh Singh +Signed-off-by: Ashish Kalra +Change-Id: I987f2df9cd7d300825d9e70c14760a2ab0fb9959 +--- + .../X64/PeiDxeVirtualMemory.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +index a49cf12..42e3b03 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +@@ -727,6 +727,7 @@ SetMemoryEncDec ( + UINT64 PgTableMask; + UINT64 AddressEncMask; + BOOLEAN IsWpEnabled; ++ BOOLEAN CBitChanged; + UINTN OrigLength; + RETURN_STATUS Status; + PHYSICAL_ADDRESS PageAddress; +@@ -800,6 +801,7 @@ SetMemoryEncDec ( + // Save the specified length and physical address (we need it later). + // + OrigLength = Length; ++ CBitChanged = FALSE; + OrigPhysicalAddress = PhysicalAddress; + + while (Length != 0) { +@@ -860,6 +862,7 @@ SetMemoryEncDec ( + )); + PhysicalAddress += BIT30; + Length -= BIT30; ++ CBitChanged = TRUE; + } else { + // + // We must split the page +@@ -915,6 +918,7 @@ SetMemoryEncDec ( + SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode); + PhysicalAddress += BIT21; + Length -= BIT21; ++ CBitChanged = TRUE; + } else { + // + // We must split up this page into 4K pages +@@ -958,6 +962,7 @@ SetMemoryEncDec ( + SetOrClearCBit (&PageTableEntry->Uint64, Mode); + PhysicalAddress += EFI_PAGE_SIZE; + Length -= EFI_PAGE_SIZE; ++ CBitChanged = TRUE; + } + } + } +@@ -990,6 +995,17 @@ SetMemoryEncDec ( + ); + } + ++ // ++ // Notify Hypervisor on C-bit status ++ // ++ if (CBitChanged) { ++ Status = SetMemoryEncDecHypercall3 ( ++ OrigPhysicalAddress, ++ EFI_SIZE_TO_PAGES (OrigLength), ++ (Mode == SetCBit) ? TRUE : FALSE ++ ); ++ } ++ + Done: + // + // Restore page table write protection, if any. +-- +2.31.1 + diff --git a/0014-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch b/0014-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch new file mode 100644 index 0000000000000000000000000000000000000000..0e964cab76f20aa889dbaec42e7478f1695ca325 --- /dev/null +++ b/0014-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch @@ -0,0 +1,46 @@ +From 2a2d803406cdad2b704e6ab6b769adb5ac055051 Mon Sep 17 00:00:00 2001 +From: Ashish Kalra +Date: Tue, 5 Apr 2022 16:27:26 +0000 +Subject: [PATCH 14/19] OvmfPkg/VmgExitLib: Encryption state change hypercall + support in VC handler + +Make the #VC handler aware of the page encryption state +change hypercall by adding support to check KVM_HC_MAP_GPA_RANGE +hypercall and add the additional register values used by +hypercall in the GHCB. + +Cc: Jordan Justen +Cc: Ard Biesheuvel +Signed-off-by: Ashish Kalra +Change-Id: I0f0da3d441c1a3fd5301a127b3e710a1fbd59087 +--- + OvmfPkg/Library/CcExitLib/CcExitVcHandler.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c +index 0fc30f7..5c9a908 100644 +--- a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c ++++ b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c +@@ -677,6 +677,19 @@ VmmCallExit ( + Ghcb->SaveArea.Cpl = (UINT8)(Regs->Cs & 0x3); + CcExitVmgSetOffsetValid (Ghcb, GhcbCpl); + ++ if (Regs->Rax == KVM_HC_MAP_GPA_RANGE) { ++ // ++ // KVM_HC_MAP_GPA_RANGE hypercall requires these ++ // extra registers. ++ // ++ Ghcb->SaveArea.Rbx = Regs->Rbx; ++ CcExitVmgSetOffsetValid (Ghcb, GhcbRbx); ++ Ghcb->SaveArea.Rcx = Regs->Rcx; ++ CcExitVmgSetOffsetValid (Ghcb, GhcbRcx); ++ Ghcb->SaveArea.Rdx = Regs->Rdx; ++ CcExitVmgSetOffsetValid (Ghcb, GhcbRdx); ++ } ++ + Status = CcExitVmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0); + if (Status != 0) { + return Status; +-- +2.31.1 + diff --git a/0015-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch b/0015-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch new file mode 100644 index 0000000000000000000000000000000000000000..02bbcd4d8c1ba1bf3b79ef22961c5dae5e2367a9 --- /dev/null +++ b/0015-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch @@ -0,0 +1,43 @@ +From d51c45863a3b4d862534c30aa0fac320da84b8ef Mon Sep 17 00:00:00 2001 +From: Ashish Kalra +Date: Tue, 5 Apr 2022 16:30:54 +0000 +Subject: [PATCH 15/19] OvmfPkg/PlatformPei: Mark SEC GHCB page as unencrypted + via hypercall + +Mark the SEC GHCB page (that is mapped as unencrypted in +ResetVector code) in the hypervisor's guest page encryption +state tracking. + +Cc: Jordan Justen +Cc: Ard Biesheuvel +Signed-off-by: Ashish Kalra +Change-Id: I007edc82b63a530511c62ac72afa412ae9dbad02 +--- + OvmfPkg/PlatformPei/AmdSev.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c +index e6b602d..553e841 100644 +--- a/OvmfPkg/PlatformPei/AmdSev.c ++++ b/OvmfPkg/PlatformPei/AmdSev.c +@@ -229,6 +229,17 @@ AmdSevEsInitialize ( + Status = PcdSetBoolS (PcdSevEsIsEnabled, TRUE); + ASSERT_RETURN_ERROR (Status); + ++ // ++ // The SEC Ghcb setup during reset-vector needs to be marked as ++ // decrypted in the hypervisor's guest page encryption state ++ // tracking. ++ // ++ SetMemoryEncDecHypercall3 ( ++ FixedPcdGet32 (PcdOvmfSecGhcbBase), ++ EFI_SIZE_TO_PAGES (FixedPcdGet32 (PcdOvmfSecGhcbSize)), ++ FALSE ++ ); ++ + // + // Allocate GHCB and per-CPU variable pages. + // Since the pages must survive across the UEFI to OS transition +-- +2.31.1 + diff --git a/0016-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch b/0016-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch new file mode 100644 index 0000000000000000000000000000000000000000..7bd6bd428be5432a321fce27deb36ec077abec33 --- /dev/null +++ b/0016-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch @@ -0,0 +1,193 @@ +From e390ce48daa1df1cf9d8fdc9f6f5bb7e31e36470 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Thu, 16 May 2024 17:37:03 +0800 +Subject: [PATCH 16/19] OvmfPkg/AmdSevDxe: Add support for SEV live migration. + +Check for SEV live migration feature support, if detected +setup a new UEFI enviroment variable to indicate OVMF +support for SEV live migration. + +This environment variable is created by UEFI but consumed +by the (guest) linux kernel. This is actually part of a +3-way negotiation of the live migration feature between +hypervisor, guest OVMF and guest kernel. Host indicates +support for live migration, which is detected by OVMF +and correspondingly OVMF sets this SetLiveMigrationEnabled +UEFI variable, which is read by the guest kernel and it +indicates to the guest kernel that both host and OVMF +support and have enabled the live migration feature. + +The new runtime UEFI environment variable is set via the +notification function registered for the +EFI_END_OF_DXE_EVENT_GROUP_GUID event in AmdSevDxe driver. + +AmdSevDxe module is an apriori driver so it gets loaded between PEI +and DXE phases and the SetVariable call will fail at the driver's +entry point as the Variable DXE module is still not loaded yet. +So we need to wait for an event notification which is signaled +after the Variable DXE module is loaded, hence, using the +EndOfDxe event notification to make this call. +--- + OvmfPkg/AmdSevDxe/AmdSevDxe.c | 96 +++++++++++++++++++++++++++++++++ + OvmfPkg/AmdSevDxe/AmdSevDxe.inf | 4 ++ + OvmfPkg/OvmfPkg.dec | 1 + + 3 files changed, 101 insertions(+) + +diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c +index db3675a..c2271fa 100644 +--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c ++++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c +@@ -15,10 +15,13 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -191,6 +194,39 @@ STATIC EDKII_MEMORY_ACCEPT_PROTOCOL mMemoryAcceptProtocol = { + AmdSevMemoryAccept + }; + ++STATIC ++VOID ++EFIAPI ++AmdSevDxeOnEndOfDxe ( ++ IN EFI_EVENT Event, ++ IN VOID *EventToSignal ++ ) ++{ ++ EFI_STATUS Status; ++ BOOLEAN SevLiveMigrationEnabled; ++ ++ SevLiveMigrationEnabled = MemEncryptSevLiveMigrationIsEnabled (); ++ ++ if (SevLiveMigrationEnabled) { ++ Status = gRT->SetVariable ( ++ L"SevLiveMigrationEnabled", ++ &gAmdSevMemEncryptGuid, ++ EFI_VARIABLE_NON_VOLATILE | ++ EFI_VARIABLE_BOOTSERVICE_ACCESS | ++ EFI_VARIABLE_RUNTIME_ACCESS, ++ sizeof SevLiveMigrationEnabled, ++ &SevLiveMigrationEnabled ++ ); ++ ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: Setting SevLiveMigrationEnabled variable, status = %lx\n", ++ __FUNCTION__, ++ Status ++ )); ++ } ++} ++ + EFI_STATUS + EFIAPI + AmdSevDxeEntryPoint ( +@@ -202,6 +238,7 @@ AmdSevDxeEntryPoint ( + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *AllDescMap; + UINTN NumEntries; + UINTN Index; ++ EFI_EVENT Event; + CONFIDENTIAL_COMPUTING_SNP_BLOB_LOCATION *SnpBootDxeTable; + + // +@@ -361,5 +398,64 @@ AmdSevDxeEntryPoint ( + ); + } + ++ // ++ // AmdSevDxe module is an apriori driver so it gets loaded between PEI ++ // and DXE phases and the SetVariable call will fail at the driver's ++ // entry point as the Variable DXE module is still not loaded yet. ++ // So we need to wait for an event notification which is signaled ++ // after the Variable DXE module is loaded, hence, using the ++ // EndOfDxe event notification to make this call. ++ // ++ // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event. ++ // The notification function sets the runtime variable indicating OVMF ++ // support for SEV live migration. ++ // ++ Status = gBS->CreateEventEx ( ++ EVT_NOTIFY_SIGNAL, ++ TPL_CALLBACK, ++ AmdSevDxeOnEndOfDxe, ++ NULL, ++ &gEfiEndOfDxeEventGroupGuid, ++ &Event ++ ); ++ ++ if (EFI_ERROR (Status)) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: CreateEventEx(): %r\n", ++ __FUNCTION__, ++ Status ++ )); ++ } ++// ++// AmdSevDxe module is an apriori driver so it gets loaded between PEI ++// and DXE phases and the SetVariable call will fail at the driver's ++// entry point as the Variable DXE module is still not loaded yet. ++// So we need to wait for an event notification which is signaled ++// after the Variable DXE module is loaded, hence, using the ++// EndOfDxe event notification to make this call. ++// ++// Register EFI_END_OF_DXE_EVENT_GROUP_GUID event. ++// The notification function sets the runtime variable indicating OVMF ++// support for SEV live migration. ++// ++Status = gBS->CreateEventEx ( ++ EVT_NOTIFY_SIGNAL, ++ TPL_CALLBACK, ++ AmdSevDxeOnEndOfDxe, ++ NULL, ++ &gEfiEndOfDxeEventGroupGuid, ++ &Event ++ ); ++ ++if (EFI_ERROR (Status)) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: CreateEventEx(): %r\n", ++ __FUNCTION__, ++ Status ++ )); ++} ++ + return EFI_SUCCESS; + } +diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.inf b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf +index e7c7d52..dd1da52 100644 +--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.inf ++++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf +@@ -57,3 +57,7 @@ + + [Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId ++ ++[Guids] ++ gAmdSevMemEncryptGuid ++ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event +diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec +index b3fd44d..3be7a42 100644 +--- a/OvmfPkg/OvmfPkg.dec ++++ b/OvmfPkg/OvmfPkg.dec +@@ -171,6 +171,7 @@ + gUefiOvmfPkgTdxAcpiHobGuid = {0x6a0c5870, 0xd4ed, 0x44f4, {0xa1, 0x35, 0xdd, 0x23, 0x8b, 0x6f, 0x0c, 0x8d}} + gEfiNonCcFvGuid = {0xae047c6d, 0xbce9, 0x426c, {0xae, 0x03, 0xa6, 0x8e, 0x3b, 0x8a, 0x04, 0x88}} + gOvmfVariableGuid = {0x50bea1e5, 0xa2c5, 0x46e9, {0x9b, 0x3a, 0x59, 0x59, 0x65, 0x16, 0xb0, 0x0a}} ++ gAmdSevMemEncryptGuid = {0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}} + + [Ppis] + # PPI whose presence in the PPI database signals that the TPM base address +-- +2.31.1 + diff --git a/0017-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch b/0017-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch new file mode 100644 index 0000000000000000000000000000000000000000..f6979b08897d82c69427d1c54bc011663e7d0e06 --- /dev/null +++ b/0017-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch @@ -0,0 +1,35 @@ +From 066330bf62b9f50635bf0dc7b30c885dfce38a43 Mon Sep 17 00:00:00 2001 +From: hanliyang +Date: Mon, 17 Jan 2022 01:19:21 -0500 +Subject: [PATCH 17/19] anolis: OvmfPkg/BaseMemcryptSevLib: Correct the + calculation of page range that notified to hypervisor + +Correct the calculation of page range that notified to hypervisor. + +Change-Id: Ie2ac4a4e894095ea9ae3b1d44afed04681b9d491 +--- + .../Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +index 42e3b03..69ada87 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +@@ -999,9 +999,13 @@ SetMemoryEncDec ( + // Notify Hypervisor on C-bit status + // + if (CBitChanged) { ++ UINTN StartPfn = OrigPhysicalAddress >> EFI_PAGE_SHIFT; ++ UINTN EndPfn = (OrigPhysicalAddress + OrigLength + ++ ((1 << EFI_PAGE_SHIFT) - 1)) >> EFI_PAGE_SHIFT; ++ + Status = SetMemoryEncDecHypercall3 ( + OrigPhysicalAddress, +- EFI_SIZE_TO_PAGES (OrigLength), ++ (EndPfn - StartPfn), + (Mode == SetCBit) ? TRUE : FALSE + ); + } +-- +2.31.1 + diff --git a/0018-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch b/0018-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch new file mode 100644 index 0000000000000000000000000000000000000000..6decf48ef2f848af64097bbfab48dd2155161944 --- /dev/null +++ b/0018-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch @@ -0,0 +1,36 @@ +From f6088e094de52e8d4ef7fa3811ada1838dea486d Mon Sep 17 00:00:00 2001 +From: hanliyang +Date: Sun, 19 Jun 2022 18:12:35 +0800 +Subject: [PATCH 18/19] anolis: OvmfPkg/BaseMemEncryptLib: Return SUCCESS if + not support SEV live migration + +Add this change to avoid trigger 'ASSERT_EFI_ERROR (Status = Unsupported)' +when QEMU doesn't support SEV live migration. + +Change-Id: I48066d6cf1b4357c984496bcb6450be4d35b7e16 +--- + OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c +index a64ff2a..7b29582 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c +@@ -168,10 +168,12 @@ SetMemoryEncDecHypercall3 ( + UINTN Error; + UINTN EncryptState; + +- Ret = RETURN_UNSUPPORTED; ++ // ++ // Return success if not support migration. ++ // ++ Ret = RETURN_SUCCESS; + + if (MemEncryptSevLiveMigrationIsEnabled ()) { +- Ret = RETURN_SUCCESS; + // + // The encryption bit is set/clear on the smallest page size, hence + // use the 4k page size in MAP_GPA_RANGE hypercall below. +-- +2.31.1 + diff --git a/0019-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch b/0019-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch new file mode 100644 index 0000000000000000000000000000000000000000..531bbdebfa8b180b673190b4d9e23727a2b5c62c --- /dev/null +++ b/0019-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch @@ -0,0 +1,202 @@ +From 09dbce68f9fdb6a3052d97d7f82048d31fb6cf26 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Thu, 16 May 2024 17:38:26 +0800 +Subject: [PATCH 19/19] anolis: OvmfPkg/BaseMemEncryptLib: Save memory encrypt + status in reserved memory + +The MMIO routine of VC handler will get memory encrypt status to +validate MMIO address. MemEncryptSevGetEncryptionMask() will enable +interrupt while interrupt must be disabled during VC. + +During DXE stage, VC routine as below: +CcExitHandleVc->MemEncryptSevGetAddressRangeState-> +MemEncryptSevGetEncryptionMask->PcdGet64(PcdPteMemoryEncryptionAddressOrMask) + +Unfortunately, PcdGet64() will enable interrupt in VC context. +--- + OvmfPkg/AmdSev/AmdSevX64.fdf | 5 ++++- + OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h | 20 +++++++++++++++++++ + OvmfPkg/IntelTdx/IntelTdxX64.fdf | 5 ++++- + .../DxeMemEncryptSevLib.inf | 4 ++++ + .../DxeMemEncryptSevLibInternal.c | 9 ++------- + OvmfPkg/OvmfPkg.dec | 4 ++++ + OvmfPkg/OvmfPkgX64.fdf | 5 ++++- + OvmfPkg/PlatformPei/AmdSev.c | 2 ++ + OvmfPkg/PlatformPei/Csv.c | 6 ++++++ + OvmfPkg/PlatformPei/PlatformPei.inf | 2 ++ + 10 files changed, 52 insertions(+), 10 deletions(-) + create mode 100644 OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h + +diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf +index a704cae..86b9bc1 100644 +--- a/OvmfPkg/AmdSev/AmdSevX64.fdf ++++ b/OvmfPkg/AmdSev/AmdSevX64.fdf +@@ -80,7 +80,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGui + 0x012000|0x001000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize + +-0x013000|0x00D000 ++0x013000|0x001000 ++gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase|gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize ++ ++0x014000|0x00C000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + + 0x020000|0x0E0000 +diff --git a/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h b/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h +new file mode 100644 +index 0000000..62d22e7 +--- /dev/null ++++ b/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h +@@ -0,0 +1,20 @@ ++/** @file ++ ++ AMD Memory Encryption GUID, define a new GUID for defining ++ new UEFI environment variables assocaiated with SEV Memory Encryption. ++ ++ Copyright (c) 2021, AMD Inc. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#ifndef __AMD_SEV_MEMENCRYPT_LIB_H__ ++#define __AMD_SEV_MEMENCRYPT_LIB_H__ ++ ++#define AMD_SEV_MEMENCRYPT_GUID \ ++{0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}} ++ ++extern EFI_GUID gAmdSevMemEncryptGuid; ++ ++#endif +diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.fdf b/OvmfPkg/IntelTdx/IntelTdxX64.fdf +index c3e759f..d31a93d 100644 +--- a/OvmfPkg/IntelTdx/IntelTdxX64.fdf ++++ b/OvmfPkg/IntelTdx/IntelTdxX64.fdf +@@ -100,7 +100,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGui + 0x011000|0x001000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize + +-0x012000|0x00E000 ++0x012000|0x001000 ++gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase|gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize ++ ++0x013000|0x00D000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + + 0x100000|0x700000 +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +index 4d32fae..6f2f69d 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +@@ -61,3 +61,7 @@ + [Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask + gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr ++ ++[FixedPcd] ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c +index d80ebe2..a9d4323 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c +@@ -22,8 +22,6 @@ + + STATIC UINT64 mCurrentAttr = 0; + STATIC BOOLEAN mCurrentAttrRead = FALSE; +-STATIC UINT64 mSevEncryptionMask = 0; +-STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE; + STATIC BOOLEAN mSevLiveMigrationStatus = FALSE; + STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE; + +@@ -193,10 +191,7 @@ MemEncryptSevGetEncryptionMask ( + VOID + ) + { +- if (!mSevEncryptionMaskSaved) { +- mSevEncryptionMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask); +- mSevEncryptionMaskSaved = TRUE; +- } ++ UINT64 *MemEncryptStatus = (UINT64 *)(UINT64)FixedPcdGet32 (PcdMemEncrpytStatusBase); + +- return mSevEncryptionMask; ++ return *MemEncryptStatus; + } +diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec +index 3be7a42..374cab9 100644 +--- a/OvmfPkg/OvmfPkg.dec ++++ b/OvmfPkg/OvmfPkg.dec +@@ -352,6 +352,10 @@ + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|0|UINT32|0x72 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize|0|UINT32|0x73 + ++ ## the base address of memory encryption status. ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase|0|UINT32|0x74 ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize|0|UINT32|0x75 ++ + [PcdsDynamic, PcdsDynamicEx] + gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 +diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf +index 6c8c8cc..9f12926 100644 +--- a/OvmfPkg/OvmfPkgX64.fdf ++++ b/OvmfPkg/OvmfPkgX64.fdf +@@ -100,7 +100,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGui + 0x011000|0x001000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize + +-0x012000|0x00E000 ++0x012000|0x001000 ++gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase|gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize ++ ++0x013000|0x00D000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + + 0x020000|0x0E0000 +diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c +index 553e841..7c4ef89 100644 +--- a/OvmfPkg/PlatformPei/AmdSev.c ++++ b/OvmfPkg/PlatformPei/AmdSev.c +@@ -379,6 +379,8 @@ AmdSevInitialize ( + PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask); + ASSERT_RETURN_ERROR (PcdStatus); + ++ *(UINT64 *)(UINT64)FixedPcdGet32 (PcdMemEncrpytStatusBase) = EncryptionMask; ++ + DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask)); + + // +diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c +index a52112d..fe8c059 100644 +--- a/OvmfPkg/PlatformPei/Csv.c ++++ b/OvmfPkg/PlatformPei/Csv.c +@@ -33,6 +33,12 @@ CsvInitializeMemInfo ( + UINT64 LowerMemorySize; + UINT64 UpperMemorySize; + ++ BuildMemoryAllocationHob ( ++ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdMemEncrpytStatusBase), ++ (UINT64)(UINTN) FixedPcdGet32 (PcdMemEncrpytStatusSize), ++ EfiReservedMemoryType ++ ); ++ + if (!CsvIsEnabled ()) { + return ; + } +diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf +index 5fb0882..b28b0ed 100644 +--- a/OvmfPkg/PlatformPei/PlatformPei.inf ++++ b/OvmfPkg/PlatformPei/PlatformPei.inf +@@ -137,6 +137,8 @@ + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize + + [FeaturePcd] + gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire +-- +2.31.1 + diff --git a/edk2.spec b/edk2.spec index 3189603c8522bd647d438f561f8fde27d207f738..e574fcb2765d9e288d036bb3749ec87879943669 100644 --- a/edk2.spec +++ b/edk2.spec @@ -1,4 +1,4 @@ -%define anolis_release 1 +%define anolis_release 2 %undefine _auto_set_build_flags ExclusiveArch: x86_64 aarch64 loongarch64 @@ -60,6 +60,26 @@ Source51: 51-edk2-loongarch64-verbose.json Source80: https://gitlab.com/kraxel/edk2-build-config/-/blob/master/bin/edk2-build.py Source81: edk2-build +Patch0001: 0001-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch +Patch0002: 0002-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch +Patch0003: 0003-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch +Patch0004: 0004-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch +Patch0005: 0005-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch +Patch0006: 0006-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch +Patch0007: 0007-anolis-OvmfPkg-Add-CsvDxe-driver.patch +Patch0008: 0008-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch +Patch0009: 0009-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch +Patch0010: 0010-anolis-OvmfPkg-Use-classic-mmio-window-for-CSV-guest.patch +Patch0011: 0011-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch +Patch0012: 0012-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch +Patch0013: 0013-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch +Patch0014: 0014-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch +Patch0015: 0015-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch +Patch0016: 0016-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch +Patch0017: 0017-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch +Patch0018: 0018-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch +Patch0019: 0019-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch + BuildRequires: python3-devel BuildRequires: libuuid-devel %ifnarch loongarch64 @@ -458,6 +478,10 @@ install -m 0644 \ %changelog +* Thu May 16 2024 Kaiqiang Wang - 202402-2 +- Support Hygon CSV3 feature +- Support SEV migration + * Sun May 05 2024 Kaiqiang Wang - 202402-1 - update to 202402 - fix CVE-2023-45234