]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/SecMain: register GHCB gpa for the SEV-SNP guest
authorBrijesh Singh via groups.io <brijesh.singh=amd.com@groups.io>
Thu, 9 Dec 2021 03:27:38 +0000 (11:27 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Thu, 9 Dec 2021 06:28:10 +0000 (06:28 +0000)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

The SEV-SNP guest requires that GHCB GPA must be registered before using.
See the GHCB specification section 2.3.2 for more details.

Cc: Michael Roth <michael.roth@amd.com>
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: Erdem Aktas <erdemaktas@google.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Jiewen Yao <Jiewen.yao@intel.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
OvmfPkg/Sec/AmdSev.c

index 0828d090feaf5a186481afb72719f7285733137e..aa655fd9cbaef7dc196130623a7f51765f9d38a0 100644 (file)
@@ -48,6 +48,104 @@ SevEsProtocolFailure (
   CpuDeadLoop ();\r
 }\r
 \r
+/**\r
+  Determine if SEV-SNP is active.\r
+\r
+  @retval TRUE   SEV-SNP is enabled\r
+  @retval FALSE  SEV-SNP is not enabled\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+SevSnpIsEnabled (\r
+  VOID\r
+  )\r
+{\r
+  MSR_SEV_STATUS_REGISTER  Msr;\r
+\r
+  //\r
+  // Read the SEV_STATUS MSR to determine whether SEV-SNP is active.\r
+  //\r
+  Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);\r
+\r
+  //\r
+  // Check MSR_0xC0010131 Bit 2 (Sev-Snp Enabled)\r
+  //\r
+  if (Msr.Bits.SevSnpBit) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+ Register the GHCB GPA\r
+\r
+*/\r
+STATIC\r
+VOID\r
+SevSnpGhcbRegister (\r
+  EFI_PHYSICAL_ADDRESS  Address\r
+  )\r
+{\r
+  MSR_SEV_ES_GHCB_REGISTER  Msr;\r
+\r
+  //\r
+  // Use the GHCB MSR Protocol to request to register the GPA.\r
+  //\r
+  Msr.GhcbPhysicalAddress      = Address & ~EFI_PAGE_MASK;\r
+  Msr.GhcbGpaRegister.Function = GHCB_INFO_GHCB_GPA_REGISTER_REQUEST;\r
+  AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);\r
+\r
+  AsmVmgExit ();\r
+\r
+  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);\r
+\r
+  //\r
+  // If hypervisor responded with a different GPA than requested then fail.\r
+  //\r
+  if ((Msr.GhcbGpaRegister.Function != GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE) ||\r
+      ((Msr.GhcbPhysicalAddress & ~EFI_PAGE_MASK) != Address))\r
+  {\r
+    SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL);\r
+  }\r
+}\r
+\r
+/**\r
+ Verify that Hypervisor supports the SNP feature.\r
+\r
+ */\r
+STATIC\r
+BOOLEAN\r
+HypervisorSnpFeatureCheck (\r
+  VOID\r
+  )\r
+{\r
+  MSR_SEV_ES_GHCB_REGISTER  Msr;\r
+  UINT64                    Features;\r
+\r
+  //\r
+  // Use the GHCB MSR Protocol to query the hypervisor capabilities\r
+  //\r
+  Msr.GhcbPhysicalAddress             = 0;\r
+  Msr.GhcbHypervisorFeatures.Function = GHCB_HYPERVISOR_FEATURES_REQUEST;\r
+  AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);\r
+\r
+  AsmVmgExit ();\r
+\r
+  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);\r
+\r
+  Features =  RShiftU64 (Msr.GhcbPhysicalAddress, 12);\r
+\r
+  if ((Msr.GhcbHypervisorFeatures.Function != GHCB_HYPERVISOR_FEATURES_RESPONSE) ||\r
+      (!(Features & GHCB_HV_FEATURES_SNP)))\r
+  {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
 /**\r
   Validate the SEV-ES/GHCB protocol level.\r
 \r
@@ -89,6 +187,27 @@ SevEsProtocolCheck (
     SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL);\r
   }\r
 \r
+  //\r
+  // We cannot use the MemEncryptSevSnpIsEnabled () because the\r
+  // ProcessLibraryConstructorList () is not called yet.\r
+  //\r
+  if (SevSnpIsEnabled ()) {\r
+    //\r
+    // Check if hypervisor supports the SNP feature\r
+    //\r
+    if (!HypervisorSnpFeatureCheck ()) {\r
+      SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL);\r
+    }\r
+\r
+    //\r
+    // Unlike the SEV-ES guest, the SNP requires that GHCB GPA must be\r
+    // registered with the Hypervisor before the use. This can be done\r
+    // using the new VMGEXIT defined in the GHCB v2. Register the GPA\r
+    // before it is used.\r
+    //\r
+    SevSnpGhcbRegister ((EFI_PHYSICAL_ADDRESS)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase));\r
+  }\r
+\r
   //\r
   // SEV-ES protocol checking succeeded, set the initial GHCB address\r
   //\r