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>
130 lines
4.2 KiB
NASM
130 lines
4.2 KiB
NASM
;------------------------------------------------------------------------------
|
|
; @file
|
|
; Sets the CR3 register for 64-bit paging
|
|
;
|
|
; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
|
|
; Copyright (c) 2017 - 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
|
|
; SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
;
|
|
;------------------------------------------------------------------------------
|
|
|
|
BITS 32
|
|
|
|
%define PAGE_PRESENT 0x01
|
|
%define PAGE_READ_WRITE 0x02
|
|
%define PAGE_USER_SUPERVISOR 0x04
|
|
%define PAGE_WRITE_THROUGH 0x08
|
|
%define PAGE_CACHE_DISABLE 0x010
|
|
%define PAGE_ACCESSED 0x020
|
|
%define PAGE_DIRTY 0x040
|
|
%define PAGE_PAT 0x080
|
|
%define PAGE_GLOBAL 0x0100
|
|
%define PAGE_2M_MBO 0x080
|
|
%define PAGE_2M_PAT 0x01000
|
|
|
|
%define PAGE_4K_PDE_ATTR (PAGE_ACCESSED + \
|
|
PAGE_DIRTY + \
|
|
PAGE_READ_WRITE + \
|
|
PAGE_PRESENT)
|
|
|
|
%define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \
|
|
PAGE_ACCESSED + \
|
|
PAGE_DIRTY + \
|
|
PAGE_READ_WRITE + \
|
|
PAGE_PRESENT)
|
|
|
|
%define PAGE_PDP_ATTR (PAGE_ACCESSED + \
|
|
PAGE_READ_WRITE + \
|
|
PAGE_PRESENT)
|
|
|
|
%define TDX_BSP 1
|
|
%define TDX_AP 2
|
|
|
|
;
|
|
; Modified: EAX, EBX, ECX, EDX
|
|
;
|
|
SetCr3ForPageTables64:
|
|
; Check the TDX features.
|
|
; If it is TDX APs, then jump to SetCr3 directly.
|
|
; In TD guest the initialization is done by BSP, including building
|
|
; the page tables. APs will spin on until byte[TDX_WORK_AREA_PGTBL_READY]
|
|
; is set.
|
|
OneTimeCall CheckTdxFeaturesBeforeBuildPagetables
|
|
cmp eax, TDX_BSP
|
|
je ClearOvmfPageTables
|
|
cmp eax, TDX_AP
|
|
je SetCr3
|
|
|
|
; Check whether the SEV is active and populate the SevEsWorkArea
|
|
OneTimeCall CheckSevFeatures
|
|
|
|
; If SEV is enabled, the C-bit position is always above 31.
|
|
; The mask will be saved in the EDX and applied during the
|
|
; the page table build below.
|
|
OneTimeCall GetSevCBitMaskAbove31
|
|
|
|
ClearOvmfPageTables:
|
|
;
|
|
; For OVMF, build some initial page tables at
|
|
; PcdOvmfSecPageTablesBase - (PcdOvmfSecPageTablesBase + 0x6000).
|
|
;
|
|
; This range should match with PcdOvmfSecPageTablesSize which is
|
|
; declared in the FDF files.
|
|
;
|
|
; At the end of PEI, the pages tables will be rebuilt into a
|
|
; more permanent location by DxeIpl.
|
|
;
|
|
|
|
mov ecx, 6 * 0x1000 / 4
|
|
xor eax, eax
|
|
clearPageTablesMemoryLoop:
|
|
mov dword[ecx * 4 + PT_ADDR (0) - 4], eax
|
|
loop clearPageTablesMemoryLoop
|
|
|
|
;
|
|
; Top level Page Directory Pointers (1 * 512GB entry)
|
|
;
|
|
mov dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDP_ATTR
|
|
mov dword[PT_ADDR (4)], edx
|
|
|
|
;
|
|
; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
|
|
;
|
|
mov dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDP_ATTR
|
|
mov dword[PT_ADDR (0x1004)], edx
|
|
mov dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDP_ATTR
|
|
mov dword[PT_ADDR (0x100C)], edx
|
|
mov dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDP_ATTR
|
|
mov dword[PT_ADDR (0x1014)], edx
|
|
mov dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDP_ATTR
|
|
mov dword[PT_ADDR (0x101C)], edx
|
|
|
|
;
|
|
; Page Table Entries (2048 * 2MB entries => 4GB)
|
|
;
|
|
mov ecx, 0x800
|
|
pageTableEntriesLoop:
|
|
mov eax, ecx
|
|
dec eax
|
|
shl eax, 21
|
|
add eax, PAGE_2M_PDE_ATTR
|
|
mov [ecx * 8 + PT_ADDR (0x2000 - 8)], eax
|
|
mov [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
|
|
loop pageTableEntriesLoop
|
|
|
|
; Clear the C-bit from the GHCB page if the SEV-ES is enabled.
|
|
OneTimeCall SevClearPageEncMaskForGhcbPage
|
|
|
|
; TDX will do some PostBuildPages task, such as setting
|
|
; byte[TDX_WORK_AREA_PGTBL_READY].
|
|
OneTimeCall TdxPostBuildPageTables
|
|
|
|
SetCr3:
|
|
;
|
|
; Set CR3 now that the paging structures are available
|
|
;
|
|
mov eax, PT_ADDR (0)
|
|
mov cr3, eax
|
|
|
|
OneTimeCallRet SetCr3ForPageTables64
|