In TDX, Application Processor busy-loops on Mailbox for OS to issue
MpProtectedModeWakeupCommandWakeup command to UEFI. As the AP acking to
it, it clears the command member according to ACPI spec 6.4, 5.2.12.19
Multiprocessor Wakeup Structure: "The application processor need clear the
command to Noop(0) as the acknowledgement that the command is received."
However, AsmRelocateApMailBoxLoop wrongly clears WakeupVector. Correctly
clear command instead of WakeupVector.
Without this patch, TD guest kernel fails to boot APs.
Fixes: fae5c1464d
("OvmfPkg: Add TdxDxe driver")
Cc: Min Xu <min.m.xu@intel.com>
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Min Xu <min.m.xu@intel.com>
91 lines
2.7 KiB
NASM
91 lines
2.7 KiB
NASM
;------------------------------------------------------------------------------ ;
|
|
; Copyright (c) 2021, 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 .text
|
|
|
|
BITS 64
|
|
|
|
%define TDVMCALL_EXPOSE_REGS_MASK 0xffec
|
|
%define TDVMCALL 0x0
|
|
%define EXIT_REASON_CPUID 0xa
|
|
|
|
%macro tdcall 0
|
|
db 0x66, 0x0f, 0x01, 0xcc
|
|
%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 rax, TDVMCALL
|
|
mov rcx, TDVMCALL_EXPOSE_REGS_MASK
|
|
mov r11, EXIT_REASON_CPUID
|
|
mov r12, 0xb
|
|
tdcall
|
|
test rax, rax
|
|
jnz Panic
|
|
mov r8, r15
|
|
|
|
MailBoxLoop:
|
|
; Spin until command set
|
|
cmp dword [rbx + CommandOffset], MpProtectedModeWakeupCommandNoop
|
|
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], MpProtectedModeWakeupCommandWakeup
|
|
je MailBoxWakeUp
|
|
cmp dword [rbx + CommandOffset], MpProtectedModeWakeupCommandSleep
|
|
je MailBoxSleep
|
|
; 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
|
|
MailBoxSleep:
|
|
jmp $
|
|
Panic:
|
|
ud2
|
|
BITS 64
|
|
AsmRelocateApMailBoxLoopEnd:
|
|
|
|
;-------------------------------------------------------------------------------------
|
|
; AsmGetRelocationMap (&RelocationMap);
|
|
;-------------------------------------------------------------------------------------
|
|
global ASM_PFX(AsmGetRelocationMap)
|
|
ASM_PFX(AsmGetRelocationMap):
|
|
lea rax, [ASM_PFX(AsmRelocateApMailBoxLoopStart)]
|
|
mov qword [rcx], rax
|
|
mov qword [rcx + 8h], AsmRelocateApMailBoxLoopEnd - AsmRelocateApMailBoxLoopStart
|
|
ret
|
|
|