mirror of
https://github.com/rdmsr/zag.git
synced 2026-10-30 06:48:22 +00:00
feat(pl/pc): add APIC timer support
This commit is contained in:
@@ -81,30 +81,33 @@ fn early_cpu_init() linksection(r.init) void {
|
||||
efer.nxe = true;
|
||||
|
||||
amd64.write_msr(.Efer, @bitCast(efer));
|
||||
|
||||
amd64.sti();
|
||||
}
|
||||
|
||||
pub fn ap_entry(cpu_id: u32) noreturn {
|
||||
pub fn ap_entry(cpu_id: u32, booted: *std.atomic.Value(usize)) noreturn {
|
||||
early_cpu_init();
|
||||
ki.cpu.init_cpu(cpu_id);
|
||||
pl.impl.init_ap();
|
||||
|
||||
_ = booted.fetchAdd(1, .monotonic);
|
||||
|
||||
while (true) {
|
||||
std.atomic.spinLoopHint();
|
||||
}
|
||||
}
|
||||
|
||||
var initial_offsets: [1]usize = undefined;
|
||||
var initial_offsets: [1]usize = .{0};
|
||||
extern var __percpu_start: u8;
|
||||
|
||||
pub fn early_init() linksection(r.init) void {
|
||||
amd64.detect_cpu_features();
|
||||
early_cpu_init();
|
||||
|
||||
initial_offsets[0] = @intFromPtr(&__percpu_start);
|
||||
impl.cpu_offsets = &initial_offsets;
|
||||
|
||||
int.init();
|
||||
|
||||
// Enable Per-CPU data for this CPU
|
||||
amd64.write_msr(.GsBase, 0);
|
||||
|
||||
int.init();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ const std = @import("std");
|
||||
const r = @import("root");
|
||||
const ke = r.ke;
|
||||
const ki = ke.private;
|
||||
const pl = r.pl;
|
||||
|
||||
extern const __interrupt_vectors: [256]usize;
|
||||
|
||||
@@ -44,6 +45,8 @@ const exception_msg = [32][]const u8{
|
||||
};
|
||||
|
||||
export fn isr_handler_main(frame: *const amd64.IrqFrame) callconv(.{ .x86_64_sysv = .{} }) void {
|
||||
const ipl = ke.ipl.set_hardware(.Device);
|
||||
|
||||
if (frame.intno < 32) {
|
||||
std.log.err("Unhandled exception: 0x{x} ({s}), err=0x{x}, pc=0x{x}", .{ frame.intno, exception_msg[frame.intno], frame.errcode, frame.rip });
|
||||
std.log.err("RAX=0x{x:0>16} RBX=0x{x:0>16} RCX=0x{x:0>16} RDX=0x{x:0>16}", .{ frame.rax, frame.rbx, frame.rcx, frame.rdx });
|
||||
@@ -75,6 +78,20 @@ export fn isr_handler_main(frame: *const amd64.IrqFrame) callconv(.{ .x86_64_sys
|
||||
|
||||
ki.panic.panic_with_frame("Unhandled exception", frame.rbp);
|
||||
}
|
||||
|
||||
if (frame.intno == 32) {
|
||||
ki.timer.clock();
|
||||
}
|
||||
|
||||
if (frame.intno >= 32) {
|
||||
pl.impl.apic.eoi();
|
||||
}
|
||||
|
||||
ki.impl.set_hardware_ipl(ipl);
|
||||
|
||||
if (@intFromEnum(ipl) < @intFromEnum(ke.Ipl.get_max_software()) and ki.ipl.is_softint_pending(.Dispatch)) {
|
||||
ki.dpc.dispatch(ke.cpu.current());
|
||||
}
|
||||
}
|
||||
|
||||
extern fn idt_load(idt_ptr: *const amd64.Idtr) callconv(.{ .x86_64_sysv = .{} }) void;
|
||||
|
||||
+1
-2
@@ -100,7 +100,7 @@ const balance_interval = @as(u64, config.CONFIG_BALANCE_INTERVAL);
|
||||
const steal_threshold = 1;
|
||||
|
||||
var balance_timer: ke.Timer = undefined;
|
||||
var balance_dpc: ke.Dpc = undefined;
|
||||
var balance_dpc: ke.Dpc = .init(balance);
|
||||
|
||||
// LCG values taken from FreeBSD.
|
||||
var lcg = std.Random.lcg.Wrapping(u32).init(0, 69069, 5);
|
||||
@@ -313,7 +313,6 @@ fn init_cpu() linksection(r.init) callconv(.c) void {
|
||||
|
||||
/// Called on CPU 0 to initialize load balancing mechanisms.
|
||||
pub fn late_init() linksection(r.init) void {
|
||||
balance_dpc = ke.Dpc.init(balance);
|
||||
balance_timer.init();
|
||||
ke.timer.set(&balance_timer, balance_interval * std.time.ns_per_ms, &balance_dpc);
|
||||
}
|
||||
|
||||
+11
-9
@@ -8,7 +8,10 @@ fn set_signals(enabled: bool) bool {
|
||||
var newmask: c.sigset_t = undefined;
|
||||
var oldmask: c.sigset_t = undefined;
|
||||
|
||||
_ = c.sigfillset(&newmask);
|
||||
_ = c.sigemptyset(&newmask);
|
||||
_ = c.sigaddset(&newmask, c.SIGUSR1);
|
||||
_ = c.sigaddset(&newmask, c.SIGUSR2);
|
||||
_ = c.sigaddset(&newmask, c.SIGALRM);
|
||||
|
||||
const how = if (enabled) c.SIG_UNBLOCK else c.SIG_BLOCK;
|
||||
|
||||
@@ -19,12 +22,13 @@ fn set_signals(enabled: bool) bool {
|
||||
return c.sigismember(&oldmask, c.SIGUSR1) == 0;
|
||||
}
|
||||
|
||||
threadlocal var hard_ipl: ke.Ipl = .Passive;
|
||||
|
||||
/// Set the hardware IPL.
|
||||
pub fn set_hardware_ipl(ipl: ke.Ipl) void {
|
||||
// This is a no-op since we handle this in enable_interrupts().
|
||||
hard_ipl = ipl;
|
||||
if (@intFromEnum(ipl) > @intFromEnum(ke.Ipl.get_max_software())) {
|
||||
_ = disable_interrupts();
|
||||
} else {
|
||||
_ = enable_interrupts();
|
||||
}
|
||||
}
|
||||
|
||||
/// Disable interrupts and return the previous state.
|
||||
@@ -34,14 +38,12 @@ pub fn disable_interrupts() bool {
|
||||
|
||||
/// Enable interrupts and return the previous state.
|
||||
pub fn enable_interrupts() bool {
|
||||
const ipl_allows_ints = @intFromEnum(hard_ipl) <= @intFromEnum(ke.Ipl.get_max_software());
|
||||
return set_signals(ipl_allows_ints);
|
||||
return set_signals(true);
|
||||
}
|
||||
|
||||
/// Restore an interrupt state.
|
||||
pub fn restore_interrupts(val: bool) void {
|
||||
const ipl_allows_ints = @intFromEnum(hard_ipl) <= @intFromEnum(ke.Ipl.get_max_software());
|
||||
_ = set_signals(val and ipl_allows_ints);
|
||||
_ = set_signals(val);
|
||||
}
|
||||
|
||||
pub fn send_resched_ipi(cpu: u32) void {
|
||||
|
||||
Reference in New Issue
Block a user