Skip to content

Commit 2ebf5ca

Browse files
committed
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>
1 parent 7218122 commit 2ebf5ca

6 files changed

Lines changed: 286 additions & 0 deletions

File tree

OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,30 @@ resetVector:
177177
;
178178
; This is where the processor will begin execution
179179
;
180+
; In IA32 we follow the standard reset vector flow. While in X64, Td guest
181+
; may be supported. Td guest requires the startup mode to be 32-bit
182+
; protected mode but the legacy VM startup mode is 16-bit real mode.
183+
; To make NASM generate such shared entry code that behaves correctly in
184+
; both 16-bit and 32-bit mode, more BITS directives are added.
185+
;
186+
%ifdef ARCH_IA32
180187
nop
181188
nop
182189
jmp EarlyBspInitReal16
183190

191+
%else
192+
193+
mov eax, cr0
194+
test al, 1
195+
jz .Real
196+
BITS 32
197+
jmp Main32
198+
BITS 16
199+
.Real:
200+
jmp EarlyBspInitReal16
201+
202+
%endif
203+
184204
ALIGN 16
185205

186206
fourGigabytes:

OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ Transition32FlatTo64Flat:
2121
bts eax, 5 ; enable PAE
2222
mov cr4, eax
2323

24+
;
25+
; In TDX LME has already been set. So we're done and jump to enable
26+
; paging directly if Tdx is enabled.
27+
; EBX is cleared because in the later it will be used to check if
28+
; the second step of the SEV-ES mitigation is to be performed.
29+
;
30+
xor ebx, ebx
31+
OneTimeCall IsTdxEnabled
32+
test eax, eax
33+
jnz EnablePaging
34+
2435
mov ecx, 0xc0000080
2536
rdmsr
2637
bts eax, 8 ; set LME
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
;------------------------------------------------------------------------------
2+
; @file
3+
; Intel TDX routines
4+
;
5+
; Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
6+
; SPDX-License-Identifier: BSD-2-Clause-Patent
7+
;
8+
;------------------------------------------------------------------------------
9+
10+
%define VM_GUEST_TDX 2
11+
12+
BITS 32
13+
14+
;
15+
; Check if it is Intel Tdx
16+
;
17+
; Modified: EAX, EBX, ECX, EDX
18+
;
19+
; If it is Intel Tdx, EAX is 1
20+
; If it is not Intel Tdx, EAX is 0
21+
;
22+
IsTdx:
23+
;
24+
; CPUID (0)
25+
;
26+
mov eax, 0
27+
cpuid
28+
cmp ebx, 0x756e6547 ; "Genu"
29+
jne IsNotTdx
30+
cmp edx, 0x49656e69 ; "ineI"
31+
jne IsNotTdx
32+
cmp ecx, 0x6c65746e ; "ntel"
33+
jne IsNotTdx
34+
35+
;
36+
; CPUID (1)
37+
;
38+
mov eax, 1
39+
cpuid
40+
test ecx, 0x80000000
41+
jz IsNotTdx
42+
43+
;
44+
; CPUID[0].EAX >= 0x21?
45+
;
46+
mov eax, 0
47+
cpuid
48+
cmp eax, 0x21
49+
jl IsNotTdx
50+
51+
;
52+
; CPUID (0x21,0)
53+
;
54+
mov eax, 0x21
55+
mov ecx, 0
56+
cpuid
57+
58+
cmp ebx, 0x65746E49 ; "Inte"
59+
jne IsNotTdx
60+
cmp edx, 0x5844546C ; "lTDX"
61+
jne IsNotTdx
62+
cmp ecx, 0x20202020 ; " "
63+
jne IsNotTdx
64+
65+
mov eax, 1
66+
jmp ExitIsTdx
67+
68+
IsNotTdx:
69+
xor eax, eax
70+
71+
ExitIsTdx:
72+
73+
OneTimeCallRet IsTdx
74+
75+
;
76+
; Initialize work area if it is Tdx guest. Detailed definition is in
77+
; OvmfPkg/Include/WorkArea.h.
78+
; BSP and APs all go here. Only BSP initialize this work area.
79+
;
80+
; Param[in] EBX[5:0] CPU Supported GPAW (48 or 52)
81+
; Param[in] ESI[31:0] vCPU ID (BSP is 0, others are AP)
82+
;
83+
; Modified: EBX
84+
;
85+
InitTdxWorkarea:
86+
87+
;
88+
; First check if it is Tdx
89+
;
90+
OneTimeCall IsTdx
91+
92+
test eax, eax
93+
jz ExitInitTdxWorkarea
94+
95+
cmp esi, 0
96+
je TdxBspEntry
97+
98+
;
99+
; In Td guest, BSP/AP shares the same entry point
100+
; BSP builds up the page table, while APs shouldn't do the same task.
101+
; Instead, APs just leverage the page table which is built by BSP.
102+
; APs will wait until the page table is ready.
103+
;
104+
TdxApWait:
105+
cmp byte[TDX_WORK_AREA_PGTBL_READY], 0
106+
je TdxApWait
107+
jmp ExitInitTdxWorkarea
108+
109+
TdxBspEntry:
110+
;
111+
; Set Type of WORK_AREA_GUEST_TYPE so that the following code can use
112+
; these information.
113+
;
114+
mov byte[WORK_AREA_GUEST_TYPE], VM_GUEST_TDX
115+
116+
;
117+
; EBX[5:0] CPU supported GPA width
118+
;
119+
and ebx, 0x3f
120+
mov DWORD[TDX_WORK_AREA_GPAW], ebx
121+
122+
ExitInitTdxWorkarea:
123+
OneTimeCallRet InitTdxWorkarea
124+
125+
;
126+
; Load the GDT and set the CS/DS/ES/FS/GS/SS.
127+
;
128+
; Modified: EAX, DS, ES, FS, GS, SS, CS
129+
;
130+
ReloadFlat32:
131+
132+
cli
133+
mov eax, ADDR_OF(gdtr)
134+
lgdt [eax]
135+
136+
jmp LINEAR_CODE_SEL:dword ADDR_OF(jumpToFlat32BitAndLandHere)
137+
138+
jumpToFlat32BitAndLandHere:
139+
140+
debugShowPostCode POSTCODE_32BIT_MODE
141+
142+
mov ax, LINEAR_SEL
143+
mov ds, ax
144+
mov es, ax
145+
mov fs, ax
146+
mov gs, ax
147+
mov ss, ax
148+
149+
OneTimeCallRet ReloadFlat32
150+
151+
;
152+
; Tdx initialization after entering into ResetVector
153+
;
154+
; Modified: EAX, EBX, ECX, EDX, EBP, EDI, ESP
155+
;
156+
InitTdx:
157+
;
158+
; First load the GDT and jump to Flat32 mode
159+
;
160+
OneTimeCall ReloadFlat32
161+
162+
;
163+
; Initialization of Tdx work area
164+
;
165+
OneTimeCall InitTdxWorkarea
166+
167+
OneTimeCallRet InitTdx
168+
169+
;
170+
; Check TDX features, TDX or TDX-BSP or TDX-APs?
171+
;
172+
; By design TDX BSP is reponsible for initializing the PageTables.
173+
; After PageTables are ready, byte[TDX_WORK_AREA_PGTBL_READY] is set to 1.
174+
; APs will spin when byte[TDX_WORK_AREA_PGTBL_READY] is 0 until it is set to 1.
175+
;
176+
; When this routine is run on TDX BSP, byte[TDX_WORK_AREA_PGTBL_READY] should be 0.
177+
; When this routine is run on TDX APs, byte[TDX_WORK_AREA_PGTBL_READY] should be 1.
178+
;
179+
;
180+
; Modified: EAX, EDX
181+
;
182+
; 0-NonTdx, 1-TdxBsp, 2-TdxAps
183+
;
184+
CheckTdxFeaturesBeforeBuildPagetables:
185+
xor eax, eax
186+
cmp byte[WORK_AREA_GUEST_TYPE], VM_GUEST_TDX
187+
jne NotTdx
188+
189+
xor edx, edx
190+
mov al, byte[TDX_WORK_AREA_PGTBL_READY]
191+
inc eax
192+
193+
NotTdx:
194+
OneTimeCallRet CheckTdxFeaturesBeforeBuildPagetables
195+
196+
;
197+
; Set byte[TDX_WORK_AREA_PGTBL_READY] to 1
198+
;
199+
TdxPostBuildPageTables:
200+
cmp byte[WORK_AREA_GUEST_TYPE], VM_GUEST_TDX
201+
jne ExitTdxPostBuildPageTables
202+
mov byte[TDX_WORK_AREA_PGTBL_READY], 1
203+
204+
ExitTdxPostBuildPageTables:
205+
OneTimeCallRet TdxPostBuildPageTables
206+
207+
;
208+
; Check if TDX is enabled
209+
;
210+
; Modified: EAX
211+
;
212+
; If TDX is enabled then EAX will be 1
213+
; If TDX is disabled then EAX will be 0.
214+
;
215+
IsTdxEnabled:
216+
xor eax, eax
217+
cmp byte[WORK_AREA_GUEST_TYPE], VM_GUEST_TDX
218+
jne TdxNotEnabled
219+
mov eax, 1
220+
221+
TdxNotEnabled:
222+
OneTimeCallRet IsTdxEnabled

