aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mirai.old/asm/context.zig3
-rw-r--r--mirai.old/asm/cpu.zig3
-rw-r--r--mirai/asm/asm.zig1
-rw-r--r--mirai/asm/cpu/control.zig6
-rw-r--r--mirai/asm/fpu/fpu.zig12
-rw-r--r--mirai/asm/gdt/lgdt.zig6
-rw-r--r--mirai/asm/gdt/segments.zig6
-rw-r--r--mirai/asm/interrupts/flags.zig23
-rw-r--r--mirai/asm/interrupts/idt.zig17
-rw-r--r--mirai/asm/interrupts/interrupts.zig11
-rw-r--r--mirai/asm/interrupts/stubs.zig42
-rw-r--r--mirai/crimson/classify/analyze.zig29
-rw-r--r--mirai/crimson/classify/vector.zig16
-rw-r--r--mirai/crimson/constants/flavors.zig28
-rw-r--r--mirai/crimson/constants/vectors.zig12
-rw-r--r--mirai/crimson/ports/array.zig26
-rw-r--r--mirai/crimson/ports/port.zig16
-rw-r--r--mirai/crimson/types/context.zig47
-rw-r--r--mirai/crimson/types/corpse.zig35
-rw-r--r--mirai/crimson/types/exception.zig32
-rw-r--r--mirai/crimson/types/frame.zig21
-rw-r--r--mirai/crimson/types/identity.zig16
-rw-r--r--mirai/crimson/types/port.zig15
-rw-r--r--mirai/drivers/drivers.zig1
-rw-r--r--mirai/drivers/pit/constants.zig15
-rw-r--r--mirai/drivers/pit/handler.zig35
-rw-r--r--mirai/drivers/pit/init.zig16
-rw-r--r--mirai/drivers/pit/pit.zig10
-rw-r--r--mirai/interrupts/handlers/common.zig30
-rw-r--r--mirai/interrupts/handlers/exceptions.zig89
-rw-r--r--mirai/interrupts/handlers/handlers.zig9
-rw-r--r--mirai/interrupts/handlers/hardware.zig66
-rw-r--r--mirai/interrupts/idt.zig49
-rw-r--r--mirai/interrupts/load/lidt.zig20
-rw-r--r--mirai/interrupts/load/load.zig6
-rw-r--r--mirai/interrupts/pic/eoi.zig20
-rw-r--r--mirai/interrupts/pic/init.zig41
-rw-r--r--mirai/interrupts/pic/mask.zig40
-rw-r--r--mirai/interrupts/pic/pic.zig13
-rw-r--r--mirai/interrupts/pic/ports.zig15
-rw-r--r--mirai/interrupts/table/entries.zig5
-rw-r--r--mirai/interrupts/table/install.zig27
-rw-r--r--mirai/interrupts/table/table.zig10
-rw-r--r--mirai/interrupts/types/descriptor.zig19
-rw-r--r--mirai/interrupts/types/gate.zig67
-rw-r--r--mirai/interrupts/types/types.zig9
-rw-r--r--mirai/pmm/bitmap/operations.zig2
-rw-r--r--shared/fs/afs/constants/magic.zig6
48 files changed, 951 insertions, 92 deletions
diff --git a/mirai.old/asm/context.zig b/mirai.old/asm/context.zig
index ada6585..5876b33 100644
--- a/mirai.old/asm/context.zig
+++ b/mirai.old/asm/context.zig
@@ -60,7 +60,6 @@ pub fn switch_to_context(ctx: *const kata_mod.Context, page_table: u64, kernel_s
: [ctx_addr] "r" (ctx_addr),
[pt] "r" (page_table),
[kstack] "r" (kernel_stack),
- : .{ .memory = true }
- );
+ : .{ .memory = true });
unreachable;
}
diff --git a/mirai.old/asm/cpu.zig b/mirai.old/asm/cpu.zig
index 86324a0..608aa6b 100644
--- a/mirai.old/asm/cpu.zig
+++ b/mirai.old/asm/cpu.zig
@@ -63,6 +63,5 @@ pub inline fn reload_code_segment(selector: u16) void {
\\1:
:
: [sel] "r" (@as(u64, selector)),
- : .{ .rax = true }
- );
+ : .{ .rax = true });
}
diff --git a/mirai/asm/asm.zig b/mirai/asm/asm.zig
index 1a12c31..f2bae9b 100644
--- a/mirai/asm/asm.zig
+++ b/mirai/asm/asm.zig
@@ -5,3 +5,4 @@ pub const io = @import("io/io.zig");
pub const gdt = @import("gdt/gdt.zig");
pub const debug = @import("debug/debug.zig");
pub const fpu = @import("fpu/fpu.zig");
+pub const interrupts = @import("interrupts/interrupts.zig");
diff --git a/mirai/asm/cpu/control.zig b/mirai/asm/cpu/control.zig
index ec408c1..719c8bd 100644
--- a/mirai/asm/cpu/control.zig
+++ b/mirai/asm/cpu/control.zig
@@ -35,8 +35,7 @@ pub fn write_cr3(value: u64) void {
asm volatile ("mov %[value], %%cr3"
:
: [value] "r" (value),
- : .{ .memory = true }
- );
+ : .{ .memory = true });
}
pub fn read_cr4() u64 {
@@ -63,6 +62,5 @@ pub fn invalidate_page(virtual_address: u64) void {
asm volatile ("invlpg (%[address])"
:
: [address] "r" (virtual_address),
- : .{ .memory = true }
- );
+ : .{ .memory = true });
}
diff --git a/mirai/asm/fpu/fpu.zig b/mirai/asm/fpu/fpu.zig
index 4f5e5db..e6f86ec 100644
--- a/mirai/asm/fpu/fpu.zig
+++ b/mirai/asm/fpu/fpu.zig
@@ -4,16 +4,14 @@ pub fn fxsave(addr: u64) void {
asm volatile ("fxsave (%[addr])"
:
: [addr] "r" (addr),
- : .{ .memory = true }
- );
+ : .{ .memory = true });
}
pub fn fxrstor(addr: u64) void {
asm volatile ("fxrstor (%[addr])"
:
: [addr] "r" (addr),
- : .{ .memory = true }
- );
+ : .{ .memory = true });
}
pub fn fninit() void {
@@ -28,14 +26,12 @@ pub fn stmxcsr(addr: *u32) void {
asm volatile ("stmxcsr (%[addr])"
:
: [addr] "r" (addr),
- : .{ .memory = true }
- );
+ : .{ .memory = true });
}
pub fn ldmxcsr(addr: *const u32) void {
asm volatile ("ldmxcsr (%[addr])"
:
: [addr] "r" (addr),
- : .{ .memory = true }
- );
+ : .{ .memory = true });
}
diff --git a/mirai/asm/gdt/lgdt.zig b/mirai/asm/gdt/lgdt.zig
index 457a8aa..42a640b 100644
--- a/mirai/asm/gdt/lgdt.zig
+++ b/mirai/asm/gdt/lgdt.zig
@@ -9,8 +9,7 @@ pub fn lgdt(gdtr: *const Gdtr) void {
asm volatile ("lgdt (%[gdtr])"
:
: [gdtr] "r" (gdtr),
- : .{ .memory = true }
- );
+ : .{ .memory = true });
}
pub fn sgdt() Gdtr {
@@ -18,7 +17,6 @@ pub fn sgdt() Gdtr {
asm volatile ("sgdt (%[gdtr])"
:
: [gdtr] "r" (&gdtr),
- : .{ .memory = true }
- );
+ : .{ .memory = true });
return gdtr;
}
diff --git a/mirai/asm/gdt/segments.zig b/mirai/asm/gdt/segments.zig
index ab2a26a..10d7c9e 100644
--- a/mirai/asm/gdt/segments.zig
+++ b/mirai/asm/gdt/segments.zig
@@ -9,8 +9,7 @@ pub fn reload_code_segment(code_selector: u16) void {
\\1:
:
: [code_sel] "r" (@as(u64, code_selector)),
- : .{ .rax = true, .memory = true }
- );
+ : .{ .rax = true, .memory = true });
}
pub fn reload_data_segments(data_selector: u16) void {
@@ -23,8 +22,7 @@ pub fn reload_data_segments(data_selector: u16) void {
\\mov %%ax, %%ss
:
: [data_sel] "r" (data_selector),
- : .{ .rax = true, .memory = true }
- );
+ : .{ .rax = true, .memory = true });
}
pub fn load_tss(tss_selector: u16) void {
diff --git a/mirai/asm/interrupts/flags.zig b/mirai/asm/interrupts/flags.zig
new file mode 100644
index 0000000..2bf3fc3
--- /dev/null
+++ b/mirai/asm/interrupts/flags.zig
@@ -0,0 +1,23 @@
+//! Interrupt Flag Operations
+
+pub fn enable() void {
+ asm volatile ("sti");
+}
+
+pub fn disable() void {
+ asm volatile ("cli");
+}
+
+pub fn read_flags() u64 {
+ var flags: u64 = undefined;
+ asm volatile (
+ \\pushfq
+ \\pop %[flags]
+ : [flags] "=r" (flags),
+ );
+ return flags;
+}
+
+pub fn are_enabled() bool {
+ return (read_flags() & 0x200) != 0;
+}
diff --git a/mirai/asm/interrupts/idt.zig b/mirai/asm/interrupts/idt.zig
new file mode 100644
index 0000000..85147a2
--- /dev/null
+++ b/mirai/asm/interrupts/idt.zig
@@ -0,0 +1,17 @@
+//! IDT Assembly Operations
+
+pub fn lidt(desc: *const anyopaque) void {
+ asm volatile ("lidt (%[desc])"
+ :
+ : [desc] "r" (desc),
+ : .{ .memory = true }
+ );
+}
+
+pub fn sidt(desc: *anyopaque) void {
+ asm volatile ("sidt (%[desc])"
+ :
+ : [desc] "r" (desc),
+ : .{ .memory = true }
+ );
+}
diff --git a/mirai/asm/interrupts/interrupts.zig b/mirai/asm/interrupts/interrupts.zig
new file mode 100644
index 0000000..812ee04
--- /dev/null
+++ b/mirai/asm/interrupts/interrupts.zig
@@ -0,0 +1,11 @@
+//! Interrupt Assembly Operations
+
+pub const idt = @import("idt.zig");
+pub const flags = @import("flags.zig");
+pub const stubs = @import("stubs.zig");
+
+pub const lidt = idt.lidt;
+pub const sidt = idt.sidt;
+pub const enable = flags.enable;
+pub const disable = flags.disable;
+pub const are_enabled = flags.are_enabled;
diff --git a/mirai/asm/interrupts/stubs.zig b/mirai/asm/interrupts/stubs.zig
new file mode 100644
index 0000000..65b3cd8
--- /dev/null
+++ b/mirai/asm/interrupts/stubs.zig
@@ -0,0 +1,42 @@
+//! Interrupt Handler Stub Assembly
+
+pub const push_all =
+ \\push %%rax
+ \\push %%rbx
+ \\push %%rcx
+ \\push %%rdx
+ \\push %%rsi
+ \\push %%rdi
+ \\push %%rbp
+ \\push %%r8
+ \\push %%r9
+ \\push %%r10
+ \\push %%r11
+ \\push %%r12
+ \\push %%r13
+ \\push %%r14
+ \\push %%r15
+;
+
+pub const pop_all =
+ \\pop %%r15
+ \\pop %%r14
+ \\pop %%r13
+ \\pop %%r12
+ \\pop %%r11
+ \\pop %%r10
+ \\pop %%r9
+ \\pop %%r8
+ \\pop %%rbp
+ \\pop %%rdi
+ \\pop %%rsi
+ \\pop %%rdx
+ \\pop %%rcx
+ \\pop %%rbx
+ \\pop %%rax
+;
+
+pub const iret_cleanup =
+ \\add $16, %%rsp
+ \\iretq
+;
diff --git a/mirai/crimson/classify/analyze.zig b/mirai/crimson/classify/analyze.zig
index e4287a4..b7c9818 100644
--- a/mirai/crimson/classify/analyze.zig
+++ b/mirai/crimson/classify/analyze.zig
@@ -1,16 +1,29 @@
//! Analyze Error Codes
pub const PageFaultError = struct {
- present: bool, write: bool, user: bool, reserved_write: bool, instruction_fetch: bool,
+ present: bool,
+ write: bool,
+ user: bool,
+ reserved_write: bool,
+ instruction_fetch: bool,
pub fn from_error_code(code: u64) PageFaultError {
return PageFaultError{
- .present = (code & 1) != 0, .write = (code & 2) != 0, .user = (code & 4) != 0,
- .reserved_write = (code & 8) != 0, .instruction_fetch = (code & 16) != 0,
+ .present = (code & 1) != 0,
+ .write = (code & 2) != 0,
+ .user = (code & 4) != 0,
+ .reserved_write = (code & 8) != 0,
+ .instruction_fetch = (code & 16) != 0,
};
}
- pub fn is_not_present(self: PageFaultError) bool { return !self.present; }
- pub fn is_write_access(self: PageFaultError) bool { return self.write; }
- pub fn is_execute_access(self: PageFaultError) bool { return self.instruction_fetch; }
+ pub fn is_not_present(self: PageFaultError) bool {
+ return !self.present;
+ }
+ pub fn is_write_access(self: PageFaultError) bool {
+ return self.write;
+ }
+ pub fn is_execute_access(self: PageFaultError) bool {
+ return self.instruction_fetch;
+ }
pub fn description(self: PageFaultError) []const u8 {
if (self.instruction_fetch) return if (self.present) "Execute on non-executable page" else "Execute on non-present page";
if (self.write) return if (self.present) "Write to read-only page" else "Write to non-present page";
@@ -19,7 +32,9 @@ pub const PageFaultError = struct {
};
pub const SelectorError = struct {
- external: bool, table: u2, index: u13,
+ external: bool,
+ table: u2,
+ index: u13,
pub fn from_error_code(code: u64) SelectorError {
return SelectorError{ .external = (code & 1) != 0, .table = @truncate((code >> 1) & 0x3), .index = @truncate((code >> 3) & 0x1FFF) };
}
diff --git a/mirai/crimson/classify/vector.zig b/mirai/crimson/classify/vector.zig
index 213b1ee..5d03a13 100644
--- a/mirai/crimson/classify/vector.zig
+++ b/mirai/crimson/classify/vector.zig
@@ -4,7 +4,15 @@ const constants = @import("../constants/constants.zig");
const ExceptionType = constants.ExceptionType;
const vectors = constants.vectors;
-pub fn classify_vector(vector_number: u8) ExceptionType { return vectors.get_exception_type(vector_number); }
-pub fn get_vector_name(vector_number: u8) []const u8 { return vectors.get_name(vector_number); }
-pub fn vector_has_error_code(vector_number: u8) bool { return vectors.has_error_code(vector_number); }
-pub fn is_exception_vector(vector_number: u8) bool { return vector_number < 32; }
+pub fn classify_vector(vector_number: u8) ExceptionType {
+ return vectors.get_exception_type(vector_number);
+}
+pub fn get_vector_name(vector_number: u8) []const u8 {
+ return vectors.get_name(vector_number);
+}
+pub fn vector_has_error_code(vector_number: u8) bool {
+ return vectors.has_error_code(vector_number);
+}
+pub fn is_exception_vector(vector_number: u8) bool {
+ return vector_number < 32;
+}
diff --git a/mirai/crimson/constants/flavors.zig b/mirai/crimson/constants/flavors.zig
index 4639522..b614bd9 100644
--- a/mirai/crimson/constants/flavors.zig
+++ b/mirai/crimson/constants/flavors.zig
@@ -1,11 +1,29 @@
//! State Flavors
pub const Flavor = enum(u8) {
- none = 0, general = 1, float = 2, debug = 3, avx = 4, full = 5,
- pub fn includes_general(self: Flavor) bool { return self == .general or self == .full; }
- pub fn includes_float(self: Flavor) bool { return self == .float or self == .full; }
- pub fn includes_debug(self: Flavor) bool { return self == .debug or self == .full; }
+ none = 0,
+ general = 1,
+ float = 2,
+ debug = 3,
+ avx = 4,
+ full = 5,
+ pub fn includes_general(self: Flavor) bool {
+ return self == .general or self == .full;
+ }
+ pub fn includes_float(self: Flavor) bool {
+ return self == .float or self == .full;
+ }
+ pub fn includes_debug(self: Flavor) bool {
+ return self == .debug or self == .full;
+ }
pub fn name(self: Flavor) []const u8 {
- return switch (self) { .none => "None", .general => "General", .float => "Float", .debug => "Debug", .avx => "AVX", .full => "Full" };
+ return switch (self) {
+ .none => "None",
+ .general => "General",
+ .float => "Float",
+ .debug => "Debug",
+ .avx => "AVX",
+ .full => "Full",
+ };
}
};
diff --git a/mirai/crimson/constants/vectors.zig b/mirai/crimson/constants/vectors.zig
index 92d903b..684683f 100644
--- a/mirai/crimson/constants/vectors.zig
+++ b/mirai/crimson/constants/vectors.zig
@@ -27,16 +27,22 @@ pub const vectors = [_]Vector{
};
pub fn get_exception_type(vector_number: u8) ExceptionType {
- for (vectors) |v| { if (v.number == vector_number) return v.exception_type; }
+ for (vectors) |v| {
+ if (v.number == vector_number) return v.exception_type;
+ }
return .forbidden;
}
pub fn has_error_code(vector_number: u8) bool {
- for (vectors) |v| { if (v.number == vector_number) return v.has_error_code; }
+ for (vectors) |v| {
+ if (v.number == vector_number) return v.has_error_code;
+ }
return false;
}
pub fn get_name(vector_number: u8) []const u8 {
- for (vectors) |v| { if (v.number == vector_number) return v.name; }
+ for (vectors) |v| {
+ if (v.number == vector_number) return v.name;
+ }
return "Unknown";
}
diff --git a/mirai/crimson/ports/array.zig b/mirai/crimson/ports/array.zig
index 6157fc8..1f1d265 100644
--- a/mirai/crimson/ports/array.zig
+++ b/mirai/crimson/ports/array.zig
@@ -9,10 +9,24 @@ pub const exception_type_count = 10;
pub const PortArray = struct {
ports: [exception_type_count]Port,
- pub fn init() PortArray { var a = PortArray{ .ports = undefined }; for (&a.ports) |*p| p.clear(); return a; }
- pub fn get(self: *PortArray, t: ExceptionType) *Port { return &self.ports[@intFromEnum(t)]; }
- pub fn get_const(self: *const PortArray, t: ExceptionType) *const Port { return &self.ports[@intFromEnum(t)]; }
- pub fn set(self: *PortArray, t: ExceptionType, port: Port) void { self.ports[@intFromEnum(t)] = port; }
- pub fn clear_all(self: *PortArray) void { for (&self.ports) |*p| p.clear(); }
- pub fn has_port(self: *const PortArray, t: ExceptionType) bool { return self.get_const(t).is_valid(); }
+ pub fn init() PortArray {
+ var a = PortArray{ .ports = undefined };
+ for (&a.ports) |*p| p.clear();
+ return a;
+ }
+ pub fn get(self: *PortArray, t: ExceptionType) *Port {
+ return &self.ports[@intFromEnum(t)];
+ }
+ pub fn get_const(self: *const PortArray, t: ExceptionType) *const Port {
+ return &self.ports[@intFromEnum(t)];
+ }
+ pub fn set(self: *PortArray, t: ExceptionType, port: Port) void {
+ self.ports[@intFromEnum(t)] = port;
+ }
+ pub fn clear_all(self: *PortArray) void {
+ for (&self.ports) |*p| p.clear();
+ }
+ pub fn has_port(self: *const PortArray, t: ExceptionType) bool {
+ return self.get_const(t).is_valid();
+ }
};
diff --git a/mirai/crimson/ports/port.zig b/mirai/crimson/ports/port.zig
index 79d9844..3e4263a 100644
--- a/mirai/crimson/ports/port.zig
+++ b/mirai/crimson/ports/port.zig
@@ -11,7 +11,15 @@ pub fn create(port_id: u64, owner: PortOwner, owner_id: u64) Port {
return Port{ .port_id = port_id, .behavior = .default, .flavor = .general, .owner = owner, .owner_id = owner_id, .active = true };
}
-pub fn set_behavior(port: *Port, behavior: Behavior) void { port.behavior = behavior; }
-pub fn set_flavor(port: *Port, flavor: Flavor) void { port.flavor = flavor; }
-pub fn activate(port: *Port) void { port.active = true; }
-pub fn deactivate(port: *Port) void { port.active = false; }
+pub fn set_behavior(port: *Port, behavior: Behavior) void {
+ port.behavior = behavior;
+}
+pub fn set_flavor(port: *Port, flavor: Flavor) void {
+ port.flavor = flavor;
+}
+pub fn activate(port: *Port) void {
+ port.active = true;
+}
+pub fn deactivate(port: *Port) void {
+ port.active = false;
+}
diff --git a/mirai/crimson/types/context.zig b/mirai/crimson/types/context.zig
index 710e25f..8df912e 100644
--- a/mirai/crimson/types/context.zig
+++ b/mirai/crimson/types/context.zig
@@ -1,20 +1,47 @@
//! CPU Context
pub const Context = extern struct {
- rax: u64 = 0, rbx: u64 = 0, rcx: u64 = 0, rdx: u64 = 0,
- rsi: u64 = 0, rdi: u64 = 0, rbp: u64 = 0, rsp: u64 = 0,
- r8: u64 = 0, r9: u64 = 0, r10: u64 = 0, r11: u64 = 0,
- r12: u64 = 0, r13: u64 = 0, r14: u64 = 0, r15: u64 = 0,
- rip: u64 = 0, rflags: u64 = 0,
- cs: u16 = 0, ds: u16 = 0, es: u16 = 0, fs: u16 = 0, gs: u16 = 0, ss: u16 = 0,
+ rax: u64 = 0,
+ rbx: u64 = 0,
+ rcx: u64 = 0,
+ rdx: u64 = 0,
+ rsi: u64 = 0,
+ rdi: u64 = 0,
+ rbp: u64 = 0,
+ rsp: u64 = 0,
+ r8: u64 = 0,
+ r9: u64 = 0,
+ r10: u64 = 0,
+ r11: u64 = 0,
+ r12: u64 = 0,
+ r13: u64 = 0,
+ r14: u64 = 0,
+ r15: u64 = 0,
+ rip: u64 = 0,
+ rflags: u64 = 0,
+ cs: u16 = 0,
+ ds: u16 = 0,
+ es: u16 = 0,
+ fs: u16 = 0,
+ gs: u16 = 0,
+ ss: u16 = 0,
padding: u32 = 0,
- cr0: u64 = 0, cr2: u64 = 0, cr3: u64 = 0, cr4: u64 = 0,
+ cr0: u64 = 0,
+ cr2: u64 = 0,
+ cr3: u64 = 0,
+ cr4: u64 = 0,
pub fn clear(self: *Context) void {
self.* = Context{};
}
- pub fn is_user_mode(self: *const Context) bool { return (self.cs & 0x3) == 3; }
- pub fn is_kernel_mode(self: *const Context) bool { return (self.cs & 0x3) == 0; }
- pub fn get_fault_address(self: *const Context) u64 { return self.cr2; }
+ pub fn is_user_mode(self: *const Context) bool {
+ return (self.cs & 0x3) == 3;
+ }
+ pub fn is_kernel_mode(self: *const Context) bool {
+ return (self.cs & 0x3) == 0;
+ }
+ pub fn get_fault_address(self: *const Context) u64 {
+ return self.cr2;
+ }
};
diff --git a/mirai/crimson/types/corpse.zig b/mirai/crimson/types/corpse.zig
index 4e3479c..4790aa8 100644
--- a/mirai/crimson/types/corpse.zig
+++ b/mirai/crimson/types/corpse.zig
@@ -8,11 +8,32 @@ const constants = @import("../constants/constants.zig");
const ExceptionType = constants.ExceptionType;
pub const Corpse = struct {
- kata_id: u64, thread_id: u64, exception_type: ExceptionType, exception_code: u64, exception_subcode: u64,
- fault_address: u64, identity: Identity, context: Context, float_state: FloatState, debug_state: DebugState,
- stack_snapshot: [4096]u8, stack_snapshot_size: u64, memory_snapshot: [4096]u8,
- memory_snapshot_address: u64, memory_snapshot_size: u64, timestamp: u64, valid: bool,
- pub fn clear(self: *Corpse) void { self.valid = false; self.stack_snapshot_size = 0; self.memory_snapshot_size = 0; }
- pub fn is_valid(self: *const Corpse) bool { return self.valid; }
- pub fn mark_valid(self: *Corpse) void { self.valid = true; }
+ kata_id: u64,
+ thread_id: u64,
+ exception_type: ExceptionType,
+ exception_code: u64,
+ exception_subcode: u64,
+ fault_address: u64,
+ identity: Identity,
+ context: Context,
+ float_state: FloatState,
+ debug_state: DebugState,
+ stack_snapshot: [4096]u8,
+ stack_snapshot_size: u64,
+ memory_snapshot: [4096]u8,
+ memory_snapshot_address: u64,
+ memory_snapshot_size: u64,
+ timestamp: u64,
+ valid: bool,
+ pub fn clear(self: *Corpse) void {
+ self.valid = false;
+ self.stack_snapshot_size = 0;
+ self.memory_snapshot_size = 0;
+ }
+ pub fn is_valid(self: *const Corpse) bool {
+ return self.valid;
+ }
+ pub fn mark_valid(self: *Corpse) void {
+ self.valid = true;
+ }
};
diff --git a/mirai/crimson/types/exception.zig b/mirai/crimson/types/exception.zig
index 47723e5..1b9d5ec 100644
--- a/mirai/crimson/types/exception.zig
+++ b/mirai/crimson/types/exception.zig
@@ -6,12 +6,30 @@ const Frame = @import("frame.zig").Frame;
const ExceptionType = constants.ExceptionType;
pub const Exception = struct {
- exception_type: ExceptionType, code: u64, subcode: u64, vector: u8, address: u64,
- context: *Context, frame: *Frame, kata_id: u64, thread_id: u64, recoverable: bool,
+ exception_type: ExceptionType,
+ code: u64,
+ subcode: u64,
+ vector: u8,
+ address: u64,
+ context: *Context,
+ frame: *Frame,
+ kata_id: u64,
+ thread_id: u64,
+ recoverable: bool,
- pub fn is_kernel(self: *const Exception) bool { return self.kata_id == 0; }
- pub fn is_user(self: *const Exception) bool { return self.kata_id != 0; }
- pub fn is_page_fault(self: *const Exception) bool { return self.vector == 14; }
- pub fn is_fatal(self: *const Exception) bool { return !self.recoverable; }
- pub fn get_type_name(self: *const Exception) []const u8 { return self.exception_type.name(); }
+ pub fn is_kernel(self: *const Exception) bool {
+ return self.kata_id == 0;
+ }
+ pub fn is_user(self: *const Exception) bool {
+ return self.kata_id != 0;
+ }
+ pub fn is_page_fault(self: *const Exception) bool {
+ return self.vector == 14;
+ }
+ pub fn is_fatal(self: *const Exception) bool {
+ return !self.recoverable;
+ }
+ pub fn get_type_name(self: *const Exception) []const u8 {
+ return self.exception_type.name();
+ }
};
diff --git a/mirai/crimson/types/frame.zig b/mirai/crimson/types/frame.zig
index 5960654..20f89fb 100644
--- a/mirai/crimson/types/frame.zig
+++ b/mirai/crimson/types/frame.zig
@@ -1,11 +1,24 @@
//! Interrupt Stack Frame
pub const Frame = extern struct {
- error_code: u64, rip: u64, cs: u64, rflags: u64, rsp: u64, ss: u64,
- pub fn is_user_mode(self: *const Frame) bool { return (self.cs & 0x3) == 3; }
- pub fn is_kernel_mode(self: *const Frame) bool { return (self.cs & 0x3) == 0; }
+ error_code: u64,
+ rip: u64,
+ cs: u64,
+ rflags: u64,
+ rsp: u64,
+ ss: u64,
+ pub fn is_user_mode(self: *const Frame) bool {
+ return (self.cs & 0x3) == 3;
+ }
+ pub fn is_kernel_mode(self: *const Frame) bool {
+ return (self.cs & 0x3) == 0;
+ }
};
pub const FrameNoError = extern struct {
- rip: u64, cs: u64, rflags: u64, rsp: u64, ss: u64,
+ rip: u64,
+ cs: u64,
+ rflags: u64,
+ rsp: u64,
+ ss: u64,
};
diff --git a/mirai/crimson/types/identity.zig b/mirai/crimson/types/identity.zig
index 197ca22..cc02149 100644
--- a/mirai/crimson/types/identity.zig
+++ b/mirai/crimson/types/identity.zig
@@ -1,8 +1,16 @@
//! Exception Identity
pub const Identity = struct {
- thread_id: u64, kata_id: u64, thread_port: u64, kata_port: u64,
- thread_name: [32]u8, kata_name: [32]u8,
- pub fn clear(self: *Identity) void { self.* = Identity{ .thread_id = 0, .kata_id = 0, .thread_port = 0, .kata_port = 0, .thread_name = [_]u8{0} ** 32, .kata_name = [_]u8{0} ** 32 }; }
- pub fn is_kernel(self: *const Identity) bool { return self.kata_id == 0; }
+ thread_id: u64,
+ kata_id: u64,
+ thread_port: u64,
+ kata_port: u64,
+ thread_name: [32]u8,
+ kata_name: [32]u8,
+ pub fn clear(self: *Identity) void {
+ self.* = Identity{ .thread_id = 0, .kata_id = 0, .thread_port = 0, .kata_port = 0, .thread_name = [_]u8{0} ** 32, .kata_name = [_]u8{0} ** 32 };
+ }
+ pub fn is_kernel(self: *const Identity) bool {
+ return self.kata_id == 0;
+ }
};
diff --git a/mirai/crimson/types/port.zig b/mirai/crimson/types/port.zig
index dd01851..fc47fc4 100644
--- a/mirai/crimson/types/port.zig
+++ b/mirai/crimson/types/port.zig
@@ -7,9 +7,18 @@ const Flavor = constants.Flavor;
pub const PortOwner = enum(u8) { none = 0, thread = 1, kata = 2, host = 3 };
pub const Port = struct {
- port_id: u64, behavior: Behavior, flavor: Flavor, owner: PortOwner, owner_id: u64, active: bool,
- pub fn is_valid(self: *const Port) bool { return self.port_id != 0 and self.active; }
- pub fn clear(self: *Port) void { self.* = Port{ .port_id = 0, .behavior = .default, .flavor = .none, .owner = .none, .owner_id = 0, .active = false }; }
+ port_id: u64,
+ behavior: Behavior,
+ flavor: Flavor,
+ owner: PortOwner,
+ owner_id: u64,
+ active: bool,
+ pub fn is_valid(self: *const Port) bool {
+ return self.port_id != 0 and self.active;
+ }
+ pub fn clear(self: *Port) void {
+ self.* = Port{ .port_id = 0, .behavior = .default, .flavor = .none, .owner = .none, .owner_id = 0, .active = false };
+ }
};
pub fn create_port(port_id: u64, owner: PortOwner, owner_id: u64) Port {
diff --git a/mirai/drivers/drivers.zig b/mirai/drivers/drivers.zig
index b12736b..424397a 100644
--- a/mirai/drivers/drivers.zig
+++ b/mirai/drivers/drivers.zig
@@ -1,3 +1,4 @@
//! Drivers
pub const serial = @import("serial/serial.zig");
+pub const pit = @import("pit/pit.zig");
diff --git a/mirai/drivers/pit/constants.zig b/mirai/drivers/pit/constants.zig
new file mode 100644
index 0000000..9aa8dec
--- /dev/null
+++ b/mirai/drivers/pit/constants.zig
@@ -0,0 +1,15 @@
+//! PIT Constants
+
+pub const channel0_data: u16 = 0x40;
+pub const channel1_data: u16 = 0x41;
+pub const channel2_data: u16 = 0x42;
+pub const command: u16 = 0x43;
+
+pub const base_frequency: u32 = 1193182;
+pub const target_frequency: u32 = 1000;
+
+pub const mode_square_wave: u8 = 0x36;
+pub const mode_rate_generator: u8 = 0x34;
+
+pub const irq: u4 = 0;
+pub const vector: u8 = 32;
diff --git a/mirai/drivers/pit/handler.zig b/mirai/drivers/pit/handler.zig
new file mode 100644
index 0000000..4d3d3b0
--- /dev/null
+++ b/mirai/drivers/pit/handler.zig
@@ -0,0 +1,35 @@
+//! PIT IRQ Handler
+
+const constants = @import("constants.zig");
+const pic = @import("../../interrupts/pic/pic.zig");
+const idt = @import("../../interrupts/idt.zig");
+
+var ticks: u64 = 0;
+var tick_callback: ?*const fn () void = null;
+
+pub fn handler(_: u8) void {
+ ticks += 1;
+
+ if (tick_callback) |callback| {
+ callback();
+ }
+
+ pic.send_eoi(constants.irq);
+}
+
+pub fn register() void {
+ idt.register_irq(constants.irq, &handler);
+ pic.enable_irq(constants.irq);
+}
+
+pub fn set_callback(callback: *const fn () void) void {
+ tick_callback = callback;
+}
+
+pub fn clear_callback() void {
+ tick_callback = null;
+}
+
+pub fn get_ticks() u64 {
+ return ticks;
+}
diff --git a/mirai/drivers/pit/init.zig b/mirai/drivers/pit/init.zig
new file mode 100644
index 0000000..f31e47f
--- /dev/null
+++ b/mirai/drivers/pit/init.zig
@@ -0,0 +1,16 @@
+//! PIT Initialization
+
+const constants = @import("constants.zig");
+const asm_io = @import("../../asm/io/io.zig");
+
+pub fn init(frequency: u32) void {
+ const divisor: u16 = @truncate(constants.base_frequency / frequency);
+
+ asm_io.outb(constants.command, constants.mode_square_wave);
+ asm_io.outb(constants.channel0_data, @truncate(divisor));
+ asm_io.outb(constants.channel0_data, @truncate(divisor >> 8));
+}
+
+pub fn init_default() void {
+ init(constants.target_frequency);
+}
diff --git a/mirai/drivers/pit/pit.zig b/mirai/drivers/pit/pit.zig
new file mode 100644
index 0000000..db0f12a
--- /dev/null
+++ b/mirai/drivers/pit/pit.zig
@@ -0,0 +1,10 @@
+//! PIT - Programmable Interval Timer
+
+pub const constants = @import("constants.zig");
+pub const init = @import("init.zig");
+pub const handler = @import("handler.zig");
+
+pub const initialize = init.init_default;
+pub const register = handler.register;
+pub const set_callback = handler.set_callback;
+pub const get_ticks = handler.get_ticks;
diff --git a/mirai/interrupts/handlers/common.zig b/mirai/interrupts/handlers/common.zig
new file mode 100644
index 0000000..9c80580
--- /dev/null
+++ b/mirai/interrupts/handlers/common.zig
@@ -0,0 +1,30 @@
+//! Common Interrupt Entry/Exit
+
+pub const InterruptFrame = extern struct {
+ r15: u64,
+ r14: u64,
+ r13: u64,
+ r12: u64,
+ r11: u64,
+ r10: u64,
+ r9: u64,
+ r8: u64,
+ rbp: u64,
+ rdi: u64,
+ rsi: u64,
+ rdx: u64,
+ rcx: u64,
+ rbx: u64,
+ rax: u64,
+ vector: u64,
+ error_code: u64,
+ rip: u64,
+ cs: u64,
+ rflags: u64,
+ rsp: u64,
+ ss: u64,
+};
+
+comptime {
+ if (@sizeOf(InterruptFrame) != 22 * 8) @compileError("InterruptFrame size mismatch");
+}
diff --git a/mirai/interrupts/handlers/exceptions.zig b/mirai/interrupts/handlers/exceptions.zig
new file mode 100644
index 0000000..87e63db
--- /dev/null
+++ b/mirai/interrupts/handlers/exceptions.zig
@@ -0,0 +1,89 @@
+//! Exception Handler Stubs (Vectors 0-31)
+
+const common = @import("common.zig");
+const InterruptFrame = common.InterruptFrame;
+const asm_stubs = @import("../../asm/interrupts/stubs.zig");
+
+const crimson = @import("../../crimson/crimson.zig");
+
+fn make_handler(comptime vector: u8, comptime has_error_code: bool) fn () callconv(.Naked) void {
+ return struct {
+ fn handler() callconv(.Naked) void {
+ if (!has_error_code) {
+ asm volatile ("push $0");
+ }
+ asm volatile ("push %[v]"
+ :
+ : [v] "i" (vector),
+ );
+ asm volatile (asm_stubs.push_all ++
+ \\mov %%rsp, %%rdi
+ \\call exception_dispatch
+ ++ asm_stubs.pop_all ++ asm_stubs.iret_cleanup);
+ }
+ }.handler;
+}
+
+export fn exception_dispatch(frame: *InterruptFrame) void {
+ const vector: u8 = @truncate(frame.vector);
+
+ var exception = crimson.handlers.create_exception(
+ vector,
+ frame.error_code,
+ frame.rip,
+ frame.rsp,
+ );
+
+ const action = crimson.handlers.dispatch(&exception);
+
+ switch (action) {
+ .resume_execution => {},
+ .terminate => crimson.collapse(&exception),
+ .collapse => crimson.collapse(&exception),
+ else => crimson.collapse(&exception),
+ }
+}
+
+pub const exception_0 = make_handler(0, false);
+pub const exception_1 = make_handler(1, false);
+pub const exception_2 = make_handler(2, false);
+pub const exception_3 = make_handler(3, false);
+pub const exception_4 = make_handler(4, false);
+pub const exception_5 = make_handler(5, false);
+pub const exception_6 = make_handler(6, false);
+pub const exception_7 = make_handler(7, false);
+pub const exception_8 = make_handler(8, true);
+pub const exception_9 = make_handler(9, false);
+pub const exception_10 = make_handler(10, true);
+pub const exception_11 = make_handler(11, true);
+pub const exception_12 = make_handler(12, true);
+pub const exception_13 = make_handler(13, true);
+pub const exception_14 = make_handler(14, true);
+pub const exception_15 = make_handler(15, false);
+pub const exception_16 = make_handler(16, false);
+pub const exception_17 = make_handler(17, true);
+pub const exception_18 = make_handler(18, false);
+pub const exception_19 = make_handler(19, false);
+pub const exception_20 = make_handler(20, false);
+pub const exception_21 = make_handler(21, true);
+pub const exception_22 = make_handler(22, false);
+pub const exception_23 = make_handler(23, false);
+pub const exception_24 = make_handler(24, false);
+pub const exception_25 = make_handler(25, false);
+pub const exception_26 = make_handler(26, false);
+pub const exception_27 = make_handler(27, false);
+pub const exception_28 = make_handler(28, false);
+pub const exception_29 = make_handler(29, true);
+pub const exception_30 = make_handler(30, true);
+pub const exception_31 = make_handler(31, false);
+
+pub const stubs = [32]*const fn () callconv(.Naked) void{
+ &exception_0, &exception_1, &exception_2, &exception_3,
+ &exception_4, &exception_5, &exception_6, &exception_7,
+ &exception_8, &exception_9, &exception_10, &exception_11,
+ &exception_12, &exception_13, &exception_14, &exception_15,
+ &exception_16, &exception_17, &exception_18, &exception_19,
+ &exception_20, &exception_21, &exception_22, &exception_23,
+ &exception_24, &exception_25, &exception_26, &exception_27,
+ &exception_28, &exception_29, &exception_30, &exception_31,
+};
diff --git a/mirai/interrupts/handlers/handlers.zig b/mirai/interrupts/handlers/handlers.zig
new file mode 100644
index 0000000..f32cc8e
--- /dev/null
+++ b/mirai/interrupts/handlers/handlers.zig
@@ -0,0 +1,9 @@
+//! IDT Handlers
+
+pub const common = @import("common.zig");
+pub const exceptions = @import("exceptions.zig");
+pub const hardware = @import("hardware.zig");
+
+pub const InterruptFrame = common.InterruptFrame;
+pub const register_irq = hardware.register_handler;
+pub const unregister_irq = hardware.unregister_handler;
diff --git a/mirai/interrupts/handlers/hardware.zig b/mirai/interrupts/handlers/hardware.zig
new file mode 100644
index 0000000..6b1d09d
--- /dev/null
+++ b/mirai/interrupts/handlers/hardware.zig
@@ -0,0 +1,66 @@
+//! Hardware IRQ Stubs (Vectors 32-47)
+
+const common = @import("common.zig");
+const InterruptFrame = common.InterruptFrame;
+const asm_stubs = @import("../../asm/interrupts/stubs.zig");
+
+var irq_handlers: [16]?*const fn (u8) void = [_]?*const fn (u8) void{null} ** 16;
+
+pub fn register_handler(irq: u4, handler: *const fn (u8) void) void {
+ irq_handlers[irq] = handler;
+}
+
+pub fn unregister_handler(irq: u4) void {
+ irq_handlers[irq] = null;
+}
+
+fn make_irq_handler(comptime irq: u8) fn () callconv(.Naked) void {
+ return struct {
+ fn handler() callconv(.Naked) void {
+ asm volatile ("push $0");
+ asm volatile ("push %[v]"
+ :
+ : [v] "i" (irq + 32),
+ );
+ asm volatile (asm_stubs.push_all ++
+ \\mov %%rsp, %%rdi
+ \\call irq_dispatch
+ ++ asm_stubs.pop_all ++ asm_stubs.iret_cleanup);
+ }
+ }.handler;
+}
+
+export fn irq_dispatch(frame: *InterruptFrame) void {
+ const vector: u8 = @truncate(frame.vector);
+ const irq = vector - 32;
+
+ if (irq < 16) {
+ if (irq_handlers[irq]) |handler| {
+ handler(irq);
+ }
+ }
+}
+
+pub const irq_0 = make_irq_handler(0);
+pub const irq_1 = make_irq_handler(1);
+pub const irq_2 = make_irq_handler(2);
+pub const irq_3 = make_irq_handler(3);
+pub const irq_4 = make_irq_handler(4);
+pub const irq_5 = make_irq_handler(5);
+pub const irq_6 = make_irq_handler(6);
+pub const irq_7 = make_irq_handler(7);
+pub const irq_8 = make_irq_handler(8);
+pub const irq_9 = make_irq_handler(9);
+pub const irq_10 = make_irq_handler(10);
+pub const irq_11 = make_irq_handler(11);
+pub const irq_12 = make_irq_handler(12);
+pub const irq_13 = make_irq_handler(13);
+pub const irq_14 = make_irq_handler(14);
+pub const irq_15 = make_irq_handler(15);
+
+pub const stubs = [16]*const fn () callconv(.Naked) void{
+ &irq_0, &irq_1, &irq_2, &irq_3,
+ &irq_4, &irq_5, &irq_6, &irq_7,
+ &irq_8, &irq_9, &irq_10, &irq_11,
+ &irq_12, &irq_13, &irq_14, &irq_15,
+};
diff --git a/mirai/interrupts/idt.zig b/mirai/interrupts/idt.zig
new file mode 100644
index 0000000..7cafb4f
--- /dev/null
+++ b/mirai/interrupts/idt.zig
@@ -0,0 +1,49 @@
+//! IDT - Interrupt Descriptor Table
+
+const gdt = @import("../boot/gdt/gdt.zig");
+const asm_int = @import("../asm/interrupts/interrupts.zig");
+
+pub const types = @import("types/types.zig");
+pub const table = @import("table/table.zig");
+pub const handlers = @import("handlers/handlers.zig");
+pub const load = @import("load/load.zig");
+pub const pic = @import("pic/pic.zig");
+
+pub const Gate64 = types.Gate64;
+pub const Descriptor = types.Descriptor;
+pub const InterruptFrame = handlers.InterruptFrame;
+
+pub const set_gate = table.set_gate;
+pub const set_interrupt = table.set_interrupt;
+pub const set_trap = table.set_trap;
+pub const register_irq = handlers.register_irq;
+pub const unregister_irq = handlers.unregister_irq;
+
+pub fn initialize() void {
+ pic.remap();
+ pic.mask_all();
+
+ const selector = gdt.selectors.kernel_code_selector;
+
+ for (0..32) |i| {
+ const vector: u8 = @truncate(i);
+ const handler_ptr = @intFromPtr(handlers.exceptions.stubs[i]);
+ table.set_interrupt(vector, handler_ptr, selector);
+ }
+
+ for (0..16) |i| {
+ const vector: u8 = @truncate(i + 32);
+ const handler_ptr = @intFromPtr(handlers.hardware.stubs[i]);
+ table.set_interrupt(vector, handler_ptr, selector);
+ }
+
+ load.load();
+}
+
+pub fn enable() void {
+ asm_int.enable();
+}
+
+pub fn disable() void {
+ asm_int.disable();
+}
diff --git a/mirai/interrupts/load/lidt.zig b/mirai/interrupts/load/lidt.zig
new file mode 100644
index 0000000..926518d
--- /dev/null
+++ b/mirai/interrupts/load/lidt.zig
@@ -0,0 +1,20 @@
+//! LIDT Operations
+
+const types = @import("../types/types.zig");
+const table = @import("../table/table.zig");
+const asm_int = @import("../../asm/interrupts/interrupts.zig");
+
+pub fn lidt(desc: *const types.Descriptor) void {
+ asm_int.lidt(desc);
+}
+
+pub fn load() void {
+ const desc = types.Descriptor.from_table(&table.entries.entries);
+ lidt(&desc);
+}
+
+pub fn sidt() types.Descriptor {
+ var desc: types.Descriptor = undefined;
+ asm_int.sidt(&desc);
+ return desc;
+}
diff --git a/mirai/interrupts/load/load.zig b/mirai/interrupts/load/load.zig
new file mode 100644
index 0000000..567a9f0
--- /dev/null
+++ b/mirai/interrupts/load/load.zig
@@ -0,0 +1,6 @@
+//! IDT Load Operations
+
+pub const lidt = @import("lidt.zig");
+
+pub const load = lidt.load;
+pub const sidt = lidt.sidt;
diff --git a/mirai/interrupts/pic/eoi.zig b/mirai/interrupts/pic/eoi.zig
new file mode 100644
index 0000000..810ea37
--- /dev/null
+++ b/mirai/interrupts/pic/eoi.zig
@@ -0,0 +1,20 @@
+//! PIC End-of-Interrupt
+
+const ports = @import("ports.zig");
+const asm_io = @import("../../asm/io/io.zig");
+
+pub fn send(irq: u4) void {
+ if (irq >= 8) {
+ asm_io.outb(ports.pic2_command, ports.eoi);
+ }
+ asm_io.outb(ports.pic1_command, ports.eoi);
+}
+
+pub fn send_master() void {
+ asm_io.outb(ports.pic1_command, ports.eoi);
+}
+
+pub fn send_slave() void {
+ asm_io.outb(ports.pic2_command, ports.eoi);
+ asm_io.outb(ports.pic1_command, ports.eoi);
+}
diff --git a/mirai/interrupts/pic/init.zig b/mirai/interrupts/pic/init.zig
new file mode 100644
index 0000000..2f84b8a
--- /dev/null
+++ b/mirai/interrupts/pic/init.zig
@@ -0,0 +1,41 @@
+//! PIC Initialization
+
+const ports = @import("ports.zig");
+const asm_io = @import("../../asm/io/io.zig");
+
+pub fn remap() void {
+ const mask1 = asm_io.inb(ports.pic1_data);
+ const mask2 = asm_io.inb(ports.pic2_data);
+
+ asm_io.outb(ports.pic1_command, ports.icw1_init | ports.icw1_icw4);
+ io_wait();
+ asm_io.outb(ports.pic2_command, ports.icw1_init | ports.icw1_icw4);
+ io_wait();
+
+ asm_io.outb(ports.pic1_data, ports.vector_offset_master);
+ io_wait();
+ asm_io.outb(ports.pic2_data, ports.vector_offset_slave);
+ io_wait();
+
+ asm_io.outb(ports.pic1_data, 4);
+ io_wait();
+ asm_io.outb(ports.pic2_data, 2);
+ io_wait();
+
+ asm_io.outb(ports.pic1_data, ports.icw4_8086);
+ io_wait();
+ asm_io.outb(ports.pic2_data, ports.icw4_8086);
+ io_wait();
+
+ asm_io.outb(ports.pic1_data, mask1);
+ asm_io.outb(ports.pic2_data, mask2);
+}
+
+pub fn disable() void {
+ asm_io.outb(ports.pic1_data, 0xFF);
+ asm_io.outb(ports.pic2_data, 0xFF);
+}
+
+fn io_wait() void {
+ asm_io.outb(0x80, 0);
+}
diff --git a/mirai/interrupts/pic/mask.zig b/mirai/interrupts/pic/mask.zig
new file mode 100644
index 0000000..3b98e28
--- /dev/null
+++ b/mirai/interrupts/pic/mask.zig
@@ -0,0 +1,40 @@
+//! PIC IRQ Masking
+
+const ports = @import("ports.zig");
+const asm_io = @import("../../asm/io/io.zig");
+
+pub fn enable_irq(irq: u4) void {
+ if (irq < 8) {
+ const mask = asm_io.inb(ports.pic1_data);
+ asm_io.outb(ports.pic1_data, mask & ~(@as(u8, 1) << @truncate(irq)));
+ } else {
+ const mask = asm_io.inb(ports.pic2_data);
+ asm_io.outb(ports.pic2_data, mask & ~(@as(u8, 1) << @truncate(irq - 8)));
+ }
+}
+
+pub fn disable_irq(irq: u4) void {
+ if (irq < 8) {
+ const mask = asm_io.inb(ports.pic1_data);
+ asm_io.outb(ports.pic1_data, mask | (@as(u8, 1) << @truncate(irq)));
+ } else {
+ const mask = asm_io.inb(ports.pic2_data);
+ asm_io.outb(ports.pic2_data, mask | (@as(u8, 1) << @truncate(irq - 8)));
+ }
+}
+
+pub fn mask_all() void {
+ asm_io.outb(ports.pic1_data, 0xFF);
+ asm_io.outb(ports.pic2_data, 0xFF);
+}
+
+pub fn unmask_all() void {
+ asm_io.outb(ports.pic1_data, 0x00);
+ asm_io.outb(ports.pic2_data, 0x00);
+}
+
+pub fn get_mask() u16 {
+ const low = asm_io.inb(ports.pic1_data);
+ const high = asm_io.inb(ports.pic2_data);
+ return @as(u16, high) << 8 | low;
+}
diff --git a/mirai/interrupts/pic/pic.zig b/mirai/interrupts/pic/pic.zig
new file mode 100644
index 0000000..ee34508
--- /dev/null
+++ b/mirai/interrupts/pic/pic.zig
@@ -0,0 +1,13 @@
+//! PIC - 8259A Programmable Interrupt Controller
+
+pub const ports = @import("ports.zig");
+pub const init = @import("init.zig");
+pub const mask = @import("mask.zig");
+pub const eoi = @import("eoi.zig");
+
+pub const remap = init.remap;
+pub const disable = init.disable;
+pub const enable_irq = mask.enable_irq;
+pub const disable_irq = mask.disable_irq;
+pub const mask_all = mask.mask_all;
+pub const send_eoi = eoi.send;
diff --git a/mirai/interrupts/pic/ports.zig b/mirai/interrupts/pic/ports.zig
new file mode 100644
index 0000000..aba363f
--- /dev/null
+++ b/mirai/interrupts/pic/ports.zig
@@ -0,0 +1,15 @@
+//! PIC I/O Ports
+
+pub const pic1_command: u16 = 0x20;
+pub const pic1_data: u16 = 0x21;
+pub const pic2_command: u16 = 0xA0;
+pub const pic2_data: u16 = 0xA1;
+
+pub const icw1_icw4: u8 = 0x01;
+pub const icw1_init: u8 = 0x10;
+pub const icw4_8086: u8 = 0x01;
+
+pub const eoi: u8 = 0x20;
+
+pub const vector_offset_master: u8 = 32;
+pub const vector_offset_slave: u8 = 40;
diff --git a/mirai/interrupts/table/entries.zig b/mirai/interrupts/table/entries.zig
new file mode 100644
index 0000000..d62b1e7
--- /dev/null
+++ b/mirai/interrupts/table/entries.zig
@@ -0,0 +1,5 @@
+//! IDT Entries Table
+
+const types = @import("../types/types.zig");
+
+pub var entries: [256]types.Gate64 = [_]types.Gate64{types.Gate64.empty()} ** 256;
diff --git a/mirai/interrupts/table/install.zig b/mirai/interrupts/table/install.zig
new file mode 100644
index 0000000..72b9bab
--- /dev/null
+++ b/mirai/interrupts/table/install.zig
@@ -0,0 +1,27 @@
+//! IDT Gate Installation
+
+const types = @import("../types/types.zig");
+const entries = @import("entries.zig");
+
+pub fn set_gate(vector: u8, handler: u64, selector: u16, ist: u3, dpl: types.DPL, gate_type: types.GateType) void {
+ entries.entries[vector] = switch (gate_type) {
+ .interrupt => types.Gate64.interrupt(handler, selector, ist, dpl),
+ .trap => types.Gate64.trap(handler, selector, ist, dpl),
+ };
+}
+
+pub fn set_interrupt(vector: u8, handler: u64, selector: u16) void {
+ set_gate(vector, handler, selector, 0, .ring0, .interrupt);
+}
+
+pub fn set_trap(vector: u8, handler: u64, selector: u16) void {
+ set_gate(vector, handler, selector, 0, .ring0, .trap);
+}
+
+pub fn set_interrupt_ist(vector: u8, handler: u64, selector: u16, ist: u3) void {
+ set_gate(vector, handler, selector, ist, .ring0, .interrupt);
+}
+
+pub fn clear_gate(vector: u8) void {
+ entries.entries[vector] = types.Gate64.empty();
+}
diff --git a/mirai/interrupts/table/table.zig b/mirai/interrupts/table/table.zig
new file mode 100644
index 0000000..70e46bf
--- /dev/null
+++ b/mirai/interrupts/table/table.zig
@@ -0,0 +1,10 @@
+//! IDT Table
+
+pub const entries = @import("entries.zig");
+pub const install = @import("install.zig");
+
+pub const set_gate = install.set_gate;
+pub const set_interrupt = install.set_interrupt;
+pub const set_trap = install.set_trap;
+pub const set_interrupt_ist = install.set_interrupt_ist;
+pub const clear_gate = install.clear_gate;
diff --git a/mirai/interrupts/types/descriptor.zig b/mirai/interrupts/types/descriptor.zig
new file mode 100644
index 0000000..7b9865d
--- /dev/null
+++ b/mirai/interrupts/types/descriptor.zig
@@ -0,0 +1,19 @@
+//! IDT Descriptor for LIDT
+
+const gate = @import("gate.zig");
+
+pub const Descriptor = packed struct(u80) {
+ limit: u16,
+ base: u64,
+
+ pub fn from_table(table: *const [256]gate.Gate64) Descriptor {
+ return Descriptor{
+ .limit = @sizeOf([256]gate.Gate64) - 1,
+ .base = @intFromPtr(table),
+ };
+ }
+};
+
+comptime {
+ if (@sizeOf(Descriptor) != 10) @compileError("Descriptor must be 10 bytes");
+}
diff --git a/mirai/interrupts/types/gate.zig b/mirai/interrupts/types/gate.zig
new file mode 100644
index 0000000..ff046a2
--- /dev/null
+++ b/mirai/interrupts/types/gate.zig
@@ -0,0 +1,67 @@
+//! IDT Gate Descriptor (64-bit)
+
+pub const GateType = enum(u4) {
+ interrupt = 0xE,
+ trap = 0xF,
+};
+
+pub const DPL = enum(u2) {
+ ring0 = 0,
+ ring1 = 1,
+ ring2 = 2,
+ ring3 = 3,
+};
+
+pub const Gate64 = packed struct(u128) {
+ offset_low: u16,
+ selector: u16,
+ ist: u3,
+ reserved0: u5 = 0,
+ gate_type: GateType,
+ zero: u1 = 0,
+ dpl: DPL,
+ present: bool,
+ offset_mid: u16,
+ offset_high: u32,
+ reserved1: u32 = 0,
+
+ pub fn empty() Gate64 {
+ return @bitCast(@as(u128, 0));
+ }
+
+ pub fn interrupt(handler: u64, selector: u16, ist: u3, dpl: DPL) Gate64 {
+ return Gate64{
+ .offset_low = @truncate(handler),
+ .selector = selector,
+ .ist = ist,
+ .gate_type = .interrupt,
+ .dpl = dpl,
+ .present = true,
+ .offset_mid = @truncate(handler >> 16),
+ .offset_high = @truncate(handler >> 32),
+ };
+ }
+
+ pub fn trap(handler: u64, selector: u16, ist: u3, dpl: DPL) Gate64 {
+ return Gate64{
+ .offset_low = @truncate(handler),
+ .selector = selector,
+ .ist = ist,
+ .gate_type = .trap,
+ .dpl = dpl,
+ .present = true,
+ .offset_mid = @truncate(handler >> 16),
+ .offset_high = @truncate(handler >> 32),
+ };
+ }
+
+ pub fn get_offset(self: Gate64) u64 {
+ return @as(u64, self.offset_low) |
+ (@as(u64, self.offset_mid) << 16) |
+ (@as(u64, self.offset_high) << 32);
+ }
+};
+
+comptime {
+ if (@sizeOf(Gate64) != 16) @compileError("Gate64 must be 16 bytes");
+}
diff --git a/mirai/interrupts/types/types.zig b/mirai/interrupts/types/types.zig
new file mode 100644
index 0000000..292a2df
--- /dev/null
+++ b/mirai/interrupts/types/types.zig
@@ -0,0 +1,9 @@
+//! IDT Types
+
+pub const gate = @import("gate.zig");
+pub const descriptor = @import("descriptor.zig");
+
+pub const Gate64 = gate.Gate64;
+pub const GateType = gate.GateType;
+pub const DPL = gate.DPL;
+pub const Descriptor = descriptor.Descriptor;
diff --git a/mirai/pmm/bitmap/operations.zig b/mirai/pmm/bitmap/operations.zig
index d793fa3..cade105 100644
--- a/mirai/pmm/bitmap/operations.zig
+++ b/mirai/pmm/bitmap/operations.zig
@@ -79,4 +79,4 @@ pub fn count_clear_bits(bitmap: []const u8, max_bit: u64) u64 {
}
}
return count;
-} \ No newline at end of file
+}
diff --git a/shared/fs/afs/constants/magic.zig b/shared/fs/afs/constants/magic.zig
index 757bcab..84f46db 100644
--- a/shared/fs/afs/constants/magic.zig
+++ b/shared/fs/afs/constants/magic.zig
@@ -12,7 +12,7 @@ pub const journal_signature: u32 = 0x4A4E524C;
/// AFS partition type GUID: 414B4942-4146-5300-0000-000000000001
pub const partition_type_guid = [16]u8{
0x42, 0x49, 0x4B, 0x41,
- 0x46, 0x41,
- 0x00, 0x53,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x46, 0x41, 0x00, 0x53,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01,
};