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