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 <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
[lersek@redhat.com: trivial coding style improvements]
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Brijesh Singh 2018-03-09 10:06:03 -06:00 committed by Laszlo Ersek
parent d5a002aba0
commit e4a1d5a7c4
5 changed files with 84 additions and 0 deletions

View File

@ -40,6 +40,7 @@
FwBlockService.c FwBlockService.c
FwBlockServiceSmm.c FwBlockServiceSmm.c
QemuFlash.c QemuFlash.c
QemuFlashSmm.c
[Packages] [Packages]
MdePkg/MdePkg.dec MdePkg/MdePkg.dec
@ -53,6 +54,7 @@
DevicePathLib DevicePathLib
DxeServicesTableLib DxeServicesTableLib
MemoryAllocationLib MemoryAllocationLib
MemEncryptSevLib
PcdLib PcdLib
SmmServicesTableLib SmmServicesTableLib
UefiBootServicesTableLib UefiBootServicesTableLib

View File

@ -244,6 +244,15 @@ QemuFlashInitialize (
ASSERT(PcdGet32 (PcdOvmfFirmwareFdSize) % mFdBlockSize == 0); ASSERT(PcdGet32 (PcdOvmfFirmwareFdSize) % mFdBlockSize == 0);
mFdBlockCount = PcdGet32 (PcdOvmfFirmwareFdSize) / mFdBlockSize; mFdBlockCount = PcdGet32 (PcdOvmfFirmwareFdSize) / mFdBlockSize;
//
// execute module specific hooks before probing the flash
//
QemuFlashBeforeProbe (
(EFI_PHYSICAL_ADDRESS)(UINTN) mFlashBase,
mFdBlockSize,
mFdBlockCount
);
if (!QemuFlashDetected ()) { if (!QemuFlashDetected ()) {
ASSERT (!FeaturePcdGet (PcdSmmSmramRequire)); ASSERT (!FeaturePcdGet (PcdSmmSmramRequire));
return EFI_WRITE_PROTECTED; return EFI_WRITE_PROTECTED;

View File

@ -88,5 +88,12 @@ QemuFlashConvertPointers (
VOID VOID
); );
VOID
QemuFlashBeforeProbe (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINTN FdBlockSize,
IN UINTN FdBlockCount
);
#endif #endif

View File

@ -26,3 +26,15 @@ QemuFlashConvertPointers (
{ {
EfiConvertPointer (0x0, (VOID **) &mFlashBase); EfiConvertPointer (0x0, (VOID **) &mFlashBase);
} }
VOID
QemuFlashBeforeProbe (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINTN FdBlockSize,
IN UINTN FdBlockCount
)
{
//
// Do nothing
//
}

View File

@ -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 <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
#include <Library/MemEncryptSevLib.h>
#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);
}