blob: 62474fde398c3a5c8bcdc663d97ab126feb9f65f [file] [log] [blame]
;------------------------------------------------------------------------------ ;
; Copyright (c) 2025, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Module Name:
;
; ApRunLoop.nasm
;
; Abstract:
;
; This is the assembly code for run loop for APs in the guest TD
;
;-------------------------------------------------------------------------------
%include "TdxCommondefs.inc"
DEFAULT REL
SECTION .bss
global STACK_BASE
STACK_BASE:
resb 1024
STACK_TOP:
SECTION .text
%define TDX_WORK_AREA_MAILBOX_GDTR (FixedPcdGet32 (PcdOvmfWorkAreaBase) + 128)
%define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (Offset))
%define TDX_WORK_AREA_PGTBL_READY (FixedPcdGet32 (PcdOvmfWorkAreaBase) + 4)
%define PG_5_LEVEL (FixedPcdGetBool (PcdUse5LevelPageTable))
%define TDX_BSP 1
%define TDX_AP 2
%define TDX_AP_5_LEVEL 3
BITS 64
%define TDVMCALL_EXPOSE_REGS_MASK 0xffc4
%define TDVMCALL 0x0
%define EXIT_REASON_CPUID 0xa
; Defined in ACPI 6.6 section 5.2.12.19 MultiProcessor Wakeup Mailbox Command.
%define MULTIPROCESSOR_WAKEUP_MAILBOX_COMMAND_NOOP 0
%define MULTIPROCESSOR_WAKEUP_MAILBOX_COMMAND_WAKEUP 1
%define MULTIPROCESSOR_WAKEUP_MAILBOX_COMMAND_TEST 2
%macro tdcall 0
db 0x66, 0x0f, 0x01, 0xcc
%endmacro
%macro tdcall_regs_preamble 2
mov rax, %1
xor rcx, rcx
mov ecx, %2
; R10 = 0 (standard TDVMCALL)
xor r10d, r10d
; Zero out unused (for standard TDVMCALL) registers to avoid leaking
; secrets to the VMM.
xor esi, esi
xor edi, edi
xor edx, edx
xor ebp, ebp
xor r8d, r8d
xor r9d, r9d
xor r14, r14
xor r15, r15
%endmacro
;
; Relocated Ap Mailbox loop
;
; @param[in] RBX: Relocated mailbox address
; @param[in] RBP: vCpuId
;
; @return None This routine does not return
;
global ASM_PFX(AsmRelocateApMailBoxLoop)
ASM_PFX(AsmRelocateApMailBoxLoop):
AsmRelocateApMailBoxLoopStart:
mov r11, EXIT_REASON_CPUID
mov r12, 0xb
tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK
tdcall
test r10, r10
jnz Panic
mov r8, r15
mov qword[rel mailbox_address], rbx
MailBoxLoop:
; Spin until command set
cmp dword [rbx + CommandOffset], MULTIPROCESSOR_WAKEUP_MAILBOX_COMMAND_NOOP
je MailBoxLoop
; Determine if this is a broadcast or directly for my apic-id, if not, ignore
cmp dword [rbx + ApicidOffset], MailboxApicidBroadcast
je MailBoxProcessCommand
cmp dword [rbx + ApicidOffset], r8d
jne MailBoxLoop
MailBoxProcessCommand:
cmp dword [rbx + CommandOffset], MULTIPROCESSOR_WAKEUP_MAILBOX_COMMAND_WAKEUP
je MailBoxWakeUp
cmp dword [rbx + CommandOffset], MULTIPROCESSOR_WAKEUP_MAILBOX_COMMAND_TEST
je MailBoxTest
; Don't support this command, so ignore
jmp MailBoxLoop
MailBoxWakeUp:
mov rax, [rbx + WakeupVectorOffset]
; OS sends a wakeup command for a given APIC ID, firmware is supposed to reset
; the command field back to zero as acknowledgement.
mov qword [rbx + CommandOffset], 0
jmp rax
MailBoxTest:
mov qword [rbx + CommandOffset], 0
jmp MailBoxLoop
Panic:
ud2
AsmRelocateApResetVector:
.prepareStack:
; The stack can then be used to switch from long mode to compatibility mode
mov rsp, STACK_TOP
.loadGDT:
cli
mov rax, TDX_WORK_AREA_MAILBOX_GDTR
lgdt [rax]
.loadSwicthModeCode:
mov rcx, dword 0x10 ; load long mode selector
shl rcx, 32
lea rdx, [LongMode] ; assume address < 4G
or rcx, rdx
push rcx
mov rcx, dword 0x08 ; load compatible mode selector
shl rcx, 32
lea rdx, [Compatible] ; assume address < 4G
or rcx, rdx
push rcx
retf
BITS 32
Compatible:
mov eax, dword 0x18
; ; reload DS/ES/SS to make sure they are correct referred to current GDT
mov ds, ax
mov es, ax
mov ss, ax
; reload the fs and gs
mov fs, ax
mov gs, ax
; Must clear the CR4.PCIDE before clearing paging
mov ecx, cr4
btc ecx, 17
mov cr4, ecx
;
; Disable paging
;
mov ecx, cr0
btc ecx, 31
mov cr0, ecx
;
RestoreCr0:
; Only enable PE(bit 0), NE(bit 5), ET(bit 4) 0x31
mov eax, dword 0x31
mov cr0, eax
; Only Enable MCE(bit 6), VMXE(bit 13) 0x2040
; TDX enforeced the VMXE = 1 and mask it in VMM, so not set it.
RestoreCr4:
mov eax, 0x40
mov cr4, eax
%if PG_5_LEVEL
mov al, byte[TDX_WORK_AREA_PGTBL_READY]
inc eax
cmp eax, TDX_AP_5_LEVEL
jne SetCr3
SetCr4La57:
; set la57 bit in cr4
mov eax, cr4
bts eax, 12
mov cr4, eax
%endif
SetCr3:
;
; Can use the boot page tables since it's reserved
mov eax, PT_ADDR (0)
mov cr3, eax
EnablePAE:
mov eax, cr4
bts eax, 5
mov cr4, eax
EnablePaging:
mov eax, cr0
bts eax, 31 ; set PG
mov cr0, eax ; enable paging
; return to LongMode
retf
BITS 64
LongMode:
mov rbx, qword[rel mailbox_address]
jmp AsmRelocateApMailBoxLoopStart
align 16
mailbox_address:
dq 0
BITS 64
AsmRelocateApMailBoxLoopEnd:
;-------------------------------------------------------------------------------------
; AsmGetRelocationMap (&RelocationMap);
;-------------------------------------------------------------------------------------
global ASM_PFX(AsmGetRelocationMap)
ASM_PFX(AsmGetRelocationMap):
; mov byte[TDX_WORK_AREA_MB_PGTBL_READY], 0
lea rax, [AsmRelocateApMailBoxLoopStart]
mov qword [rcx], rax
mov qword [rcx + 8h], AsmRelocateApMailBoxLoopEnd - AsmRelocateApMailBoxLoopStart
lea rax, [AsmRelocateApResetVector]
mov qword [rcx + 10h], rax
ret