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>
This commit is contained in:
Michael Roth 2021-12-09 11:27:36 +08:00 committed by mergify[bot]
parent f2dc28f0b6
commit 34819f2cac
1 changed files with 75 additions and 5 deletions

View File

@ -34,6 +34,18 @@ BITS 32
%define GHCB_CPUID_REGISTER_SHIFT 30 %define GHCB_CPUID_REGISTER_SHIFT 30
%define CPUID_INSN_LEN 2 %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_GHCB_MSR 0xc0010130
%define SEV_STATUS_MSR 0xc0010131 %define SEV_STATUS_MSR 0xc0010131
@ -335,11 +347,61 @@ SevEsIdtNotCpuid:
TerminateVmgExit TERM_VC_NOT_CPUID TerminateVmgExit TERM_VC_NOT_CPUID
iret iret
; ; Use the SNP CPUID page to handle the cpuid lookup
; Total stack usage for the #VC handler is 44 bytes: ;
; - 12 bytes for the exception IRET (after popping error code) ; Modified: EAX, EBX, ECX, EDX
; - 32 bytes for the local variables. ;
; ; 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: SevEsIdtVmmComm:
; ;
; If we're here, then we are an SEV-ES guest and this ; If we're here, then we are an SEV-ES guest and this
@ -367,6 +429,13 @@ SevEsIdtVmmComm:
; Save the CPUID function being requested ; Save the CPUID function being requested
mov [esp + VC_CPUID_FUNCTION], eax 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 ; The GHCB CPUID protocol uses the following mapping to request
; a specific register: ; a specific register:
; 0 => EAX, 1 => EBX, 2 => ECX, 3 => EDX ; 0 => EAX, 1 => EBX, 2 => ECX, 3 => EDX
@ -424,6 +493,7 @@ VmmDone:
mov ecx, SEV_GHCB_MSR mov ecx, SEV_GHCB_MSR
wrmsr wrmsr
VmmDoneSnpCpuid:
mov eax, [esp + VC_CPUID_RESULT_EAX] mov eax, [esp + VC_CPUID_RESULT_EAX]
mov ebx, [esp + VC_CPUID_RESULT_EBX] mov ebx, [esp + VC_CPUID_RESULT_EBX]
mov ecx, [esp + VC_CPUID_RESULT_ECX] mov ecx, [esp + VC_CPUID_RESULT_ECX]