summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/ResetVector/Ia32/IntelTdx.asm
diff options
context:
space:
mode:
Diffstat (limited to 'OvmfPkg/ResetVector/Ia32/IntelTdx.asm')
-rw-r--r--OvmfPkg/ResetVector/Ia32/IntelTdx.asm222
1 files changed, 222 insertions, 0 deletions
diff --git a/OvmfPkg/ResetVector/Ia32/IntelTdx.asm b/OvmfPkg/ResetVector/Ia32/IntelTdx.asm
new file mode 100644
index 0000000000..06794baef8
--- /dev/null
+++ b/OvmfPkg/ResetVector/Ia32/IntelTdx.asm
@@ -0,0 +1,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