aboutsummaryrefslogtreecommitdiff
path: root/src/interrupts.zig
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-05-03 20:19:38 +0200
committerHimbeer <himbeer@disroot.org>2024-05-03 20:19:38 +0200
commit1becdbc7660f910a65db31fe10b8b0189f535729 (patch)
tree0e57429e67ea752ccd64197fab04452882c5147a /src/interrupts.zig
parente90bb5f463e8f1fd69544f8ad1693f973160ba16 (diff)
Implement initial interrupt / trap handler
Diffstat (limited to 'src/interrupts.zig')
-rw-r--r--src/interrupts.zig85
1 files changed, 79 insertions, 6 deletions
diff --git a/src/interrupts.zig b/src/interrupts.zig
index 4f83fda..3bc2b1b 100644
--- a/src/interrupts.zig
+++ b/src/interrupts.zig
@@ -4,6 +4,7 @@
const std = @import("std");
+const debug_console = @import("sbi/debug_console.zig");
const instructions = @import("instructions.zig");
pub const SupervisorTrapVector = packed struct(usize) {
@@ -55,14 +56,86 @@ pub const TrapFrame = extern struct {
hart_id: usize, // Offset: 528
};
-export fn supervisor_trap(epc: usize, tval: usize, cause: usize, hart_id: usize, status: usize, frame: *TrapFrame) usize {
- _ = &epc;
- _ = &tval;
- _ = &cause;
- _ = &hart_id;
+pub const Cause = packed struct(usize) {
+ num: u63,
+ @"async": u1,
+
+ pub fn is_async(self: Cause) bool {
+ return self.@"async" == 1;
+ }
+};
+
+pub const AsyncCause = enum(u63) {
+ user_software = 0,
+ supervisor_software = 1,
+ user_timer = 4,
+ supervisor_timer = 5,
+ user_external = 8,
+ supervisor_external = 9,
+};
+
+pub const SyncCause = enum(u63) {
+ instruction_address_misaligned = 0,
+ instruction_access_fault = 1,
+ illegal_instruction = 2,
+ breakpoint = 3,
+ load_access_fault = 5,
+ amo_address_misaligned = 6,
+ store_or_amo_access_fault = 7,
+ ecall = 8,
+ instruction_page_fault = 12,
+ load_page_fault = 13,
+ store_or_amo_page_fault = 15,
+};
+
+export fn supervisor_trap(epc: usize, tval: usize, cause_bits: usize, hart_id: usize, status: usize, frame: *TrapFrame) usize {
_ = &status;
_ = &frame;
- return 0;
+
+ const w = debug_console.writer() catch while (true) {};
+
+ const cause: Cause = @bitCast(cause_bits);
+
+ if (cause.is_async()) {
+ switch (@as(AsyncCause, @enumFromInt(cause.num))) {
+ .supervisor_software => w.print("Hart {d}: Supervisor software interrupt\r\n", .{hart_id}) catch while (true) {},
+ .supervisor_timer => w.print("Hart {d}: Supervisor timer interrupt\r\n", .{hart_id}) catch while (true) {},
+ .supervisor_external => w.print("Hart {d}: Supervisor external interrupt\r\n", .{hart_id}) catch while (true) {},
+ else => {
+ w.print("Hart {d}: Unhandled asynchronous interrupt\r\n", .{hart_id}) catch while (true) {};
+ while (true) {}
+ },
+ }
+ } else {
+ switch (@as(SyncCause, @enumFromInt(cause.num))) {
+ .illegal_instruction => {
+ w.print("Hart {d}: Illegal instruction\r\n", .{hart_id}) catch while (true) {};
+ while (true) {}
+ },
+ .ecall => {
+ w.print("Hart {d}: Environment call from U-mode\r\n", .{hart_id}) catch while (true) {};
+ return epc + 4;
+ },
+ .instruction_page_fault => {
+ w.print("Hart {d}: Instruction page fault, tval = 0x{x:0>16}\r\n", .{ hart_id, tval }) catch while (true) {};
+ return epc + 4;
+ },
+ .load_page_fault => {
+ w.print("Hart {d}: Load page fault, tval = 0x{x:0>16}\r\n", .{ hart_id, tval }) catch while (true) {};
+ return epc + 4;
+ },
+ .store_or_amo_page_fault => {
+ w.print("Hart {d}: Store/AMO page fault, tval = 0x{x:0>16}\r\n", .{ hart_id, tval }) catch while (true) {};
+ return epc + 4;
+ },
+ else => {
+ w.print("Hart {d}: Unhandled synchronous interrupt\r\n", .{hart_id}) catch while (true) {};
+ while (true) {}
+ },
+ }
+ }
+
+ return epc;
}
export fn supervisor_trap_vector() align(4) callconv(.Naked) noreturn {