From e4a1d5a7c4e4668fe128261fdc9eb799c384f109 Mon Sep 17 00:00:00 2001 From: Brijesh Singh Date: Fri, 9 Mar 2018 10:06:03 -0600 Subject: [PATCH] OvmfPkg/QemuFlashFvbServicesRuntimeDxe: Clear C-bit when SEV is active Commit:24e4ad7 (OvmfPkg: Add AmdSevDxe driver) added a driver which runs early in DXE phase and clears the C-bit from NonExistent entry -- which is later split and accommodate the flash MMIO. When SMM is enabled, we build two sets of page tables; first page table is used when executing code in non SMM mode (SMM-less-pgtable) and second page table is used when we are executing code in SMM mode (SMM-pgtable). During boot time, AmdSevDxe driver clears the C-bit from the SMM-less-pgtable. But when SMM is enabled, Qemu Flash services are used from SMM mode. In this patch we explicitly clear the C-bit from Qemu flash MMIO range before we probe the flash. When OVMF is built with SMM_REQUIRE then call to initialize the flash services happen after the SMM-pgtable is created and processor has served the first SMI. At this time we will have access to the SMM-pgtable. Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Brijesh Singh [lersek@redhat.com: trivial coding style improvements] Reviewed-by: Laszlo Ersek --- .../FvbServicesSmm.inf | 2 + .../QemuFlash.c | 9 ++++ .../QemuFlash.h | 7 +++ .../QemuFlashDxe.c | 12 +++++ .../QemuFlashSmm.c | 54 +++++++++++++++++++ 5 files changed, 84 insertions(+) create mode 100644 OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf index ba2d3679a4..b5c79762c2 100644 --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf @@ -40,6 +40,7 @@ FwBlockService.c FwBlockServiceSmm.c QemuFlash.c + QemuFlashSmm.c [Packages] MdePkg/MdePkg.dec @@ -53,6 +54,7 @@ DevicePathLib DxeServicesTableLib MemoryAllocationLib + MemEncryptSevLib PcdLib SmmServicesTableLib UefiBootServicesTableLib diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c index 5677b5ee11..462d9c0322 100644 --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c @@ -244,6 +244,15 @@ QemuFlashInitialize ( ASSERT(PcdGet32 (PcdOvmfFirmwareFdSize) % mFdBlockSize == 0); mFdBlockCount = PcdGet32 (PcdOvmfFirmwareFdSize) / mFdBlockSize; + // + // execute module specific hooks before probing the flash + // + QemuFlashBeforeProbe ( + (EFI_PHYSICAL_ADDRESS)(UINTN) mFlashBase, + mFdBlockSize, + mFdBlockCount + ); + if (!QemuFlashDetected ()) { ASSERT (!FeaturePcdGet (PcdSmmSmramRequire)); return EFI_WRITE_PROTECTED; diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h index 8d83dca7a5..d34a8a19a0 100644 --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h @@ -88,5 +88,12 @@ QemuFlashConvertPointers ( VOID ); +VOID +QemuFlashBeforeProbe ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN FdBlockSize, + IN UINTN FdBlockCount + ); + #endif diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c index 08ece2beae..332ceafd3f 100644 --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c @@ -26,3 +26,15 @@ QemuFlashConvertPointers ( { EfiConvertPointer (0x0, (VOID **) &mFlashBase); } + +VOID +QemuFlashBeforeProbe ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN FdBlockSize, + IN UINTN FdBlockCount + ) +{ + // + // Do nothing + // +} diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c new file mode 100644 index 0000000000..8999ad8d0d --- /dev/null +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c @@ -0,0 +1,54 @@ +/** @file + Define the module hooks used while probing the QEMU flash device. + + Copyright (C) 2018, Advanced Micro Devices. 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 "QemuFlash.h" + +VOID +QemuFlashBeforeProbe ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN FdBlockSize, + IN UINTN FdBlockCount + ) +{ + EFI_STATUS Status; + + ASSERT (FeaturePcdGet (PcdSmmSmramRequire)); + + if (!MemEncryptSevIsEnabled ()) { + return; + } + + // + // When SEV is enabled, AmdSevDxe runs early in DXE phase and clears the + // C-bit from the NonExistent entry -- which is later split and accommodate + // the flash MMIO but the driver runs in non SMM context hence it cleared the + // flash ranges from non SMM page table. When SMM is enabled, the flash + // services are accessed from the SMM mode hence we explicitly clear the + // C-bit on flash ranges from SMM page table. + // + + Status = MemEncryptSevClearPageEncMask ( + 0, + BaseAddress, + EFI_SIZE_TO_PAGES (FdBlockSize * FdBlockCount), + FALSE + ); + ASSERT_EFI_ERROR (Status); +}