From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.120]) by mx.groups.io with SMTP id smtpd.web09.2916.1583238806345490816 for ; Tue, 03 Mar 2020 04:33:26 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=WggYkVY4; spf=pass (domain: redhat.com, ip: 207.211.31.120, mailfrom: lersek@redhat.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1583238805; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=srpW4GAOuVI66tsl3bgqZpZpgRy8aXOFiX41VL6rL6c=; b=WggYkVY4zl+I7DMVmAFGGiFecDSZo7kZNn07Mz2z/uilfbRCkvCPC7hQiWrqYz+YXWUIqu hkPLk43wNbqQuzK/e0RbfZsuqvJXsnE4SLFyiM8qiUOe5kv1q1IwUbb4ErlZxI5WNPdYSB bfhIzY7z1BfUvbC2TLVKY4keZ6c3lLY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-393-Yny4dwVRO4ua2n_490SM6A-1; Tue, 03 Mar 2020 07:33:21 -0500 X-MC-Unique: Yny4dwVRO4ua2n_490SM6A-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7E907100550E; Tue, 3 Mar 2020 12:33:19 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-117-34.ams2.redhat.com [10.36.117.34]) by smtp.corp.redhat.com (Postfix) with ESMTP id 603F973860; Tue, 3 Mar 2020 12:33:17 +0000 (UTC) Subject: Re: [edk2-devel] [PATCH v5 36/42] OvmfPkg/QemuFlashFvbServicesRuntimeDxe: Bypass flash detection with SEV-ES is enabled To: devel@edk2.groups.io, thomas.lendacky@amd.com Cc: Jordan Justen , Ard Biesheuvel , Michael D Kinney , Liming Gao , Eric Dong , Ray Ni , Brijesh Singh References: <05bb0fa97078cbaeac5d6388c25a7b203fb62286.1583190432.git.thomas.lendacky@amd.com> From: "Laszlo Ersek" Message-ID: Date: Tue, 3 Mar 2020 13:33:16 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <05bb0fa97078cbaeac5d6388c25a7b203fb62286.1583190432.git.thomas.lendacky@amd.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Hi Tom, On 03/03/20 00:07, Lendacky, Thomas wrote: > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198 > > The flash detection routine will attempt to determine how the flash > device behaves (e.g. ROM, RAM, Flash). But when SEV-ES is enabled and > the flash device behaves as a ROM device (meaning it is marked read-only > by the hypervisor), this check may result in an infinite nested page fault > because of the attempted write. Since the instruction cannot be emulated > when SEV-ES is enabled, the RIP is never advanced, resulting in repeated > nested page faults. > > When SEV-ES is enabled, exit the flash detection early and assume that > the FD behaves as Flash. This will result in QemuFlashWrite() being called > to store EFI variables, which will also result in an infinite nested page > fault when the write is performed. In this case, update QemuFlashWrite() > to use the VmgMmioWrite function from the VmgExitLib library to have the > hypervisor perform the write without having to emulate the instruction. > > Cc: Jordan Justen > Cc: Laszlo Ersek > Cc: Ard Biesheuvel > Reviewed-by: Laszlo Ersek > Signed-off-by: Tom Lendacky > --- > OvmfPkg/OvmfPkgIa32.dsc | 1 + > OvmfPkg/OvmfPkgIa32X64.dsc | 1 + > OvmfPkg/OvmfPkgX64.dsc | 1 + I asked for these lib class resolutions to be dropped, under v4. http://mid.mail-archive.com/53e0bc61-5105-1597-7add-86e038015e15@redhat.com Laszlo > .../FvbServicesRuntimeDxe.inf | 2 ++ > .../QemuFlash.h | 6 +++++ > .../QemuFlash.c | 23 ++++++++++++++++--- > .../QemuFlashDxe.c | 15 ++++++++++++ > .../QemuFlashSmm.c | 9 ++++++++ > 8 files changed, 55 insertions(+), 3 deletions(-) > > diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc > index 51d7acafdda3..2531b7edccf5 100644 > --- a/OvmfPkg/OvmfPkgIa32.dsc > +++ b/OvmfPkg/OvmfPkgIa32.dsc > @@ -318,6 +318,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER] > BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf > PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf > QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf > + VmgExitLib|UefiCpuPkg/Library/VmgExitLib/VmgExitLib.inf > > [LibraryClasses.common.UEFI_DRIVER] > PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf > diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc > index 764fa8c287a0..629725ef2b44 100644 > --- a/OvmfPkg/OvmfPkgIa32X64.dsc > +++ b/OvmfPkg/OvmfPkgIa32X64.dsc > @@ -323,6 +323,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER] > BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf > PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf > QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf > + VmgExitLib|UefiCpuPkg/Library/VmgExitLib/VmgExitLib.inf > > [LibraryClasses.common.UEFI_DRIVER] > PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf > diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc > index b6e29e09db97..74076cbe7692 100644 > --- a/OvmfPkg/OvmfPkgX64.dsc > +++ b/OvmfPkg/OvmfPkgX64.dsc > @@ -323,6 +323,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER] > BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf > PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf > QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf > + VmgExitLib|UefiCpuPkg/Library/VmgExitLib/VmgExitLib.inf > > [LibraryClasses.common.UEFI_DRIVER] > PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf > diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf > index 8125fd0735a1..3ce19d1bfa8e 100644 > --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf > +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf > @@ -38,6 +38,7 @@ [Sources] > [Packages] > MdePkg/MdePkg.dec > MdeModulePkg/MdeModulePkg.dec > + UefiCpuPkg/UefiCpuPkg.dec > OvmfPkg/OvmfPkg.dec > > [LibraryClasses] > @@ -52,6 +53,7 @@ [LibraryClasses] > UefiBootServicesTableLib > UefiDriverEntryPoint > UefiRuntimeLib > + VmgExitLib > > [Guids] > gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED > diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h > index f1afabcbe6ae..19ac1f733279 100644 > --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h > +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h > @@ -89,5 +89,11 @@ QemuFlashBeforeProbe ( > IN UINTN FdBlockCount > ); > > +VOID > +QemuFlashPtrWrite ( > + IN volatile UINT8 *Ptr, > + IN UINT8 Value > + ); > + > #endif > > diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c > index c81c58972bf2..ccf5ad7f7afb 100644 > --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c > +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c > @@ -9,6 +9,7 @@ > > #include > #include > +#include > #include > > #include "QemuFlash.h" > @@ -80,6 +81,21 @@ QemuFlashDetected ( > > DEBUG ((EFI_D_INFO, "QEMU Flash: Attempting flash detection at %p\n", Ptr)); > > + if (MemEncryptSevEsIsEnabled()) { > + // > + // When SEV-ES is enabled, the check below can result in an infinite > + // loop with respect to a nested page fault. When the memslot is mapped > + // read-only, the nested page table entry is read-only. The check below > + // will cause a nested page fault that cannot be emulated, causing > + // the instruction to retried over and over. For SEV-ES, acknowledge that > + // the FD appears as ROM and not as FLASH, but report FLASH anyway because > + // FLASH behavior can be simulated using VMGEXIT. > + // > + DEBUG ((DEBUG_INFO, > + "QEMU Flash: SEV-ES enabled, assuming FD behaves as FLASH\n")); > + return TRUE; > + } > + > OriginalUint8 = *Ptr; > *Ptr = CLEAR_STATUS_CMD; > ProbeUint8 = *Ptr; > @@ -181,8 +197,9 @@ QemuFlashWrite ( > // > Ptr = QemuFlashPtr (Lba, Offset); > for (Loop = 0; Loop < *NumBytes; Loop++) { > - *Ptr = WRITE_BYTE_CMD; > - *Ptr = Buffer[Loop]; > + QemuFlashPtrWrite (Ptr, WRITE_BYTE_CMD); > + QemuFlashPtrWrite (Ptr, Buffer[Loop]); > + > Ptr++; > } > > @@ -190,7 +207,7 @@ QemuFlashWrite ( > // Restore flash to read mode > // > if (*NumBytes > 0) { > - *(Ptr - 1) = READ_ARRAY_CMD; > + QemuFlashPtrWrite (Ptr - 1, READ_ARRAY_CMD); > } > > return EFI_SUCCESS; > diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c > index 5aabe9d7b59c..939463a8e17c 100644 > --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c > +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c > @@ -10,6 +10,8 @@ > **/ > > #include > +#include > +#include > > #include "QemuFlash.h" > > @@ -32,3 +34,16 @@ QemuFlashBeforeProbe ( > // Do nothing > // > } > + > +VOID > +QemuFlashPtrWrite ( > + IN volatile UINT8 *Ptr, > + IN UINT8 Value > + ) > +{ > + if (MemEncryptSevEsIsEnabled()) { > + VmgMmioWrite ((UINT8 *) Ptr, &Value, 1); > + } else { > + *Ptr = Value; > + } > +} > diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c > index 7eb426e03855..eff40ae28032 100644 > --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c > +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c > @@ -46,3 +46,12 @@ QemuFlashBeforeProbe ( > ); > ASSERT_EFI_ERROR (Status); > } > + > +VOID > +QemuFlashPtrWrite ( > + IN volatile UINT8 *Ptr, > + IN UINT8 Value > + ) > +{ > + *Ptr = Value; > +} >