feat: fireworks!

This commit is contained in:
Loïc Grégoire
2026-04-18 20:44:52 -04:00
parent 712a8012af
commit 8fc133cc3c
18 changed files with 186 additions and 127 deletions
+2 -1
View File
@@ -142,10 +142,11 @@ pub fn send_sipi(apic_id: u32, startup_page: u8) void {
}
pub fn send_ipi(apic_id: u32, vector: u8, delivery_mode: u8) void {
const icr_value = (@as(u64, apic_id) << 32) | (@as(u64, delivery_mode) << 8) | vector;
if (in_x2apic_mode.local().*) {
const icr_value = (@as(u64, apic_id) << 32) | (@as(u64, delivery_mode) << 8) | vector;
x2apic_write(.Icr, icr_value);
} else {
const icr_value = (@as(u32, delivery_mode) << 8) | vector;
// Write to ICR1 first, because writing to the low word causes
// the IPI to be sent.
xapic_write(.Icr1, @as(u32, apic_id) << 24);
+5 -1
View File
@@ -5,7 +5,7 @@ const std = @import("std");
const tsc = @import("tsc.zig");
const pvclock = @import("pvclock.zig");
pub const apic = @import("apic.zig");
const smp = @import("smp.zig");
pub const smp = @import("smp.zig");
const ki = r.ke.private;
@@ -105,3 +105,7 @@ pub fn debug_write(c: u8) void {
pub fn arm_timer(deadline: r.Nanoseconds) void {
apic.arm_timer(deadline);
}
pub fn send_resched_ipi(target_cpu: u32) void {
apic.send_ipi(smp.cpu_id_to_apic_id[target_cpu], 240, 0);
}
+18 -2
View File
@@ -17,10 +17,12 @@ extern var AP_TRAMPOLINE_DATA: u8;
extern var __percpu_start: u8;
extern var __percpu_end: u8;
export var cpu_id_to_apic_id: [config.CONFIG_NCPUS]u32 = undefined;
pub export var cpu_id_to_apic_id: [config.CONFIG_NCPUS]u32 = undefined;
const start_stack = ke.ExportedCpuLocal(usize, 0, "ap_start_stack");
pub const start_thread = ke.CpuLocal(*ke.Thread, undefined);
var aps_booted: std.atomic.Value(usize) = .init(0);
const ApData = extern struct {
@@ -35,6 +37,16 @@ fn ap_entry(cpu_id: u32) callconv(.c) noreturn {
ki.impl.init.ap_entry(cpu_id, &aps_booted);
}
fn make_thread(entrypoint: *const fn (?*anyopaque) void, stack: usize) *ke.Thread {
const td = mm.zone.gpa.create(ke.Thread) catch @panic("Failed to allocate thread for AP");
td.init(stack, r.kib(32), entrypoint, null);
td.priority = 0;
td.priority_class = .Idle;
return td;
}
pub fn init() linksection(r.init) void {
const trampoline_start = @intFromPtr(&AP_TRAMPOLINE_START);
const trampoline_size = @intFromPtr(&AP_TRAMPOLINE_END) - trampoline_start;
@@ -94,10 +106,12 @@ pub fn init() linksection(r.init) void {
// copy the offset into the AP's self_offset variable
@as(*usize, @ptrCast(@alignCast(&cpu_data[self_offset_offset]))).* = ki.impl.cpu_offsets[cpu_id];
const stack_top = @intFromPtr(mm.heap.alloc(r.kib(16)) catch @panic("Failed to allocate AP stack")) + r.kib(16);
const stack_top = @intFromPtr(mm.heap.alloc(r.kib(32)) catch @panic("Failed to allocate AP stack")) + r.kib(32);
start_stack.remote(@intCast(cpu_id)).* = stack_top & ~@as(usize, 15);
start_thread.remote(@intCast(cpu_id)).* = make_thread(@ptrCast(&ap_entry), stack_top - r.kib(32));
rtl.barrier.wmb();
// Send the INIT-SIPI-SIPI sequence to start the AP.
@@ -109,6 +123,8 @@ pub fn init() linksection(r.init) void {
apic.send_sipi(apic_id, 0x08);
}
log.info("Waiting for APs...", .{});
while (aps_booted.load(.acquire) < apic.apics.items.len) {
std.atomic.spinLoopHint();
}
+7
View File
@@ -38,6 +38,7 @@ pub const GlobalState = struct {
pub const CpuState = struct {
pthread: c.pthread_t,
td: *ke.Thread,
};
pub var global_state: GlobalState = undefined;
@@ -122,6 +123,8 @@ fn other_cpu_entry(_: ?*anyopaque) callconv(.c) ?*anyopaque {
ki.cpu.init_cpu(@intCast(my_cpu_id));
ki.sched.percpu.local().current_thread = percpu.local().td;
timer.init_cpu();
while (true) {}
@@ -174,6 +177,10 @@ pub fn late_init(_: *pl.BootInfo) linksection(r.init) void {
@memcpy(block, @as([*]u8, @ptrCast(&__percpu_start))[0..size]);
const td = allocator.create(ke.Thread) catch @panic("oom");
make_thread(idle, td);
percpu.remote(@intCast(i)).td = td;
var attr: c.pthread_attr_t = undefined;
_ = c.pthread_attr_init(&attr);