core: Add PIT timer code to preempt the scheduler

This commit is contained in:
Gabriel 2025-02-16 11:58:01 +01:00
parent a209ba7b99
commit 671a9b5887
3 changed files with 41 additions and 3 deletions

View File

@ -139,7 +139,16 @@ fn pageFault(frame: *InterruptStackFrame) void {
} }
export fn interruptEntry(frame: *InterruptStackFrame) callconv(.C) void { export fn interruptEntry(frame: *InterruptStackFrame) callconv(.C) void {
debug.print("Caught interrupt {d}\n", .{frame.isr}); if (frame.isr >= 32 and frame.isr < 48) {
// IRQ
const irq_handler = irq_handlers[frame.error_or_irq];
if (irq_handler) |handler| {
handler(@intCast(frame.error_or_irq), frame);
}
pic.picEOI(@intCast(frame.error_or_irq));
return;
}
switch (frame.isr) { switch (frame.isr) {
@intFromEnum(Exceptions.PageFault) => { @intFromEnum(Exceptions.PageFault) => {
pageFault(frame); pageFault(frame);
@ -149,7 +158,7 @@ export fn interruptEntry(frame: *InterruptStackFrame) callconv(.C) void {
}, },
SYSCALL_INTERRUPT => { SYSCALL_INTERRUPT => {
var args = sys.Arguments{ .arg0 = frame.rdi, .arg1 = frame.rsi, .arg2 = frame.rdx, .arg3 = frame.r10, .arg4 = frame.r8, .arg5 = frame.r9 }; var args = sys.Arguments{ .arg0 = frame.rdi, .arg1 = frame.rsi, .arg2 = frame.rdx, .arg3 = frame.r10, .arg4 = frame.r8, .arg5 = frame.r9 };
sys.invokeSyscall(frame.rax, frame, &args, @ptrFromInt(@as(usize, @intFromPtr(&frame.rax)))); sys.invokeSyscall(frame.rax, frame, &args, @ptrCast(&frame.rax));
}, },
else => {}, else => {},
} }

View File

@ -0,0 +1,28 @@
const io = @import("ioports.zig");
const interrupts = @import("interrupts.zig");
const pic = @import("pic.zig");
const thread = @import("../../thread.zig");
// Every timer tick is equivalent to 1 millisecond.
const TIMER_RESOLUTION = 1;
const PIT_CHANNEL_0 = 0x40;
const base_frequency: u64 = 1193182;
pub fn initializePIT() void {
const divisor: u16 = @intCast(base_frequency / (TIMER_RESOLUTION * 1000));
if (divisor < 100) {
@compileError("Timer resolution is too low");
}
io.outb(PIT_CHANNEL_0, @as(u8, @intCast(divisor & 0xFF)));
io.outb(0x80, 0); // short delay
io.outb(PIT_CHANNEL_0, @as(u8, @intCast((divisor & 0xFF00) >> 8)));
_ = interrupts.registerIRQ(0, &pitTimerHandler);
}
pub fn pitTimerHandler(_: u32, regs: *interrupts.InterruptStackFrame) void {
thread.preempt(regs);
}

View File

@ -1,6 +1,7 @@
const gdt = @import("gdt.zig"); const gdt = @import("gdt.zig");
const idt = @import("idt.zig"); const idt = @import("idt.zig");
const pic = @import("pic.zig"); const pic = @import("pic.zig");
const pit = @import("pit.zig");
const interrupts = @import("interrupts.zig"); const interrupts = @import("interrupts.zig");
pub const PAGE_SIZE = 4096; pub const PAGE_SIZE = 4096;
@ -26,5 +27,5 @@ pub fn platformInit() void {
pub fn platformEndInit() void { pub fn platformEndInit() void {
pic.remapPIC(); pic.remapPIC();
interrupts.syncInterrupts(); interrupts.syncInterrupts();
interrupts.enableInterrupts(); pit.initializePIT();
} }