Create a separate control flow for TDX BSP. TdxPostBuildPageTables will now only be called when running in TDX mode, so the TDX check in that function is not needed any more. No functional change. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20240301074402.98625-5-kraxel@redhat.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Oliver Steffen <osteffen@redhat.com> Cc: Michael Roth <michael.roth@amd.com> Cc: Erdem Aktas <erdemaktas@google.com> Cc: Min Xu <min.m.xu@intel.com> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Tom Lendacky <thomas.lendacky@amd.com> [lersek@redhat.com: turn the "Cc:" message headers from Gerd's on-list posting into "Cc:" tags in the commit message, in order to pacify "PatchCheck.py"]
219 lines
4.7 KiB
NASM
219 lines
4.7 KiB
NASM
;------------------------------------------------------------------------------
|
|
; @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:
|
|
mov byte[TDX_WORK_AREA_PGTBL_READY], 1
|
|
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
|