public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Lendacky, Thomas" <thomas.lendacky@amd.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: Jordan Justen <jordan.l.justen@intel.com>,
	Laszlo Ersek <lersek@redhat.com>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Michael D Kinney <michael.d.kinney@intel.com>,
	Liming Gao <liming.gao@intel.com>,
	Eric Dong <eric.dong@intel.com>, Ray Ni <ray.ni@intel.com>,
	"Singh, Brijesh" <brijesh.singh@amd.com>
Subject: [RFC PATCH 02/28] OvmfPkg/ResetVector: Add support for a 32-bit SEV check
Date: Mon, 19 Aug 2019 21:35:49 +0000	[thread overview]
Message-ID: <91782da0444dc5238d4623e96bfa1ab203586390.1566250534.git.thomas.lendacky@amd.com> (raw)
In-Reply-To: <cover.1566250534.git.thomas.lendacky@amd.com>

From: Tom Lendacky <thomas.lendacky@amd.com>

When running as an SEV-ES guest in 32-bit mode, it is not possible to
perform a CPUID instruction because it will require communicating with
the hypervisor using the GHCB.  However, writes to the GHCB when in
32-bit mode will be will be encrypted and thus not able to be read
by the hypervisor.

To get around this, add an IDT entry for the #VC exception.  The #VC
handler will use the GHCB CPUID request/response protocol to obtain
the requested CPUID function values and provide these to the guest.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 OvmfPkg/ResetVector/ResetVector.inf       |   2 +
 OvmfPkg/ResetVector/Ia32/PageTables64.asm | 173 ++++++++++++++++++++++
 OvmfPkg/ResetVector/ResetVector.nasmb     |   1 +
 3 files changed, 176 insertions(+)

diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf
index b0ddfa5832a2..960b47cd0797 100644
--- a/OvmfPkg/ResetVector/ResetVector.inf
+++ b/OvmfPkg/ResetVector/ResetVector.inf
@@ -35,3 +35,5 @@ [BuildOptions]
 [Pcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index abad009f20f5..c6071fe934de 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -37,6 +37,15 @@ BITS    32
 ; If SEV is disabled then EAX will be zero.
 ;
 CheckSevFeature:
+    ;
+    ; Set up exception handlers to check for SEV-ES
+    ;   Load temporary RAM stack based on PCDs
+    ;   Establish exception handlers
+    ;
+    mov       esp, SEV_TOP_OF_STACK
+    mov       eax, ADDR_OF(idtr)
+    lidt      [cs:eax]
+
     ; Check if we have a valid (0x8000_001F) CPUID leaf
     mov       eax, 0x80000000
     cpuid
@@ -73,6 +82,15 @@ NoSev:
     xor       eax, eax
 
 SevExit:
+    ;
+    ; Clear exception handlers and stack
+    ;
+    push      eax
+    mov       eax, ADDR_OF(idtr_clear)
+    lidt      [cs:eax]
+    pop       eax
+    mov       esp, 0
+
     OneTimeCallRet CheckSevFeature
 
 ;
@@ -146,3 +164,158 @@ pageTableEntriesLoop:
     mov     cr3, eax
 
     OneTimeCallRet SetCr3ForPageTables64
+
+SevEsIdtCommon:
+    hlt
+    jmp     SevEsIdtCommon
+    iret
+
+SevEsIdtVmmComm:
+    ;
+    ; If we're here, then we are an SEV-ES guest and this
+    ; was triggered by a CPUID instruction
+    ;
+    pop     ecx                     ; Error code
+    cmp     ecx, 0x72               ; Be sure it was CPUID
+    jne     SevEsIdtCommon
+
+    ;
+    ; Set up local variable room on the stack
+    ;   CPUID function      : + 28
+    ;   CPUID register      : + 24
+    ;   GHCB MSR (EAX)      : + 20
+    ;   GHCB MSR (EDX)      : + 16
+    ;   CPUID result (EDX)  : + 12
+    ;   CPUID result (ECX)  : + 8
+    ;   CPUID result (EBX)  : + 4
+    ;   CPUID result (EAX)  : + 0
+    sub     esp, 32
+
+    ; Save CPUID function and initial register request
+    mov     [esp + 28], eax
+    xor     eax, eax
+    mov     [esp + 24], eax
+
+    ; Save current GHCB MSR value
+    mov     ecx, 0xc0010130
+    rdmsr
+    mov     [esp + 20], eax
+    mov     [esp + 16], edx
+
+NextReg:
+    ;
+    ; Setup GHCB MSR
+    ;   GHCB_MSR[63:32] = CPUID function
+    ;   GHCB_MSR[31:30] = CPUID register
+    ;   GHCB_MSR[11:0]  = CPUID request protocol
+    ;
+    mov     eax, [esp + 24]
+    cmp     eax, 4
+    jge     VmmDone
+
+    shl     eax, 30
+    or      eax, 0x004
+    mov     edx, [esp + 28]
+    mov     ecx, 0xc0010130
+    wrmsr
+
+    ; Issue VMGEXIT (rep; vmmcall)
+    db      0xf3
+    db      0x0f
+    db      0x01
+    db      0xd9
+
+    ;
+    ; Read GHCB MSR
+    ;   GHCB_MSR[63:32] = CPUID register value
+    ;   GHCB_MSR[31:30] = CPUID register
+    ;   GHCB_MSR[11:0]  = CPUID response protocol
+    ;
+    mov     ecx, 0xc0010130
+    rdmsr
+    mov     ecx, eax
+    and     ecx, 0xfff
+    cmp     ecx, 0x005
+    jne     SevEsIdtCommon
+
+    ; Save returned value
+    shr     eax, 30
+    and     eax, 0x3
+    shl     eax, 2
+    mov     ecx, esp
+    add     ecx, eax
+    mov     [ecx], edx
+
+    ; Next register
+    inc     word [esp + 24]
+
+    jmp     NextReg
+
+VmmDone:
+    ;
+    ; At this point we have all CPUID register values. Restore the GHCB MSR,
+    ; set the return register values and return.
+    ;
+    mov     eax, [esp + 20]
+    mov     edx, [esp + 16]
+    mov     ecx, 0xc0010130
+    wrmsr
+
+    mov     eax, [esp + 0]
+    mov     ebx, [esp + 4]
+    mov     ecx, [esp + 8]
+    mov     edx, [esp + 12]
+
+    add     esp, 32
+    add     word [esp], 2           ; Skip over the CPUID instruction
+    iret
+
+ALIGN   2
+
+idtr:
+    dw      IDT_END - IDT_BASE - 1  ; Limit
+    dd      ADDR_OF(IDT_BASE)       ; Base
+
+idtr_clear:
+    dw      0                       ; Limit
+    dd      0                       ; Base
+
+ALIGN   16
+
+;
+; The Interrupt Descriptor Table (IDT)
+;   This will be used to determine if SEV-ES is enabled.  Upon execution
+;   of the CPUID instruction, a VMM Communication Exception will occur.
+;   This will tell us if SEV-ES is enabled.  We can use the current value
+;   of the GHCB MSR to determine the SEV attributes.
+;
+IDT_BASE:
+;
+; Vectors 0 - 28
+;
+%rep 29
+    dw      (ADDR_OF(SevEsIdtCommon) & 0xffff)   ; Offset low bits 15..0
+    dw      0x10                                 ; Selector
+    db      0                                    ; Reserved
+    db      0x8E                                 ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
+    dw      (ADDR_OF(SevEsIdtCommon) >> 16)      ; Offset high bits 31..16
+%endrep
+;
+; Vector 29 (VMM Communication Exception)
+;
+    dw      (ADDR_OF(SevEsIdtVmmComm) & 0xffff)  ; Offset low bits 15..0
+    dw      0x10                                 ; Selector
+    db      0                                    ; Reserved
+    db      0x8E                                 ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
+    dw      (ADDR_OF(SevEsIdtVmmComm) >> 16)     ; Offset high bits 31..16
+;
+; Vectors 30 - 31
+;
+%rep 2
+    dw      (ADDR_OF(SevEsIdtCommon) & 0xffff)   ; Offset low bits 15..0
+    dw      0x10                                 ; Selector
+    db      0                                    ; Reserved
+    db      0x8E                                 ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
+    dw      (ADDR_OF(SevEsIdtCommon) >> 16)      ; Offset high bits 31..16
+%endrep
+IDT_END:
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index 75cfe16654b1..3b213cd05ab2 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -55,6 +55,7 @@
 
   %define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (Offset))
 %include "Ia32/Flat32ToFlat64.asm"
+  %define SEV_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))
 %include "Ia32/PageTables64.asm"
 %endif
 
