audk/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
Min Xu 8b76f23534 OvmfPkg: Enable TDX in ResetVector
RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429

Intel's Trust Domain Extensions (Intel TDX) refers to an Intel technology
that extends Virtual Machines Extensions (VMX) and Multi-Key Total Memory
Encryption (MKTME) with a new kind of virutal machines guest called a
Trust Domain (TD). A TD is desinged to run in a CPU mode that protects the
confidentiality of TD memory contents and the TD's CPU state from other
software, including the hosting Virtual-Machine Monitor (VMM), unless
explicitly shared by the TD itself.

Note: Intel TDX is only available on X64, so the Tdx related changes are
in X64 path. In IA32 path, there may be null stub to make the build
success.

This patch includes below major changes.

1. Ia32/IntelTdx.asm
IntelTdx.asm includes below routines used in ResetVector
 - IsTdx
   Check if the running system is Tdx guest.

 - InitTdxWorkarea
   It initialize the TDX_WORK_AREA. Because it is called by both BSP and
   APs and to avoid the race condition, only BSP can initialize the
   WORK_AREA. AP will wait until the field of TDX_WORK_AREA_PGTBL_READY
   is set.

 - ReloadFlat32
   After reset all CPUs in TDX are initialized to 32-bit protected mode.
   But GDT register is not set. So this routine loads the GDT then jump
   to Flat 32 protected mode again.

 - InitTdx
   This routine wrap above 3 routines together to do Tdx initialization
   in ResetVector phase.

 - IsTdxEnabled
   It is a OneTimeCall to probe if TDX is enabled by checking the
   CC_WORK_AREA.

 - CheckTdxFeaturesBeforeBuildPagetables
   This routine is called to check if it is Non-TDX guest, TDX-Bsp or
   TDX-APs. Because in TDX guest all the initialization is done by BSP
   (including the page tables). APs should not build the tables.

 - TdxPostBuildPageTables
   It is called after Page Tables are built by BSP.
   byte[TDX_WORK_AREA_PGTBL_READY] is set by BSP to indicate APs can
   leave spin and go.

2. Ia32/PageTables64.asm
As described above only the TDX BSP build the page tables. So
PageTables64.asm is updated to make sure only TDX BSP build the
PageTables. TDX APs will skip the page table building and set Cr3
directly.

3. Ia16/ResetVectorVtf0.asm
In Tdx all CPUs "reset" to run on 32-bit protected mode with flat
descriptor (paging disabled). But in Non-Td guest the initial state of
CPUs is 16-bit real mode. To resolve this conflict, BITS 16/32 is used
in the ResetVectorVtf0.asm. It checks the 32-bit protected mode or 16-bit
real mode, then jump to the corresponding entry point.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2021-10-24 02:09:27 +00:00

130 lines
4.1 KiB
NASM

;------------------------------------------------------------------------------
; @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
cmp byte[SEV_ES_WORK_AREA], 0
jz 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