Add the IDT table
This commit is contained in:
parent
2e9292be6e
commit
7dfdbe10ec
2 changed files with 163 additions and 0 deletions
142
src/idt.zig
Normal file
142
src/idt.zig
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const InterruptStackFrame = extern struct {
|
||||||
|
instruction_ptr: u64,
|
||||||
|
code_segment: u64,
|
||||||
|
cpu_flags: u64,
|
||||||
|
stack_ptr: u64,
|
||||||
|
stack_segment: u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
const HandlerFunction = *const fn (_: *InterruptStackFrame) callconv(.{ .x86_interrupt = .{} }) void;
|
||||||
|
|
||||||
|
fn HandlerFunctionWithErrorCode(comptime Return: type) type {
|
||||||
|
if (Return != void and Return != noreturn) {
|
||||||
|
@compileError("Return should either be void or noreturn");
|
||||||
|
}
|
||||||
|
|
||||||
|
return *const fn (_: *InterruptStackFrame, error_code: u32) callconv(.{ .x86_interrupt = .{} }) Return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const InterruptDescriptorTableEntryType = enum(u8) {
|
||||||
|
division_error = 0,
|
||||||
|
debug = 1,
|
||||||
|
non_maskable_interrupt = 2,
|
||||||
|
breakpoint = 3,
|
||||||
|
overflow = 4,
|
||||||
|
bound_range_exceeded = 5,
|
||||||
|
invalid_opcode = 6,
|
||||||
|
device_not_available = 7,
|
||||||
|
double_fault = 8,
|
||||||
|
coprocessor_segment_overrun = 9,
|
||||||
|
invalid_tss = 10,
|
||||||
|
segment_not_present = 11,
|
||||||
|
stack_segment_fault = 12,
|
||||||
|
general_protection_fault = 13,
|
||||||
|
page_fault = 14,
|
||||||
|
x87_floating_point_exception = 16,
|
||||||
|
alignment_check = 17,
|
||||||
|
machine_check = 18,
|
||||||
|
simd_floating_point = 19,
|
||||||
|
virtualization = 20,
|
||||||
|
control_protection_exception = 21,
|
||||||
|
hypervisor_injection_exception = 28,
|
||||||
|
vmm_communication_exception = 29,
|
||||||
|
security_exception = 30,
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub fn HandlerFunctionType(self: Self) type {
|
||||||
|
return switch (self) {
|
||||||
|
.double_fault, .machine_check => HandlerFunctionWithErrorCode(noreturn),
|
||||||
|
.invalid_tss, .segment_not_present, .stack_segment_fault, .general_protection_fault, .page_fault, .alignment_check, .control_protection_exception, .vmm_communication_exception, .security_exception => HandlerFunctionWithErrorCode(void),
|
||||||
|
else => HandlerFunction,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const InterruptDescriptorTable = extern struct {
|
||||||
|
table: [Length]Entry,
|
||||||
|
|
||||||
|
const Length = std.math.maxInt(u8) + 1;
|
||||||
|
|
||||||
|
const Entry = packed struct {
|
||||||
|
ptr_low: u16,
|
||||||
|
options: Options,
|
||||||
|
ptr_mid: u16,
|
||||||
|
ptr_high: u32,
|
||||||
|
reserved: u32,
|
||||||
|
|
||||||
|
pub const missing: Entry = .{
|
||||||
|
.ptr_low = 0,
|
||||||
|
.options = .minimal,
|
||||||
|
.ptr_mid = 0,
|
||||||
|
.ptr_high = 0,
|
||||||
|
.reserved = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Options = packed struct {
|
||||||
|
code_segment: u16,
|
||||||
|
bit_set: std.bit_set.IntegerBitSet(16),
|
||||||
|
|
||||||
|
pub const minimal: Options = .{
|
||||||
|
.code_segment = 0,
|
||||||
|
.bit_set = .{ .mask = 0b1110_0000_0000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn setCodeSelector(self: *align(2) Options, segment: u16) void {
|
||||||
|
self.code_segment = segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setPresent(self: *align(2) Options, present: bool) void {
|
||||||
|
self.bit_set.setValue(15, present);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn setHandler(self: *Entry, handler_addr: u64) void {
|
||||||
|
self.ptr_low = @truncate(handler_addr);
|
||||||
|
self.ptr_mid = @truncate(handler_addr >> 16);
|
||||||
|
self.ptr_high = @truncate(handler_addr >> 32);
|
||||||
|
|
||||||
|
self.options = .minimal;
|
||||||
|
const segment = asm volatile (
|
||||||
|
\\ mov %%cs, %[segment]
|
||||||
|
: [segment] "=&r" (-> u16)
|
||||||
|
:
|
||||||
|
);
|
||||||
|
self.options.setCodeSelector(segment);
|
||||||
|
self.options.setPresent(true);
|
||||||
|
|
||||||
|
std.log.info("Setting handler {any}\n", .{ self.* });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const empty: InterruptDescriptorTable = .{
|
||||||
|
.table = [_]Entry{.missing} ** Length,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn setEntry(
|
||||||
|
self: *InterruptDescriptorTable,
|
||||||
|
comptime entry_type: InterruptDescriptorTableEntryType,
|
||||||
|
handler: InterruptDescriptorTableEntryType.HandlerFunctionType(entry_type),
|
||||||
|
) void {
|
||||||
|
self.table[@intFromEnum(entry_type)].setHandler(@intFromPtr(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load(self: *InterruptDescriptorTable) void {
|
||||||
|
const DescriptorTablePointer = packed struct {
|
||||||
|
limit: u16,
|
||||||
|
base: u64,
|
||||||
|
};
|
||||||
|
const idt: DescriptorTablePointer = .{
|
||||||
|
.limit = @sizeOf(@TypeOf(self.*)) - 1,
|
||||||
|
.base = @intFromPtr(self),
|
||||||
|
};
|
||||||
|
|
||||||
|
asm volatile (
|
||||||
|
\\ lidt (%[idt])
|
||||||
|
:
|
||||||
|
: [idt] "r" (idt),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
21
src/main.zig
21
src/main.zig
|
|
@ -1,7 +1,11 @@
|
||||||
const lazy = @import("utils/Lazy.zig").lazy;
|
const lazy = @import("utils/Lazy.zig").lazy;
|
||||||
const Console = @import("Console.zig");
|
const Console = @import("Console.zig");
|
||||||
|
|
||||||
const MultibootInfo = @import("multiboot.zig").Info;
|
const MultibootInfo = @import("multiboot.zig").Info;
|
||||||
|
|
||||||
|
const InterruptDescriptorTable = @import("idt.zig").InterruptDescriptorTable;
|
||||||
|
const InterruptStackFrame = @import("idt.zig").InterruptStackFrame;
|
||||||
|
|
||||||
const MultibootHeader = packed struct {
|
const MultibootHeader = packed struct {
|
||||||
magic: i32,
|
magic: i32,
|
||||||
flags: i32,
|
flags: i32,
|
||||||
|
|
@ -37,6 +41,8 @@ export fn _start() callconv(.naked) noreturn {
|
||||||
|
|
||||||
var console = lazy(Console, .init);
|
var console = lazy(Console, .init);
|
||||||
|
|
||||||
|
var idt: InterruptDescriptorTable = .empty;
|
||||||
|
|
||||||
fn kmain(magic: u32, info: *const MultibootInfo) callconv(.c) void {
|
fn kmain(magic: u32, info: *const MultibootInfo) callconv(.c) void {
|
||||||
std.debug.assert(magic == MAGIC);
|
std.debug.assert(magic == MAGIC);
|
||||||
|
|
||||||
|
|
@ -49,9 +55,24 @@ fn kmain(magic: u32, info: *const MultibootInfo) callconv(.c) void {
|
||||||
std.log.info("Booted with cmdline \"{s}\"", .{info.cmdline});
|
std.log.info("Booted with cmdline \"{s}\"", .{info.cmdline});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
idt.setEntry(.breakpoint, breakpointHandler);
|
||||||
|
idt.load();
|
||||||
|
|
||||||
|
//asm volatile (
|
||||||
|
// \\ int3
|
||||||
|
// :
|
||||||
|
// :
|
||||||
|
//);
|
||||||
|
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn breakpointHandler(stack_frame: *InterruptStackFrame) callconv(.{ .x86_interrupt = .{} }) void {
|
||||||
|
_ = stack_frame;
|
||||||
|
|
||||||
|
std.log.err("breakpoint\n", .{});
|
||||||
|
}
|
||||||
|
|
||||||
fn hang() noreturn {
|
fn hang() noreturn {
|
||||||
while (true) asm volatile ("hlt");
|
while (true) asm volatile ("hlt");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue