Files
RedBear-OS/local/patches/kernel/P15-1-ap-cpu-id-race.patch
T
vasilito 45e086558e fix: boot process improvements — dependency cycle, INIT_NOTIFY, probing loop, and log spam fixes
- Fix P15-8-init-cycle-detection.patch: replace visiting+error with seen+silent-skip
  to eliminate 11 false-positive 'dependency cycle detected' errors on shared deps
- Fix P0-daemon-fix-init-notify-unwrap.patch: remove eprintln! for missing
  INIT_NOTIFY (expected for oneshot_async services, ~7 daemons affected)
- Fix driver-manager hotplug loop: add PERMANENTLY_SKIPPED static set shared
  between hotplug handler and DriverConfig::probe() to stop infinite re-probing
  of Fatal/NotSupported/deferred-exhausted device+driver pairs (e.g. ided)
- Fix driver-manager log_timeline: suppress repeated EPIPE/ENOENT errors with
  AtomicI32 dedup and AtomicBool one-shot guards for boot timeline JSON
- Add driver-manager SIGTERM handler, ACPI bus registration, --status mode,
  driver reap loop, graceful shutdown, and reduced deferred retries (30→3)
2026-05-17 12:34:02 +03:00

84 lines
3.8 KiB
Diff

--- a/src/acpi/madt/arch/x86.rs
+++ b/src/acpi/madt/arch/x86.rs
@@ -150,15 +150,16 @@
let stack_start = RmmA::phys_to_virt(alloc.base()).data();
let stack_end = stack_start + (PAGE_SIZE << 4);
- let next_cpu = crate::CPU_COUNT.load(Ordering::Relaxed);
- if next_cpu >= crate::cpu_set::MAX_CPU_COUNT {
+ // Atomically allocate a CPU ID — fetch_add is SeqCst so that
+ // all later stores (PercpuBlock, NUMA node) are ordered after.
+ let cpu_id = LogicalCpuId::new(crate::CPU_COUNT.fetch_add(1, Ordering::SeqCst));
+ if cpu_id.get() >= crate::cpu_set::MAX_CPU_COUNT {
println!(
"KERNEL AP: CPU {} exceeds logical CPU limit, skipping",
ap_local_apic.id
);
continue;
}
- let cpu_id = LogicalCpuId::new(next_cpu);
let pcr_ptr = crate::arch::gdt::allocate_and_init_pcr(cpu_id, stack_end);
@@ -184,8 +185,10 @@
#[expect(clippy::fn_to_numeric_cast)]
ap_code.write(kstart_ap as u64);
- // TODO: Is this necessary (this fence)?
- core::arch::asm!("");
+ // Ensure all trampoline writes are visible to the AP before
+ // it starts executing. asm!("") is only a compiler barrier;
+ // fence(SeqCst) is a full hardware memory barrier.
+ core::sync::atomic::fence(Ordering::SeqCst);
};
AP_READY.store(false, Ordering::SeqCst);
@@ -241,8 +244,6 @@
continue;
}
- crate::CPU_COUNT.fetch_add(1, Ordering::Relaxed);
-
// Record APIC→CPU mapping for NUMA topology.
unsafe {
record_apic_mapping(u32::from(ap_local_apic.id), cpu_id);
@@ -273,15 +274,16 @@
let stack_start = RmmA::phys_to_virt(alloc.base()).data();
let stack_end = stack_start + (PAGE_SIZE << 4);
- let next_cpu = crate::CPU_COUNT.load(Ordering::Relaxed);
- if next_cpu >= crate::cpu_set::MAX_CPU_COUNT {
+ // Atomically allocate a CPU ID — fetch_add is SeqCst so that
+ // all later stores (PercpuBlock, NUMA node) are ordered after.
+ let cpu_id = LogicalCpuId::new(crate::CPU_COUNT.fetch_add(1, Ordering::SeqCst));
+ if cpu_id.get() >= crate::cpu_set::MAX_CPU_COUNT {
println!(
"KERNEL AP: CPU {} exceeds logical CPU limit, skipping",
apic_id
);
continue;
}
- let cpu_id = LogicalCpuId::new(next_cpu);
let pcr_ptr = crate::arch::gdt::allocate_and_init_pcr(cpu_id, stack_end);
let idt_ptr = crate::arch::idt::allocate_and_init_idt(cpu_id);
@@ -304,7 +306,8 @@
ap_page_table.write(page_table_physaddr as u64);
#[expect(clippy::fn_to_numeric_cast)]
ap_code.write(kstart_ap as u64);
- core::arch::asm!("");
+ // Ensure all trampoline writes are visible to the AP.
+ core::sync::atomic::fence(Ordering::SeqCst);
}
AP_READY.store(false, Ordering::SeqCst);
@@ -362,8 +365,6 @@
continue;
}
- crate::CPU_COUNT.fetch_add(1, Ordering::Relaxed);
-
// Record APIC→CPU mapping for NUMA topology.
unsafe {
record_apic_mapping(apic_id, cpu_id);