According to TDX Architecture Specification, 9.8 Interrupt Handling and APIC Virtualization: 1. Guest TDs must use virtualized x2APIC mode. xAPIC mode(using memory mapped APIC access) is not allowed. 2. Guest TDs attempts to RDMSR or WRMSR the IA32_APIC_BASE MSR cause a VE to the guest TD. The guest TD cannot disable the APIC. Bypass xAPIC initialization and enable x2APIC directly. Set software enable bit in x2APIC initializaion. Use uid/apicid mapping to get apicid in setup_tss(). Initially I enabled x2APIC early so apic_id() could be used. But that brings issue for multiprocessor support as reading APIC_ID in AP triggers #VE and require gdt/tss/idt to be initialized early, so setup_gdt_tss() early. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxx> Reviewed-by: Yu Zhang <yu.c.zhang@xxxxxxxxx> --- lib/x86/apic.c | 4 ++++ lib/x86/setup.c | 10 +++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/x86/apic.c b/lib/x86/apic.c index da8f30134b22..84bfe98c58ff 100644 --- a/lib/x86/apic.c +++ b/lib/x86/apic.c @@ -147,6 +147,10 @@ int enable_x2apic(void) asm ("rdmsr" : "=a"(a), "=d"(d) : "c"(MSR_IA32_APICBASE)); a |= 1 << 10; asm ("wrmsr" : : "a"(a), "d"(d), "c"(MSR_IA32_APICBASE)); + + /* software APIC enabled bit is cleared after reset in TD-guest */ + x2apic_write(APIC_SPIV, 0x1ff); + apic_ops = &x2apic_ops; return 1; } else { diff --git a/lib/x86/setup.c b/lib/x86/setup.c index fbcd188ebb8f..e834fdfd290c 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -108,8 +108,9 @@ unsigned long setup_tss(u8 *stacktop) { u32 id; tss64_t *tss_entry; + static u32 cpus = 0; - id = apic_id(); + id = is_tdx_guest() ? id_map[cpus++] : apic_id(); /* Runtime address of current TSS */ tss_entry = &tss[id]; @@ -327,12 +328,15 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo) return status; } - reset_apic(); + /* xAPIC mode isn't allowed in TDX */ + if (!is_tdx_guest()) + reset_apic(); setup_gdt_tss(); setup_idt(); load_idt(); mask_pic_interrupts(); - enable_apic(); + if (!is_tdx_guest()) + enable_apic(); enable_x2apic(); smp_init(); setup_page_table(); -- 2.25.1