85 lines
2.3 KiB
Zig
85 lines
2.3 KiB
Zig
![]() |
// Zig version: 0.4.0
|
||
|
|
||
|
const gdt = @import("gdt.zig");
|
||
|
const arch = @import("arch.zig");
|
||
|
|
||
|
const NUMBER_OF_ENTRIES: u16 = 256;
|
||
|
const TABLE_SIZE: u16 = @sizeOf(IdtEntry) * NUMBER_OF_ENTRIES - 1;
|
||
|
|
||
|
// The different gate types
|
||
|
const TASK_GATE_32BIT: u4 = 0x5;
|
||
|
const INTERRUPT_GATE_16BIT: u4 = 0x6;
|
||
|
const TRAP_GATE_16BIT: u4 = 0x7;
|
||
|
const INTERRUPT_GATE_32BIT: u4 = 0xE;
|
||
|
const TRAP_GATE_32BIT: u4 = 0xF;
|
||
|
|
||
|
const PRIVILEGE_RING_0: u2 = 0x0;
|
||
|
const PRIVILEGE_RING_1: u2 = 0x1;
|
||
|
const PRIVILEGE_RING_2: u2 = 0x2;
|
||
|
const PRIVILEGE_RING_3: u2 = 0x3;
|
||
|
|
||
|
const IdtEntry = packed struct {
|
||
|
/// The lower 16 bits of the base address of the interrupt handler offset.
|
||
|
base_low: u16,
|
||
|
|
||
|
/// The code segment in the GDT which the handlers will be held.
|
||
|
selector: u16,
|
||
|
|
||
|
/// Must be zero, unused.
|
||
|
zero: u8,
|
||
|
|
||
|
/// The IDT gate type.
|
||
|
gate_type: u4,
|
||
|
|
||
|
/// Must be 0 for interrupt and trap gates.
|
||
|
storage_segment: u1,
|
||
|
|
||
|
/// The minimum ring level that the calling code must have to run the handler. So user code may not be able to run some interrupts.
|
||
|
privilege: u2,
|
||
|
|
||
|
/// Whether the IDT entry is present.
|
||
|
present: u1,
|
||
|
|
||
|
/// The upper 16 bits of the base address of the interrupt handler offset.
|
||
|
base_high: u16,
|
||
|
};
|
||
|
|
||
|
pub const IdtPtr = packed struct {
|
||
|
/// The total size of the IDT (minus 1) in bytes.
|
||
|
limit: u16,
|
||
|
|
||
|
/// The base address where the IDT is located.
|
||
|
base: *IdtEntry,
|
||
|
};
|
||
|
|
||
|
var idt: [NUMBER_OF_ENTRIES]IdtEntry = []IdtEntry{makeEntry(0, 0, 0, 0, 0)} ** NUMBER_OF_ENTRIES;
|
||
|
|
||
|
const idt_ptr: IdtPtr = IdtPtr {
|
||
|
.limit = TABLE_SIZE,
|
||
|
.base = &idt[0],
|
||
|
};
|
||
|
|
||
|
fn makeEntry(base: u32, selector: u16, gate_type: u4, privilege: u2, present: u1) IdtEntry {
|
||
|
return IdtEntry {
|
||
|
.base_low = @truncate(u16, base),
|
||
|
.selector = selector,
|
||
|
.zero = 0,
|
||
|
.gate_type = gate_type,
|
||
|
.storage_segment = 0,
|
||
|
.privilege = privilege,
|
||
|
.present = present,
|
||
|
.base_high = @truncate(u16, base >> 16),
|
||
|
};
|
||
|
}
|
||
|
|
||
|
pub fn openInterruptGate(index: u8, base: extern fn()void) void {
|
||
|
idt[index] = makeEntry(@ptrToInt(base), gdt.KERNEL_CODE_OFFSET, INTERRUPT_GATE_32BIT, PRIVILEGE_RING_0, 1);
|
||
|
}
|
||
|
|
||
|
pub fn closeInterruptGate(index: u8) void {
|
||
|
idt[index] = makeEntry(0, 0, 0, 0, 0);
|
||
|
}
|
||
|
|
||
|
pub fn init() void {
|
||
|
arch.lidt(&idt_ptr);
|
||
|
}
|