;------------------------------------------------------------------------------ | |
; @file | |
; Transition from 32 bit flat protected mode into 64 bit flat protected mode | |
; | |
; Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR> | |
; Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR> | |
; SPDX-License-Identifier: BSD-2-Clause-Patent | |
; | |
;------------------------------------------------------------------------------ | |
BITS 32 | |
; | |
; Modified: EAX, ECX, EDX | |
; | |
Transition32FlatTo64Flat: | |
OneTimeCall SetCr3ForPageTables64 | |
mov eax, cr4 | |
bts eax, 5 ; enable PAE | |
mov cr4, eax | |
; | |
; In TDX LME has already been set. So we're done and jump to enable | |
; paging directly if Tdx is enabled. | |
; EBX is cleared because in the later it will be used to check if | |
; the second step of the SEV-ES mitigation is to be performed. | |
; | |
xor ebx, ebx | |
OneTimeCall IsTdxEnabled | |
test eax, eax | |
jnz EnablePaging | |
mov ecx, 0xc0000080 | |
rdmsr | |
bts eax, 8 ; set LME | |
wrmsr | |
; | |
; SEV-ES mitigation check support | |
; | |
xor ebx, ebx | |
mov ecx, 1 | |
bt [SEV_ES_WORK_AREA_STATUS_MSR], ecx | |
jnc EnablePaging | |
; | |
; SEV-ES is active, perform a quick sanity check against the reported | |
; encryption bit position. This is to help mitigate against attacks where | |
; the hypervisor reports an incorrect encryption bit position. | |
; | |
; This is the first step in a two step process. Before paging is enabled | |
; writes to memory are encrypted. Using the RDRAND instruction (available | |
; on all SEV capable processors), write 64-bits of random data to the | |
; SEV_ES_WORK_AREA and maintain the random data in registers (register | |
; state is protected under SEV-ES). This will be used in the second step. | |
; | |
RdRand1: | |
rdrand ecx | |
jnc RdRand1 | |
mov dword[SEV_ES_WORK_AREA_RDRAND], ecx | |
RdRand2: | |
rdrand edx | |
jnc RdRand2 | |
mov dword[SEV_ES_WORK_AREA_RDRAND + 4], edx | |
; | |
; Use EBX instead of the SEV_ES_WORK_AREA memory to determine whether to | |
; perform the second step. | |
; | |
mov ebx, 1 | |
EnablePaging: | |
mov eax, cr0 | |
bts eax, 31 ; set PG | |
mov cr0, eax ; enable paging | |
jmp LINEAR_CODE64_SEL:ADDR_OF(jumpTo64BitAndLandHere) | |
BITS 64 | |
jumpTo64BitAndLandHere: | |
; | |
; Check if the second step of the SEV-ES mitigation is to be performed. | |
; | |
test ebx, ebx | |
jz InsnCompare | |
; | |
; SEV-ES is active, perform the second step of the encryption bit postion | |
; mitigation check. The ECX and EDX register contain data from RDRAND that | |
; was stored to memory in encrypted form. If the encryption bit position is | |
; valid, the contents of ECX and EDX will match the memory location. | |
; | |
cmp dword[SEV_ES_WORK_AREA_RDRAND], ecx | |
jne SevEncBitHlt | |
cmp dword[SEV_ES_WORK_AREA_RDRAND + 4], edx | |
jne SevEncBitHlt | |
; | |
; If SEV or SEV-ES is active, perform a quick sanity check against | |
; the reported encryption bit position. This is to help mitigate | |
; against attacks where the hypervisor reports an incorrect encryption | |
; bit position. If SEV is not active, this check will always succeed. | |
; | |
; The cmp instruction compares the first four bytes of the cmp instruction | |
; itself (which will be read decrypted if SEV or SEV-ES is active and the | |
; encryption bit position is valid) against the immediate within the | |
; instruction (an instruction fetch is always decrypted correctly by | |
; hardware) based on RIP relative addressing. | |
; | |
InsnCompare: | |
cmp dword[rel InsnCompare], 0xFFF63D81 | |
je GoodCompare | |
; | |
; The hypervisor provided an incorrect encryption bit position, do not | |
; proceed. | |
; | |
SevEncBitHlt: | |
cli | |
hlt | |
jmp SevEncBitHlt | |
GoodCompare: | |
debugShowPostCode POSTCODE_64BIT_MODE | |
OneTimeCallRet Transition32FlatTo64Flat | |