:: commit 9456dcb1d96a9628e090eaa62396782cb5389e4d

Mintsuki <mintsuki@protonmail.com> — 2026-02-23 14:39

parents: 37eddc6ddb

sys/smp: Add xAPIC ICR delivery status checks to INIT-SIPI-SIPI sequence

diff --git a/common/sys/lapic.c b/common/sys/lapic.c
index 5579a00f..ddaa7f10 100644
--- a/common/sys/lapic.c
+++ b/common/sys/lapic.c
@@ -242,6 +242,15 @@ void lapic_write(uint32_t reg, uint32_t data) {
     mmoutd(lapic_mmio_base + reg, data);
 }
 
+void lapic_icr_wait(void) {
+    for (int i = 0; i < 1000000; i++) {
+        if (!(lapic_read(LAPIC_REG_ICR0) & (1 << 12))) {
+            return;
+        }
+        asm volatile ("pause");
+    }
+}
+
 bool x2apic_check(void) {
     uint32_t eax, ebx, ecx, edx;
     if (!cpuid(1, 0, &eax, &ebx, &ecx, &edx))
diff --git a/common/sys/lapic.h b/common/sys/lapic.h
index 02bf49f4..9edcfd69 100644
--- a/common/sys/lapic.h
+++ b/common/sys/lapic.h
@@ -17,6 +17,7 @@ bool lapic_check(void);
 void lapic_eoi(void);
 uint32_t lapic_read(uint32_t reg);
 void lapic_write(uint32_t reg, uint32_t data);
+void lapic_icr_wait(void);
 
 bool x2apic_check(void);
 bool x2apic_enable(void);
diff --git a/common/sys/smp.c b/common/sys/smp.c
index 30d71a7d..4ecc3049 100644
--- a/common/sys/smp.c
+++ b/common/sys/smp.c
@@ -84,6 +84,7 @@ static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
     if (x2apic) {
         x2apic_write(LAPIC_REG_ICR0, ((uint64_t)lapic_id << 32) | 0x4500);
     } else {
+        lapic_icr_wait();
         lapic_write(LAPIC_REG_ICR1, lapic_id << 24);
         lapic_write(LAPIC_REG_ICR0, 0x4500);
     }
@@ -95,10 +96,17 @@ static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
             x2apic_write(LAPIC_REG_ICR0, ((uint64_t)lapic_id << 32) |
                                          ((size_t)trampoline / 4096) | 0x4600);
         } else {
+            lapic_icr_wait();
             lapic_write(LAPIC_REG_ICR1, lapic_id << 24);
             lapic_write(LAPIC_REG_ICR0, ((size_t)trampoline / 4096) | 0x4600);
         }
-        stall(200);
+        if (j == 0) {
+            stall(200);
+        }
+    }
+
+    if (!x2apic) {
+        lapic_icr_wait();
     }
 
     for (int i = 0; i < 100; i++) {
tab: 248 wrap: offon