[edk2-devel] [PATCH v2] OvmfPkg/QemuFlashFvbServicesRuntimeDxe: Use physical address with SEV-ES

Lendacky, Thomas thomas.lendacky at amd.com
Sat Jan 23 13:57:44 UTC 2021


From: Tom Lendacky <thomas.lendacky at amd.com>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3183

Under SEV-ES, a write to the flash device is done using a direct VMGEXIT
to perform an MMIO write. The address provided to the MMIO write must be
the physical address of the MMIO write destitnation. During boot, OVMF
runs with an identity mapped pagetable structure so that VA == PA and the
VMGEXIT MMIO write destination is just the virtual address of the flash
area address being written.

However, when the UEFI SetVitualAddressMap() API is invoked, an identity
mapped pagetable structure may not be in place and using the virtual
address for the flash area address is no longer valid. This results in
writes to the flash not being performed successfully. This can be seen
by attempting to change the boot order under Linux. The update will
appear to be performed, based on the output of the command. But rebooting
the guest will show that the new boot order has not been set.

To remedy this, save the value of the flash base physical address before
converting the address as part of SetVirtualAddressMap(). The physical
address can then be calculated by obtaining the offset of the MMIO target
virtual address relative to the flash base virtual address and adding that
to the original flash base physical address. The resulting value produces
a successful MMIO write during runtime services.

Fixes: 437eb3f7a8db7681afe0e6064d3a8edb12abb766
Cc: Jordan Justen <jordan.l.justen at intel.com>
Cc: Laszlo Ersek <lersek at redhat.com>
Cc: Ard Biesheuvel <ardb+tianocore at kernel.org>
Signed-off-by: Tom Lendacky <thomas.lendacky at amd.com>
---
 .../QemuFlashDxe.c                            | 20 ++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
index 1b0742967f71..d303b0078b08 100644
--- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
+++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
@@ -16,11 +16,17 @@
 
 #include "QemuFlash.h"
 
+STATIC EFI_PHYSICAL_ADDRESS mSevEsFlashPhysBase;
+
 VOID
 QemuFlashConvertPointers (
   VOID
   )
 {
+  if (MemEncryptSevEsIsEnabled ()) {
+    mSevEsFlashPhysBase = (UINTN) mFlashBase;
+  }
+
   EfiConvertPointer (0x0, (VOID **) &mFlashBase);
 }
 
@@ -52,11 +58,23 @@ QemuFlashPtrWrite (
   if (MemEncryptSevEsIsEnabled ()) {
     MSR_SEV_ES_GHCB_REGISTER  Msr;
     GHCB                      *Ghcb;
+    EFI_PHYSICAL_ADDRESS      PhysAddr;
     BOOLEAN                   InterruptState;
 
     Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
     Ghcb = Msr.Ghcb;
 
+    //
+    // The MMIO write needs to be to the physical address of the flash pointer.
+    // Since this service is available as part of the EFI runtime services,
+    // account for a non-identity mapped VA after SetVitualAddressMap().
+    //
+    if (mSevEsFlashPhysBase == 0) {
+      PhysAddr = (UINTN) Ptr;
+    } else {
+      PhysAddr = mSevEsFlashPhysBase + (Ptr - mFlashBase);
+    }
+
     //
     // Writing to flash is emulated by the hypervisor through the use of write
     // protection. This won't work for an SEV-ES guest because the write won't
@@ -68,7 +86,7 @@ QemuFlashPtrWrite (
     Ghcb->SharedBuffer[0] = Value;
     Ghcb->SaveArea.SwScratch = (UINT64) (UINTN) Ghcb->SharedBuffer;
     VmgSetOffsetValid (Ghcb, GhcbSwScratch);
-    VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, (UINT64) (UINTN) Ptr, 1);
+    VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, PhysAddr, 1);
     VmgDone (Ghcb, InterruptState);
   } else {
     *Ptr = Value;
-- 
2.30.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#70703): https://edk2.groups.io/g/devel/message/70703
Mute This Topic: https://groups.io/mt/80055199/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-






More information about the edk2-devel-archive mailing list