mirror of https://github.com/acidanthera/audk.git
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:
parent
f2dc28f0b6
commit
34819f2cac
|
@ -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]
|
||||||
|
|
Loading…
Reference in New Issue