diff --git a/lib/x86/asm/setup.h b/lib/x86/asm/setup.h
index c467a2e94861..5e7aa2eb4332 100644
--- a/lib/x86/asm/setup.h
+++ b/lib/x86/asm/setup.h
@@ -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"
 
diff --git a/lib/x86/setup.c b/lib/x86/setup.c
index 63c4dbb25064..7bf5d431f2a8 100644
--- a/lib/x86/setup.c
+++ b/lib/x86/setup.c
@@ -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();
 
diff --git a/lib/x86/tdx.c b/lib/x86/tdx.c
index b74c697353d9..4bd658b95028 100644
--- a/lib/x86/tdx.c
+++ b/lib/x86/tdx.c
@@ -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);
+}
diff --git a/lib/x86/tdx.h b/lib/x86/tdx.h
index 2f938038dc45..4b75fcec7367 100644
--- a/lib/x86/tdx.h
+++ b/lib/x86/tdx.h
@@ -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,
diff --git a/x86/efi/crt0-efi-x86_64.S b/x86/efi/crt0-efi-x86_64.S
index eaf165649591..f3309f6e35ef 100644
--- a/x86/efi/crt0-efi-x86_64.S
+++ b/x86/efi/crt0-efi-x86_64.S
@@ -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
diff --git a/x86/efi/efistart64.S b/x86/efi/efistart64.S
index 017abba85a68..648d047febb5 100644
--- a/x86/efi/efistart64.S
+++ b/x86/efi/efistart64.S
@@ -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
