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 | 12 ++++++++++++
x86_64/cpuboot.S | 17 +++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/i386/i386/cpuboot.S b/i386/i386/cpuboot.S
index fd3d6323..747a9407 100644
--- a/i386/i386/cpuboot.S
+++ b/i386/i386/cpuboot.S
@@ -168,6 +168,11 @@ apboot32:
andb %cs:apic_id_mask, %bl
movl %cs:CX(cpu_id_lut, %ebx), %ebp
+ 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 +281,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
diff --git a/x86_64/cpuboot.S b/x86_64/cpuboot.S
index b927c73c..64390ad2 100644
--- a/x86_64/cpuboot.S
+++ b/x86_64/cpuboot.S
@@ -216,6 +216,11 @@ switch64:
movq $cpu_id_lut, %rdi
movl %cs:(%rdi, %rbx, 4), %ebp
+ testl %ebp, %ebp
+ js apboot_park
+ cmpl $NCPUS, %ebp
+ jae apboot_park
+
/* set up mini stack to do far return */
movq $EXT(int_stack_top), %rdi
movq (%rdi, %rbp, 8), %rsp
@@ -244,6 +249,11 @@ start64:
movq $cpu_id_lut, %rdi
movl %cs:(%rdi, %rbx, 4), %ebp
+ testl %ebp, %ebp
+ js apboot_park
+ cmpl $NCPUS, %ebp
+ jae apboot_park
+
/* Access per_cpu area */
movq %rbp, %rax
movq $PC_SIZE,%rbx
@@ -325,6 +335,13 @@ apboot_jmp_offset:
.long RELOC(apboot32)
.word BOOT_CS
+.align 16
+apboot_park:
+ cli
+apboot_park_loop:
+ hlt
+ jmp apboot_park_loop
+
apbootend:
.section .boot.data,"ax",@progbits