OvmfPkg/ResetVector/Ia32/PageTables64.asm

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,23 @@ BITS 32
3737
PAGE_READ_WRITE + \
3838
PAGE_PRESENT)
3939

40+
%define TDX_BSP 1
41+
%define TDX_AP 2
42+
4043
;
4144
; Modified: EAX, EBX, ECX, EDX
4245
;
4346
SetCr3ForPageTables64:
47+
; Check the TDX features.
48+
; If it is TDX APs, then jump to SetCr3 directly.
49+
; In TD guest the initialization is done by BSP, including building
50+
; the page tables. APs will spin on until byte[TDX_WORK_AREA_PGTBL_READY]
51+
; is set.
52+
OneTimeCall CheckTdxFeaturesBeforeBuildPagetables
53+
cmp eax, TDX_BSP
54+
je ClearOvmfPageTables
55+
cmp eax, TDX_AP
56+
je SetCr3
4457

4558
; Check whether the SEV is active and populate the SevEsWorkArea
4659
OneTimeCall CheckSevFeatures
@@ -50,6 +63,7 @@ SetCr3ForPageTables64:
5063
; the page table build below.
5164
OneTimeCall GetSevCBitMaskAbove31
5265

66+
ClearOvmfPageTables:
5367
;
5468
; For OVMF, build some initial page tables at
5569
; PcdOvmfSecPageTablesBase - (PcdOvmfSecPageTablesBase + 0x6000).
@@ -101,6 +115,10 @@ pageTableEntriesLoop:
101115
; Clear the C-bit from the GHCB page if the SEV-ES is enabled.
102116
OneTimeCall SevClearPageEncMaskForGhcbPage
103117

118+
; TDX will do some PostBuildPages task, such as setting
119+
; byte[TDX_WORK_AREA_PGTBL_READY].
120+
OneTimeCall TdxPostBuildPageTables
121+
104122
SetCr3:
105123
;
106124
; Set CR3 now that the paging structures are available

OvmfPkg/ResetVector/Main.asm

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,20 @@ BITS 32
4040
; work area when detected.
4141
mov byte[WORK_AREA_GUEST_TYPE], 0
4242

43+
%ifdef ARCH_X64
44+
45+
jmp SearchBfv
46+
47+
;
48+
; Entry point of Main32
49+
;
50+
Main32:
51+
OneTimeCall InitTdx
52+
53+
SearchBfv:
54+
55+
%endif
56+
4357
;
4458
; Search for the Boot Firmware Volume (BFV)
4559
;

OvmfPkg/ResetVector/ResetVector.nasmb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
%include "Ia32/Flat32ToFlat64.asm"
109109
%include "Ia32/AmdSev.asm"
110110
%include "Ia32/PageTables64.asm"
111+
%include "Ia32/IntelTdx.asm"
111112
%endif
112113

113114
%include "Ia16/Real16ToFlat32.asm"

0 commit comments

Comments
 (0)