The BSP starts APs with a broadcast INIT/STARTUP IPI, so every exposed AP
runs this code, including the ones the kernel rejected. Rejected APIC
IDs are -1 in cpu_id_lut; test the lookup and park before using it to
index percpu_array or the per-CPU GDT.
---
i386/i386/cpuboot.S | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/i386/i386/cpuboot.S b/i386/i386/cpuboot.S
index fd3d632..68c4b79 100644
--- a/i386/i386/cpuboot.S
+++ b/i386/i386/cpuboot.S
@@ -168,6 +168,12 @@ apboot32:
andb %cs:apic_id_mask, %bl
movl %cs:CX(cpu_id_lut, %ebx), %ebp
+ /* Park APs the kernel did not accept (cpu_id_lut == -1). */
+ testl %ebp, %ebp
+ js apboot_park
+ cmpl $NCPUS, %ebp
+ jae apboot_park
+
/* Copy first gdt descriptor and gdt to cpu-th area */
movl $(GDT_DESCR_M32 + GDT_TABLE_M32), %ecx
movl $apboot_gdt_top, %esi
@@ -276,5 +282,12 @@ apboot_jmp_offset:
.long RELOC(apboot32)
.word BOOT_CS
+.align 16
+apboot_park:
+ cli
+apboot_park_loop:
+ hlt
+ jmp apboot_park_loop
+
apbootend:
#endif