[edk2-devel] [RFC PATCH v5 08/28] OvmfPkg/ResetVector: invalidate the GHCB page

Brijesh Singh via groups.io brijesh.singh=amd.com at groups.io
Wed Jun 30 12:53:01 UTC 2021


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

The GHCB page is part of a pre-validated memory range specified through
the SnpBootBlock GUID. When SEV-SNP is active, the GHCB page is
pre-validated by the hyperivosr during the SNP guest creation. On boot,
the reset vector maps the GHCB page as un-encrypted in the initial page
table. Just clearing the encryption attribute from the page table is not
enough. To maintain the security guarantees, the page must be invalidated.

The page invalidation consists of two steps:

1. Use the PVALIDATE instruction to clear Validated Bit from the RMP table.
2. Use the Page State Change VMGEXIT to ask hypervisor to change the page
   state to shared in the RMP table.

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

diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
index c4c00056f9f3..b6f33d049a43 100644
--- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm
+++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
@@ -8,6 +8,8 @@
 ;
 ;------------------------------------------------------------------------------
 
+%include "Nasm.inc"
+
 BITS    32
 
 ;
@@ -45,6 +47,25 @@ BITS    32
 ; The unexpected response code
 %define TERM_UNEXPECTED_RESP_CODE   2
 
+; SNP page state change failure
+%define TERM_PAGE_STATE_CHANAGE     3
+
+; Hypervisor does not support SEV-SNP feature
+%define TERM_HV_UNSUPPORTED_FEATURE 4
+
+; GHCB SEV Information MSR protocol
+%define GHCB_SEV_INFORMATION_REQUEST        2
+%define GHCB_SEV_INFORMATION_RESPONSE       1
+
+; 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 Hypervisor features MSR protocol
+%define GHCB_HYPERVISOR_FEATURES_REQUEST    128
+%define GHCB_HYPERVISOR_FEATURES_RESPONSE   129
 
 ; Macro is used to issue the MSR protocol based VMGEXIT. The caller is
 ; responsible to populate values in the EDX:EAX registers. After the vmmcall
@@ -247,6 +268,110 @@ SevExit:
 
     OneTimeCallRet CheckSevFeatures
 
+; The version 2 of GHCB specification added the support to query the hypervisor
+; features. If the GHCB version is >=2 then read the hypervisor features and
+; verify that SEV-SNP feature is supported.
+;
+CheckSnpHypervisorFeatures:
+    ; Get the SEV Information
+    xor     eax, eax
+    xor     edx, edx
+
+    VmgExit GHCB_SEV_INFORMATION_REQUEST, GHCB_SEV_INFORMATION_RESPONSE
+
+    ;
+    ; SEV Information Response GHCB MSR
+    ;   GHCB_MSR[63:48] = Maximum protocol version
+    ;   GHCB_MSR[47:32] = Minimum protocol version
+    ;
+    shr     edx, 16
+    cmp     edx, 2
+    jl      SevSnpUnsupportedFeature
+
+    ; Get the hypervisor features
+    xor     eax, eax
+    xor     edx, edx
+
+    VmgExit GHCB_HYPERVISOR_FEATURES_REQUEST, GHCB_HYPERVISOR_FEATURES_RESPONSE
+
+    ;
+    ; Hypervisor features reponse
+    ;   GHCB_MSR[63:12] = Features bitmap
+    ;       BIT0        = SEV-SNP Supported
+    ;
+    shr     eax, 12
+    bt      eax, 0
+    jnc     SevSnpUnsupportedFeature
+
+CheckSnpHypervisorFeaturesDone:
+    OneTimeCallRet CheckSnpHypervisorFeatures
+
+; 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 SEV-SNP is enabled
+    ;  MSR_0xC0010131 - Bit 2 (SEV-SNP enabled)
+    mov       ecx, SEV_STATUS_MSR
+    rdmsr
+    bt        eax, 2
+    jnc       InvalidateGHCBPageDone
+
+    ; Verify that SEV-SNP feature is supported by the hypervisor.
+    OneTimeCall   CheckSnpHypervisorFeatures
+
+    ; Use PVALIDATE instruction to invalidate the page
+    mov     eax, GHCB_BASE
+    mov     ecx, 0
+    mov     edx, 0
+    PVALIDATE
+
+    ; Save the carry flag to be use later.
+    setc    dl
+
+    ; If PVALIDATE fail then abort the launch.
+    cmp     eax, 0
+    jne     SevSnpPageStateFailureTerminate
+
+    ; Check the carry flag to determine if RMP entry was updated.
+    cmp     dl, 0
+    jne     SevSnpPageStateFailureTerminate
+
+    ; 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
+    ;
+    mov     eax, (GHCB_BASE >> 12)
+    shl     eax, 12
+    mov     edx, (GHCB_PAGE_STATE_SHARED << 20)
+
+    VmgExit  GHCB_PAGE_STATE_CHANGE_REQUEST, GHCB_PAGE_STATE_CHANGE_RESPONSE
+
+    ;
+    ; Response GHCB MSR
+    ;   GHCB_MSR[63:12] = Error code
+    ;
+    cmp     edx, 0
+    jnz     SevSnpPageStateFailureTerminate
+
+InvalidateGHCBPageDone:
+    OneTimeCallRet InvalidateGHCBPage
+
+; Terminate the SEV-SNP guest due to the page state change failure
+SevSnpPageStateFailureTerminate:
+    TerminateVmgExit   TERM_PAGE_STATE_CHANAGE
+
+; Terminate the SEV-SNP guest because hypervisor does not support
+; the SEV-SNP feature
+SevSnpUnsupportedFeature:
+    TerminateVmgExit   TERM_HV_UNSUPPORTED_FEATURE
+
+
 ; Check if Secure Encrypted Virtualization - Encrypted State (SEV-ES) feature
 ; is enabled.
 ;
diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index eacdb69ddb9f..f587ef912e4c 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -140,6 +140,19 @@ clearGhcbMemoryLoop:
     mov     dword[ecx * 4 + GHCB_BASE - 4], eax
     loop    clearGhcbMemoryLoop
 
+    ;
+    ; 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



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#77343): https://edk2.groups.io/g/devel/message/77343
Mute This Topic: https://groups.io/mt/83891521/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-






More information about the edk2-devel-archive mailing list