@@ -14,6 +14,7 @@ unsigned long setup_tss(u8 *stacktop);
efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo);
void setup_5level_page_table(void);
+void secondary_startup_64(void);
#endif /* TARGET_EFI */
#include "x86/tdx.h"
@@ -279,6 +279,35 @@ static void setup_gdt_tss(void)
load_gdt_tss(tss_offset);
}
+static void setup_percpu_area(void)
+{
+ u64 rsp;
+
+ asm volatile ("mov %%rsp, %0" : "=m"(rsp) :: "memory");
+
+ /* per cpu stack size is PAGE_SIZE */
+ rsp &= ~((u64)PAGE_SIZE - 1);
+ wrmsr(MSR_GS_BASE, rsp);
+}
+
+void secondary_startup_64(void)
+{
+ setup_gdt_tss();
+ load_idt();
+ setup_percpu_area();
+ enable_x2apic();
+ tdx_ap_init();
+
+ while (1)
+ safe_halt();
+}
+
+static void aps_init(void)
+{
+ if (is_tdx_guest())
+ tdx_aps_init();
+}
+
efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
{
efi_status_t status;
@@ -332,6 +361,7 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
return status;
}
+ setup_percpu_area();
/* xAPIC mode isn't allowed in TDX */
if (!is_tdx_guest())
reset_apic();
@@ -342,6 +372,7 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
if (!is_tdx_guest())
enable_apic();
enable_x2apic();
+ aps_init();
smp_init();
setup_page_table();
@@ -12,9 +12,14 @@
#include "tdx.h"
#include "errno.h"
#include "bitops.h"
+#include "atomic.h"
+#include "fwcfg.h"
+#include "x86/acpi.h"
#include "x86/processor.h"
#include "x86/smp.h"
+#include "x86/apic.h"
#include "asm/page.h"
+#include "asm/barrier.h"
#define VE_IS_IO_OUT(exit_qual) (((exit_qual) & 8) ? 0 : 1)
#define VE_GET_IO_SIZE(exit_qual) (((exit_qual) & 7) + 1)
@@ -541,3 +546,31 @@ efi_status_t setup_tdx(efi_bootinfo_t *efi_bootinfo)
return EFI_SUCCESS;
}
+
+static atomic_t cpu_online_count = {1};
+extern unsigned char online_cpus[(MAX_TEST_CPUS + 7) / 8];
+extern void ap_start64(void);
+
+/* TDX uses ACPI WAKE UP mechanism to wake up APs instead of SIPI */
+efi_status_t tdx_aps_init(void)
+{
+ u32 i, total_cpus = fwcfg_get_nb_cpus();
+
+ /* BSP is already online */
+ set_bit(id_map[0], online_cpus);
+
+ for (i = 1; i < total_cpus; i++) {
+ if (acpi_wakeup_cpu(id_map[i], (u64)ap_start64))
+ return EFI_DEVICE_ERROR;
+ }
+
+ while (atomic_read(&cpu_online_count) != total_cpus)
+ cpu_relax();
+
+ return EFI_SUCCESS;
+}
+
+void tdx_ap_init(void)
+{
+ atomic_inc(&cpu_online_count);
+}
@@ -96,6 +96,8 @@ int tdx_hcall_gpa_intent(phys_addr_t start, phys_addr_t end,
enum tdx_map_type map_type);
bool tdx_accept_memory(phys_addr_t start, phys_addr_t end);
efi_status_t setup_tdx(efi_bootinfo_t *efi_bootinfo);
+efi_status_t tdx_aps_init(void);
+void tdx_ap_init(void);
/* Helper function used to communicate with the TDX module */
u64 __tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
@@ -41,6 +41,8 @@
.globl _start
_start:
+ lea stacktop(%rip), %rsp
+ add %rsp, smp_stacktop(%rip)
subq $8, %rsp
pushq %rcx
pushq %rdx
@@ -61,12 +63,20 @@ _start:
call efi_main
addq $8, %rsp
+ .globl ap_start64
+ap_start64:
+ mov $-PAGE_SIZE, %rsp
+ lock xadd %rsp, smp_stacktop(%rip)
+ call secondary_startup_64
+
.exit:
ret
+ .data
+smp_stacktop: .quad -PAGE_SIZE
+
// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:
- .data
dummy: .long 0
#define IMAGE_REL_ABSOLUTE 0
@@ -22,6 +22,11 @@ ptl4:
. = . + PAGE_SIZE
.align PAGE_SIZE
+.globl stacktop
+ . = . + PAGE_SIZE * MAX_TEST_CPUS
+stacktop:
+.align PAGE_SIZE
+
.section .init
.code64
.text