summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Roth <michael.roth@amd.com>2021-12-09 11:27:36 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2021-12-09 06:28:10 +0000
commit34819f2caccb061a982e77fd8ba908632cb9dcaf (patch)
treeb7ea0ec267a989df9fdc4a6b543553dcbedb45f3
parentf2dc28f0b69717255d9c9e3c753f6efbd96c2fc7 (diff)
downloadedk2-34819f2caccb061a982e77fd8ba908632cb9dcaf.tar.gz
edk2-34819f2caccb061a982e77fd8ba908632cb9dcaf.tar.bz2
edk2-34819f2caccb061a982e77fd8ba908632cb9dcaf.zip
OvmfPkg/ResetVector: use SEV-SNP-validated CPUID values
CPUID instructions are issued during early boot to do things like probe for SEV support. Currently these are handled by a minimal #VC handler that uses the MSR-based GHCB protocol to fetch the CPUID values from the hypervisor. When SEV-SNP is enabled, use the firmware-validated CPUID values from the CPUID page instead [1]. [1]: SEV SNP Firmware ABI Specification, Rev. 0.8, 8.13.2.6 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: Michael Roth <michael.roth@amd.com> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
-rw-r--r--OvmfPkg/ResetVector/Ia32/AmdSev.asm80
1 files changed, 75 insertions, 5 deletions
diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
index 48d9178168..1f827da3b9 100644
--- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm
+++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
@@ -34,6 +34,18 @@ BITS 32
%define GHCB_CPUID_REGISTER_SHIFT 30
%define CPUID_INSN_LEN 2
+; #VC handler offsets/sizes for accessing SNP CPUID page
+;
+%define SNP_CPUID_ENTRY_SZ 48
+%define SNP_CPUID_COUNT 0
+%define SNP_CPUID_ENTRY 16
+%define SNP_CPUID_ENTRY_EAX_IN 0
+%define SNP_CPUID_ENTRY_ECX_IN 4
+%define SNP_CPUID_ENTRY_EAX 24
+%define SNP_CPUID_ENTRY_EBX 28
+%define SNP_CPUID_ENTRY_ECX 32
+%define SNP_CPUID_ENTRY_EDX 36
+
%define SEV_GHCB_MSR 0xc0010130
%define SEV_STATUS_MSR 0xc0010131
@@ -335,11 +347,61 @@ SevEsIdtNotCpuid:
TerminateVmgExit TERM_VC_NOT_CPUID
iret
- ;
- ; Total stack usage for the #VC handler is 44 bytes:
- ; - 12 bytes for the exception IRET (after popping error code)
- ; - 32 bytes for the local variables.
- ;
+; Use the SNP CPUID page to handle the cpuid lookup
+;
+; Modified: EAX, EBX, ECX, EDX
+;
+; Relies on the stack setup/usage in #VC handler:
+;
+; On entry,
+; [esp + VC_CPUID_FUNCTION] contains EAX input to cpuid instruction
+;
+; On return, stores corresponding results of CPUID lookup in:
+; [esp + VC_CPUID_RESULT_EAX]
+; [esp + VC_CPUID_RESULT_EBX]
+; [esp + VC_CPUID_RESULT_ECX]
+; [esp + VC_CPUID_RESULT_EDX]
+;
+SnpCpuidLookup:
+ mov eax, [esp + VC_CPUID_FUNCTION]
+ mov ebx, [CPUID_BASE + SNP_CPUID_COUNT]
+ mov ecx, CPUID_BASE + SNP_CPUID_ENTRY
+ ; Zero these out now so we can simply return if lookup fails
+ mov dword[esp + VC_CPUID_RESULT_EAX], 0
+ mov dword[esp + VC_CPUID_RESULT_EBX], 0
+ mov dword[esp + VC_CPUID_RESULT_ECX], 0
+ mov dword[esp + VC_CPUID_RESULT_EDX], 0
+
+SnpCpuidCheckEntry:
+ cmp ebx, 0
+ je VmmDoneSnpCpuid
+ cmp dword[ecx + SNP_CPUID_ENTRY_EAX_IN], eax
+ jne SnpCpuidCheckEntryNext
+ ; As with SEV-ES handler we assume requested CPUID sub-leaf/index is 0
+ cmp dword[ecx + SNP_CPUID_ENTRY_ECX_IN], 0
+ je SnpCpuidEntryFound
+
+SnpCpuidCheckEntryNext:
+ dec ebx
+ add ecx, SNP_CPUID_ENTRY_SZ
+ jmp SnpCpuidCheckEntry
+
+SnpCpuidEntryFound:
+ mov eax, [ecx + SNP_CPUID_ENTRY_EAX]
+ mov [esp + VC_CPUID_RESULT_EAX], eax
+ mov eax, [ecx + SNP_CPUID_ENTRY_EBX]
+ mov [esp + VC_CPUID_RESULT_EBX], eax
+ mov eax, [ecx + SNP_CPUID_ENTRY_EDX]
+ mov [esp + VC_CPUID_RESULT_ECX], eax
+ mov eax, [ecx + SNP_CPUID_ENTRY_ECX]
+ mov [esp + VC_CPUID_RESULT_EDX], eax
+ jmp VmmDoneSnpCpuid
+
+;
+; Total stack usage for the #VC handler is 44 bytes:
+; - 12 bytes for the exception IRET (after popping error code)
+; - 32 bytes for the local variables.
+;
SevEsIdtVmmComm:
;
; If we're here, then we are an SEV-ES guest and this
@@ -367,6 +429,13 @@ SevEsIdtVmmComm:
; Save the CPUID function being requested
mov [esp + VC_CPUID_FUNCTION], eax
+ ; If SEV-SNP is enabled, use the CPUID page to handle the CPUID
+ ; instruction.
+ mov ecx, SEV_STATUS_MSR
+ rdmsr
+ bt eax, 2
+ jc SnpCpuidLookup
+
; The GHCB CPUID protocol uses the following mapping to request
; a specific register:
; 0 => EAX, 1 => EBX, 2 => ECX, 3 => EDX
@@ -424,6 +493,7 @@ VmmDone:
mov ecx, SEV_GHCB_MSR
wrmsr
+VmmDoneSnpCpuid:
mov eax, [esp + VC_CPUID_RESULT_EAX]
mov ebx, [esp + VC_CPUID_RESULT_EBX]
mov ecx, [esp + VC_CPUID_RESULT_ECX]