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