-- 
2.17.1


  parent reply	other threads:[~2019-08-19 21:35 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-19 21:35 [RFC PATCH 00/28] SEV-ES guest support thomas.lendacky
2019-08-19 21:35 ` [RFC PATCH 01/28] OvmfPkg/Sec: Enable cache early to speed up booting Lendacky, Thomas
2019-08-21 14:21   ` [edk2-devel] " Laszlo Ersek
2019-08-21 21:25     ` Lendacky, Thomas
2019-08-21 21:51     ` Jordan Justen
2019-08-22 13:46       ` Laszlo Ersek
2019-08-22 20:44         ` Jordan Justen
2019-08-23 13:32           ` Laszlo Ersek
2019-08-19 21:35 ` Lendacky, Thomas [this message]
2019-08-19 21:35 ` [RFC PATCH 03/28] OvmfPkg/MemEncryptSevLib: Add an SEV-ES guest indicator function Lendacky, Thomas
2019-08-19 21:35 ` [RFC PATCH 04/28] OvmfPkg: Create a GHCB page for use during Sec phase Lendacky, Thomas
2019-08-21 14:25   ` [edk2-devel] " Laszlo Ersek
2019-08-21 21:29     ` Lendacky, Thomas
2019-08-19 21:35 ` [RFC PATCH 05/28] OvmfPkg: Create GHCB pages for use during Pei and Dxe phase Lendacky, Thomas
2019-08-21 14:31   ` [edk2-devel] " Laszlo Ersek
2019-08-21 21:42     ` Lendacky, Thomas
2019-08-22 14:12       ` Laszlo Ersek
2019-08-22 15:24         ` Lendacky, Thomas
2019-08-23 13:26           ` Laszlo Ersek
2019-08-19 21:35 ` [RFC PATCH 06/28] OvmfPkg: A per-CPU variable area for #VC usage Lendacky, Thomas
2019-08-19 21:35 ` [RFC PATCH 07/28] OvmfPkg/PlatformPei: Move early GDT into ram when SEV-ES is enabled Lendacky, Thomas
2019-08-21 15:44   ` [edk2-devel] " Laszlo Ersek
2019-08-19 21:35 ` [RFC PATCH 08/28] MdePkg/BaseLib: Implement the VMGEXIT support Lendacky, Thomas
2019-08-19 21:47   ` Ni, Ray
2019-08-19 22:25     ` Lendacky, Thomas
2019-08-19 21:35 ` [RFC PATCH 09/28] UefiCpuPkg/CpuExceptionHandler: Add base support for the #VC exception Lendacky, Thomas
2019-08-19 21:35 ` [RFC PATCH 10/28] UefiCpuPkg/CpuExceptionHandler: Add base #VC exception handling support for Sec phase Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 11/28] UefiCpuPkg/CpuExceptionHandler: Add support for IOIO_PROT NAE events Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 12/28] UefiCpuPkg/CpuExceptionHandler: Support string IO " Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 13/28] UefiCpuPkg/CpuExceptionHandler: Add support for CPUID " Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 14/28] UefiCpuPkg/CpuExceptionHandler: Add support for MSR_PROT " Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 15/28] UefiCpuPkg/CpuExceptionHandler: Add support for NPF NAE events (MMIO) Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 16/28] UefiCpuPkg/CpuExceptionHandler: Add support for WBINVD NAE events Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 17/28] UefiCpuPkg/CpuExceptionHandler: Add support for RDTSC " Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 18/28] UefiCpuPkg/CpuExceptionHandler: Add support for RDPMC " Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 19/28] UefiCpuPkg/CpuExceptionHandler: Add support for INVD " Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 20/28] UefiCpuPkg/CpuExceptionHandler: Add support for VMMCALL " Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 21/28] UefiCpuPkg/CpuExceptionHandler: Add support for RDTSCP " Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 22/28] UefiCpuPkg/CpuExceptionHandler: Add support for MONITOR/MONITORX " Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 23/28] UefiCpuPkg/CpuExceptionHandler: Add support for MWAIT/MWAITX " Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 24/28] UefiCpuPkg/CpuExceptionHandler: Add support for DR7 Read/Write " Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 25/28] UefiCpuPkg/CpuExceptionHandler: Add base #VC exception handling support for Pei/Dxe phases Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 26/28] UefiCpuPkg/MpInitLib: Update CPU MP data with a flag to indicate if SEV-ES is active Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 27/28] UefiCpuPkg/MpInitLib: Allow AP booting under SEV-ES Lendacky, Thomas
2019-08-19 21:36 ` [RFC PATCH 28/28] UefiCpuPkg/MpInitLib: Introduce an MP finalization routine to support SEV-ES Lendacky, Thomas
2019-08-21 14:17 ` [edk2-devel] [RFC PATCH 00/28] SEV-ES guest support Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=91782da0444dc5238d4623e96bfa1ab203586390.1566250534.git.thomas.lendacky@amd.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox