core: Add PIT timer code to preempt the scheduler
This commit is contained in:
parent
a209ba7b99
commit
671a9b5887
@ -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 => {},
|
||||||
}
|
}
|
||||||
|
28
core/src/arch/x86_64/pit.zig
Normal file
28
core/src/arch/x86_64/pit.zig
Normal 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);
|
||||||
|
}
|
@ -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();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user