aboutsummaryrefslogtreecommitdiff
path: root/src/lib/interrupts.zig
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-08-01 13:07:30 +0200
committerHimbeer <himbeer@disroot.org>2024-08-01 13:07:30 +0200
commitc22a1c2214d5f3256684fa08262501cfd70be915 (patch)
tree28ed508137c86d15bb2c7e15a6ec2802d1cea1ed /src/lib/interrupts.zig
parent017c63d49f4c6fdd2f762dd7d14323fbbdb7775e (diff)
Flatten 'lib' directory into main 'src' tree
Diffstat (limited to 'src/lib/interrupts.zig')
-rw-r--r--src/lib/interrupts.zig301
1 files changed, 0 insertions, 301 deletions
diff --git a/src/lib/interrupts.zig b/src/lib/interrupts.zig
deleted file mode 100644
index 66c8acd..0000000
--- a/src/lib/interrupts.zig
+++ /dev/null
@@ -1,301 +0,0 @@
-// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
-//
-// SPDX-License-Identifier: AGPL-3.0-or-later
-
-const std = @import("std");
-const Console = @import("Console.zig");
-const TrapFrame = @import("TrapFrame.zig");
-const plic = @import("plic.zig");
-const process = @import("process.zig");
-const riscv = @import("riscv.zig");
-const syscall = @import("syscall.zig");
-
-pub var trap_frame: TrapFrame = undefined;
-
-pub const SupervisorTrapVector = packed struct(usize) {
- pub const Mode = enum(u2) {
- direct,
- vectored,
- };
-
- mode: u2,
- base_addr: u62,
-
- pub fn fromBaseAddr(mode: Mode, base_addr: usize) SupervisorTrapVector {
- return .{
- .mode = @intFromEnum(mode),
- .base_addr = base_addr >> 2,
- };
- }
-};
-
-pub const Enable = packed struct(usize) {
- u_software: u1,
- s_software: u1,
- reserved0: u2,
- u_timer: u1,
- s_timer: u1,
- reserved1: u2,
- u_external: u1,
- s_external: u1,
- reserved2: u54,
-
- pub const none = std.mem.zeroInit(Enable, .{});
- pub const all = std.mem.zeroInit(Enable, .{
- .u_software = 1,
- .s_software = 1,
- .u_timer = 1,
- .s_timer = 1,
- .u_external = 1,
- .s_external = 1,
- });
-};
-
-pub const Cause = packed struct(usize) {
- num: u63,
- @"async": u1,
-
- pub fn isAsync(self: Cause) bool {
- return self.@"async" == 1;
- }
-};
-
-pub const AsyncCause = enum(u63) {
- user_software,
- supervisor_software,
- user_timer = 4,
- supervisor_timer,
- user_external = 8,
- supervisor_external,
- _,
-};
-
-pub const SyncCause = enum(u63) {
- instruction_address_misaligned,
- instruction_access_fault,
- illegal_instruction,
- breakpoint,
- load_access_fault = 5,
- amo_address_misaligned,
- store_or_amo_access_fault,
- ecall,
- instruction_page_fault = 12,
- load_page_fault,
- store_or_amo_page_fault = 15,
- _,
-};
-
-export fn handleTrap(epc: usize, cause: Cause, frame: *TrapFrame) usize {
- const w = Console.autoChoose().?.writer();
-
- const status = riscv.sstatus.read();
-
- if (cause.isAsync()) {
- switch (@as(AsyncCause, @enumFromInt(cause.num))) {
- .supervisor_software => w.print("Hart {d}: Software interrupt\r\n", .{frame.hart_id}) catch unreachable,
- .supervisor_timer => {
- if (status.previous_privilege == .user) {
- // Trapped from U-mode, update pc for next time slice.
- //
- // We can simply use the last node of the process list here
- // because the scheduler moves a process to the end of the queue
- // before returning into it.
-
- process.list.last.?.data.pc = epc;
- process.list.last.?.data.state = .waiting;
-
- process.schedule() catch |err| {
- std.debug.panic("schedule error: {}", .{err});
- };
- }
-
- // Don't interrupt kernel code, it may never run otherwise.
- },
- .supervisor_external => {
- const context: u14 = @intCast(2 * frame.hart_id + 1);
-
- const external_cause = plic.default.claim(context) catch |err| {
- std.debug.panic("plic claim error: {}", .{err});
- };
- if (external_cause) |source| {
- w.print("Hart {d}: External interrupt: 0x{x}\r\n", .{ frame.hart_id, source }) catch unreachable;
- handleExternal(source);
- plic.default.complete(context, source) catch |err| {
- std.debug.panic("plic complete error: {}", .{err});
- };
- }
- },
- else => {
- std.debug.panic("unhandled interrupt {}", .{cause.num});
- },
- }
- } else {
- const pid = if (status.previous_privilege == .user) blk: {
- const proc = &process.list.last.?.data;
- proc.pc = epc;
- proc.state = .waiting;
- break :blk proc.id;
- } else 0;
-
- switch (@as(SyncCause, @enumFromInt(cause.num))) {
- .illegal_instruction => {
- std.debug.panic("illegal instruction", .{});
- },
- .instruction_access_fault => {
- std.debug.panic("instruction access fault", .{});
- },
- .load_access_fault => {
- std.debug.panic("load access fault", .{});
- },
- .store_or_amo_access_fault => {
- std.debug.panic("store/amo access fault", .{});
- },
- .ecall => {
- const proc = &process.list.last.?.data;
- syscall.handler(proc, frame) catch |err| switch (err) {
- syscall.HandleError.UnknownSyscall => {
- const a7 = frame.general_purpose_registers[17];
- w.print("Hart {d}, PID = {d}: Unknown syscall, a7 = 0x{x:0>16}\r\n", .{ frame.hart_id, pid, a7 }) catch unreachable;
- },
- };
-
- return epc + 4;
- },
- .instruction_page_fault => {
- std.debug.panic("instruction page fault", .{});
- },
- .load_page_fault => {
- std.debug.panic("load page fault", .{});
- },
- .store_or_amo_page_fault => {
- std.debug.panic("store/amo page fault", .{});
- },
- else => {
- std.debug.panic("unhandled exception {d}", .{cause.num});
- },
- }
- }
-
- return epc;
-}
-
-fn handleExternal(interrupt: ?u10) void {
- _ = &interrupt;
-}
-
-export fn supervisorTrapVector() align(4) callconv(.Naked) noreturn {
- asm volatile (
- \\ csrrw t6, sscratch, t6
- \\
- \\ sd x1, 8(t6)
- \\ sd x2, 16(t6)
- \\ sd x3, 24(t6)
- \\ sd x4, 32(t6)
- \\ sd x5, 40(t6)
- \\ sd x6, 48(t6)
- \\ sd x7, 56(t6)
- \\ sd x8, 64(t6)
- \\ sd x9, 72(t6)
- \\ sd x10, 80(t6)
- \\ sd x11, 88(t6)
- \\ sd x12, 96(t6)
- \\ sd x13, 104(t6)
- \\ sd x14, 112(t6)
- \\ sd x15, 120(t6)
- \\ sd x16, 128(t6)
- \\ sd x17, 136(t6)
- \\ sd x18, 144(t6)
- \\ sd x19, 152(t6)
- \\ sd x20, 160(t6)
- \\ sd x21, 168(t6)
- \\ sd x22, 176(t6)
- \\ sd x23, 184(t6)
- \\ sd x24, 192(t6)
- \\ sd x25, 200(t6)
- \\ sd x26, 208(t6)
- \\ sd x27, 216(t6)
- \\ sd x28, 224(t6)
- \\ sd x29, 232(t6)
- \\ sd x30, 240(t6)
- \\
- \\ mv t5, t6
- \\ csrr t6, sscratch
- \\
- \\ sd x31, 248(t5)
- \\
- \\ csrw sscratch, t5
- \\
- \\ .option push
- \\ .option norelax
- \\ la gp, _global_pointer
- \\ .option pop
- \\
- \\ csrr a0, sepc
- \\ csrr a1, scause
- \\ mv a2, t5
- \\
- \\ la sp, _stvec_stack_end
- \\ call handleTrap
- \\
- \\ csrw sepc, a0
- \\
- \\ csrr t6, sscratch
- \\
- \\ ld x1, 8(t6)
- \\ ld x2, 16(t6)
- \\ ld x3, 24(t6)
- \\ ld x4, 32(t6)
- \\ ld x5, 40(t6)
- \\ ld x6, 48(t6)
- \\ ld x7, 56(t6)
- \\ ld x8, 64(t6)
- \\ ld x9, 72(t6)
- \\ ld x10, 80(t6)
- \\ ld x11, 88(t6)
- \\ ld x12, 96(t6)
- \\ ld x13, 104(t6)
- \\ ld x14, 112(t6)
- \\ ld x15, 120(t6)
- \\ ld x16, 128(t6)
- \\ ld x17, 136(t6)
- \\ ld x18, 144(t6)
- \\ ld x19, 152(t6)
- \\ ld x20, 160(t6)
- \\ ld x21, 168(t6)
- \\ ld x22, 176(t6)
- \\ ld x23, 184(t6)
- \\ ld x24, 192(t6)
- \\ ld x25, 200(t6)
- \\ ld x26, 208(t6)
- \\ ld x27, 216(t6)
- \\ ld x28, 224(t6)
- \\ ld x29, 232(t6)
- \\ ld x30, 240(t6)
- \\ ld x31, 248(t6)
- \\
- \\ sret
- );
-}
-
-pub fn init(hart_id: usize) void {
- trap_frame = .{
- .general_purpose_registers = [_]usize{0} ** 32,
- .floating_point_registers = [_]usize{0} ** 32,
- .satp = 0,
- .stack_pointer = @ptrFromInt(riscv.stackPointer()),
- .hart_id = hart_id,
- };
-
- asm volatile (
- \\ csrw sscratch, %[trapframe]
- \\
- \\ la t0, supervisorTrapVector
- \\ csrw stvec, t0
- \\
- \\ csrr t0, sstatus
- \\ ori t0, t0, 2
- \\ csrw sstatus, t0
- :
- : [trapframe] "r" (&trap_frame),
- );
-}