enumerate usable CPU cores from the MADT

Keep each Local APIC's id and expose platform.cpus().
This commit is contained in:
Daniel Samson
2026-07-08 12:35:30 +01:00
parent 26d2f5259c
commit cf7c6df41c
4 changed files with 66 additions and 1 deletions
+41
View File
@@ -91,6 +91,35 @@ pub const PlatformInfo = struct {
/// Filled in by `discover`; the arch layer reads it during bring-up.
pub var platform_info: PlatformInfo = .{};
/// One usable logical processor, from a MADT type-0 (Local APIC) record. The
/// `apic_id` is the Local APIC ID that SMP bring-up targets to wake this core
/// (INIT–SIPI–SIPI); `processor_id` is the ACPI namespace handle. Only processors
/// the firmware marks *enabled* are recorded — a disabled one can't be started.
pub const Cpu = struct {
processor_id: u8,
apic_id: u8,
/// MADT flags bit 1: usable but firmware-started offline (hot-plug / deferred
/// bring-up), as opposed to already available. Informational for now.
online_capable: bool,
};
/// The set of usable logical processors the MADT listed — the hardware's degree of
/// parallelism. Includes the bootstrap processor danos already runs on; the rest
/// are the application processors SMP bring-up would start (see docs/smp.md).
pub const CpuInfo = struct {
/// A static pool sized well above any danos target (a desktop, two 4-core Pis).
/// If the MADT ever lists more, the surplus is dropped and counted in `dropped`
/// so the truncation is never silent.
cpus: [max_cpus]Cpu = undefined,
count: usize = 0,
dropped: usize = 0,
};
const max_cpus = 64;
/// Filled in by `discover` (from the MADT); SMP bring-up reads it to wake the APs.
pub var cpu_info: CpuInfo = .{};
/// Integrity/diagnostics for the AML parse. `consumed == total` means the parser
/// walked every byte of the DSDT/SSDTs without desyncing.
pub const AmlStats = struct {
@@ -438,6 +467,18 @@ fn parseMadt(dt: *DeviceTree, header: *const SystemDescriptorTableHeader) !void
var nb: [24]u8 = undefined;
const nm = std.fmt.bufPrint(&nb, "cpu{d}", .{la.processor_id}) catch "cpu";
_ = try dt.addChild(dt.root, .processor, nm);
// Also record it as a schedulable core (with the APIC ID an AP
// wake needs, which the device node name doesn't preserve).
if (cpu_info.count < cpu_info.cpus.len) {
cpu_info.cpus[cpu_info.count] = .{
.processor_id = la.processor_id,
.apic_id = la.apic_id,
.online_capable = la.flags & 2 != 0,
};
cpu_info.count += 1;
} else {
cpu_info.dropped += 1;
}
}
},
1 => {