From: "Lendacky, Thomas" <thomas.lendacky@amd.com>
To: devel@edk2.groups.io
Cc: Brijesh Singh <brijesh.singh@amd.com>,
Jordan Justen <jordan.l.justen@intel.com>,
Laszlo Ersek <lersek@redhat.com>,
Ard Biesheuvel <ardb+tianocore@kernel.org>
Subject: [PATCH] OvmfPkg/QemuFlashFvbServicesRuntimeDxe: Use physical address with SEV-ES
Date: Fri, 22 Jan 2021 11:55:06 -0600 [thread overview]
Message-ID: <8bba19920e58813f32889dec522bbcd8de113219.1611338106.git.thomas.lendacky@amd.com> (raw)
From: Tom Lendacky <thomas.lendacky@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, update the Qemu flash services constructor to maintain a
copy of the original PA of the flash device. When performing the VMGEXIT
MMIO write, the PA can be calculated by subtracting the difference between
the current flash virtual address base and the original physical address
base. Using the resulting value in the MMIO write produces a successful
write during boot and during runtime services.
Fixes: 437eb3f7a8db7681afe0e6064d3a8edb12abb766
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h | 1 +
OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c | 2 ++
OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c | 10 +++++++++-
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h
index 219d0d6e83cf..0a91c15d0e81 100644
--- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h
+++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h
@@ -13,6 +13,7 @@
#include <Protocol/FirmwareVolumeBlock.h>
extern UINT8 *mFlashBase;
+extern UINT8 *mFlashBasePhysical;
/**
Read from QEMU Flash
diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c
index d19997032ec9..36ae63ebde31 100644
--- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c
+++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c
@@ -26,6 +26,7 @@
UINT8 *mFlashBase;
+UINT8 *mFlashBasePhysical;
STATIC UINTN mFdBlockSize = 0;
STATIC UINTN mFdBlockCount = 0;
@@ -251,6 +252,7 @@ QemuFlashInitialize (
)
{
mFlashBase = (UINT8*)(UINTN) PcdGet32 (PcdOvmfFdBaseAddress);
+ mFlashBasePhysical = mFlashBase;
mFdBlockSize = PcdGet32 (PcdOvmfFirmwareBlockSize);
ASSERT(PcdGet32 (PcdOvmfFirmwareFdSize) % mFdBlockSize == 0);
mFdBlockCount = PcdGet32 (PcdOvmfFirmwareFdSize) / mFdBlockSize;
diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
index 1b0742967f71..db247f324e3c 100644
--- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
+++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
@@ -52,11 +52,19 @@ QemuFlashPtrWrite (
if (MemEncryptSevEsIsEnabled ()) {
MSR_SEV_ES_GHCB_REGISTER Msr;
GHCB *Ghcb;
+ UINT64 PtrPa;
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().
+ //
+ PtrPa = (UINT64) (UINTN) (Ptr - (mFlashBase - mFlashBasePhysical));
+
//
// 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 +76,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, PtrPa, 1);
VmgDone (Ghcb, InterruptState);
} else {
*Ptr = Value;
--
2.30.0
next reply other threads:[~2021-01-22 17:55 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-22 17:55 Lendacky, Thomas [this message]
2021-01-22 22:29 ` [edk2-devel] [PATCH] OvmfPkg/QemuFlashFvbServicesRuntimeDxe: Use physical address with SEV-ES Laszlo Ersek
2021-01-22 22:40 ` Lendacky, Thomas
2021-01-23 0:25 ` Laszlo Ersek
2021-01-23 1:29 ` Andrew Fish
2021-01-23 2:24 ` Laszlo Ersek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8bba19920e58813f32889dec522bbcd8de113219.1611338106.git.thomas.lendacky@amd.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox