; Sets the CR3 register for 64-bit paging\r
;\r
; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>\r
+; Copyright (c) 2017 - 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
; SPDX-License-Identifier: BSD-2-Clause-Patent\r
;\r
;------------------------------------------------------------------------------\r
%define CPUID_INSN_LEN 2\r
\r
\r
-; Check if Secure Encrypted Virtualization (SEV) feature is enabled\r
+; Check if Secure Encrypted Virtualization (SEV) features are enabled.\r
+;\r
+; Register usage is tight in this routine, so multiple calls for the\r
+; same CPUID and MSR data are performed to keep things simple.\r
;\r
; Modified: EAX, EBX, ECX, EDX, ESP\r
;\r
; If SEV is enabled then EAX will be at least 32.\r
; If SEV is disabled then EAX will be zero.\r
;\r
-CheckSevFeature:\r
+CheckSevFeatures:\r
; Set the first byte of the workarea to zero to communicate to the SEC\r
; phase that SEV-ES is not enabled. If SEV-ES is enabled, the CPUID\r
; instruction will trigger a #VC exception where the first byte of the\r
- ; workarea will be set to one.\r
+ ; workarea will be set to one or, if CPUID is not being intercepted,\r
+ ; the MSR check below will set the first byte of the workarea to one.\r
mov byte[SEV_ES_WORK_AREA], 0\r
\r
;\r
cmp eax, 0x8000001f\r
jl NoSev\r
\r
- ; Check for memory encryption feature:\r
+ ; Check for SEV memory encryption feature:\r
; CPUID Fn8000_001F[EAX] - Bit 1\r
; CPUID raises a #VC exception if running as an SEV-ES guest\r
- mov eax, 0x8000001f\r
+ mov eax, 0x8000001f\r
cpuid\r
bt eax, 1\r
jnc NoSev\r
\r
- ; Check if memory encryption is enabled\r
+ ; Check if SEV memory encryption is enabled\r
; MSR_0xC0010131 - Bit 0 (SEV enabled)\r
mov ecx, 0xc0010131\r
rdmsr\r
bt eax, 0\r
jnc NoSev\r
\r
+ ; Check for SEV-ES memory encryption feature:\r
+ ; CPUID Fn8000_001F[EAX] - Bit 3\r
+ ; CPUID raises a #VC exception if running as an SEV-ES guest\r
+ mov eax, 0x8000001f\r
+ cpuid\r
+ bt eax, 3\r
+ jnc GetSevEncBit\r
+\r
+ ; Check if SEV-ES is enabled\r
+ ; MSR_0xC0010131 - Bit 1 (SEV-ES enabled)\r
+ mov ecx, 0xc0010131\r
+ rdmsr\r
+ bt eax, 1\r
+ jnc GetSevEncBit\r
+\r
+ ; Set the first byte of the workarea to one to communicate to the SEC\r
+ ; phase that SEV-ES is enabled.\r
+ mov byte[SEV_ES_WORK_AREA], 1\r
+\r
+GetSevEncBit:\r
; Get pte bit position to enable memory encryption\r
; CPUID Fn8000_001F[EBX] - Bits 5:0\r
;\r
pop eax\r
mov esp, 0\r
\r
- OneTimeCallRet CheckSevFeature\r
+ OneTimeCallRet CheckSevFeatures\r
\r
; Check if Secure Encrypted Virtualization - Encrypted State (SEV-ES) feature\r
; is enabled.\r
;\r
-; Modified: EAX, EBX, ECX\r
+; Modified: EAX\r
;\r
; If SEV-ES is enabled then EAX will be non-zero.\r
; If SEV-ES is disabled then EAX will be zero.\r
;\r
-CheckSevEsFeature:\r
+IsSevEsEnabled:\r
xor eax, eax\r
\r
- ; SEV-ES can't be enabled if SEV isn't, so first check the encryption\r
- ; mask.\r
- test edx, edx\r
- jz NoSevEs\r
-\r
- ; Save current value of encryption mask\r
- mov ebx, edx\r
-\r
- ; Check if SEV-ES is enabled\r
- ; MSR_0xC0010131 - Bit 1 (SEV-ES enabled)\r
- mov ecx, 0xc0010131\r
- rdmsr\r
- and eax, 2\r
+ ; During CheckSevFeatures, the SEV_ES_WORK_AREA was set to 1 if\r
+ ; SEV-ES is enabled.\r
+ cmp byte[SEV_ES_WORK_AREA], 1\r
+ jne SevEsDisabled\r
\r
- ; Restore encryption mask\r
- mov edx, ebx\r
+ mov eax, 1\r
\r
-NoSevEs:\r
- OneTimeCallRet CheckSevEsFeature\r
+SevEsDisabled:\r
+ OneTimeCallRet IsSevEsEnabled\r
\r
;\r
; Modified: EAX, EBX, ECX, EDX\r
;\r
SetCr3ForPageTables64:\r
\r
- OneTimeCall CheckSevFeature\r
+ OneTimeCall CheckSevFeatures\r
xor edx, edx\r
test eax, eax\r
jz SevNotActive\r
mov [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx\r
loop pageTableEntriesLoop\r
\r
- OneTimeCall CheckSevEsFeature\r
+ OneTimeCall IsSevEsEnabled\r
test eax, eax\r
jz SetCr3\r
\r
; If we're here, then we are an SEV-ES guest and this\r
; was triggered by a CPUID instruction\r
;\r
- ; Set the first byte of the workarea to one to communicate to the SEC\r
- ; phase that SEV-ES is enabled.\r
+ ; Set the first byte of the workarea to one to communicate that\r
+ ; a #VC was taken.\r
mov byte[SEV_ES_WORK_AREA], 1\r
\r
pop ecx ; Error code\r