diff options
author | Michael Roth <michael.roth@amd.com> | 2024-05-02 13:49:26 +0200 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2024-05-02 12:43:50 +0000 |
commit | f0ed194236b1fe55199ee82c014b70119ee3f227 (patch) | |
tree | bfda327ab2be6e0a0d46d5d009402aa238f47170 /OvmfPkg | |
parent | fd290ab8628478c62c32c972fc16b86b6c3372ce (diff) | |
download | edk2-f0ed194236b1fe55199ee82c014b70119ee3f227.zip edk2-f0ed194236b1fe55199ee82c014b70119ee3f227.tar.gz edk2-f0ed194236b1fe55199ee82c014b70119ee3f227.tar.bz2 |
OvmfPkg: Don't make APIC MMIO accesses with encryption bit set
For the most part, OVMF will clear the encryption bit for MMIO regions,
but there is currently one known exception during SEC when the APIC
base address is accessed via MMIO with the encryption bit set for
SEV-ES/SEV-SNP guests. In the case of SEV-SNP, this requires special
handling on the hypervisor side which may not be available in the
future[1], so make the necessary changes in the SEC-configured page
table to clear the encryption bit for 4K region containing the APIC
base address.
[1] https://lore.kernel.org/lkml/20240208002420.34mvemnzrwwsaesw@amd.com/#t
Suggested-by: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jianyong Wu <jianyong.wu@arm.com>
Cc: Anatol Belski <anbelski@linux.microsoft.com>
Signed-off-by: Michael Roth <michael.roth@amd.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'OvmfPkg')
-rw-r--r-- | OvmfPkg/AmdSev/AmdSevX64.fdf | 5 | ||||
-rw-r--r-- | OvmfPkg/Bhyve/BhyveX64.dsc | 1 | ||||
-rw-r--r-- | OvmfPkg/CloudHv/CloudHvX64.fdf | 5 | ||||
-rw-r--r-- | OvmfPkg/Microvm/MicrovmX64.fdf | 3 | ||||
-rw-r--r-- | OvmfPkg/OvmfPkg.dec | 5 | ||||
-rw-r--r-- | OvmfPkg/OvmfPkgX64.fdf | 5 | ||||
-rw-r--r-- | OvmfPkg/Sec/AmdSev.c | 58 | ||||
-rw-r--r-- | OvmfPkg/Sec/AmdSev.h | 14 | ||||
-rw-r--r-- | OvmfPkg/Sec/SecMain.c | 1 | ||||
-rw-r--r-- | OvmfPkg/Sec/SecMain.inf | 3 |
10 files changed, 97 insertions, 3 deletions
diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf index d49555c..5959451 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.fdf +++ b/OvmfPkg/AmdSev/AmdSevX64.fdf @@ -77,7 +77,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.Pcd 0x010C00|0x000400
gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableSize
-0x011000|0x00F000
+0x011000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
+0x012000|0x00E000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc index 6f305d6..7805095 100644 --- a/OvmfPkg/Bhyve/BhyveX64.dsc +++ b/OvmfPkg/Bhyve/BhyveX64.dsc @@ -174,6 +174,7 @@ PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
+ CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
diff --git a/OvmfPkg/CloudHv/CloudHvX64.fdf b/OvmfPkg/CloudHv/CloudHvX64.fdf index eae3ada..3e6688b 100644 --- a/OvmfPkg/CloudHv/CloudHvX64.fdf +++ b/OvmfPkg/CloudHv/CloudHvX64.fdf @@ -76,7 +76,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp 0x00F000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdXenPvhStartOfDayStructPtr|gUefiOvmfPkgTokenSpaceGuid.PcdXenPvhStartOfDayStructPtrSize
-0x010000|0x010000
+0x010000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
+0x011000|0x00F000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/Microvm/MicrovmX64.fdf b/OvmfPkg/Microvm/MicrovmX64.fdf index 825bf9f..055e659 100644 --- a/OvmfPkg/Microvm/MicrovmX64.fdf +++ b/OvmfPkg/Microvm/MicrovmX64.fdf @@ -62,6 +62,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvm 0x00C000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
+0x00D000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
0x010000|0x010000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 731f67b..51be9a5 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -278,6 +278,11 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|0|UINT32|0x44
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize|0|UINT32|0x45
+ ## Specify the extra page table needed to mark the APIC MMIO range as unencrypted.
+ # The value should be a multiple of 4KB for each.
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|0x0|UINT32|0x72
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize|0x0|UINT32|0x73
+
## The base address and size of the SEV Launch Secret Area provisioned
# after remote attestation. If this is set in the .fdf, the platform
# is responsible for protecting the area from DXE phase overwrites.
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index c2d3cc9..b6e8f43 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -97,7 +97,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp 0x00F000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecSvsmCaaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecSvsmCaaSize
-0x010000|0x010000
+0x010000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
+0x011000|0x00F000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/Sec/AmdSev.c b/OvmfPkg/Sec/AmdSev.c index 520b125..89fba2f 100644 --- a/OvmfPkg/Sec/AmdSev.c +++ b/OvmfPkg/Sec/AmdSev.c @@ -8,7 +8,10 @@ **/
#include <Library/BaseLib.h>
+#include <Library/CpuLib.h>
+#include <Library/CpuPageTableLib.h>
#include <Library/DebugLib.h>
+#include <Library/LocalApicLib.h>
#include <Library/MemEncryptSevLib.h>
#include <Library/BaseMemoryLib.h>
#include <Register/Amd/Ghcb.h>
@@ -301,3 +304,58 @@ SecValidateSystemRam ( MemEncryptSevSnpPreValidateSystemRam (Start, EFI_SIZE_TO_PAGES ((UINTN)(End - Start)));
}
}
+
+/**
+ Map known MMIO regions unencrypted if SEV-ES is active.
+
+ During early booting, page table entries default to having the encryption bit
+ set for SEV-ES/SEV-SNP guests. In cases where there is MMIO to an address, the
+ encryption bit should be cleared. Clear it here for any known MMIO accesses
+ during SEC, which is currently just the APIC base address.
+
+**/
+VOID
+SecMapApicBaseUnencrypted (
+ VOID
+ )
+{
+ PHYSICAL_ADDRESS Cr3;
+ UINT64 ApicAddress;
+ VOID *Buffer;
+ UINTN BufferSize;
+ IA32_MAP_ATTRIBUTE MapAttribute;
+ IA32_MAP_ATTRIBUTE MapMask;
+ RETURN_STATUS Status;
+
+ if (!SevEsIsEnabled ()) {
+ return;
+ }
+
+ ApicAddress = (UINT64)GetLocalApicBaseAddress ();
+ Buffer = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecApicPageTableBase);
+ Cr3 = AsmReadCr3 ();
+
+ MapAttribute.Uint64 = ApicAddress;
+ MapAttribute.Bits.Present = 1;
+ MapAttribute.Bits.ReadWrite = 1;
+ MapMask.Uint64 = MAX_UINT64;
+ BufferSize = SIZE_4KB;
+
+ Status = PageTableMap (
+ (UINTN *)&Cr3,
+ Paging4Level,
+ Buffer,
+ &BufferSize,
+ ApicAddress,
+ SIZE_4KB,
+ &MapAttribute,
+ &MapMask,
+ NULL
+ );
+ if (RETURN_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to map APIC MMIO region as unencrypted: %d\n", Status));
+ ASSERT (FALSE);
+ }
+
+ CpuFlushTlb ();
+}
diff --git a/OvmfPkg/Sec/AmdSev.h b/OvmfPkg/Sec/AmdSev.h index f758770..c5ab0d5 100644 --- a/OvmfPkg/Sec/AmdSev.h +++ b/OvmfPkg/Sec/AmdSev.h @@ -91,4 +91,18 @@ SevSnpIsEnabled ( VOID
);
+/**
+ Map MMIO regions unencrypted if SEV-ES is active.
+
+ During early booting, page table entries default to having the encryption bit
+ set for SEV-ES/SEV-SNP guests. In cases where there is MMIO to an address, the
+ encryption bit should be cleared. Clear it here for any known MMIO accesses
+ during SEC, which is currently just the APIC base address.
+
+**/
+VOID
+SecMapApicBaseUnencrypted (
+ VOID
+ );
+
#endif
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c index a30d4ce..60dfa61 100644 --- a/OvmfPkg/Sec/SecMain.c +++ b/OvmfPkg/Sec/SecMain.c @@ -938,6 +938,7 @@ SecCoreStartupWithStack ( // interrupts before initializing the Debug Agent and the debug timer is
// enabled.
//
+ SecMapApicBaseUnencrypted ();
InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
DisableApicTimerInterrupt ();
diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf index dca932a..88c2d3f 100644 --- a/OvmfPkg/Sec/SecMain.inf +++ b/OvmfPkg/Sec/SecMain.inf @@ -55,6 +55,7 @@ MemEncryptSevLib
CpuExceptionHandlerLib
CcProbeLib
+ CpuPageTableLib
[Ppis]
gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
@@ -83,6 +84,8 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
|