public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support
@ 2021-04-30 11:51 Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 01/28] MdePkg: Expand the SEV MSR to include the SNP definition Brijesh Singh
                   ` (28 more replies)
  0 siblings, 29 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

SEV-SNP builds upon existing SEV and SEV-ES functionality while adding
new hardware-based memory protections. SEV-SNP adds strong memory integrity
protection to help prevent malicious hypervisor-based attacks like data
replay, memory re-mapping and more in order to create an isolated memory
encryption environment.
 
This series provides the basic building blocks to support booting the SEV-SNP
VMs, it does not cover all the security enhancement introduced by the SEV-SNP
such as interrupt protection.

Many of the integrity guarantees of SEV-SNP are enforced through a new
structure called the Reverse Map Table (RMP). Adding a new page to SEV-SNP
VM requires a 2-step process. First, the hypervisor assigns a page to the
guest using the new RMPUPDATE instruction. This transitions the page to
guest-invalid. Second, the guest validates the page using the new PVALIDATE
instruction. The SEV-SNP VMs can use the new "Page State Change Request NAE"
defined in the GHCB specification to ask hypervisor to add or remove page
from the RMP table.

Each page assigned to the SEV-SNP VM can either be validated or unvalidated,
as indicated by the Validated flag in the page's RMP entry. There are two
approaches that can be taken for the page validation: Pre-validation and
Lazy Validation.

Under pre-validation, the pages are validated prior to first use. And under
lazy validation, pages are validated when first accessed. An access to a
unvalidated page results in a #VC exception, at which time the exception
handler may validate the page. Lazy validation requires careful tracking of
the validated pages to avoid validating the same GPA more than once. The
recently introduced "Unaccepted" memory type can be used to communicate the
unvalidated memory ranges to the Guest OS.

At this time we only support the pre-validation. OVMF detects all the available
system RAM in the PEI phase. When SEV-SNP is enabled, the memory is validated
before it is made available to the EDK2 core.

This series does not implements the following SEV-SNP features yet:

* CPUID filtering
* AP bring up using the new SEV-SNP NAE
* Lazy validation
* Interrupt security

The series is based on commit:
01c0ab90be (origin/master, origin/HEAD, master) AzurePipelines: Add support for ArmPlatformPkg

Additional resources
---------------------
SEV-SNP whitepaper
https://www.amd.com/system/files/TechDocs/SEV-SNP-strengthening-vm-isolation-with-integrity-protection-and-more.pdf

APM 2: https://www.amd.com/system/files/TechDocs/24593.pdf (section 15.36)

The complete source is available at
https://github.com/AMDESE/ovmf/tree/sev-snp-rfc-2

GHCB spec:
https://developer.amd.com/wp-content/resources/56421.pdf

SEV-SNP firmware specification:
https://developer.amd.com/sev/
	         
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>

Changes since v1:
 * Drop the interval tree support to detect the pre-validated overlap region.
 * Use an array to keep track of pre-validated regions.
 * Add support to query the Hypervisor feature and verify that SNP feature is supported.
 * Introduce MemEncryptSevClearMmioPageEncMask() to clear the C-bit from MMIO ranges.
 * Pull the SevSecretDxe and SevSecretPei into OVMF package build.
 * Extend the SevSecretDxe to expose confidential computing blob location through
   EFI configuration table.

Brijesh Singh (28):
  MdePkg: Expand the SEV MSR to include the SNP definition
  MdePkg: Define the GHCB Hypervisor features
  MdePkg: Define the GHCB GPA structure
  MdePkg: Define the Page State Change VMGEXIT structures
  MdePkg: Add AsmPvalidate() support
  OvmfPkg/BaseMemEncryptSevLib: Introduce
    MemEncryptSevClearMmioPageEncMask()
  OvmfPkg: Use MemEncryptSevClearMmioPageEncMask() to clear EncMask from
    Mmio
  OvmfPkg/BaseMemEncryptSevLib: Remove CacheFlush parameter
  OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase
  OvmfPkg/MemEncryptSevLib: add MemEncryptSevSnpEnabled()
  OvmfPkg: Reserve Secrets page in MEMFD
  OvmfPkg: Reserve CPUID page for the SEV-SNP guest
  OvmfPkg: Validate the data pages used in the Reset vector and SEC
    phase
  UefiCpuPkg: Define the SEV-SNP specific dynamic PCDs
  OvmfPkg/MemEncryptSevLib: extend the workarea to include SNP enabled
    field
  OvmfPkg/MemEncryptSevLib: Extend Es Workarea to include hv features
  OvmfPkg/ResetVector: Invalidate the GHCB page
  OvmfPkg: Add a library to support registering GHCB GPA
  OvmfPkg: register GHCB gpa for the SEV-SNP guest
  UefiCpuPkg/MpLib: add support to register GHCB GPA when SEV-SNP is
    enabled
  OvmfPkg/MemEncryptSevLib: Add support to validate system RAM
  OvmfPkg/BaseMemEncryptSevLib: Skip the pre-validated system RAM
  OvmfPkg/MemEncryptSevLib: Add support to validate > 4GB memory in PEI
    phase
  OvmfPkg/SecMain: Pre-validate the memory used for decompressing Fv
  OvmfPkg/PlatformPei: Validate the system RAM when SNP is active
  OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table
  OvmfPkg/AmdSev: Expose the SNP reserved pages through configuration
    table
  MdePkg/GHCB: Increase the GHCB protocol max version

 MdePkg/Include/Library/BaseLib.h              |  37 +++
 MdePkg/Include/Register/Amd/Fam17Msr.h        |  36 ++-
 MdePkg/Include/Register/Amd/Ghcb.h            |  37 ++-
 MdePkg/Library/BaseLib/BaseLib.inf            |   1 +
 MdePkg/Library/BaseLib/X64/Pvalidate.nasm     |  43 +++
 OvmfPkg/AmdSev/SecretDxe/SecretDxe.c          |  21 ++
 OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf        |   4 +
 OvmfPkg/AmdSev/SecretPei/SecretPei.c          |  16 +-
 OvmfPkg/AmdSev/SecretPei/SecretPei.inf        |   1 +
 OvmfPkg/AmdSevDxe/AmdSevDxe.c                 |  13 +-
 OvmfPkg/FvmainCompactScratchEnd.fdf.inc       |   5 +
 .../Guid/ConfidentialComputingSecret.h        |  17 ++
 OvmfPkg/Include/Library/GhcbRegisterLib.h     |  27 ++
 OvmfPkg/Include/Library/MemEncryptSevLib.h    |  66 ++++-
 OvmfPkg/IoMmuDxe/AmdSevIoMmu.c                |   6 +-
 .../DxeMemEncryptSevLib.inf                   |   3 +
 .../DxeMemEncryptSevLibInternal.c             |  27 ++
 .../Ia32/MemEncryptSevLib.c                   |  58 +++-
 .../PeiMemEncryptSevLib.inf                   |   7 +
 .../PeiMemEncryptSevLibInternal.c             |  27 ++
 .../SecMemEncryptSevLib.inf                   |   3 +
 .../SecMemEncryptSevLibInternal.c             |  19 ++
 .../X64/DxeSnpSystemRamValidate.c             |  40 +++
 .../X64/MemEncryptSevLib.c                    |  49 +++-
 .../X64/PeiDxeVirtualMemory.c                 | 203 +++++++++++++-
 .../X64/PeiSnpSystemRamValidate.c             | 126 +++++++++
 .../X64/SecSnpSystemRamValidate.c             |  36 +++
 .../X64/SecVirtualMemory.c                    |   8 +-
 .../X64/SnpPageStateChange.h                  |  31 +++
 .../X64/SnpPageStateChangeInternal.c          | 261 ++++++++++++++++++
 .../BaseMemEncryptSevLib/X64/VirtualMemory.h  |  52 +++-
 .../Library/GhcbRegisterLib/GhcbRegisterLib.c |  97 +++++++
 .../GhcbRegisterLib/GhcbRegisterLib.inf       |  33 +++
 .../SmmCpuFeaturesLib/SmmCpuFeaturesLib.c     |   3 +-
 OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf  |   4 +
 OvmfPkg/Library/VmgExitLib/VmgExitLib.inf     |   7 +
 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c |  45 +++
 OvmfPkg/OvmfPkg.dec                           |  21 ++
 OvmfPkg/OvmfPkgIa32.dsc                       |   2 +
 OvmfPkg/OvmfPkgIa32X64.dsc                    |   2 +
 OvmfPkg/OvmfPkgX64.dsc                        |   3 +
 OvmfPkg/OvmfPkgX64.fdf                        |  17 +-
 OvmfPkg/PlatformPei/AmdSev.c                  |  84 +++++-
 OvmfPkg/PlatformPei/MemDetect.c               |  13 +
 OvmfPkg/PlatformPei/PlatformPei.inf           |   5 +
 .../FwBlockServiceDxe.c                       |   5 +-
 .../QemuFlashSmm.c                            |   5 +-
 OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm  |  23 ++
 OvmfPkg/ResetVector/Ia32/PageTables64.asm     | 216 +++++++++++++++
 OvmfPkg/ResetVector/ResetVector.inf           |   4 +
 OvmfPkg/ResetVector/ResetVector.nasmb         |   6 +
 OvmfPkg/Sec/SecMain.c                         | 103 +++++++
 OvmfPkg/Sec/SecMain.inf                       |   3 +
 UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf |   1 +
 UefiCpuPkg/Library/MpInitLib/MpEqu.inc        |   1 +
 UefiCpuPkg/Library/MpInitLib/MpLib.c          |   2 +
 UefiCpuPkg/Library/MpInitLib/MpLib.h          |   2 +
 UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf |   1 +
 UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm |  51 ++++
 UefiCpuPkg/UefiCpuPkg.dec                     |  11 +
 60 files changed, 1970 insertions(+), 80 deletions(-)
 create mode 100644 MdePkg/Library/BaseLib/X64/Pvalidate.nasm
 create mode 100644 OvmfPkg/Include/Library/GhcbRegisterLib.h
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/DxeSnpSystemRamValidate.c
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChange.h
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c
 create mode 100644 OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.c
 create mode 100644 OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.inf

-- 
2.17.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 01/28] MdePkg: Expand the SEV MSR to include the SNP definition
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-03  8:39   ` [edk2-devel] " Laszlo Ersek
  2021-04-30 11:51 ` [PATCH RFC v2 02/28] MdePkg: Define the GHCB Hypervisor features Brijesh Singh
                   ` (27 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

Define the SEV-SNP MSR bits.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 MdePkg/Include/Register/Amd/Fam17Msr.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
index e4db09c518..4d33bef220 100644
--- a/MdePkg/Include/Register/Amd/Fam17Msr.h
+++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
@@ -87,7 +87,12 @@ typedef union {
     ///
     UINT32  SevEsBit:1;
 
-    UINT32  Reserved:30;
+    ///
+    /// [Bit 2] Secure Nested Paging (SevSnp) is enabled
+    ///
+    UINT32  SevSnpBit:1;
+
+    UINT32  Reserved:29;
   } Bits;
   ///
   /// All bit fields as a 32-bit value
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 02/28] MdePkg: Define the GHCB Hypervisor features
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 01/28] MdePkg: Expand the SEV MSR to include the SNP definition Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-03 10:10   ` [edk2-devel] " Laszlo Ersek
  2021-04-30 11:51 ` [PATCH RFC v2 03/28] MdePkg: Define the GHCB GPA structure Brijesh Singh
                   ` (26 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

Version 2 of GHCB introduces advertisement of features that are supported
by the hypervisor. See the GHCB spec section 2.2 for an additional details.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 MdePkg/Include/Register/Amd/Fam17Msr.h | 7 +++++++
 MdePkg/Include/Register/Amd/Ghcb.h     | 6 ++++++
 2 files changed, 13 insertions(+)

diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
index 4d33bef220..a65d51ab12 100644
--- a/MdePkg/Include/Register/Amd/Fam17Msr.h
+++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
@@ -48,6 +48,11 @@ typedef union {
     UINT32  Reserved2:32;
   } GhcbTerminate;
 
+  struct {
+    UINT64  Function:12;
+    UINT64  Features:52;
+  } GhcbHypervisorFeatures;
+
   VOID    *Ghcb;
 
   UINT64  GhcbPhysicalAddress;
@@ -57,6 +62,8 @@ typedef union {
 #define GHCB_INFO_SEV_INFO_GET             2
 #define GHCB_INFO_CPUID_REQUEST            4
 #define GHCB_INFO_CPUID_RESPONSE           5
+#define GHCB_HYPERVISOR_FEATURES_REQUEST   128
+#define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
 #define GHCB_INFO_TERMINATE_REQUEST        256
 
 #define GHCB_TERMINATE_GHCB                0
diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
index ccdb662af7..2d64a4c28f 100644
--- a/MdePkg/Include/Register/Amd/Ghcb.h
+++ b/MdePkg/Include/Register/Amd/Ghcb.h
@@ -54,6 +54,7 @@
 #define SVM_EXIT_NMI_COMPLETE   0x80000003ULL
 #define SVM_EXIT_AP_RESET_HOLD  0x80000004ULL
 #define SVM_EXIT_AP_JUMP_TABLE  0x80000005ULL
+#define SVM_EXIT_HYPERVISOR_FEATURES  0x8000FFFDULL
 #define SVM_EXIT_UNSUPPORTED    0x8000FFFFULL
 
 //
@@ -154,4 +155,9 @@ typedef union {
 #define GHCB_EVENT_INJECTION_TYPE_EXCEPTION  3
 #define GHCB_EVENT_INJECTION_TYPE_SOFT_INT   4
 
+// Hypervisor features
+#define GHCB_HV_FEATURES_SNP                              BIT0
+#define GHCB_HV_FEATURES_SNP_AP_CREATE                    (GHCB_HV_FEATURES_SNP | BIT1)
+#define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION         (GHCB_HV_FEATURES_SNP_AP_CREATE | BIT2)
+#define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION_TIMER   (GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION | BIT3)
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 03/28] MdePkg: Define the GHCB GPA structure
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 01/28] MdePkg: Expand the SEV MSR to include the SNP definition Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 02/28] MdePkg: Define the GHCB Hypervisor features Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-03 10:24   ` [edk2-devel] " Laszlo Ersek
  2021-04-30 11:51 ` [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures Brijesh Singh
                   ` (25 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

An SEV-SNP guest is required to perform the GHCB GPA registration. See
the GHCB specification for further details.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 MdePkg/Include/Register/Amd/Fam17Msr.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
index a65d51ab12..e19bd04b6c 100644
--- a/MdePkg/Include/Register/Amd/Fam17Msr.h
+++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
@@ -53,6 +53,11 @@ typedef union {
     UINT64  Features:52;
   } GhcbHypervisorFeatures;
 
+  struct {
+    UINT64  Function:12;
+    UINT64  GuestFrameNumber:52;
+  } GhcbGpaRegister;
+
   VOID    *Ghcb;
 
   UINT64  GhcbPhysicalAddress;
@@ -62,6 +67,8 @@ typedef union {
 #define GHCB_INFO_SEV_INFO_GET             2
 #define GHCB_INFO_CPUID_REQUEST            4
 #define GHCB_INFO_CPUID_RESPONSE           5
+#define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
+#define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
 #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
 #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
 #define GHCB_INFO_TERMINATE_REQUEST        256
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (2 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 03/28] MdePkg: Define the GHCB GPA structure Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-04 12:33   ` [edk2-devel] " Laszlo Ersek
  2021-04-30 11:51 ` [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support Brijesh Singh
                   ` (24 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

The Page State Change NAE exit will be used by the SEV-SNP guest to
request a page state change using the GHCB protocol. See the GHCB
spec section 4.1.6 and 2.3.1 for more detail on the structure
definitions.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 MdePkg/Include/Register/Amd/Fam17Msr.h | 15 ++++++++++
 MdePkg/Include/Register/Amd/Ghcb.h     | 29 ++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
index e19bd04b6c..432cee2feb 100644
--- a/MdePkg/Include/Register/Amd/Fam17Msr.h
+++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
@@ -58,6 +58,19 @@ typedef union {
     UINT64  GuestFrameNumber:52;
   } GhcbGpaRegister;
 
+  struct {
+    UINT64 Function:12;
+    UINT64 GuestFrameNumber:40;
+    UINT64 Operation:4;
+    UINT64 Reserved:8;
+  } SnpPageStateChangeRequest;
+
+  struct {
+    UINT32 Function:12;
+    UINT32 Reserved:20;
+    UINT32 ErrorCode;
+  } SnpPageStateChangeResponse;
+
   VOID    *Ghcb;
 
   UINT64  GhcbPhysicalAddress;
@@ -69,6 +82,8 @@ typedef union {
 #define GHCB_INFO_CPUID_RESPONSE           5
 #define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
 #define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
+#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_REQUEST   20
+#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_RESPONSE  21
 #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
 #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
 #define GHCB_INFO_TERMINATE_REQUEST        256
diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
index 2d64a4c28f..1e7c0daed3 100644
--- a/MdePkg/Include/Register/Amd/Ghcb.h
+++ b/MdePkg/Include/Register/Amd/Ghcb.h
@@ -54,6 +54,7 @@
 #define SVM_EXIT_NMI_COMPLETE   0x80000003ULL
 #define SVM_EXIT_AP_RESET_HOLD  0x80000004ULL
 #define SVM_EXIT_AP_JUMP_TABLE  0x80000005ULL
+#define SVM_EXIT_SNP_PAGE_STATE_CHANGE    0x80000010ULL
 #define SVM_EXIT_HYPERVISOR_FEATURES  0x8000FFFDULL
 #define SVM_EXIT_UNSUPPORTED    0x8000FFFFULL
 
@@ -160,4 +161,32 @@ typedef union {
 #define GHCB_HV_FEATURES_SNP_AP_CREATE                    (GHCB_HV_FEATURES_SNP | BIT1)
 #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION         (GHCB_HV_FEATURES_SNP_AP_CREATE | BIT2)
 #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION_TIMER   (GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION | BIT3)
+
+// SNP Page State Change
+#define SNP_PAGE_STATE_MAX_NPAGES           4095
+#define SNP_PAGE_STATE_MAX_ENTRY            253
+#define SNP_PAGE_STATE_PRIVATE              1
+#define SNP_PAGE_STATE_SHARED               2
+#define SNP_PAGE_STATE_PSMASH               3
+#define SNP_PAGE_STATE_UNSMASH              4
+
+typedef PACKED struct {
+  UINT64  CurrentPage:12;
+  UINT64  GuestFrameNumber:40;
+  UINT64  Op:4;
+  UINT64  PageSize:1;
+  UINT64  Rsvd: 7;
+} SNP_PAGE_STATE_ENTRY;
+
+typedef PACKED struct {
+  UINT16 CurrentEntry;
+  UINT16 EndEntry;
+  UINT32 Rsvd;
+} SNP_PAGE_STATE_HEADER;
+
+typedef struct {
+  SNP_PAGE_STATE_HEADER  Header;
+  SNP_PAGE_STATE_ENTRY   Entry[SNP_PAGE_STATE_MAX_ENTRY];
+} SNP_PAGE_STATE_CHANGE_INFO;
+
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (3 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-04 13:58   ` [edk2-devel] " Laszlo Ersek
  2021-04-30 11:51 ` [PATCH RFC v2 06/28] OvmfPkg/BaseMemEncryptSevLib: Introduce MemEncryptSevClearMmioPageEncMask() Brijesh Singh
                   ` (23 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

The PVALIDATE instruction validates or rescinds validation of a guest
page RMP entry. Upon completion, a return code is stored in EAX, rFLAGS
bits OF, ZF, AF, PF and SF are set based on this return code. If the
instruction completed succesfully, the rFLAGS bit CF indicates if the
contents of the RMP entry were changed or not.

For more information about the instruction see AMD APM volume 3.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 MdePkg/Include/Library/BaseLib.h          | 37 +++++++++++++++++
 MdePkg/Library/BaseLib/BaseLib.inf        |  1 +
 MdePkg/Library/BaseLib/X64/Pvalidate.nasm | 43 ++++++++++++++++++++
 3 files changed, 81 insertions(+)

diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h
index 7253997a6f..92ce695e93 100644
--- a/MdePkg/Include/Library/BaseLib.h
+++ b/MdePkg/Include/Library/BaseLib.h
@@ -7518,5 +7518,42 @@ PatchInstructionX86 (
   IN  UINTN                    ValueSize
   );
 
+/**
+ Execute a PVALIDATE instruction to validate or rescnids validation of a guest
+ page's RMP entry.
+
+ Upon completion, in addition to the return value the instruction also updates
+ the eFlags. A caller must check both the return code as well as eFlags to
+ determine if the RMP entry has been updated.
+
+ The function is available on x64.
+
+ @param[in]    Address        The guest virtual address to validate.
+ @param[in]    PageSize       The page size to use.
+ @param[i]     Validate       Validate or rescinds.
+ @param[out]   Eflags         The value of Eflags after PVALIDATE completion.
+
+ @retval       PvalidateRetValue  The return value from the PVALIDATE instruction.
+**/
+typedef enum {
+  PvalidatePageSize4K = 0,
+  PvalidatePageSize2MB,
+} PVALIDATE_PAGE_SIZE;
+
+typedef enum {
+  PvalidateRetSuccess = 0,
+  PvalidateRetFailInput = 1,
+  PvalidateRetFailSizemismatch = 6,
+} PVALIDATE_RET_VALUE;
+
+PVALIDATE_RET_VALUE
+EFIAPI
+AsmPvalidate (
+  IN   PVALIDATE_PAGE_SIZE     PageSize,
+  IN   BOOLEAN                 Validate,
+  IN   UINTN                   Address,
+  OUT  IA32_EFLAGS32           *Eflags
+  );
+
 #endif // defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
 #endif // !defined (__BASE_LIB__)
diff --git a/MdePkg/Library/BaseLib/BaseLib.inf b/MdePkg/Library/BaseLib/BaseLib.inf
index b76f3af380..d33b4a8f7d 100644
--- a/MdePkg/Library/BaseLib/BaseLib.inf
+++ b/MdePkg/Library/BaseLib/BaseLib.inf
@@ -321,6 +321,7 @@
   X64/XGetBv.nasm
   X64/XSetBv.nasm
   X64/VmgExit.nasm
+  X64/Pvalidate.nasm
   ChkStkGcc.c  | GCC
 
 [Sources.EBC]
diff --git a/MdePkg/Library/BaseLib/X64/Pvalidate.nasm b/MdePkg/Library/BaseLib/X64/Pvalidate.nasm
new file mode 100644
index 0000000000..f2aba114ac
--- /dev/null
+++ b/MdePkg/Library/BaseLib/X64/Pvalidate.nasm
@@ -0,0 +1,43 @@
+;-----------------------------------------------------------------------------
+;
+; Copyright (c) 2020-2021, AMD. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+;   Pvalidate.Asm
+;
+; Abstract:
+;
+;   AsmPvalidate function
+;
+; Notes:
+;
+;-----------------------------------------------------------------------------
+
+    SECTION .text
+
+;-----------------------------------------------------------------------------
+;  PvalidateRetValue
+;  EFIAPI
+;  AsmPvalidate (
+;    IN   UINT32  RmpPageSize
+;    IN   UINT32  Validate,
+;    IN   UINTN   Address,
+;    OUT  UINTN  *Eflags,
+;    )
+;-----------------------------------------------------------------------------
+global ASM_PFX(AsmPvalidate)
+ASM_PFX(AsmPvalidate):
+  mov     rax, r8
+
+  ; PVALIDATE instruction opcode
+  DB      0xF2, 0x0F, 0x01, 0xFF
+
+  ; Read the Eflags
+  pushfq
+  pop     r8
+  mov     [r9], r8
+
+  ; The PVALIDATE instruction returns the status in rax register.
+  ret
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 06/28] OvmfPkg/BaseMemEncryptSevLib: Introduce MemEncryptSevClearMmioPageEncMask()
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (4 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-06 10:39   ` [edk2-devel] " Laszlo Ersek
  2021-04-30 11:51 ` [PATCH RFC v2 07/28] OvmfPkg: Use MemEncryptSevClearMmioPageEncMask() to clear EncMask from Mmio Brijesh Singh
                   ` (22 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

The MemEncryptSevClearMmioPageEncMask() helper can be used for clearing
the memory encryption mask for the Mmio region from the current page
table context.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/Include/Library/MemEncryptSevLib.h                     | 25 +++++++++++
 OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c   | 31 ++++++++++++++
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c    | 33 +++++++++++++++
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 44 ++++++++++++++++++--
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h       | 23 ++++++++++
 5 files changed, 153 insertions(+), 3 deletions(-)

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index 99f15a7d12..c19f92afc6 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -203,4 +203,29 @@ MemEncryptSevGetAddressRangeState (
   IN UINTN                    Length
   );
 
+/**
+  This function clears memory encryption bit for the mmio region specified by
+  BaseAddress and NumPages from the current page table context.
+
+  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
+                                      current CR3)
+  @param[in]  BaseAddress             The physical address that is the start
+                                      address of a mmio region.
+  @param[in]  NumPages                The number of pages from start memory
+                                      region.
+
+  @retval RETURN_SUCCESS              The attributes were cleared for the
+                                      memory region.
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
+  @retval RETURN_UNSUPPORTED          Clearing the memory encryption attribute
+                                      is not supported
+**/
+RETURN_STATUS
+EFIAPI
+MemEncryptSevClearMmioPageEncMask (
+  IN PHYSICAL_ADDRESS         Cr3BaseAddress,
+  IN PHYSICAL_ADDRESS         BaseAddress,
+  IN UINTN                    NumPages
+  );
+
 #endif // _MEM_ENCRYPT_SEV_LIB_H_
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
index 12a5bf495b..4e8a997d42 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
@@ -111,3 +111,34 @@ MemEncryptSevGetAddressRangeState (
   //
   return MemEncryptSevAddressRangeEncrypted;
 }
+
+/**
+  This function clears memory encryption bit for the mmio region specified by
+  BaseAddress and NumPages from the current page table context.
+
+  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
+                                      current CR3)
+  @param[in]  BaseAddress             The physical address that is the start
+                                      address of a mmio region.
+  @param[in]  NumPages                The number of pages from start memory
+                                      region.
+
+  @retval RETURN_SUCCESS              The attributes were cleared for the
+                                      memory region.
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
+  @retval RETURN_UNSUPPORTED          Clearing the memory encryption attribute
+                                      is not supported
+**/
+RETURN_STATUS
+EFIAPI
+MemEncryptSevClearMmioPageEncMask (
+  IN PHYSICAL_ADDRESS         Cr3BaseAddress,
+  IN PHYSICAL_ADDRESS         BaseAddress,
+  IN UINTN                    NumPages
+  )
+{
+  //
+  // Memory encryption bit is not accessible in 32-bit mode
+  //
+  return RETURN_UNSUPPORTED;
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
index 4fea6a6be0..6786573aea 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
@@ -118,3 +118,36 @@ MemEncryptSevGetAddressRangeState (
            Length
            );
 }
+
+/**
+  This function clears memory encryption bit for the mmio region specified by
+  BaseAddress and NumPages from the current page table context.
+
+  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
+                                      current CR3)
+  @param[in]  BaseAddress             The physical address that is the start
+                                      address of a mmio region.
+  @param[in]  NumPages                The number of pages from start memory
+                                      region.
+
+  @retval RETURN_SUCCESS              The attributes were cleared for the
+                                      memory region.
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
+  @retval RETURN_UNSUPPORTED          Clearing the memory encryption attribute
+                                      is not supported
+**/
+RETURN_STATUS
+EFIAPI
+MemEncryptSevClearMmioPageEncMask (
+  IN PHYSICAL_ADDRESS         Cr3BaseAddress,
+  IN PHYSICAL_ADDRESS         BaseAddress,
+  IN UINTN                    NumPages
+  )
+{
+  return InternalMemEncryptSevClearMmioPageEncMask (
+           Cr3BaseAddress,
+           BaseAddress,
+           EFI_PAGES_TO_SIZE (NumPages)
+           );
+
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
index d3455e812b..3bcc92f2e9 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
@@ -557,6 +557,7 @@ EnableReadOnlyPageWriteProtect (
   @param[in]  Mode                    Set or Clear mode
   @param[in]  CacheFlush              Flush the caches before applying the
                                       encryption mask
+  @param[in]  IsMmio                  The address is Mmio address.
 
   @retval RETURN_SUCCESS              The attributes were cleared for the
                                       memory region.
@@ -572,7 +573,8 @@ SetMemoryEncDec (
   IN    PHYSICAL_ADDRESS         PhysicalAddress,
   IN    UINTN                    Length,
   IN    MAP_RANGE_MODE           Mode,
-  IN    BOOLEAN                  CacheFlush
+  IN    BOOLEAN                  CacheFlush,
+  IN    BOOLEAN                  Mmio
   )
 {
   PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
@@ -852,7 +854,8 @@ InternalMemEncryptSevSetMemoryDecrypted (
            PhysicalAddress,
            Length,
            ClearCBit,
-           Flush
+           Flush,
+           FALSE
            );
 }
 
@@ -888,6 +891,41 @@ InternalMemEncryptSevSetMemoryEncrypted (
            PhysicalAddress,
            Length,
            SetCBit,
-           Flush
+           Flush,
+           FALSE
+           );
+}
+
+/**
+  This function clears memory encryption bit for the Mmio region specified by
+  PhysicalAddress and Length from the current page table context.
+
+  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
+                                      current CR3)
+  @param[in]  PhysicalAddress         The physical address that is the start
+                                      address of a mmio region.
+  @param[in]  Length                  The length of memory region
+
+  @retval RETURN_SUCCESS              The attributes were cleared for the
+                                      memory region.
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
+  @retval RETURN_UNSUPPORTED          Clearing the memory encyrption attribute
+                                      is not supported
+**/
+RETURN_STATUS
+EFIAPI
+InternalMemEncryptSevClearMmioPageEncMask (
+  IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
+  IN  PHYSICAL_ADDRESS        PhysicalAddress,
+  IN  UINTN                   Length
+  )
+{
+  return SetMemoryEncDec (
+           Cr3BaseAddress,
+           PhysicalAddress,
+           Length,
+           ClearCBit,
+           FALSE,
+           TRUE
            );
 }
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
index fe2a0b2826..99ee7ea0e8 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
@@ -126,4 +126,27 @@ InternalMemEncryptSevGetAddressRangeState (
   IN UINTN                    Length
   );
 
+/**
+  This function clears memory encryption bit for the Mmio region specified by
+  PhysicalAddress and Length from the current page table context.
+
+  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
+                                      current CR3)
+  @param[in]  PhysicalAddress         The physical address that is the start
+                                      address of a mmio region.
+  @param[in]  Length                  The length of memory region
+
+  @retval RETURN_SUCCESS              The attributes were cleared for the
+                                      memory region.
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
+  @retval RETURN_UNSUPPORTED          Clearing the memory encyrption attribute
+                                      is not supported
+**/
+RETURN_STATUS
+EFIAPI
+InternalMemEncryptSevClearMmioPageEncMask (
+  IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
+  IN  PHYSICAL_ADDRESS        PhysicalAddress,
+  IN  UINTN                   Length
+  );
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 07/28] OvmfPkg: Use MemEncryptSevClearMmioPageEncMask() to clear EncMask from Mmio
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (5 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 06/28] OvmfPkg/BaseMemEncryptSevLib: Introduce MemEncryptSevClearMmioPageEncMask() Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-06 10:50   ` [edk2-devel] " Laszlo Ersek
  2021-04-30 11:51 ` [PATCH RFC v2 08/28] OvmfPkg/BaseMemEncryptSevLib: Remove CacheFlush parameter Brijesh Singh
                   ` (21 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

Use the MemEncryptSevClearMmioPageEncMask() to clear memory encryption mask
for the Mmio address range from the current page table context.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/AmdSevDxe/AmdSevDxe.c                              | 10 ++++------
 OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c |  5 ++---
 OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c      |  5 ++---
 3 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
index 689bfb376d..80831b81fa 100644
--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c
+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
@@ -53,11 +53,10 @@ AmdSevDxeEntryPoint (
       Desc = &AllDescMap[Index];
       if (Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo ||
           Desc->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
-        Status = MemEncryptSevClearPageEncMask (
+        Status = MemEncryptSevClearMmioPageEncMask (
                    0,
                    Desc->BaseAddress,
-                   EFI_SIZE_TO_PAGES (Desc->Length),
-                   FALSE
+                   EFI_SIZE_TO_PAGES (Desc->Length)
                    );
         ASSERT_EFI_ERROR (Status);
       }
@@ -73,11 +72,10 @@ AmdSevDxeEntryPoint (
   // the range.
   //
   if (PcdGet16 (PcdOvmfHostBridgePciDevId) == INTEL_Q35_MCH_DEVICE_ID) {
-    Status = MemEncryptSevClearPageEncMask (
+    Status = MemEncryptSevClearMmioPageEncMask (
                0,
                FixedPcdGet64 (PcdPciExpressBaseAddress),
-               EFI_SIZE_TO_PAGES (SIZE_256MB),
-               FALSE
+               EFI_SIZE_TO_PAGES (SIZE_256MB)
                );
 
     ASSERT_EFI_ERROR (Status);
diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
index 1f285e0083..ab40087a84 100644
--- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
+++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
@@ -205,11 +205,10 @@ MarkIoMemoryRangeForRuntimeAccess (
   // memory range.
   //
   if (MemEncryptSevIsEnabled ()) {
-    Status = MemEncryptSevClearPageEncMask (
+    Status = MemEncryptSevClearMmioPageEncMask (
                0,
                BaseAddress,
-               EFI_SIZE_TO_PAGES (Length),
-               FALSE
+               EFI_SIZE_TO_PAGES (Length)
                );
     ASSERT_EFI_ERROR (Status);
   }
diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
index 7eb80bfeff..ea75b489c7 100644
--- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
+++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
@@ -38,11 +38,10 @@ QemuFlashBeforeProbe (
   // C-bit on flash ranges from SMM page table.
   //
 
-  Status = MemEncryptSevClearPageEncMask (
+  Status = MemEncryptSevClearMmioPageEncMask (
              0,
              BaseAddress,
-             EFI_SIZE_TO_PAGES (FdBlockSize * FdBlockCount),
-             FALSE
+             EFI_SIZE_TO_PAGES (FdBlockSize * FdBlockCount)
              );
   ASSERT_EFI_ERROR (Status);
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 08/28] OvmfPkg/BaseMemEncryptSevLib: Remove CacheFlush parameter
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (6 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 07/28] OvmfPkg: Use MemEncryptSevClearMmioPageEncMask() to clear EncMask from Mmio Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-06 11:08   ` [edk2-devel] " Laszlo Ersek
  2021-04-30 11:51 ` [PATCH RFC v2 09/28] OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase Brijesh Singh
                   ` (20 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

The CacheFlush parameter is used to provide hint whether the specified
range is Mmio address. Now that we have a dedicated helper to clear the
memory encryption mask for the Mmio address range, its safe to remove the
CacheFlush parameter from MemEncryptSev{Set,Clear}PageEncMask().

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/AmdSevDxe/AmdSevDxe.c                                  |  3 +--
 OvmfPkg/Include/Library/MemEncryptSevLib.h                     | 10 ++--------
 OvmfPkg/IoMmuDxe/AmdSevIoMmu.c                                 |  6 ++----
 OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c   | 10 ++--------
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c    | 16 ++++------------
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 14 ++++----------
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c    |  8 ++------
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h       | 10 ++--------
 OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c          |  3 +--
 OvmfPkg/PlatformPei/AmdSev.c                                   |  3 +--
 10 files changed, 21 insertions(+), 62 deletions(-)

diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
index 80831b81fa..41e4b291d0 100644
--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c
+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
@@ -120,8 +120,7 @@ AmdSevDxeEntryPoint (
     Status = MemEncryptSevClearPageEncMask (
                0,             // Cr3BaseAddress -- use current CR3
                MapPagesBase,  // BaseAddress
-               MapPagesCount, // NumPages
-               TRUE           // Flush
+               MapPagesCount // NumPages
                );
     if (EFI_ERROR (Status)) {
       DEBUG ((DEBUG_ERROR, "%a: MemEncryptSevClearPageEncMask(): %r\n",
diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index c19f92afc6..9b15d80931 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -100,8 +100,6 @@ MemEncryptSevIsEnabled (
                                       address of a memory region.
   @param[in]  NumPages                The number of pages from start memory
                                       region.
-  @param[in]  Flush                   Flush the caches before clearing the bit
-                                      (mostly TRUE except MMIO addresses)
 
   @retval RETURN_SUCCESS              The attributes were cleared for the
                                       memory region.
@@ -114,8 +112,7 @@ EFIAPI
 MemEncryptSevClearPageEncMask (
   IN PHYSICAL_ADDRESS         Cr3BaseAddress,
   IN PHYSICAL_ADDRESS         BaseAddress,
-  IN UINTN                    NumPages,
-  IN BOOLEAN                  Flush
+  IN UINTN                    NumPages
   );
 
 /**
@@ -128,8 +125,6 @@ MemEncryptSevClearPageEncMask (
                                       address of a memory region.
   @param[in]  NumPages                The number of pages from start memory
                                       region.
-  @param[in]  Flush                   Flush the caches before setting the bit
-                                      (mostly TRUE except MMIO addresses)
 
   @retval RETURN_SUCCESS              The attributes were set for the memory
                                       region.
@@ -142,8 +137,7 @@ EFIAPI
 MemEncryptSevSetPageEncMask (
   IN PHYSICAL_ADDRESS         Cr3BaseAddress,
   IN PHYSICAL_ADDRESS         BaseAddress,
-  IN UINTN                    NumPages,
-  IN BOOLEAN                  Flush
+  IN UINTN                    NumPages
   );
 
 
diff --git a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
index 49ffa24488..b30628078f 100644
--- a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
+++ b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
@@ -252,8 +252,7 @@ IoMmuMap (
   Status = MemEncryptSevClearPageEncMask (
              0,
              MapInfo->PlainTextAddress,
-             MapInfo->NumberOfPages,
-             TRUE
+             MapInfo->NumberOfPages
              );
   ASSERT_EFI_ERROR (Status);
   if (EFI_ERROR (Status)) {
@@ -407,8 +406,7 @@ IoMmuUnmapWorker (
   Status = MemEncryptSevSetPageEncMask (
              0,
              MapInfo->PlainTextAddress,
-             MapInfo->NumberOfPages,
-             TRUE
+             MapInfo->NumberOfPages
              );
   ASSERT_EFI_ERROR (Status);
   if (EFI_ERROR (Status)) {
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
index 4e8a997d42..34e7c59e2c 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
@@ -25,8 +25,6 @@
                                       address of a memory region.
   @param[in]  NumPages                The number of pages from start memory
                                       region.
-  @param[in]  Flush                   Flush the caches before clearing the bit
-                                      (mostly TRUE except MMIO addresses)
 
   @retval RETURN_SUCCESS              The attributes were cleared for the
                                       memory region.
@@ -39,8 +37,7 @@ EFIAPI
 MemEncryptSevClearPageEncMask (
   IN PHYSICAL_ADDRESS         Cr3BaseAddress,
   IN PHYSICAL_ADDRESS         BaseAddress,
-  IN UINTN                    NumPages,
-  IN BOOLEAN                  Flush
+  IN UINTN                    NumPages
   )
 {
   //
@@ -59,8 +56,6 @@ MemEncryptSevClearPageEncMask (
                                       address of a memory region.
   @param[in]  NumPages                The number of pages from start memory
                                       region.
-  @param[in]  Flush                   Flush the caches before setting the bit
-                                      (mostly TRUE except MMIO addresses)
 
   @retval RETURN_SUCCESS              The attributes were set for the memory
                                       region.
@@ -73,8 +68,7 @@ EFIAPI
 MemEncryptSevSetPageEncMask (
   IN PHYSICAL_ADDRESS         Cr3BaseAddress,
   IN PHYSICAL_ADDRESS         BaseAddress,
-  IN UINTN                    NumPages,
-  IN BOOLEAN                  Flush
+  IN UINTN                    NumPages
   )
 {
   //
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
index 6786573aea..5c260c546e 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
@@ -27,8 +27,6 @@
                                       address of a memory region.
   @param[in]  NumPages                The number of pages from start memory
                                       region.
-  @param[in]  Flush                   Flush the caches before clearing the bit
-                                      (mostly TRUE except MMIO addresses)
 
   @retval RETURN_SUCCESS              The attributes were cleared for the
                                       memory region.
@@ -41,15 +39,13 @@ EFIAPI
 MemEncryptSevClearPageEncMask (
   IN PHYSICAL_ADDRESS         Cr3BaseAddress,
   IN PHYSICAL_ADDRESS         BaseAddress,
-  IN UINTN                    NumPages,
-  IN BOOLEAN                  Flush
+  IN UINTN                    NumPages
   )
 {
   return InternalMemEncryptSevSetMemoryDecrypted (
            Cr3BaseAddress,
            BaseAddress,
-           EFI_PAGES_TO_SIZE (NumPages),
-           Flush
+           EFI_PAGES_TO_SIZE (NumPages)
            );
 }
 
@@ -63,8 +59,6 @@ MemEncryptSevClearPageEncMask (
                                       address of a memory region.
   @param[in]  NumPages                The number of pages from start memory
                                       region.
-  @param[in]  Flush                   Flush the caches before setting the bit
-                                      (mostly TRUE except MMIO addresses)
 
   @retval RETURN_SUCCESS              The attributes were set for the memory
                                       region.
@@ -77,15 +71,13 @@ EFIAPI
 MemEncryptSevSetPageEncMask (
   IN PHYSICAL_ADDRESS         Cr3BaseAddress,
   IN PHYSICAL_ADDRESS         BaseAddress,
-  IN UINTN                    NumPages,
-  IN BOOLEAN                  Flush
+  IN UINTN                    NumPages
   )
 {
   return InternalMemEncryptSevSetMemoryEncrypted (
            Cr3BaseAddress,
            BaseAddress,
-           EFI_PAGES_TO_SIZE (NumPages),
-           Flush
+           EFI_PAGES_TO_SIZE (NumPages)
            );
 }
 
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
index 3bcc92f2e9..707db5a74a 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
@@ -830,8 +830,6 @@ Done:
   @param[in]  PhysicalAddress         The physical address that is the start
                                       address of a memory region.
   @param[in]  Length                  The length of memory region
-  @param[in]  Flush                   Flush the caches before applying the
-                                      encryption mask
 
   @retval RETURN_SUCCESS              The attributes were cleared for the
                                       memory region.
@@ -844,8 +842,7 @@ EFIAPI
 InternalMemEncryptSevSetMemoryDecrypted (
   IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
   IN  PHYSICAL_ADDRESS        PhysicalAddress,
-  IN  UINTN                   Length,
-  IN  BOOLEAN                 Flush
+  IN  UINTN                   Length
   )
 {
 
@@ -854,7 +851,7 @@ InternalMemEncryptSevSetMemoryDecrypted (
            PhysicalAddress,
            Length,
            ClearCBit,
-           Flush,
+           TRUE,
            FALSE
            );
 }
@@ -868,8 +865,6 @@ InternalMemEncryptSevSetMemoryDecrypted (
   @param[in]  PhysicalAddress         The physical address that is the start
                                       address of a memory region.
   @param[in]  Length                  The length of memory region
-  @param[in]  Flush                   Flush the caches before applying the
-                                      encryption mask
 
   @retval RETURN_SUCCESS              The attributes were set for the memory
                                       region.
@@ -882,8 +877,7 @@ EFIAPI
 InternalMemEncryptSevSetMemoryEncrypted (
   IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
   IN  PHYSICAL_ADDRESS        PhysicalAddress,
-  IN  UINTN                   Length,
-  IN  BOOLEAN                 Flush
+  IN  UINTN                   Length
   )
 {
   return SetMemoryEncDec (
@@ -891,7 +885,7 @@ InternalMemEncryptSevSetMemoryEncrypted (
            PhysicalAddress,
            Length,
            SetCBit,
-           Flush,
+           TRUE,
            FALSE
            );
 }
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c
index bca5e3febb..24d19d3ca1 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c
@@ -42,8 +42,6 @@ InternalGetMemEncryptionAddressMask (
   @param[in]  PhysicalAddress         The physical address that is the start
                                       address of a memory region.
   @param[in]  Length                  The length of memory region
-  @param[in]  Flush                   Flush the caches before applying the
-                                      encryption mask
 
   @retval RETURN_SUCCESS              The attributes were cleared for the
                                       memory region.
@@ -56,8 +54,7 @@ EFIAPI
 InternalMemEncryptSevSetMemoryDecrypted (
   IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
   IN  PHYSICAL_ADDRESS        PhysicalAddress,
-  IN  UINTN                   Length,
-  IN  BOOLEAN                 Flush
+  IN  UINTN                   Length
   )
 {
   //
@@ -89,8 +86,7 @@ EFIAPI
 InternalMemEncryptSevSetMemoryEncrypted (
   IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
   IN  PHYSICAL_ADDRESS        PhysicalAddress,
-  IN  UINTN                   Length,
-  IN  BOOLEAN                 Flush
+  IN  UINTN                   Length
   )
 {
   //
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
index 99ee7ea0e8..832ff10a33 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
@@ -58,8 +58,6 @@ InternalGetMemEncryptionAddressMask (
   @param[in]  PhysicalAddress         The physical address that is the start
                                       address of a memory region.
   @param[in]  Length                  The length of memory region
-  @param[in]  Flush                   Flush the caches before applying the
-                                      encryption mask
 
   @retval RETURN_SUCCESS              The attributes were cleared for the
                                       memory region.
@@ -72,8 +70,7 @@ EFIAPI
 InternalMemEncryptSevSetMemoryDecrypted (
   IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
   IN  PHYSICAL_ADDRESS        PhysicalAddress,
-  IN  UINTN                   Length,
-  IN  BOOLEAN                 Flush
+  IN  UINTN                   Length
   );
 
 /**
@@ -85,8 +82,6 @@ InternalMemEncryptSevSetMemoryDecrypted (
   @param[in]  PhysicalAddress         The physical address that is the start
                                       address of a memory region.
   @param[in]  Length                  The length of memory region
-  @param[in]  Flush                   Flush the caches before applying the
-                                      encryption mask
 
   @retval RETURN_SUCCESS              The attributes were set for the memory
                                       region.
@@ -99,8 +94,7 @@ EFIAPI
 InternalMemEncryptSevSetMemoryEncrypted (
   IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
   IN  PHYSICAL_ADDRESS        PhysicalAddress,
-  IN  UINTN                   Length,
-  IN  BOOLEAN                 Flush
+  IN  UINTN                   Length
   );
 
 /**
diff --git a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
index fdf2380974..c7cc5b0389 100644
--- a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
+++ b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
@@ -283,8 +283,7 @@ SmmCpuFeaturesSmmRelocationComplete (
   Status = MemEncryptSevSetPageEncMask (
              0,             // Cr3BaseAddress -- use current CR3
              MapPagesBase,  // BaseAddress
-             MapPagesCount, // NumPages
-             TRUE           // Flush
+             MapPagesCount  // NumPages
              );
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a: MemEncryptSevSetPageEncMask(): %r\n",
diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index dddffdebda..a8bf610022 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -72,8 +72,7 @@ AmdSevEsInitialize (
     DecryptStatus = MemEncryptSevClearPageEncMask (
       0,
       GhcbBasePa + EFI_PAGES_TO_SIZE (PageCount),
-      1,
-      TRUE
+      1
       );
     ASSERT_RETURN_ERROR (DecryptStatus);
   }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 09/28] OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (7 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 08/28] OvmfPkg/BaseMemEncryptSevLib: Remove CacheFlush parameter Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-06 14:08   ` [edk2-devel] " Laszlo Ersek
  2021-04-30 11:51 ` [PATCH RFC v2 10/28] OvmfPkg/MemEncryptSevLib: add MemEncryptSevSnpEnabled() Brijesh Singh
                   ` (19 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

Commit 85b8eac59b8c5bd9c7eb9afdb64357ce1aa2e803 added support to ensure
that MMIO is only performed against the un-encrypted memory. If MMIO
is performed against encrypted memory, a #GP is raised.

The VmgExitLib library depends on ApicTimerLib to get the APIC base
address so that it can exclude the APIC range from the un-encrypted
check. The OvmfPkg provides ApicTimerLib for the DXE phase. The
constructor AcpiTimerLibConstructor() used in the ApicTimerLib uses
the PciRead to get the PMBASE register. The PciRead() will cause an
MMIO access.

The AmdSevDxe driver clears the memory encryption attribute from the
MMIO ranges. However, if VmgExitLib is linked to AmdSevDxe driver then the
AcpiTimerLibConstructor() will be called before AmdSevDxe driver can
clear the encryption attributes for the MMIO regions.

Exclude the PMBASE register from the encrypted check so that we
can link VmgExitLib to the MemEncryptSevLib; which gets linked to
AmdSevDxe driver.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf  |  4 ++
 OvmfPkg/Library/VmgExitLib/VmgExitLib.inf     |  7 +++
 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 45 ++++++++++++++++++++
 3 files changed, 56 insertions(+)

diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
index e6f6ea7972..22435a0590 100644
--- a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
+++ b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
@@ -27,6 +27,7 @@
   SecVmgExitVcHandler.c
 
 [Packages]
+  MdeModulePkg/MdeModulePkg.dec
   MdePkg/MdePkg.dec
   OvmfPkg/OvmfPkg.dec
   UefiCpuPkg/UefiCpuPkg.dec
@@ -42,4 +43,7 @@
 [FixedPcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
 
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
index c66c68726c..d3175c260e 100644
--- a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
+++ b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
@@ -27,6 +27,7 @@
   PeiDxeVmgExitVcHandler.c
 
 [Packages]
+  MdeModulePkg/MdeModulePkg.dec
   MdePkg/MdePkg.dec
   OvmfPkg/OvmfPkg.dec
   UefiCpuPkg/UefiCpuPkg.dec
@@ -37,4 +38,10 @@
   DebugLib
   LocalApicLib
   MemEncryptSevLib
+  PcdLib
 
+[FixedPcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
index 24259060fd..01ac5d8c19 100644
--- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
+++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
@@ -14,7 +14,10 @@
 #include <Library/VmgExitLib.h>
 #include <Register/Amd/Msr.h>
 #include <Register/Intel/Cpuid.h>
+#include <IndustryStandard/Q35MchIch9.h>
+#include <IndustryStandard/I440FxPiix4.h>
 #include <IndustryStandard/InstructionParsing.h>
+#include <Library/PcdLib.h>
 
 #include "VmgExitVcHandler.h"
 
@@ -596,6 +599,40 @@ UnsupportedExit (
   return Status;
 }
 
+STATIC
+BOOLEAN
+IsPmbaBaseAddress (
+  IN  UINTN     Address
+  )
+{
+  UINT16 HostBridgeDevId;
+  UINTN Pmba;
+
+  //
+  // Query Host Bridge DID to determine platform type
+  //
+  HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
+  switch (HostBridgeDevId) {
+    case INTEL_82441_DEVICE_ID:
+      Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
+      break;
+    case INTEL_Q35_MCH_DEVICE_ID:
+      Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
+      //
+      // Add the MMCONFIG base address to get the Pmba base access address
+      //
+      Pmba += FixedPcdGet64 (PcdPciExpressBaseAddress);
+      break;
+    default:
+      return FALSE;
+  }
+
+  // Round up the offset to page size
+  Pmba = Pmba & ~(SIZE_4KB - 1);
+
+  return (Address == Pmba);
+}
+
 /**
   Validate that the MMIO memory access is not to encrypted memory.
 
@@ -640,6 +677,14 @@ ValidateMmioMemory (
     return 0;
   }
 
+  //
+  // Allow PMBASE accesses (which will have the encryption bit set before
+  // AmdSevDxe runs in the DXE phase)
+  //
+  if (IsPmbaBaseAddress (Address)) {
+    return 0;
+  }
+
   //
   // Any state other than unencrypted is an error, issue a #GP.
   //
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 10/28] OvmfPkg/MemEncryptSevLib: add MemEncryptSevSnpEnabled()
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (8 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 09/28] OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD Brijesh Singh
                   ` (18 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

Create a function that can be used to determine if VM is running as an
SEV-SNP guest.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/Include/Library/MemEncryptSevLib.h                         | 12 +++++++++
 OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c | 27 ++++++++++++++++++++
 OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c | 27 ++++++++++++++++++++
 OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c | 19 ++++++++++++++
 4 files changed, 85 insertions(+)

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index 9b15d80931..3868376dbf 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -66,6 +66,18 @@ typedef enum {
   MemEncryptSevAddressRangeError,
 } MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE;
 
+/**
+  Returns a boolean to indicate whether SEV-SNP is enabled
+
+  @retval TRUE           SEV-SNP is enabled
+  @retval FALSE          SEV-SNP is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevSnpIsEnabled (
+  VOID
+  );
+
 /**
   Returns a boolean to indicate whether SEV-ES is enabled.
 
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
index 2816f859a0..0571297238 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
@@ -19,6 +19,7 @@
 
 STATIC BOOLEAN mSevStatus = FALSE;
 STATIC BOOLEAN mSevEsStatus = FALSE;
+STATIC BOOLEAN mSevSnpStatus = FALSE;
 STATIC BOOLEAN mSevStatusChecked = FALSE;
 
 STATIC UINT64  mSevEncryptionMask = 0;
@@ -82,11 +83,37 @@ InternalMemEncryptSevStatus (
     if (Msr.Bits.SevEsBit) {
       mSevEsStatus = TRUE;
     }
+
+    //
+    // Check MSR_0xC0010131 Bit 2 (Sev-Snp Enabled)
+    //
+    if (Msr.Bits.SevSnpBit) {
+      mSevSnpStatus = TRUE;
+    }
   }
 
   mSevStatusChecked = TRUE;
 }
 
+/**
+  Returns a boolean to indicate whether SEV-SNP is enabled.
+
+  @retval TRUE           SEV-SNP is enabled
+  @retval FALSE          SEV-SNP is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevSnpIsEnabled (
+  VOID
+  )
+{
+  if (!mSevStatusChecked) {
+    InternalMemEncryptSevStatus ();
+  }
+
+  return mSevSnpStatus;
+}
+
 /**
   Returns a boolean to indicate whether SEV-ES is enabled.
 
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
index e2fd109d12..b561f211f5 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
@@ -19,6 +19,7 @@
 
 STATIC BOOLEAN mSevStatus = FALSE;
 STATIC BOOLEAN mSevEsStatus = FALSE;
+STATIC BOOLEAN mSevSnpStatus = FALSE;
 STATIC BOOLEAN mSevStatusChecked = FALSE;
 
 STATIC UINT64  mSevEncryptionMask = 0;
@@ -82,11 +83,37 @@ InternalMemEncryptSevStatus (
     if (Msr.Bits.SevEsBit) {
       mSevEsStatus = TRUE;
     }
+
+    //
+    // Check MSR_0xC0010131 Bit 2 (Sev-Snp Enabled)
+    //
+    if (Msr.Bits.SevSnpBit) {
+      mSevSnpStatus = TRUE;
+    }
   }
 
   mSevStatusChecked = TRUE;
 }
 
+/**
+  Returns a boolean to indicate whether SEV-SNP is enabled.
+
+  @retval TRUE           SEV-SNP is enabled
+  @retval FALSE          SEV-SNP is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevSnpIsEnabled (
+  VOID
+  )
+{
+  if (!mSevStatusChecked) {
+    InternalMemEncryptSevStatus ();
+  }
+
+  return mSevSnpStatus;
+}
+
 /**
   Returns a boolean to indicate whether SEV-ES is enabled.
 
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
index 56d8f3f318..69852779e2 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
@@ -62,6 +62,25 @@ InternalMemEncryptSevStatus (
   return ReadSevMsr ? AsmReadMsr32 (MSR_SEV_STATUS) : 0;
 }
 
+/**
+  Returns a boolean to indicate whether SEV-SNP is enabled.
+
+  @retval TRUE           SEV-SNP is enabled
+  @retval FALSE          SEV-SNP is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevSnpIsEnabled (
+  VOID
+  )
+{
+  MSR_SEV_STATUS_REGISTER           Msr;
+
+  Msr.Uint32 = InternalMemEncryptSevStatus ();
+
+  return Msr.Bits.SevSnpBit ? TRUE : FALSE;
+}
+
 /**
   Returns a boolean to indicate whether SEV-ES is enabled.
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (9 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 10/28] OvmfPkg/MemEncryptSevLib: add MemEncryptSevSnpEnabled() Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-05  6:42   ` [edk2-devel] " Dov Murik
  2021-04-30 11:51 ` [PATCH RFC v2 12/28] OvmfPkg: Reserve CPUID page for the SEV-SNP guest Brijesh Singh
                   ` (17 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

When AMD SEV is enabled in the guest VM, a hypervisor need to insert a
secrets page.

When SEV-SNP is enabled, the secrets page contains the VM platform
communication keys. The guest BIOS and OS can use this key to communicate
with the SEV firmware to get attesation report. See the SEV-SNP firmware
spec for more details for the content of the secrets page.

When SEV and SEV-ES is enabled, the secrets page contains the information
provided by the guest owner after the attestation. See the SEV
LAUNCH_SECRET command for more details.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/AmdSev/SecretPei/SecretPei.c   | 16 +++++++++++++++-
 OvmfPkg/AmdSev/SecretPei/SecretPei.inf |  1 +
 OvmfPkg/OvmfPkgX64.dsc                 |  2 ++
 OvmfPkg/OvmfPkgX64.fdf                 |  5 +++++
 4 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.c b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
index ad491515dd..92836c562c 100644
--- a/OvmfPkg/AmdSev/SecretPei/SecretPei.c
+++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
@@ -7,6 +7,7 @@
 #include <PiPei.h>
 #include <Library/HobLib.h>
 #include <Library/PcdLib.h>
+#include <Library/MemEncryptSevLib.h>
 
 EFI_STATUS
 EFIAPI
@@ -15,10 +16,23 @@ InitializeSecretPei (
   IN CONST EFI_PEI_SERVICES     **PeiServices
   )
 {
+  UINTN   Type;
+
+  //
+  // The secret page should be mapped encrypted by the guest OS and must not
+  // be treated as a system RAM. Mark it as ACPI NVS so that guest OS maps it
+  // encrypted.
+  //
+  if (MemEncryptSevSnpIsEnabled ()) {
+    Type = EfiACPIMemoryNVS;
+  } else {
+    Type = EfiBootServicesData;
+  }
+
   BuildMemoryAllocationHob (
     PcdGet32 (PcdSevLaunchSecretBase),
     PcdGet32 (PcdSevLaunchSecretSize),
-    EfiBootServicesData
+    Type
     );
 
   return EFI_SUCCESS;
diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
index 08be156c4b..9265f8adee 100644
--- a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
+++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
@@ -26,6 +26,7 @@
   HobLib
   PeimEntryPoint
   PcdLib
+  MemEncryptSevLib
 
 [FixedPcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index a7d747f6b4..593c0e69f6 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -716,6 +716,7 @@
   OvmfPkg/SmmAccess/SmmAccessPei.inf
 !endif
   UefiCpuPkg/CpuMpPei/CpuMpPei.inf
+  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
 
 !if $(TPM_ENABLE) == TRUE
   OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
@@ -965,6 +966,7 @@
   OvmfPkg/PlatformDxe/Platform.inf
   OvmfPkg/AmdSevDxe/AmdSevDxe.inf
   OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+  OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
 
 !if $(SMM_REQUIRE) == TRUE
   OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index d519f85328..b04175f77c 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -88,6 +88,9 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.PcdSevE
 0x00C000|0x001000
 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
 
+0x00D000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
+
 0x010000|0x010000
 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
 
@@ -178,6 +181,7 @@ INF  OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
 INF  SecurityPkg/Tcg/TcgPei/TcgPei.inf
 INF  SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
 !endif
+INF  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
 
 ################################################################################
 
@@ -313,6 +317,7 @@ INF  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
 INF  ShellPkg/Application/Shell/Shell.inf
 
 INF MdeModulePkg/Logo/LogoDxe.inf
+INF OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
 
 #
 # Network modules
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 12/28] OvmfPkg: Reserve CPUID page for the SEV-SNP guest
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (10 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 13/28] OvmfPkg: Validate the data pages used in the Reset vector and SEC phase Brijesh Singh
                   ` (16 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

During the SEV-SNP guest launch sequence, two special pages need to be
inserted, the secrets and CPUID. The secrets page, contain the VM
platform communication keys. The guest BIOS and/or OS can use this key
to communicate with the SEV firmware to get the attestation report.
The CPUID page, contain the CPUIDs entries filtered through the AMD-SEV
firmware.

OvmfPkg already reserves the memory for the Secrets Page in the MEMFD.
Extend the MEMFD to reserve the memory for the CPUID page.

See SEV-SNP spec for more information on the content layout of the secrets
and CPUID page, and how it can be used by the SEV-SNP guest VM.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/OvmfPkg.dec                          |  6 ++++++
 OvmfPkg/OvmfPkgX64.fdf                       |  3 +++
 OvmfPkg/PlatformPei/MemDetect.c              | 13 +++++++++++++
 OvmfPkg/PlatformPei/PlatformPei.inf          |  2 ++
 OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 18 ++++++++++++++++++
 OvmfPkg/ResetVector/ResetVector.inf          |  2 ++
 OvmfPkg/ResetVector/ResetVector.nasmb        |  2 ++
 7 files changed, 46 insertions(+)

diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 9629707020..dac5fb1653 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -317,6 +317,12 @@
   gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|0x0|UINT32|0x42
   gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize|0x0|UINT32|0x43
 
+  ## The base address and size of the SEV-SNP CPUID Area provisioned by the
+  #  SEV-SNP firmware. If this is set in the .fdf, the platform
+  #  is responsible for protecting the area from DXE phase overwrites.
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase|0x0|UINT32|0x47
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize|0x0|UINT32|0x48
+
 [PcdsDynamic, PcdsDynamicEx]
   gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index b04175f77c..5cc1da425e 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -91,6 +91,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.P
 0x00D000|0x001000
 gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
 
+0x00E000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize
+
 0x010000|0x010000
 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
 
diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c
index c08aa2e45a..02584123c1 100644
--- a/OvmfPkg/PlatformPei/MemDetect.c
+++ b/OvmfPkg/PlatformPei/MemDetect.c
@@ -894,6 +894,19 @@ InitializeRamRegions (
         EfiACPIMemoryNVS
         );
     }
+
+    if (MemEncryptSevSnpIsEnabled ()) {
+      //
+      // If SEV-SNP is enabled, reserve the CPUID page. The memory range should
+      // not be treated as a RAM and must be mapped encrypted by the guest OS, so,
+      // reserve it as ACPI NVS.
+      //
+      BuildMemoryAllocationHob (
+        (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfSnpCpuidBase),
+        (UINT64)(UINTN) PcdGet32 (PcdOvmfSnpCpuidSize),
+        EfiACPIMemoryNVS
+      );
+    }
 #endif
   }
 
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index 6ef77ba7bb..6d18b0be9f 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -118,6 +118,8 @@
   gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
   gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
   gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
index 9c0b5853a4..05c7e32f46 100644
--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
+++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
@@ -47,6 +47,24 @@ TIMES (15 - ((guidedStructureEnd - guidedStructureStart + 15) % 16)) DB 0
 ;
 guidedStructureStart:
 
+;
+; SEV-SNP boot support
+;
+; sevSnpBlock:
+;   For the initial boot of SEV-SNP guest, a CPUID page must be reserved by
+;   the BIOS at a RAM area defined by SEV_SNP_CPUID_BASE. A hypervisor will
+;   locate this information using the SEV-SNP boot block GUID.
+;
+; GUID (SEV-SNP boot block): bd39c0c2-2f8e-4243-83e8-1b74cebcb7d9
+;
+sevSnpBootBlockStart:
+    DD      SNP_CPUID_BASE
+    DD      SNP_CPUID_SIZE
+    DW      sevSnpBootBlockEnd - sevSnpBootBlockStart
+    DB      0xC2, 0xC0, 0x39, 0xBD, 0x8e, 0x2F, 0x43, 0x42
+    DB      0x83, 0xE8, 0x1B, 0x74, 0xCE, 0xBC, 0xB7, 0xD9
+sevSnpBootBlockEnd:
+
 ;
 ; SEV Secret block
 ;
diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf
index dc38f68919..8e52265602 100644
--- a/OvmfPkg/ResetVector/ResetVector.inf
+++ b/OvmfPkg/ResetVector/ResetVector.inf
@@ -45,5 +45,7 @@
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
 
 [FixedPcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize
   gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
   gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index 5fbacaed5f..57f01aa7c7 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -88,5 +88,7 @@
   %define SEV_ES_AP_RESET_IP  FixedPcdGet32 (PcdSevEsWorkAreaBase)
   %define SEV_LAUNCH_SECRET_BASE  FixedPcdGet32 (PcdSevLaunchSecretBase)
   %define SEV_LAUNCH_SECRET_SIZE  FixedPcdGet32 (PcdSevLaunchSecretSize)
+  %define SNP_CPUID_BASE  FixedPcdGet32 (PcdOvmfSnpCpuidBase)
+  %define SNP_CPUID_SIZE  FixedPcdGet32 (PcdOvmfSnpCpuidSize)
 %include "Ia16/ResetVectorVtf0.asm"
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 13/28] OvmfPkg: Validate the data pages used in the Reset vector and SEC phase
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (11 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 12/28] OvmfPkg: Reserve CPUID page for the SEV-SNP guest Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 14/28] UefiCpuPkg: Define the SEV-SNP specific dynamic PCDs Brijesh Singh
                   ` (15 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

An SEV-SNP guest requires that private memory (aka pages mapped encrypted)
must be validated before being accessed.

The validation process consist of the following sequence:

1) Set the memory encryption attribute in the page table (aka C-bit).
   Note: If the processor is in non-PAE mode, then all the memory accesses
   are considered private.
2) Add the memory range as private in the RMP table. This can be performed
   using the Page State Change VMGEXIT defined in the GHCB specification.
3) Use the PVALIDATE instruction to set the Validated Bit in the RMP table.

During the guest creation time, the VMM encrypts the OVMF_CODE.fd using
the SEV-SNP firmware provided LAUNCH_UPDATE_DATA command. In addition to
encrypting the content, the command also validates the memory region.
This allows us to execute the code without going through the validation
sequence.

During execution, the reset vector need to access some data pages
(such as page tables, SevESWorkarea, Sec stack). The data pages are
accessed as private memory. The data pages are not part of the
OVMF_CODE.fd, so they were not validated during the guest creation.

There are two approaches we can take to validate the data pages before
the access:

a) Enhance the OVMF reset vector code to validate the pages as described
   above (go through step 2 - 3).
OR
b) Validate the pages during the guest creation time. The SEV firmware
   provides a command which can be used by the VMM to validate the pages
   without affecting the measurement of the launch.

Approach #b seems much simpler; it does not require any changes to the
OVMF reset vector code.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/OvmfPkg.dec                          | 5 +++++
 OvmfPkg/OvmfPkgX64.fdf                       | 9 ++++++++-
 OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 5 +++++
 OvmfPkg/ResetVector/ResetVector.inf          | 2 ++
 OvmfPkg/ResetVector/ResetVector.nasmb        | 2 ++
 5 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index dac5fb1653..3d5574364b 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -323,6 +323,11 @@
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase|0x0|UINT32|0x47
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize|0x0|UINT32|0x48
 
+  ## The start and end of pre-validated memory region by the hypervisor
+  #  through the SEV-SNP firmware.
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedStart|0x0|UINT32|0x49
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedEnd|0x0|UINT32|0x50
+
 [PcdsDynamic, PcdsDynamicEx]
   gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 5cc1da425e..806c86bb3f 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -105,7 +105,14 @@ FV = PEIFV
 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
 FV = DXEFV
 
-################################################################################
+##########################################################################################
+#
+# The range of the pages pre-validated through the SEV-SNP firmware while creating SEV-SNP guest
+#
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedStart = $(MEMFD_BASE_ADDRESS) + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedEnd = $(MEMFD_BASE_ADDRESS) + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
+##########################################################################################
 
 [FV.SECFV]
 FvNameGuid         = 763BED0D-DE9F-48F5-81F1-3E90E1B1A015
diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
index 05c7e32f46..769dd0bccf 100644
--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
+++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
@@ -55,11 +55,16 @@ guidedStructureStart:
 ;   the BIOS at a RAM area defined by SEV_SNP_CPUID_BASE. A hypervisor will
 ;   locate this information using the SEV-SNP boot block GUID.
 ;
+;   In order to boot the SEV-SNP guest the hypervisor must pre-validated the
+;   memory range from SNP_HV_VALIDATED_START to SNP_HV_VALIDATED_END.
+;
 ; GUID (SEV-SNP boot block): bd39c0c2-2f8e-4243-83e8-1b74cebcb7d9
 ;
 sevSnpBootBlockStart:
     DD      SNP_CPUID_BASE
     DD      SNP_CPUID_SIZE
+    DD      SNP_HV_VALIDATED_START
+    DD      SNP_HV_VALIDATED_END
     DW      sevSnpBootBlockEnd - sevSnpBootBlockStart
     DB      0xC2, 0xC0, 0x39, 0xBD, 0x8e, 0x2F, 0x43, 0x42
     DB      0x83, 0xE8, 0x1B, 0x74, 0xCE, 0xBC, 0xB7, 0xD9
diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf
index 8e52265602..2a75e909c7 100644
--- a/OvmfPkg/ResetVector/ResetVector.inf
+++ b/OvmfPkg/ResetVector/ResetVector.inf
@@ -49,3 +49,5 @@
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize
   gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
   gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedStart
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedEnd
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index 57f01aa7c7..f936870b81 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -90,5 +90,7 @@
   %define SEV_LAUNCH_SECRET_SIZE  FixedPcdGet32 (PcdSevLaunchSecretSize)
   %define SNP_CPUID_BASE  FixedPcdGet32 (PcdOvmfSnpCpuidBase)
   %define SNP_CPUID_SIZE  FixedPcdGet32 (PcdOvmfSnpCpuidSize)
+  %define SNP_HV_VALIDATED_START FixedPcdGet32 (PcdOvmfSnpHypervisorPreValidatedStart)
+  %define SNP_HV_VALIDATED_END FixedPcdGet32 (PcdOvmfSnpHypervisorPreValidatedEnd)
 %include "Ia16/ResetVectorVtf0.asm"
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 14/28] UefiCpuPkg: Define the SEV-SNP specific dynamic PCDs
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (12 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 13/28] OvmfPkg: Validate the data pages used in the Reset vector and SEC phase Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 15/28] OvmfPkg/MemEncryptSevLib: extend the workarea to include SNP enabled field Brijesh Singh
                   ` (14 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

Define the PCDs used by the MpLib while creating the AP when SEV-SNP is
active in the guest VMs.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 UefiCpuPkg/UefiCpuPkg.dec | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 62acb291f3..1793769439 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -396,5 +396,16 @@
   # @Prompt SEV-ES Status
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled|FALSE|BOOLEAN|0x60000016
 
+  ## This dynamic PCD indicates whether SEV-SNP is enabled
+  #   TRUE  - SEV-SNP is enabled
+  #   FALSE - SEV-SNP is not enabled
+  # @Prompt SEV-SNP Status
+  gUefiCpuPkgTokenSpaceGuid.PcdSevSnpIsEnabled|FALSE|BOOLEAN|0x60000017
+
+  ## This dynamic PCD contains the hypervisor features value obtained through the GHCB HYPERVISOR
+  #  features VMGEXIT defined in the GHCB section 2.2.
+  # @Prompt GHCB Hypervisor Features
+  gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures|0x0|UINT64|0x60000018
+
 [UserExtensions.TianoCore."ExtraFiles"]
   UefiCpuPkgExtra.uni
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 15/28] OvmfPkg/MemEncryptSevLib: extend the workarea to include SNP enabled field
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (13 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 14/28] UefiCpuPkg: Define the SEV-SNP specific dynamic PCDs Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 16/28] OvmfPkg/MemEncryptSevLib: Extend Es Workarea to include hv features Brijesh Singh
                   ` (13 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

Extend the workarea to include the SEV-SNP enabled fields. This will be set
when SEV-SNP is active in the guest VM.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/Include/Library/MemEncryptSevLib.h |  3 ++-
 OvmfPkg/PlatformPei/AmdSev.c               | 26 ++++++++++++++++++++
 OvmfPkg/PlatformPei/PlatformPei.inf        |  1 +
 OvmfPkg/ResetVector/Ia32/PageTables64.asm  | 12 +++++++++
 OvmfPkg/ResetVector/ResetVector.nasmb      |  1 +
 5 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index 3868376dbf..03e476ef2a 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -49,7 +49,8 @@ typedef struct {
 //
 typedef struct _SEC_SEV_ES_WORK_AREA {
   UINT8    SevEsEnabled;
-  UINT8    Reserved1[7];
+  UINT8    SevSnpEnabled;
+  UINT8    Reserved1[6];
 
   UINT64   RandomData;
 
diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index a8bf610022..67b78fd5fa 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -22,6 +22,27 @@
 
 #include "Platform.h"
 
+/**
+
+  Initialize SEV-SNP support if running as an SEV-SNP guest.
+
+  **/
+STATIC
+VOID
+AmdSevSnpInitialize (
+  VOID
+  )
+{
+  RETURN_STATUS        PcdStatus;
+
+  if (!MemEncryptSevSnpIsEnabled ()) {
+    return;
+  }
+
+  PcdStatus = PcdSetBoolS (PcdSevSnpIsEnabled, TRUE);
+  ASSERT_RETURN_ERROR (PcdStatus);
+}
+
 /**
 
   Initialize SEV-ES support if running as an SEV-ES guest.
@@ -209,4 +230,9 @@ AmdSevInitialize (
   // Check and perform SEV-ES initialization if required.
   //
   AmdSevEsInitialize ();
+
+  //
+  // Check and perform SEV-SNP initialization if required.
+  //
+  AmdSevSnpInitialize ();
 }
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index 6d18b0be9f..3aef0773b1 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -110,6 +110,7 @@
   gUefiCpuPkgTokenSpaceGuid.PcdCpuBootLogicalProcessorNumber
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled
+  gUefiCpuPkgTokenSpaceGuid.PcdSevSnpIsEnabled
 
 [FixedPcd]
   gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index 5fae8986d9..6838cdeec9 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -81,6 +81,11 @@ CheckSevFeatures:
     ; the MSR check below will set the first byte of the workarea to one.
     mov     byte[SEV_ES_WORK_AREA], 0
 
+    ; Set the SevSnpEnabled field in workarea to zero to communicate to the SEC
+    ; phase that SEV-SNP is not enabled. If SEV-SNP is enabled, this function
+    ; will set it to 1.
+    mov       byte[SEV_ES_WORK_AREA_SNP], 0
+
     ;
     ; Set up exception handlers to check for SEV-ES
     ;   Load temporary RAM stack based on PCDs (see SevEsIdtVmmComm for
@@ -136,6 +141,13 @@ CheckSevFeatures:
     ; phase that SEV-ES is enabled.
     mov       byte[SEV_ES_WORK_AREA], 1
 
+    bt        eax, 2
+    jnc       GetSevEncBit
+
+    ; Set the second byte of the workarea to one to communicate to the SEC
+    ; phase that the SEV-SNP is enabled
+    mov       byte[SEV_ES_WORK_AREA_SNP], 1
+
 GetSevEncBit:
     ; Get pte bit position to enable memory encryption
     ; CPUID Fn8000_001F[EBX] - Bits 5:0
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index f936870b81..34b900127e 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -73,6 +73,7 @@
   %define GHCB_BASE (FixedPcdGet32 (PcdOvmfSecGhcbBase))
   %define GHCB_SIZE (FixedPcdGet32 (PcdOvmfSecGhcbSize))
   %define SEV_ES_WORK_AREA (FixedPcdGet32 (PcdSevEsWorkAreaBase))
+  %define SEV_ES_WORK_AREA_SNP (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 1)
   %define SEV_ES_WORK_AREA_RDRAND (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 8)
   %define SEV_ES_WORK_AREA_ENC_MASK (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 16)
   %define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 16/28] OvmfPkg/MemEncryptSevLib: Extend Es Workarea to include hv features
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (14 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 15/28] OvmfPkg/MemEncryptSevLib: extend the workarea to include SNP enabled field Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 17/28] OvmfPkg/ResetVector: Invalidate the GHCB page Brijesh Singh
                   ` (12 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

The GHCB Version 2 introduces advertisement of features that are supported
by the hypervisor. The features value is saved in the SevEs workarea. Save
the value in the PCD for the later use.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/Include/Library/MemEncryptSevLib.h |   2 +
 OvmfPkg/PlatformPei/AmdSev.c               |  26 +++++
 OvmfPkg/PlatformPei/PlatformPei.inf        |   1 +
 OvmfPkg/ResetVector/Ia32/PageTables64.asm  | 122 ++++++++++++++++++++
 OvmfPkg/ResetVector/ResetVector.nasmb      |   1 +
 5 files changed, 152 insertions(+)

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index 03e476ef2a..42caa6497b 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -55,6 +55,8 @@ typedef struct _SEC_SEV_ES_WORK_AREA {
   UINT64   RandomData;
 
   UINT64   EncryptionMask;
+
+  UINT64   HypervisorFeatures;
 } SEC_SEV_ES_WORK_AREA;
 
 //
diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index 67b78fd5fa..81e40e0889 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -43,6 +43,27 @@ AmdSevSnpInitialize (
   ASSERT_RETURN_ERROR (PcdStatus);
 }
 
+/**
+
+  Function to set the PcdHypervisorFeatures.
+**/
+STATIC
+VOID
+AmdSevHypervisorFeatures (
+  VOID
+  )
+{
+  SEC_SEV_ES_WORK_AREA  *SevEsWorkArea;
+  RETURN_STATUS         PcdStatus;
+
+  SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *) FixedPcdGet32 (PcdSevEsWorkAreaBase);
+
+  PcdStatus = PcdSet64S (PcdGhcbHypervisorFeatures, SevEsWorkArea->HypervisorFeatures);
+  ASSERT_RETURN_ERROR (PcdStatus);
+
+  DEBUG ((DEBUG_INFO, "GHCB Hypervisor Features=0x%Lx\n", SevEsWorkArea->HypervisorFeatures));
+}
+
 /**
 
   Initialize SEV-ES support if running as an SEV-ES guest.
@@ -73,6 +94,11 @@ AmdSevEsInitialize (
   PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);
   ASSERT_RETURN_ERROR (PcdStatus);
 
+  //
+  // Set the hypervisor features PCD.
+  //
+  AmdSevHypervisorFeatures ();
+
   //
   // Allocate GHCB and per-CPU variable pages.
   //   Since the pages must survive across the UEFI to OS transition
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index 3aef0773b1..89c8e9627c 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -111,6 +111,7 @@
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled
   gUefiCpuPkgTokenSpaceGuid.PcdSevSnpIsEnabled
+  gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures
 
 [FixedPcd]
   gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index 6838cdeec9..6bf4a3524a 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -62,6 +62,16 @@ BITS    32
 %define GHCB_CPUID_REGISTER_SHIFT  30
 %define CPUID_INSN_LEN              2
 
+; GHCB SEV Information MSR protocol
+%define GHCB_SEV_INFORMATION_REQUEST    2
+%define GHCB_SEV_INFORMATION_RESPONSE   1
+
+; GHCB Hypervisor features MSR protocol
+%define GHCB_HYPERVISOR_FEATURES_REQUEST    128
+%define GHCB_HYPERVISOR_FEATURES_RESPONSE   129
+
+; GHCB request to terminate protocol values
+%define GHCB_GENERAL_TERMINATE_REQUEST    255
 
 ; Check if Secure Encrypted Virtualization (SEV) features are enabled.
 ;
@@ -86,6 +96,13 @@ CheckSevFeatures:
     ; will set it to 1.
     mov       byte[SEV_ES_WORK_AREA_SNP], 0
 
+    ; Set the Hypervisor features field in the workarea to zero to communicate
+    ; to the hypervisor features to the SEC phase. The hypervisor feature is
+    ; filled during the call to CheckHypervisorFeatures.
+    mov     eax, 0
+    mov     dword[SEV_ES_WORK_AREA_HYPERVISOR_FEATURES], eax
+    mov     dword[SEV_ES_WORK_AREA_HYPERVISOR_FEATURES + 4], eax
+
     ;
     ; Set up exception handlers to check for SEV-ES
     ;   Load temporary RAM stack based on PCDs (see SevEsIdtVmmComm for
@@ -225,6 +242,106 @@ IsSevEsEnabled:
 SevEsDisabled:
     OneTimeCallRet IsSevEsEnabled
 
+; The version 2 of GHCB specification added the support to query the hypervisor features.
+; If the GHCB version is greather than 2 then read the hypervisor features.
+;
+; Modified:  EAX, EBX, ECX, EDX
+;
+CheckHypervisorFeatures:
+    ; Get the SEV Information
+    ; Setup GHCB MSR
+    ;   GHCB_MSR[11:0]  = SEV information request
+    ;
+    mov     edx, 0
+    mov     eax, GHCB_SEV_INFORMATION_REQUEST
+    mov     ecx, 0xc0010130
+    wrmsr
+
+    ;
+    ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
+    ; mode, so work around this by temporarily switching to 64-bit mode.
+    ;
+BITS    64
+    rep     vmmcall
+BITS    32
+
+    ;
+    ; SEV Information Response GHCB MSR
+    ;   GHCB_MSR[63:48] = Maximum protocol version
+    ;   GHCB_MSR[47:32] = Minimum protocol version
+    ;   GHCB_MSR[11:0]  = SEV information response
+    ;
+    mov     ecx, 0xc0010130
+    rdmsr
+    and     eax, 0xfff
+    cmp     eax, GHCB_SEV_INFORMATION_RESPONSE
+    jnz     TerminateSevGuestLaunch
+    shr     edx, 16
+    cmp     edx, 2
+    jl      CheckHypervisorFeaturesDone
+
+    ; Get the hypervisor features
+    ; Setup GHCB MSR
+    ;   GHCB_MSR[11:0]  = Hypervisor features request
+    ;
+    mov     edx, 0
+    mov     eax, GHCB_HYPERVISOR_FEATURES_REQUEST
+    mov     ecx, 0xc0010130
+    wrmsr
+
+    ;
+    ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
+    ; mode, so work around this by temporarily switching to 64-bit mode.
+    ;
+BITS    64
+    rep     vmmcall
+BITS    32
+
+    ;
+    ; Hypervisor features reponse
+    ;   GHCB_MSR[63:12] = Features bitmap
+    ;   GHCB_MSR[11:0]  = Hypervisor features response
+    ;
+    mov     ecx, 0xc0010130
+    rdmsr
+    mov     ebx, eax
+    and     eax, 0xfff
+    cmp     eax, GHCB_HYPERVISOR_FEATURES_RESPONSE
+    jnz     TerminateSevGuestLaunch
+
+    shr     ebx, 12
+    mov     dword[SEV_ES_WORK_AREA_HYPERVISOR_FEATURES], ebx
+    mov     dword[SEV_ES_WORK_AREA_HYPERVISOR_FEATURES + 4], edx
+
+    jmp     CheckHypervisorFeaturesDone
+TerminateSevGuestLaunch:
+    ;
+    ; Setup GHCB MSR
+    ;   GHCB_MSR[23:16] = 0
+    ;   GHCB_MSR[15:12] = 0
+    ;   GHCB_MSR[11:0]  = Terminate Request
+    ;
+    mov     edx, 0
+    mov     eax, GHCB_GENERAL_TERMINATE_REQUEST
+    mov     ecx, 0xc0010130
+    wrmsr
+
+    ;
+    ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
+    ; mode, so work around this by temporarily switching to 64-bit mode.
+    ;
+BITS    64
+    rep     vmmcall
+BITS    32
+
+TerminateSevGuestLaunchHlt:
+    cli
+    hlt
+    jmp     TerminateSevGuestLaunchHlt
+
+CheckHypervisorFeaturesDone:
+    OneTimeCallRet CheckHypervisorFeatures
+
 ;
 ; Modified:  EAX, EBX, ECX, EDX
 ;
@@ -328,6 +445,11 @@ clearGhcbMemoryLoop:
     mov     dword[ecx * 4 + GHCB_BASE - 4], eax
     loop    clearGhcbMemoryLoop
 
+    ;
+    ; It is SEV-ES guest, query the Hypervisor features
+    ;
+    OneTimeCall   CheckHypervisorFeatures
+
 SetCr3:
     ;
     ; Set CR3 now that the paging structures are available
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index 34b900127e..465038e39d 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -76,6 +76,7 @@
   %define SEV_ES_WORK_AREA_SNP (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 1)
   %define SEV_ES_WORK_AREA_RDRAND (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 8)
   %define SEV_ES_WORK_AREA_ENC_MASK (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 16)
+  %define SEV_ES_WORK_AREA_HYPERVISOR_FEATURES (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 24)
   %define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))
 %include "Ia32/Flat32ToFlat64.asm"
 %include "Ia32/PageTables64.asm"
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 17/28] OvmfPkg/ResetVector: Invalidate the GHCB page
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (15 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 16/28] OvmfPkg/MemEncryptSevLib: Extend Es Workarea to include hv features Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-03 13:05   ` Erdem Aktas
  2021-04-30 11:51 ` [PATCH RFC v2 18/28] OvmfPkg: Add a library to support registering GHCB GPA Brijesh Singh
                   ` (11 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

When SEV-SNP is active, the GHCB page is mapped un-encrypted in the
initial page table built by the reset vector code. Just clearing the
encryption attribute from the page table is not enough. The page also
needs to be added as shared in the RMP table.

The GHCB page was part of the pre-validated memory range specified
through the SnpBootBlock GUID. To maintain the security guarantees,
we must invalidate the GHCB page before clearing the encryption
attribute from the page table, and add the page shared in the RMP
table.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/ResetVector/Ia32/PageTables64.asm | 82 ++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index 6bf4a3524a..9949fcdfba 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -70,9 +70,78 @@ BITS    32
 %define GHCB_HYPERVISOR_FEATURES_REQUEST    128
 %define GHCB_HYPERVISOR_FEATURES_RESPONSE   129
 
+; GHCB Page Invalidate request and response protocol values
+;
+%define GHCB_PAGE_STATE_CHANGE_REQUEST    20
+%define GHCB_PAGE_STATE_CHANGE_RESPONSE   21
+%define GHCB_PAGE_STATE_SHARED            2
+
 ; GHCB request to terminate protocol values
 %define GHCB_GENERAL_TERMINATE_REQUEST    255
 
+; If its an SEV-SNP guest then use the page state change VMGEXIT to invalidate
+; the GHCB page.
+;
+; Modified:  EAX, EBX, ECX, EDX
+;
+InvalidateGHCBPage:
+    ; Check if it is SEV-SNP guest.
+    cmp     byte[SEV_ES_WORK_AREA_SNP], 1
+    jne     InvalidateGHCBPageDone
+
+    ; Check whether hypervisor features has SEV-SNP (BIT0) set to indicate that
+    ; hypervisor supports the page state change.
+    mov     eax, dword[SEV_ES_WORK_AREA_HYPERVISOR_FEATURES]
+    bt      eax, 0
+    jnc     TerminateSevGuestLaunch
+
+    ; Use PVALIDATE instruction to invalidate the page
+    mov     eax, GHCB_BASE
+    mov     ecx, 0
+    mov     edx, 0
+    DB      0xF2, 0x0F, 0x01, 0xFF
+    cmp     eax, 0
+    jnz     TerminateSevGuestLaunch
+
+    ; Ask hypervisor to change the page state to shared using the
+    ; Page State Change VMGEXIT.
+    ;
+    ; Setup GHCB MSR
+    ;   GHCB_MSR[55:52] = Page Operation
+    ;   GHCB_MSR[51:12] = Guest Physical Frame Number
+    ;   GHCB_MSR[11:0]  = Page State Change Request
+    ;
+    mov     eax, (GHCB_BASE >> 12)
+    shl     eax, 12
+    or      eax, GHCB_PAGE_STATE_CHANGE_REQUEST
+    mov     edx, (GHCB_PAGE_STATE_SHARED << 20)
+    mov     ecx, 0xc0010130
+    wrmsr
+
+    ;
+    ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
+    ; mode, so work around this by temporarily switching to 64-bit mode.
+    ;
+BITS    64
+    rep     vmmcall
+BITS    32
+
+    ;
+    ; Response GHCB MSR
+    ;   GHCB_MSR[51:12] = Guest Physical Frame Number
+    ;   GHCB_MSR[11:0]  = Page State Change Response
+    ;
+    mov     ecx, 0xc0010130
+    rdmsr
+    and     eax, 0xfff
+    cmp     eax, GHCB_PAGE_STATE_CHANGE_RESPONSE
+    jnz     TerminateSevGuestLaunch
+    cmp     edx, 0
+    jnz     TerminateSevGuestLaunch
+
+InvalidateGHCBPageDone:
+    OneTimeCallRet InvalidateGHCBPage
+
 ; Check if Secure Encrypted Virtualization (SEV) features are enabled.
 ;
 ; Register usage is tight in this routine, so multiple calls for the
@@ -450,6 +519,19 @@ clearGhcbMemoryLoop:
     ;
     OneTimeCall   CheckHypervisorFeatures
 
+    ;
+    ; The page table built above cleared the memory encryption mask from the
+    ; GHCB_BASE (aka made it shared). When SEV-SNP is enabled, to maintain
+    ; the security guarantees, the page state transition from private to
+    ; shared must go through the page invalidation steps. Invalidate the
+    ; memory range before loading the page table below.
+    ;
+    ; NOTE: the invalidation must happen after zeroing the GHCB memory. This
+    ;       is because, in the 32-bit mode all the access are considered private.
+    ;       The invalidation before the zero'ing will cause a #VC.
+    ;
+    OneTimeCall  InvalidateGHCBPage
+
 SetCr3:
     ;
     ; Set CR3 now that the paging structures are available
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 18/28] OvmfPkg: Add a library to support registering GHCB GPA
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (16 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 17/28] OvmfPkg/ResetVector: Invalidate the GHCB page Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 19/28] OvmfPkg: register GHCB gpa for the SEV-SNP guest Brijesh Singh
                   ` (10 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

An SEV-SNP guest us required to perform GHCB GPA registration before
using a GHCB. See the GHCB spec section 2.5.2 for more details.

Add a library that can be called to perform the GHCB GPA registration.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/Include/Library/GhcbRegisterLib.h           | 27 ++++++
 OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.c   | 97 ++++++++++++++++++++
 OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.inf | 33 +++++++
 OvmfPkg/OvmfPkg.dec                                 |  4 +
 OvmfPkg/OvmfPkgIa32.dsc                             |  1 +
 OvmfPkg/OvmfPkgIa32X64.dsc                          |  1 +
 OvmfPkg/OvmfPkgX64.dsc                              |  1 +
 7 files changed, 164 insertions(+)

diff --git a/OvmfPkg/Include/Library/GhcbRegisterLib.h b/OvmfPkg/Include/Library/GhcbRegisterLib.h
new file mode 100644
index 0000000000..7d98b6eb36
--- /dev/null
+++ b/OvmfPkg/Include/Library/GhcbRegisterLib.h
@@ -0,0 +1,27 @@
+/** @file
+
+  Declarations of utility functions used for GHCB GPA registration.
+
+  Copyright (C) 2021, AMD Inc, All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _GHCB_REGISTER_LIB_H_
+#define _GHCB_REGISTER_LIB_H_
+
+/**
+
+  This function can be used to register the GHCB GPA.
+
+  @param[in]  Address           The physical address to registered.
+
+**/
+VOID
+EFIAPI
+GhcbRegister (
+  IN  EFI_PHYSICAL_ADDRESS   Address
+  );
+
+#endif // _GHCB_REGISTER_LIB_H_
diff --git a/OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.c b/OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.c
new file mode 100644
index 0000000000..7fe0aad75a
--- /dev/null
+++ b/OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.c
@@ -0,0 +1,97 @@
+/** @file
+  GHCBRegister Support Library.
+
+  Copyright (C) 2021, Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/VmgExitLib.h>
+#include <Library/GhcbRegisterLib.h>
+#include <Register/Amd/Msr.h>
+
+/**
+  Handle an SEV-SNP/GHCB protocol check failure.
+
+  Notify the hypervisor using the VMGEXIT instruction that the SEV-SNP guest
+  wishes to be terminated.
+
+  @param[in] ReasonCode  Reason code to provide to the hypervisor for the
+                         termination request.
+
+**/
+STATIC
+VOID
+SevEsProtocolFailure (
+  IN UINT8  ReasonCode
+  )
+{
+  MSR_SEV_ES_GHCB_REGISTER  Msr;
+
+  //
+  // Use the GHCB MSR Protocol to request termination by the hypervisor
+  //
+  Msr.GhcbPhysicalAddress = 0;
+  Msr.GhcbTerminate.Function = GHCB_INFO_TERMINATE_REQUEST;
+  Msr.GhcbTerminate.ReasonCodeSet = GHCB_TERMINATE_GHCB;
+  Msr.GhcbTerminate.ReasonCode = ReasonCode;
+  AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);
+
+  AsmVmgExit ();
+
+  ASSERT (FALSE);
+  CpuDeadLoop ();
+}
+
+/**
+
+  This function can be used to register the GHCB GPA.
+
+  @param[in]  Address           The physical address to be registered.
+
+**/
+VOID
+EFIAPI
+GhcbRegister (
+  IN  EFI_PHYSICAL_ADDRESS   Address
+  )
+{
+  MSR_SEV_ES_GHCB_REGISTER  Msr;
+  MSR_SEV_ES_GHCB_REGISTER  CurrentMsr;
+  EFI_PHYSICAL_ADDRESS      GuestFrameNumber;
+
+  GuestFrameNumber = Address >> EFI_PAGE_SHIFT;
+
+  //
+  // Save the current MSR Value
+  //
+  CurrentMsr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+
+  //
+  // Use the GHCB MSR Protocol to request to register the GPA.
+  //
+  Msr.GhcbPhysicalAddress = 0;
+  Msr.GhcbGpaRegister.Function = GHCB_INFO_GHCB_GPA_REGISTER_REQUEST;
+  Msr.GhcbGpaRegister.GuestFrameNumber = GuestFrameNumber;
+  AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);
+
+  AsmVmgExit ();
+
+  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+
+  //
+  // If hypervisor responded with a different GPA than requested then fail.
+  //
+  if ((Msr.GhcbGpaRegister.Function != GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE) ||
+      (Msr.GhcbGpaRegister.GuestFrameNumber != GuestFrameNumber)) {
+    SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL);
+  }
+
+  //
+  // Restore the MSR
+  //
+  AsmWriteMsr64 (MSR_SEV_ES_GHCB, CurrentMsr.GhcbPhysicalAddress);
+}
diff --git a/OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.inf b/OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.inf
new file mode 100644
index 0000000000..8cc39ef715
--- /dev/null
+++ b/OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.inf
@@ -0,0 +1,33 @@
+## @file
+#  GHCBRegisterLib Support Library.
+#
+#  Copyright (C) 2021, Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = GhcbRegisterLib
+  FILE_GUID                      = 0e913c15-12cd-430b-8714-ffe85672a77b
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = GhcbRegisterLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = X64
+#
+
+[Sources.common]
+  GhcbRegisterLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 3d5574364b..70948ab478 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -106,6 +106,10 @@
   #
   XenPlatformLib|Include/Library/XenPlatformLib.h
 
+  ##  @libraryclass  Register GHCB GPA
+  #
+  GhcbRegisterLib|Include/Library/GhcbRegisterLib.h
+
 [Guids]
   gUefiOvmfPkgTokenSpaceGuid            = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
   gEfiXenInfoGuid                       = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 1730b6558b..f9355172d6 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -243,6 +243,7 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+  GhcbRegisterLib|OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.inf
 
 [LibraryClasses.common.SEC]
   TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 78a559da0d..3f27d7b90d 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -247,6 +247,7 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+  GhcbRegisterLib|OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.inf
 
 [LibraryClasses.common.SEC]
   TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 593c0e69f6..92447f6a2d 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -247,6 +247,7 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
+  GhcbRegisterLib|OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.inf
 
 [LibraryClasses.common.SEC]
   TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 19/28] OvmfPkg: register GHCB gpa for the SEV-SNP guest
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (17 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 18/28] OvmfPkg: Add a library to support registering GHCB GPA Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 20/28] UefiCpuPkg/MpLib: add support to register GHCB GPA when SEV-SNP is enabled Brijesh Singh
                   ` (9 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

The SEV-SNP guest requires that GHCB GPA must be registered before using.
The GHCB GPA can be registred using the GhcbGPARegister().

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/PlatformPei/AmdSev.c        |  8 +++
 OvmfPkg/PlatformPei/PlatformPei.inf |  1 +
 OvmfPkg/Sec/SecMain.c               | 76 ++++++++++++++++++++
 3 files changed, 85 insertions(+)

diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index 81e40e0889..54b07622b4 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -14,6 +14,7 @@
 #include <Library/DebugLib.h>
 #include <Library/HobLib.h>
 #include <Library/MemEncryptSevLib.h>
+#include <Library/GhcbRegisterLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/PcdLib.h>
 #include <PiPei.h>
@@ -156,6 +157,13 @@ AmdSevEsInitialize (
     "SEV-ES is enabled, %lu GHCB backup pages allocated starting at 0x%p\n",
     (UINT64)GhcbBackupPageCount, GhcbBackupBase));
 
+  if (MemEncryptSevSnpIsEnabled ()) {
+    //
+    // SEV-SNP guest requires that GHCB GPA must be registered before using it.
+    //
+    GhcbRegister (GhcbBasePa);
+  }
+
   AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);
 
   //
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index 89c8e9627c..e9a10146ef 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -52,6 +52,7 @@
   BaseLib
   CacheMaintenanceLib
   DebugLib
+  GhcbRegisterLib
   HobLib
   IoLib
   PciLib
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
index 9db67e17b2..7c9650ba8f 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/SecMain.c
@@ -750,6 +750,76 @@ SevEsProtocolFailure (
   CpuDeadLoop ();
 }
 
+/**
+  Determine if SEV-SNP is active. There is a MemEncryptIsSnpEnabled() in MemEncryptSevLib
+  but we can not use it because the SEV-SNP check need to be done before the
+  ProcessLibraryConstructorList() is called.
+
+  @retval TRUE   SEV-SNP is enabled
+  @retval FALSE  SEV-SNP is not enabled
+
+**/
+STATIC
+BOOLEAN
+SevSnpIsEnabled (
+  VOID
+  )
+{
+  SEC_SEV_ES_WORK_AREA  *SevEsWorkArea;
+
+  SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *) FixedPcdGet32 (PcdSevEsWorkAreaBase);
+
+  return ((SevEsWorkArea != NULL) && (SevEsWorkArea->SevSnpEnabled != 0));
+}
+
+/**
+ The GHCB GPA registeration need to be done before the ProcessLibraryConstructorList()
+ is called. So use a local implementation instead of including the GhcbRegisterLib.
+
+ */
+STATIC
+VOID
+SevSnpGhcbRegister (
+  UINTN   Address
+  )
+{
+  MSR_SEV_ES_GHCB_REGISTER  Msr;
+  MSR_SEV_ES_GHCB_REGISTER  CurrentMsr;
+  EFI_PHYSICAL_ADDRESS      GuestFrameNumber;
+
+  GuestFrameNumber = Address >> EFI_PAGE_SHIFT;
+
+  //
+  // Save the current MSR Value
+  //
+  CurrentMsr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+
+  //
+  // Use the GHCB MSR Protocol to request to register the GPA.
+  //
+  Msr.GhcbPhysicalAddress = 0;
+  Msr.GhcbGpaRegister.Function = GHCB_INFO_GHCB_GPA_REGISTER_REQUEST;
+  Msr.GhcbGpaRegister.GuestFrameNumber = GuestFrameNumber;
+  AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);
+
+  AsmVmgExit ();
+
+  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+
+  //
+  // If hypervisor responded with a different GPA than requested then fail.
+  //
+  if ((Msr.GhcbGpaRegister.Function != GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE) ||
+      (Msr.GhcbGpaRegister.GuestFrameNumber != GuestFrameNumber)) {
+    SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL);
+  }
+
+  //
+  // Restore the MSR
+  //
+  AsmWriteMsr64 (MSR_SEV_ES_GHCB, CurrentMsr.GhcbPhysicalAddress);
+}
+
 /**
   Validate the SEV-ES/GHCB protocol level.
 
@@ -791,6 +861,12 @@ SevEsProtocolCheck (
     SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL);
   }
 
+  if (SevSnpIsEnabled ()) {
+    //
+    // SEV-SNP guest requires that GHCB GPA must be registered before using it.
+    //
+    SevSnpGhcbRegister (FixedPcdGet32 (PcdOvmfSecGhcbBase));
+  }
   //
   // SEV-ES protocol checking succeeded, set the initial GHCB address
   //
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 20/28] UefiCpuPkg/MpLib: add support to register GHCB GPA when SEV-SNP is enabled
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (18 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 19/28] OvmfPkg: register GHCB gpa for the SEV-SNP guest Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 21/28] OvmfPkg/MemEncryptSevLib: Add support to validate system RAM Brijesh Singh
                   ` (8 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

An SEV-SNP guest requires that the physical address of the GHCB must
be registered with the hypervisor before using it. See the GHCB
specification for the futher detail.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf |  1 +
 UefiCpuPkg/Library/MpInitLib/MpEqu.inc        |  1 +
 UefiCpuPkg/Library/MpInitLib/MpLib.c          |  2 +
 UefiCpuPkg/Library/MpInitLib/MpLib.h          |  2 +
 UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf |  1 +
 UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 51 ++++++++++++++++++++
 6 files changed, 58 insertions(+)

diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
index d34419c2a5..48d7dfa445 100644
--- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
+++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
@@ -76,3 +76,4 @@
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase                       ## SOMETIMES_CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard                      ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase                           ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdSevSnpIsEnabled                         ## CONSUMES
diff --git a/UefiCpuPkg/Library/MpInitLib/MpEqu.inc b/UefiCpuPkg/Library/MpInitLib/MpEqu.inc
index 2e9368a374..01668638f2 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpEqu.inc
+++ b/UefiCpuPkg/Library/MpInitLib/MpEqu.inc
@@ -92,6 +92,7 @@ struc MP_CPU_EXCHANGE_INFO
   .ModeHighSegment:              CTYPE_UINT16 1
   .Enable5LevelPaging:           CTYPE_BOOLEAN 1
   .SevEsIsEnabled:               CTYPE_BOOLEAN 1
+  .SevSnpIsEnabled               CTYPE_BOOLEAN 1
   .GhcbBase:                     CTYPE_UINTN 1
 endstruc
 
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c
index 3d945972a0..c5a5da3984 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c
@@ -1040,6 +1040,7 @@ FillExchangeInfoData (
   DEBUG ((DEBUG_INFO, "%a: 5-Level Paging = %d\n", gEfiCallerBaseName, ExchangeInfo->Enable5LevelPaging));
 
   ExchangeInfo->SevEsIsEnabled  = CpuMpData->SevEsIsEnabled;
+  ExchangeInfo->SevSnpIsEnabled  = CpuMpData->SevSnpIsEnabled;
   ExchangeInfo->GhcbBase        = (UINTN) CpuMpData->GhcbBase;
 
   //
@@ -2016,6 +2017,7 @@ MpInitLibInitialize (
   CpuMpData->CpuInfoInHob     = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber);
   InitializeSpinLock(&CpuMpData->MpLock);
   CpuMpData->SevEsIsEnabled = PcdGetBool (PcdSevEsIsEnabled);
+  CpuMpData->SevSnpIsEnabled = PcdGetBool (PcdSevSnpIsEnabled);
   CpuMpData->SevEsAPBuffer  = (UINTN) -1;
   CpuMpData->GhcbBase       = PcdGet64 (PcdGhcbBase);
 
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h
index e88a5355c9..4abaa2243d 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -218,6 +218,7 @@ typedef struct {
   //
   BOOLEAN               Enable5LevelPaging;
   BOOLEAN               SevEsIsEnabled;
+  BOOLEAN               SevSnpIsEnabled;
   UINTN                 GhcbBase;
 } MP_CPU_EXCHANGE_INFO;
 
@@ -287,6 +288,7 @@ struct _CPU_MP_DATA {
   BOOLEAN                        WakeUpByInitSipiSipi;
 
   BOOLEAN                        SevEsIsEnabled;
+  BOOLEAN                        SevSnpIsEnabled;
   UINTN                          SevEsAPBuffer;
   UINTN                          SevEsAPResetStackStart;
   CPU_MP_DATA                    *NewCpuMpData;
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
index 36fcb96b58..ab8279df59 100644
--- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
+++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
@@ -65,6 +65,7 @@
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled                      ## CONSUMES
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase                   ## SOMETIMES_CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase                       ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdSevSnpIsEnabled                     ## CONSUMES
 
 [Ppis]
   gEdkiiPeiShadowMicrocodePpiGuid        ## SOMETIMES_CONSUMES
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
index 50df802d1f..19939c093d 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
@@ -194,9 +194,60 @@ LongModeStart:
     mov        rdx, rax
     shr        rdx, 32
     mov        rcx, 0xc0010130
+
+    ;
+    ; Register GHCB GPA when SEV-SNP is enabled
+    ;
+    lea        edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevSnpIsEnabled)]
+    cmp        byte [edi], 1        ; SevSnpIsEnabled
+    jne        SetGhcbAddress
+
+    ; Save the rdi and rsi to used for later comparison
+    push       rdi
+    push       rsi
+    mov        edi, eax
+    mov        esi, edx
+    or         eax, 18              ; Ghcb registration request
+    wrmsr
+    rep vmmcall
+    rdmsr
+    mov        r12, rax
+    and        r12, 0fffh
+    cmp        r12, 19              ; Ghcb registration response
+    jne        GhcbGpaRegisterFailure
+
+    ; Verify that GPA is not changed
+    and        eax, 0fffff000h
+    cmp        edi, eax
+    jne        GhcbGpaRegisterFailure
+    cmp        esi, edx
+    jne        GhcbGpaRegisterFailure
+    pop        rsi
+    pop        rdi
+
+    ;
+    ; Program GHCB
+    ;
+SetGhcbAddress:
     wrmsr
     jmp        CProcedureInvoke
 
+    ;
+    ; Request the guest termination
+    ;
+GhcbGpaRegisterFailure:
+    xor        edx, edx
+    mov        eax, 256             ; GHCB terminate
+    wrmsr
+    rep vmmcall
+
+    ; We should not return from the above terminate request, but if we do
+    ; then enter into the hlt loop.
+DoHltLoop:
+    cli
+    hlt
+    jmp        DoHltLoop
+
 GetApicId:
     lea        edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)]
     cmp        byte [edi], 1        ; SevEsIsEnabled
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 21/28] OvmfPkg/MemEncryptSevLib: Add support to validate system RAM
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (19 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 20/28] UefiCpuPkg/MpLib: add support to register GHCB GPA when SEV-SNP is enabled Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-03 14:04   ` Erdem Aktas
  2021-04-30 11:51 ` [PATCH RFC v2 22/28] OvmfPkg/BaseMemEncryptSevLib: Skip the pre-validated " Brijesh Singh
                   ` (7 subsequent siblings)
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

Many of the integrity guarantees of SEV-SNP are enforced through the
Reverse Map Table (RMP). Each RMP entry contains the GPA at which a
particular page of DRAM should be mapped. The guest can request the
hypervisor to add pages in the RMP table via the Page State Change VMGEXIT
defined in the GHCB specification section 2.5.1 and 4.1.6. Inside each RMP
entry is a Validated flag; this flag is automatically cleared to 0 by the
CPU hardware when a new RMP entry is created for a guest. Each VM page
can be either validated or invalidated, as indicated by the Validated
flag in the RMP entry. Memory access to a private page that is not
validated generates a #VC. A VM can use the PVALIDATE instruction to
validate the private page before using it.

During the guest creation, the boot ROM memory is pre-validated by the
AMD-SEV firmware. The MemEncryptSevSnpValidateSystemRam() can be called
during the SEC and PEI phase to validate the detected system RAM.

One of the fields in the Page State Change NAE is the RMP page size. The
page size input parameter indicates that either a 4KB or 2MB page should
be used while adding the RMP entry. During the validation, when possible,
the MemEncryptSevSnpValidateSystemRam() will use the 2MB entry. A
hypervisor backing the memory may choose to use the different page size
in the RMP entry. In those cases, the PVALIDATE instruction should return
SIZEMISMATCH. If a SIZEMISMATCH is detected, then validate all 512-pages
constituting a 2MB region.

Upon completion, the PVALIDATE instruction sets the rFLAGS.CF to 0 if
instruction changed the RMP entry and to 1 if the instruction did not
change the RMP entry. The rFlags.CF will be 1 only when a memory region
is already validated. We should not double validate a memory
as it could lead to a security compromise. If double validation is
detected, terminate the boot.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/Include/Library/MemEncryptSevLib.h                            |  14 ++
 OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf          |   2 +
 OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c          |  17 ++
 OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf          |   3 +
 OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf          |   3 +
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/DxeSnpSystemRamValidate.c    |  40 +++
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c    |  36 +++
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c    |  36 +++
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChange.h         |  31 +++
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c | 261 ++++++++++++++++++++
 OvmfPkg/OvmfPkgIa32.dsc                                               |   1 +
 OvmfPkg/OvmfPkgIa32X64.dsc                                            |   1 +
 12 files changed, 445 insertions(+)

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index 42caa6497b..c4e89abe0d 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -237,4 +237,18 @@ MemEncryptSevClearMmioPageEncMask (
   IN UINTN                    NumPages
   );
 
+/**
+  Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.
+
+  @param[in]  BaseAddress             Base address
+  @param[in]  NumPages                Number of pages starting from the base address
+
+**/
+VOID
+EFIAPI
+MemEncryptSevSnpPreValidateSystemRam (
+  IN PHYSICAL_ADDRESS           BaseAddress,
+  IN UINTN                      NumPages
+  );
+
 #endif // _MEM_ENCRYPT_SEV_LIB_H_
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
index f2e162d680..2158e1cba3 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
@@ -34,8 +34,10 @@
   PeiDxeMemEncryptSevLibInternal.c
 
 [Sources.X64]
+  X64/DxeSnpSystemRamValidate.c
   X64/MemEncryptSevLib.c
   X64/PeiDxeVirtualMemory.c
+  X64/SnpPageStateChangeInternal.c
   X64/VirtualMemory.c
   X64/VirtualMemory.h
 
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
index 34e7c59e2c..2ca3a400bd 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
@@ -136,3 +136,20 @@ MemEncryptSevClearMmioPageEncMask (
   //
   return RETURN_UNSUPPORTED;
 }
+
+/**
+  Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.
+
+  @param[in]  BaseAddress             Base address
+  @param[in]  NumPages                Number of pages starting from the base address
+
+**/
+VOID
+EFIAPI
+MemEncryptSevSnpPreValidateSystemRam (
+  IN PHYSICAL_ADDRESS           BaseAddress,
+  IN UINTN                      NumPages
+  )
+{
+  ASSERT (FALSE);
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
index 03a78c32df..0402e49a10 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
@@ -36,6 +36,8 @@
 [Sources.X64]
   X64/MemEncryptSevLib.c
   X64/PeiDxeVirtualMemory.c
+  X64/PeiSnpSystemRamValidate.c
+  X64/SnpPageStateChangeInternal.c
   X64/VirtualMemory.c
   X64/VirtualMemory.h
 
@@ -49,6 +51,7 @@
   DebugLib
   MemoryAllocationLib
   PcdLib
+  VmgExitLib
 
 [FeaturePcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
index 279c38bfbc..939af0a91e 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
@@ -35,6 +35,8 @@
 [Sources.X64]
   X64/MemEncryptSevLib.c
   X64/SecVirtualMemory.c
+  X64/SecSnpSystemRamValidate.c
+  X64/SnpPageStateChangeInternal.c
   X64/VirtualMemory.c
   X64/VirtualMemory.h
 
@@ -46,6 +48,7 @@
   CpuLib
   DebugLib
   PcdLib
+  VmgExitLib
 
 [FixedPcd]
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/DxeSnpSystemRamValidate.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/DxeSnpSystemRamValidate.c
new file mode 100644
index 0000000000..d46a8408f8
--- /dev/null
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/DxeSnpSystemRamValidate.c
@@ -0,0 +1,40 @@
+/** @file
+
+  SEV-SNP Page Validation functions.
+
+  Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemEncryptSevLib.h>
+
+#include "SnpPageStateChange.h"
+
+/**
+  Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.
+
+  @param[in]  BaseAddress             Base address
+  @param[in]  NumPages                Number of pages starting from the base address
+
+**/
+VOID
+EFIAPI
+MemEncryptSevSnpPreValidateSystemRam (
+  IN PHYSICAL_ADDRESS                   BaseAddress,
+  IN UINTN                              NumPages
+  )
+{
+  if (!MemEncryptSevSnpIsEnabled ()) {
+    return;
+  }
+
+  //
+  // All the pre-validation must be completed in the PEI phase.
+  //
+  ASSERT (FALSE);
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
new file mode 100644
index 0000000000..ba673d193b
--- /dev/null
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
@@ -0,0 +1,36 @@
+/** @file
+
+  SEV-SNP Page Validation functions.
+
+  Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/MemEncryptSevLib.h>
+
+#include "SnpPageStateChange.h"
+
+/**
+  Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.
+
+  @param[in]  BaseAddress             Base address
+  @param[in]  NumPages                Number of pages starting from the base address
+
+**/
+VOID
+EFIAPI
+MemEncryptSevSnpPreValidateSystemRam (
+  IN PHYSICAL_ADDRESS                   BaseAddress,
+  IN UINTN                              NumPages
+  )
+{
+  if (!MemEncryptSevSnpIsEnabled ()) {
+    return;
+  }
+
+  InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c
new file mode 100644
index 0000000000..ba673d193b
--- /dev/null
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c
@@ -0,0 +1,36 @@
+/** @file
+
+  SEV-SNP Page Validation functions.
+
+  Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/MemEncryptSevLib.h>
+
+#include "SnpPageStateChange.h"
+
+/**
+  Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.
+
+  @param[in]  BaseAddress             Base address
+  @param[in]  NumPages                Number of pages starting from the base address
+
+**/
+VOID
+EFIAPI
+MemEncryptSevSnpPreValidateSystemRam (
+  IN PHYSICAL_ADDRESS                   BaseAddress,
+  IN UINTN                              NumPages
+  )
+{
+  if (!MemEncryptSevSnpIsEnabled ()) {
+    return;
+  }
+
+  InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChange.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChange.h
new file mode 100644
index 0000000000..0dd90d4a16
--- /dev/null
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChange.h
@@ -0,0 +1,31 @@
+/** @file
+
+  SEV-SNP Page Validation functions.
+
+  Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SNP_PAGE_STATE_INTERNAL_H_
+#define SNP_PAGE_STATE_INTERNAL_H_
+
+//
+// SEV-SNP Page states
+//
+typedef enum {
+  SevSnpPagePrivate,
+  SevSnpPageShared,
+
+} SEV_SNP_PAGE_STATE;
+
+VOID
+InternalSetPageState (
+  IN EFI_PHYSICAL_ADDRESS             BaseAddress,
+  IN UINTN                            NumPages,
+  IN SEV_SNP_PAGE_STATE               State,
+  IN BOOLEAN                          UseLargeEntry
+  );
+
+#endif
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c
new file mode 100644
index 0000000000..182f6040ec
--- /dev/null
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c
@@ -0,0 +1,261 @@
+/** @file
+
+  SEV-SNP Page Validation functions.
+
+  Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/DebugLib.h>
+#include <Library/VmgExitLib.h>
+
+#include <Register/Amd/Ghcb.h>
+#include <Register/Amd/Msr.h>
+
+#include "SnpPageStateChange.h"
+
+#define IS_ALIGNED(x, y)        ((((x) & (y - 1)) == 0))
+#define PAGES_PER_LARGE_ENTRY   512
+
+STATIC
+UINTN
+MemoryStateToGhcbOp (
+  IN SEV_SNP_PAGE_STATE   State
+  )
+{
+  UINTN Cmd;
+
+  switch (State) {
+    case SevSnpPageShared: Cmd = SNP_PAGE_STATE_SHARED; break;
+    case SevSnpPagePrivate: Cmd = SNP_PAGE_STATE_PRIVATE; break;
+    default: ASSERT(0);
+  }
+
+  return Cmd;
+}
+
+STATIC
+VOID
+SnpPageStateFailureTerminate (
+  VOID
+  )
+{
+  MSR_SEV_ES_GHCB_REGISTER  Msr;
+
+  //
+  // Use the GHCB MSR Protocol to request termination by the hypervisor
+  //
+  Msr.GhcbPhysicalAddress = 0;
+  Msr.GhcbTerminate.Function = GHCB_INFO_TERMINATE_REQUEST;
+  Msr.GhcbTerminate.ReasonCodeSet = GHCB_TERMINATE_GHCB;
+  Msr.GhcbTerminate.ReasonCode = GHCB_TERMINATE_GHCB_GENERAL;
+  AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);
+
+  AsmVmgExit ();
+
+  ASSERT (FALSE);
+  CpuDeadLoop ();
+}
+
+STATIC
+UINTN
+IssuePvalidate (
+  IN    UINTN       Address,
+  IN    UINTN       RmpPageSize,
+  IN    BOOLEAN     Validate
+  )
+{
+  IA32_EFLAGS32         EFlags;
+  UINTN                 Ret;
+
+  Ret = AsmPvalidate (RmpPageSize, Validate, Address, &EFlags);
+
+  //
+  // Check the rFlags.CF to verify that PVALIDATE updated the RMP entry.
+  // If there was a no change in the RMP entry then we are either double
+  // validating or invalidating the memory. This can lead to a security compromise.
+  //
+  if (EFlags.Bits.CF) {
+    DEBUG ((
+      DEBUG_ERROR, "%a:%a: Double %a detected for address 0x%Lx\n",
+      gEfiCallerBaseName,
+      __FUNCTION__,
+      Validate ? "Validate" : "Invalidate",
+      Address
+      ));
+    SnpPageStateFailureTerminate ();
+  }
+
+  return Ret;
+}
+
+/**
+ This function issues the PVALIDATE instruction to validate or invalidate the memory
+ range specified. If PVALIDATE returns size mismatch then it retry validating with
+ smaller page size.
+
+ */
+STATIC
+VOID
+PvalidateRange (
+  IN  SNP_PAGE_STATE_CHANGE_INFO    *Info,
+  IN  UINTN                         StartIndex,
+  IN  UINTN                         EndIndex,
+  IN  BOOLEAN                       Validate
+  )
+{
+  UINTN         Address, RmpPageSize, Ret, i;
+
+  for (; StartIndex < EndIndex; StartIndex++) {
+    //
+    // Get the address and the page size from the Info.
+    //
+    Address = Info->Entry[StartIndex].GuestFrameNumber << EFI_PAGE_SHIFT;
+    RmpPageSize = Info->Entry[StartIndex].PageSize;
+
+    Ret = IssuePvalidate (Address, RmpPageSize, Validate);
+
+    //
+    // If we fail to validate due to size mismatch then try with the
+    // smaller page size. This senario will occur if the backing page in
+    // the RMP entry is 4K and we are validating it as a 2MB.
+    //
+    if ((Ret == PvalidateRetFailSizemismatch) && (RmpPageSize == PvalidatePageSize2MB)) {
+      for (i = 0; i < PAGES_PER_LARGE_ENTRY; i++) {
+        Ret = IssuePvalidate (Address, PvalidatePageSize4K, Validate);
+        if (Ret) {
+          break;
+        }
+
+        Address = Address + EFI_PAGE_SIZE;
+      }
+    }
+
+    //
+    // If validation failed then do not continue.
+    //
+    if (Ret) {
+      DEBUG ((
+        DEBUG_ERROR, "%a:%a: Failed to %a address 0x%Lx Error code %d\n",
+        gEfiCallerBaseName,
+        __FUNCTION__,
+        Validate ? "Validate" : "Invalidate",
+        Address,
+        Ret
+        ));
+      SnpPageStateFailureTerminate ();
+    }
+  }
+}
+
+/**
+ The function is used to set the page state when SEV-SNP is active. The page state
+ transition consist of changing the page ownership in the RMP table, and using the
+ PVALIDATE instruction to update the Validated bit in RMP table.
+
+ When the UseLargeEntry is set to TRUE, then function will try to use the large RMP
+ entry (whevever possible).
+ */
+VOID
+InternalSetPageState (
+  IN EFI_PHYSICAL_ADDRESS             BaseAddress,
+  IN UINTN                            NumPages,
+  IN SEV_SNP_PAGE_STATE               State,
+  IN BOOLEAN                          UseLargeEntry
+  )
+{
+  EFI_STATUS                      Status;
+  GHCB                            *Ghcb;
+  EFI_PHYSICAL_ADDRESS            NextAddress, EndAddress;
+  MSR_SEV_ES_GHCB_REGISTER        Msr;
+  BOOLEAN                         InterruptState;
+  SNP_PAGE_STATE_CHANGE_INFO      *Info;
+  UINTN                           i, RmpPageSize;
+
+  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+  Ghcb = Msr.Ghcb;
+
+  EndAddress = BaseAddress + EFI_PAGES_TO_SIZE (NumPages);
+
+  DEBUG ((
+    DEBUG_VERBOSE, "%a:%a Address 0x%Lx - 0x%Lx State = %a LargeEntry = %d\n",
+    gEfiCallerBaseName,
+    __FUNCTION__,
+    BaseAddress,
+    EndAddress,
+    State == SevSnpPageShared ? "Shared" : "Private",
+    UseLargeEntry
+    ));
+
+  for (; BaseAddress < EndAddress; BaseAddress = NextAddress) {
+    //
+    // Initialize the GHCB and setup scratch sw to point to shared buffer.
+    //
+    VmgInit (Ghcb, &InterruptState);
+    Info = (SNP_PAGE_STATE_CHANGE_INFO *) Ghcb->SharedBuffer;
+
+    SetMem (Info, sizeof (*Info), 0);
+
+    //
+    // Build page state change buffer
+    //
+    for (i = 0; (EndAddress > BaseAddress) && i < SNP_PAGE_STATE_MAX_ENTRY;
+        BaseAddress = NextAddress, i++) {
+      //
+      // Is this a 2MB aligned page? Check if we can use the Large RMP entry.
+      //
+      if (UseLargeEntry && IS_ALIGNED (BaseAddress, SIZE_2MB) &&
+        ((EndAddress - BaseAddress) >= SIZE_2MB)) {
+        RmpPageSize = PvalidatePageSize2MB;
+        NextAddress = BaseAddress + SIZE_2MB;
+      } else {
+        RmpPageSize = PvalidatePageSize4K;
+        NextAddress = BaseAddress + EFI_PAGE_SIZE;
+      }
+
+      Info->Entry[i].GuestFrameNumber = BaseAddress >> EFI_PAGE_SHIFT;
+      Info->Entry[i].PageSize = RmpPageSize;
+      Info->Entry[i].Op = MemoryStateToGhcbOp (State);
+      Info->Entry[i].CurrentPage = 0;
+    }
+
+    Info->Header.CurrentEntry = 0;
+    Info->Header.EndEntry = i - 1;
+
+    //
+    // If the request page state change is shared then invalidate the pages before
+    // adding the page in the RMP table.
+    //
+    if (State == SevSnpPageShared) {
+      PvalidateRange (Info, 0, i, FALSE);
+    }
+
+    //
+    // Issue the VMGEXIT and retry if hypervisor failed to process all the entries.
+    //
+    Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;
+    VmgSetOffsetValid (Ghcb, GhcbSwScratch);
+    while (Info->Header.CurrentEntry <= Info->Header.EndEntry) {
+      Status = VmgExit (Ghcb, SVM_EXIT_SNP_PAGE_STATE_CHANGE, 0, 0);
+      if (EFI_ERROR (Status)) {
+        SnpPageStateFailureTerminate ();
+      }
+    }
+
+    //
+    // If the request page state change is shared then invalidate the pages before
+    // adding the page in the RMP table.
+    //
+    if (State == SevSnpPagePrivate) {
+      PvalidateRange (Info, 0, i, TRUE);
+    }
+
+    VmgDone (Ghcb, InterruptState);
+  }
+}
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index f9355172d6..1c1e911bd0 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -267,6 +267,7 @@
 !else
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
+  MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
 
 [LibraryClasses.common.PEI_CORE]
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 3f27d7b90d..804f5d62be 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -271,6 +271,7 @@
 !else
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
+  MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
 
 [LibraryClasses.common.PEI_CORE]
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 22/28] OvmfPkg/BaseMemEncryptSevLib: Skip the pre-validated system RAM
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (20 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 21/28] OvmfPkg/MemEncryptSevLib: Add support to validate system RAM Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 23/28] OvmfPkg/MemEncryptSevLib: Add support to validate > 4GB memory in PEI phase Brijesh Singh
                   ` (6 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

The MemEncryptSevSnpPreValidateSystemRam() is used for pre-validating the
system RAM. As the boot progress, each phase validates a fixed region of
the RAM. In the PEI phase, the PlatformPei detects all the available RAM
and calls to pre-validate the detected system RAM.

While validating the system RAM in PEI phase, we must skip previously
validated system RAM to avoid the double validation.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf       |  2 +
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c | 65 +++++++++++++++++++-
 2 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
index 0402e49a10..f4058911e7 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
@@ -58,3 +58,5 @@
 
 [FixedPcd]
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedEnd
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedStart
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
index ba673d193b..1fc3337f7c 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
@@ -14,6 +14,44 @@
 
 #include "SnpPageStateChange.h"
 
+typedef struct {
+  UINT64    StartAddress;
+  UINT64    EndAddress;
+} SNP_PRE_VALIDATED_RANGE;
+
+STATIC SNP_PRE_VALIDATED_RANGE mPreValidatedRange[] = {
+  // This range is pre-validated by the Hypervisor.
+  {
+    FixedPcdGet32 (PcdOvmfSnpHypervisorPreValidatedStart),
+    FixedPcdGet32 (PcdOvmfSnpHypervisorPreValidatedEnd)
+  }
+};
+
+STATIC
+BOOLEAN
+DetectPreValidatedOverLap (
+  IN    PHYSICAL_ADDRESS            StartAddress,
+  IN    PHYSICAL_ADDRESS            EndAddress,
+  OUT   SNP_PRE_VALIDATED_RANGE     *OverlapRange
+  )
+{
+  UINTN               i;
+
+  //
+  // Check if the specified address range exist in pre-validated array.
+  //
+  for (i = 0; i < ARRAY_SIZE (mPreValidatedRange); i++) {
+    if ((mPreValidatedRange[i].StartAddress < EndAddress) &&
+        (StartAddress < mPreValidatedRange[i].EndAddress)) {
+      OverlapRange->StartAddress = mPreValidatedRange[i].StartAddress;
+      OverlapRange->EndAddress = mPreValidatedRange[i].EndAddress;
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
 /**
   Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.
 
@@ -28,9 +66,34 @@ MemEncryptSevSnpPreValidateSystemRam (
   IN UINTN                              NumPages
   )
 {
+  PHYSICAL_ADDRESS          EndAddress;
+  SNP_PRE_VALIDATED_RANGE   OverlapRange;
+
   if (!MemEncryptSevSnpIsEnabled ()) {
     return;
   }
 
-  InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);
+  EndAddress = BaseAddress + EFI_PAGES_TO_SIZE (NumPages);
+
+  while (BaseAddress < EndAddress) {
+    //
+    // Check if the range overlaps with the pre-validated ranges.
+    //
+    if (DetectPreValidatedOverLap (BaseAddress, EndAddress, &OverlapRange)) {
+      // Validate the non-overlap regions.
+      if (BaseAddress < OverlapRange.StartAddress) {
+        NumPages = EFI_SIZE_TO_PAGES (OverlapRange.StartAddress - BaseAddress);
+
+        InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);
+      }
+
+      BaseAddress = OverlapRange.EndAddress;
+      continue;
+    }
+
+    // Validate the remaining pages.
+    NumPages = EFI_SIZE_TO_PAGES (EndAddress - BaseAddress);
+    InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);
+    BaseAddress = EndAddress;
+  }
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 23/28] OvmfPkg/MemEncryptSevLib: Add support to validate > 4GB memory in PEI phase
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (21 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 22/28] OvmfPkg/BaseMemEncryptSevLib: Skip the pre-validated " Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 24/28] OvmfPkg/SecMain: Pre-validate the memory used for decompressing Fv Brijesh Singh
                   ` (5 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

The initial page built during the SEC phase is used by the
MemEncryptSevSnpValidateSystemRam() for the system RAM validation. The
page validation process requires using the PVALIDATE instruction;  the
instruction accepts a virtual address of the memory region that needs
to be validated. If hardware encounters a page table walk failure (due
to page-not-present) then it raises #GP.

The initial page table built in SEC phase address up to 4GB. Add an
internal function to extend the page table to cover > 4GB. The function
builds 1GB entries in the page table for access > 4GB. This will provide
the support to call PVALIDATE instruction for the virtual address >
4GB in PEI phase.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c     | 115 ++++++++++++++++++++
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c |  22 ++++
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h           |  19 ++++
 3 files changed, 156 insertions(+)

diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
index 707db5a74a..996a319b26 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
@@ -536,6 +536,121 @@ EnableReadOnlyPageWriteProtect (
   AsmWriteCr0 (AsmReadCr0() | BIT16);
 }
 
+RETURN_STATUS
+EFIAPI
+InternalMemEncryptSevCreateIdentityMap1G (
+  IN    PHYSICAL_ADDRESS      Cr3BaseAddress,
+  IN    PHYSICAL_ADDRESS      PhysicalAddress,
+  IN    UINTN                 Length
+  )
+{
+  PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
+  PAGE_TABLE_1G_ENTRY            *PageDirectory1GEntry;
+  UINT64                         PgTableMask;
+  UINT64                         AddressEncMask;
+  BOOLEAN                        IsWpEnabled;
+  RETURN_STATUS                  Status;
+
+  //
+  // Set PageMapLevel4Entry to suppress incorrect compiler/analyzer warnings.
+  //
+  PageMapLevel4Entry = NULL;
+
+  DEBUG ((
+    DEBUG_VERBOSE,
+    "%a:%a: Cr3Base=0x%Lx Physical=0x%Lx Length=0x%Lx\n",
+    gEfiCallerBaseName,
+    __FUNCTION__,
+    Cr3BaseAddress,
+    PhysicalAddress,
+    (UINT64)Length
+    ));
+
+  if (Length == 0) {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  //
+  // Check if we have a valid memory encryption mask
+  //
+  AddressEncMask = InternalGetMemEncryptionAddressMask ();
+  if (!AddressEncMask) {
+    return RETURN_ACCESS_DENIED;
+  }
+
+  PgTableMask = AddressEncMask | EFI_PAGE_MASK;
+
+
+  //
+  // Make sure that the page table is changeable.
+  //
+  IsWpEnabled = IsReadOnlyPageWriteProtected ();
+  if (IsWpEnabled) {
+    DisableReadOnlyPageWriteProtect ();
+  }
+
+  Status = EFI_SUCCESS;
+
+  while (Length)
+  {
+    //
+    // If Cr3BaseAddress is not specified then read the current CR3
+    //
+    if (Cr3BaseAddress == 0) {
+      Cr3BaseAddress = AsmReadCr3();
+    }
+
+    PageMapLevel4Entry = (VOID*) (Cr3BaseAddress & ~PgTableMask);
+    PageMapLevel4Entry += PML4_OFFSET(PhysicalAddress);
+    if (!PageMapLevel4Entry->Bits.Present) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "%a:%a: bad PML4 for Physical=0x%Lx\n",
+        gEfiCallerBaseName,
+        __FUNCTION__,
+        PhysicalAddress
+        ));
+      Status = RETURN_NO_MAPPING;
+      goto Done;
+    }
+
+    PageDirectory1GEntry = (VOID *)(
+                             (PageMapLevel4Entry->Bits.PageTableBaseAddress <<
+                              12) & ~PgTableMask
+                             );
+    PageDirectory1GEntry += PDP_OFFSET(PhysicalAddress);
+    if (!PageDirectory1GEntry->Bits.Present) {
+      PageDirectory1GEntry->Bits.Present = 1;
+      PageDirectory1GEntry->Bits.MustBe1 = 1;
+      PageDirectory1GEntry->Bits.MustBeZero = 0;
+      PageDirectory1GEntry->Bits.ReadWrite = 1;
+      PageDirectory1GEntry->Uint64 |= (UINT64)PhysicalAddress | AddressEncMask;
+    }
+
+    if (Length <= BIT30) {
+      Length = 0;
+    } else {
+      Length -= BIT30;
+    }
+
+    PhysicalAddress += BIT30;
+  }
+
+  //
+  // Flush TLB
+  //
+  CpuFlushTlb();
+
+Done:
+  //
+  // Restore page table write protection, if any.
+  //
+  if (IsWpEnabled) {
+    EnableReadOnlyPageWriteProtect ();
+  }
+
+  return Status;
+}
 
 /**
   This function either sets or clears memory encryption bit for the memory
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
index 1fc3337f7c..ff4c0742ed 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
@@ -10,9 +10,12 @@
 
 #include <Uefi/UefiBaseType.h>
 #include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
 #include <Library/MemEncryptSevLib.h>
 
 #include "SnpPageStateChange.h"
+#include "VirtualMemory.h"
 
 typedef struct {
   UINT64    StartAddress;
@@ -68,6 +71,7 @@ MemEncryptSevSnpPreValidateSystemRam (
 {
   PHYSICAL_ADDRESS          EndAddress;
   SNP_PRE_VALIDATED_RANGE   OverlapRange;
+  EFI_STATUS                Status;
 
   if (!MemEncryptSevSnpIsEnabled ()) {
     return;
@@ -75,6 +79,24 @@ MemEncryptSevSnpPreValidateSystemRam (
 
   EndAddress = BaseAddress + EFI_PAGES_TO_SIZE (NumPages);
 
+  //
+  // The page table used in PEI can address up to 4GB memory. If we are asked to
+  // validate a range above the 4GB, then create an identity mapping so that the
+  // PVALIDATE instruction can execute correctly. If the page table entry is not
+  // present then PVALIDATE will #GP.
+  //
+  if (BaseAddress >= SIZE_4GB) {
+    Status = InternalMemEncryptSevCreateIdentityMap1G (
+                0,
+                BaseAddress,
+                EFI_PAGES_TO_SIZE (NumPages)
+                );
+    if (EFI_ERROR (Status)) {
+      ASSERT (FALSE);
+      CpuDeadLoop ();
+    }
+  }
+
   while (BaseAddress < EndAddress) {
     //
     // Check if the range overlaps with the pre-validated ranges.
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
index 832ff10a33..25de939797 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
@@ -143,4 +143,23 @@ InternalMemEncryptSevClearMmioPageEncMask (
   IN  PHYSICAL_ADDRESS        PhysicalAddress,
   IN  UINTN                   Length
   );
+
+/**
+  Create 1GB identity mapping for the specified virtual address range.
+
+  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
+                                      current CR3)
+  @param[in]  VirtualAddress          Virtual address
+  @param[in]  Length                  Length of virtual address range
+
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
+
+**/
+RETURN_STATUS
+EFIAPI
+InternalMemEncryptSevCreateIdentityMap1G (
+  IN    PHYSICAL_ADDRESS      Cr3BaseAddress,
+  IN    PHYSICAL_ADDRESS      PhysicalAddress,
+  IN    UINTN                 Length
+  );
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 24/28] OvmfPkg/SecMain: Pre-validate the memory used for decompressing Fv
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (22 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 23/28] OvmfPkg/MemEncryptSevLib: Add support to validate > 4GB memory in PEI phase Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 25/28] OvmfPkg/PlatformPei: Validate the system RAM when SNP is active Brijesh Singh
                   ` (4 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

The VMM launch sequence should have pre-validated all the data pages used
in the Reset vector. The range does not cover the data pages used during
the SEC phase (mainly PEI and DXE firmware volume decompression memory).

When SEV-SNP is active, the memory must be pre-validated before the access.
Add support to pre-validate the memory range from SnpSecPreValidatedStart
to SnpSecPreValidatedEnd. This should be sufficent to enter into the PEI
phase.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/FvmainCompactScratchEnd.fdf.inc                            |  5 ++++
 OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf       |  2 ++
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c |  5 ++++
 OvmfPkg/OvmfPkg.dec                                                |  5 ++++
 OvmfPkg/Sec/SecMain.c                                              | 27 ++++++++++++++++++++
 OvmfPkg/Sec/SecMain.inf                                            |  3 +++
 6 files changed, 47 insertions(+)

diff --git a/OvmfPkg/FvmainCompactScratchEnd.fdf.inc b/OvmfPkg/FvmainCompactScratchEnd.fdf.inc
index 46f5258329..b560fb0b8e 100644
--- a/OvmfPkg/FvmainCompactScratchEnd.fdf.inc
+++ b/OvmfPkg/FvmainCompactScratchEnd.fdf.inc
@@ -63,3 +63,8 @@ DEFINE DECOMP_SCRATCH_BASE_MASK      = 0xFFF00000
 DEFINE DECOMP_SCRATCH_BASE           = (($(DECOMP_SCRATCH_BASE_UNALIGNED) + $(DECOMP_SCRATCH_BASE_ALIGNMENT)) & $(DECOMP_SCRATCH_BASE_MASK))
 
 SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd = $(DECOMP_SCRATCH_BASE) + $(DECOMP_SCRATCH_SIZE)
+
+#
+# The range of pages that should be pre-validated during the SEC phase when SEV-SNP is active in the guest VM.
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecPreValidatedStart = $(MEMFD_BASE_ADDRESS) + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecPreValidatedEnd = $(DECOMP_SCRATCH_BASE) + $(DECOMP_SCRATCH_SIZE)
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
index f4058911e7..2b60920f4b 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
@@ -58,5 +58,7 @@
 
 [FixedPcd]
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecPreValidatedEnd
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecPreValidatedStart
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedEnd
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedStart
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
index ff4c0742ed..7d8e681acd 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
@@ -27,6 +27,11 @@ STATIC SNP_PRE_VALIDATED_RANGE mPreValidatedRange[] = {
   {
     FixedPcdGet32 (PcdOvmfSnpHypervisorPreValidatedStart),
     FixedPcdGet32 (PcdOvmfSnpHypervisorPreValidatedEnd)
+  },
+  // This range is pre-validated by the Sec/SecMain.c
+  {
+    FixedPcdGet32 (PcdOvmfSnpSecPreValidatedStart),
+    FixedPcdGet32 (PcdOvmfSnpSecPreValidatedEnd)
   }
 };
 
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 70948ab478..d1bfe49731 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -332,6 +332,11 @@
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedStart|0x0|UINT32|0x49
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedEnd|0x0|UINT32|0x50
 
+  ## The range of memory that need to be pre-validated in the SEC phase
+  #  when SEV-SNP is active in the guest VM.
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecPreValidatedStart|0|UINT32|0x51
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecPreValidatedEnd|0|UINT32|0x52
+
 [PcdsDynamic, PcdsDynamicEx]
   gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
index 7c9650ba8f..c5467465ab 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/SecMain.c
@@ -907,6 +907,26 @@ SevEsIsEnabled (
   return ((SevEsWorkArea != NULL) && (SevEsWorkArea->SevEsEnabled != 0));
 }
 
+/**
+ Pre-validate System RAM used for decompressing the PEI and DXE firmware volumes
+ when SEV-SNP is active. The PCDs SecPreValidatedStart and SecPreValidatedEnd are
+ set in OvmfPkg/FvmainCompactScratchEnd.fdf.inc.
+
+**/
+STATIC
+VOID
+SevSnpSecPreValidateSystemRam (
+  VOID
+  )
+{
+  PHYSICAL_ADDRESS        Start, End;
+
+  Start = (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfSnpSecPreValidatedStart);
+  End = (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfSnpSecPreValidatedEnd);
+
+  MemEncryptSevSnpPreValidateSystemRam (Start, EFI_SIZE_TO_PAGES (End - Start));
+}
+
 VOID
 EFIAPI
 SecCoreStartupWithStack (
@@ -1038,6 +1058,13 @@ SecCoreStartupWithStack (
   SecCoreData.BootFirmwareVolumeBase = BootFv;
   SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
 
+  if (SevSnpIsEnabled ()) {
+    //
+    // Pre-validate the System RAM used in the SEC Phase
+    //
+    SevSnpSecPreValidateSystemRam ();
+  }
+
   //
   // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
   //
diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf
index 7f78dcee27..8144b1d115 100644
--- a/OvmfPkg/Sec/SecMain.inf
+++ b/OvmfPkg/Sec/SecMain.inf
@@ -50,6 +50,7 @@
   PeCoffExtraActionLib
   ExtractGuidedSectionLib
   LocalApicLib
+  MemEncryptSevLib
   CpuExceptionHandlerLib
 
 [Ppis]
@@ -70,6 +71,8 @@
   gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd
   gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecPreValidatedStart
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecPreValidatedEnd
 
 [FeaturePcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 25/28] OvmfPkg/PlatformPei: Validate the system RAM when SNP is active
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (23 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 24/28] OvmfPkg/SecMain: Pre-validate the memory used for decompressing Fv Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 26/28] OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table Brijesh Singh
                   ` (3 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

When SEV-SNP is active, a memory region mapped encrypted in the page
table must be validated before access. There are two approaches that
can be taken to validate the system RAM detected during the PEI phase:

1) Validate on-demand
OR
2) Validate before access

On-demand
=========
If memory is not validated before access, it will cause a #VC
exception with the page-not-validated error code. The VC exception
handler can perform the validation steps.

The pages that have been validated will need to be tracked to avoid
the double validation scenarios. The range of memory that has not
been validated will need to be communicated to the OS through the
recently introduced unaccepted memory type
https://github.com/microsoft/mu_basecore/pull/66, so that OS can
validate those ranges before using them.

Validate before access
======================
Since the PEI phase detects all the available system RAM, use the
MemEncryptSevSnpValidateSystemRam() function to pre-validate the
system RAM in the PEI phase.

For now, choose option 2 due to the dependency and the complexity
of the on-demand validation.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/PlatformPei/AmdSev.c | 33 ++++++++++++++++----
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index 54b07622b4..9a20165db7 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -34,7 +34,9 @@ AmdSevSnpInitialize (
   VOID
   )
 {
-  RETURN_STATUS        PcdStatus;
+  RETURN_STATUS                 PcdStatus;
+  EFI_PEI_HOB_POINTERS          Hob;
+  EFI_HOB_RESOURCE_DESCRIPTOR   *ResourceHob;
 
   if (!MemEncryptSevSnpIsEnabled ()) {
     return;
@@ -42,6 +44,22 @@ AmdSevSnpInitialize (
 
   PcdStatus = PcdSetBoolS (PcdSevSnpIsEnabled, TRUE);
   ASSERT_RETURN_ERROR (PcdStatus);
+
+  //
+  // Iterate through the system RAM and validate it.
+  //
+  for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+    if (Hob.Raw != NULL && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+      ResourceHob = Hob.ResourceDescriptor;
+
+      if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+        MemEncryptSevSnpPreValidateSystemRam (
+          ResourceHob->PhysicalStart,
+          EFI_SIZE_TO_PAGES ((UINTN) ResourceHob->ResourceLength)
+          );
+      }
+    }
+  }
 }
 
 /**
@@ -204,6 +222,14 @@ AmdSevInitialize (
     return;
   }
 
+  //
+  // Check and perform SEV-SNP initialization if required. This need to be
+  // done before the GHCB page is made shared in the current page table. This
+  // is because the system RAM must be validated before it is made shared.
+  // The AmdSevSnpInitialize() validates the system RAM.
+  //
+  AmdSevSnpInitialize ();
+
   //
   // Set Memory Encryption Mask PCD
   //
@@ -264,9 +290,4 @@ AmdSevInitialize (
   // Check and perform SEV-ES initialization if required.
   //
   AmdSevEsInitialize ();
-
-  //
-  // Check and perform SEV-SNP initialization if required.
-  //
-  AmdSevSnpInitialize ();
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 26/28] OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (24 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 25/28] OvmfPkg/PlatformPei: Validate the system RAM when SNP is active Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 11:51 ` [PATCH RFC v2 27/28] OvmfPkg/AmdSev: Expose the SNP reserved pages through configuration table Brijesh Singh
                   ` (2 subsequent siblings)
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

The MemEncryptSev{Set,Clear}PageEncMask() functions are used to set or
clear the memory encryption attribute in the page table. When SEV-SNP
is active, we also need to change the page state in the RMP table so that
it is in sync with the memory encryption attribute change.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf   |  1 +
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 34 ++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
index 2158e1cba3..f613bb314f 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
@@ -51,6 +51,7 @@
   DebugLib
   MemoryAllocationLib
   PcdLib
+  VmgExitLib
 
 [FeaturePcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
index 996a319b26..9cca8efecb 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
@@ -17,6 +17,7 @@
 #include <Register/Cpuid.h>
 
 #include "VirtualMemory.h"
+#include "SnpPageStateChange.h"
 
 STATIC BOOLEAN mAddressEncMaskChecked = FALSE;
 STATIC UINT64  mAddressEncMask;
@@ -697,10 +698,12 @@ SetMemoryEncDec (
   PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
   PAGE_TABLE_1G_ENTRY            *PageDirectory1GEntry;
   PAGE_TABLE_ENTRY               *PageDirectory2MEntry;
+  PHYSICAL_ADDRESS               OrigPhysicalAddress;
   PAGE_TABLE_4K_ENTRY            *PageTableEntry;
   UINT64                         PgTableMask;
   UINT64                         AddressEncMask;
   BOOLEAN                        IsWpEnabled;
+  UINTN                          OrigLength;
   RETURN_STATUS                  Status;
 
   //
@@ -753,6 +756,22 @@ SetMemoryEncDec (
 
   Status = EFI_SUCCESS;
 
+  //
+  // To maintain the security gurantees we must set the page to shared in the RMP
+  // table before clearing the memory encryption mask from the current page table.
+  //
+  // The InternalSetPageState() is used for setting the page state in the RMP table.
+  //
+  if (!Mmio && (Mode == ClearCBit) && MemEncryptSevSnpIsEnabled ()) {
+    InternalSetPageState (PhysicalAddress, EFI_SIZE_TO_PAGES (Length), SevSnpPageShared, FALSE);
+  }
+
+  //
+  // Save the specified length and physical address (we need it later).
+  //
+  OrigLength = Length;
+  OrigPhysicalAddress = PhysicalAddress;
+
   while (Length != 0)
   {
     //
@@ -925,6 +944,21 @@ SetMemoryEncDec (
   //
   CpuFlushTlb();
 
+  //
+  // SEV-SNP requires that all the private pages (i.e pages mapped encrypted) must be
+  // added in the RMP table (as a private) before the access.
+  //
+  // The InternalSetPageState() is used for setting the page state in the RMP table.
+  //
+  if (!Mmio && (Mode == SetCBit) && MemEncryptSevSnpIsEnabled ()) {
+    InternalSetPageState (
+      OrigPhysicalAddress,
+      EFI_SIZE_TO_PAGES (OrigLength),
+      SevSnpPagePrivate,
+      FALSE
+      );
+  }
+
 Done:
   //
   // Restore page table write protection, if any.
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 27/28] OvmfPkg/AmdSev: Expose the SNP reserved pages through configuration table
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (25 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 26/28] OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-05-05  7:10   ` [edk2-devel] " Dov Murik
  2021-04-30 11:51 ` [PATCH RFC v2 28/28] MdePkg/GHCB: Increase the GHCB protocol max version Brijesh Singh
  2021-04-30 16:49 ` [edk2-devel] [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Laszlo Ersek
  28 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

Now that both the secrets and cpuid pages are reserved in the HOB,
extract the location details through fixed PCD and make it available
to the guest OS through the configuration table.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/AmdSev/SecretDxe/SecretDxe.c               | 21 ++++++++++++++++++++
 OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf             |  4 ++++
 OvmfPkg/Include/Guid/ConfidentialComputingSecret.h | 17 ++++++++++++++++
 OvmfPkg/OvmfPkg.dec                                |  1 +
 4 files changed, 43 insertions(+)

diff --git a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c
index 308022b5b2..08b6d9bddf 100644
--- a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c
+++ b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c
@@ -6,6 +6,7 @@
 **/
 #include <PiDxe.h>
 #include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemEncryptSevLib.h>
 #include <Guid/ConfidentialComputingSecret.h>
 
 STATIC CONFIDENTIAL_COMPUTING_SECRET_LOCATION mSecretDxeTable = {
@@ -13,6 +14,15 @@ STATIC CONFIDENTIAL_COMPUTING_SECRET_LOCATION mSecretDxeTable = {
   FixedPcdGet32 (PcdSevLaunchSecretSize),
 };
 
+STATIC CONFIDENTIAL_COMPUTING_BLOB_LOCATION mSnpBootDxeTable = {
+  0x414d4445,     // AMDE
+  1,
+  (UINT64)(UINTN) FixedPcdGet32 (PcdSevLaunchSecretBase),
+  FixedPcdGet32 (PcdSevLaunchSecretSize),
+  (UINT64)(UINTN) FixedPcdGet32 (PcdOvmfSnpCpuidBase),
+  FixedPcdGet32 (PcdOvmfSnpCpuidSize),
+};
+
 EFI_STATUS
 EFIAPI
 InitializeSecretDxe(
@@ -20,6 +30,17 @@ InitializeSecretDxe(
   IN EFI_SYSTEM_TABLE     *SystemTable
   )
 {
+  //
+  // If its SEV-SNP active guest then install the CONFIDENTIAL_COMPUTING_BLOB.
+  // It contains the location for both the Secrets and CPUID page.
+  //
+  if (MemEncryptSevSnpIsEnabled ()) {
+    return gBS->InstallConfigurationTable (
+                  &gConfidentialComputingBlobGuid,
+                  &mSnpBootDxeTable
+                  );
+  }
+
   return gBS->InstallConfigurationTable (
                 &gConfidentialComputingSecretGuid,
                 &mSecretDxeTable
diff --git a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
index 40bda7ff84..d15194b368 100644
--- a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
+++ b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
@@ -23,13 +23,17 @@
   MdePkg/MdePkg.dec
 
 [LibraryClasses]
+  MemEncryptSevLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
 
 [Guids]
   gConfidentialComputingSecretGuid
+  gConfidentialComputingBlobGuid
 
 [FixedPcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize
   gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
   gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
 
diff --git a/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h b/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
index 7026fc5b08..0d7f1b8818 100644
--- a/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
+++ b/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
@@ -18,11 +18,28 @@
     { 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47 }, \
   }
 
+#define CONFIDENTIAL_COMPUTING_BLOB_GUID                \
+  { 0x067b1f5f,                                         \
+    0xcf26,                                             \
+    0x44c5,                                             \
+    { 0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42 }, \
+  }
+
 typedef struct {
   UINT64 Base;
   UINT64 Size;
 } CONFIDENTIAL_COMPUTING_SECRET_LOCATION;
 
+typedef struct {
+  UINT32  Header;
+  UINT16  Version;
+  UINT64  SecretsPhysicalAddress;
+  UINT32  SecretsSize;
+  UINT64  CpuidPhysicalAddress;
+  UINT32  CpuidLSize;
+} CONFIDENTIAL_COMPUTING_BLOB_LOCATION;
+
 extern EFI_GUID gConfidentialComputingSecretGuid;
+extern EFI_GUID gConfidentialComputingBlobGuid;
 
 #endif // SEV_LAUNCH_SECRET_H_
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index d1bfe49731..f38c5e476a 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -126,6 +126,7 @@
   gQemuKernelLoaderFsMediaGuid          = {0x1428f772, 0xb64a, 0x441e, {0xb8, 0xc3, 0x9e, 0xbd, 0xd7, 0xf8, 0x93, 0xc7}}
   gGrubFileGuid                         = {0xb5ae312c, 0xbc8a, 0x43b1, {0x9c, 0x62, 0xeb, 0xb8, 0x26, 0xdd, 0x5d, 0x07}}
   gConfidentialComputingSecretGuid      = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}}
+  gConfidentialComputingBlobGuid        = {0x067b1f5f, 0xcf26, 0x44c5, {0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42}}
 
 [Ppis]
   # PPI whose presence in the PPI database signals that the TPM base address
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* [PATCH RFC v2 28/28] MdePkg/GHCB: Increase the GHCB protocol max version
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (26 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 27/28] OvmfPkg/AmdSev: Expose the SNP reserved pages through configuration table Brijesh Singh
@ 2021-04-30 11:51 ` Brijesh Singh
  2021-04-30 16:49 ` [edk2-devel] [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Laszlo Ersek
  28 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-04-30 11:51 UTC (permalink / raw)
  To: devel
  Cc: Brijesh Singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

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

Now that OvmfPkg supports version 2 of the GHCB specification, bump the
protocol version.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 MdePkg/Include/Register/Amd/Ghcb.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
index 1e7c0daed3..7a1b6c6d24 100644
--- a/MdePkg/Include/Register/Amd/Ghcb.h
+++ b/MdePkg/Include/Register/Amd/Ghcb.h
@@ -24,7 +24,7 @@
 #define VC_EXCEPTION 29
 
 #define GHCB_VERSION_MIN     1
-#define GHCB_VERSION_MAX     1
+#define GHCB_VERSION_MAX     2
 
 #define GHCB_STANDARD_USAGE  0
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support
  2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
                   ` (27 preceding siblings ...)
  2021-04-30 11:51 ` [PATCH RFC v2 28/28] MdePkg/GHCB: Increase the GHCB protocol max version Brijesh Singh
@ 2021-04-30 16:49 ` Laszlo Ersek
  28 siblings, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-04-30 16:49 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

Hi,

On 04/30/21 13:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
> 
> SEV-SNP builds upon existing SEV and SEV-ES functionality while adding
> new hardware-based memory protections. SEV-SNP adds strong memory integrity
> protection to help prevent malicious hypervisor-based attacks like data
> replay, memory re-mapping and more in order to create an isolated memory
> encryption environment.
>  
> This series provides the basic building blocks to support booting the SEV-SNP
> VMs, it does not cover all the security enhancement introduced by the SEV-SNP
> such as interrupt protection.

I've added this to my review queue.

Thanks
Laszlo

> 
> Many of the integrity guarantees of SEV-SNP are enforced through a new
> structure called the Reverse Map Table (RMP). Adding a new page to SEV-SNP
> VM requires a 2-step process. First, the hypervisor assigns a page to the
> guest using the new RMPUPDATE instruction. This transitions the page to
> guest-invalid. Second, the guest validates the page using the new PVALIDATE
> instruction. The SEV-SNP VMs can use the new "Page State Change Request NAE"
> defined in the GHCB specification to ask hypervisor to add or remove page
> from the RMP table.
> 
> Each page assigned to the SEV-SNP VM can either be validated or unvalidated,
> as indicated by the Validated flag in the page's RMP entry. There are two
> approaches that can be taken for the page validation: Pre-validation and
> Lazy Validation.
> 
> Under pre-validation, the pages are validated prior to first use. And under
> lazy validation, pages are validated when first accessed. An access to a
> unvalidated page results in a #VC exception, at which time the exception
> handler may validate the page. Lazy validation requires careful tracking of
> the validated pages to avoid validating the same GPA more than once. The
> recently introduced "Unaccepted" memory type can be used to communicate the
> unvalidated memory ranges to the Guest OS.
> 
> At this time we only support the pre-validation. OVMF detects all the available
> system RAM in the PEI phase. When SEV-SNP is enabled, the memory is validated
> before it is made available to the EDK2 core.
> 
> This series does not implements the following SEV-SNP features yet:
> 
> * CPUID filtering
> * AP bring up using the new SEV-SNP NAE
> * Lazy validation
> * Interrupt security
> 
> The series is based on commit:
> 01c0ab90be (origin/master, origin/HEAD, master) AzurePipelines: Add support for ArmPlatformPkg
> 
> Additional resources
> ---------------------
> SEV-SNP whitepaper
> https://www.amd.com/system/files/TechDocs/SEV-SNP-strengthening-vm-isolation-with-integrity-protection-and-more.pdf
> 
> APM 2: https://www.amd.com/system/files/TechDocs/24593.pdf (section 15.36)
> 
> The complete source is available at
> https://github.com/AMDESE/ovmf/tree/sev-snp-rfc-2
> 
> GHCB spec:
> https://developer.amd.com/wp-content/resources/56421.pdf
> 
> SEV-SNP firmware specification:
> https://developer.amd.com/sev/
> 	         
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> 
> Changes since v1:
>  * Drop the interval tree support to detect the pre-validated overlap region.
>  * Use an array to keep track of pre-validated regions.
>  * Add support to query the Hypervisor feature and verify that SNP feature is supported.
>  * Introduce MemEncryptSevClearMmioPageEncMask() to clear the C-bit from MMIO ranges.
>  * Pull the SevSecretDxe and SevSecretPei into OVMF package build.
>  * Extend the SevSecretDxe to expose confidential computing blob location through
>    EFI configuration table.
> 
> Brijesh Singh (28):
>   MdePkg: Expand the SEV MSR to include the SNP definition
>   MdePkg: Define the GHCB Hypervisor features
>   MdePkg: Define the GHCB GPA structure
>   MdePkg: Define the Page State Change VMGEXIT structures
>   MdePkg: Add AsmPvalidate() support
>   OvmfPkg/BaseMemEncryptSevLib: Introduce
>     MemEncryptSevClearMmioPageEncMask()
>   OvmfPkg: Use MemEncryptSevClearMmioPageEncMask() to clear EncMask from
>     Mmio
>   OvmfPkg/BaseMemEncryptSevLib: Remove CacheFlush parameter
>   OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase
>   OvmfPkg/MemEncryptSevLib: add MemEncryptSevSnpEnabled()
>   OvmfPkg: Reserve Secrets page in MEMFD
>   OvmfPkg: Reserve CPUID page for the SEV-SNP guest
>   OvmfPkg: Validate the data pages used in the Reset vector and SEC
>     phase
>   UefiCpuPkg: Define the SEV-SNP specific dynamic PCDs
>   OvmfPkg/MemEncryptSevLib: extend the workarea to include SNP enabled
>     field
>   OvmfPkg/MemEncryptSevLib: Extend Es Workarea to include hv features
>   OvmfPkg/ResetVector: Invalidate the GHCB page
>   OvmfPkg: Add a library to support registering GHCB GPA
>   OvmfPkg: register GHCB gpa for the SEV-SNP guest
>   UefiCpuPkg/MpLib: add support to register GHCB GPA when SEV-SNP is
>     enabled
>   OvmfPkg/MemEncryptSevLib: Add support to validate system RAM
>   OvmfPkg/BaseMemEncryptSevLib: Skip the pre-validated system RAM
>   OvmfPkg/MemEncryptSevLib: Add support to validate > 4GB memory in PEI
>     phase
>   OvmfPkg/SecMain: Pre-validate the memory used for decompressing Fv
>   OvmfPkg/PlatformPei: Validate the system RAM when SNP is active
>   OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table
>   OvmfPkg/AmdSev: Expose the SNP reserved pages through configuration
>     table
>   MdePkg/GHCB: Increase the GHCB protocol max version
> 
>  MdePkg/Include/Library/BaseLib.h              |  37 +++
>  MdePkg/Include/Register/Amd/Fam17Msr.h        |  36 ++-
>  MdePkg/Include/Register/Amd/Ghcb.h            |  37 ++-
>  MdePkg/Library/BaseLib/BaseLib.inf            |   1 +
>  MdePkg/Library/BaseLib/X64/Pvalidate.nasm     |  43 +++
>  OvmfPkg/AmdSev/SecretDxe/SecretDxe.c          |  21 ++
>  OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf        |   4 +
>  OvmfPkg/AmdSev/SecretPei/SecretPei.c          |  16 +-
>  OvmfPkg/AmdSev/SecretPei/SecretPei.inf        |   1 +
>  OvmfPkg/AmdSevDxe/AmdSevDxe.c                 |  13 +-
>  OvmfPkg/FvmainCompactScratchEnd.fdf.inc       |   5 +
>  .../Guid/ConfidentialComputingSecret.h        |  17 ++
>  OvmfPkg/Include/Library/GhcbRegisterLib.h     |  27 ++
>  OvmfPkg/Include/Library/MemEncryptSevLib.h    |  66 ++++-
>  OvmfPkg/IoMmuDxe/AmdSevIoMmu.c                |   6 +-
>  .../DxeMemEncryptSevLib.inf                   |   3 +
>  .../DxeMemEncryptSevLibInternal.c             |  27 ++
>  .../Ia32/MemEncryptSevLib.c                   |  58 +++-
>  .../PeiMemEncryptSevLib.inf                   |   7 +
>  .../PeiMemEncryptSevLibInternal.c             |  27 ++
>  .../SecMemEncryptSevLib.inf                   |   3 +
>  .../SecMemEncryptSevLibInternal.c             |  19 ++
>  .../X64/DxeSnpSystemRamValidate.c             |  40 +++
>  .../X64/MemEncryptSevLib.c                    |  49 +++-
>  .../X64/PeiDxeVirtualMemory.c                 | 203 +++++++++++++-
>  .../X64/PeiSnpSystemRamValidate.c             | 126 +++++++++
>  .../X64/SecSnpSystemRamValidate.c             |  36 +++
>  .../X64/SecVirtualMemory.c                    |   8 +-
>  .../X64/SnpPageStateChange.h                  |  31 +++
>  .../X64/SnpPageStateChangeInternal.c          | 261 ++++++++++++++++++
>  .../BaseMemEncryptSevLib/X64/VirtualMemory.h  |  52 +++-
>  .../Library/GhcbRegisterLib/GhcbRegisterLib.c |  97 +++++++
>  .../GhcbRegisterLib/GhcbRegisterLib.inf       |  33 +++
>  .../SmmCpuFeaturesLib/SmmCpuFeaturesLib.c     |   3 +-
>  OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf  |   4 +
>  OvmfPkg/Library/VmgExitLib/VmgExitLib.inf     |   7 +
>  OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c |  45 +++
>  OvmfPkg/OvmfPkg.dec                           |  21 ++
>  OvmfPkg/OvmfPkgIa32.dsc                       |   2 +
>  OvmfPkg/OvmfPkgIa32X64.dsc                    |   2 +
>  OvmfPkg/OvmfPkgX64.dsc                        |   3 +
>  OvmfPkg/OvmfPkgX64.fdf                        |  17 +-
>  OvmfPkg/PlatformPei/AmdSev.c                  |  84 +++++-
>  OvmfPkg/PlatformPei/MemDetect.c               |  13 +
>  OvmfPkg/PlatformPei/PlatformPei.inf           |   5 +
>  .../FwBlockServiceDxe.c                       |   5 +-
>  .../QemuFlashSmm.c                            |   5 +-
>  OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm  |  23 ++
>  OvmfPkg/ResetVector/Ia32/PageTables64.asm     | 216 +++++++++++++++
>  OvmfPkg/ResetVector/ResetVector.inf           |   4 +
>  OvmfPkg/ResetVector/ResetVector.nasmb         |   6 +
>  OvmfPkg/Sec/SecMain.c                         | 103 +++++++
>  OvmfPkg/Sec/SecMain.inf                       |   3 +
>  UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf |   1 +
>  UefiCpuPkg/Library/MpInitLib/MpEqu.inc        |   1 +
>  UefiCpuPkg/Library/MpInitLib/MpLib.c          |   2 +
>  UefiCpuPkg/Library/MpInitLib/MpLib.h          |   2 +
>  UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf |   1 +
>  UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm |  51 ++++
>  UefiCpuPkg/UefiCpuPkg.dec                     |  11 +
>  60 files changed, 1970 insertions(+), 80 deletions(-)
>  create mode 100644 MdePkg/Library/BaseLib/X64/Pvalidate.nasm
>  create mode 100644 OvmfPkg/Include/Library/GhcbRegisterLib.h
>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/DxeSnpSystemRamValidate.c
>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c
>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChange.h
>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c
>  create mode 100644 OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.c
>  create mode 100644 OvmfPkg/Library/GhcbRegisterLib/GhcbRegisterLib.inf
> 


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 01/28] MdePkg: Expand the SEV MSR to include the SNP definition
  2021-04-30 11:51 ` [PATCH RFC v2 01/28] MdePkg: Expand the SEV MSR to include the SNP definition Brijesh Singh
@ 2021-05-03  8:39   ` Laszlo Ersek
  2021-05-03 11:42     ` Brijesh Singh
  0 siblings, 1 reply; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-03  8:39 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 04/30/21 13:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
> 
> Define the SEV-SNP MSR bits.
> 
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  MdePkg/Include/Register/Amd/Fam17Msr.h | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
> index e4db09c518..4d33bef220 100644
> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
> @@ -87,7 +87,12 @@ typedef union {
>      ///
>      UINT32  SevEsBit:1;
>  
> -    UINT32  Reserved:30;
> +    ///
> +    /// [Bit 2] Secure Nested Paging (SevSnp) is enabled
> +    ///
> +    UINT32  SevSnpBit:1;
> +
> +    UINT32  Reserved:29;
>    } Bits;
>    ///
>    /// All bit fields as a 32-bit value
> 

(1) When changing a Reserved field's meaning, the field should be
renamed. Usually we do this by numbering, and the numbers only ever
increase. This is because code might exist that uses a Reserved field.
Such code should be prevented from compiling, because that's much better
than silently breaking its behavior. So the new name of the field should
be Reserved2.

(If we modify Reserved2 later, it should be renamed to Reserved3, and so
on -- we should never return to a field name used before.)

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 02/28] MdePkg: Define the GHCB Hypervisor features
  2021-04-30 11:51 ` [PATCH RFC v2 02/28] MdePkg: Define the GHCB Hypervisor features Brijesh Singh
@ 2021-05-03 10:10   ` Laszlo Ersek
  2021-05-03 12:20     ` Brijesh Singh
  0 siblings, 1 reply; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-03 10:10 UTC (permalink / raw)
  To: brijesh.singh, Tom Lendacky
  Cc: devel, James Bottomley, Min Xu, Jiewen Yao, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

Hi Brijesh, Tom,

On 04/30/21 13:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
> 
> Version 2 of GHCB introduces advertisement of features that are supported
> by the hypervisor. See the GHCB spec section 2.2 for an additional details.
> 
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  MdePkg/Include/Register/Amd/Fam17Msr.h | 7 +++++++
>  MdePkg/Include/Register/Amd/Ghcb.h     | 6 ++++++
>  2 files changed, 13 insertions(+)
> 
> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
> index 4d33bef220..a65d51ab12 100644
> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
> @@ -48,6 +48,11 @@ typedef union {
>      UINT32  Reserved2:32;
>    } GhcbTerminate;
>  
> +  struct {
> +    UINT64  Function:12;
> +    UINT64  Features:52;
> +  } GhcbHypervisorFeatures;
> +
>    VOID    *Ghcb;
>  
>    UINT64  GhcbPhysicalAddress;
> @@ -57,6 +62,8 @@ typedef union {
>  #define GHCB_INFO_SEV_INFO_GET             2
>  #define GHCB_INFO_CPUID_REQUEST            4
>  #define GHCB_INFO_CPUID_RESPONSE           5
> +#define GHCB_HYPERVISOR_FEATURES_REQUEST   128
> +#define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>  #define GHCB_INFO_TERMINATE_REQUEST        256
>  
>  #define GHCB_TERMINATE_GHCB                0
> diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
> index ccdb662af7..2d64a4c28f 100644
> --- a/MdePkg/Include/Register/Amd/Ghcb.h
> +++ b/MdePkg/Include/Register/Amd/Ghcb.h
> @@ -54,6 +54,7 @@
>  #define SVM_EXIT_NMI_COMPLETE   0x80000003ULL
>  #define SVM_EXIT_AP_RESET_HOLD  0x80000004ULL
>  #define SVM_EXIT_AP_JUMP_TABLE  0x80000005ULL
> +#define SVM_EXIT_HYPERVISOR_FEATURES  0x8000FFFDULL
>  #define SVM_EXIT_UNSUPPORTED    0x8000FFFFULL
>  
>  //
> @@ -154,4 +155,9 @@ typedef union {
>  #define GHCB_EVENT_INJECTION_TYPE_EXCEPTION  3
>  #define GHCB_EVENT_INJECTION_TYPE_SOFT_INT   4
>  
> +// Hypervisor features

(1) Comment style -- leading and trailing // lines missing.


> +#define GHCB_HV_FEATURES_SNP                              BIT0
> +#define GHCB_HV_FEATURES_SNP_AP_CREATE                    (GHCB_HV_FEATURES_SNP | BIT1)
> +#define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION         (GHCB_HV_FEATURES_SNP_AP_CREATE | BIT2)
> +#define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION_TIMER   (GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION | BIT3)
>  #endif
> 

I'm going to take this series slow, because I need to rebuild whatever
understanding I've ever had of SEV-ES from the bottom up.

The patch looks good to me (I checked the GHCB spec 2.0, and the values
seem to match).

But I need some confirmation. The GHCB spec defines the "GHCB MSR"
protocol, where MSR_SEV_ES_GHCB can be used for a direct
request/response protocol when the least significant 12 bits are nonzero
(i.e., they stand for a "function"). The sequence in this case (from the
guest side is): wrmsr, vmgexit, rdmsr.

On the host side, upon vmgexit, the MSR's twelve least significant bits
are checked, and if they are nonzero, the function is handled, and the
response is provided in the high-order bits of the MSR. Otherwise, if
the "function" is zero, the MSR's contents are taken as a GPA, and then
the pointed-to page (the GHCB) is consulted for the actual request.

This means that some functions are possible for the guest to call in two
ways -- with and without a (decrypted) GHCB existing. (The spec writes
in 2.3.1, "The GHCB MSR protocol is valid at any time but is most useful
when the GHCB page cannot be written by the guest in an unencrypted
fashion").

One of the new things the GHCB 2.0 spec introduces is the "hypervisor
feature advertisement", which is (apparently) one of those functions
that are available to the guest via both the GHCB *MSR protocol*
(function = GHCB_HYPERVISOR_FEATURES_REQUEST) and the GHCB *page*
(SwExitCode = SVM_EXIT_HYPERVISOR_FEATURES, response in SwExitInfo2).

My question is: when is it useful to fetch the hv features through the
GHCB *page* (i.e., not through the MSR protocol)? At the end of the
series, I don't see any use for SVM_EXIT_HYPERVISOR_FEATURES.

A similarly unused macro (from before this series) is
SVM_EXIT_NMI_COMPLETE. So I guess the approach in the edk2 SEV* work has
been to incorporate all spec-defined constants in MdePkg. That's a valid
approach per se; what I'd like to understand is what use case for
SVM_EXIT_HYPERVISOR_FEATURES the GHCB *spec* foresees.

(2) Does the spec define SVM_EXIT_HYPERVISOR_FEATURES for completeness'
sake -- so that no function be restricted to the MSR protocol? (IOW,
should the MSR protocol be a subset, by principle, of the functions
available through the GHCB *page*?)

I prefer to define only such macros in edk2 that are actually used --
but I admit that may be different from the general MdePkg rules. So I
don't mind SVM_EXIT_HYPERVISOR_FEATURES, it's just a bit more difficult
to review / understand without actual use.


(3) I suggest the following subject:

MdePkg/Register/Amd: define GHCB macros for hypervisor feature detection

(72 chars)

With (1) and (3) fixed:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>


Thanks
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 03/28] MdePkg: Define the GHCB GPA structure
  2021-04-30 11:51 ` [PATCH RFC v2 03/28] MdePkg: Define the GHCB GPA structure Brijesh Singh
@ 2021-05-03 10:24   ` Laszlo Ersek
  2021-05-03 12:19     ` Laszlo Ersek
  0 siblings, 1 reply; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-03 10:24 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 04/30/21 13:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
> 
> An SEV-SNP guest is required to perform the GHCB GPA registration. See
> the GHCB specification for further details.
> 
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  MdePkg/Include/Register/Amd/Fam17Msr.h | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
> index a65d51ab12..e19bd04b6c 100644
> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
> @@ -53,6 +53,11 @@ typedef union {
>      UINT64  Features:52;
>    } GhcbHypervisorFeatures;
>  
> +  struct {
> +    UINT64  Function:12;
> +    UINT64  GuestFrameNumber:52;
> +  } GhcbGpaRegister;
> +
>    VOID    *Ghcb;
>  
>    UINT64  GhcbPhysicalAddress;
> @@ -62,6 +67,8 @@ typedef union {
>  #define GHCB_INFO_SEV_INFO_GET             2
>  #define GHCB_INFO_CPUID_REQUEST            4
>  #define GHCB_INFO_CPUID_RESPONSE           5
> +#define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
> +#define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
>  #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>  #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>  #define GHCB_INFO_TERMINATE_REQUEST        256
> 

The number match the spec (2.0), but I have some remarks / questions.

(1) Patch #2 (SVM_EXIT_HYPERVISOR_FEATURES) and this patch
(GHCB_INFO_GHCB_GPA_REGISTER_REQUEST) break the nice alignments of the
macro values (replacement texts) in both header files. Can you prepend a
whitespace-only patch that simply moves the affected "columns" to the
right far enough?

(2) I've checked section 2.3.2 "GHCB GPA Registration" in the spec
(2.0). What is the specific risk of allowing a guest to switch from one
GHCB address to another?

(3) It seems strange to expect that a guest stick with a particular GHCB
address for its entire lifetime (including firmware and OS) -- in fact
OVMF already uses multiple GHCB addresses. The spec does not explain how
the guest can "unlock" (de-register) a registered GHCB address.
Furthermore, if a guest can do that *at all* (which I think it must --
we're already using different GHCB addresses between SEC and DXE, for
example), then what protection does the *temporary* locking of the GHCB
address provide?

I'll stop reviewing here, because I think I need to understand your
answers. I'd like to have a rudimentary mental basis for reviewing the rest.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 01/28] MdePkg: Expand the SEV MSR to include the SNP definition
  2021-05-03  8:39   ` [edk2-devel] " Laszlo Ersek
@ 2021-05-03 11:42     ` Brijesh Singh
  0 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-05-03 11:42 UTC (permalink / raw)
  To: Laszlo Ersek, devel
  Cc: brijesh.singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/3/21 3:39 AM, Laszlo Ersek wrote:
> On 04/30/21 13:51, Brijesh Singh wrote:
>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7Ceea6f3b3eab148c16fdf08d90e0ef790%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637556279729207954%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=i4WYjB4hqOLiQR8dZyCLjSd8iUrE0QILyRavcHAEmGY%3D&amp;reserved=0
>>
>> Define the SEV-SNP MSR bits.
>>
>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  MdePkg/Include/Register/Amd/Fam17Msr.h | 7 ++++++-
>>  1 file changed, 6 insertions(+), 1 deletion(-)
>>
>> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
>> index e4db09c518..4d33bef220 100644
>> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
>> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
>> @@ -87,7 +87,12 @@ typedef union {
>>      ///
>>      UINT32  SevEsBit:1;
>>  
>> -    UINT32  Reserved:30;
>> +    ///
>> +    /// [Bit 2] Secure Nested Paging (SevSnp) is enabled
>> +    ///
>> +    UINT32  SevSnpBit:1;
>> +
>> +    UINT32  Reserved:29;
>>    } Bits;
>>    ///
>>    /// All bit fields as a 32-bit value
>>
> (1) When changing a Reserved field's meaning, the field should be
> renamed. Usually we do this by numbering, and the numbers only ever
> increase. This is because code might exist that uses a Reserved field.
> Such code should be prevented from compiling, because that's much better
> than silently breaking its behavior. So the new name of the field should
> be Reserved2.
>
> (If we modify Reserved2 later, it should be renamed to Reserved3, and so
> on -- we should never return to a field name used before.)


Noted, I will fix it in next rev. thanks


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 03/28] MdePkg: Define the GHCB GPA structure
  2021-05-03 10:24   ` [edk2-devel] " Laszlo Ersek
@ 2021-05-03 12:19     ` Laszlo Ersek
  2021-05-03 12:55       ` Brijesh Singh
  0 siblings, 1 reply; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-03 12:19 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/03/21 12:24, Laszlo Ersek wrote:
> On 04/30/21 13:51, Brijesh Singh wrote:
>> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
>>
>> An SEV-SNP guest is required to perform the GHCB GPA registration. See
>> the GHCB specification for further details.
>>
>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  MdePkg/Include/Register/Amd/Fam17Msr.h | 7 +++++++
>>  1 file changed, 7 insertions(+)
>>
>> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
>> index a65d51ab12..e19bd04b6c 100644
>> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
>> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
>> @@ -53,6 +53,11 @@ typedef union {
>>      UINT64  Features:52;
>>    } GhcbHypervisorFeatures;
>>  
>> +  struct {
>> +    UINT64  Function:12;
>> +    UINT64  GuestFrameNumber:52;
>> +  } GhcbGpaRegister;
>> +
>>    VOID    *Ghcb;
>>  
>>    UINT64  GhcbPhysicalAddress;
>> @@ -62,6 +67,8 @@ typedef union {
>>  #define GHCB_INFO_SEV_INFO_GET             2
>>  #define GHCB_INFO_CPUID_REQUEST            4
>>  #define GHCB_INFO_CPUID_RESPONSE           5
>> +#define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
>> +#define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
>>  #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>>  #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>>  #define GHCB_INFO_TERMINATE_REQUEST        256
>>
> 
> The number match the spec (2.0), but I have some remarks / questions.
> 
> (1) Patch #2 (SVM_EXIT_HYPERVISOR_FEATURES) and this patch
> (GHCB_INFO_GHCB_GPA_REGISTER_REQUEST) break the nice alignments of the
> macro values (replacement texts) in both header files. Can you prepend a
> whitespace-only patch that simply moves the affected "columns" to the
> right far enough?
> 
> (2) I've checked section 2.3.2 "GHCB GPA Registration" in the spec
> (2.0). What is the specific risk of allowing a guest to switch from one
> GHCB address to another?
> 
> (3) It seems strange to expect that a guest stick with a particular GHCB
> address for its entire lifetime (including firmware and OS) -- in fact
> OVMF already uses multiple GHCB addresses. The spec does not explain how
> the guest can "unlock" (de-register) a registered GHCB address.
> Furthermore, if a guest can do that *at all* (which I think it must --
> we're already using different GHCB addresses between SEC and DXE, for
> example), then what protection does the *temporary* locking of the GHCB
> address provide?
> 
> I'll stop reviewing here, because I think I need to understand your
> answers. I'd like to have a rudimentary mental basis for reviewing the rest.

... interestingly, with reference to my question (2) under patch "RFC v2
02/28", the GHCB GPA registration function is one that can *only* be
performed with the GHCB MSR protocol, and not through the GHCB page.

So that shows that the MSR protocol's functions cannot be considered a
pure subset of the GHCB page's functions. If
SVM_EXIT_HYPERVISOR_FEATURES didn't exist (and the same function would
only be accessible via GHCB_HYPERVISOR_FEATURES_REQUEST), then no
"larger principle" would be damaged.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 02/28] MdePkg: Define the GHCB Hypervisor features
  2021-05-03 10:10   ` [edk2-devel] " Laszlo Ersek
@ 2021-05-03 12:20     ` Brijesh Singh
  2021-05-03 13:40       ` Laszlo Ersek
  0 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-05-03 12:20 UTC (permalink / raw)
  To: Laszlo Ersek, Tom Lendacky
  Cc: brijesh.singh, devel, James Bottomley, Min Xu, Jiewen Yao,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/3/21 5:10 AM, Laszlo Ersek wrote:
> Hi Brijesh, Tom,
>
> On 04/30/21 13:51, Brijesh Singh wrote:
>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C9a7e31fbf85043c6ee8508d90e1ba94d%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637556334239842920%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=fSThw3T7P4LcLhcZz9tfy4ZB1Y7Zny0BzwA2jTyWAkY%3D&amp;reserved=0
>>
>> Version 2 of GHCB introduces advertisement of features that are supported
>> by the hypervisor. See the GHCB spec section 2.2 for an additional details.
>>
>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  MdePkg/Include/Register/Amd/Fam17Msr.h | 7 +++++++
>>  MdePkg/Include/Register/Amd/Ghcb.h     | 6 ++++++
>>  2 files changed, 13 insertions(+)
>>
>> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
>> index 4d33bef220..a65d51ab12 100644
>> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
>> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
>> @@ -48,6 +48,11 @@ typedef union {
>>      UINT32  Reserved2:32;
>>    } GhcbTerminate;
>>  
>> +  struct {
>> +    UINT64  Function:12;
>> +    UINT64  Features:52;
>> +  } GhcbHypervisorFeatures;
>> +
>>    VOID    *Ghcb;
>>  
>>    UINT64  GhcbPhysicalAddress;
>> @@ -57,6 +62,8 @@ typedef union {
>>  #define GHCB_INFO_SEV_INFO_GET             2
>>  #define GHCB_INFO_CPUID_REQUEST            4
>>  #define GHCB_INFO_CPUID_RESPONSE           5
>> +#define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>> +#define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>>  #define GHCB_INFO_TERMINATE_REQUEST        256
>>  
>>  #define GHCB_TERMINATE_GHCB                0
>> diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
>> index ccdb662af7..2d64a4c28f 100644
>> --- a/MdePkg/Include/Register/Amd/Ghcb.h
>> +++ b/MdePkg/Include/Register/Amd/Ghcb.h
>> @@ -54,6 +54,7 @@
>>  #define SVM_EXIT_NMI_COMPLETE   0x80000003ULL
>>  #define SVM_EXIT_AP_RESET_HOLD  0x80000004ULL
>>  #define SVM_EXIT_AP_JUMP_TABLE  0x80000005ULL
>> +#define SVM_EXIT_HYPERVISOR_FEATURES  0x8000FFFDULL
>>  #define SVM_EXIT_UNSUPPORTED    0x8000FFFFULL
>>  
>>  //
>> @@ -154,4 +155,9 @@ typedef union {
>>  #define GHCB_EVENT_INJECTION_TYPE_EXCEPTION  3
>>  #define GHCB_EVENT_INJECTION_TYPE_SOFT_INT   4
>>  
>> +// Hypervisor features
> (1) Comment style -- leading and trailing // lines missing.


Noted.


>
>
>> +#define GHCB_HV_FEATURES_SNP                              BIT0
>> +#define GHCB_HV_FEATURES_SNP_AP_CREATE                    (GHCB_HV_FEATURES_SNP | BIT1)
>> +#define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION         (GHCB_HV_FEATURES_SNP_AP_CREATE | BIT2)
>> +#define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION_TIMER   (GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION | BIT3)
>>  #endif
>>
> I'm going to take this series slow, because I need to rebuild whatever
> understanding I've ever had of SEV-ES from the bottom up.
>
> The patch looks good to me (I checked the GHCB spec 2.0, and the values
> seem to match).
>
> But I need some confirmation. The GHCB spec defines the "GHCB MSR"
> protocol, where MSR_SEV_ES_GHCB can be used for a direct
> request/response protocol when the least significant 12 bits are nonzero
> (i.e., they stand for a "function"). The sequence in this case (from the
> guest side is): wrmsr, vmgexit, rdmsr.
>
> On the host side, upon vmgexit, the MSR's twelve least significant bits
> are checked, and if they are nonzero, the function is handled, and the
> response is provided in the high-order bits of the MSR. Otherwise, if
> the "function" is zero, the MSR's contents are taken as a GPA, and then
> the pointed-to page (the GHCB) is consulted for the actual request.
>
> This means that some functions are possible for the guest to call in two
> ways -- with and without a (decrypted) GHCB existing. (The spec writes
> in 2.3.1, "The GHCB MSR protocol is valid at any time but is most useful
> when the GHCB page cannot be written by the guest in an unencrypted
> fashion").
>
> One of the new things the GHCB 2.0 spec introduces is the "hypervisor
> feature advertisement", which is (apparently) one of those functions
> that are available to the guest via both the GHCB *MSR protocol*
> (function = GHCB_HYPERVISOR_FEATURES_REQUEST) and the GHCB *page*
> (SwExitCode = SVM_EXIT_HYPERVISOR_FEATURES, response in SwExitInfo2).
>
> My question is: when is it useful to fetch the hv features through the
> GHCB *page* (i.e., not through the MSR protocol)? At the end of the
> series, I don't see any use for SVM_EXIT_HYPERVISOR_FEATURES.

In my OVMF and Linux-guest patches I am using the MSR protocol based
HV_FEATUERS because I query the features during the negotiation and
cache it. The value is saved in Es workarea and platformPei saves in a PCD.

In a different implementation, a guest can call the HV_FEATURES every
time they need to consult the feature values. I think spec wanted to
keep the flexibility that feature can be queried through the non-MSR
based vmgexit so that the guest does not need save/restore the GHCB
address after the GHCB is established. If I was not caching the feature
value in patch #16 then I would have used the non-MSR based vmgexit to
query the value in PlatformPei to build the PCD.


> A similarly unused macro (from before this series) is
> SVM_EXIT_NMI_COMPLETE. So I guess the approach in the edk2 SEV* work has
> been to incorporate all spec-defined constants in MdePkg. That's a valid
> approach per se; what I'd like to understand is what use case for
> SVM_EXIT_HYPERVISOR_FEATURES the GHCB *spec* foresees.
> (2) Does the spec define SVM_EXIT_HYPERVISOR_FEATURES for completeness'
> sake -- so that no function be restricted to the MSR protocol? (IOW,
> should the MSR protocol be a subset, by principle, of the functions
> available through the GHCB *page*?)

I think non-MSR based vmgexit is done for completeness sake. It maybe
used by other HV or Guests (e.g Windows, Unix etc etc). At this time I
am not using it in OVMF or Linux guest.


>
> I prefer to define only such macros in edk2 that are actually used --
> but I admit that may be different from the general MdePkg rules. So I
> don't mind SVM_EXIT_HYPERVISOR_FEATURES, it's just a bit more difficult
> to review / understand without actual use.

Good point, I have no issue removing the unused macro. If we see a need
for it then it can be added in the future.


>
> (3) I suggest the following subject:
>
> MdePkg/Register/Amd: define GHCB macros for hypervisor feature detection
>
> (72 chars)
>
> With (1) and (3) fixed:
>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
>
>
> Thanks
> Laszlo
>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 03/28] MdePkg: Define the GHCB GPA structure
  2021-05-03 12:19     ` Laszlo Ersek
@ 2021-05-03 12:55       ` Brijesh Singh
  2021-05-03 13:50         ` Laszlo Ersek
  0 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-05-03 12:55 UTC (permalink / raw)
  To: Laszlo Ersek, devel
  Cc: brijesh.singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/3/21 7:19 AM, Laszlo Ersek wrote:
> On 05/03/21 12:24, Laszlo Ersek wrote:
>> On 04/30/21 13:51, Brijesh Singh wrote:
>>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C9eac9a93753d403dcc4d08d90e2dbcb5%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637556411874265560%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=eNafEGfhCMOkOboQOJnxq8Rw%2BOTuvAUGIziDuELV8%2Bk%3D&amp;reserved=0
>>>
>>> An SEV-SNP guest is required to perform the GHCB GPA registration. See
>>> the GHCB specification for further details.
>>>
>>> Cc: James Bottomley <jejb@linux.ibm.com>
>>> Cc: Min Xu <min.m.xu@intel.com>
>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>>> Cc: Laszlo Ersek <lersek@redhat.com>
>>> Cc: Erdem Aktas <erdemaktas@google.com>
>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>> ---
>>>  MdePkg/Include/Register/Amd/Fam17Msr.h | 7 +++++++
>>>  1 file changed, 7 insertions(+)
>>>
>>> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>> index a65d51ab12..e19bd04b6c 100644
>>> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
>>> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>> @@ -53,6 +53,11 @@ typedef union {
>>>      UINT64  Features:52;
>>>    } GhcbHypervisorFeatures;
>>>  
>>> +  struct {
>>> +    UINT64  Function:12;
>>> +    UINT64  GuestFrameNumber:52;
>>> +  } GhcbGpaRegister;
>>> +
>>>    VOID    *Ghcb;
>>>  
>>>    UINT64  GhcbPhysicalAddress;
>>> @@ -62,6 +67,8 @@ typedef union {
>>>  #define GHCB_INFO_SEV_INFO_GET             2
>>>  #define GHCB_INFO_CPUID_REQUEST            4
>>>  #define GHCB_INFO_CPUID_RESPONSE           5
>>> +#define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
>>> +#define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
>>>  #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>>>  #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>>>  #define GHCB_INFO_TERMINATE_REQUEST        256
>>>
>> The number match the spec (2.0), but I have some remarks / questions.
>>
>> (1) Patch #2 (SVM_EXIT_HYPERVISOR_FEATURES) and this patch
>> (GHCB_INFO_GHCB_GPA_REGISTER_REQUEST) break the nice alignments of the
>> macro values (replacement texts) in both header files. Can you prepend a
>> whitespace-only patch that simply moves the affected "columns" to the
>> right far enough?

Sure, do you want me to the post after all the new VMGEXIT's are defined ?


>>
>> (2) I've checked section 2.3.2 "GHCB GPA Registration" in the spec
>> (2.0). What is the specific risk of allowing a guest to switch from one
>> GHCB address to another?

The GHCB is a shared page, there is no risk to switch from one page to
another. This feature is designed to simplify some of the hypervisor
implementation. Since the GHCB is accessed on every vmgexit, a
hypervisor may prefer to create a map during the registration and refer
the map instead of creating a new mapping on every vmgexit.


>>
>> (3) It seems strange to expect that a guest stick with a particular GHCB
>> address for its entire lifetime (including firmware and OS) -- in fact
>> OVMF already uses multiple GHCB addresses. The spec does not explain how
>> the guest can "unlock" (de-register) a registered GHCB address.
>> Furthermore, if a guest can do that *at all* (which I think it must --
>> we're already using different GHCB addresses between SEC and DXE, for
>> example), then what protection does the *temporary* locking of the GHCB
>> address provide?

The spec does not force that GHCB should *never* change once registered.
It says that before switching to new GHCB page, the guest must register
the page. As you rightly said that OVMF uses multiple GHCBs from SEC to
DXE. There is no unregister, registering a new GHCB is a hint to
hypervisor that it should drop the old GHCB mapping. The GHCB
registration is not a PSP function, and are not designed to mitigate a
security exploits. It is purely a hypevisor virtualized feature.


>> I'll stop reviewing here, because I think I need to understand your
>> answers. I'd like to have a rudimentary mental basis for reviewing the rest.
> ... interestingly, with reference to my question (2) under patch "RFC v2
> 02/28", the GHCB GPA registration function is one that can *only* be
> performed with the GHCB MSR protocol, and not through the GHCB page.
>
> So that shows that the MSR protocol's functions cannot be considered a
> pure subset of the GHCB page's functions. If
> SVM_EXIT_HYPERVISOR_FEATURES didn't exist (and the same function would
> only be accessible via GHCB_HYPERVISOR_FEATURES_REQUEST), then no
> "larger principle" would be damaged.

That is correct, not every exit have both MSR and non MSR protocol based
vmgexit. It seems that during the spec review no other HV vendor saw the
need for non-MSR based exit. Certainly, I don't see a need for it in KVM
and can't comment on other HV ;)


>
> Thanks
> Laszlo
>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH RFC v2 17/28] OvmfPkg/ResetVector: Invalidate the GHCB page
  2021-04-30 11:51 ` [PATCH RFC v2 17/28] OvmfPkg/ResetVector: Invalidate the GHCB page Brijesh Singh
@ 2021-05-03 13:05   ` Erdem Aktas
  2021-05-03 14:28     ` Brijesh Singh
  0 siblings, 1 reply; 81+ messages in thread
From: Erdem Aktas @ 2021-05-03 13:05 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: devel, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek

Hi Brijesh,
I have few naive questions inlined:

On Fri, Apr 30, 2021 at 4:52 AM Brijesh Singh <brijesh.singh@amd.com> wrote:
> +    ; Use PVALIDATE instruction to invalidate the page
> +    mov     eax, GHCB_BASE
> +    mov     ecx, 0
> +    mov     edx, 0
> +    DB      0xF2, 0x0F, 0x01, 0xFF
> +    cmp     eax, 0
> +    jnz     TerminateSevGuestLaunch
Any reason why the PVALIDATE return value (EFLAGS.CF) is not checked
here? IMO, this might lead some page replay attacks.

>
> +    ;
> +    ; The page table built above cleared the memory encryption mask from the
> +    ; GHCB_BASE (aka made it shared). When SEV-SNP is enabled, to maintain
> +    ; the security guarantees, the page state transition from private to
> +    ; shared must go through the page invalidation steps. Invalidate the
> +    ; memory range before loading the page table below.
> +    ;
> +    ; NOTE: the invalidation must happen after zeroing the GHCB memory. This
> +    ;       is because, in the 32-bit mode all the access are considered private.
> +    ;       The invalidation before the zero'ing will cause a #VC.
> +    ;
> +    OneTimeCall  InvalidateGHCBPage
I am not sure if this is a great idea.
1. Zeroing page content before paging is enabled. We are actually
writing 0s encrypted with a guest key.
2. invalidating the page and making it shared.
Doesn't this reveal a mapping of what 0's look like when a specific
page is encrypted?  And when the page is marked as shared, from the
guest and host perspective, it is not zeroed but filled with some data
that looks random. So what is the purpose of zeroing the page before
invalidation?

Thanks
-Erdem

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 02/28] MdePkg: Define the GHCB Hypervisor features
  2021-05-03 12:20     ` Brijesh Singh
@ 2021-05-03 13:40       ` Laszlo Ersek
  0 siblings, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-03 13:40 UTC (permalink / raw)
  To: Brijesh Singh, Tom Lendacky
  Cc: devel, James Bottomley, Min Xu, Jiewen Yao, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/03/21 14:20, Brijesh Singh wrote:
> 
> On 5/3/21 5:10 AM, Laszlo Ersek wrote:
>> Hi Brijesh, Tom,
>>
>> On 04/30/21 13:51, Brijesh Singh wrote:
>>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C9a7e31fbf85043c6ee8508d90e1ba94d%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637556334239842920%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=fSThw3T7P4LcLhcZz9tfy4ZB1Y7Zny0BzwA2jTyWAkY%3D&amp;reserved=0
>>>
>>> Version 2 of GHCB introduces advertisement of features that are supported
>>> by the hypervisor. See the GHCB spec section 2.2 for an additional details.
>>>
>>> Cc: James Bottomley <jejb@linux.ibm.com>
>>> Cc: Min Xu <min.m.xu@intel.com>
>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>>> Cc: Laszlo Ersek <lersek@redhat.com>
>>> Cc: Erdem Aktas <erdemaktas@google.com>
>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>> ---
>>>  MdePkg/Include/Register/Amd/Fam17Msr.h | 7 +++++++
>>>  MdePkg/Include/Register/Amd/Ghcb.h     | 6 ++++++
>>>  2 files changed, 13 insertions(+)
>>>
>>> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>> index 4d33bef220..a65d51ab12 100644
>>> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
>>> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>> @@ -48,6 +48,11 @@ typedef union {
>>>      UINT32  Reserved2:32;
>>>    } GhcbTerminate;
>>>  
>>> +  struct {
>>> +    UINT64  Function:12;
>>> +    UINT64  Features:52;
>>> +  } GhcbHypervisorFeatures;
>>> +
>>>    VOID    *Ghcb;
>>>  
>>>    UINT64  GhcbPhysicalAddress;
>>> @@ -57,6 +62,8 @@ typedef union {
>>>  #define GHCB_INFO_SEV_INFO_GET             2
>>>  #define GHCB_INFO_CPUID_REQUEST            4
>>>  #define GHCB_INFO_CPUID_RESPONSE           5
>>> +#define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>>> +#define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>>>  #define GHCB_INFO_TERMINATE_REQUEST        256
>>>  
>>>  #define GHCB_TERMINATE_GHCB                0
>>> diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
>>> index ccdb662af7..2d64a4c28f 100644
>>> --- a/MdePkg/Include/Register/Amd/Ghcb.h
>>> +++ b/MdePkg/Include/Register/Amd/Ghcb.h
>>> @@ -54,6 +54,7 @@
>>>  #define SVM_EXIT_NMI_COMPLETE   0x80000003ULL
>>>  #define SVM_EXIT_AP_RESET_HOLD  0x80000004ULL
>>>  #define SVM_EXIT_AP_JUMP_TABLE  0x80000005ULL
>>> +#define SVM_EXIT_HYPERVISOR_FEATURES  0x8000FFFDULL
>>>  #define SVM_EXIT_UNSUPPORTED    0x8000FFFFULL
>>>  
>>>  //
>>> @@ -154,4 +155,9 @@ typedef union {
>>>  #define GHCB_EVENT_INJECTION_TYPE_EXCEPTION  3
>>>  #define GHCB_EVENT_INJECTION_TYPE_SOFT_INT   4
>>>  
>>> +// Hypervisor features
>> (1) Comment style -- leading and trailing // lines missing.
> 
> 
> Noted.
> 
> 
>>
>>
>>> +#define GHCB_HV_FEATURES_SNP                              BIT0
>>> +#define GHCB_HV_FEATURES_SNP_AP_CREATE                    (GHCB_HV_FEATURES_SNP | BIT1)
>>> +#define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION         (GHCB_HV_FEATURES_SNP_AP_CREATE | BIT2)
>>> +#define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION_TIMER   (GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION | BIT3)
>>>  #endif
>>>
>> I'm going to take this series slow, because I need to rebuild whatever
>> understanding I've ever had of SEV-ES from the bottom up.
>>
>> The patch looks good to me (I checked the GHCB spec 2.0, and the values
>> seem to match).
>>
>> But I need some confirmation. The GHCB spec defines the "GHCB MSR"
>> protocol, where MSR_SEV_ES_GHCB can be used for a direct
>> request/response protocol when the least significant 12 bits are nonzero
>> (i.e., they stand for a "function"). The sequence in this case (from the
>> guest side is): wrmsr, vmgexit, rdmsr.
>>
>> On the host side, upon vmgexit, the MSR's twelve least significant bits
>> are checked, and if they are nonzero, the function is handled, and the
>> response is provided in the high-order bits of the MSR. Otherwise, if
>> the "function" is zero, the MSR's contents are taken as a GPA, and then
>> the pointed-to page (the GHCB) is consulted for the actual request.
>>
>> This means that some functions are possible for the guest to call in two
>> ways -- with and without a (decrypted) GHCB existing. (The spec writes
>> in 2.3.1, "The GHCB MSR protocol is valid at any time but is most useful
>> when the GHCB page cannot be written by the guest in an unencrypted
>> fashion").
>>
>> One of the new things the GHCB 2.0 spec introduces is the "hypervisor
>> feature advertisement", which is (apparently) one of those functions
>> that are available to the guest via both the GHCB *MSR protocol*
>> (function = GHCB_HYPERVISOR_FEATURES_REQUEST) and the GHCB *page*
>> (SwExitCode = SVM_EXIT_HYPERVISOR_FEATURES, response in SwExitInfo2).
>>
>> My question is: when is it useful to fetch the hv features through the
>> GHCB *page* (i.e., not through the MSR protocol)? At the end of the
>> series, I don't see any use for SVM_EXIT_HYPERVISOR_FEATURES.
> 
> In my OVMF and Linux-guest patches I am using the MSR protocol based
> HV_FEATUERS because I query the features during the negotiation and
> cache it. The value is saved in Es workarea and platformPei saves in a PCD.
> 
> In a different implementation, a guest can call the HV_FEATURES every
> time they need to consult the feature values. I think spec wanted to
> keep the flexibility that feature can be queried through the non-MSR
> based vmgexit so that the guest does not need save/restore the GHCB
> address after the GHCB is established. If I was not caching the feature
> value in patch #16 then I would have used the non-MSR based vmgexit to
> query the value in PlatformPei to build the PCD.
> 
> 
>> A similarly unused macro (from before this series) is
>> SVM_EXIT_NMI_COMPLETE. So I guess the approach in the edk2 SEV* work has
>> been to incorporate all spec-defined constants in MdePkg. That's a valid
>> approach per se; what I'd like to understand is what use case for
>> SVM_EXIT_HYPERVISOR_FEATURES the GHCB *spec* foresees.
>> (2) Does the spec define SVM_EXIT_HYPERVISOR_FEATURES for completeness'
>> sake -- so that no function be restricted to the MSR protocol? (IOW,
>> should the MSR protocol be a subset, by principle, of the functions
>> available through the GHCB *page*?)
> 
> I think non-MSR based vmgexit is done for completeness sake. It maybe
> used by other HV or Guests (e.g Windows, Unix etc etc). At this time I
> am not using it in OVMF or Linux guest.
> 
> 
>>
>> I prefer to define only such macros in edk2 that are actually used --
>> but I admit that may be different from the general MdePkg rules. So I
>> don't mind SVM_EXIT_HYPERVISOR_FEATURES, it's just a bit more difficult
>> to review / understand without actual use.
> 
> Good point, I have no issue removing the unused macro. If we see a need
> for it then it can be added in the future.

Thanks for the explanation.

I'm not necessarily requesting that SVM_EXIT_HYPERVISOR_FEATURES be
removed from the patch. We already have the (similarly unused)
SVM_EXIT_NMI_COMPLETE macro in MdePkg. We should aim for consistency --
we should decide whether MdePkg headers need to stick with the spec(s)
as closely and comprehensively as possible, or whether they should only
incorporate what's actually used by code. Given that edk2 is a "kit",
and MdePkg is the most central part of it, I think being comprehensive
in MdePkg is not a bad choice. Given that SVM_EXIT_NMI_COMPLETE already
exemplifies this approach, I think we can and *should* bring in
SVM_EXIT_HYPERVISOR_FEATURES as well, given that the spec provides it.

Thanks
Laszlo



> 
> 
>>
>> (3) I suggest the following subject:
>>
>> MdePkg/Register/Amd: define GHCB macros for hypervisor feature detection
>>
>> (72 chars)
>>
>> With (1) and (3) fixed:
>>
>> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
>>
>>
>> Thanks
>> Laszlo
>>
> 


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 03/28] MdePkg: Define the GHCB GPA structure
  2021-05-03 12:55       ` Brijesh Singh
@ 2021-05-03 13:50         ` Laszlo Ersek
  2021-05-03 13:55           ` Laszlo Ersek
  0 siblings, 1 reply; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-03 13:50 UTC (permalink / raw)
  To: Brijesh Singh, devel
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/03/21 14:55, Brijesh Singh wrote:
> 
> On 5/3/21 7:19 AM, Laszlo Ersek wrote:
>> On 05/03/21 12:24, Laszlo Ersek wrote:
>>> On 04/30/21 13:51, Brijesh Singh wrote:
>>>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C9eac9a93753d403dcc4d08d90e2dbcb5%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637556411874265560%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=eNafEGfhCMOkOboQOJnxq8Rw%2BOTuvAUGIziDuELV8%2Bk%3D&amp;reserved=0
>>>>
>>>> An SEV-SNP guest is required to perform the GHCB GPA registration. See
>>>> the GHCB specification for further details.
>>>>
>>>> Cc: James Bottomley <jejb@linux.ibm.com>
>>>> Cc: Min Xu <min.m.xu@intel.com>
>>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>>>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>>>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>>>> Cc: Laszlo Ersek <lersek@redhat.com>
>>>> Cc: Erdem Aktas <erdemaktas@google.com>
>>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>>> ---
>>>>  MdePkg/Include/Register/Amd/Fam17Msr.h | 7 +++++++
>>>>  1 file changed, 7 insertions(+)
>>>>
>>>> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>>> index a65d51ab12..e19bd04b6c 100644
>>>> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
>>>> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>>> @@ -53,6 +53,11 @@ typedef union {
>>>>      UINT64  Features:52;
>>>>    } GhcbHypervisorFeatures;
>>>>  
>>>> +  struct {
>>>> +    UINT64  Function:12;
>>>> +    UINT64  GuestFrameNumber:52;
>>>> +  } GhcbGpaRegister;
>>>> +
>>>>    VOID    *Ghcb;
>>>>  
>>>>    UINT64  GhcbPhysicalAddress;
>>>> @@ -62,6 +67,8 @@ typedef union {
>>>>  #define GHCB_INFO_SEV_INFO_GET             2
>>>>  #define GHCB_INFO_CPUID_REQUEST            4
>>>>  #define GHCB_INFO_CPUID_RESPONSE           5
>>>> +#define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
>>>> +#define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
>>>>  #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>>>>  #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>>>>  #define GHCB_INFO_TERMINATE_REQUEST        256
>>>>
>>> The number match the spec (2.0), but I have some remarks / questions.
>>>
>>> (1) Patch #2 (SVM_EXIT_HYPERVISOR_FEATURES) and this patch
>>> (GHCB_INFO_GHCB_GPA_REGISTER_REQUEST) break the nice alignments of the
>>> macro values (replacement texts) in both header files. Can you prepend a
>>> whitespace-only patch that simply moves the affected "columns" to the
>>> right far enough?
> 
> Sure, do you want me to the post after all the new VMGEXIT's are defined ?

Optimally, you should please look at the header file at the end of the
series, and determine the new starting *character* column for the macro
replacement texts. Then, at the very beginning of the series, pad
everything to that column. This way, you only need to adjust the
whitespace once (every macro addition will then fit nicely in place
later on), and whenever you add a new macro, it will already have the
final amount of whitespace needed.

> 
> 
>>>
>>> (2) I've checked section 2.3.2 "GHCB GPA Registration" in the spec
>>> (2.0). What is the specific risk of allowing a guest to switch from one
>>> GHCB address to another?
> 
> The GHCB is a shared page, there is no risk to switch from one page to
> another. This feature is designed to simplify some of the hypervisor
> implementation. Since the GHCB is accessed on every vmgexit, a
> hypervisor may prefer to create a map during the registration and refer
> the map instead of creating a new mapping on every vmgexit.

OK. So my comment in return is not for the patch set, but the spec: I
think this motivation should be highlighted in the spec. "Some
hypervisors may prefer" is vague. Prefer that for what? "Simplicity of
implementation" is a good answer (eliminate new mappings on every exit),
but it should be explained (perhaps in informative / non-normative text).

> 
> 
>>>
>>> (3) It seems strange to expect that a guest stick with a particular GHCB
>>> address for its entire lifetime (including firmware and OS) -- in fact
>>> OVMF already uses multiple GHCB addresses. The spec does not explain how
>>> the guest can "unlock" (de-register) a registered GHCB address.
>>> Furthermore, if a guest can do that *at all* (which I think it must --
>>> we're already using different GHCB addresses between SEC and DXE, for
>>> example), then what protection does the *temporary* locking of the GHCB
>>> address provide?
> 
> The spec does not force that GHCB should *never* change once registered.
> It says that before switching to new GHCB page, the guest must register
> the page. As you rightly said that OVMF uses multiple GHCBs from SEC to
> DXE. There is no unregister, registering a new GHCB is a hint to
> hypervisor that it should drop the old GHCB mapping. The GHCB
> registration is not a PSP function, and are not designed to mitigate a
> security exploits. It is purely a hypevisor virtualized feature.

Yes, very reasonable; it's a new "paravirt op" basically, where the
guest provides additional info to the hypervisor, for performance
optimization (or simplicity of code / implementation). That motivation
should be clarified.

> 
> 
>>> I'll stop reviewing here, because I think I need to understand your
>>> answers. I'd like to have a rudimentary mental basis for reviewing the rest.
>> ... interestingly, with reference to my question (2) under patch "RFC v2
>> 02/28", the GHCB GPA registration function is one that can *only* be
>> performed with the GHCB MSR protocol, and not through the GHCB page.
>>
>> So that shows that the MSR protocol's functions cannot be considered a
>> pure subset of the GHCB page's functions. If
>> SVM_EXIT_HYPERVISOR_FEATURES didn't exist (and the same function would
>> only be accessible via GHCB_HYPERVISOR_FEATURES_REQUEST), then no
>> "larger principle" would be damaged.
> 
> That is correct, not every exit have both MSR and non MSR protocol based
> vmgexit. It seems that during the spec review no other HV vendor saw the
> need for non-MSR based exit. Certainly, I don't see a need for it in KVM
> and can't comment on other HV ;)

I think a general comment that there's no intent to make either access
method a subset of the other could be helpful. Personally I don't mind
if an interface spec grows organically (i.e. if something is not
specified because people have never needed it). I just didn't know what
to expect.

Also, I'm sorry that I'm looking at the new version(s) of the spec only
now. I can usually deal with abstract interfaces only when there's code
and actual use cases.

Thanks
Laszlo



> 
> 
>>
>> Thanks
>> Laszlo
>>
> 


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 03/28] MdePkg: Define the GHCB GPA structure
  2021-05-03 13:50         ` Laszlo Ersek
@ 2021-05-03 13:55           ` Laszlo Ersek
  0 siblings, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-03 13:55 UTC (permalink / raw)
  To: Brijesh Singh, devel
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/03/21 15:50, Laszlo Ersek wrote:
> On 05/03/21 14:55, Brijesh Singh wrote:
>>
>> On 5/3/21 7:19 AM, Laszlo Ersek wrote:
>>> On 05/03/21 12:24, Laszlo Ersek wrote:
>>>> On 04/30/21 13:51, Brijesh Singh wrote:
>>>>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C9eac9a93753d403dcc4d08d90e2dbcb5%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637556411874265560%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=eNafEGfhCMOkOboQOJnxq8Rw%2BOTuvAUGIziDuELV8%2Bk%3D&amp;reserved=0
>>>>>
>>>>> An SEV-SNP guest is required to perform the GHCB GPA registration. See
>>>>> the GHCB specification for further details.
>>>>>
>>>>> Cc: James Bottomley <jejb@linux.ibm.com>
>>>>> Cc: Min Xu <min.m.xu@intel.com>
>>>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>>>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>>>>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>>>>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>>>>> Cc: Laszlo Ersek <lersek@redhat.com>
>>>>> Cc: Erdem Aktas <erdemaktas@google.com>
>>>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>>>> ---
>>>>>  MdePkg/Include/Register/Amd/Fam17Msr.h | 7 +++++++
>>>>>  1 file changed, 7 insertions(+)
>>>>>
>>>>> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>>>> index a65d51ab12..e19bd04b6c 100644
>>>>> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
>>>>> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>>>> @@ -53,6 +53,11 @@ typedef union {
>>>>>      UINT64  Features:52;
>>>>>    } GhcbHypervisorFeatures;
>>>>>  
>>>>> +  struct {
>>>>> +    UINT64  Function:12;
>>>>> +    UINT64  GuestFrameNumber:52;
>>>>> +  } GhcbGpaRegister;
>>>>> +
>>>>>    VOID    *Ghcb;
>>>>>  
>>>>>    UINT64  GhcbPhysicalAddress;
>>>>> @@ -62,6 +67,8 @@ typedef union {
>>>>>  #define GHCB_INFO_SEV_INFO_GET             2
>>>>>  #define GHCB_INFO_CPUID_REQUEST            4
>>>>>  #define GHCB_INFO_CPUID_RESPONSE           5
>>>>> +#define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
>>>>> +#define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
>>>>>  #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>>>>>  #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>>>>>  #define GHCB_INFO_TERMINATE_REQUEST        256
>>>>>
>>>> The number match the spec (2.0), but I have some remarks / questions.
>>>>
>>>> (1) Patch #2 (SVM_EXIT_HYPERVISOR_FEATURES) and this patch
>>>> (GHCB_INFO_GHCB_GPA_REGISTER_REQUEST) break the nice alignments of the
>>>> macro values (replacement texts) in both header files. Can you prepend a
>>>> whitespace-only patch that simply moves the affected "columns" to the
>>>> right far enough?
>>
>> Sure, do you want me to the post after all the new VMGEXIT's are defined ?
> 
> Optimally, you should please look at the header file at the end of the
> series, and determine the new starting *character* column for the macro
> replacement texts. Then, at the very beginning of the series, pad
> everything to that column. This way, you only need to adjust the
> whitespace once (every macro addition will then fit nicely in place
> later on), and whenever you add a new macro, it will already have the
> final amount of whitespace needed.

Ultimately, with the whitespace fixed (1):

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo

> 
>>
>>
>>>>
>>>> (2) I've checked section 2.3.2 "GHCB GPA Registration" in the spec
>>>> (2.0). What is the specific risk of allowing a guest to switch from one
>>>> GHCB address to another?
>>
>> The GHCB is a shared page, there is no risk to switch from one page to
>> another. This feature is designed to simplify some of the hypervisor
>> implementation. Since the GHCB is accessed on every vmgexit, a
>> hypervisor may prefer to create a map during the registration and refer
>> the map instead of creating a new mapping on every vmgexit.
> 
> OK. So my comment in return is not for the patch set, but the spec: I
> think this motivation should be highlighted in the spec. "Some
> hypervisors may prefer" is vague. Prefer that for what? "Simplicity of
> implementation" is a good answer (eliminate new mappings on every exit),
> but it should be explained (perhaps in informative / non-normative text).
> 
>>
>>
>>>>
>>>> (3) It seems strange to expect that a guest stick with a particular GHCB
>>>> address for its entire lifetime (including firmware and OS) -- in fact
>>>> OVMF already uses multiple GHCB addresses. The spec does not explain how
>>>> the guest can "unlock" (de-register) a registered GHCB address.
>>>> Furthermore, if a guest can do that *at all* (which I think it must --
>>>> we're already using different GHCB addresses between SEC and DXE, for
>>>> example), then what protection does the *temporary* locking of the GHCB
>>>> address provide?
>>
>> The spec does not force that GHCB should *never* change once registered.
>> It says that before switching to new GHCB page, the guest must register
>> the page. As you rightly said that OVMF uses multiple GHCBs from SEC to
>> DXE. There is no unregister, registering a new GHCB is a hint to
>> hypervisor that it should drop the old GHCB mapping. The GHCB
>> registration is not a PSP function, and are not designed to mitigate a
>> security exploits. It is purely a hypevisor virtualized feature.
> 
> Yes, very reasonable; it's a new "paravirt op" basically, where the
> guest provides additional info to the hypervisor, for performance
> optimization (or simplicity of code / implementation). That motivation
> should be clarified.
> 
>>
>>
>>>> I'll stop reviewing here, because I think I need to understand your
>>>> answers. I'd like to have a rudimentary mental basis for reviewing the rest.
>>> ... interestingly, with reference to my question (2) under patch "RFC v2
>>> 02/28", the GHCB GPA registration function is one that can *only* be
>>> performed with the GHCB MSR protocol, and not through the GHCB page.
>>>
>>> So that shows that the MSR protocol's functions cannot be considered a
>>> pure subset of the GHCB page's functions. If
>>> SVM_EXIT_HYPERVISOR_FEATURES didn't exist (and the same function would
>>> only be accessible via GHCB_HYPERVISOR_FEATURES_REQUEST), then no
>>> "larger principle" would be damaged.
>>
>> That is correct, not every exit have both MSR and non MSR protocol based
>> vmgexit. It seems that during the spec review no other HV vendor saw the
>> need for non-MSR based exit. Certainly, I don't see a need for it in KVM
>> and can't comment on other HV ;)
> 
> I think a general comment that there's no intent to make either access
> method a subset of the other could be helpful. Personally I don't mind
> if an interface spec grows organically (i.e. if something is not
> specified because people have never needed it). I just didn't know what
> to expect.
> 
> Also, I'm sorry that I'm looking at the new version(s) of the spec only
> now. I can usually deal with abstract interfaces only when there's code
> and actual use cases.
> 
> Thanks
> Laszlo
> 
> 
> 
>>
>>
>>>
>>> Thanks
>>> Laszlo
>>>
>>
> 
> 
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH RFC v2 21/28] OvmfPkg/MemEncryptSevLib: Add support to validate system RAM
  2021-04-30 11:51 ` [PATCH RFC v2 21/28] OvmfPkg/MemEncryptSevLib: Add support to validate system RAM Brijesh Singh
@ 2021-05-03 14:04   ` Erdem Aktas
  2021-05-03 18:56     ` Brijesh Singh
  0 siblings, 1 reply; 81+ messages in thread
From: Erdem Aktas @ 2021-05-03 14:04 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: devel, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek

> +    //
> +    // If the request page state change is shared then invalidate the pages before
> +    // adding the page in the RMP table.
> +    //
> +    if (State == SevSnpPagePrivate) {
> +      PvalidateRange (Info, 0, i, TRUE);
> +    }
Looks like some copy-paste mistake in the comment.
Also, it checks the  if hypervisor failed to process all the entries
for shared pages, but I do not see that it is checked if for the
private pages. Is there any reason for that?


> +    VmgDone (Ghcb, InterruptState);
> +  }
> +}
> diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> index f9355172d6..1c1e911bd0 100644
> --- a/OvmfPkg/OvmfPkgIa32.dsc
> +++ b/OvmfPkg/OvmfPkgIa32.dsc
> @@ -267,6 +267,7 @@
>  !else
>    CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
>  !endif
> +  MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
>
>  [LibraryClasses.common.PEI_CORE]
>    HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
> diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
> index 3f27d7b90d..804f5d62be 100644
> --- a/OvmfPkg/OvmfPkgIa32X64.dsc
> +++ b/OvmfPkg/OvmfPkgIa32X64.dsc
> @@ -271,6 +271,7 @@
>  !else
>    CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
>  !endif
> +  MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
>
>  [LibraryClasses.common.PEI_CORE]
>    HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH RFC v2 17/28] OvmfPkg/ResetVector: Invalidate the GHCB page
  2021-05-03 13:05   ` Erdem Aktas
@ 2021-05-03 14:28     ` Brijesh Singh
  0 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-05-03 14:28 UTC (permalink / raw)
  To: Erdem Aktas
  Cc: brijesh.singh, devel, James Bottomley, Min Xu, Jiewen Yao,
	Tom Lendacky, Jordan Justen, Ard Biesheuvel, Laszlo Ersek


On 5/3/21 8:05 AM, Erdem Aktas wrote:
> Hi Brijesh,
> I have few naive questions inlined:
>
> On Fri, Apr 30, 2021 at 4:52 AM Brijesh Singh <brijesh.singh@amd.com> wrote:
>> +    ; Use PVALIDATE instruction to invalidate the page
>> +    mov     eax, GHCB_BASE
>> +    mov     ecx, 0
>> +    mov     edx, 0
>> +    DB      0xF2, 0x0F, 0x01, 0xFF
>> +    cmp     eax, 0
>> +    jnz     TerminateSevGuestLaunch
> Any reason why the PVALIDATE return value (EFLAGS.CF) is not checked
> here? IMO, this might lead some page replay attacks.

Ah, good catch. I will add this in next rev.


>
>> +    ;
>> +    ; The page table built above cleared the memory encryption mask from the
>> +    ; GHCB_BASE (aka made it shared). When SEV-SNP is enabled, to maintain
>> +    ; the security guarantees, the page state transition from private to
>> +    ; shared must go through the page invalidation steps. Invalidate the
>> +    ; memory range before loading the page table below.
>> +    ;
>> +    ; NOTE: the invalidation must happen after zeroing the GHCB memory. This
>> +    ;       is because, in the 32-bit mode all the access are considered private.
>> +    ;       The invalidation before the zero'ing will cause a #VC.
>> +    ;
>> +    OneTimeCall  InvalidateGHCBPage
> I am not sure if this is a great idea.
> 1. Zeroing page content before paging is enabled. We are actually
> writing 0s encrypted with a guest key.
> 2. invalidating the page and making it shared.
> Doesn't this reveal a mapping of what 0's look like when a specific
> page is encrypted?  And when the page is marked as shared, from the
> guest and host perspective, it is not zeroed but filled with some data
> that looks random. So what is the purpose of zeroing the page before
> invalidation?

I don't know why zeroing of the GHCB page is done here. The code to
zero'ing was added in ES. I will check with Tom to get a bit of histroy.
The GHCB is not established until we reach to Sec/SecMain.c, so,
theoretically we can remove the zero'ing and push it to Sec/SecMain.c.


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH RFC v2 21/28] OvmfPkg/MemEncryptSevLib: Add support to validate system RAM
  2021-05-03 14:04   ` Erdem Aktas
@ 2021-05-03 18:56     ` Brijesh Singh
  0 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-05-03 18:56 UTC (permalink / raw)
  To: Erdem Aktas
  Cc: brijesh.singh, devel, James Bottomley, Min Xu, Jiewen Yao,
	Tom Lendacky, Jordan Justen, Ard Biesheuvel, Laszlo Ersek


On 5/3/21 9:04 AM, Erdem Aktas wrote:
>> +    //
>> +    // If the request page state change is shared then invalidate the pages before
>> +    // adding the page in the RMP table.
>> +    //
>> +    if (State == SevSnpPagePrivate) {
>> +      PvalidateRange (Info, 0, i, TRUE);
>> +    }
> Looks like some copy-paste mistake in the comment.

Ah, thanks for pointing. Yes its copy-paste error.


> Also, it checks the  if hypervisor failed to process all the entries
> for shared pages, but I do not see that it is checked if for the
> private pages. Is there any reason for that?

Sorry, I am not able to follow, can you please expand your review
comment. In the current patch the approach is:

- If page change request is shared then invalidate the range before
requesting the page state change in the RMP.

- Issue the page state change request. Make sure all the entries are
processed by the hypervisor.

- If the page change request is private then validate the range after
its added in the RMP table.


>
>
>> +    VmgDone (Ghcb, InterruptState);
>> +  }
>> +}
>> diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
>> index f9355172d6..1c1e911bd0 100644
>> --- a/OvmfPkg/OvmfPkgIa32.dsc
>> +++ b/OvmfPkg/OvmfPkgIa32.dsc
>> @@ -267,6 +267,7 @@
>>  !else
>>    CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
>>  !endif
>> +  MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
>>
>>  [LibraryClasses.common.PEI_CORE]
>>    HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
>> diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
>> index 3f27d7b90d..804f5d62be 100644
>> --- a/OvmfPkg/OvmfPkgIa32X64.dsc
>> +++ b/OvmfPkg/OvmfPkgIa32X64.dsc
>> @@ -271,6 +271,7 @@
>>  !else
>>    CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
>>  !endif
>> +  MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
>>
>>  [LibraryClasses.common.PEI_CORE]
>>    HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
>> --
>> 2.17.1
>>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures
  2021-04-30 11:51 ` [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures Brijesh Singh
@ 2021-05-04 12:33   ` Laszlo Ersek
  2021-05-04 13:59     ` Laszlo Ersek
  2021-05-04 18:53     ` Brijesh Singh
  0 siblings, 2 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-04 12:33 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 04/30/21 13:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
> 
> The Page State Change NAE exit will be used by the SEV-SNP guest to
> request a page state change using the GHCB protocol. See the GHCB
> spec section 4.1.6 and 2.3.1 for more detail on the structure
> definitions.
> 
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  MdePkg/Include/Register/Amd/Fam17Msr.h | 15 ++++++++++
>  MdePkg/Include/Register/Amd/Ghcb.h     | 29 ++++++++++++++++++++
>  2 files changed, 44 insertions(+)
> 
> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
> index e19bd04b6c..432cee2feb 100644
> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
> @@ -58,6 +58,19 @@ typedef union {
>      UINT64  GuestFrameNumber:52;
>    } GhcbGpaRegister;
>  
> +  struct {
> +    UINT64 Function:12;
> +    UINT64 GuestFrameNumber:40;
> +    UINT64 Operation:4;
> +    UINT64 Reserved:8;
> +  } SnpPageStateChangeRequest;
> +
> +  struct {
> +    UINT32 Function:12;
> +    UINT32 Reserved:20;
> +    UINT32 ErrorCode;
> +  } SnpPageStateChangeResponse;
> +
>    VOID    *Ghcb;
>  
This matches section 2.3.1 in rev 2.00.

>    UINT64  GhcbPhysicalAddress;
> @@ -69,6 +82,8 @@ typedef union {
>  #define GHCB_INFO_CPUID_RESPONSE           5
>  #define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
>  #define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
> +#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_REQUEST   20
> +#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_RESPONSE  21
>  #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>  #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>  #define GHCB_INFO_TERMINATE_REQUEST        256

Matches section 2.3.1.

> diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
> index 2d64a4c28f..1e7c0daed3 100644
> --- a/MdePkg/Include/Register/Amd/Ghcb.h
> +++ b/MdePkg/Include/Register/Amd/Ghcb.h
> @@ -54,6 +54,7 @@
>  #define SVM_EXIT_NMI_COMPLETE   0x80000003ULL
>  #define SVM_EXIT_AP_RESET_HOLD  0x80000004ULL
>  #define SVM_EXIT_AP_JUMP_TABLE  0x80000005ULL
> +#define SVM_EXIT_SNP_PAGE_STATE_CHANGE    0x80000010ULL
>  #define SVM_EXIT_HYPERVISOR_FEATURES  0x8000FFFDULL
>  #define SVM_EXIT_UNSUPPORTED    0x8000FFFFULL
>  

Matches "Table 5. List of Supported Non-Automatic Events".

> @@ -160,4 +161,32 @@ typedef union {
>  #define GHCB_HV_FEATURES_SNP_AP_CREATE                    (GHCB_HV_FEATURES_SNP | BIT1)
>  #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION         (GHCB_HV_FEATURES_SNP_AP_CREATE | BIT2)
>  #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION_TIMER   (GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION | BIT3)
> +
> +// SNP Page State Change

(1) Comment style.

> +#define SNP_PAGE_STATE_MAX_NPAGES           4095
> +#define SNP_PAGE_STATE_MAX_ENTRY            253
> +#define SNP_PAGE_STATE_PRIVATE              1
> +#define SNP_PAGE_STATE_SHARED               2
> +#define SNP_PAGE_STATE_PSMASH               3
> +#define SNP_PAGE_STATE_UNSMASH              4

(2) The PSMASH and UNSMASH operations are not documented in the rev 2.00
spec, in the GHCB MSR protocol. That's probably because PSMASH and
UNSMASH can only be defined in terms of 2MB pages, and
GHCB_INFO_SNP_PAGE_STATE_CHANGE_REQUEST is suitable only for individual,
4KB pages. I think it would be useful to point out somehow here that
PSMASH and UNSMASH are restricted to the GHCB shared area protocol
(perhaps extend the leading comment on this block of macros).

(3) I don't understand what "MAX_NPAGES" stands for (4095). The rest of
the series never uses the macro, and I can't associate it with anything
from the spec. If the macro is supposed to relate to the 4KB / 2MB page
smashing / splitting, then its replacement text should be 512. Unless
the macro corresponds to a definition in the spec, I think we should
drop it.

> +
> +typedef PACKED struct {
> +  UINT64  CurrentPage:12;
> +  UINT64  GuestFrameNumber:40;
> +  UINT64  Op:4;
> +  UINT64  PageSize:1;
> +  UINT64  Rsvd: 7;
> +} SNP_PAGE_STATE_ENTRY;
> +
> +typedef PACKED struct {
> +  UINT16 CurrentEntry;
> +  UINT16 EndEntry;
> +  UINT32 Rsvd;
> +} SNP_PAGE_STATE_HEADER;

(4) We tend to write

#pragma pack (1)
...
#pragma pack ()

rather than PACKED -- but anyway, is packing really necessary? "Natural
alignment" is required in edk2. I'm OK with packing, but I think the
pragma is the preferred form.

(5) Please spell out both "Rsvd" fields above as "Reserved".

(6) Stray space character in "Rsvd: 7".

(7) The field name "Op" is inconsistent with the other field name
"Operation".

(8) I think there is a bug (typo) in the rev 2.00 spec, in 4.1.6 "SNP
Page State Change": it says

  ... calculated from the supplied guest physical frame number (GFN) for
  the requested page size (GPA = GFN << 12).

But, if you can choose 2MB page size in the request, then the (GPA = GFN
<< 12) formula is not g

(9) If my understanding of the spec is correct, "EndEntry" has
*inclusive* meaning. That's unusual. Any particular reason for not
making "EndEntry" exclusive (in the spec)?

> +
> +typedef struct {
> +  SNP_PAGE_STATE_HEADER  Header;
> +  SNP_PAGE_STATE_ENTRY   Entry[SNP_PAGE_STATE_MAX_ENTRY];
> +} SNP_PAGE_STATE_CHANGE_INFO;
> +
>  #endif
> 

Yes, this looks OK. Size is 2+2+4+253*8 = 2032 bytes, which matches the
size of GHCB.SharedBuffer.

(10) However, *if* you decide to declare SNP_PAGE_STATE_ENTRY and
SNP_PAGE_STATE_HEADER explicitly as packed, then you should do the same
for SNP_PAGE_STATE_CHANGE_INFO.

(11) Like I mentioned earlier, it's probably helpful if you start the
subject line with

  MdePkg/Register/Amd: ...

on all of these MdePkg patches. If that becomes too tight, for some of
the MdePkg patches, then I suggest "MdePkg/Amd: ..." (i.e., drop
"Register").

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support
  2021-04-30 11:51 ` [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support Brijesh Singh
@ 2021-05-04 13:58   ` Laszlo Ersek
  2021-05-04 14:09     ` Laszlo Ersek
                       ` (2 more replies)
  0 siblings, 3 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-04 13:58 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 04/30/21 13:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
>
> The PVALIDATE instruction validates or rescinds validation of a guest
> page RMP entry. Upon completion, a return code is stored in EAX, rFLAGS
> bits OF, ZF, AF, PF and SF are set based on this return code. If the
> instruction completed succesfully, the rFLAGS bit CF indicates if the
> contents of the RMP entry were changed or not.
>
> For more information about the instruction see AMD APM volume 3.
>
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  MdePkg/Include/Library/BaseLib.h          | 37 +++++++++++++++++
>  MdePkg/Library/BaseLib/BaseLib.inf        |  1 +
>  MdePkg/Library/BaseLib/X64/Pvalidate.nasm | 43 ++++++++++++++++++++
>  3 files changed, 81 insertions(+)
>
> diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h
> index 7253997a6f..92ce695e93 100644
> --- a/MdePkg/Include/Library/BaseLib.h
> +++ b/MdePkg/Include/Library/BaseLib.h
> @@ -7518,5 +7518,42 @@ PatchInstructionX86 (
>    IN  UINTN                    ValueSize
>    );
>
> +/**
> + Execute a PVALIDATE instruction to validate or rescnids validation of a guest

(1) typo: "rescnids"


> + page's RMP entry.
> +
> + Upon completion, in addition to the return value the instruction also updates
> + the eFlags. A caller must check both the return code as well as eFlags to
> + determine if the RMP entry has been updated.
> +
> + The function is available on x64.

(2) Please write "X64"; that's how the architecture is usually mentioned
in both the UEFI spec and in edk2.


> +
> + @param[in]    Address        The guest virtual address to validate.
> + @param[in]    PageSize       The page size to use.
> + @param[i]     Validate       Validate or rescinds.
> + @param[out]   Eflags         The value of Eflags after PVALIDATE completion.

(3) Typo: "[i]" should be "[in]".


(4) The order of parameters listed in this comment block differs from
the actual parameter list.

The ECC plugin of the edk2 CI will catch this issue anyway. So, before
submitting the patch set to the list, please submit a personal PR on
github.com against the main repo, just to run CI on your patches.


> +
> + @retval       PvalidateRetValue  The return value from the PVALIDATE instruction.

More on the return value / type later, below.

> +**/
> +typedef enum {
> +  PvalidatePageSize4K = 0,
> +  PvalidatePageSize2MB,
> +} PVALIDATE_PAGE_SIZE;
> +
> +typedef enum {
> +  PvalidateRetSuccess = 0,
> +  PvalidateRetFailInput = 1,
> +  PvalidateRetFailSizemismatch = 6,
> +} PVALIDATE_RET_VALUE;
> +

(5) These typedefs do not belong between the function leading comment
and the function declaration. Please hoist the typedefs just above the
leading comment, and add a separate comment for the typedefs -- using
the proper comment style for typedefs, too.


> +PVALIDATE_RET_VALUE

(6) In my opinion, using an enum for an EFIAPI function's return type is
problematic. According to the UEFI spec (v2.9), "Table 2-3 Common UEFI
Data Types", <Enumerated Type> may correspond to INT32 or UINT32. I
don't like that ambiguity here. The spec also says that such types
should never be used at least as structure fields.

I'm perfectly fine with functions in standard (ISO) C programs returning
enums, but I think the situation is less clear in UEFI. I don't recall
standard interfaces (spec-level, or even edk2 / MdePkg interfaces) that
return enums.

I suggest the following instead. Drop the PVALIDATE_RET_VALUE enum
altogether. Specify EFI_STATUS as the return type, in the declaration of
the function.

In the UEFI spec, Appendix D specifies the numeric values of the status
codes. Furthermore, there are examples for NASM sources using EFI_*
status codes *numerically* in edk2; minimally:

- IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm
- IntelFsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/SecEntry.nasm

Thus, please modify the assembly source code in this patch to return
EFI_SUCCESS (already value 0, conveniently) if the instruction succeeds.

Return EFI_INVALID_PARAMETER (0x8000_0002) in case the instruction fails
with error code 1 (FAIL_INPUT).

Return EFI_UNSUPPORTED (0x8000_0003), or even EFI_NO_MAPPING
(0x8000_0017), for value 6 (FAIL_SIZEMISMATCH).

The leading comment block of the function is supposed to explain these
associations:

  @retval EFI_SUCCESS        Successful completion (regardless of
                             whether the Validated bit changed state).
  @retval INVALID_PARAMETER  Invalid input parameters (FAIL_INPUT).
  @retval EFI_UNSUPPORTED    Page size mismatch between guest (2M) and
                             RMP entry (4K) (FAIL_SIZEMISMATCH).

(Passing in the PVALIDATE_PAGE_SIZE enum, as a parameter, should be
fine, BTW)


(7) According to the AMD APM, "Support for this instruction is indicated
by CPUID Fn8000_001F_EAX[SNP]=1".

Presumably, if the (physical, or emulated) hardware does not support
PVALIDATE, an #UD is raised. That condition should be explained in the
function's leading comment. (Mention the CPUID and the #UD, I guess.)


> +EFIAPI
> +AsmPvalidate (
> +  IN   PVALIDATE_PAGE_SIZE     PageSize,
> +  IN   BOOLEAN                 Validate,
> +  IN   UINTN                   Address,

(8) This should be EFI_PHYSICAL_ADDRESS, not UINTN.


> +  OUT  IA32_EFLAGS32           *Eflags
> +  );
> +
>  #endif // defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
>  #endif // !defined (__BASE_LIB__)

(9) Unless you foresee particular uses for eflags *other than* CF, I
would suggest replacing the Eflags output parameter with

  OUT BOOLEAN   *RmpEntryUpdated

The function would still only have 4 parameters, which shouldn't be
difficult to handle in the assembly implementation (i.e. write to the
UINT8 (= BOOLEAN) object referenced by "RmpEntryUpdated"). EFIAPI means
that the first four params are passed in RCX, RDX, R8, R9.

Thus far, I can see only one AsmPvalidate() call: in IssuePvalidate(),
from patch #21 ("OvmfPkg/MemEncryptSevLib: Add support to validate
system RAM"). And there, CF looks sufficient.


(10) The instruction is X64 only, but you are providing the declaration
even if MDE_CPU_IA32 is #defined. That seems wrong; even the declaration
should be invisible in that case. Please declare the function for
MDE_CPU_X64 only.


> diff --git a/MdePkg/Library/BaseLib/BaseLib.inf b/MdePkg/Library/BaseLib/BaseLib.inf
> index b76f3af380..d33b4a8f7d 100644
> --- a/MdePkg/Library/BaseLib/BaseLib.inf
> +++ b/MdePkg/Library/BaseLib/BaseLib.inf
> @@ -321,6 +321,7 @@
>    X64/XGetBv.nasm
>    X64/XSetBv.nasm
>    X64/VmgExit.nasm
> +  X64/Pvalidate.nasm
>    ChkStkGcc.c  | GCC
>
>  [Sources.EBC]

(11) This list of source files is already not sorted alphabetically,
unfortunately. But we can still do better than this: I suggest inserting
"X64/Pvalidate.nasm" just before "X64/RdRand.nasm".


(12) Your git setup seems less than ideal for formatting edk2 patches.
The @@ hunk header above does not show the INF file section being
modified. It should look something like this:

  @@ -317,6 +317,7 @@ [Sources.X64]
                      ^^^^^^^^^^^^^

Please run the "BaseTools/Scripts/SetupGit.py" script in your working
tree.

Alternatively, please see "xfuncname" at
<https://github.com/tianocore/tianocore.github.io/wiki/Laszlo%27s-unkempt-git-guide-for-edk2-contributors-and-maintainers#contrib-05>.

This is of course not a bug in the patch, but fixing your setup will
help with the next round of review.


> diff --git a/MdePkg/Library/BaseLib/X64/Pvalidate.nasm b/MdePkg/Library/BaseLib/X64/Pvalidate.nasm
> new file mode 100644
> index 0000000000..f2aba114ac
> --- /dev/null
> +++ b/MdePkg/Library/BaseLib/X64/Pvalidate.nasm
> @@ -0,0 +1,43 @@
> +;-----------------------------------------------------------------------------
> +;
> +; Copyright (c) 2020-2021, AMD. All rights reserved.<BR>

(13) I believe we don't introduce new files with copyright notices
referring to the past. IOW, I think you should only say "2021" here.


> +; SPDX-License-Identifier: BSD-2-Clause-Patent
> +;
> +; Module Name:
> +;
> +;   Pvalidate.Asm
> +;
> +; Abstract:
> +;
> +;   AsmPvalidate function
> +;
> +; Notes:
> +;

(14) I defer to the MdePkg maintainers on this, but "Module Name" is
plain wrong, and the Abstract is useless. Either fix those up please
("Abstract" could be a copy of the corrected leading comment block), or
just drop them both.


> +;-----------------------------------------------------------------------------
> +
> +    SECTION .text
> +
> +;-----------------------------------------------------------------------------
> +;  PvalidateRetValue
> +;  EFIAPI
> +;  AsmPvalidate (
> +;    IN   UINT32  RmpPageSize
> +;    IN   UINT32  Validate,
> +;    IN   UINTN   Address,
> +;    OUT  UINTN  *Eflags,
> +;    )
> +;-----------------------------------------------------------------------------

(15) Please update this accordingly to the corrected function
specification.


> +global ASM_PFX(AsmPvalidate)
> +ASM_PFX(AsmPvalidate):
> +  mov     rax, r8
> +
> +  ; PVALIDATE instruction opcode
> +  DB      0xF2, 0x0F, 0x01, 0xFF

This is bad practice; we make every effort to avoid DB-encoded
instructions.

We have two PVALIDATE instances in the patch set (... that I can see
immediateyl); the first here, and the other in
"OvmfPkg/ResetVector/Ia32/PageTables64.asm" (from patch #17,
"OvmfPkg/ResetVector: Invalidate the GHCB page"). Therefore, hiding the
encoding of PVALIDATE behind a NASM macro definitely makes sense.

(16a) Please file a NASM feature request for PVALIDATE at
<https://bugzilla.nasm.us>.

(16b) In the present MdePkg patch, please extend the file

  MdePkg/Include/X64/Nasm.inc

as follows:

> diff --git a/MdePkg/Include/X64/Nasm.inc b/MdePkg/Include/X64/Nasm.inc
> index 527f71e9eb4d..ff37f1e35707 100644
> --- a/MdePkg/Include/X64/Nasm.inc
> +++ b/MdePkg/Include/X64/Nasm.inc
> @@ -33,6 +33,15 @@
>      DB 0xF3, 0x48, 0x0F, 0xAE, 0xE8
>  %endmacro
>
> +;
> +; Macro for the PVALIDATE instruction, defined in AMD publication #24594
> +; revision 3.32. NASM feature request URL:
> +; <https://bugzilla.nasm.us/show_bug.cgi?id=FIXME>.
> +;
> +%macro PVALIDATE       0
> +    DB 0xF2, 0x0F, 0x01, 0xFF
> +%endmacro
> +
>  ; NASM provides built-in macros STRUC and ENDSTRUC for structure definition.
>  ; For example, to define a structure called mytype containing a longword,
>  ; a word, a byte and a string of bytes, you might code

(16c) Please replace the FIXME placeholder above with the actual NASM BZ
number (from (16a)).

(16d) In the "MdePkg/Library/BaseLib/X64/Pvalidate.nasm" source file,
and also (later) in the "OvmfPkg/ResetVector/Ia32/PageTables64.asm"
source file, please use the PVALIDATE macro, in place of the naked DBs.


Back to your patch:

On 04/30/21 13:51, Brijesh Singh wrote:
> +
> +  ; Read the Eflags
> +  pushfq
> +  pop     r8
> +  mov     [r9], r8
> +
> +  ; The PVALIDATE instruction returns the status in rax register.
> +  ret
>

(17) The assembly code should be updated to match the new interface
contract (parameter order, parameter types, return values).


I'll continue reviewing the series later this week (hopefully tomorrow).

Thanks,
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures
  2021-05-04 12:33   ` [edk2-devel] " Laszlo Ersek
@ 2021-05-04 13:59     ` Laszlo Ersek
  2021-05-04 14:48       ` Lendacky, Thomas
  2021-05-04 18:53     ` Brijesh Singh
  1 sibling, 1 reply; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-04 13:59 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/04/21 14:33, Laszlo Ersek wrote:
> On 04/30/21 13:51, Brijesh Singh wrote:
>> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
>>
>> The Page State Change NAE exit will be used by the SEV-SNP guest to
>> request a page state change using the GHCB protocol. See the GHCB
>> spec section 4.1.6 and 2.3.1 for more detail on the structure
>> definitions.
>>
>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  MdePkg/Include/Register/Amd/Fam17Msr.h | 15 ++++++++++
>>  MdePkg/Include/Register/Amd/Ghcb.h     | 29 ++++++++++++++++++++
>>  2 files changed, 44 insertions(+)
>>
>> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
>> index e19bd04b6c..432cee2feb 100644
>> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
>> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
>> @@ -58,6 +58,19 @@ typedef union {
>>      UINT64  GuestFrameNumber:52;
>>    } GhcbGpaRegister;
>>  
>> +  struct {
>> +    UINT64 Function:12;
>> +    UINT64 GuestFrameNumber:40;
>> +    UINT64 Operation:4;
>> +    UINT64 Reserved:8;
>> +  } SnpPageStateChangeRequest;
>> +
>> +  struct {
>> +    UINT32 Function:12;
>> +    UINT32 Reserved:20;
>> +    UINT32 ErrorCode;
>> +  } SnpPageStateChangeResponse;
>> +
>>    VOID    *Ghcb;
>>  
> This matches section 2.3.1 in rev 2.00.
> 
>>    UINT64  GhcbPhysicalAddress;
>> @@ -69,6 +82,8 @@ typedef union {
>>  #define GHCB_INFO_CPUID_RESPONSE           5
>>  #define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
>>  #define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
>> +#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_REQUEST   20
>> +#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_RESPONSE  21
>>  #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>>  #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>>  #define GHCB_INFO_TERMINATE_REQUEST        256
> 
> Matches section 2.3.1.
> 
>> diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
>> index 2d64a4c28f..1e7c0daed3 100644
>> --- a/MdePkg/Include/Register/Amd/Ghcb.h
>> +++ b/MdePkg/Include/Register/Amd/Ghcb.h
>> @@ -54,6 +54,7 @@
>>  #define SVM_EXIT_NMI_COMPLETE   0x80000003ULL
>>  #define SVM_EXIT_AP_RESET_HOLD  0x80000004ULL
>>  #define SVM_EXIT_AP_JUMP_TABLE  0x80000005ULL
>> +#define SVM_EXIT_SNP_PAGE_STATE_CHANGE    0x80000010ULL
>>  #define SVM_EXIT_HYPERVISOR_FEATURES  0x8000FFFDULL
>>  #define SVM_EXIT_UNSUPPORTED    0x8000FFFFULL
>>  
> 
> Matches "Table 5. List of Supported Non-Automatic Events".
> 
>> @@ -160,4 +161,32 @@ typedef union {
>>  #define GHCB_HV_FEATURES_SNP_AP_CREATE                    (GHCB_HV_FEATURES_SNP | BIT1)
>>  #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION         (GHCB_HV_FEATURES_SNP_AP_CREATE | BIT2)
>>  #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION_TIMER   (GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION | BIT3)
>> +
>> +// SNP Page State Change
> 
> (1) Comment style.
> 
>> +#define SNP_PAGE_STATE_MAX_NPAGES           4095
>> +#define SNP_PAGE_STATE_MAX_ENTRY            253
>> +#define SNP_PAGE_STATE_PRIVATE              1
>> +#define SNP_PAGE_STATE_SHARED               2
>> +#define SNP_PAGE_STATE_PSMASH               3
>> +#define SNP_PAGE_STATE_UNSMASH              4
> 
> (2) The PSMASH and UNSMASH operations are not documented in the rev 2.00
> spec, in the GHCB MSR protocol. That's probably because PSMASH and
> UNSMASH can only be defined in terms of 2MB pages, and
> GHCB_INFO_SNP_PAGE_STATE_CHANGE_REQUEST is suitable only for individual,
> 4KB pages. I think it would be useful to point out somehow here that
> PSMASH and UNSMASH are restricted to the GHCB shared area protocol
> (perhaps extend the leading comment on this block of macros).
> 
> (3) I don't understand what "MAX_NPAGES" stands for (4095). The rest of
> the series never uses the macro, and I can't associate it with anything
> from the spec. If the macro is supposed to relate to the 4KB / 2MB page
> smashing / splitting, then its replacement text should be 512. Unless
> the macro corresponds to a definition in the spec, I think we should
> drop it.
> 
>> +
>> +typedef PACKED struct {
>> +  UINT64  CurrentPage:12;
>> +  UINT64  GuestFrameNumber:40;
>> +  UINT64  Op:4;
>> +  UINT64  PageSize:1;
>> +  UINT64  Rsvd: 7;
>> +} SNP_PAGE_STATE_ENTRY;
>> +
>> +typedef PACKED struct {
>> +  UINT16 CurrentEntry;
>> +  UINT16 EndEntry;
>> +  UINT32 Rsvd;
>> +} SNP_PAGE_STATE_HEADER;
> 
> (4) We tend to write
> 
> #pragma pack (1)
> ...
> #pragma pack ()
> 
> rather than PACKED -- but anyway, is packing really necessary? "Natural
> alignment" is required in edk2. I'm OK with packing, but I think the
> pragma is the preferred form.
> 
> (5) Please spell out both "Rsvd" fields above as "Reserved".
> 
> (6) Stray space character in "Rsvd: 7".
> 
> (7) The field name "Op" is inconsistent with the other field name
> "Operation".
> 
> (8) I think there is a bug (typo) in the rev 2.00 spec, in 4.1.6 "SNP
> Page State Change": it says
> 
>   ... calculated from the supplied guest physical frame number (GFN) for
>   the requested page size (GPA = GFN << 12).
> 
> But, if you can choose 2MB page size in the request, then the (GPA = GFN
> << 12) formula is not g

Sorry, unfinished sentence: I meant that the formula was not generally
correct.

Thanks
Laszlo

> 
> (9) If my understanding of the spec is correct, "EndEntry" has
> *inclusive* meaning. That's unusual. Any particular reason for not
> making "EndEntry" exclusive (in the spec)?
> 
>> +
>> +typedef struct {
>> +  SNP_PAGE_STATE_HEADER  Header;
>> +  SNP_PAGE_STATE_ENTRY   Entry[SNP_PAGE_STATE_MAX_ENTRY];
>> +} SNP_PAGE_STATE_CHANGE_INFO;
>> +
>>  #endif
>>
> 
> Yes, this looks OK. Size is 2+2+4+253*8 = 2032 bytes, which matches the
> size of GHCB.SharedBuffer.
> 
> (10) However, *if* you decide to declare SNP_PAGE_STATE_ENTRY and
> SNP_PAGE_STATE_HEADER explicitly as packed, then you should do the same
> for SNP_PAGE_STATE_CHANGE_INFO.
> 
> (11) Like I mentioned earlier, it's probably helpful if you start the
> subject line with
> 
>   MdePkg/Register/Amd: ...
> 
> on all of these MdePkg patches. If that becomes too tight, for some of
> the MdePkg patches, then I suggest "MdePkg/Amd: ..." (i.e., drop
> "Register").
> 
> Thanks
> Laszlo
> 


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support
  2021-05-04 13:58   ` [edk2-devel] " Laszlo Ersek
@ 2021-05-04 14:09     ` Laszlo Ersek
  2021-05-04 19:07     ` Brijesh Singh
       [not found]     ` <167BF2A01FA60569.6407@groups.io>
  2 siblings, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-04 14:09 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/04/21 15:58, Laszlo Ersek wrote:

> The leading comment block of the function is supposed to explain these
> associations:
> 
>   @retval EFI_SUCCESS        Successful completion (regardless of
>                              whether the Validated bit changed state).
>   @retval INVALID_PARAMETER  Invalid input parameters (FAIL_INPUT).
>   @retval EFI_UNSUPPORTED    Page size mismatch between guest (2M) and
>                              RMP entry (4K) (FAIL_SIZEMISMATCH).

Apologies, that should have been "EFI_INVALID_PARAMETER", not just
"INVALID_PARAMETER".

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures
  2021-05-04 13:59     ` Laszlo Ersek
@ 2021-05-04 14:48       ` Lendacky, Thomas
  2021-05-04 18:07         ` Laszlo Ersek
  0 siblings, 1 reply; 81+ messages in thread
From: Lendacky, Thomas @ 2021-05-04 14:48 UTC (permalink / raw)
  To: Laszlo Ersek, devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas



On 5/4/21 8:59 AM, Laszlo Ersek wrote:
> On 05/04/21 14:33, Laszlo Ersek wrote:
>> On 04/30/21 13:51, Brijesh Singh wrote:
>>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cthomas.lendacky%40amd.com%7Cf400bca14b6f4f138a1908d90f05090f%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637557336582189771%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=bjXNVWGpurRGUZkjemvDQR%2FYnEQRG9ENN22jUjtkNP0%3D&amp;reserved=0
>>>
>>> The Page State Change NAE exit will be used by the SEV-SNP guest to
>>> request a page state change using the GHCB protocol. See the GHCB
>>> spec section 4.1.6 and 2.3.1 for more detail on the structure
>>> definitions.
>>>
>>> Cc: James Bottomley <jejb@linux.ibm.com>
>>> Cc: Min Xu <min.m.xu@intel.com>
>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>>> Cc: Laszlo Ersek <lersek@redhat.com>
>>> Cc: Erdem Aktas <erdemaktas@google.com>
>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>> ---
>>>  MdePkg/Include/Register/Amd/Fam17Msr.h | 15 ++++++++++
>>>  MdePkg/Include/Register/Amd/Ghcb.h     | 29 ++++++++++++++++++++
>>>  2 files changed, 44 insertions(+)
>>>
>>> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>> index e19bd04b6c..432cee2feb 100644
>>> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
>>> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>> @@ -58,6 +58,19 @@ typedef union {
>>>      UINT64  GuestFrameNumber:52;
>>>    } GhcbGpaRegister;
>>>  
>>> +  struct {
>>> +    UINT64 Function:12;
>>> +    UINT64 GuestFrameNumber:40;
>>> +    UINT64 Operation:4;
>>> +    UINT64 Reserved:8;
>>> +  } SnpPageStateChangeRequest;
>>> +
>>> +  struct {
>>> +    UINT32 Function:12;
>>> +    UINT32 Reserved:20;
>>> +    UINT32 ErrorCode;
>>> +  } SnpPageStateChangeResponse;
>>> +
>>>    VOID    *Ghcb;
>>>  
>> This matches section 2.3.1 in rev 2.00.
>>
>>>    UINT64  GhcbPhysicalAddress;
>>> @@ -69,6 +82,8 @@ typedef union {
>>>  #define GHCB_INFO_CPUID_RESPONSE           5
>>>  #define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
>>>  #define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
>>> +#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_REQUEST   20
>>> +#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_RESPONSE  21
>>>  #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>>>  #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>>>  #define GHCB_INFO_TERMINATE_REQUEST        256
>>
>> Matches section 2.3.1.
>>
>>> diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
>>> index 2d64a4c28f..1e7c0daed3 100644
>>> --- a/MdePkg/Include/Register/Amd/Ghcb.h
>>> +++ b/MdePkg/Include/Register/Amd/Ghcb.h
>>> @@ -54,6 +54,7 @@
>>>  #define SVM_EXIT_NMI_COMPLETE   0x80000003ULL
>>>  #define SVM_EXIT_AP_RESET_HOLD  0x80000004ULL
>>>  #define SVM_EXIT_AP_JUMP_TABLE  0x80000005ULL
>>> +#define SVM_EXIT_SNP_PAGE_STATE_CHANGE    0x80000010ULL
>>>  #define SVM_EXIT_HYPERVISOR_FEATURES  0x8000FFFDULL
>>>  #define SVM_EXIT_UNSUPPORTED    0x8000FFFFULL
>>>  
>>
>> Matches "Table 5. List of Supported Non-Automatic Events".
>>
>>> @@ -160,4 +161,32 @@ typedef union {
>>>  #define GHCB_HV_FEATURES_SNP_AP_CREATE                    (GHCB_HV_FEATURES_SNP | BIT1)
>>>  #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION         (GHCB_HV_FEATURES_SNP_AP_CREATE | BIT2)
>>>  #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION_TIMER   (GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION | BIT3)
>>> +
>>> +// SNP Page State Change
>>
>> (1) Comment style.
>>
>>> +#define SNP_PAGE_STATE_MAX_NPAGES           4095
>>> +#define SNP_PAGE_STATE_MAX_ENTRY            253
>>> +#define SNP_PAGE_STATE_PRIVATE              1
>>> +#define SNP_PAGE_STATE_SHARED               2
>>> +#define SNP_PAGE_STATE_PSMASH               3
>>> +#define SNP_PAGE_STATE_UNSMASH              4
>>
>> (2) The PSMASH and UNSMASH operations are not documented in the rev 2.00
>> spec, in the GHCB MSR protocol. That's probably because PSMASH and
>> UNSMASH can only be defined in terms of 2MB pages, and
>> GHCB_INFO_SNP_PAGE_STATE_CHANGE_REQUEST is suitable only for individual,
>> 4KB pages. I think it would be useful to point out somehow here that
>> PSMASH and UNSMASH are restricted to the GHCB shared area protocol
>> (perhaps extend the leading comment on this block of macros).
>>
>> (3) I don't understand what "MAX_NPAGES" stands for (4095). The rest of
>> the series never uses the macro, and I can't associate it with anything
>> from the spec. If the macro is supposed to relate to the 4KB / 2MB page
>> smashing / splitting, then its replacement text should be 512. Unless
>> the macro corresponds to a definition in the spec, I think we should
>> drop it.
>>
>>> +
>>> +typedef PACKED struct {
>>> +  UINT64  CurrentPage:12;
>>> +  UINT64  GuestFrameNumber:40;
>>> +  UINT64  Op:4;
>>> +  UINT64  PageSize:1;
>>> +  UINT64  Rsvd: 7;
>>> +} SNP_PAGE_STATE_ENTRY;
>>> +
>>> +typedef PACKED struct {
>>> +  UINT16 CurrentEntry;
>>> +  UINT16 EndEntry;
>>> +  UINT32 Rsvd;
>>> +} SNP_PAGE_STATE_HEADER;
>>
>> (4) We tend to write
>>
>> #pragma pack (1)
>> ...
>> #pragma pack ()
>>
>> rather than PACKED -- but anyway, is packing really necessary? "Natural
>> alignment" is required in edk2. I'm OK with packing, but I think the
>> pragma is the preferred form.
>>
>> (5) Please spell out both "Rsvd" fields above as "Reserved".
>>
>> (6) Stray space character in "Rsvd: 7".
>>
>> (7) The field name "Op" is inconsistent with the other field name
>> "Operation".
>>
>> (8) I think there is a bug (typo) in the rev 2.00 spec, in 4.1.6 "SNP
>> Page State Change": it says
>>
>>   ... calculated from the supplied guest physical frame number (GFN) for
>>   the requested page size (GPA = GFN << 12).
>>
>> But, if you can choose 2MB page size in the request, then the (GPA = GFN
>> << 12) formula is not g
> 
> Sorry, unfinished sentence: I meant that the formula was not generally
> correct.

Actually, for any page size, the GPA for any GFN is GFN << 12.

For the SNP Page State Change NAE event, it is up to the hypervisor to
ensure that the GFN/GPA supplied is aligned appropriately for the
requested page size (see 4.1.6 of the GHCB spec where the page operations
are defined). A GFN is naturally 4K aligned, so only a 2MB page size needs
GFN/GPA alignment validation.

For the SNP Page State Change MSR protocol, only a 4K page size is supported.

Thanks,
Tom

> 
> Thanks
> Laszlo
> 
>>
>> (9) If my understanding of the spec is correct, "EndEntry" has
>> *inclusive* meaning. That's unusual. Any particular reason for not
>> making "EndEntry" exclusive (in the spec)?
>>
>>> +
>>> +typedef struct {
>>> +  SNP_PAGE_STATE_HEADER  Header;
>>> +  SNP_PAGE_STATE_ENTRY   Entry[SNP_PAGE_STATE_MAX_ENTRY];
>>> +} SNP_PAGE_STATE_CHANGE_INFO;
>>> +
>>>  #endif
>>>
>>
>> Yes, this looks OK. Size is 2+2+4+253*8 = 2032 bytes, which matches the
>> size of GHCB.SharedBuffer.
>>
>> (10) However, *if* you decide to declare SNP_PAGE_STATE_ENTRY and
>> SNP_PAGE_STATE_HEADER explicitly as packed, then you should do the same
>> for SNP_PAGE_STATE_CHANGE_INFO.
>>
>> (11) Like I mentioned earlier, it's probably helpful if you start the
>> subject line with
>>
>>   MdePkg/Register/Amd: ...
>>
>> on all of these MdePkg patches. If that becomes too tight, for some of
>> the MdePkg patches, then I suggest "MdePkg/Amd: ..." (i.e., drop
>> "Register").
>>
>> Thanks
>> Laszlo
>>
> 

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures
  2021-05-04 14:48       ` Lendacky, Thomas
@ 2021-05-04 18:07         ` Laszlo Ersek
  0 siblings, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-04 18:07 UTC (permalink / raw)
  To: Tom Lendacky, devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/04/21 16:48, Tom Lendacky wrote:
> 
> 
> On 5/4/21 8:59 AM, Laszlo Ersek wrote:
>> On 05/04/21 14:33, Laszlo Ersek wrote:
>>> On 04/30/21 13:51, Brijesh Singh wrote:
>>>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cthomas.lendacky%40amd.com%7Cf400bca14b6f4f138a1908d90f05090f%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637557336582189771%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=bjXNVWGpurRGUZkjemvDQR%2FYnEQRG9ENN22jUjtkNP0%3D&amp;reserved=0
>>>>
>>>> The Page State Change NAE exit will be used by the SEV-SNP guest to
>>>> request a page state change using the GHCB protocol. See the GHCB
>>>> spec section 4.1.6 and 2.3.1 for more detail on the structure
>>>> definitions.
>>>>
>>>> Cc: James Bottomley <jejb@linux.ibm.com>
>>>> Cc: Min Xu <min.m.xu@intel.com>
>>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>>>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>>>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>>>> Cc: Laszlo Ersek <lersek@redhat.com>
>>>> Cc: Erdem Aktas <erdemaktas@google.com>
>>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>>> ---
>>>>  MdePkg/Include/Register/Amd/Fam17Msr.h | 15 ++++++++++
>>>>  MdePkg/Include/Register/Amd/Ghcb.h     | 29 ++++++++++++++++++++
>>>>  2 files changed, 44 insertions(+)
>>>>
>>>> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>>> index e19bd04b6c..432cee2feb 100644
>>>> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
>>>> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
>>>> @@ -58,6 +58,19 @@ typedef union {
>>>>      UINT64  GuestFrameNumber:52;
>>>>    } GhcbGpaRegister;
>>>>  
>>>> +  struct {
>>>> +    UINT64 Function:12;
>>>> +    UINT64 GuestFrameNumber:40;
>>>> +    UINT64 Operation:4;
>>>> +    UINT64 Reserved:8;
>>>> +  } SnpPageStateChangeRequest;
>>>> +
>>>> +  struct {
>>>> +    UINT32 Function:12;
>>>> +    UINT32 Reserved:20;
>>>> +    UINT32 ErrorCode;
>>>> +  } SnpPageStateChangeResponse;
>>>> +
>>>>    VOID    *Ghcb;
>>>>  
>>> This matches section 2.3.1 in rev 2.00.
>>>
>>>>    UINT64  GhcbPhysicalAddress;
>>>> @@ -69,6 +82,8 @@ typedef union {
>>>>  #define GHCB_INFO_CPUID_RESPONSE           5
>>>>  #define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
>>>>  #define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
>>>> +#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_REQUEST   20
>>>> +#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_RESPONSE  21
>>>>  #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>>>>  #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>>>>  #define GHCB_INFO_TERMINATE_REQUEST        256
>>>
>>> Matches section 2.3.1.
>>>
>>>> diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
>>>> index 2d64a4c28f..1e7c0daed3 100644
>>>> --- a/MdePkg/Include/Register/Amd/Ghcb.h
>>>> +++ b/MdePkg/Include/Register/Amd/Ghcb.h
>>>> @@ -54,6 +54,7 @@
>>>>  #define SVM_EXIT_NMI_COMPLETE   0x80000003ULL
>>>>  #define SVM_EXIT_AP_RESET_HOLD  0x80000004ULL
>>>>  #define SVM_EXIT_AP_JUMP_TABLE  0x80000005ULL
>>>> +#define SVM_EXIT_SNP_PAGE_STATE_CHANGE    0x80000010ULL
>>>>  #define SVM_EXIT_HYPERVISOR_FEATURES  0x8000FFFDULL
>>>>  #define SVM_EXIT_UNSUPPORTED    0x8000FFFFULL
>>>>  
>>>
>>> Matches "Table 5. List of Supported Non-Automatic Events".
>>>
>>>> @@ -160,4 +161,32 @@ typedef union {
>>>>  #define GHCB_HV_FEATURES_SNP_AP_CREATE                    (GHCB_HV_FEATURES_SNP | BIT1)
>>>>  #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION         (GHCB_HV_FEATURES_SNP_AP_CREATE | BIT2)
>>>>  #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION_TIMER   (GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION | BIT3)
>>>> +
>>>> +// SNP Page State Change
>>>
>>> (1) Comment style.
>>>
>>>> +#define SNP_PAGE_STATE_MAX_NPAGES           4095
>>>> +#define SNP_PAGE_STATE_MAX_ENTRY            253
>>>> +#define SNP_PAGE_STATE_PRIVATE              1
>>>> +#define SNP_PAGE_STATE_SHARED               2
>>>> +#define SNP_PAGE_STATE_PSMASH               3
>>>> +#define SNP_PAGE_STATE_UNSMASH              4
>>>
>>> (2) The PSMASH and UNSMASH operations are not documented in the rev 2.00
>>> spec, in the GHCB MSR protocol. That's probably because PSMASH and
>>> UNSMASH can only be defined in terms of 2MB pages, and
>>> GHCB_INFO_SNP_PAGE_STATE_CHANGE_REQUEST is suitable only for individual,
>>> 4KB pages. I think it would be useful to point out somehow here that
>>> PSMASH and UNSMASH are restricted to the GHCB shared area protocol
>>> (perhaps extend the leading comment on this block of macros).
>>>
>>> (3) I don't understand what "MAX_NPAGES" stands for (4095). The rest of
>>> the series never uses the macro, and I can't associate it with anything
>>> from the spec. If the macro is supposed to relate to the 4KB / 2MB page
>>> smashing / splitting, then its replacement text should be 512. Unless
>>> the macro corresponds to a definition in the spec, I think we should
>>> drop it.
>>>
>>>> +
>>>> +typedef PACKED struct {
>>>> +  UINT64  CurrentPage:12;
>>>> +  UINT64  GuestFrameNumber:40;
>>>> +  UINT64  Op:4;
>>>> +  UINT64  PageSize:1;
>>>> +  UINT64  Rsvd: 7;
>>>> +} SNP_PAGE_STATE_ENTRY;
>>>> +
>>>> +typedef PACKED struct {
>>>> +  UINT16 CurrentEntry;
>>>> +  UINT16 EndEntry;
>>>> +  UINT32 Rsvd;
>>>> +} SNP_PAGE_STATE_HEADER;
>>>
>>> (4) We tend to write
>>>
>>> #pragma pack (1)
>>> ...
>>> #pragma pack ()
>>>
>>> rather than PACKED -- but anyway, is packing really necessary? "Natural
>>> alignment" is required in edk2. I'm OK with packing, but I think the
>>> pragma is the preferred form.
>>>
>>> (5) Please spell out both "Rsvd" fields above as "Reserved".
>>>
>>> (6) Stray space character in "Rsvd: 7".
>>>
>>> (7) The field name "Op" is inconsistent with the other field name
>>> "Operation".
>>>
>>> (8) I think there is a bug (typo) in the rev 2.00 spec, in 4.1.6 "SNP
>>> Page State Change": it says
>>>
>>>   ... calculated from the supplied guest physical frame number (GFN) for
>>>   the requested page size (GPA = GFN << 12).
>>>
>>> But, if you can choose 2MB page size in the request, then the (GPA = GFN
>>> << 12) formula is not g
>>
>> Sorry, unfinished sentence: I meant that the formula was not generally
>> correct.
> 
> Actually, for any page size, the GPA for any GFN is GFN << 12.
> 
> For the SNP Page State Change NAE event, it is up to the hypervisor to
> ensure that the GFN/GPA supplied is aligned appropriately for the
> requested page size (see 4.1.6 of the GHCB spec where the page operations
> are defined). A GFN is naturally 4K aligned, so only a 2MB page size needs
> GFN/GPA alignment validation.

Thanks. I guess I was confused by the term "for the requested page size".

> For the SNP Page State Change MSR protocol, only a 4K page size is supported.

Yes, that's clear.

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures
  2021-05-04 12:33   ` [edk2-devel] " Laszlo Ersek
  2021-05-04 13:59     ` Laszlo Ersek
@ 2021-05-04 18:53     ` Brijesh Singh
  2021-05-05 18:24       ` Laszlo Ersek
  1 sibling, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-05-04 18:53 UTC (permalink / raw)
  To: Laszlo Ersek, devel
  Cc: brijesh.singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/4/21 7:33 AM, Laszlo Ersek wrote:
> On 04/30/21 13:51, Brijesh Singh wrote:
>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7Cbb2eaad10f574a464cb008d90ef8e5b4%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637557284470753463%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=fpm8afTb4UwW13njwD9WzHWIZZhjUCdmm3Vkt9GJ2SI%3D&amp;reserved=0
>>
>> The Page State Change NAE exit will be used by the SEV-SNP guest to
>> request a page state change using the GHCB protocol. See the GHCB
>> spec section 4.1.6 and 2.3.1 for more detail on the structure
>> definitions.
>>
>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  MdePkg/Include/Register/Amd/Fam17Msr.h | 15 ++++++++++
>>  MdePkg/Include/Register/Amd/Ghcb.h     | 29 ++++++++++++++++++++
>>  2 files changed, 44 insertions(+)
>>
>> diff --git a/MdePkg/Include/Register/Amd/Fam17Msr.h b/MdePkg/Include/Register/Amd/Fam17Msr.h
>> index e19bd04b6c..432cee2feb 100644
>> --- a/MdePkg/Include/Register/Amd/Fam17Msr.h
>> +++ b/MdePkg/Include/Register/Amd/Fam17Msr.h
>> @@ -58,6 +58,19 @@ typedef union {
>>      UINT64  GuestFrameNumber:52;
>>    } GhcbGpaRegister;
>>  
>> +  struct {
>> +    UINT64 Function:12;
>> +    UINT64 GuestFrameNumber:40;
>> +    UINT64 Operation:4;
>> +    UINT64 Reserved:8;
>> +  } SnpPageStateChangeRequest;
>> +
>> +  struct {
>> +    UINT32 Function:12;
>> +    UINT32 Reserved:20;
>> +    UINT32 ErrorCode;
>> +  } SnpPageStateChangeResponse;
>> +
>>    VOID    *Ghcb;
>>  
> This matches section 2.3.1 in rev 2.00.
>
>>    UINT64  GhcbPhysicalAddress;
>> @@ -69,6 +82,8 @@ typedef union {
>>  #define GHCB_INFO_CPUID_RESPONSE           5
>>  #define GHCB_INFO_GHCB_GPA_REGISTER_REQUEST   18
>>  #define GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE  19
>> +#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_REQUEST   20
>> +#define GHCB_INFO_SNP_PAGE_STATE_CHANGE_RESPONSE  21
>>  #define GHCB_HYPERVISOR_FEATURES_REQUEST   128
>>  #define GHCB_HYPERVISOR_FEATURES_RESPONSE  129
>>  #define GHCB_INFO_TERMINATE_REQUEST        256
> Matches section 2.3.1.
>
>> diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
>> index 2d64a4c28f..1e7c0daed3 100644
>> --- a/MdePkg/Include/Register/Amd/Ghcb.h
>> +++ b/MdePkg/Include/Register/Amd/Ghcb.h
>> @@ -54,6 +54,7 @@
>>  #define SVM_EXIT_NMI_COMPLETE   0x80000003ULL
>>  #define SVM_EXIT_AP_RESET_HOLD  0x80000004ULL
>>  #define SVM_EXIT_AP_JUMP_TABLE  0x80000005ULL
>> +#define SVM_EXIT_SNP_PAGE_STATE_CHANGE    0x80000010ULL
>>  #define SVM_EXIT_HYPERVISOR_FEATURES  0x8000FFFDULL
>>  #define SVM_EXIT_UNSUPPORTED    0x8000FFFFULL
>>  
> Matches "Table 5. List of Supported Non-Automatic Events".
>
>> @@ -160,4 +161,32 @@ typedef union {
>>  #define GHCB_HV_FEATURES_SNP_AP_CREATE                    (GHCB_HV_FEATURES_SNP | BIT1)
>>  #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION         (GHCB_HV_FEATURES_SNP_AP_CREATE | BIT2)
>>  #define GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION_TIMER   (GHCB_HV_FEATURES_SNP_RESTRICTED_INJECTION | BIT3)
>> +
>> +// SNP Page State Change
> (1) Comment style.

Noted.


>
>> +#define SNP_PAGE_STATE_MAX_NPAGES           4095
>> +#define SNP_PAGE_STATE_MAX_ENTRY            253
>> +#define SNP_PAGE_STATE_PRIVATE              1
>> +#define SNP_PAGE_STATE_SHARED               2
>> +#define SNP_PAGE_STATE_PSMASH               3
>> +#define SNP_PAGE_STATE_UNSMASH              4
> (2) The PSMASH and UNSMASH operations are not documented in the rev 2.00
> spec, in the GHCB MSR protocol. That's probably because PSMASH and
> UNSMASH can only be defined in terms of 2MB pages, and
> GHCB_INFO_SNP_PAGE_STATE_CHANGE_REQUEST is suitable only for individual,
> 4KB pages. I think it would be useful to point out somehow here that
> PSMASH and UNSMASH are restricted to the GHCB shared area protocol
> (perhaps extend the leading comment on this block of macros).

I will add something in comment to clarify that UNMASH and PSMASH are
not available in MSR protocol.


>
> (3) I don't understand what "MAX_NPAGES" stands for (4095). The rest of
> the series never uses the macro, and I can't associate it with anything
> from the spec. If the macro is supposed to relate to the 4KB / 2MB page
> smashing / splitting, then its replacement text should be 512. Unless
> the macro corresponds to a definition in the spec, I think we should
> drop it.
That macro is replaced is no longer used, I ended up creating a more
meaningful macro (SNP_PAGES_STATE_MAX_ENTRY). I will remove it MAX_NPAGES.

>> +
>> +typedef PACKED struct {
>> +  UINT64  CurrentPage:12;
>> +  UINT64  GuestFrameNumber:40;
>> +  UINT64  Op:4;
>> +  UINT64  PageSize:1;
>> +  UINT64  Rsvd: 7;
>> +} SNP_PAGE_STATE_ENTRY;
>> +
>> +typedef PACKED struct {
>> +  UINT16 CurrentEntry;
>> +  UINT16 EndEntry;
>> +  UINT32 Rsvd;
>> +} SNP_PAGE_STATE_HEADER;
> (4) We tend to write
>
> #pragma pack (1)
> ...
> #pragma pack ()
>
> rather than PACKED -- but anyway, is packing really necessary? "Natural
> alignment" is required in edk2. I'm OK with packing, but I think the
> pragma is the preferred form.

Noted.


> (5) Please spell out both "Rsvd" fields above as "Reserved".

Noted.


>
> (6) Stray space character in "Rsvd: 7".

Noted.


>
> (7) The field name "Op" is inconsistent with the other field name
> "Operation".

Noted.


>
> (8) I think there is a bug (typo) in the rev 2.00 spec, in 4.1.6 "SNP
> Page State Change": it says
>
>   ... calculated from the supplied guest physical frame number (GFN) for
>   the requested page size (GPA = GFN << 12).
>
> But, if you can choose 2MB page size in the request, then the (GPA = GFN
> << 12) formula is not g

I think Tom already clarified it on his latest response.


> (9) If my understanding of the spec is correct, "EndEntry" has
> *inclusive* meaning. That's unusual. Any particular reason for not
> making "EndEntry" exclusive (in the spec)?

Sometimes guest may need to fill only few entries. The "EndEntry" will
give hint to hypervisor that it should stop processing after it reached
to the EndEntry.


>> +
>> +typedef struct {
>> +  SNP_PAGE_STATE_HEADER  Header;
>> +  SNP_PAGE_STATE_ENTRY   Entry[SNP_PAGE_STATE_MAX_ENTRY];
>> +} SNP_PAGE_STATE_CHANGE_INFO;
>> +
>>  #endif
>>
> Yes, this looks OK. Size is 2+2+4+253*8 = 2032 bytes, which matches the
> size of GHCB.SharedBuffer.
>
> (10) However, *if* you decide to declare SNP_PAGE_STATE_ENTRY and
> SNP_PAGE_STATE_HEADER explicitly as packed, then you should do the same
> for SNP_PAGE_STATE_CHANGE_INFO.

Noted.


>
> (11) Like I mentioned earlier, it's probably helpful if you start the
> subject line with
>
>   MdePkg/Register/Amd: ...
>
> on all of these MdePkg patches. If that becomes too tight, for some of
> the MdePkg patches, then I suggest "MdePkg/Amd: ..." (i.e., drop
> "Register").

Noted.

Thanks

Brijesh


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support
  2021-05-04 13:58   ` [edk2-devel] " Laszlo Ersek
  2021-05-04 14:09     ` Laszlo Ersek
@ 2021-05-04 19:07     ` Brijesh Singh
  2021-05-05 18:56       ` Laszlo Ersek
       [not found]     ` <167BF2A01FA60569.6407@groups.io>
  2 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-05-04 19:07 UTC (permalink / raw)
  To: Laszlo Ersek, devel
  Cc: brijesh.singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/4/21 8:58 AM, Laszlo Ersek wrote:
> On 04/30/21 13:51, Brijesh Singh wrote:
>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C6ceeec6c984d468bb87908d90f04b789%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637557335220626621%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=jF44vk%2FBUVukpuNg4vrcRqHnEa7nO%2FGPEe9ti720cnE%3D&amp;reserved=0
>>
>> The PVALIDATE instruction validates or rescinds validation of a guest
>> page RMP entry. Upon completion, a return code is stored in EAX, rFLAGS
>> bits OF, ZF, AF, PF and SF are set based on this return code. If the
>> instruction completed succesfully, the rFLAGS bit CF indicates if the
>> contents of the RMP entry were changed or not.
>>
>> For more information about the instruction see AMD APM volume 3.
>>
>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  MdePkg/Include/Library/BaseLib.h          | 37 +++++++++++++++++
>>  MdePkg/Library/BaseLib/BaseLib.inf        |  1 +
>>  MdePkg/Library/BaseLib/X64/Pvalidate.nasm | 43 ++++++++++++++++++++
>>  3 files changed, 81 insertions(+)
>>
>> diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h
>> index 7253997a6f..92ce695e93 100644
>> --- a/MdePkg/Include/Library/BaseLib.h
>> +++ b/MdePkg/Include/Library/BaseLib.h
>> @@ -7518,5 +7518,42 @@ PatchInstructionX86 (
>>    IN  UINTN                    ValueSize
>>    );
>>
>> +/**
>> + Execute a PVALIDATE instruction to validate or rescnids validation of a guest
> (1) typo: "rescnids"

Noted.


>
>
>> + page's RMP entry.
>> +
>> + Upon completion, in addition to the return value the instruction also updates
>> + the eFlags. A caller must check both the return code as well as eFlags to
>> + determine if the RMP entry has been updated.
>> +
>> + The function is available on x64.
> (2) Please write "X64"; that's how the architecture is usually mentioned
> in both the UEFI spec and in edk2.

Noted.


>
>
>> +
>> + @param[in]    Address        The guest virtual address to validate.
>> + @param[in]    PageSize       The page size to use.
>> + @param[i]     Validate       Validate or rescinds.
>> + @param[out]   Eflags         The value of Eflags after PVALIDATE completion.
> (3) Typo: "[i]" should be "[in]".

Noted.


>
>
> (4) The order of parameters listed in this comment block differs from
> the actual parameter list.
>
> The ECC plugin of the edk2 CI will catch this issue anyway. So, before
> submitting the patch set to the list, please submit a personal PR on
> github.com against the main repo, just to run CI on your patches.
>
Interestingly I did ran the series with edk2 CI and everything passed
before I submitted for the review. But, I will go ahead and fix the order.



>> +
>> + @retval       PvalidateRetValue  The return value from the PVALIDATE instruction.
> More on the return value / type later, below.
>
>> +**/
>> +typedef enum {
>> +  PvalidatePageSize4K = 0,
>> +  PvalidatePageSize2MB,
>> +} PVALIDATE_PAGE_SIZE;
>> +
>> +typedef enum {
>> +  PvalidateRetSuccess = 0,
>> +  PvalidateRetFailInput = 1,
>> +  PvalidateRetFailSizemismatch = 6,
>> +} PVALIDATE_RET_VALUE;
>> +
> (5) These typedefs do not belong between the function leading comment
> and the function declaration. Please hoist the typedefs just above the
> leading comment, and add a separate comment for the typedefs -- using
> the proper comment style for typedefs, too.
>
>
>> +PVALIDATE_RET_VALUE
> (6) In my opinion, using an enum for an EFIAPI function's return type is
> problematic. According to the UEFI spec (v2.9), "Table 2-3 Common UEFI
> Data Types", <Enumerated Type> may correspond to INT32 or UINT32. I
> don't like that ambiguity here. The spec also says that such types
> should never be used at least as structure fields.
>
> I'm perfectly fine with functions in standard (ISO) C programs returning
> enums, but I think the situation is less clear in UEFI. I don't recall
> standard interfaces (spec-level, or even edk2 / MdePkg interfaces) that
> return enums.
>
> I suggest the following instead. Drop the PVALIDATE_RET_VALUE enum
> altogether. Specify EFI_STATUS as the return type, in the declaration of
> the function.

Works with me.


>
> In the UEFI spec, Appendix D specifies the numeric values of the status
> codes. Furthermore, there are examples for NASM sources using EFI_*
> status codes *numerically* in edk2; minimally:
>
> - IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm
> - IntelFsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/SecEntry.nasm
>
> Thus, please modify the assembly source code in this patch to return
> EFI_SUCCESS (already value 0, conveniently) if the instruction succeeds.

Works with me.


> Return EFI_INVALID_PARAMETER (0x8000_0002) in case the instruction fails
> with error code 1 (FAIL_INPUT).

Works with me.


>
> Return EFI_UNSUPPORTED (0x8000_0003), or even EFI_NO_MAPPING
> (0x8000_0017), for value 6 (FAIL_SIZEMISMATCH).

I am not sure if we really want to do this. You will see later in the
patches that in some cases the PVALIDATE will return a failure and we
will need to know the failure code to determine the next steps.
Especially this particular error code is used later. This error happens
when the page size of the backing pages does not match with the
pvalidated size. In those cases we need to retry the PVALIDATE with
lower page size so that a validation succeed. One such a example is:

- Guest ask hypervisor to add the page as 2M in RMP table.

- Hypervisor added the page as 512 4K pages - because it was not able to
find a large backing pages.

- Guest attempts to pvalidate the page as a 2M. The pvalidate will
return a failure saying its a size mismatch between the requested
pvalidated and RMP table. The recommendation is that guest should try
with a smaller page size.

I would prefer to pass the pvalidate error as-is to caller so that it
can make the correct decision.


>
> The leading comment block of the function is supposed to explain these
> associations:
>
>   @retval EFI_SUCCESS        Successful completion (regardless of
>                              whether the Validated bit changed state).
>   @retval INVALID_PARAMETER  Invalid input parameters (FAIL_INPUT).
>   @retval EFI_UNSUPPORTED    Page size mismatch between guest (2M) and
>                              RMP entry (4K) (FAIL_SIZEMISMATCH).
>
> (Passing in the PVALIDATE_PAGE_SIZE enum, as a parameter, should be
> fine, BTW)
>
>
> (7) According to the AMD APM, "Support for this instruction is indicated
> by CPUID Fn8000_001F_EAX[SNP]=1".
>
> Presumably, if the (physical, or emulated) hardware does not support
> PVALIDATE, an #UD is raised. That condition should be explained in the
> function's leading comment. (Mention the CPUID and the #UD, I guess.)
Noted.
>
>> +EFIAPI
>> +AsmPvalidate (
>> +  IN   PVALIDATE_PAGE_SIZE     PageSize,
>> +  IN   BOOLEAN                 Validate,
>> +  IN   UINTN                   Address,
> (8) This should be EFI_PHYSICAL_ADDRESS, not UINTN.

Noted.


>
>> +  OUT  IA32_EFLAGS32           *Eflags
>> +  );
>> +
>>  #endif // defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
>>  #endif // !defined (__BASE_LIB__)
> (9) Unless you foresee particular uses for eflags *other than* CF, I
> would suggest replacing the Eflags output parameter with
>
>   OUT BOOLEAN   *RmpEntryUpdated
>
> The function would still only have 4 parameters, which shouldn't be
> difficult to handle in the assembly implementation (i.e. write to the
> UINT8 (= BOOLEAN) object referenced by "RmpEntryUpdated"). EFIAPI means
> that the first four params are passed in RCX, RDX, R8, R9.
Works with me, thats what I ended up doing for the guest kernel patches
and will do the same for OVMF as well.
>
> Thus far, I can see only one AsmPvalidate() call: in IssuePvalidate(),
> from patch #21 ("OvmfPkg/MemEncryptSevLib: Add support to validate
> system RAM"). And there, CF looks sufficient.
>
>
> (10) The instruction is X64 only, but you are providing the declaration
> even if MDE_CPU_IA32 is #defined. That seems wrong; even the declaration
> should be invisible in that case. Please declare the function for
> MDE_CPU_X64 only.
>
Noted.


>> diff --git a/MdePkg/Library/BaseLib/BaseLib.inf b/MdePkg/Library/BaseLib/BaseLib.inf
>> index b76f3af380..d33b4a8f7d 100644
>> --- a/MdePkg/Library/BaseLib/BaseLib.inf
>> +++ b/MdePkg/Library/BaseLib/BaseLib.inf
>> @@ -321,6 +321,7 @@
>>    X64/XGetBv.nasm
>>    X64/XSetBv.nasm
>>    X64/VmgExit.nasm
>> +  X64/Pvalidate.nasm
>>    ChkStkGcc.c  | GCC
>>
>>  [Sources.EBC]
> (11) This list of source files is already not sorted alphabetically,
> unfortunately. But we can still do better than this: I suggest inserting
> "X64/Pvalidate.nasm" just before "X64/RdRand.nasm".

Noted.


>
> (12) Your git setup seems less than ideal for formatting edk2 patches.
> The @@ hunk header above does not show the INF file section being
> modified. It should look something like this:
>
>   @@ -317,6 +317,7 @@ [Sources.X64]
>                       ^^^^^^^^^^^^^
>
> Please run the "BaseTools/Scripts/SetupGit.py" script in your working
> tree.

Will do.


>
> Alternatively, please see "xfuncname" at
> <https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FLaszlo%2527s-unkempt-git-guide-for-edk2-contributors-and-maintainers%23contrib-05&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C6ceeec6c984d468bb87908d90f04b789%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637557335220626621%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=W16GsCzqxFZlH7DBOIFY0EJy%2FS6DTSCt0qEVOMLjjRs%3D&amp;reserved=0>.
>
> This is of course not a bug in the patch, but fixing your setup will
> help with the next round of review.
>
>
>> diff --git a/MdePkg/Library/BaseLib/X64/Pvalidate.nasm b/MdePkg/Library/BaseLib/X64/Pvalidate.nasm
>> new file mode 100644
>> index 0000000000..f2aba114ac
>> --- /dev/null
>> +++ b/MdePkg/Library/BaseLib/X64/Pvalidate.nasm
>> @@ -0,0 +1,43 @@
>> +;-----------------------------------------------------------------------------
>> +;
>> +; Copyright (c) 2020-2021, AMD. All rights reserved.<BR>
> (13) I believe we don't introduce new files with copyright notices
> referring to the past. IOW, I think you should only say "2021" here.
>
Noted.


>> +; SPDX-License-Identifier: BSD-2-Clause-Patent
>> +;
>> +; Module Name:
>> +;
>> +;   Pvalidate.Asm
>> +;
>> +; Abstract:
>> +;
>> +;   AsmPvalidate function
>> +;
>> +; Notes:
>> +;
> (14) I defer to the MdePkg maintainers on this, but "Module Name" is
> plain wrong, and the Abstract is useless. Either fix those up please
> ("Abstract" could be a copy of the corrected leading comment block), or
> just drop them both.
>
>
>> +;-----------------------------------------------------------------------------
>> +
>> +    SECTION .text
>> +
>> +;-----------------------------------------------------------------------------
>> +;  PvalidateRetValue
>> +;  EFIAPI
>> +;  AsmPvalidate (
>> +;    IN   UINT32  RmpPageSize
>> +;    IN   UINT32  Validate,
>> +;    IN   UINTN   Address,
>> +;    OUT  UINTN  *Eflags,
>> +;    )
>> +;-----------------------------------------------------------------------------
> (15) Please update this accordingly to the corrected function
> specification.

Noted.


>
>> +global ASM_PFX(AsmPvalidate)
>> +ASM_PFX(AsmPvalidate):
>> +  mov     rax, r8
>> +
>> +  ; PVALIDATE instruction opcode
>> +  DB      0xF2, 0x0F, 0x01, 0xFF
> This is bad practice; we make every effort to avoid DB-encoded
> instructions.
>
> We have two PVALIDATE instances in the patch set (... that I can see
> immediateyl); the first here, and the other in
> "OvmfPkg/ResetVector/Ia32/PageTables64.asm" (from patch #17,
> "OvmfPkg/ResetVector: Invalidate the GHCB page"). Therefore, hiding the
> encoding of PVALIDATE behind a NASM macro definitely makes sense.
>
> (16a) Please file a NASM feature request for PVALIDATE at
> <https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.nasm.us%2F&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C6ceeec6c984d468bb87908d90f04b789%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637557335220636620%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=VtpkUnBunOdo3n86u3dBhoJZPxLN8M95ClyYUtC7v9o%3D&amp;reserved=0>.

Will do.


>
> (16b) In the present MdePkg patch, please extend the file
>
>   MdePkg/Include/X64/Nasm.inc
>
> as follows:
>
>> diff --git a/MdePkg/Include/X64/Nasm.inc b/MdePkg/Include/X64/Nasm.inc
>> index 527f71e9eb4d..ff37f1e35707 100644
>> --- a/MdePkg/Include/X64/Nasm.inc
>> +++ b/MdePkg/Include/X64/Nasm.inc
>> @@ -33,6 +33,15 @@
>>      DB 0xF3, 0x48, 0x0F, 0xAE, 0xE8
>>  %endmacro
>>
>> +;
>> +; Macro for the PVALIDATE instruction, defined in AMD publication #24594
>> +; revision 3.32. NASM feature request URL:
>> +; <https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.nasm.us%2Fshow_bug.cgi%3Fid%3DFIXME&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C6ceeec6c984d468bb87908d90f04b789%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637557335220636620%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=WeN3YmLN6OEpY8azwBt0ixogffkCCSk70P2Y%2Bff0Hlo%3D&amp;reserved=0>.
>> +;
>> +%macro PVALIDATE       0
>> +    DB 0xF2, 0x0F, 0x01, 0xFF
>> +%endmacro
>> +
>>  ; NASM provides built-in macros STRUC and ENDSTRUC for structure definition.
>>  ; For example, to define a structure called mytype containing a longword,
>>  ; a word, a byte and a string of bytes, you might code

Sure, I will add the new macro and use it.


> (16c) Please replace the FIXME placeholder above with the actual NASM BZ
> number (from (16a)).
>
> (16d) In the "MdePkg/Library/BaseLib/X64/Pvalidate.nasm" source file,
> and also (later) in the "OvmfPkg/ResetVector/Ia32/PageTables64.asm"
> source file, please use the PVALIDATE macro, in place of the naked DBs.
>
>
> Back to your patch:
>
> On 04/30/21 13:51, Brijesh Singh wrote:
>> +
>> +  ; Read the Eflags
>> +  pushfq
>> +  pop     r8
>> +  mov     [r9], r8
>> +
>> +  ; The PVALIDATE instruction returns the status in rax register.
>> +  ret
>>
> (17) The assembly code should be updated to match the new interface
> contract (parameter order, parameter types, return values).

Sure, I will update based on your feedback.


>
> I'll continue reviewing the series later this week (hopefully tomorrow).


thanks for all your review feedback.


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support
       [not found]     ` <167BF2A01FA60569.6407@groups.io>
@ 2021-05-04 19:55       ` Brijesh Singh
  2021-05-05 19:10         ` Laszlo Ersek
       [not found]       ` <167BF53DA09B327E.22277@groups.io>
  1 sibling, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-05-04 19:55 UTC (permalink / raw)
  To: devel, Laszlo Ersek
  Cc: brijesh.singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/4/21 2:07 PM, Brijesh Singh via groups.io wrote:
>> Return EFI_UNSUPPORTED (0x8000_0003), or even EFI_NO_MAPPING
>> (0x8000_0017), for value 6 (FAIL_SIZEMISMATCH).
> I am not sure if we really want to do this. You will see later in the
> patches that in some cases the PVALIDATE will return a failure and we
> will need to know the failure code to determine the next steps.
> Especially this particular error code is used later. This error happens
> when the page size of the backing pages does not match with the
> pvalidated size. In those cases we need to retry the PVALIDATE with
> lower page size so that a validation succeed. One such a example is:
>
> - Guest ask hypervisor to add the page as 2M in RMP table.
>
> - Hypervisor added the page as 512 4K pages - because it was not able to
> find a large backing pages.
>
> - Guest attempts to pvalidate the page as a 2M. The pvalidate will
> return a failure saying its a size mismatch between the requested
> pvalidated and RMP table. The recommendation is that guest should try
> with a smaller page size.
>
> I would prefer to pass the pvalidate error as-is to caller so that it
> can make the correct decision.
>
I am perfectly fine if the function return UINTN and then use #define
instead of the enum to define the PVALIDATE return code. So that caller
can check the error code. Let me know your thought on #define instead of
the enum.

-Brijesh


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support
       [not found]       ` <167BF53DA09B327E.22277@groups.io>
@ 2021-05-04 20:28         ` Brijesh Singh
  2021-05-04 23:03           ` Brijesh Singh
  2021-05-05 19:17           ` Laszlo Ersek
  0 siblings, 2 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-05-04 20:28 UTC (permalink / raw)
  To: devel, Laszlo Ersek
  Cc: brijesh.singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/4/21 2:55 PM, Brijesh Singh via groups.io wrote:
> On 5/4/21 2:07 PM, Brijesh Singh via groups.io wrote:
>>> Return EFI_UNSUPPORTED (0x8000_0003), or even EFI_NO_MAPPING
>>> (0x8000_0017), for value 6 (FAIL_SIZEMISMATCH).
>> I am not sure if we really want to do this. You will see later in the
>> patches that in some cases the PVALIDATE will return a failure and we
>> will need to know the failure code to determine the next steps.
>> Especially this particular error code is used later. This error happens
>> when the page size of the backing pages does not match with the
>> pvalidated size. In those cases we need to retry the PVALIDATE with
>> lower page size so that a validation succeed. One such a example is:
>>
>> - Guest ask hypervisor to add the page as 2M in RMP table.
>>
>> - Hypervisor added the page as 512 4K pages - because it was not able to
>> find a large backing pages.
>>
>> - Guest attempts to pvalidate the page as a 2M. The pvalidate will
>> return a failure saying its a size mismatch between the requested
>> pvalidated and RMP table. The recommendation is that guest should try
>> with a smaller page size.
>>
>> I would prefer to pass the pvalidate error as-is to caller so that it
>> can make the correct decision.
>>
> I am perfectly fine if the function return UINTN and then use #define
> instead of the enum to define the PVALIDATE return code. So that caller
> can check the error code. Let me know your thought on #define instead of
> the enum.

Apologies, I missed the fact that you said document the mapping between
the PVALIDATE return value and EFI_STATUS. So a caller is responsible to
look at the EFI document to know what the error code means. The
unsupported here does not mean that PVALIDATE is not support on
platform. I am good with it. I will go ahead with it.

-Brijesh


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support
  2021-05-04 20:28         ` Brijesh Singh
@ 2021-05-04 23:03           ` Brijesh Singh
  2021-05-05 19:19             ` Laszlo Ersek
  2021-05-05 19:17           ` Laszlo Ersek
  1 sibling, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-05-04 23:03 UTC (permalink / raw)
  To: devel, Laszlo Ersek
  Cc: brijesh.singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/4/21 3:28 PM, Brijesh Singh wrote:
> On 5/4/21 2:55 PM, Brijesh Singh via groups.io wrote:
>> On 5/4/21 2:07 PM, Brijesh Singh via groups.io wrote:
>>>> Return EFI_UNSUPPORTED (0x8000_0003), or even EFI_NO_MAPPING
>>>> (0x8000_0017), for value 6 (FAIL_SIZEMISMATCH).
>>> I am not sure if we really want to do this. You will see later in the
>>> patches that in some cases the PVALIDATE will return a failure and we
>>> will need to know the failure code to determine the next steps.
>>> Especially this particular error code is used later. This error happens
>>> when the page size of the backing pages does not match with the
>>> pvalidated size. In those cases we need to retry the PVALIDATE with
>>> lower page size so that a validation succeed. One such a example is:
>>>
>>> - Guest ask hypervisor to add the page as 2M in RMP table.
>>>
>>> - Hypervisor added the page as 512 4K pages - because it was not able to
>>> find a large backing pages.
>>>
>>> - Guest attempts to pvalidate the page as a 2M. The pvalidate will
>>> return a failure saying its a size mismatch between the requested
>>> pvalidated and RMP table. The recommendation is that guest should try
>>> with a smaller page size.
>>>
>>> I would prefer to pass the pvalidate error as-is to caller so that it
>>> can make the correct decision.
>>>
>> I am perfectly fine if the function return UINTN and then use #define
>> instead of the enum to define the PVALIDATE return code. So that caller
>> can check the error code. Let me know your thought on #define instead of
>> the enum.
> Apologies, I missed the fact that you said document the mapping between
> the PVALIDATE return value and EFI_STATUS. So a caller is responsible to
> look at the EFI document to know what the error code means. The
> unsupported here does not mean that PVALIDATE is not support on
> platform. I am good with it. I will go ahead with it.

While coding it I am coming to realizing that mapping from PVALIDATE
return value to EFI will add more code in assemblym and wanted to make
sure that we all are okay with it. The proposed mapping looks like this:

// No mapping required, both the values are zero

PVALIDATE_RET_SUCCESS -> EFI_SUCCESS   

// Pvalidate.nasm need to map from PVALIDATE fail input (1) to
EFI_INVALID_PRAMS (2)

PVALIATE_RET_FAIL_INPUT -> EFI_INVALID_PARAMS

// Pvalidate.nasm need to map from PVALIDATE SIZE_MISMATCH (6) to
EFI_UNSUPPORT(3)

PVALIATE_RET_SIZEMISMATCH -> EFI_UNSUPPORTED

May I recommend to use UINTN and simply propagate the PVALIDATE return
value  or use the below mapping to simplify the pvalidate.nasm
implementation:

PVALIDATE_RET_SUCCESS(0) -> EFI_SUCCESS(0)

PVALIDATE_RET_FAIL_INPUT(1) -> EFI_LOAD_ERROR(1)

PVALIDATE_RET_SIZE_MISMATCH(6) -> EFI_NOT_READY(6)

Thanks


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD
  2021-04-30 11:51 ` [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD Brijesh Singh
@ 2021-05-05  6:42   ` Dov Murik
  2021-05-05 13:11     ` Brijesh Singh
  0 siblings, 1 reply; 81+ messages in thread
From: Dov Murik @ 2021-05-05  6:42 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Laszlo Ersek, Erdem Aktas, tobin@ibm.com

[+cc: Tobin]

Hi Brijesh,

On 30/04/2021 14:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
> 
> When AMD SEV is enabled in the guest VM, a hypervisor need to insert a
> secrets page.
> 
> When SEV-SNP is enabled, the secrets page contains the VM platform
> communication keys. The guest BIOS and OS can use this key to communicate
> with the SEV firmware to get attesation report. See the SEV-SNP firmware
> spec for more details for the content of the secrets page.
> 
> When SEV and SEV-ES is enabled, the secrets page contains the information
> provided by the guest owner after the attestation. See the SEV
> LAUNCH_SECRET command for more details.
> 
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  OvmfPkg/AmdSev/SecretPei/SecretPei.c   | 16 +++++++++++++++-
>  OvmfPkg/AmdSev/SecretPei/SecretPei.inf |  1 +
>  OvmfPkg/OvmfPkgX64.dsc                 |  2 ++
>  OvmfPkg/OvmfPkgX64.fdf                 |  5 +++++
>  4 files changed, 23 insertions(+), 1 deletion(-)
> 
> diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.c b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
> index ad491515dd..92836c562c 100644
> --- a/OvmfPkg/AmdSev/SecretPei/SecretPei.c
> +++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
> @@ -7,6 +7,7 @@
>  #include <PiPei.h>
>  #include <Library/HobLib.h>
>  #include <Library/PcdLib.h>
> +#include <Library/MemEncryptSevLib.h>
> 
>  EFI_STATUS
>  EFIAPI
> @@ -15,10 +16,23 @@ InitializeSecretPei (
>    IN CONST EFI_PEI_SERVICES     **PeiServices
>    )
>  {
> +  UINTN   Type;
> +
> +  //
> +  // The secret page should be mapped encrypted by the guest OS and must not
> +  // be treated as a system RAM. Mark it as ACPI NVS so that guest OS maps it
> +  // encrypted.
> +  //
> +  if (MemEncryptSevSnpIsEnabled ()) {
> +    Type = EfiACPIMemoryNVS;
> +  } else {
> +    Type = EfiBootServicesData;
> +  }
> +

Would it make sense to always use EfiACPIMemoryNVS for the injected secret area, even for regular SEV (non-SNP)?

-Dov



>    BuildMemoryAllocationHob (
>      PcdGet32 (PcdSevLaunchSecretBase),
>      PcdGet32 (PcdSevLaunchSecretSize),
> -    EfiBootServicesData
> +    Type
>      );
> 
>    return EFI_SUCCESS;
> diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
> index 08be156c4b..9265f8adee 100644
> --- a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
> +++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
> @@ -26,6 +26,7 @@
>    HobLib
>    PeimEntryPoint
>    PcdLib
> +  MemEncryptSevLib
> 
>  [FixedPcd]
>    gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
> index a7d747f6b4..593c0e69f6 100644
> --- a/OvmfPkg/OvmfPkgX64.dsc
> +++ b/OvmfPkg/OvmfPkgX64.dsc
> @@ -716,6 +716,7 @@
>    OvmfPkg/SmmAccess/SmmAccessPei.inf
>  !endif
>    UefiCpuPkg/CpuMpPei/CpuMpPei.inf
> +  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
> 
>  !if $(TPM_ENABLE) == TRUE
>    OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
> @@ -965,6 +966,7 @@
>    OvmfPkg/PlatformDxe/Platform.inf
>    OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>    OvmfPkg/IoMmuDxe/IoMmuDxe.inf
> +  OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
> 
>  !if $(SMM_REQUIRE) == TRUE
>    OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
> diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
> index d519f85328..b04175f77c 100644
> --- a/OvmfPkg/OvmfPkgX64.fdf
> +++ b/OvmfPkg/OvmfPkgX64.fdf
> @@ -88,6 +88,9 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.PcdSevE
>  0x00C000|0x001000
>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
> 
> +0x00D000|0x001000
> +gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
> +
>  0x010000|0x010000
>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
> 
> @@ -178,6 +181,7 @@ INF  OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
>  INF  SecurityPkg/Tcg/TcgPei/TcgPei.inf
>  INF  SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
>  !endif
> +INF  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
> 
>  ################################################################################
> 
> @@ -313,6 +317,7 @@ INF  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
>  INF  ShellPkg/Application/Shell/Shell.inf
> 
>  INF MdeModulePkg/Logo/LogoDxe.inf
> +INF OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
> 
>  #
>  # Network modules
> 

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 27/28] OvmfPkg/AmdSev: Expose the SNP reserved pages through configuration table
  2021-04-30 11:51 ` [PATCH RFC v2 27/28] OvmfPkg/AmdSev: Expose the SNP reserved pages through configuration table Brijesh Singh
@ 2021-05-05  7:10   ` Dov Murik
  2021-05-05 19:37     ` Laszlo Ersek
  0 siblings, 1 reply; 81+ messages in thread
From: Dov Murik @ 2021-05-05  7:10 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Laszlo Ersek, Erdem Aktas

Hi Brijesh,

On 30/04/2021 14:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
> 
> Now that both the secrets and cpuid pages are reserved in the HOB,
> extract the location details through fixed PCD and make it available
> to the guest OS through the configuration table.
> 
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  OvmfPkg/AmdSev/SecretDxe/SecretDxe.c               | 21 ++++++++++++++++++++
>  OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf             |  4 ++++
>  OvmfPkg/Include/Guid/ConfidentialComputingSecret.h | 17 ++++++++++++++++
>  OvmfPkg/OvmfPkg.dec                                |  1 +
>  4 files changed, 43 insertions(+)
> 
> diff --git a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c
> index 308022b5b2..08b6d9bddf 100644
> --- a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c
> +++ b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c
> @@ -6,6 +6,7 @@
>  **/
>  #include <PiDxe.h>
>  #include <Library/UefiBootServicesTableLib.h>
> +#include <Library/MemEncryptSevLib.h>
>  #include <Guid/ConfidentialComputingSecret.h>
> 
>  STATIC CONFIDENTIAL_COMPUTING_SECRET_LOCATION mSecretDxeTable = {
> @@ -13,6 +14,15 @@ STATIC CONFIDENTIAL_COMPUTING_SECRET_LOCATION mSecretDxeTable = {
>    FixedPcdGet32 (PcdSevLaunchSecretSize),
>  };
> 
> +STATIC CONFIDENTIAL_COMPUTING_BLOB_LOCATION mSnpBootDxeTable = {
> +  0x414d4445,     // AMDE

(nit: I believe this UINT32 will appear in memory as the string "EDMA".)



> +  1,

Not sure what's the official stance regarding a version field here. Maybe it's better to generate a new GUID whenever there's a struct change.


-Dov


> +  (UINT64)(UINTN) FixedPcdGet32 (PcdSevLaunchSecretBase),
> +  FixedPcdGet32 (PcdSevLaunchSecretSize),
> +  (UINT64)(UINTN) FixedPcdGet32 (PcdOvmfSnpCpuidBase),
> +  FixedPcdGet32 (PcdOvmfSnpCpuidSize),
> +};
> +
>  EFI_STATUS
>  EFIAPI
>  InitializeSecretDxe(
> @@ -20,6 +30,17 @@ InitializeSecretDxe(
>    IN EFI_SYSTEM_TABLE     *SystemTable
>    )
>  {
> +  //
> +  // If its SEV-SNP active guest then install the CONFIDENTIAL_COMPUTING_BLOB.
> +  // It contains the location for both the Secrets and CPUID page.
> +  //
> +  if (MemEncryptSevSnpIsEnabled ()) {
> +    return gBS->InstallConfigurationTable (
> +                  &gConfidentialComputingBlobGuid,
> +                  &mSnpBootDxeTable
> +                  );
> +  }
> +
>    return gBS->InstallConfigurationTable (
>                  &gConfidentialComputingSecretGuid,
>                  &mSecretDxeTable
> diff --git a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
> index 40bda7ff84..d15194b368 100644
> --- a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
> +++ b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
> @@ -23,13 +23,17 @@
>    MdePkg/MdePkg.dec
> 
>  [LibraryClasses]
> +  MemEncryptSevLib
>    UefiBootServicesTableLib
>    UefiDriverEntryPoint
> 
>  [Guids]
>    gConfidentialComputingSecretGuid
> +  gConfidentialComputingBlobGuid
> 
>  [FixedPcd]
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize
>    gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
>    gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
> 
> diff --git a/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h b/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
> index 7026fc5b08..0d7f1b8818 100644
> --- a/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
> +++ b/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
> @@ -18,11 +18,28 @@
>      { 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47 }, \
>    }
> 
> +#define CONFIDENTIAL_COMPUTING_BLOB_GUID                \
> +  { 0x067b1f5f,                                         \
> +    0xcf26,                                             \
> +    0x44c5,                                             \
> +    { 0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42 }, \
> +  }
> +
>  typedef struct {
>    UINT64 Base;
>    UINT64 Size;
>  } CONFIDENTIAL_COMPUTING_SECRET_LOCATION;
> 
> +typedef struct {
> +  UINT32  Header;
> +  UINT16  Version;
> +  UINT64  SecretsPhysicalAddress;
> +  UINT32  SecretsSize;
> +  UINT64  CpuidPhysicalAddress;
> +  UINT32  CpuidLSize;
> +} CONFIDENTIAL_COMPUTING_BLOB_LOCATION;
> +
>  extern EFI_GUID gConfidentialComputingSecretGuid;
> +extern EFI_GUID gConfidentialComputingBlobGuid;
> 
>  #endif // SEV_LAUNCH_SECRET_H_
> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> index d1bfe49731..f38c5e476a 100644
> --- a/OvmfPkg/OvmfPkg.dec
> +++ b/OvmfPkg/OvmfPkg.dec
> @@ -126,6 +126,7 @@
>    gQemuKernelLoaderFsMediaGuid          = {0x1428f772, 0xb64a, 0x441e, {0xb8, 0xc3, 0x9e, 0xbd, 0xd7, 0xf8, 0x93, 0xc7}}
>    gGrubFileGuid                         = {0xb5ae312c, 0xbc8a, 0x43b1, {0x9c, 0x62, 0xeb, 0xb8, 0x26, 0xdd, 0x5d, 0x07}}
>    gConfidentialComputingSecretGuid      = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}}
> +  gConfidentialComputingBlobGuid        = {0x067b1f5f, 0xcf26, 0x44c5, {0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42}}
> 
>  [Ppis]
>    # PPI whose presence in the PPI database signals that the TPM base address
> 

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD
  2021-05-05  6:42   ` [edk2-devel] " Dov Murik
@ 2021-05-05 13:11     ` Brijesh Singh
  2021-05-05 19:33       ` Laszlo Ersek
  0 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-05-05 13:11 UTC (permalink / raw)
  To: Dov Murik, devel
  Cc: brijesh.singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Laszlo Ersek, Erdem Aktas,
	tobin@ibm.com


On 5/5/21 1:42 AM, Dov Murik wrote:
> [+cc: Tobin]
>
> Hi Brijesh,
>
> On 30/04/2021 14:51, Brijesh Singh wrote:
>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C93168c94eb6d44ed08e608d90f910426%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637557937779907471%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=nLpmk3G%2BmXcZrzXxCmO3M9EDPiLRnP1IUmPqRQNbBuU%3D&amp;reserved=0
>>
>> When AMD SEV is enabled in the guest VM, a hypervisor need to insert a
>> secrets page.
>>
>> When SEV-SNP is enabled, the secrets page contains the VM platform
>> communication keys. The guest BIOS and OS can use this key to communicate
>> with the SEV firmware to get attesation report. See the SEV-SNP firmware
>> spec for more details for the content of the secrets page.
>>
>> When SEV and SEV-ES is enabled, the secrets page contains the information
>> provided by the guest owner after the attestation. See the SEV
>> LAUNCH_SECRET command for more details.
>>
>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  OvmfPkg/AmdSev/SecretPei/SecretPei.c   | 16 +++++++++++++++-
>>  OvmfPkg/AmdSev/SecretPei/SecretPei.inf |  1 +
>>  OvmfPkg/OvmfPkgX64.dsc                 |  2 ++
>>  OvmfPkg/OvmfPkgX64.fdf                 |  5 +++++
>>  4 files changed, 23 insertions(+), 1 deletion(-)
>>
>> diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.c b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>> index ad491515dd..92836c562c 100644
>> --- a/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>> +++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>> @@ -7,6 +7,7 @@
>>  #include <PiPei.h>
>>  #include <Library/HobLib.h>
>>  #include <Library/PcdLib.h>
>> +#include <Library/MemEncryptSevLib.h>
>>
>>  EFI_STATUS
>>  EFIAPI
>> @@ -15,10 +16,23 @@ InitializeSecretPei (
>>    IN CONST EFI_PEI_SERVICES     **PeiServices
>>    )
>>  {
>> +  UINTN   Type;
>> +
>> +  //
>> +  // The secret page should be mapped encrypted by the guest OS and must not
>> +  // be treated as a system RAM. Mark it as ACPI NVS so that guest OS maps it
>> +  // encrypted.
>> +  //
>> +  if (MemEncryptSevSnpIsEnabled ()) {
>> +    Type = EfiACPIMemoryNVS;
>> +  } else {
>> +    Type = EfiBootServicesData;
>> +  }
>> +
> Would it make sense to always use EfiACPIMemoryNVS for the injected secret area, even for regular SEV (non-SNP)?

Ideally yes. Maybe James had some reasons for choosing the
EfiBootServicesData. If I had to guess, it was mainly because there no
guest kernel support which consumes the SEV secrets page. Since the
memory is not marked ACPI NVS, so it can be used as a system RAM after
the ExitBootServices is called in the kernel.

I am fine with using ACPI NVS for both SEV and SEV-SNP. I was not able
to build and run AmdSev package in my setup, can you submit a prepatch
to change the memory type and verify that it works ?

>
> -Dov
>
>
>
>>    BuildMemoryAllocationHob (
>>      PcdGet32 (PcdSevLaunchSecretBase),
>>      PcdGet32 (PcdSevLaunchSecretSize),
>> -    EfiBootServicesData
>> +    Type
>>      );
>>
>>    return EFI_SUCCESS;
>> diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>> index 08be156c4b..9265f8adee 100644
>> --- a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>> +++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>> @@ -26,6 +26,7 @@
>>    HobLib
>>    PeimEntryPoint
>>    PcdLib
>> +  MemEncryptSevLib
>>
>>  [FixedPcd]
>>    gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
>> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
>> index a7d747f6b4..593c0e69f6 100644
>> --- a/OvmfPkg/OvmfPkgX64.dsc
>> +++ b/OvmfPkg/OvmfPkgX64.dsc
>> @@ -716,6 +716,7 @@
>>    OvmfPkg/SmmAccess/SmmAccessPei.inf
>>  !endif
>>    UefiCpuPkg/CpuMpPei/CpuMpPei.inf
>> +  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>
>>  !if $(TPM_ENABLE) == TRUE
>>    OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
>> @@ -965,6 +966,7 @@
>>    OvmfPkg/PlatformDxe/Platform.inf
>>    OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>>    OvmfPkg/IoMmuDxe/IoMmuDxe.inf
>> +  OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>>
>>  !if $(SMM_REQUIRE) == TRUE
>>    OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
>> diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
>> index d519f85328..b04175f77c 100644
>> --- a/OvmfPkg/OvmfPkgX64.fdf
>> +++ b/OvmfPkg/OvmfPkgX64.fdf
>> @@ -88,6 +88,9 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.PcdSevE
>>  0x00C000|0x001000
>>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
>>
>> +0x00D000|0x001000
>> +gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
>> +
>>  0x010000|0x010000
>>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
>>
>> @@ -178,6 +181,7 @@ INF  OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
>>  INF  SecurityPkg/Tcg/TcgPei/TcgPei.inf
>>  INF  SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
>>  !endif
>> +INF  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>
>>  ################################################################################
>>
>> @@ -313,6 +317,7 @@ INF  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
>>  INF  ShellPkg/Application/Shell/Shell.inf
>>
>>  INF MdeModulePkg/Logo/LogoDxe.inf
>> +INF OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>>
>>  #
>>  # Network modules
>>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures
  2021-05-04 18:53     ` Brijesh Singh
@ 2021-05-05 18:24       ` Laszlo Ersek
  2021-05-05 19:27         ` Brijesh Singh
  0 siblings, 1 reply; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-05 18:24 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/04/21 20:53, Brijesh Singh wrote:
> 
> On 5/4/21 7:33 AM, Laszlo Ersek wrote:
>> On 04/30/21 13:51, Brijesh Singh wrote:

>>> +typedef PACKED struct {
>>> +  UINT16 CurrentEntry;
>>> +  UINT16 EndEntry;
>>> +  UINT32 Rsvd;
>>> +} SNP_PAGE_STATE_HEADER;

>> (9) If my understanding of the spec is correct, "EndEntry" has
>> *inclusive* meaning. That's unusual. Any particular reason for not
>> making "EndEntry" exclusive (in the spec)?
> 
> Sometimes guest may need to fill only few entries. The "EndEntry" will
> give hint to hypervisor that it should stop processing after it reached
> to the EndEntry.

I understood the purpose of EndEntry.

My question is why the entry identified by EndEntry *itself* needs to be
processed.

Put differently, I'm asking why your loop controlling expression is

  Info->Header.CurrentEntry <= Info->Header.EndEntry            [1]

and why not

  Info->Header.CurrentEntry < Info->Header.EndEntry             [2]

in patch #21 ("OvmfPkg/MemEncryptSevLib: Add support to validate system
RAM").

In case [1], EndEntry is an inclusive limit.

In case [2], EndEntry would be an exclusive limit.

My question is why the spec defines EndEntry with inclusive rather than
exclusive meaning.

Using inclusive low bounds with exclusive high bounds has mental advantages:

https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html

Is there a specific reason for which the spec chose the inclusive high
bound?

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support
  2021-05-04 19:07     ` Brijesh Singh
@ 2021-05-05 18:56       ` Laszlo Ersek
  0 siblings, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-05 18:56 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/04/21 21:07, Brijesh Singh wrote:
>
> On 5/4/21 8:58 AM, Laszlo Ersek wrote:

>> (4) The order of parameters listed in this comment block differs from
>> the actual parameter list.
>>
>> The ECC plugin of the edk2 CI will catch this issue anyway. So,
>> before submitting the patch set to the list, please submit a personal
>> PR on github.com against the main repo, just to run CI on your
>> patches.
>>
> Interestingly I did ran the series with edk2 CI and everything passed
> before I submitted for the review. But, I will go ahead and fix the
> order.

Thank you for being careful up-front -- and then I don't understand this
result. The "EccCheck" plugin is not disabled in
"MdePkg/MdePkg.ci.yaml", and I distinctly remember ECC being incredibly
pedantic about any function leading comment matching the function's
declaration.

Anyway, thanks for updating this, in the next version.


>> Return EFI_UNSUPPORTED (0x8000_0003), or even EFI_NO_MAPPING
>> (0x8000_0017), for value 6 (FAIL_SIZEMISMATCH).
>
> I am not sure if we really want to do this. You will see later in the
> patches that in some cases the PVALIDATE will return a failure and we
> will need to know the failure code to determine the next steps.
> Especially this particular error code is used later. This error
> happens when the page size of the backing pages does not match with
> the pvalidated size. In those cases we need to retry the PVALIDATE
> with lower page size so that a validation succeed. One such a example
> is:
>
> - Guest ask hypervisor to add the page as 2M in RMP table.
>
> - Hypervisor added the page as 512 4K pages - because it was not able
> to find a large backing pages.
>
> - Guest attempts to pvalidate the page as a 2M. The pvalidate will
> return a failure saying its a size mismatch between the requested
> pvalidated and RMP table. The recommendation is that guest should try
> with a smaller page size.
>
> I would prefer to pass the pvalidate error as-is to caller so that it
> can make the correct decision.

My intent is certainly not to mask, or collapse, distinct outputs from
PVALIDATE.

The EFI_STATUS codes that I suggested for AsmPvalidate() keep the
distinct PVALIDATE results distinct. The AMD APM (vol3) describes three
result codes (SUCCESS, FAIL_INPUT, FAIL_SIZEMISMATCH), and I suggested a
*bijective* EFI_STATUS mapping for those -- EFI_SUCCESS,
EFI_INVALID_PARAMETER, and EFI_UNSUPPORTED; in that order.

EFI_NO_MAPPING was only an alternative for EFI_UNSUPPORTED -- in case
you preferred EFI_NO_MAPPING to EFI_UNSUPPORTED, for representing
FAIL_SIZEMISMATCH.

Each one of the EFI_STATUS codes I suggest corresponds uniquely to a
direct PVALIDATE result code (injectivity), and each direct PVALIDATE
result code is covered (surjectivity). So it's a bijection.

CF is only meaningful on output if PVALIDATE succeeds, according to the
AMD APM:

    If the instruction completed successfully, the rFLAGS bit CF
    indicates if the contents of the RMP entry were changed or not.

Therefore CF should only be checked (and it *can* be checked, via the
BOOLEAN "RmpEntryUpdated" output parameter that I also recommended) if
EFI_SUCCESS is returned by AsmPvalidate().


Furthermore, I *did* check the (sole) AsmPvalidate() call site in the
series, before posting my earlier comment. It goes like this, in patch
#21 ("OvmfPkg/MemEncryptSevLib: Add support to validate system RAM"):

>   Ret = AsmPvalidate (RmpPageSize, Validate, Address, &EFlags);
>
>   //
>   // Check the rFlags.CF to verify that PVALIDATE updated the RMP entry.
>   // If there was a no change in the RMP entry then we are either double
>   // validating or invalidating the memory. This can lead to a security compromise.
>   //
>   if (EFlags.Bits.CF) {
>     DEBUG ((
>       DEBUG_ERROR, "%a:%a: Double %a detected for address 0x%Lx\n",
>       gEfiCallerBaseName,
>       __FUNCTION__,
>       Validate ? "Validate" : "Invalidate",
>       Address
>       ));
>     SnpPageStateFailureTerminate ();
>   }
>
>   return Ret;

This logic is incorrect, in my opinion. CF should not be checked before
ensuring that Ret equal SUCCESS.

The correct logic for IssuePvalidate() would be:

  Status = AsmPvalidate (RmpPageSize, Validate, Address, &RmpEntryUpdated);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  if (!RmpEntryUpdated) {
    SnpPageStateFailureTerminate ();
  }

And then the caller of IssuePvalidate() -- PvalidateRange() -- can rely
on the status codes, returned by IssuePvalidate(), with the following
meanings:

- EFI_SUCCESS: PVALIDATE completed *and* it successfully updated the RMP
  entry

- EFI_INVALID_PARAMETER: PVALIDATE failed with FAIL_INPUT (and CF was
  meaningless on output)

- EFI_UNSUPPORTED (or EFI_NO_MAPPING, if you like): PVALIDATE failed
  with FAIL_SIZEMISMATCH (and CF was meaningless on output); PVALIDATE
  should be retried with the small (4K) page size.


I entirely agree with your high-level goal here. My point is that the
mapping that I'm proposing loses *no* information, it is more idiomatic
for edk2, and it's not difficult to implement in assembly.

If you absolutely insist on returning status codes 0, 1, and 6, from
AsmPvalidate(), I can live with that too (although I do think it's a lot
less idiomatic for edk2); in that case however, please make the return
type of AsmPvalidate() UINT32.

(And to repeat: my other point is that the CF checking logic in
IssuePvalidate() is currently wrong, as it relies on a value (CF) which
may be indeterminate in some cases.)

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support
  2021-05-04 19:55       ` Brijesh Singh
@ 2021-05-05 19:10         ` Laszlo Ersek
  0 siblings, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-05 19:10 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/04/21 21:55, Brijesh Singh wrote:
> 
> On 5/4/21 2:07 PM, Brijesh Singh via groups.io wrote:
>>> Return EFI_UNSUPPORTED (0x8000_0003), or even EFI_NO_MAPPING
>>> (0x8000_0017), for value 6 (FAIL_SIZEMISMATCH).
>> I am not sure if we really want to do this. You will see later in the
>> patches that in some cases the PVALIDATE will return a failure and we
>> will need to know the failure code to determine the next steps.
>> Especially this particular error code is used later. This error happens
>> when the page size of the backing pages does not match with the
>> pvalidated size. In those cases we need to retry the PVALIDATE with
>> lower page size so that a validation succeed. One such a example is:
>>
>> - Guest ask hypervisor to add the page as 2M in RMP table.
>>
>> - Hypervisor added the page as 512 4K pages - because it was not able to
>> find a large backing pages.
>>
>> - Guest attempts to pvalidate the page as a 2M. The pvalidate will
>> return a failure saying its a size mismatch between the requested
>> pvalidated and RMP table. The recommendation is that guest should try
>> with a smaller page size.
>>
>> I would prefer to pass the pvalidate error as-is to caller so that it
>> can make the correct decision.
>>
> I am perfectly fine if the function return UINTN and then use #define
> instead of the enum to define the PVALIDATE return code. So that caller
> can check the error code. Let me know your thought on #define instead of
> the enum.

(1) If the funcion returns UINTN rather than an enum type, that resolves
my request, technically speaking. I think it's inferior to the
EFI_STATUS mapping that I proposed, but it certainly resolves my request!

(2) How you provide the symbolic names for the values 0, 1, 6, does not
matter. If you use #define's (= macros), that's fine. If you use an enum
type, with enum constants, that's also fine. This aspect is orthogonal
to my request.

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support
  2021-05-04 20:28         ` Brijesh Singh
  2021-05-04 23:03           ` Brijesh Singh
@ 2021-05-05 19:17           ` Laszlo Ersek
  1 sibling, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-05 19:17 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/04/21 22:28, Brijesh Singh wrote:
> 
> On 5/4/21 2:55 PM, Brijesh Singh via groups.io wrote:
>> On 5/4/21 2:07 PM, Brijesh Singh via groups.io wrote:
>>>> Return EFI_UNSUPPORTED (0x8000_0003), or even EFI_NO_MAPPING
>>>> (0x8000_0017), for value 6 (FAIL_SIZEMISMATCH).
>>> I am not sure if we really want to do this. You will see later in the
>>> patches that in some cases the PVALIDATE will return a failure and we
>>> will need to know the failure code to determine the next steps.
>>> Especially this particular error code is used later. This error happens
>>> when the page size of the backing pages does not match with the
>>> pvalidated size. In those cases we need to retry the PVALIDATE with
>>> lower page size so that a validation succeed. One such a example is:
>>>
>>> - Guest ask hypervisor to add the page as 2M in RMP table.
>>>
>>> - Hypervisor added the page as 512 4K pages - because it was not able to
>>> find a large backing pages.
>>>
>>> - Guest attempts to pvalidate the page as a 2M. The pvalidate will
>>> return a failure saying its a size mismatch between the requested
>>> pvalidated and RMP table. The recommendation is that guest should try
>>> with a smaller page size.
>>>
>>> I would prefer to pass the pvalidate error as-is to caller so that it
>>> can make the correct decision.
>>>
>> I am perfectly fine if the function return UINTN and then use #define
>> instead of the enum to define the PVALIDATE return code. So that caller
>> can check the error code. Let me know your thought on #define instead of
>> the enum.

I'm sorry that I'm responding out-of-order to this email of yours -- for
some reason, your email is not correctly threaded in my list folder. It
is not connected to the 05/28 sub-thread, but to the blurb.

> Apologies, I missed the fact that you said document the mapping between
> the PVALIDATE return value and EFI_STATUS. So a caller is responsible to
> look at the EFI document to know what the error code means. The
> unsupported here does not mean that PVALIDATE is not support on
> platform.

That's right. First, you are only providing an X64 function definition.
Second, I requested that even the *declaration* of the function be
restricted to X64. Third, I requested that we document in the leading
comment that, unless CPUID reports support for PVALIDATE, the function
will trigger an #UD; it's the caller's responsibility *not* to call the
function, then. With those in mind, EFI_UNSUPPORTED *need not* stand for
any particular "platform characteristic", it can stand for whatever we
want it to -- such as mismatched page size. Still, in case you disliked
this ambiguity of EFI_UNSUPPORTED, I offered EFI_NO_MAPPING, for the
page size mismatch case.

> I am good with it. I will go ahead with it.

Thanks -- if you still prefer the UINTN approach, I can live with that
too (although EFI_STATUS would certainly make me happier).

Thank you!
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support
  2021-05-04 23:03           ` Brijesh Singh
@ 2021-05-05 19:19             ` Laszlo Ersek
  0 siblings, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-05 19:19 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/05/21 01:03, Brijesh Singh wrote:
> 
> On 5/4/21 3:28 PM, Brijesh Singh wrote:
>> On 5/4/21 2:55 PM, Brijesh Singh via groups.io wrote:
>>> On 5/4/21 2:07 PM, Brijesh Singh via groups.io wrote:
>>>>> Return EFI_UNSUPPORTED (0x8000_0003), or even EFI_NO_MAPPING
>>>>> (0x8000_0017), for value 6 (FAIL_SIZEMISMATCH).
>>>> I am not sure if we really want to do this. You will see later in the
>>>> patches that in some cases the PVALIDATE will return a failure and we
>>>> will need to know the failure code to determine the next steps.
>>>> Especially this particular error code is used later. This error happens
>>>> when the page size of the backing pages does not match with the
>>>> pvalidated size. In those cases we need to retry the PVALIDATE with
>>>> lower page size so that a validation succeed. One such a example is:
>>>>
>>>> - Guest ask hypervisor to add the page as 2M in RMP table.
>>>>
>>>> - Hypervisor added the page as 512 4K pages - because it was not able to
>>>> find a large backing pages.
>>>>
>>>> - Guest attempts to pvalidate the page as a 2M. The pvalidate will
>>>> return a failure saying its a size mismatch between the requested
>>>> pvalidated and RMP table. The recommendation is that guest should try
>>>> with a smaller page size.
>>>>
>>>> I would prefer to pass the pvalidate error as-is to caller so that it
>>>> can make the correct decision.
>>>>
>>> I am perfectly fine if the function return UINTN and then use #define
>>> instead of the enum to define the PVALIDATE return code. So that caller
>>> can check the error code. Let me know your thought on #define instead of
>>> the enum.
>> Apologies, I missed the fact that you said document the mapping between
>> the PVALIDATE return value and EFI_STATUS. So a caller is responsible to
>> look at the EFI document to know what the error code means. The
>> unsupported here does not mean that PVALIDATE is not support on
>> platform. I am good with it. I will go ahead with it.
> 
> While coding it I am coming to realizing that mapping from PVALIDATE
> return value to EFI will add more code in assemblym and wanted to make
> sure that we all are okay with it. The proposed mapping looks like this:
> 
> // No mapping required, both the values are zero
> 
> PVALIDATE_RET_SUCCESS -> EFI_SUCCESS   
> 
> // Pvalidate.nasm need to map from PVALIDATE fail input (1) to
> EFI_INVALID_PRAMS (2)
> 
> PVALIATE_RET_FAIL_INPUT -> EFI_INVALID_PARAMS
> 
> // Pvalidate.nasm need to map from PVALIDATE SIZE_MISMATCH (6) to
> EFI_UNSUPPORT(3)
> 
> PVALIATE_RET_SIZEMISMATCH -> EFI_UNSUPPORTED
> 
> May I recommend to use UINTN and simply propagate the PVALIDATE return
> value  or use the below mapping to simplify the pvalidate.nasm
> implementation:
> 
> PVALIDATE_RET_SUCCESS(0) -> EFI_SUCCESS(0)
> 
> PVALIDATE_RET_FAIL_INPUT(1) -> EFI_LOAD_ERROR(1)
> 
> PVALIDATE_RET_SIZE_MISMATCH(6) -> EFI_NOT_READY(6)

The additional complexity in the assembly source code is not lost on me.
I'm receptive to that.

I think EFI_LOAD_ERROR and EFI_NOT_READY would do more damage than good;
those error codes are meaningless in this context.

Therefore, please go ahead with the UINTN return type. And, whether you
pick #defines, or enum constants, for the symbolic names (for the
comparisons at the call sites), that's up to you.

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures
  2021-05-05 18:24       ` Laszlo Ersek
@ 2021-05-05 19:27         ` Brijesh Singh
  0 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-05-05 19:27 UTC (permalink / raw)
  To: Laszlo Ersek, devel
  Cc: brijesh.singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/5/21 1:24 PM, Laszlo Ersek wrote:
> On 05/04/21 20:53, Brijesh Singh wrote:
>> On 5/4/21 7:33 AM, Laszlo Ersek wrote:
>>> On 04/30/21 13:51, Brijesh Singh wrote:
>>>> +typedef PACKED struct {
>>>> +  UINT16 CurrentEntry;
>>>> +  UINT16 EndEntry;
>>>> +  UINT32 Rsvd;
>>>> +} SNP_PAGE_STATE_HEADER;
>>> (9) If my understanding of the spec is correct, "EndEntry" has
>>> *inclusive* meaning. That's unusual. Any particular reason for not
>>> making "EndEntry" exclusive (in the spec)?
>> Sometimes guest may need to fill only few entries. The "EndEntry" will
>> give hint to hypervisor that it should stop processing after it reached
>> to the EndEntry.
> I understood the purpose of EndEntry.
>
> My question is why the entry identified by EndEntry *itself* needs to be
> processed.
>
> Put differently, I'm asking why your loop controlling expression is
>
>   Info->Header.CurrentEntry <= Info->Header.EndEntry            [1]
>
> and why not
>
>   Info->Header.CurrentEntry < Info->Header.EndEntry             [2]
>
> in patch #21 ("OvmfPkg/MemEncryptSevLib: Add support to validate system
> RAM").
>
> In case [1], EndEntry is an inclusive limit.
>
> In case [2], EndEntry would be an exclusive limit.
>
> My question is why the spec defines EndEntry with inclusive rather than
> exclusive meaning.
>
> Using inclusive low bounds with exclusive high bounds has mental advantages:
>
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.cs.utexas.edu%2Fusers%2FEWD%2Ftranscriptions%2FEWD08xx%2FEWD831.html&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7Ce837bb9a71bd47a8337b08d90ff303ae%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637558358685096067%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=uhtfVW6Q%2FIpHwI%2BfNM3DVur92b2KFB5pjaL1dgZtLC8%3D&amp;reserved=0
>
> Is there a specific reason for which the spec chose the inclusive high
> bound?

Tom and I talked to see if one of us remembers the reason for choosing
the EndEntry inclusive. Unfortunately, we were not able to recall or
trace from where this request came in, but now it is in the spec, and we
have to live with it :(

-Brijesh


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD
  2021-05-05 13:11     ` Brijesh Singh
@ 2021-05-05 19:33       ` Laszlo Ersek
  2021-05-06 10:57         ` Dov Murik
  2021-05-06 16:02         ` James Bottomley
  0 siblings, 2 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-05 19:33 UTC (permalink / raw)
  To: devel, brijesh.singh, Dov Murik
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas, tobin@ibm.com

On 05/05/21 15:11, Brijesh Singh wrote:
> 
> On 5/5/21 1:42 AM, Dov Murik wrote:
>> [+cc: Tobin]
>>
>> Hi Brijesh,
>>
>> On 30/04/2021 14:51, Brijesh Singh wrote:
>>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C93168c94eb6d44ed08e608d90f910426%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637557937779907471%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=nLpmk3G%2BmXcZrzXxCmO3M9EDPiLRnP1IUmPqRQNbBuU%3D&amp;reserved=0
>>>
>>> When AMD SEV is enabled in the guest VM, a hypervisor need to insert a
>>> secrets page.
>>>
>>> When SEV-SNP is enabled, the secrets page contains the VM platform
>>> communication keys. The guest BIOS and OS can use this key to communicate
>>> with the SEV firmware to get attesation report. See the SEV-SNP firmware
>>> spec for more details for the content of the secrets page.
>>>
>>> When SEV and SEV-ES is enabled, the secrets page contains the information
>>> provided by the guest owner after the attestation. See the SEV
>>> LAUNCH_SECRET command for more details.
>>>
>>> Cc: James Bottomley <jejb@linux.ibm.com>
>>> Cc: Min Xu <min.m.xu@intel.com>
>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>>> Cc: Laszlo Ersek <lersek@redhat.com>
>>> Cc: Erdem Aktas <erdemaktas@google.com>
>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>> ---
>>>  OvmfPkg/AmdSev/SecretPei/SecretPei.c   | 16 +++++++++++++++-
>>>  OvmfPkg/AmdSev/SecretPei/SecretPei.inf |  1 +
>>>  OvmfPkg/OvmfPkgX64.dsc                 |  2 ++
>>>  OvmfPkg/OvmfPkgX64.fdf                 |  5 +++++
>>>  4 files changed, 23 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.c b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>>> index ad491515dd..92836c562c 100644
>>> --- a/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>>> +++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>>> @@ -7,6 +7,7 @@
>>>  #include <PiPei.h>
>>>  #include <Library/HobLib.h>
>>>  #include <Library/PcdLib.h>
>>> +#include <Library/MemEncryptSevLib.h>
>>>
>>>  EFI_STATUS
>>>  EFIAPI
>>> @@ -15,10 +16,23 @@ InitializeSecretPei (
>>>    IN CONST EFI_PEI_SERVICES     **PeiServices
>>>    )
>>>  {
>>> +  UINTN   Type;
>>> +
>>> +  //
>>> +  // The secret page should be mapped encrypted by the guest OS and must not
>>> +  // be treated as a system RAM. Mark it as ACPI NVS so that guest OS maps it
>>> +  // encrypted.
>>> +  //
>>> +  if (MemEncryptSevSnpIsEnabled ()) {
>>> +    Type = EfiACPIMemoryNVS;
>>> +  } else {
>>> +    Type = EfiBootServicesData;
>>> +  }
>>> +
>> Would it make sense to always use EfiACPIMemoryNVS for the injected secret area, even for regular SEV (non-SNP)?
> 
> Ideally yes. Maybe James had some reasons for choosing the
> EfiBootServicesData. If I had to guess, it was mainly because there no
> guest kernel support which consumes the SEV secrets page.

git-blame fingers commit bff2811c6d99 ("OvmfPkg/AmdSev: assign and
reserve the Sev Secret area", 2020-12-14).

Commit bff2811c6d99 makes it clear that the area in question lives in MEMFD.

We're populating the area in the PEI phase. We don't want anything in
DXE to overwrite it.

Once the bootloader (and/or perhaps the kernel's EFI stub) fetched the
secret from that particular location, there is no need to prevent later
parts of the OS (the actual kernel) from repurposing that area. That's
why EfiBootServicesData was used.

> Since the
> memory is not marked ACPI NVS, so it can be used as a system RAM after
> the ExitBootServices is called in the kernel.

Yes.

I don't think AcpiNVS would be a good fit. Linux saves and restores
AcpiNVS areas upon S3 suspend/resume. Regardless of whether S3 works, or
will work, in SEV* guests, if we don't want the guest kernel to touch
that area *at all*, Reserved is a better type.

Please refer to "Table 7-6 Memory Type Usage after ExitBootServices()"
in the UEFI spec (v2.9).

> 
> I am fine with using ACPI NVS for both SEV and SEV-SNP. I was not able
> to build and run AmdSev package in my setup, can you submit a prepatch
> to change the memory type and verify that it works ?

NB: I've not yet reached this patch in my own review of the series, so
I'm likely missing some context. I do have a thought -- under SEV-SNP,
the secrets page apparently needs different (stronger) protection from
the host as under plain SEV. I don't think that hiding the different
protection requirements behind a single common memory type is helpful.
Not to mention the wasted memory in the plain SEV case -- it's not a lot
of memory, mind you, but the principle matters.

So ATM I would like to keep this patch in the SEV-SNP series, and to
preserve the different memory types between SEV and SEV-SNP.

Thanks
Laszlo




> 
>>
>> -Dov
>>
>>
>>
>>>    BuildMemoryAllocationHob (
>>>      PcdGet32 (PcdSevLaunchSecretBase),
>>>      PcdGet32 (PcdSevLaunchSecretSize),
>>> -    EfiBootServicesData
>>> +    Type
>>>      );
>>>
>>>    return EFI_SUCCESS;
>>> diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>> index 08be156c4b..9265f8adee 100644
>>> --- a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>> +++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>> @@ -26,6 +26,7 @@
>>>    HobLib
>>>    PeimEntryPoint
>>>    PcdLib
>>> +  MemEncryptSevLib
>>>
>>>  [FixedPcd]
>>>    gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
>>> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
>>> index a7d747f6b4..593c0e69f6 100644
>>> --- a/OvmfPkg/OvmfPkgX64.dsc
>>> +++ b/OvmfPkg/OvmfPkgX64.dsc
>>> @@ -716,6 +716,7 @@
>>>    OvmfPkg/SmmAccess/SmmAccessPei.inf
>>>  !endif
>>>    UefiCpuPkg/CpuMpPei/CpuMpPei.inf
>>> +  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>
>>>  !if $(TPM_ENABLE) == TRUE
>>>    OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
>>> @@ -965,6 +966,7 @@
>>>    OvmfPkg/PlatformDxe/Platform.inf
>>>    OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>>>    OvmfPkg/IoMmuDxe/IoMmuDxe.inf
>>> +  OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>>>
>>>  !if $(SMM_REQUIRE) == TRUE
>>>    OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
>>> diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
>>> index d519f85328..b04175f77c 100644
>>> --- a/OvmfPkg/OvmfPkgX64.fdf
>>> +++ b/OvmfPkg/OvmfPkgX64.fdf
>>> @@ -88,6 +88,9 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.PcdSevE
>>>  0x00C000|0x001000
>>>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
>>>
>>> +0x00D000|0x001000
>>> +gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
>>> +
>>>  0x010000|0x010000
>>>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
>>>
>>> @@ -178,6 +181,7 @@ INF  OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
>>>  INF  SecurityPkg/Tcg/TcgPei/TcgPei.inf
>>>  INF  SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
>>>  !endif
>>> +INF  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>
>>>  ################################################################################
>>>
>>> @@ -313,6 +317,7 @@ INF  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
>>>  INF  ShellPkg/Application/Shell/Shell.inf
>>>
>>>  INF MdeModulePkg/Logo/LogoDxe.inf
>>> +INF OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>>>
>>>  #
>>>  # Network modules
>>>
> 
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 27/28] OvmfPkg/AmdSev: Expose the SNP reserved pages through configuration table
  2021-05-05  7:10   ` [edk2-devel] " Dov Murik
@ 2021-05-05 19:37     ` Laszlo Ersek
  0 siblings, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-05 19:37 UTC (permalink / raw)
  To: devel, dovmurik, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/05/21 09:10, Dov Murik wrote:
> Hi Brijesh,
> 
> On 30/04/2021 14:51, Brijesh Singh wrote:
>> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
>>
>> Now that both the secrets and cpuid pages are reserved in the HOB,
>> extract the location details through fixed PCD and make it available
>> to the guest OS through the configuration table.
>>
>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  OvmfPkg/AmdSev/SecretDxe/SecretDxe.c               | 21 ++++++++++++++++++++
>>  OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf             |  4 ++++
>>  OvmfPkg/Include/Guid/ConfidentialComputingSecret.h | 17 ++++++++++++++++
>>  OvmfPkg/OvmfPkg.dec                                |  1 +
>>  4 files changed, 43 insertions(+)
>>
>> diff --git a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c
>> index 308022b5b2..08b6d9bddf 100644
>> --- a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c
>> +++ b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c
>> @@ -6,6 +6,7 @@
>>  **/
>>  #include <PiDxe.h>
>>  #include <Library/UefiBootServicesTableLib.h>
>> +#include <Library/MemEncryptSevLib.h>
>>  #include <Guid/ConfidentialComputingSecret.h>
>>
>>  STATIC CONFIDENTIAL_COMPUTING_SECRET_LOCATION mSecretDxeTable = {
>> @@ -13,6 +14,15 @@ STATIC CONFIDENTIAL_COMPUTING_SECRET_LOCATION mSecretDxeTable = {
>>    FixedPcdGet32 (PcdSevLaunchSecretSize),
>>  };
>>
>> +STATIC CONFIDENTIAL_COMPUTING_BLOB_LOCATION mSnpBootDxeTable = {
>> +  0x414d4445,     // AMDE
> 
> (nit: I believe this UINT32 will appear in memory as the string "EDMA".)

Please consider the SIGNATURE_32() macro.

> 
> 
> 
>> +  1,
> 
> Not sure what's the official stance regarding a version field here. Maybe it's better to generate a new GUID whenever there's a struct change.

A version scalar is good for compatible changes (= only appending new
fields). Incompatible changes require GUID changes.

(I'll review this patch myself from the scratch later; just making some
quick comments-on-comments for the time being.)

Thanks
Laszlo

> 
> 
> -Dov
> 
> 
>> +  (UINT64)(UINTN) FixedPcdGet32 (PcdSevLaunchSecretBase),
>> +  FixedPcdGet32 (PcdSevLaunchSecretSize),
>> +  (UINT64)(UINTN) FixedPcdGet32 (PcdOvmfSnpCpuidBase),
>> +  FixedPcdGet32 (PcdOvmfSnpCpuidSize),
>> +};
>> +
>>  EFI_STATUS
>>  EFIAPI
>>  InitializeSecretDxe(
>> @@ -20,6 +30,17 @@ InitializeSecretDxe(
>>    IN EFI_SYSTEM_TABLE     *SystemTable
>>    )
>>  {
>> +  //
>> +  // If its SEV-SNP active guest then install the CONFIDENTIAL_COMPUTING_BLOB.
>> +  // It contains the location for both the Secrets and CPUID page.
>> +  //
>> +  if (MemEncryptSevSnpIsEnabled ()) {
>> +    return gBS->InstallConfigurationTable (
>> +                  &gConfidentialComputingBlobGuid,
>> +                  &mSnpBootDxeTable
>> +                  );
>> +  }
>> +
>>    return gBS->InstallConfigurationTable (
>>                  &gConfidentialComputingSecretGuid,
>>                  &mSecretDxeTable
>> diff --git a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>> index 40bda7ff84..d15194b368 100644
>> --- a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>> +++ b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>> @@ -23,13 +23,17 @@
>>    MdePkg/MdePkg.dec
>>
>>  [LibraryClasses]
>> +  MemEncryptSevLib
>>    UefiBootServicesTableLib
>>    UefiDriverEntryPoint
>>
>>  [Guids]
>>    gConfidentialComputingSecretGuid
>> +  gConfidentialComputingBlobGuid
>>
>>  [FixedPcd]
>> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase
>> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize
>>    gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
>>    gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
>>
>> diff --git a/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h b/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
>> index 7026fc5b08..0d7f1b8818 100644
>> --- a/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
>> +++ b/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
>> @@ -18,11 +18,28 @@
>>      { 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47 }, \
>>    }
>>
>> +#define CONFIDENTIAL_COMPUTING_BLOB_GUID                \
>> +  { 0x067b1f5f,                                         \
>> +    0xcf26,                                             \
>> +    0x44c5,                                             \
>> +    { 0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42 }, \
>> +  }
>> +
>>  typedef struct {
>>    UINT64 Base;
>>    UINT64 Size;
>>  } CONFIDENTIAL_COMPUTING_SECRET_LOCATION;
>>
>> +typedef struct {
>> +  UINT32  Header;
>> +  UINT16  Version;
>> +  UINT64  SecretsPhysicalAddress;
>> +  UINT32  SecretsSize;
>> +  UINT64  CpuidPhysicalAddress;
>> +  UINT32  CpuidLSize;
>> +} CONFIDENTIAL_COMPUTING_BLOB_LOCATION;
>> +
>>  extern EFI_GUID gConfidentialComputingSecretGuid;
>> +extern EFI_GUID gConfidentialComputingBlobGuid;
>>
>>  #endif // SEV_LAUNCH_SECRET_H_
>> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
>> index d1bfe49731..f38c5e476a 100644
>> --- a/OvmfPkg/OvmfPkg.dec
>> +++ b/OvmfPkg/OvmfPkg.dec
>> @@ -126,6 +126,7 @@
>>    gQemuKernelLoaderFsMediaGuid          = {0x1428f772, 0xb64a, 0x441e, {0xb8, 0xc3, 0x9e, 0xbd, 0xd7, 0xf8, 0x93, 0xc7}}
>>    gGrubFileGuid                         = {0xb5ae312c, 0xbc8a, 0x43b1, {0x9c, 0x62, 0xeb, 0xb8, 0x26, 0xdd, 0x5d, 0x07}}
>>    gConfidentialComputingSecretGuid      = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}}
>> +  gConfidentialComputingBlobGuid        = {0x067b1f5f, 0xcf26, 0x44c5, {0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42}}
>>
>>  [Ppis]
>>    # PPI whose presence in the PPI database signals that the TPM base address
>>
> 
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 06/28] OvmfPkg/BaseMemEncryptSevLib: Introduce MemEncryptSevClearMmioPageEncMask()
  2021-04-30 11:51 ` [PATCH RFC v2 06/28] OvmfPkg/BaseMemEncryptSevLib: Introduce MemEncryptSevClearMmioPageEncMask() Brijesh Singh
@ 2021-05-06 10:39   ` Laszlo Ersek
  2021-05-06 19:18     ` Brijesh Singh
  0 siblings, 1 reply; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-06 10:39 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 04/30/21 13:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
> 
> The MemEncryptSevClearMmioPageEncMask() helper can be used for clearing
> the memory encryption mask for the Mmio region from the current page
> table context.

The commit message, and five comments in the patch, say "current page
table context". However, Cr3BaseAddress is taken explicitly.

I realize the files being modified in this patch already make similarly
incorrect statements, but I'd like if we avoided adding more.

(1) Please just drop "current page table context" from the mentioned six
locations. (Explaining that Cr3BaseAddress=0 means "current CR3" is of
course valid.)


> 
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  OvmfPkg/Include/Library/MemEncryptSevLib.h                     | 25 +++++++++++
>  OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c   | 31 ++++++++++++++
>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c    | 33 +++++++++++++++
>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 44 ++++++++++++++++++--
>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h       | 23 ++++++++++
>  5 files changed, 153 insertions(+), 3 deletions(-)
> 
> diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
> index 99f15a7d12..c19f92afc6 100644
> --- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
> +++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
> @@ -203,4 +203,29 @@ MemEncryptSevGetAddressRangeState (
>    IN UINTN                    Length
>    );
>  
> +/**
> +  This function clears memory encryption bit for the mmio region specified by
> +  BaseAddress and NumPages from the current page table context.
> +
> +  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
> +                                      current CR3)
> +  @param[in]  BaseAddress             The physical address that is the start
> +                                      address of a mmio region.
> +  @param[in]  NumPages                The number of pages from start memory
> +                                      region.
> +
> +  @retval RETURN_SUCCESS              The attributes were cleared for the
> +                                      memory region.
> +  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
> +  @retval RETURN_UNSUPPORTED          Clearing the memory encryption attribute
> +                                      is not supported
> +**/
> +RETURN_STATUS
> +EFIAPI
> +MemEncryptSevClearMmioPageEncMask (
> +  IN PHYSICAL_ADDRESS         Cr3BaseAddress,
> +  IN PHYSICAL_ADDRESS         BaseAddress,
> +  IN UINTN                    NumPages
> +  );
> +
>  #endif // _MEM_ENCRYPT_SEV_LIB_H_
> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
> index 12a5bf495b..4e8a997d42 100644
> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
> @@ -111,3 +111,34 @@ MemEncryptSevGetAddressRangeState (
>    //
>    return MemEncryptSevAddressRangeEncrypted;
>  }
> +
> +/**
> +  This function clears memory encryption bit for the mmio region specified by
> +  BaseAddress and NumPages from the current page table context.
> +
> +  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
> +                                      current CR3)
> +  @param[in]  BaseAddress             The physical address that is the start
> +                                      address of a mmio region.
> +  @param[in]  NumPages                The number of pages from start memory
> +                                      region.
> +
> +  @retval RETURN_SUCCESS              The attributes were cleared for the
> +                                      memory region.
> +  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
> +  @retval RETURN_UNSUPPORTED          Clearing the memory encryption attribute
> +                                      is not supported
> +**/
> +RETURN_STATUS
> +EFIAPI
> +MemEncryptSevClearMmioPageEncMask (
> +  IN PHYSICAL_ADDRESS         Cr3BaseAddress,
> +  IN PHYSICAL_ADDRESS         BaseAddress,
> +  IN UINTN                    NumPages
> +  )
> +{
> +  //
> +  // Memory encryption bit is not accessible in 32-bit mode
> +  //
> +  return RETURN_UNSUPPORTED;
> +}
> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
> index 4fea6a6be0..6786573aea 100644
> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
> @@ -118,3 +118,36 @@ MemEncryptSevGetAddressRangeState (
>             Length
>             );
>  }
> +
> +/**
> +  This function clears memory encryption bit for the mmio region specified by
> +  BaseAddress and NumPages from the current page table context.
> +
> +  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
> +                                      current CR3)
> +  @param[in]  BaseAddress             The physical address that is the start
> +                                      address of a mmio region.
> +  @param[in]  NumPages                The number of pages from start memory
> +                                      region.
> +
> +  @retval RETURN_SUCCESS              The attributes were cleared for the
> +                                      memory region.
> +  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
> +  @retval RETURN_UNSUPPORTED          Clearing the memory encryption attribute
> +                                      is not supported
> +**/
> +RETURN_STATUS
> +EFIAPI
> +MemEncryptSevClearMmioPageEncMask (
> +  IN PHYSICAL_ADDRESS         Cr3BaseAddress,
> +  IN PHYSICAL_ADDRESS         BaseAddress,
> +  IN UINTN                    NumPages
> +  )
> +{
> +  return InternalMemEncryptSevClearMmioPageEncMask (
> +           Cr3BaseAddress,
> +           BaseAddress,
> +           EFI_PAGES_TO_SIZE (NumPages)
> +           );
> +
> +}
> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
> index d3455e812b..3bcc92f2e9 100644
> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
> @@ -557,6 +557,7 @@ EnableReadOnlyPageWriteProtect (
>    @param[in]  Mode                    Set or Clear mode
>    @param[in]  CacheFlush              Flush the caches before applying the
>                                        encryption mask
> +  @param[in]  IsMmio                  The address is Mmio address.
>  
>    @retval RETURN_SUCCESS              The attributes were cleared for the
>                                        memory region.

(2) The parameter's name in the documentation ("IsMmio") does not match
the actual parameter name ("Mmio").


> @@ -572,7 +573,8 @@ SetMemoryEncDec (
>    IN    PHYSICAL_ADDRESS         PhysicalAddress,
>    IN    UINTN                    Length,
>    IN    MAP_RANGE_MODE           Mode,
> -  IN    BOOLEAN                  CacheFlush
> +  IN    BOOLEAN                  CacheFlush,
> +  IN    BOOLEAN                  Mmio
>    )
>  {
>    PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;

The "Mmio" parameter is not used for anything in this patch. It's very
confusing.

(3) Please remove the addition of the Mmio parameter from this patch.
Please introduce the Mmio parameter only when it is utilized -- as far
as I can tell from a quick git-blame, that's patch #26
("OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table").

As a result, in this patch, InternalMemEncryptSevClearMmioPageEncMask()
will effectively become a slight simplification of
InternalMemEncryptSevSetMemoryDecrypted() -- rather than forwarding
"Flush" for "CacheFlush", it will pass constant FALSE for "CacheFlush".


(4) Please mention the above fact (= last paragraph above) in the commit
message.


> @@ -852,7 +854,8 @@ InternalMemEncryptSevSetMemoryDecrypted (
>             PhysicalAddress,
>             Length,
>             ClearCBit,
> -           Flush
> +           Flush,
> +           FALSE
>             );
>  }
>  
> @@ -888,6 +891,41 @@ InternalMemEncryptSevSetMemoryEncrypted (
>             PhysicalAddress,
>             Length,
>             SetCBit,
> -           Flush
> +           Flush,
> +           FALSE
> +           );
> +}
> +
> +/**
> +  This function clears memory encryption bit for the Mmio region specified by
> +  PhysicalAddress and Length from the current page table context.
> +
> +  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
> +                                      current CR3)
> +  @param[in]  PhysicalAddress         The physical address that is the start
> +                                      address of a mmio region.
> +  @param[in]  Length                  The length of memory region
> +
> +  @retval RETURN_SUCCESS              The attributes were cleared for the
> +                                      memory region.
> +  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.

This function does not take a NumPages parameter but a Length parameter.

(5) Please update the RETURN_INVALID_PARAMETER comment accordingly -- in
the header file as well.


> +  @retval RETURN_UNSUPPORTED          Clearing the memory encyrption attribute
> +                                      is not supported
> +**/
> +RETURN_STATUS
> +EFIAPI
> +InternalMemEncryptSevClearMmioPageEncMask (
> +  IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
> +  IN  PHYSICAL_ADDRESS        PhysicalAddress,
> +  IN  UINTN                   Length
> +  )
> +{
> +  return SetMemoryEncDec (
> +           Cr3BaseAddress,
> +           PhysicalAddress,
> +           Length,
> +           ClearCBit,
> +           FALSE,
> +           TRUE
>             );
>  }
> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
> index fe2a0b2826..99ee7ea0e8 100644
> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
> @@ -126,4 +126,27 @@ InternalMemEncryptSevGetAddressRangeState (
>    IN UINTN                    Length
>    );
>  
> +/**
> +  This function clears memory encryption bit for the Mmio region specified by
> +  PhysicalAddress and Length from the current page table context.
> +
> +  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
> +                                      current CR3)
> +  @param[in]  PhysicalAddress         The physical address that is the start
> +                                      address of a mmio region.
> +  @param[in]  Length                  The length of memory region
> +
> +  @retval RETURN_SUCCESS              The attributes were cleared for the
> +                                      memory region.
> +  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.

This function does not take a NumPages parameter but a Length parameter.

(6) Please update the RETURN_INVALID_PARAMETER comment accordingly --
same as in the C file.


> +  @retval RETURN_UNSUPPORTED          Clearing the memory encyrption attribute
> +                                      is not supported
> +**/
> +RETURN_STATUS
> +EFIAPI
> +InternalMemEncryptSevClearMmioPageEncMask (
> +  IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
> +  IN  PHYSICAL_ADDRESS        PhysicalAddress,
> +  IN  UINTN                   Length
> +  );
>  #endif
> 

Please carefully audit the rest of the series for comment blocks. Such
issues render reviews inefficient.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 07/28] OvmfPkg: Use MemEncryptSevClearMmioPageEncMask() to clear EncMask from Mmio
  2021-04-30 11:51 ` [PATCH RFC v2 07/28] OvmfPkg: Use MemEncryptSevClearMmioPageEncMask() to clear EncMask from Mmio Brijesh Singh
@ 2021-05-06 10:50   ` Laszlo Ersek
  2021-05-06 19:20     ` Brijesh Singh
  0 siblings, 1 reply; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-06 10:50 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 04/30/21 13:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
> 
> Use the MemEncryptSevClearMmioPageEncMask() to clear memory encryption mask
> for the Mmio address range from the current page table context.
> 
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  OvmfPkg/AmdSevDxe/AmdSevDxe.c                              | 10 ++++------
>  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c |  5 ++---
>  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c      |  5 ++---
>  3 files changed, 8 insertions(+), 12 deletions(-)
> 
> diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
> index 689bfb376d..80831b81fa 100644
> --- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c
> +++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
> @@ -53,11 +53,10 @@ AmdSevDxeEntryPoint (
>        Desc = &AllDescMap[Index];
>        if (Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo ||
>            Desc->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
> -        Status = MemEncryptSevClearPageEncMask (
> +        Status = MemEncryptSevClearMmioPageEncMask (
>                     0,
>                     Desc->BaseAddress,
> -                   EFI_SIZE_TO_PAGES (Desc->Length),
> -                   FALSE
> +                   EFI_SIZE_TO_PAGES (Desc->Length)
>                     );
>          ASSERT_EFI_ERROR (Status);
>        }
> @@ -73,11 +72,10 @@ AmdSevDxeEntryPoint (
>    // the range.
>    //
>    if (PcdGet16 (PcdOvmfHostBridgePciDevId) == INTEL_Q35_MCH_DEVICE_ID) {
> -    Status = MemEncryptSevClearPageEncMask (
> +    Status = MemEncryptSevClearMmioPageEncMask (
>                 0,
>                 FixedPcdGet64 (PcdPciExpressBaseAddress),
> -               EFI_SIZE_TO_PAGES (SIZE_256MB),
> -               FALSE
> +               EFI_SIZE_TO_PAGES (SIZE_256MB)
>                 );
>  
>      ASSERT_EFI_ERROR (Status);
> diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
> index 1f285e0083..ab40087a84 100644
> --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
> +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
> @@ -205,11 +205,10 @@ MarkIoMemoryRangeForRuntimeAccess (
>    // memory range.
>    //
>    if (MemEncryptSevIsEnabled ()) {
> -    Status = MemEncryptSevClearPageEncMask (
> +    Status = MemEncryptSevClearMmioPageEncMask (
>                 0,
>                 BaseAddress,
> -               EFI_SIZE_TO_PAGES (Length),
> -               FALSE
> +               EFI_SIZE_TO_PAGES (Length)
>                 );
>      ASSERT_EFI_ERROR (Status);
>    }
> diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
> index 7eb80bfeff..ea75b489c7 100644
> --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
> +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
> @@ -38,11 +38,10 @@ QemuFlashBeforeProbe (
>    // C-bit on flash ranges from SMM page table.
>    //
>  
> -  Status = MemEncryptSevClearPageEncMask (
> +  Status = MemEncryptSevClearMmioPageEncMask (
>               0,
>               BaseAddress,
> -             EFI_SIZE_TO_PAGES (FdBlockSize * FdBlockCount),
> -             FALSE
> +             EFI_SIZE_TO_PAGES (FdBlockSize * FdBlockCount)
>               );
>    ASSERT_EFI_ERROR (Status);
>  }
> 

The contents of this patch are sound, but they are incomplete, and
incorrectly structured too.

(1) Please provide a separate patch for each modified module.

(2) You missed the MemEncryptSevClearPageEncMask() call in
TpmMmioSevDecryptPeimEntryPoint()
[OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c] -- probably
because you worked on this series in parallel with Tom working on the
SEV-ES TPM fixes.

In the end, this patch should be split into three patches (because the
change is needed for three modules).

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD
  2021-05-05 19:33       ` Laszlo Ersek
@ 2021-05-06 10:57         ` Dov Murik
  2021-05-06 15:06           ` Laszlo Ersek
  2021-05-06 16:12           ` James Bottomley
  2021-05-06 16:02         ` James Bottomley
  1 sibling, 2 replies; 81+ messages in thread
From: Dov Murik @ 2021-05-06 10:57 UTC (permalink / raw)
  To: Laszlo Ersek, devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas, tobin@ibm.com



On 05/05/2021 22:33, Laszlo Ersek wrote:
> On 05/05/21 15:11, Brijesh Singh wrote:
>>
>> On 5/5/21 1:42 AM, Dov Murik wrote:
>>> [+cc: Tobin]
>>>
>>> Hi Brijesh,
>>>
>>> On 30/04/2021 14:51, Brijesh Singh wrote:
>>>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C93168c94eb6d44ed08e608d90f910426%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637557937779907471%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=nLpmk3G%2BmXcZrzXxCmO3M9EDPiLRnP1IUmPqRQNbBuU%3D&amp;reserved=0
>>>>
>>>> When AMD SEV is enabled in the guest VM, a hypervisor need to insert a
>>>> secrets page.
>>>>
>>>> When SEV-SNP is enabled, the secrets page contains the VM platform
>>>> communication keys. The guest BIOS and OS can use this key to communicate
>>>> with the SEV firmware to get attesation report. See the SEV-SNP firmware
>>>> spec for more details for the content of the secrets page.
>>>>
>>>> When SEV and SEV-ES is enabled, the secrets page contains the information
>>>> provided by the guest owner after the attestation. See the SEV
>>>> LAUNCH_SECRET command for more details.
>>>>
>>>> Cc: James Bottomley <jejb@linux.ibm.com>
>>>> Cc: Min Xu <min.m.xu@intel.com>
>>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>>>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>>>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>>>> Cc: Laszlo Ersek <lersek@redhat.com>
>>>> Cc: Erdem Aktas <erdemaktas@google.com>
>>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>>> ---
>>>>  OvmfPkg/AmdSev/SecretPei/SecretPei.c   | 16 +++++++++++++++-
>>>>  OvmfPkg/AmdSev/SecretPei/SecretPei.inf |  1 +
>>>>  OvmfPkg/OvmfPkgX64.dsc                 |  2 ++
>>>>  OvmfPkg/OvmfPkgX64.fdf                 |  5 +++++
>>>>  4 files changed, 23 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.c b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>>>> index ad491515dd..92836c562c 100644
>>>> --- a/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>>>> +++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>>>> @@ -7,6 +7,7 @@
>>>>  #include <PiPei.h>
>>>>  #include <Library/HobLib.h>
>>>>  #include <Library/PcdLib.h>
>>>> +#include <Library/MemEncryptSevLib.h>
>>>>
>>>>  EFI_STATUS
>>>>  EFIAPI
>>>> @@ -15,10 +16,23 @@ InitializeSecretPei (
>>>>    IN CONST EFI_PEI_SERVICES     **PeiServices
>>>>    )
>>>>  {
>>>> +  UINTN   Type;
>>>> +
>>>> +  //
>>>> +  // The secret page should be mapped encrypted by the guest OS and must not
>>>> +  // be treated as a system RAM. Mark it as ACPI NVS so that guest OS maps it
>>>> +  // encrypted.
>>>> +  //
>>>> +  if (MemEncryptSevSnpIsEnabled ()) {
>>>> +    Type = EfiACPIMemoryNVS;
>>>> +  } else {
>>>> +    Type = EfiBootServicesData;
>>>> +  }
>>>> +
>>> Would it make sense to always use EfiACPIMemoryNVS for the injected secret area, even for regular SEV (non-SNP)?
>>
>> Ideally yes. Maybe James had some reasons for choosing the
>> EfiBootServicesData. If I had to guess, it was mainly because there no
>> guest kernel support which consumes the SEV secrets page.
> 
> git-blame fingers commit bff2811c6d99 ("OvmfPkg/AmdSev: assign and
> reserve the Sev Secret area", 2020-12-14).
> 
> Commit bff2811c6d99 makes it clear that the area in question lives in MEMFD.
> 
> We're populating the area in the PEI phase. We don't want anything in
> DXE to overwrite it.
> 
> Once the bootloader (and/or perhaps the kernel's EFI stub) fetched the
> secret from that particular location, there is no need to prevent later
> parts of the OS (the actual kernel) from repurposing that area. That's
> why EfiBootServicesData was used.
> 

The first use of the secret area was to hold the guest luks disk passphrase; this is used in the grub-inside-OVMF (AmdSev package), and there was no need to keep that page around for the guest kernel.

The reason I'm raising this whole point is that we're working now on guest-kernel support for reading secrets from that injected page (for plain SEV).  We considered either (a) modifying the secrets page memory type to reserved here, or (b) add code to the kernel EFI stub that would copy this page somewhere else for kernel's later use (which seems more work and not sure what's the advantage).

Option (b) seems harder and more fragile, and I'm not sure if there are any advantages (though I'm definitely not an expert in that area).




>> Since the
>> memory is not marked ACPI NVS, so it can be used as a system RAM after
>> the ExitBootServices is called in the kernel.
> 
> Yes.
> 
> I don't think AcpiNVS would be a good fit. Linux saves and restores
> AcpiNVS areas upon S3 suspend/resume. Regardless of whether S3 works, or
> will work, in SEV* guests, if we don't want the guest kernel to touch
> that area *at all*, Reserved is a better type.

Thanks for this clarification.

> 
> Please refer to "Table 7-6 Memory Type Usage after ExitBootServices()"
> in the UEFI spec (v2.9).
> 
>>
>> I am fine with using ACPI NVS for both SEV and SEV-SNP. I was not able
>> to build and run AmdSev package in my setup, can you submit a prepatch
>> to change the memory type and verify that it works ?
> 
> NB: I've not yet reached this patch in my own review of the series, so
> I'm likely missing some context. I do have a thought -- under SEV-SNP,
> the secrets page apparently needs different (stronger) protection from
> the host as under plain SEV. I don't think that hiding the different
> protection requirements behind a single common memory type is helpful.
> Not to mention the wasted memory in the plain SEV case -- it's not a lot
> of memory, mind you, but the principle matters.
>

Like I said above, we have plans to have this small amount of memory available also to the guest OS; so maybe that shouldn't be the driving force in the decision here.

-Dov

 

> So ATM I would like to keep this patch in the SEV-SNP series, and to
> preserve the different memory types between SEV and SEV-SNP.
> 
> Thanks
> Laszlo
> 
> 
> 
> 
>>
>>>
>>> -Dov
>>>
>>>
>>>
>>>>    BuildMemoryAllocationHob (
>>>>      PcdGet32 (PcdSevLaunchSecretBase),
>>>>      PcdGet32 (PcdSevLaunchSecretSize),
>>>> -    EfiBootServicesData
>>>> +    Type
>>>>      );
>>>>
>>>>    return EFI_SUCCESS;
>>>> diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>> index 08be156c4b..9265f8adee 100644
>>>> --- a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>> +++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>> @@ -26,6 +26,7 @@
>>>>    HobLib
>>>>    PeimEntryPoint
>>>>    PcdLib
>>>> +  MemEncryptSevLib
>>>>
>>>>  [FixedPcd]
>>>>    gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
>>>> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
>>>> index a7d747f6b4..593c0e69f6 100644
>>>> --- a/OvmfPkg/OvmfPkgX64.dsc
>>>> +++ b/OvmfPkg/OvmfPkgX64.dsc
>>>> @@ -716,6 +716,7 @@
>>>>    OvmfPkg/SmmAccess/SmmAccessPei.inf
>>>>  !endif
>>>>    UefiCpuPkg/CpuMpPei/CpuMpPei.inf
>>>> +  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>>
>>>>  !if $(TPM_ENABLE) == TRUE
>>>>    OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
>>>> @@ -965,6 +966,7 @@
>>>>    OvmfPkg/PlatformDxe/Platform.inf
>>>>    OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>>>>    OvmfPkg/IoMmuDxe/IoMmuDxe.inf
>>>> +  OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>>>>
>>>>  !if $(SMM_REQUIRE) == TRUE
>>>>    OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
>>>> diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
>>>> index d519f85328..b04175f77c 100644
>>>> --- a/OvmfPkg/OvmfPkgX64.fdf
>>>> +++ b/OvmfPkg/OvmfPkgX64.fdf
>>>> @@ -88,6 +88,9 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.PcdSevE
>>>>  0x00C000|0x001000
>>>>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
>>>>
>>>> +0x00D000|0x001000
>>>> +gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
>>>> +
>>>>  0x010000|0x010000
>>>>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
>>>>
>>>> @@ -178,6 +181,7 @@ INF  OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
>>>>  INF  SecurityPkg/Tcg/TcgPei/TcgPei.inf
>>>>  INF  SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
>>>>  !endif
>>>> +INF  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>>
>>>>  ################################################################################
>>>>
>>>> @@ -313,6 +317,7 @@ INF  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
>>>>  INF  ShellPkg/Application/Shell/Shell.inf
>>>>
>>>>  INF MdeModulePkg/Logo/LogoDxe.inf
>>>> +INF OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>>>>
>>>>  #
>>>>  # Network modules
>>>>
>>
>>
>> 
>>
>>
> 

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 08/28] OvmfPkg/BaseMemEncryptSevLib: Remove CacheFlush parameter
  2021-04-30 11:51 ` [PATCH RFC v2 08/28] OvmfPkg/BaseMemEncryptSevLib: Remove CacheFlush parameter Brijesh Singh
@ 2021-05-06 11:08   ` Laszlo Ersek
  0 siblings, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-06 11:08 UTC (permalink / raw)
  To: devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 04/30/21 13:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
> 
> The CacheFlush parameter is used to provide hint whether the specified
> range is Mmio address. Now that we have a dedicated helper to clear the
> memory encryption mask for the Mmio address range, its safe to remove the
> CacheFlush parameter from MemEncryptSev{Set,Clear}PageEncMask().

The subject and the commit message body refer to "CacheFlush", but the
parameter (at the library class level) is actually called "Flush".

(1) Please update the subject and the commit message body.


> 
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  OvmfPkg/AmdSevDxe/AmdSevDxe.c                                  |  3 +--
>  OvmfPkg/Include/Library/MemEncryptSevLib.h                     | 10 ++--------
>  OvmfPkg/IoMmuDxe/AmdSevIoMmu.c                                 |  6 ++----
>  OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c   | 10 ++--------
>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c    | 16 ++++------------
>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 14 ++++----------
>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c    |  8 ++------
>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h       | 10 ++--------
>  OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c          |  3 +--
>  OvmfPkg/PlatformPei/AmdSev.c                                   |  3 +--
>  10 files changed, 21 insertions(+), 62 deletions(-)

Because we're modifying a library class header file, I agree we need to
update multiple modules in a single patch.


> 
> diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
> index 80831b81fa..41e4b291d0 100644
> --- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c
> +++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
> @@ -120,8 +120,7 @@ AmdSevDxeEntryPoint (
>      Status = MemEncryptSevClearPageEncMask (
>                 0,             // Cr3BaseAddress -- use current CR3
>                 MapPagesBase,  // BaseAddress
> -               MapPagesCount, // NumPages
> -               TRUE           // Flush
> +               MapPagesCount // NumPages
>                 );
>      if (EFI_ERROR (Status)) {
>        DEBUG ((DEBUG_ERROR, "%a: MemEncryptSevClearPageEncMask(): %r\n",

(2) By the removal of the comma, the comments are no longer nicely
aligned. Please insert a space character.

The rest looks OK to me.

Thanks
Laszlo

> diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
> index c19f92afc6..9b15d80931 100644
> --- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
> +++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
> @@ -100,8 +100,6 @@ MemEncryptSevIsEnabled (
>                                        address of a memory region.
>    @param[in]  NumPages                The number of pages from start memory
>                                        region.
> -  @param[in]  Flush                   Flush the caches before clearing the bit
> -                                      (mostly TRUE except MMIO addresses)
>  
>    @retval RETURN_SUCCESS              The attributes were cleared for the
>                                        memory region.
> @@ -114,8 +112,7 @@ EFIAPI
>  MemEncryptSevClearPageEncMask (
>    IN PHYSICAL_ADDRESS         Cr3BaseAddress,
>    IN PHYSICAL_ADDRESS         BaseAddress,
> -  IN UINTN                    NumPages,
> -  IN BOOLEAN                  Flush
> +  IN UINTN                    NumPages
>    );
>  
>  /**
> @@ -128,8 +125,6 @@ MemEncryptSevClearPageEncMask (
>                                        address of a memory region.
>    @param[in]  NumPages                The number of pages from start memory
>                                        region.
> -  @param[in]  Flush                   Flush the caches before setting the bit
> -                                      (mostly TRUE except MMIO addresses)
>  
>    @retval RETURN_SUCCESS              The attributes were set for the memory
>                                        region.
> @@ -142,8 +137,7 @@ EFIAPI
>  MemEncryptSevSetPageEncMask (
>    IN PHYSICAL_ADDRESS         Cr3BaseAddress,
>    IN PHYSICAL_ADDRESS         BaseAddress,
> -  IN UINTN                    NumPages,
> -  IN BOOLEAN                  Flush
> +  IN UINTN                    NumPages
>    );
>  
>  
> diff --git a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
> index 49ffa24488..b30628078f 100644
> --- a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
> +++ b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
> @@ -252,8 +252,7 @@ IoMmuMap (
>    Status = MemEncryptSevClearPageEncMask (
>               0,
>               MapInfo->PlainTextAddress,
> -             MapInfo->NumberOfPages,
> -             TRUE
> +             MapInfo->NumberOfPages
>               );
>    ASSERT_EFI_ERROR (Status);
>    if (EFI_ERROR (Status)) {
> @@ -407,8 +406,7 @@ IoMmuUnmapWorker (
>    Status = MemEncryptSevSetPageEncMask (
>               0,
>               MapInfo->PlainTextAddress,
> -             MapInfo->NumberOfPages,
> -             TRUE
> +             MapInfo->NumberOfPages
>               );
>    ASSERT_EFI_ERROR (Status);
>    if (EFI_ERROR (Status)) {
> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
> index 4e8a997d42..34e7c59e2c 100644
> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
> @@ -25,8 +25,6 @@
>                                        address of a memory region.
>    @param[in]  NumPages                The number of pages from start memory
>                                        region.
> -  @param[in]  Flush                   Flush the caches before clearing the bit
> -                                      (mostly TRUE except MMIO addresses)
>  
>    @retval RETURN_SUCCESS              The attributes were cleared for the
>                                        memory region.
> @@ -39,8 +37,7 @@ EFIAPI
>  MemEncryptSevClearPageEncMask (
>    IN PHYSICAL_ADDRESS         Cr3BaseAddress,
>    IN PHYSICAL_ADDRESS         BaseAddress,
> -  IN UINTN                    NumPages,
> -  IN BOOLEAN                  Flush
> +  IN UINTN                    NumPages
>    )
>  {
>    //
> @@ -59,8 +56,6 @@ MemEncryptSevClearPageEncMask (
>                                        address of a memory region.
>    @param[in]  NumPages                The number of pages from start memory
>                                        region.
> -  @param[in]  Flush                   Flush the caches before setting the bit
> -                                      (mostly TRUE except MMIO addresses)
>  
>    @retval RETURN_SUCCESS              The attributes were set for the memory
>                                        region.
> @@ -73,8 +68,7 @@ EFIAPI
>  MemEncryptSevSetPageEncMask (
>    IN PHYSICAL_ADDRESS         Cr3BaseAddress,
>    IN PHYSICAL_ADDRESS         BaseAddress,
> -  IN UINTN                    NumPages,
> -  IN BOOLEAN                  Flush
> +  IN UINTN                    NumPages
>    )
>  {
>    //
> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
> index 6786573aea..5c260c546e 100644
> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
> @@ -27,8 +27,6 @@
>                                        address of a memory region.
>    @param[in]  NumPages                The number of pages from start memory
>                                        region.
> -  @param[in]  Flush                   Flush the caches before clearing the bit
> -                                      (mostly TRUE except MMIO addresses)
>  
>    @retval RETURN_SUCCESS              The attributes were cleared for the
>                                        memory region.
> @@ -41,15 +39,13 @@ EFIAPI
>  MemEncryptSevClearPageEncMask (
>    IN PHYSICAL_ADDRESS         Cr3BaseAddress,
>    IN PHYSICAL_ADDRESS         BaseAddress,
> -  IN UINTN                    NumPages,
> -  IN BOOLEAN                  Flush
> +  IN UINTN                    NumPages
>    )
>  {
>    return InternalMemEncryptSevSetMemoryDecrypted (
>             Cr3BaseAddress,
>             BaseAddress,
> -           EFI_PAGES_TO_SIZE (NumPages),
> -           Flush
> +           EFI_PAGES_TO_SIZE (NumPages)
>             );
>  }
>  
> @@ -63,8 +59,6 @@ MemEncryptSevClearPageEncMask (
>                                        address of a memory region.
>    @param[in]  NumPages                The number of pages from start memory
>                                        region.
> -  @param[in]  Flush                   Flush the caches before setting the bit
> -                                      (mostly TRUE except MMIO addresses)
>  
>    @retval RETURN_SUCCESS              The attributes were set for the memory
>                                        region.
> @@ -77,15 +71,13 @@ EFIAPI
>  MemEncryptSevSetPageEncMask (
>    IN PHYSICAL_ADDRESS         Cr3BaseAddress,
>    IN PHYSICAL_ADDRESS         BaseAddress,
> -  IN UINTN                    NumPages,
> -  IN BOOLEAN                  Flush
> +  IN UINTN                    NumPages
>    )
>  {
>    return InternalMemEncryptSevSetMemoryEncrypted (
>             Cr3BaseAddress,
>             BaseAddress,
> -           EFI_PAGES_TO_SIZE (NumPages),
> -           Flush
> +           EFI_PAGES_TO_SIZE (NumPages)
>             );
>  }
>  
> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
> index 3bcc92f2e9..707db5a74a 100644
> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
> @@ -830,8 +830,6 @@ Done:
>    @param[in]  PhysicalAddress         The physical address that is the start
>                                        address of a memory region.
>    @param[in]  Length                  The length of memory region
> -  @param[in]  Flush                   Flush the caches before applying the
> -                                      encryption mask
>  
>    @retval RETURN_SUCCESS              The attributes were cleared for the
>                                        memory region.
> @@ -844,8 +842,7 @@ EFIAPI
>  InternalMemEncryptSevSetMemoryDecrypted (
>    IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
>    IN  PHYSICAL_ADDRESS        PhysicalAddress,
> -  IN  UINTN                   Length,
> -  IN  BOOLEAN                 Flush
> +  IN  UINTN                   Length
>    )
>  {
>  
> @@ -854,7 +851,7 @@ InternalMemEncryptSevSetMemoryDecrypted (
>             PhysicalAddress,
>             Length,
>             ClearCBit,
> -           Flush,
> +           TRUE,
>             FALSE
>             );
>  }
> @@ -868,8 +865,6 @@ InternalMemEncryptSevSetMemoryDecrypted (
>    @param[in]  PhysicalAddress         The physical address that is the start
>                                        address of a memory region.
>    @param[in]  Length                  The length of memory region
> -  @param[in]  Flush                   Flush the caches before applying the
> -                                      encryption mask
>  
>    @retval RETURN_SUCCESS              The attributes were set for the memory
>                                        region.
> @@ -882,8 +877,7 @@ EFIAPI
>  InternalMemEncryptSevSetMemoryEncrypted (
>    IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
>    IN  PHYSICAL_ADDRESS        PhysicalAddress,
> -  IN  UINTN                   Length,
> -  IN  BOOLEAN                 Flush
> +  IN  UINTN                   Length
>    )
>  {
>    return SetMemoryEncDec (
> @@ -891,7 +885,7 @@ InternalMemEncryptSevSetMemoryEncrypted (
>             PhysicalAddress,
>             Length,
>             SetCBit,
> -           Flush,
> +           TRUE,
>             FALSE
>             );
>  }
> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c
> index bca5e3febb..24d19d3ca1 100644
> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c
> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c
> @@ -42,8 +42,6 @@ InternalGetMemEncryptionAddressMask (
>    @param[in]  PhysicalAddress         The physical address that is the start
>                                        address of a memory region.
>    @param[in]  Length                  The length of memory region
> -  @param[in]  Flush                   Flush the caches before applying the
> -                                      encryption mask
>  
>    @retval RETURN_SUCCESS              The attributes were cleared for the
>                                        memory region.
> @@ -56,8 +54,7 @@ EFIAPI
>  InternalMemEncryptSevSetMemoryDecrypted (
>    IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
>    IN  PHYSICAL_ADDRESS        PhysicalAddress,
> -  IN  UINTN                   Length,
> -  IN  BOOLEAN                 Flush
> +  IN  UINTN                   Length
>    )
>  {
>    //
> @@ -89,8 +86,7 @@ EFIAPI
>  InternalMemEncryptSevSetMemoryEncrypted (
>    IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
>    IN  PHYSICAL_ADDRESS        PhysicalAddress,
> -  IN  UINTN                   Length,
> -  IN  BOOLEAN                 Flush
> +  IN  UINTN                   Length
>    )
>  {
>    //
> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
> index 99ee7ea0e8..832ff10a33 100644
> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
> @@ -58,8 +58,6 @@ InternalGetMemEncryptionAddressMask (
>    @param[in]  PhysicalAddress         The physical address that is the start
>                                        address of a memory region.
>    @param[in]  Length                  The length of memory region
> -  @param[in]  Flush                   Flush the caches before applying the
> -                                      encryption mask
>  
>    @retval RETURN_SUCCESS              The attributes were cleared for the
>                                        memory region.
> @@ -72,8 +70,7 @@ EFIAPI
>  InternalMemEncryptSevSetMemoryDecrypted (
>    IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
>    IN  PHYSICAL_ADDRESS        PhysicalAddress,
> -  IN  UINTN                   Length,
> -  IN  BOOLEAN                 Flush
> +  IN  UINTN                   Length
>    );
>  
>  /**
> @@ -85,8 +82,6 @@ InternalMemEncryptSevSetMemoryDecrypted (
>    @param[in]  PhysicalAddress         The physical address that is the start
>                                        address of a memory region.
>    @param[in]  Length                  The length of memory region
> -  @param[in]  Flush                   Flush the caches before applying the
> -                                      encryption mask
>  
>    @retval RETURN_SUCCESS              The attributes were set for the memory
>                                        region.
> @@ -99,8 +94,7 @@ EFIAPI
>  InternalMemEncryptSevSetMemoryEncrypted (
>    IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
>    IN  PHYSICAL_ADDRESS        PhysicalAddress,
> -  IN  UINTN                   Length,
> -  IN  BOOLEAN                 Flush
> +  IN  UINTN                   Length
>    );
>  
>  /**
> diff --git a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
> index fdf2380974..c7cc5b0389 100644
> --- a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
> +++ b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
> @@ -283,8 +283,7 @@ SmmCpuFeaturesSmmRelocationComplete (
>    Status = MemEncryptSevSetPageEncMask (
>               0,             // Cr3BaseAddress -- use current CR3
>               MapPagesBase,  // BaseAddress
> -             MapPagesCount, // NumPages
> -             TRUE           // Flush
> +             MapPagesCount  // NumPages
>               );
>    if (EFI_ERROR (Status)) {
>      DEBUG ((DEBUG_ERROR, "%a: MemEncryptSevSetPageEncMask(): %r\n",
> diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
> index dddffdebda..a8bf610022 100644
> --- a/OvmfPkg/PlatformPei/AmdSev.c
> +++ b/OvmfPkg/PlatformPei/AmdSev.c
> @@ -72,8 +72,7 @@ AmdSevEsInitialize (
>      DecryptStatus = MemEncryptSevClearPageEncMask (
>        0,
>        GhcbBasePa + EFI_PAGES_TO_SIZE (PageCount),
> -      1,
> -      TRUE
> +      1
>        );
>      ASSERT_RETURN_ERROR (DecryptStatus);
>    }
> 


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 09/28] OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase
  2021-04-30 11:51 ` [PATCH RFC v2 09/28] OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase Brijesh Singh
@ 2021-05-06 14:08   ` Laszlo Ersek
  2021-05-06 14:12     ` Laszlo Ersek
  2021-05-07 13:29     ` Brijesh Singh
  0 siblings, 2 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-06 14:08 UTC (permalink / raw)
  To: brijesh.singh, Tom Lendacky
  Cc: devel, James Bottomley, Min Xu, Jiewen Yao, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 04/30/21 13:51, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
>
> Commit 85b8eac59b8c5bd9c7eb9afdb64357ce1aa2e803 added support to ensure
> that MMIO is only performed against the un-encrypted memory. If MMIO
> is performed against encrypted memory, a #GP is raised.
>
> The VmgExitLib library depends on ApicTimerLib to get the APIC base
> address so that it can exclude the APIC range from the un-encrypted
> check. The OvmfPkg provides ApicTimerLib for the DXE phase. The
> constructor AcpiTimerLibConstructor() used in the ApicTimerLib uses
> the PciRead to get the PMBASE register. The PciRead() will cause an
> MMIO access.
>
> The AmdSevDxe driver clears the memory encryption attribute from the
> MMIO ranges. However, if VmgExitLib is linked to AmdSevDxe driver then the
> AcpiTimerLibConstructor() will be called before AmdSevDxe driver can
> clear the encryption attributes for the MMIO regions.
>
> Exclude the PMBASE register from the encrypted check so that we
> can link VmgExitLib to the MemEncryptSevLib; which gets linked to
> AmdSevDxe driver.

The above explanation is inexact. There are several typos ("APIC" is
incorrect, "ACPI" would be correct, for the TimerLib instance in
question), but that's really just a side observation.

The precise explanation is the following library instance dependency
chain:

  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
  -----> MemEncryptSevLib                                               class
  -----> "OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf" instance
  -[*]-> VmgExitLib                                                     class
  -----> "OvmfPkg/Library/VmgExitLib/VmgExitLib.inf"                    instance
  -----> LocalApicLib                                                   class
  -----> "UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf" instance
  -----> TimerLib                                                       class
  -----> "OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf"             instance
  -----> PciLib                                                         class
  -----> "OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf"    instance
  -----> PciExpressLib                                                  class
  -----> "MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf"       instance

The link (or dependency) marked with [*] is introduced in patch #26
("OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table").
That's the change that triggers the symptom. (In combination with you
testing on Q35, because on i440fx, the DxePciLibI440FxQ35 lib instance
accesses PCI config space via the 0xCF8, 0xCFC IO Ports, and those are
unaffected by SEV-ES.)

The symptom is somewhat "unjustified", because at the end of the series,
the AmdSevDxe driver makes no calls to actual TimerLib APIs (I checked
-- I disassembled the "AmdSevDxe.debug" file with "objdump -S", and
there is no call to any API declared in the "TimerLib.h" class header).
However, the ECAM (MMCONFIG) access is still triggered, because the
AcpiTimerLibConstructor() function, in
"OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c", is the constructor for
the "OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf" instance, and
AcpiTimerLibConstructor() calls PciRead32().

If you check the "OvmfPkg/OvmfPkgX64.dsc" file, you'll find that the
PciLib class is resolved to
"MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf" by default, and to
"OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf" for the
following module types:

- DXE_DRIVER,
- DXE_RUNTIME_DRIVER,
- SMM_CORE,
- DXE_SMM_DRIVER,
- UEFI_DRIVER,
- UEFI_APPLICATION.

The consequence is that modules strictly after the DXE_CORE get
dynamically enabled extended config space access (ECAM) on Q35 via the
PciLib class, whereas all modules strictly before the DXE_CORE, and the
DXE_CORE itself, are restricted to normal config space (IO Ports 0xCF8 /
0xCFC) via the PciLib class.

AmdSevDxe is a DXE_DRIVER, so it used to get DxePciLibI440FxQ35 as well.

The solution should be simple. In the AmdSevDxe driver specifically, we
need no access to extended PCI config space. Accessing normal PCI config
space, via IO Ports 0xCF8 / 0xCFC, should suffice. That can be achieved
with the following module-scope override:

> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
> index 8d9a0a077601..45a02b236633 100644
> --- a/OvmfPkg/OvmfPkgX64.dsc
> +++ b/OvmfPkg/OvmfPkgX64.dsc
> @@ -966,7 +966,10 @@ [Components]
>  !endif
>
>    OvmfPkg/PlatformDxe/Platform.inf
> -  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
> +  OvmfPkg/AmdSevDxe/AmdSevDxe.inf {
> +    <LibraryClasses>
> +      PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
> +  }
>    OvmfPkg/IoMmuDxe/IoMmuDxe.inf
>    OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>

(

For consistency, all DSC files that include
"OvmfPkg/AmdSevDxe/AmdSevDxe.inf" should be modified similarly:

- OvmfPkg/AmdSev/AmdSevX64.dsc
- OvmfPkg/Bhyve/BhyveX64.dsc
- OvmfPkg/OvmfPkgIa32X64.dsc
- OvmfPkg/OvmfPkgX64.dsc
- OvmfPkg/OvmfXen.dsc

)

Therefore, please try dropping this patch, and modifying patch#26
instead -- the above module-scope override (for 5 DSC files) should be
squashed into patch#26, *and* the explanation I provided above should be
included in the commit message of patch#26.

... Correction: you have an independent bug in the series that affects
my above analysis. Namely, you *seem* to add the VmgExitLib dependency
to the "OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf"
library instance, in patch#26. That's where you modify the INF file. But
that's wrong: in patch#21 ("OvmfPkg/MemEncryptSevLib: Add support to
validate system RAM"), you add a VmgInit() call to the same library
instance, via the new file
"OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c".

The bug in that patch is clear from the fact that you introduce an
#include <Library/VmgExitLib.h> directive, but that's not mirrored by an
appropriate [LibraryClasses] change in the "DxeMemEncryptSevLib.inf"
file. (The other two lib instance INF files, "SecMemEncryptSevLib.inf"
and "PeiMemEncryptSevLib.inf" *are* modified as needed.)

So you even need to move some stuff from patch#26 to patch#21, and
*then* squash the above module-scope override (and explanation) into
patch#21.

A significant amount of work is needed on this series. I'll stop
reviewing RFC v2 here, because I don't want to look at the remaining
patches deeply as long as code movements etc are going to affect them.
Please post the next version -- assuming no other reviewer would like to
finish reviewing this version first!

Thanks
Laszlo

>
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf  |  4 ++
>  OvmfPkg/Library/VmgExitLib/VmgExitLib.inf     |  7 +++
>  OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 45 ++++++++++++++++++++
>  3 files changed, 56 insertions(+)
>
> diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
> index e6f6ea7972..22435a0590 100644
> --- a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
> +++ b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
> @@ -27,6 +27,7 @@
>    SecVmgExitVcHandler.c
>
>  [Packages]
> +  MdeModulePkg/MdeModulePkg.dec
>    MdePkg/MdePkg.dec
>    OvmfPkg/OvmfPkg.dec
>    UefiCpuPkg/UefiCpuPkg.dec
> @@ -42,4 +43,7 @@
>  [FixedPcd]
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
>
> +[Pcd]
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
> diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
> index c66c68726c..d3175c260e 100644
> --- a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
> @@ -27,6 +27,7 @@
>    PeiDxeVmgExitVcHandler.c
>
>  [Packages]
> +  MdeModulePkg/MdeModulePkg.dec
>    MdePkg/MdePkg.dec
>    OvmfPkg/OvmfPkg.dec
>    UefiCpuPkg/UefiCpuPkg.dec
> @@ -37,4 +38,10 @@
>    DebugLib
>    LocalApicLib
>    MemEncryptSevLib
> +  PcdLib
>
> +[FixedPcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
> +
> +[Pcd]
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
> diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
> index 24259060fd..01ac5d8c19 100644
> --- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
> @@ -14,7 +14,10 @@
>  #include <Library/VmgExitLib.h>
>  #include <Register/Amd/Msr.h>
>  #include <Register/Intel/Cpuid.h>
> +#include <IndustryStandard/Q35MchIch9.h>
> +#include <IndustryStandard/I440FxPiix4.h>
>  #include <IndustryStandard/InstructionParsing.h>
> +#include <Library/PcdLib.h>
>
>  #include "VmgExitVcHandler.h"
>
> @@ -596,6 +599,40 @@ UnsupportedExit (
>    return Status;
>  }
>
> +STATIC
> +BOOLEAN
> +IsPmbaBaseAddress (
> +  IN  UINTN     Address
> +  )
> +{
> +  UINT16 HostBridgeDevId;
> +  UINTN Pmba;
> +
> +  //
> +  // Query Host Bridge DID to determine platform type
> +  //
> +  HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
> +  switch (HostBridgeDevId) {
> +    case INTEL_82441_DEVICE_ID:
> +      Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
> +      break;
> +    case INTEL_Q35_MCH_DEVICE_ID:
> +      Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
> +      //
> +      // Add the MMCONFIG base address to get the Pmba base access address
> +      //
> +      Pmba += FixedPcdGet64 (PcdPciExpressBaseAddress);
> +      break;
> +    default:
> +      return FALSE;
> +  }
> +
> +  // Round up the offset to page size
> +  Pmba = Pmba & ~(SIZE_4KB - 1);
> +
> +  return (Address == Pmba);
> +}
> +
>  /**
>    Validate that the MMIO memory access is not to encrypted memory.
>
> @@ -640,6 +677,14 @@ ValidateMmioMemory (
>      return 0;
>    }
>
> +  //
> +  // Allow PMBASE accesses (which will have the encryption bit set before
> +  // AmdSevDxe runs in the DXE phase)
> +  //
> +  if (IsPmbaBaseAddress (Address)) {
> +    return 0;
> +  }
> +
>    //
>    // Any state other than unencrypted is an error, issue a #GP.
>    //
>


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 09/28] OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase
  2021-05-06 14:08   ` [edk2-devel] " Laszlo Ersek
@ 2021-05-06 14:12     ` Laszlo Ersek
  2021-05-07 13:29     ` Brijesh Singh
  1 sibling, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-06 14:12 UTC (permalink / raw)
  To: brijesh.singh, Tom Lendacky
  Cc: devel, James Bottomley, Min Xu, Jiewen Yao, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/06/21 16:08, Laszlo Ersek wrote:
> On 04/30/21 13:51, Brijesh Singh wrote:
>> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
>>
>> Commit 85b8eac59b8c5bd9c7eb9afdb64357ce1aa2e803 added support to ensure
>> that MMIO is only performed against the un-encrypted memory. If MMIO
>> is performed against encrypted memory, a #GP is raised.
>>
>> The VmgExitLib library depends on ApicTimerLib to get the APIC base
>> address so that it can exclude the APIC range from the un-encrypted
>> check. The OvmfPkg provides ApicTimerLib for the DXE phase. The
>> constructor AcpiTimerLibConstructor() used in the ApicTimerLib uses
>> the PciRead to get the PMBASE register. The PciRead() will cause an
>> MMIO access.
>>
>> The AmdSevDxe driver clears the memory encryption attribute from the
>> MMIO ranges. However, if VmgExitLib is linked to AmdSevDxe driver then the
>> AcpiTimerLibConstructor() will be called before AmdSevDxe driver can
>> clear the encryption attributes for the MMIO regions.
>>
>> Exclude the PMBASE register from the encrypted check so that we
>> can link VmgExitLib to the MemEncryptSevLib; which gets linked to
>> AmdSevDxe driver.
> 
> The above explanation is inexact. There are several typos ("APIC" is
> incorrect, "ACPI" would be correct, for the TimerLib instance in
> question), but that's really just a side observation.
> 
> The precise explanation is the following library instance dependency
> chain:
> 
>   OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>   -----> MemEncryptSevLib                                               class
>   -----> "OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf" instance
>   -[*]-> VmgExitLib                                                     class
>   -----> "OvmfPkg/Library/VmgExitLib/VmgExitLib.inf"                    instance
>   -----> LocalApicLib                                                   class
>   -----> "UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf" instance
>   -----> TimerLib                                                       class
>   -----> "OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf"             instance
>   -----> PciLib                                                         class
>   -----> "OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf"    instance
>   -----> PciExpressLib                                                  class
>   -----> "MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf"       instance
> 
> The link (or dependency) marked with [*] is introduced in patch #26
> ("OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table").
> That's the change that triggers the symptom. (In combination with you
> testing on Q35, because on i440fx, the DxePciLibI440FxQ35 lib instance
> accesses PCI config space via the 0xCF8, 0xCFC IO Ports, and those are
> unaffected by SEV-ES.)
> 
> The symptom is somewhat "unjustified", because at the end of the series,
> the AmdSevDxe driver makes no calls to actual TimerLib APIs (I checked
> -- I disassembled the "AmdSevDxe.debug" file with "objdump -S", and
> there is no call to any API declared in the "TimerLib.h" class header).
> However, the ECAM (MMCONFIG) access is still triggered, because the
> AcpiTimerLibConstructor() function, in
> "OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c", is the constructor for
> the "OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf" instance, and
> AcpiTimerLibConstructor() calls PciRead32().
> 
> If you check the "OvmfPkg/OvmfPkgX64.dsc" file, you'll find that the
> PciLib class is resolved to
> "MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf" by default, and to
> "OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf" for the
> following module types:
> 
> - DXE_DRIVER,
> - DXE_RUNTIME_DRIVER,
> - SMM_CORE,
> - DXE_SMM_DRIVER,
> - UEFI_DRIVER,
> - UEFI_APPLICATION.
> 
> The consequence is that modules strictly after the DXE_CORE get
> dynamically enabled extended config space access (ECAM) on Q35 via the
> PciLib class, whereas all modules strictly before the DXE_CORE, and the
> DXE_CORE itself, are restricted to normal config space (IO Ports 0xCF8 /
> 0xCFC) via the PciLib class.
> 
> AmdSevDxe is a DXE_DRIVER, so it used to get DxePciLibI440FxQ35 as well.
> 
> The solution should be simple. In the AmdSevDxe driver specifically, we
> need no access to extended PCI config space. Accessing normal PCI config
> space, via IO Ports 0xCF8 / 0xCFC, should suffice. That can be achieved
> with the following module-scope override:
> 
>> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
>> index 8d9a0a077601..45a02b236633 100644
>> --- a/OvmfPkg/OvmfPkgX64.dsc
>> +++ b/OvmfPkg/OvmfPkgX64.dsc
>> @@ -966,7 +966,10 @@ [Components]
>>  !endif
>>
>>    OvmfPkg/PlatformDxe/Platform.inf
>> -  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>> +  OvmfPkg/AmdSevDxe/AmdSevDxe.inf {
>> +    <LibraryClasses>
>> +      PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
>> +  }
>>    OvmfPkg/IoMmuDxe/IoMmuDxe.inf
>>    OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>>
> 
> (
> 
> For consistency, all DSC files that include
> "OvmfPkg/AmdSevDxe/AmdSevDxe.inf" should be modified similarly:
> 
> - OvmfPkg/AmdSev/AmdSevX64.dsc
> - OvmfPkg/Bhyve/BhyveX64.dsc
> - OvmfPkg/OvmfPkgIa32X64.dsc
> - OvmfPkg/OvmfPkgX64.dsc
> - OvmfPkg/OvmfXen.dsc
> 
> )
> 
> Therefore, please try dropping this patch, and modifying patch#26
> instead -- the above module-scope override (for 5 DSC files) should be
> squashed into patch#26, *and* the explanation I provided above should be
> included in the commit message of patch#26.
> 
> ... Correction: you have an independent bug in the series that affects
> my above analysis. Namely, you *seem* to add the VmgExitLib dependency
> to the "OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf"
> library instance, in patch#26. That's where you modify the INF file. But
> that's wrong: in patch#21 ("OvmfPkg/MemEncryptSevLib: Add support to
> validate system RAM"), you add a VmgInit() call to the same library
> instance, via the new file
> "OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c".
> 
> The bug in that patch is clear from the fact that you introduce an
> #include <Library/VmgExitLib.h> directive, but that's not mirrored by an
> appropriate [LibraryClasses] change in the "DxeMemEncryptSevLib.inf"
> file. (The other two lib instance INF files, "SecMemEncryptSevLib.inf"
> and "PeiMemEncryptSevLib.inf" *are* modified as needed.)
> 
> So you even need to move some stuff from patch#26 to patch#21, and
> *then* squash the above module-scope override (and explanation) into
> patch#21.

Actually, I've changed my mind, regarding the squashing.

Patch#21 is already large, and the module-scope PciLib override requires
a fair bit of justification (commit message, 5 DSC files modified etc).
Therefore, please do implement the module-scope PciLib override in its
own dedicated patch; *replacing* this one.

The new patch with the module-scoped PciLib override should be inserted
in the series just before the patch that establishes the dependency
marked with [*], that is, just before patch#21.

Thanks
Laszlo

> 
> A significant amount of work is needed on this series. I'll stop
> reviewing RFC v2 here, because I don't want to look at the remaining
> patches deeply as long as code movements etc are going to affect them.
> Please post the next version -- assuming no other reviewer would like to
> finish reviewing this version first!
> 
> Thanks
> Laszlo
> 
>>
>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf  |  4 ++
>>  OvmfPkg/Library/VmgExitLib/VmgExitLib.inf     |  7 +++
>>  OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 45 ++++++++++++++++++++
>>  3 files changed, 56 insertions(+)
>>
>> diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>> index e6f6ea7972..22435a0590 100644
>> --- a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>> +++ b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>> @@ -27,6 +27,7 @@
>>    SecVmgExitVcHandler.c
>>
>>  [Packages]
>> +  MdeModulePkg/MdeModulePkg.dec
>>    MdePkg/MdePkg.dec
>>    OvmfPkg/OvmfPkg.dec
>>    UefiCpuPkg/UefiCpuPkg.dec
>> @@ -42,4 +43,7 @@
>>  [FixedPcd]
>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
>> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
>>
>> +[Pcd]
>> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
>> diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
>> index c66c68726c..d3175c260e 100644
>> --- a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
>> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
>> @@ -27,6 +27,7 @@
>>    PeiDxeVmgExitVcHandler.c
>>
>>  [Packages]
>> +  MdeModulePkg/MdeModulePkg.dec
>>    MdePkg/MdePkg.dec
>>    OvmfPkg/OvmfPkg.dec
>>    UefiCpuPkg/UefiCpuPkg.dec
>> @@ -37,4 +38,10 @@
>>    DebugLib
>>    LocalApicLib
>>    MemEncryptSevLib
>> +  PcdLib
>>
>> +[FixedPcd]
>> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
>> +
>> +[Pcd]
>> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
>> diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
>> index 24259060fd..01ac5d8c19 100644
>> --- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
>> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
>> @@ -14,7 +14,10 @@
>>  #include <Library/VmgExitLib.h>
>>  #include <Register/Amd/Msr.h>
>>  #include <Register/Intel/Cpuid.h>
>> +#include <IndustryStandard/Q35MchIch9.h>
>> +#include <IndustryStandard/I440FxPiix4.h>
>>  #include <IndustryStandard/InstructionParsing.h>
>> +#include <Library/PcdLib.h>
>>
>>  #include "VmgExitVcHandler.h"
>>
>> @@ -596,6 +599,40 @@ UnsupportedExit (
>>    return Status;
>>  }
>>
>> +STATIC
>> +BOOLEAN
>> +IsPmbaBaseAddress (
>> +  IN  UINTN     Address
>> +  )
>> +{
>> +  UINT16 HostBridgeDevId;
>> +  UINTN Pmba;
>> +
>> +  //
>> +  // Query Host Bridge DID to determine platform type
>> +  //
>> +  HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
>> +  switch (HostBridgeDevId) {
>> +    case INTEL_82441_DEVICE_ID:
>> +      Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
>> +      break;
>> +    case INTEL_Q35_MCH_DEVICE_ID:
>> +      Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
>> +      //
>> +      // Add the MMCONFIG base address to get the Pmba base access address
>> +      //
>> +      Pmba += FixedPcdGet64 (PcdPciExpressBaseAddress);
>> +      break;
>> +    default:
>> +      return FALSE;
>> +  }
>> +
>> +  // Round up the offset to page size
>> +  Pmba = Pmba & ~(SIZE_4KB - 1);
>> +
>> +  return (Address == Pmba);
>> +}
>> +
>>  /**
>>    Validate that the MMIO memory access is not to encrypted memory.
>>
>> @@ -640,6 +677,14 @@ ValidateMmioMemory (
>>      return 0;
>>    }
>>
>> +  //
>> +  // Allow PMBASE accesses (which will have the encryption bit set before
>> +  // AmdSevDxe runs in the DXE phase)
>> +  //
>> +  if (IsPmbaBaseAddress (Address)) {
>> +    return 0;
>> +  }
>> +
>>    //
>>    // Any state other than unencrypted is an error, issue a #GP.
>>    //
>>
> 


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD
  2021-05-06 10:57         ` Dov Murik
@ 2021-05-06 15:06           ` Laszlo Ersek
  2021-05-06 16:12           ` James Bottomley
  1 sibling, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-06 15:06 UTC (permalink / raw)
  To: Dov Murik, devel, brijesh.singh
  Cc: James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas, tobin@ibm.com

Hi Dov,

On 05/06/21 12:57, Dov Murik wrote:
> 
> 
> On 05/05/2021 22:33, Laszlo Ersek wrote:
>> On 05/05/21 15:11, Brijesh Singh wrote:
>>>
>>> On 5/5/21 1:42 AM, Dov Murik wrote:
>>>> [+cc: Tobin]
>>>>
>>>> Hi Brijesh,
>>>>
>>>> On 30/04/2021 14:51, Brijesh Singh wrote:
>>>>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C93168c94eb6d44ed08e608d90f910426%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637557937779907471%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=nLpmk3G%2BmXcZrzXxCmO3M9EDPiLRnP1IUmPqRQNbBuU%3D&amp;reserved=0
>>>>>
>>>>> When AMD SEV is enabled in the guest VM, a hypervisor need to insert a
>>>>> secrets page.
>>>>>
>>>>> When SEV-SNP is enabled, the secrets page contains the VM platform
>>>>> communication keys. The guest BIOS and OS can use this key to communicate
>>>>> with the SEV firmware to get attesation report. See the SEV-SNP firmware
>>>>> spec for more details for the content of the secrets page.
>>>>>
>>>>> When SEV and SEV-ES is enabled, the secrets page contains the information
>>>>> provided by the guest owner after the attestation. See the SEV
>>>>> LAUNCH_SECRET command for more details.
>>>>>
>>>>> Cc: James Bottomley <jejb@linux.ibm.com>
>>>>> Cc: Min Xu <min.m.xu@intel.com>
>>>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>>>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>>>>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>>>>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>>>>> Cc: Laszlo Ersek <lersek@redhat.com>
>>>>> Cc: Erdem Aktas <erdemaktas@google.com>
>>>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>>>> ---
>>>>>  OvmfPkg/AmdSev/SecretPei/SecretPei.c   | 16 +++++++++++++++-
>>>>>  OvmfPkg/AmdSev/SecretPei/SecretPei.inf |  1 +
>>>>>  OvmfPkg/OvmfPkgX64.dsc                 |  2 ++
>>>>>  OvmfPkg/OvmfPkgX64.fdf                 |  5 +++++
>>>>>  4 files changed, 23 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.c b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>>>>> index ad491515dd..92836c562c 100644
>>>>> --- a/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>>>>> +++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.c
>>>>> @@ -7,6 +7,7 @@
>>>>>  #include <PiPei.h>
>>>>>  #include <Library/HobLib.h>
>>>>>  #include <Library/PcdLib.h>
>>>>> +#include <Library/MemEncryptSevLib.h>
>>>>>
>>>>>  EFI_STATUS
>>>>>  EFIAPI
>>>>> @@ -15,10 +16,23 @@ InitializeSecretPei (
>>>>>    IN CONST EFI_PEI_SERVICES     **PeiServices
>>>>>    )
>>>>>  {
>>>>> +  UINTN   Type;
>>>>> +
>>>>> +  //
>>>>> +  // The secret page should be mapped encrypted by the guest OS and must not
>>>>> +  // be treated as a system RAM. Mark it as ACPI NVS so that guest OS maps it
>>>>> +  // encrypted.
>>>>> +  //
>>>>> +  if (MemEncryptSevSnpIsEnabled ()) {
>>>>> +    Type = EfiACPIMemoryNVS;
>>>>> +  } else {
>>>>> +    Type = EfiBootServicesData;
>>>>> +  }
>>>>> +
>>>> Would it make sense to always use EfiACPIMemoryNVS for the injected secret area, even for regular SEV (non-SNP)?
>>>
>>> Ideally yes. Maybe James had some reasons for choosing the
>>> EfiBootServicesData. If I had to guess, it was mainly because there no
>>> guest kernel support which consumes the SEV secrets page.
>>
>> git-blame fingers commit bff2811c6d99 ("OvmfPkg/AmdSev: assign and
>> reserve the Sev Secret area", 2020-12-14).
>>
>> Commit bff2811c6d99 makes it clear that the area in question lives in MEMFD.
>>
>> We're populating the area in the PEI phase. We don't want anything in
>> DXE to overwrite it.
>>
>> Once the bootloader (and/or perhaps the kernel's EFI stub) fetched the
>> secret from that particular location, there is no need to prevent later
>> parts of the OS (the actual kernel) from repurposing that area. That's
>> why EfiBootServicesData was used.
>>
> 
> The first use of the secret area was to hold the guest luks disk passphrase; this is used in the grub-inside-OVMF (AmdSev package), and there was no need to keep that page around for the guest kernel.
> 
> The reason I'm raising this whole point is that we're working now on guest-kernel support for reading secrets from that injected page (for plain SEV).  We considered either (a) modifying the secrets page memory type to reserved here, or (b) add code to the kernel EFI stub that would copy this page somewhere else for kernel's later use (which seems more work and not sure what's the advantage).
> 
> Option (b) seems harder and more fragile, and I'm not sure if there are any advantages (though I'm definitely not an expert in that area).
> 
> 
> 
> 
>>> Since the
>>> memory is not marked ACPI NVS, so it can be used as a system RAM after
>>> the ExitBootServices is called in the kernel.
>>
>> Yes.
>>
>> I don't think AcpiNVS would be a good fit. Linux saves and restores
>> AcpiNVS areas upon S3 suspend/resume. Regardless of whether S3 works, or
>> will work, in SEV* guests, if we don't want the guest kernel to touch
>> that area *at all*, Reserved is a better type.
> 
> Thanks for this clarification.
> 
>>
>> Please refer to "Table 7-6 Memory Type Usage after ExitBootServices()"
>> in the UEFI spec (v2.9).
>>
>>>
>>> I am fine with using ACPI NVS for both SEV and SEV-SNP. I was not able
>>> to build and run AmdSev package in my setup, can you submit a prepatch
>>> to change the memory type and verify that it works ?
>>
>> NB: I've not yet reached this patch in my own review of the series, so
>> I'm likely missing some context. I do have a thought -- under SEV-SNP,
>> the secrets page apparently needs different (stronger) protection from
>> the host as under plain SEV. I don't think that hiding the different
>> protection requirements behind a single common memory type is helpful.
>> Not to mention the wasted memory in the plain SEV case -- it's not a lot
>> of memory, mind you, but the principle matters.
>>
> 
> Like I said above, we have plans to have this small amount of memory available also to the guest OS; so maybe that shouldn't be the driving force in the decision here.

What you describe (= runtime guest OS access) seems to justify changing
the memory type of this allocation. However, that update doesn't look
tied to SEV-SNP -- it's basically a "change of use case" (change of
purpose) under plain SEV too. I think that deserves a separate
(stand-alone) patch; maybe even a separate TianoCore BZ ticket.

Thanks
Laszlo



> 
> -Dov
> 
>  
> 
>> So ATM I would like to keep this patch in the SEV-SNP series, and to
>> preserve the different memory types between SEV and SEV-SNP.
>>
>> Thanks
>> Laszlo
>>
>>
>>
>>
>>>
>>>>
>>>> -Dov
>>>>
>>>>
>>>>
>>>>>    BuildMemoryAllocationHob (
>>>>>      PcdGet32 (PcdSevLaunchSecretBase),
>>>>>      PcdGet32 (PcdSevLaunchSecretSize),
>>>>> -    EfiBootServicesData
>>>>> +    Type
>>>>>      );
>>>>>
>>>>>    return EFI_SUCCESS;
>>>>> diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>>> index 08be156c4b..9265f8adee 100644
>>>>> --- a/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>>> +++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>>> @@ -26,6 +26,7 @@
>>>>>    HobLib
>>>>>    PeimEntryPoint
>>>>>    PcdLib
>>>>> +  MemEncryptSevLib
>>>>>
>>>>>  [FixedPcd]
>>>>>    gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
>>>>> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
>>>>> index a7d747f6b4..593c0e69f6 100644
>>>>> --- a/OvmfPkg/OvmfPkgX64.dsc
>>>>> +++ b/OvmfPkg/OvmfPkgX64.dsc
>>>>> @@ -716,6 +716,7 @@
>>>>>    OvmfPkg/SmmAccess/SmmAccessPei.inf
>>>>>  !endif
>>>>>    UefiCpuPkg/CpuMpPei/CpuMpPei.inf
>>>>> +  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>>>
>>>>>  !if $(TPM_ENABLE) == TRUE
>>>>>    OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
>>>>> @@ -965,6 +966,7 @@
>>>>>    OvmfPkg/PlatformDxe/Platform.inf
>>>>>    OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>>>>>    OvmfPkg/IoMmuDxe/IoMmuDxe.inf
>>>>> +  OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>>>>>
>>>>>  !if $(SMM_REQUIRE) == TRUE
>>>>>    OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
>>>>> diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
>>>>> index d519f85328..b04175f77c 100644
>>>>> --- a/OvmfPkg/OvmfPkgX64.fdf
>>>>> +++ b/OvmfPkg/OvmfPkgX64.fdf
>>>>> @@ -88,6 +88,9 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.PcdSevE
>>>>>  0x00C000|0x001000
>>>>>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
>>>>>
>>>>> +0x00D000|0x001000
>>>>> +gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
>>>>> +
>>>>>  0x010000|0x010000
>>>>>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
>>>>>
>>>>> @@ -178,6 +181,7 @@ INF  OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
>>>>>  INF  SecurityPkg/Tcg/TcgPei/TcgPei.inf
>>>>>  INF  SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
>>>>>  !endif
>>>>> +INF  OvmfPkg/AmdSev/SecretPei/SecretPei.inf
>>>>>
>>>>>  ################################################################################
>>>>>
>>>>> @@ -313,6 +317,7 @@ INF  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
>>>>>  INF  ShellPkg/Application/Shell/Shell.inf
>>>>>
>>>>>  INF MdeModulePkg/Logo/LogoDxe.inf
>>>>> +INF OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>>>>>
>>>>>  #
>>>>>  # Network modules
>>>>>
>>>
>>>
>>> 
>>>
>>>
>>
> 


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD
  2021-05-05 19:33       ` Laszlo Ersek
  2021-05-06 10:57         ` Dov Murik
@ 2021-05-06 16:02         ` James Bottomley
  1 sibling, 0 replies; 81+ messages in thread
From: James Bottomley @ 2021-05-06 16:02 UTC (permalink / raw)
  To: Laszlo Ersek, devel, brijesh.singh, Dov Murik
  Cc: Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen, Ard Biesheuvel,
	Erdem Aktas, tobin@ibm.com

On Wed, 2021-05-05 at 21:33 +0200, Laszlo Ersek wrote:
> On 05/05/21 15:11, Brijesh Singh wrote:
> > On 5/5/21 1:42 AM, Dov Murik wrote:
[...]
> > > Would it make sense to always use EfiACPIMemoryNVS for the
> > > injected secret area, even for regular SEV (non-SNP)?
> > 
> > Ideally yes. Maybe James had some reasons for choosing the
> > EfiBootServicesData. If I had to guess, it was mainly because there
> > no guest kernel support which consumes the SEV secrets page.
> 
> git-blame fingers commit bff2811c6d99 ("OvmfPkg/AmdSev: assign and
> reserve the Sev Secret area", 2020-12-14).
> 
> Commit bff2811c6d99 makes it clear that the area in question lives in
> MEMFD.
> 
> We're populating the area in the PEI phase. We don't want anything in
> DXE to overwrite it.
> 
> Once the bootloader (and/or perhaps the kernel's EFI stub) fetched
> the secret from that particular location, there is no need to prevent
> later parts of the OS (the actual kernel) from repurposing that area.
> That's why EfiBootServicesData was used.

That's right: originally the design was not to have the boot secrets
survive boot because they should already be copied into their correct,
and presumably protected, locations by the time exit boot services
comes.  The grub code actually shreds the secret in the page once it
consumes it, so the area for a simple disk secret should be empty
anyway.

James



^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD
  2021-05-06 10:57         ` Dov Murik
  2021-05-06 15:06           ` Laszlo Ersek
@ 2021-05-06 16:12           ` James Bottomley
  1 sibling, 0 replies; 81+ messages in thread
From: James Bottomley @ 2021-05-06 16:12 UTC (permalink / raw)
  To: Dov Murik, Laszlo Ersek, devel, brijesh.singh
  Cc: Min Xu, Jiewen Yao, Tom Lendacky, Jordan Justen, Ard Biesheuvel,
	Erdem Aktas, tobin@ibm.com

On Thu, 2021-05-06 at 13:57 +0300, Dov Murik wrote:
> 
> On 05/05/2021 22:33, Laszlo Ersek wrote:
> > On 05/05/21 15:11, Brijesh Singh wrote:
> > > On 5/5/21 1:42 AM, Dov Murik wrote:
[...]
> > > > Would it make sense to always use EfiACPIMemoryNVS for the
> > > > injected secret area, even for regular SEV (non-SNP)?
> > > 
> > > Ideally yes. Maybe James had some reasons for choosing the
> > > EfiBootServicesData. If I had to guess, it was mainly because
> > > there no guest kernel support which consumes the SEV secrets
> > > page.
> > 
> > git-blame fingers commit bff2811c6d99 ("OvmfPkg/AmdSev: assign and
> > reserve the Sev Secret area", 2020-12-14).
> > 
> > Commit bff2811c6d99 makes it clear that the area in question lives
> > in MEMFD.
> > 
> > We're populating the area in the PEI phase. We don't want anything
> > in DXE to overwrite it.
> > 
> > Once the bootloader (and/or perhaps the kernel's EFI stub) fetched
> > the secret from that particular location, there is no need to
> > prevent later parts of the OS (the actual kernel) from repurposing
> > that area. That's why EfiBootServicesData was used.
> > 
> 
> The first use of the secret area was to hold the guest luks disk
> passphrase; this is used in the grub-inside-OVMF (AmdSev package),
> and there was no need to keep that page around for the guest kernel.
> 
> The reason I'm raising this whole point is that we're working now on
> guest-kernel support for reading secrets from that injected page (for
> plain SEV).  We considered either (a) modifying the secrets page
> memory type to reserved here, or (b) add code to the kernel EFI stub
> that would copy this page somewhere else for kernel's later use
> (which seems more work and not sure what's the advantage).

It mirrors the TPM boot log behaviour: the log is stored in boot time
only memory, so the kernel EFI stub has to copy it out.  The reason the
TPM boot log behaves this way is that if the kernel didn't want to
collect it, it still gets freed.  I imagine a similar rationale exists
for the boot secrets: if the kernel isn't interested in them for some
reason, we don't want them to persist.

> Option (b) seems harder and more fragile, and I'm not sure if there
> are any advantages (though I'm definitely not an expert in that
> area).

I think forcing the kernel to consume the secret before exit boot
services is still a good idea because 

   1. If the kernel can't consume the secret it gets freed
   2. Not all secrets are consumed by the kernel, so it can pick the ones
      it wants out and discard the rest
   3. If the kernel is using a secret protection mechanism, that may not
      work for the memfd page, so relocation of the secret might be a more
      secure mechanism.

James



^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 06/28] OvmfPkg/BaseMemEncryptSevLib: Introduce MemEncryptSevClearMmioPageEncMask()
  2021-05-06 10:39   ` [edk2-devel] " Laszlo Ersek
@ 2021-05-06 19:18     ` Brijesh Singh
  0 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-05-06 19:18 UTC (permalink / raw)
  To: devel, lersek
  Cc: brijesh.singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/6/21 5:39 AM, Laszlo Ersek via groups.io wrote:
> On 04/30/21 13:51, Brijesh Singh wrote:
>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C2719bcebf85d4e5228e508d9107b449d%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637558943897655383%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=YrgkAA3Kp6v2eJuovVho1I3kR%2FXAA5D%2BE2vaUKyFO68%3D&amp;reserved=0
>>
>> The MemEncryptSevClearMmioPageEncMask() helper can be used for clearing
>> the memory encryption mask for the Mmio region from the current page
>> table context.
> The commit message, and five comments in the patch, say "current page
> table context". However, Cr3BaseAddress is taken explicitly.
>
> I realize the files being modified in this patch already make similarly
> incorrect statements, but I'd like if we avoided adding more.
>
> (1) Please just drop "current page table context" from the mentioned six
> locations. (Explaining that Cr3BaseAddress=0 means "current CR3" is of
> course valid.)
>
>

Thanks Laszlo, I will go through the feedback on this patch and address
them in next rev.

-Brijesh

>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  OvmfPkg/Include/Library/MemEncryptSevLib.h                     | 25 +++++++++++
>>  OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c   | 31 ++++++++++++++
>>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c    | 33 +++++++++++++++
>>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 44 ++++++++++++++++++--
>>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h       | 23 ++++++++++
>>  5 files changed, 153 insertions(+), 3 deletions(-)
>>
>> diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
>> index 99f15a7d12..c19f92afc6 100644
>> --- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
>> +++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
>> @@ -203,4 +203,29 @@ MemEncryptSevGetAddressRangeState (
>>    IN UINTN                    Length
>>    );
>>  
>> +/**
>> +  This function clears memory encryption bit for the mmio region specified by
>> +  BaseAddress and NumPages from the current page table context.
>> +
>> +  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
>> +                                      current CR3)
>> +  @param[in]  BaseAddress             The physical address that is the start
>> +                                      address of a mmio region.
>> +  @param[in]  NumPages                The number of pages from start memory
>> +                                      region.
>> +
>> +  @retval RETURN_SUCCESS              The attributes were cleared for the
>> +                                      memory region.
>> +  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
>> +  @retval RETURN_UNSUPPORTED          Clearing the memory encryption attribute
>> +                                      is not supported
>> +**/
>> +RETURN_STATUS
>> +EFIAPI
>> +MemEncryptSevClearMmioPageEncMask (
>> +  IN PHYSICAL_ADDRESS         Cr3BaseAddress,
>> +  IN PHYSICAL_ADDRESS         BaseAddress,
>> +  IN UINTN                    NumPages
>> +  );
>> +
>>  #endif // _MEM_ENCRYPT_SEV_LIB_H_
>> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
>> index 12a5bf495b..4e8a997d42 100644
>> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
>> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
>> @@ -111,3 +111,34 @@ MemEncryptSevGetAddressRangeState (
>>    //
>>    return MemEncryptSevAddressRangeEncrypted;
>>  }
>> +
>> +/**
>> +  This function clears memory encryption bit for the mmio region specified by
>> +  BaseAddress and NumPages from the current page table context.
>> +
>> +  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
>> +                                      current CR3)
>> +  @param[in]  BaseAddress             The physical address that is the start
>> +                                      address of a mmio region.
>> +  @param[in]  NumPages                The number of pages from start memory
>> +                                      region.
>> +
>> +  @retval RETURN_SUCCESS              The attributes were cleared for the
>> +                                      memory region.
>> +  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
>> +  @retval RETURN_UNSUPPORTED          Clearing the memory encryption attribute
>> +                                      is not supported
>> +**/
>> +RETURN_STATUS
>> +EFIAPI
>> +MemEncryptSevClearMmioPageEncMask (
>> +  IN PHYSICAL_ADDRESS         Cr3BaseAddress,
>> +  IN PHYSICAL_ADDRESS         BaseAddress,
>> +  IN UINTN                    NumPages
>> +  )
>> +{
>> +  //
>> +  // Memory encryption bit is not accessible in 32-bit mode
>> +  //
>> +  return RETURN_UNSUPPORTED;
>> +}
>> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
>> index 4fea6a6be0..6786573aea 100644
>> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
>> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
>> @@ -118,3 +118,36 @@ MemEncryptSevGetAddressRangeState (
>>             Length
>>             );
>>  }
>> +
>> +/**
>> +  This function clears memory encryption bit for the mmio region specified by
>> +  BaseAddress and NumPages from the current page table context.
>> +
>> +  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
>> +                                      current CR3)
>> +  @param[in]  BaseAddress             The physical address that is the start
>> +                                      address of a mmio region.
>> +  @param[in]  NumPages                The number of pages from start memory
>> +                                      region.
>> +
>> +  @retval RETURN_SUCCESS              The attributes were cleared for the
>> +                                      memory region.
>> +  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
>> +  @retval RETURN_UNSUPPORTED          Clearing the memory encryption attribute
>> +                                      is not supported
>> +**/
>> +RETURN_STATUS
>> +EFIAPI
>> +MemEncryptSevClearMmioPageEncMask (
>> +  IN PHYSICAL_ADDRESS         Cr3BaseAddress,
>> +  IN PHYSICAL_ADDRESS         BaseAddress,
>> +  IN UINTN                    NumPages
>> +  )
>> +{
>> +  return InternalMemEncryptSevClearMmioPageEncMask (
>> +           Cr3BaseAddress,
>> +           BaseAddress,
>> +           EFI_PAGES_TO_SIZE (NumPages)
>> +           );
>> +
>> +}
>> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
>> index d3455e812b..3bcc92f2e9 100644
>> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
>> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
>> @@ -557,6 +557,7 @@ EnableReadOnlyPageWriteProtect (
>>    @param[in]  Mode                    Set or Clear mode
>>    @param[in]  CacheFlush              Flush the caches before applying the
>>                                        encryption mask
>> +  @param[in]  IsMmio                  The address is Mmio address.
>>  
>>    @retval RETURN_SUCCESS              The attributes were cleared for the
>>                                        memory region.
> (2) The parameter's name in the documentation ("IsMmio") does not match
> the actual parameter name ("Mmio").
>
>
>> @@ -572,7 +573,8 @@ SetMemoryEncDec (
>>    IN    PHYSICAL_ADDRESS         PhysicalAddress,
>>    IN    UINTN                    Length,
>>    IN    MAP_RANGE_MODE           Mode,
>> -  IN    BOOLEAN                  CacheFlush
>> +  IN    BOOLEAN                  CacheFlush,
>> +  IN    BOOLEAN                  Mmio
>>    )
>>  {
>>    PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
> The "Mmio" parameter is not used for anything in this patch. It's very
> confusing.
>
> (3) Please remove the addition of the Mmio parameter from this patch.
> Please introduce the Mmio parameter only when it is utilized -- as far
> as I can tell from a quick git-blame, that's patch #26
> ("OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table").
>
> As a result, in this patch, InternalMemEncryptSevClearMmioPageEncMask()
> will effectively become a slight simplification of
> InternalMemEncryptSevSetMemoryDecrypted() -- rather than forwarding
> "Flush" for "CacheFlush", it will pass constant FALSE for "CacheFlush".
>
>
> (4) Please mention the above fact (= last paragraph above) in the commit
> message.
>
>
>> @@ -852,7 +854,8 @@ InternalMemEncryptSevSetMemoryDecrypted (
>>             PhysicalAddress,
>>             Length,
>>             ClearCBit,
>> -           Flush
>> +           Flush,
>> +           FALSE
>>             );
>>  }
>>  
>> @@ -888,6 +891,41 @@ InternalMemEncryptSevSetMemoryEncrypted (
>>             PhysicalAddress,
>>             Length,
>>             SetCBit,
>> -           Flush
>> +           Flush,
>> +           FALSE
>> +           );
>> +}
>> +
>> +/**
>> +  This function clears memory encryption bit for the Mmio region specified by
>> +  PhysicalAddress and Length from the current page table context.
>> +
>> +  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
>> +                                      current CR3)
>> +  @param[in]  PhysicalAddress         The physical address that is the start
>> +                                      address of a mmio region.
>> +  @param[in]  Length                  The length of memory region
>> +
>> +  @retval RETURN_SUCCESS              The attributes were cleared for the
>> +                                      memory region.
>> +  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
> This function does not take a NumPages parameter but a Length parameter.
>
> (5) Please update the RETURN_INVALID_PARAMETER comment accordingly -- in
> the header file as well.
>
>
>> +  @retval RETURN_UNSUPPORTED          Clearing the memory encyrption attribute
>> +                                      is not supported
>> +**/
>> +RETURN_STATUS
>> +EFIAPI
>> +InternalMemEncryptSevClearMmioPageEncMask (
>> +  IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
>> +  IN  PHYSICAL_ADDRESS        PhysicalAddress,
>> +  IN  UINTN                   Length
>> +  )
>> +{
>> +  return SetMemoryEncDec (
>> +           Cr3BaseAddress,
>> +           PhysicalAddress,
>> +           Length,
>> +           ClearCBit,
>> +           FALSE,
>> +           TRUE
>>             );
>>  }
>> diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
>> index fe2a0b2826..99ee7ea0e8 100644
>> --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
>> +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
>> @@ -126,4 +126,27 @@ InternalMemEncryptSevGetAddressRangeState (
>>    IN UINTN                    Length
>>    );
>>  
>> +/**
>> +  This function clears memory encryption bit for the Mmio region specified by
>> +  PhysicalAddress and Length from the current page table context.
>> +
>> +  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use
>> +                                      current CR3)
>> +  @param[in]  PhysicalAddress         The physical address that is the start
>> +                                      address of a mmio region.
>> +  @param[in]  Length                  The length of memory region
>> +
>> +  @retval RETURN_SUCCESS              The attributes were cleared for the
>> +                                      memory region.
>> +  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.
> This function does not take a NumPages parameter but a Length parameter.
>
> (6) Please update the RETURN_INVALID_PARAMETER comment accordingly --
> same as in the C file.
>
>
>> +  @retval RETURN_UNSUPPORTED          Clearing the memory encyrption attribute
>> +                                      is not supported
>> +**/
>> +RETURN_STATUS
>> +EFIAPI
>> +InternalMemEncryptSevClearMmioPageEncMask (
>> +  IN  PHYSICAL_ADDRESS        Cr3BaseAddress,
>> +  IN  PHYSICAL_ADDRESS        PhysicalAddress,
>> +  IN  UINTN                   Length
>> +  );
>>  #endif
>>
> Please carefully audit the rest of the series for comment blocks. Such
> issues render reviews inefficient.
>
> Thanks
> Laszlo
>
>
>
> 
>
>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 07/28] OvmfPkg: Use MemEncryptSevClearMmioPageEncMask() to clear EncMask from Mmio
  2021-05-06 10:50   ` [edk2-devel] " Laszlo Ersek
@ 2021-05-06 19:20     ` Brijesh Singh
  0 siblings, 0 replies; 81+ messages in thread
From: Brijesh Singh @ 2021-05-06 19:20 UTC (permalink / raw)
  To: Laszlo Ersek, devel
  Cc: brijesh.singh, James Bottomley, Min Xu, Jiewen Yao, Tom Lendacky,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/6/21 5:50 AM, Laszlo Ersek wrote:
> On 04/30/21 13:51, Brijesh Singh wrote:
>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7Cce4b852d83a14265d48f08d9107cd16f%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637558950553380286%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=CgY57XQGI9QBvj7vipJoJLVZLiEvpfySW17TLLx%2BZm8%3D&amp;reserved=0
>>
>> Use the MemEncryptSevClearMmioPageEncMask() to clear memory encryption mask
>> for the Mmio address range from the current page table context.
>>
>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  OvmfPkg/AmdSevDxe/AmdSevDxe.c                              | 10 ++++------
>>  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c |  5 ++---
>>  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c      |  5 ++---
>>  3 files changed, 8 insertions(+), 12 deletions(-)
>>
>> diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
>> index 689bfb376d..80831b81fa 100644
>> --- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c
>> +++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
>> @@ -53,11 +53,10 @@ AmdSevDxeEntryPoint (
>>        Desc = &AllDescMap[Index];
>>        if (Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo ||
>>            Desc->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
>> -        Status = MemEncryptSevClearPageEncMask (
>> +        Status = MemEncryptSevClearMmioPageEncMask (
>>                     0,
>>                     Desc->BaseAddress,
>> -                   EFI_SIZE_TO_PAGES (Desc->Length),
>> -                   FALSE
>> +                   EFI_SIZE_TO_PAGES (Desc->Length)
>>                     );
>>          ASSERT_EFI_ERROR (Status);
>>        }
>> @@ -73,11 +72,10 @@ AmdSevDxeEntryPoint (
>>    // the range.
>>    //
>>    if (PcdGet16 (PcdOvmfHostBridgePciDevId) == INTEL_Q35_MCH_DEVICE_ID) {
>> -    Status = MemEncryptSevClearPageEncMask (
>> +    Status = MemEncryptSevClearMmioPageEncMask (
>>                 0,
>>                 FixedPcdGet64 (PcdPciExpressBaseAddress),
>> -               EFI_SIZE_TO_PAGES (SIZE_256MB),
>> -               FALSE
>> +               EFI_SIZE_TO_PAGES (SIZE_256MB)
>>                 );
>>  
>>      ASSERT_EFI_ERROR (Status);
>> diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
>> index 1f285e0083..ab40087a84 100644
>> --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
>> +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
>> @@ -205,11 +205,10 @@ MarkIoMemoryRangeForRuntimeAccess (
>>    // memory range.
>>    //
>>    if (MemEncryptSevIsEnabled ()) {
>> -    Status = MemEncryptSevClearPageEncMask (
>> +    Status = MemEncryptSevClearMmioPageEncMask (
>>                 0,
>>                 BaseAddress,
>> -               EFI_SIZE_TO_PAGES (Length),
>> -               FALSE
>> +               EFI_SIZE_TO_PAGES (Length)
>>                 );
>>      ASSERT_EFI_ERROR (Status);
>>    }
>> diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
>> index 7eb80bfeff..ea75b489c7 100644
>> --- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
>> +++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
>> @@ -38,11 +38,10 @@ QemuFlashBeforeProbe (
>>    // C-bit on flash ranges from SMM page table.
>>    //
>>  
>> -  Status = MemEncryptSevClearPageEncMask (
>> +  Status = MemEncryptSevClearMmioPageEncMask (
>>               0,
>>               BaseAddress,
>> -             EFI_SIZE_TO_PAGES (FdBlockSize * FdBlockCount),
>> -             FALSE
>> +             EFI_SIZE_TO_PAGES (FdBlockSize * FdBlockCount)
>>               );
>>    ASSERT_EFI_ERROR (Status);
>>  }
>>
> The contents of this patch are sound, but they are incomplete, and
> incorrectly structured too.
>
> (1) Please provide a separate patch for each modified module.

Noted.


> (2) You missed the MemEncryptSevClearPageEncMask() call in
> TpmMmioSevDecryptPeimEntryPoint()
> [OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c] -- probably
> because you worked on this series in parallel with Tom working on the
> SEV-ES TPM fixes.


I guess Tom's patches were not accepted when I rebased the the SNP
patches. Will pick those changes in next rev.


>
> In the end, this patch should be split into three patches (because the
> change is needed for three modules).
>
> Thanks
> Laszlo
>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 09/28] OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase
  2021-05-06 14:08   ` [edk2-devel] " Laszlo Ersek
  2021-05-06 14:12     ` Laszlo Ersek
@ 2021-05-07 13:29     ` Brijesh Singh
  2021-05-07 15:10       ` Laszlo Ersek
  1 sibling, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-05-07 13:29 UTC (permalink / raw)
  To: Laszlo Ersek, Tom Lendacky
  Cc: brijesh.singh, devel, James Bottomley, Min Xu, Jiewen Yao,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/6/21 9:08 AM, Laszlo Ersek wrote:
> On 04/30/21 13:51, Brijesh Singh wrote:
>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C01d3e5c5268043c18bdf08d910987251%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637559069206222390%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=CN2hZrjsKzfSqMAxcQLtoHTUqBOlZmdDEO9vY9XT%2FTQ%3D&amp;reserved=0
>>
>> Commit 85b8eac59b8c5bd9c7eb9afdb64357ce1aa2e803 added support to ensure
>> that MMIO is only performed against the un-encrypted memory. If MMIO
>> is performed against encrypted memory, a #GP is raised.
>>
>> The VmgExitLib library depends on ApicTimerLib to get the APIC base
>> address so that it can exclude the APIC range from the un-encrypted
>> check. The OvmfPkg provides ApicTimerLib for the DXE phase. The
>> constructor AcpiTimerLibConstructor() used in the ApicTimerLib uses
>> the PciRead to get the PMBASE register. The PciRead() will cause an
>> MMIO access.
>>
>> The AmdSevDxe driver clears the memory encryption attribute from the
>> MMIO ranges. However, if VmgExitLib is linked to AmdSevDxe driver then the
>> AcpiTimerLibConstructor() will be called before AmdSevDxe driver can
>> clear the encryption attributes for the MMIO regions.
>>
>> Exclude the PMBASE register from the encrypted check so that we
>> can link VmgExitLib to the MemEncryptSevLib; which gets linked to
>> AmdSevDxe driver.
> The above explanation is inexact. There are several typos ("APIC" is
> incorrect, "ACPI" would be correct, for the TimerLib instance in
> question), but that's really just a side observation.
>
> The precise explanation is the following library instance dependency
> chain:
>
>   OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>   -----> MemEncryptSevLib                                               class
>   -----> "OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf" instance
>   -[*]-> VmgExitLib                                                     class
>   -----> "OvmfPkg/Library/VmgExitLib/VmgExitLib.inf"                    instance
>   -----> LocalApicLib                                                   class
>   -----> "UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf" instance
>   -----> TimerLib                                                       class
>   -----> "OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf"             instance
>   -----> PciLib                                                         class
>   -----> "OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf"    instance
>   -----> PciExpressLib                                                  class
>   -----> "MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf"       instance
>
> The link (or dependency) marked with [*] is introduced in patch #26
> ("OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table").
> That's the change that triggers the symptom. (In combination with you
> testing on Q35, because on i440fx, the DxePciLibI440FxQ35 lib instance
> accesses PCI config space via the 0xCF8, 0xCFC IO Ports, and those are
> unaffected by SEV-ES.)
>
> The symptom is somewhat "unjustified", because at the end of the series,
> the AmdSevDxe driver makes no calls to actual TimerLib APIs (I checked
> -- I disassembled the "AmdSevDxe.debug" file with "objdump -S", and
> there is no call to any API declared in the "TimerLib.h" class header).
> However, the ECAM (MMCONFIG) access is still triggered, because the
> AcpiTimerLibConstructor() function, in
> "OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c", is the constructor for
> the "OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf" instance, and
> AcpiTimerLibConstructor() calls PciRead32().
>
> If you check the "OvmfPkg/OvmfPkgX64.dsc" file, you'll find that the
> PciLib class is resolved to
> "MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf" by default, and to
> "OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf" for the
> following module types:
>
> - DXE_DRIVER,
> - DXE_RUNTIME_DRIVER,
> - SMM_CORE,
> - DXE_SMM_DRIVER,
> - UEFI_DRIVER,
> - UEFI_APPLICATION.
>
> The consequence is that modules strictly after the DXE_CORE get
> dynamically enabled extended config space access (ECAM) on Q35 via the
> PciLib class, whereas all modules strictly before the DXE_CORE, and the
> DXE_CORE itself, are restricted to normal config space (IO Ports 0xCF8 /
> 0xCFC) via the PciLib class.
>
> AmdSevDxe is a DXE_DRIVER, so it used to get DxePciLibI440FxQ35 as well.
>
> The solution should be simple. In the AmdSevDxe driver specifically, we
> need no access to extended PCI config space. Accessing normal PCI config
> space, via IO Ports 0xCF8 / 0xCFC, should suffice. That can be achieved
> with the following module-scope override:

Thanks Laszlo, I was not aware of the module-scope override. I will go
with this approach and make sure it works after the inclusion of the
VmgExitLib.


>
>> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
>> index 8d9a0a077601..45a02b236633 100644
>> --- a/OvmfPkg/OvmfPkgX64.dsc
>> +++ b/OvmfPkg/OvmfPkgX64.dsc
>> @@ -966,7 +966,10 @@ [Components]
>>  !endif
>>
>>    OvmfPkg/PlatformDxe/Platform.inf
>> -  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>> +  OvmfPkg/AmdSevDxe/AmdSevDxe.inf {
>> +    <LibraryClasses>
>> +      PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
>> +  }
>>    OvmfPkg/IoMmuDxe/IoMmuDxe.inf
>>    OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>>
> (
>
> For consistency, all DSC files that include
> "OvmfPkg/AmdSevDxe/AmdSevDxe.inf" should be modified similarly:
>
> - OvmfPkg/AmdSev/AmdSevX64.dsc
> - OvmfPkg/Bhyve/BhyveX64.dsc
> - OvmfPkg/OvmfPkgIa32X64.dsc
> - OvmfPkg/OvmfPkgX64.dsc
> - OvmfPkg/OvmfXen.dsc
>
> )
>
> Therefore, please try dropping this patch, and modifying patch#26
> instead -- the above module-scope override (for 5 DSC files) should be
> squashed into patch#26, *and* the explanation I provided above should be
> included in the commit message of patch#26.
>
> ... Correction: you have an independent bug in the series that affects
> my above analysis. Namely, you *seem* to add the VmgExitLib dependency
> to the "OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf"
> library instance, in patch#26. That's where you modify the INF file. But
> that's wrong: in patch#21 ("OvmfPkg/MemEncryptSevLib: Add support to
> validate system RAM"), you add a VmgInit() call to the same library
> instance, via the new file
> "OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c".
>
> The bug in that patch is clear from the fact that you introduce an
> #include <Library/VmgExitLib.h> directive, but that's not mirrored by an
> appropriate [LibraryClasses] change in the "DxeMemEncryptSevLib.inf"
> file. (The other two lib instance INF files, "SecMemEncryptSevLib.inf"
> and "PeiMemEncryptSevLib.inf" *are* modified as needed.)
>
> So you even need to move some stuff from patch#26 to patch#21, and
> *then* squash the above module-scope override (and explanation) into
> patch#21.
>
> A significant amount of work is needed on this series. I'll stop
> reviewing RFC v2 here, because I don't want to look at the remaining
> patches deeply as long as code movements etc are going to affect them.
> Please post the next version -- assuming no other reviewer would like to
> finish reviewing this version first!


Sounds good. What's your thought if I take out patch 1 - 9 from this RFC
series and submit them as non-RFC for the further review and acceptance
? The patch# 1-9 are basically prepatch before we get into SNP specific
bits.


> Thanks
> Laszlo
>
>> Cc: James Bottomley <jejb@linux.ibm.com>
>> Cc: Min Xu <min.m.xu@intel.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Erdem Aktas <erdemaktas@google.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf  |  4 ++
>>  OvmfPkg/Library/VmgExitLib/VmgExitLib.inf     |  7 +++
>>  OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 45 ++++++++++++++++++++
>>  3 files changed, 56 insertions(+)
>>
>> diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>> index e6f6ea7972..22435a0590 100644
>> --- a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>> +++ b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>> @@ -27,6 +27,7 @@
>>    SecVmgExitVcHandler.c
>>
>>  [Packages]
>> +  MdeModulePkg/MdeModulePkg.dec
>>    MdePkg/MdePkg.dec
>>    OvmfPkg/OvmfPkg.dec
>>    UefiCpuPkg/UefiCpuPkg.dec
>> @@ -42,4 +43,7 @@
>>  [FixedPcd]
>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
>> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
>>
>> +[Pcd]
>> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
>> diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
>> index c66c68726c..d3175c260e 100644
>> --- a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
>> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
>> @@ -27,6 +27,7 @@
>>    PeiDxeVmgExitVcHandler.c
>>
>>  [Packages]
>> +  MdeModulePkg/MdeModulePkg.dec
>>    MdePkg/MdePkg.dec
>>    OvmfPkg/OvmfPkg.dec
>>    UefiCpuPkg/UefiCpuPkg.dec
>> @@ -37,4 +38,10 @@
>>    DebugLib
>>    LocalApicLib
>>    MemEncryptSevLib
>> +  PcdLib
>>
>> +[FixedPcd]
>> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
>> +
>> +[Pcd]
>> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
>> diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
>> index 24259060fd..01ac5d8c19 100644
>> --- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
>> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
>> @@ -14,7 +14,10 @@
>>  #include <Library/VmgExitLib.h>
>>  #include <Register/Amd/Msr.h>
>>  #include <Register/Intel/Cpuid.h>
>> +#include <IndustryStandard/Q35MchIch9.h>
>> +#include <IndustryStandard/I440FxPiix4.h>
>>  #include <IndustryStandard/InstructionParsing.h>
>> +#include <Library/PcdLib.h>
>>
>>  #include "VmgExitVcHandler.h"
>>
>> @@ -596,6 +599,40 @@ UnsupportedExit (
>>    return Status;
>>  }
>>
>> +STATIC
>> +BOOLEAN
>> +IsPmbaBaseAddress (
>> +  IN  UINTN     Address
>> +  )
>> +{
>> +  UINT16 HostBridgeDevId;
>> +  UINTN Pmba;
>> +
>> +  //
>> +  // Query Host Bridge DID to determine platform type
>> +  //
>> +  HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
>> +  switch (HostBridgeDevId) {
>> +    case INTEL_82441_DEVICE_ID:
>> +      Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
>> +      break;
>> +    case INTEL_Q35_MCH_DEVICE_ID:
>> +      Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
>> +      //
>> +      // Add the MMCONFIG base address to get the Pmba base access address
>> +      //
>> +      Pmba += FixedPcdGet64 (PcdPciExpressBaseAddress);
>> +      break;
>> +    default:
>> +      return FALSE;
>> +  }
>> +
>> +  // Round up the offset to page size
>> +  Pmba = Pmba & ~(SIZE_4KB - 1);
>> +
>> +  return (Address == Pmba);
>> +}
>> +
>>  /**
>>    Validate that the MMIO memory access is not to encrypted memory.
>>
>> @@ -640,6 +677,14 @@ ValidateMmioMemory (
>>      return 0;
>>    }
>>
>> +  //
>> +  // Allow PMBASE accesses (which will have the encryption bit set before
>> +  // AmdSevDxe runs in the DXE phase)
>> +  //
>> +  if (IsPmbaBaseAddress (Address)) {
>> +    return 0;
>> +  }
>> +
>>    //
>>    // Any state other than unencrypted is an error, issue a #GP.
>>    //
>>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 09/28] OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase
  2021-05-07 13:29     ` Brijesh Singh
@ 2021-05-07 15:10       ` Laszlo Ersek
  2021-05-07 15:19         ` Brijesh Singh
  0 siblings, 1 reply; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-07 15:10 UTC (permalink / raw)
  To: Brijesh Singh, Tom Lendacky
  Cc: devel, James Bottomley, Min Xu, Jiewen Yao, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/07/21 15:29, Brijesh Singh wrote:
> 
> On 5/6/21 9:08 AM, Laszlo Ersek wrote:
>> On 04/30/21 13:51, Brijesh Singh wrote:
>>> BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7C01d3e5c5268043c18bdf08d910987251%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637559069206222390%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=CN2hZrjsKzfSqMAxcQLtoHTUqBOlZmdDEO9vY9XT%2FTQ%3D&amp;reserved=0
>>>
>>> Commit 85b8eac59b8c5bd9c7eb9afdb64357ce1aa2e803 added support to ensure
>>> that MMIO is only performed against the un-encrypted memory. If MMIO
>>> is performed against encrypted memory, a #GP is raised.
>>>
>>> The VmgExitLib library depends on ApicTimerLib to get the APIC base
>>> address so that it can exclude the APIC range from the un-encrypted
>>> check. The OvmfPkg provides ApicTimerLib for the DXE phase. The
>>> constructor AcpiTimerLibConstructor() used in the ApicTimerLib uses
>>> the PciRead to get the PMBASE register. The PciRead() will cause an
>>> MMIO access.
>>>
>>> The AmdSevDxe driver clears the memory encryption attribute from the
>>> MMIO ranges. However, if VmgExitLib is linked to AmdSevDxe driver then the
>>> AcpiTimerLibConstructor() will be called before AmdSevDxe driver can
>>> clear the encryption attributes for the MMIO regions.
>>>
>>> Exclude the PMBASE register from the encrypted check so that we
>>> can link VmgExitLib to the MemEncryptSevLib; which gets linked to
>>> AmdSevDxe driver.
>> The above explanation is inexact. There are several typos ("APIC" is
>> incorrect, "ACPI" would be correct, for the TimerLib instance in
>> question), but that's really just a side observation.
>>
>> The precise explanation is the following library instance dependency
>> chain:
>>
>>   OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>>   -----> MemEncryptSevLib                                               class
>>   -----> "OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf" instance
>>   -[*]-> VmgExitLib                                                     class
>>   -----> "OvmfPkg/Library/VmgExitLib/VmgExitLib.inf"                    instance
>>   -----> LocalApicLib                                                   class
>>   -----> "UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf" instance
>>   -----> TimerLib                                                       class
>>   -----> "OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf"             instance
>>   -----> PciLib                                                         class
>>   -----> "OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf"    instance
>>   -----> PciExpressLib                                                  class
>>   -----> "MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf"       instance
>>
>> The link (or dependency) marked with [*] is introduced in patch #26
>> ("OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table").
>> That's the change that triggers the symptom. (In combination with you
>> testing on Q35, because on i440fx, the DxePciLibI440FxQ35 lib instance
>> accesses PCI config space via the 0xCF8, 0xCFC IO Ports, and those are
>> unaffected by SEV-ES.)
>>
>> The symptom is somewhat "unjustified", because at the end of the series,
>> the AmdSevDxe driver makes no calls to actual TimerLib APIs (I checked
>> -- I disassembled the "AmdSevDxe.debug" file with "objdump -S", and
>> there is no call to any API declared in the "TimerLib.h" class header).
>> However, the ECAM (MMCONFIG) access is still triggered, because the
>> AcpiTimerLibConstructor() function, in
>> "OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c", is the constructor for
>> the "OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf" instance, and
>> AcpiTimerLibConstructor() calls PciRead32().
>>
>> If you check the "OvmfPkg/OvmfPkgX64.dsc" file, you'll find that the
>> PciLib class is resolved to
>> "MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf" by default, and to
>> "OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf" for the
>> following module types:
>>
>> - DXE_DRIVER,
>> - DXE_RUNTIME_DRIVER,
>> - SMM_CORE,
>> - DXE_SMM_DRIVER,
>> - UEFI_DRIVER,
>> - UEFI_APPLICATION.
>>
>> The consequence is that modules strictly after the DXE_CORE get
>> dynamically enabled extended config space access (ECAM) on Q35 via the
>> PciLib class, whereas all modules strictly before the DXE_CORE, and the
>> DXE_CORE itself, are restricted to normal config space (IO Ports 0xCF8 /
>> 0xCFC) via the PciLib class.
>>
>> AmdSevDxe is a DXE_DRIVER, so it used to get DxePciLibI440FxQ35 as well.
>>
>> The solution should be simple. In the AmdSevDxe driver specifically, we
>> need no access to extended PCI config space. Accessing normal PCI config
>> space, via IO Ports 0xCF8 / 0xCFC, should suffice. That can be achieved
>> with the following module-scope override:
> 
> Thanks Laszlo, I was not aware of the module-scope override. I will go
> with this approach and make sure it works after the inclusion of the
> VmgExitLib.
> 
> 
>>
>>> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
>>> index 8d9a0a077601..45a02b236633 100644
>>> --- a/OvmfPkg/OvmfPkgX64.dsc
>>> +++ b/OvmfPkg/OvmfPkgX64.dsc
>>> @@ -966,7 +966,10 @@ [Components]
>>>  !endif
>>>
>>>    OvmfPkg/PlatformDxe/Platform.inf
>>> -  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>>> +  OvmfPkg/AmdSevDxe/AmdSevDxe.inf {
>>> +    <LibraryClasses>
>>> +      PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
>>> +  }
>>>    OvmfPkg/IoMmuDxe/IoMmuDxe.inf
>>>    OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
>>>
>> (
>>
>> For consistency, all DSC files that include
>> "OvmfPkg/AmdSevDxe/AmdSevDxe.inf" should be modified similarly:
>>
>> - OvmfPkg/AmdSev/AmdSevX64.dsc
>> - OvmfPkg/Bhyve/BhyveX64.dsc
>> - OvmfPkg/OvmfPkgIa32X64.dsc
>> - OvmfPkg/OvmfPkgX64.dsc
>> - OvmfPkg/OvmfXen.dsc
>>
>> )
>>
>> Therefore, please try dropping this patch, and modifying patch#26
>> instead -- the above module-scope override (for 5 DSC files) should be
>> squashed into patch#26, *and* the explanation I provided above should be
>> included in the commit message of patch#26.
>>
>> ... Correction: you have an independent bug in the series that affects
>> my above analysis. Namely, you *seem* to add the VmgExitLib dependency
>> to the "OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf"
>> library instance, in patch#26. That's where you modify the INF file. But
>> that's wrong: in patch#21 ("OvmfPkg/MemEncryptSevLib: Add support to
>> validate system RAM"), you add a VmgInit() call to the same library
>> instance, via the new file
>> "OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c".
>>
>> The bug in that patch is clear from the fact that you introduce an
>> #include <Library/VmgExitLib.h> directive, but that's not mirrored by an
>> appropriate [LibraryClasses] change in the "DxeMemEncryptSevLib.inf"
>> file. (The other two lib instance INF files, "SecMemEncryptSevLib.inf"
>> and "PeiMemEncryptSevLib.inf" *are* modified as needed.)
>>
>> So you even need to move some stuff from patch#26 to patch#21, and
>> *then* squash the above module-scope override (and explanation) into
>> patch#21.
>>
>> A significant amount of work is needed on this series. I'll stop
>> reviewing RFC v2 here, because I don't want to look at the remaining
>> patches deeply as long as code movements etc are going to affect them.
>> Please post the next version -- assuming no other reviewer would like to
>> finish reviewing this version first!
> 
> 
> Sounds good. What's your thought if I take out patch 1 - 9 from this RFC
> series and submit them as non-RFC for the further review and acceptance
> ? The patch# 1-9 are basically prepatch before we get into SNP specific
> bits.

More precisely, that means patches 1-8 (because patch#9 should be
replaced by the module-scope override, and also moved to just before
what is currently patch#21).

Other than that, I agree, this is a good idea. I've anyway thought that
the MdePkg stuff (5 patches) could be / should be merged up-front in
separation, and then the subsequent 3 patches for OvmfPkg are basically
refactoring. We can record the resultant commit range (8 commits) in
TianoCore#3275, and keep the BZ open for the rest of the work. So go
ahead please.

Thanks!
Laszlo


> 
> 
>> Thanks
>> Laszlo
>>
>>> Cc: James Bottomley <jejb@linux.ibm.com>
>>> Cc: Min Xu <min.m.xu@intel.com>
>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>>> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
>>> Cc: Laszlo Ersek <lersek@redhat.com>
>>> Cc: Erdem Aktas <erdemaktas@google.com>
>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>> ---
>>>  OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf  |  4 ++
>>>  OvmfPkg/Library/VmgExitLib/VmgExitLib.inf     |  7 +++
>>>  OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 45 ++++++++++++++++++++
>>>  3 files changed, 56 insertions(+)
>>>
>>> diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>>> index e6f6ea7972..22435a0590 100644
>>> --- a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>>> +++ b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>>> @@ -27,6 +27,7 @@
>>>    SecVmgExitVcHandler.c
>>>
>>>  [Packages]
>>> +  MdeModulePkg/MdeModulePkg.dec
>>>    MdePkg/MdePkg.dec
>>>    OvmfPkg/OvmfPkg.dec
>>>    UefiCpuPkg/UefiCpuPkg.dec
>>> @@ -42,4 +43,7 @@
>>>  [FixedPcd]
>>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
>>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
>>> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
>>>
>>> +[Pcd]
>>> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
>>> diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
>>> index c66c68726c..d3175c260e 100644
>>> --- a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
>>> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
>>> @@ -27,6 +27,7 @@
>>>    PeiDxeVmgExitVcHandler.c
>>>
>>>  [Packages]
>>> +  MdeModulePkg/MdeModulePkg.dec
>>>    MdePkg/MdePkg.dec
>>>    OvmfPkg/OvmfPkg.dec
>>>    UefiCpuPkg/UefiCpuPkg.dec
>>> @@ -37,4 +38,10 @@
>>>    DebugLib
>>>    LocalApicLib
>>>    MemEncryptSevLib
>>> +  PcdLib
>>>
>>> +[FixedPcd]
>>> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
>>> +
>>> +[Pcd]
>>> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
>>> diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
>>> index 24259060fd..01ac5d8c19 100644
>>> --- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
>>> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
>>> @@ -14,7 +14,10 @@
>>>  #include <Library/VmgExitLib.h>
>>>  #include <Register/Amd/Msr.h>
>>>  #include <Register/Intel/Cpuid.h>
>>> +#include <IndustryStandard/Q35MchIch9.h>
>>> +#include <IndustryStandard/I440FxPiix4.h>
>>>  #include <IndustryStandard/InstructionParsing.h>
>>> +#include <Library/PcdLib.h>
>>>
>>>  #include "VmgExitVcHandler.h"
>>>
>>> @@ -596,6 +599,40 @@ UnsupportedExit (
>>>    return Status;
>>>  }
>>>
>>> +STATIC
>>> +BOOLEAN
>>> +IsPmbaBaseAddress (
>>> +  IN  UINTN     Address
>>> +  )
>>> +{
>>> +  UINT16 HostBridgeDevId;
>>> +  UINTN Pmba;
>>> +
>>> +  //
>>> +  // Query Host Bridge DID to determine platform type
>>> +  //
>>> +  HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
>>> +  switch (HostBridgeDevId) {
>>> +    case INTEL_82441_DEVICE_ID:
>>> +      Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
>>> +      break;
>>> +    case INTEL_Q35_MCH_DEVICE_ID:
>>> +      Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
>>> +      //
>>> +      // Add the MMCONFIG base address to get the Pmba base access address
>>> +      //
>>> +      Pmba += FixedPcdGet64 (PcdPciExpressBaseAddress);
>>> +      break;
>>> +    default:
>>> +      return FALSE;
>>> +  }
>>> +
>>> +  // Round up the offset to page size
>>> +  Pmba = Pmba & ~(SIZE_4KB - 1);
>>> +
>>> +  return (Address == Pmba);
>>> +}
>>> +
>>>  /**
>>>    Validate that the MMIO memory access is not to encrypted memory.
>>>
>>> @@ -640,6 +677,14 @@ ValidateMmioMemory (
>>>      return 0;
>>>    }
>>>
>>> +  //
>>> +  // Allow PMBASE accesses (which will have the encryption bit set before
>>> +  // AmdSevDxe runs in the DXE phase)
>>> +  //
>>> +  if (IsPmbaBaseAddress (Address)) {
>>> +    return 0;
>>> +  }
>>> +
>>>    //
>>>    // Any state other than unencrypted is an error, issue a #GP.
>>>    //
>>>
> 


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 09/28] OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase
  2021-05-07 15:10       ` Laszlo Ersek
@ 2021-05-07 15:19         ` Brijesh Singh
  2021-05-07 15:47           ` Laszlo Ersek
  0 siblings, 1 reply; 81+ messages in thread
From: Brijesh Singh @ 2021-05-07 15:19 UTC (permalink / raw)
  To: Laszlo Ersek, Tom Lendacky
  Cc: brijesh.singh, devel, James Bottomley, Min Xu, Jiewen Yao,
	Jordan Justen, Ard Biesheuvel, Erdem Aktas


On 5/7/21 10:10 AM, Laszlo Ersek wrote:
>
>> Sounds good. What's your thought if I take out patch 1 - 9 from this RFC
>> series and submit them as non-RFC for the further review and acceptance
>> ? The patch# 1-9 are basically prepatch before we get into SNP specific
>> bits.
> More precisely, that means patches 1-8 (because patch#9 should be
> replaced by the module-scope override, and also moved to just before
> what is currently patch#21).
>
> Other than that, I agree, this is a good idea. I've anyway thought that
> the MdePkg stuff (5 patches) could be / should be merged up-front in
> separation, and then the subsequent 3 patches for OvmfPkg are basically
> refactoring. We can record the resultant commit range (8 commits) in
> TianoCore#3275, and keep the BZ open for the rest of the work. So go
> ahead please.

Yes, I will keep patch#9 in SNP series.

FYI, I will add couple of more patches in MdePkg to define the macros
for AP creation and RMPAJUST instruction. Now that GHCB spec is final,
we are working to get the AP creation implemented for the next version.

-Brijesh


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [edk2-devel] [PATCH RFC v2 09/28] OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase
  2021-05-07 15:19         ` Brijesh Singh
@ 2021-05-07 15:47           ` Laszlo Ersek
  0 siblings, 0 replies; 81+ messages in thread
From: Laszlo Ersek @ 2021-05-07 15:47 UTC (permalink / raw)
  To: Brijesh Singh, Tom Lendacky
  Cc: devel, James Bottomley, Min Xu, Jiewen Yao, Jordan Justen,
	Ard Biesheuvel, Erdem Aktas

On 05/07/21 17:19, Brijesh Singh wrote:
> 
> On 5/7/21 10:10 AM, Laszlo Ersek wrote:
>>
>>> Sounds good. What's your thought if I take out patch 1 - 9 from this RFC
>>> series and submit them as non-RFC for the further review and acceptance
>>> ? The patch# 1-9 are basically prepatch before we get into SNP specific
>>> bits.
>> More precisely, that means patches 1-8 (because patch#9 should be
>> replaced by the module-scope override, and also moved to just before
>> what is currently patch#21).
>>
>> Other than that, I agree, this is a good idea. I've anyway thought that
>> the MdePkg stuff (5 patches) could be / should be merged up-front in
>> separation, and then the subsequent 3 patches for OvmfPkg are basically
>> refactoring. We can record the resultant commit range (8 commits) in
>> TianoCore#3275, and keep the BZ open for the rest of the work. So go
>> ahead please.
> 
> Yes, I will keep patch#9 in SNP series.
> 
> FYI, I will add couple of more patches in MdePkg to define the macros
> for AP creation and RMPAJUST instruction. Now that GHCB spec is final,
> we are working to get the AP creation implemented for the next version.

If the spec is final, then extending the MdePkg patches makes sense, yes.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 81+ messages in thread

end of thread, other threads:[~2021-05-07 15:47 UTC | newest]

Thread overview: 81+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-04-30 11:51 [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 01/28] MdePkg: Expand the SEV MSR to include the SNP definition Brijesh Singh
2021-05-03  8:39   ` [edk2-devel] " Laszlo Ersek
2021-05-03 11:42     ` Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 02/28] MdePkg: Define the GHCB Hypervisor features Brijesh Singh
2021-05-03 10:10   ` [edk2-devel] " Laszlo Ersek
2021-05-03 12:20     ` Brijesh Singh
2021-05-03 13:40       ` Laszlo Ersek
2021-04-30 11:51 ` [PATCH RFC v2 03/28] MdePkg: Define the GHCB GPA structure Brijesh Singh
2021-05-03 10:24   ` [edk2-devel] " Laszlo Ersek
2021-05-03 12:19     ` Laszlo Ersek
2021-05-03 12:55       ` Brijesh Singh
2021-05-03 13:50         ` Laszlo Ersek
2021-05-03 13:55           ` Laszlo Ersek
2021-04-30 11:51 ` [PATCH RFC v2 04/28] MdePkg: Define the Page State Change VMGEXIT structures Brijesh Singh
2021-05-04 12:33   ` [edk2-devel] " Laszlo Ersek
2021-05-04 13:59     ` Laszlo Ersek
2021-05-04 14:48       ` Lendacky, Thomas
2021-05-04 18:07         ` Laszlo Ersek
2021-05-04 18:53     ` Brijesh Singh
2021-05-05 18:24       ` Laszlo Ersek
2021-05-05 19:27         ` Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 05/28] MdePkg: Add AsmPvalidate() support Brijesh Singh
2021-05-04 13:58   ` [edk2-devel] " Laszlo Ersek
2021-05-04 14:09     ` Laszlo Ersek
2021-05-04 19:07     ` Brijesh Singh
2021-05-05 18:56       ` Laszlo Ersek
     [not found]     ` <167BF2A01FA60569.6407@groups.io>
2021-05-04 19:55       ` Brijesh Singh
2021-05-05 19:10         ` Laszlo Ersek
     [not found]       ` <167BF53DA09B327E.22277@groups.io>
2021-05-04 20:28         ` Brijesh Singh
2021-05-04 23:03           ` Brijesh Singh
2021-05-05 19:19             ` Laszlo Ersek
2021-05-05 19:17           ` Laszlo Ersek
2021-04-30 11:51 ` [PATCH RFC v2 06/28] OvmfPkg/BaseMemEncryptSevLib: Introduce MemEncryptSevClearMmioPageEncMask() Brijesh Singh
2021-05-06 10:39   ` [edk2-devel] " Laszlo Ersek
2021-05-06 19:18     ` Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 07/28] OvmfPkg: Use MemEncryptSevClearMmioPageEncMask() to clear EncMask from Mmio Brijesh Singh
2021-05-06 10:50   ` [edk2-devel] " Laszlo Ersek
2021-05-06 19:20     ` Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 08/28] OvmfPkg/BaseMemEncryptSevLib: Remove CacheFlush parameter Brijesh Singh
2021-05-06 11:08   ` [edk2-devel] " Laszlo Ersek
2021-04-30 11:51 ` [PATCH RFC v2 09/28] OvmfPkg/VmgExitLib: Allow PMBASE register access in Dxe phase Brijesh Singh
2021-05-06 14:08   ` [edk2-devel] " Laszlo Ersek
2021-05-06 14:12     ` Laszlo Ersek
2021-05-07 13:29     ` Brijesh Singh
2021-05-07 15:10       ` Laszlo Ersek
2021-05-07 15:19         ` Brijesh Singh
2021-05-07 15:47           ` Laszlo Ersek
2021-04-30 11:51 ` [PATCH RFC v2 10/28] OvmfPkg/MemEncryptSevLib: add MemEncryptSevSnpEnabled() Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 11/28] OvmfPkg: Reserve Secrets page in MEMFD Brijesh Singh
2021-05-05  6:42   ` [edk2-devel] " Dov Murik
2021-05-05 13:11     ` Brijesh Singh
2021-05-05 19:33       ` Laszlo Ersek
2021-05-06 10:57         ` Dov Murik
2021-05-06 15:06           ` Laszlo Ersek
2021-05-06 16:12           ` James Bottomley
2021-05-06 16:02         ` James Bottomley
2021-04-30 11:51 ` [PATCH RFC v2 12/28] OvmfPkg: Reserve CPUID page for the SEV-SNP guest Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 13/28] OvmfPkg: Validate the data pages used in the Reset vector and SEC phase Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 14/28] UefiCpuPkg: Define the SEV-SNP specific dynamic PCDs Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 15/28] OvmfPkg/MemEncryptSevLib: extend the workarea to include SNP enabled field Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 16/28] OvmfPkg/MemEncryptSevLib: Extend Es Workarea to include hv features Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 17/28] OvmfPkg/ResetVector: Invalidate the GHCB page Brijesh Singh
2021-05-03 13:05   ` Erdem Aktas
2021-05-03 14:28     ` Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 18/28] OvmfPkg: Add a library to support registering GHCB GPA Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 19/28] OvmfPkg: register GHCB gpa for the SEV-SNP guest Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 20/28] UefiCpuPkg/MpLib: add support to register GHCB GPA when SEV-SNP is enabled Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 21/28] OvmfPkg/MemEncryptSevLib: Add support to validate system RAM Brijesh Singh
2021-05-03 14:04   ` Erdem Aktas
2021-05-03 18:56     ` Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 22/28] OvmfPkg/BaseMemEncryptSevLib: Skip the pre-validated " Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 23/28] OvmfPkg/MemEncryptSevLib: Add support to validate > 4GB memory in PEI phase Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 24/28] OvmfPkg/SecMain: Pre-validate the memory used for decompressing Fv Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 25/28] OvmfPkg/PlatformPei: Validate the system RAM when SNP is active Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 26/28] OvmfPkg/MemEncryptSevLib: Change the page state in the RMP table Brijesh Singh
2021-04-30 11:51 ` [PATCH RFC v2 27/28] OvmfPkg/AmdSev: Expose the SNP reserved pages through configuration table Brijesh Singh
2021-05-05  7:10   ` [edk2-devel] " Dov Murik
2021-05-05 19:37     ` Laszlo Ersek
2021-04-30 11:51 ` [PATCH RFC v2 28/28] MdePkg/GHCB: Increase the GHCB protocol max version Brijesh Singh
2021-04-30 16:49 ` [edk2-devel] [PATCH RFC v2 00/28] Add AMD Secure Nested Paging (SEV-SNP) support Laszlo Ersek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox