diff options
Diffstat (limited to 'src/interrupts.zig')
-rw-r--r-- | src/interrupts.zig | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/src/interrupts.zig b/src/interrupts.zig index efde552..ba5f440 100644 --- a/src/interrupts.zig +++ b/src/interrupts.zig @@ -90,7 +90,27 @@ pub const SyncCause = enum(u63) { _, }; -export fn handleTrap(epc: usize, tval: usize, cause_bits: usize, hart_id: usize, status: usize, frame: *trap.Frame) usize { +pub const Sstatus = packed struct(usize) { + u_interrupts: u1, + s_interrupts: u1, + reserved0: u2, + u_interrupts_previous: u1, + s_interrupts_previous: u1, + reserved1: u2, + previous_privilege: u1, + reserved2: u4, + fs: u2, + xs: u2, + reserved3: u1, + sum: u1, + mxr: u1, + reserved4: u12, + u_xlen: u2, + reserved5: u29, + sd: u1, +}; + +export fn handleTrap(epc: usize, tval: usize, cause_bits: usize, hart_id: usize, status: Sstatus, frame: *trap.Frame) usize { _ = &status; _ = &frame; @@ -102,6 +122,16 @@ export fn handleTrap(epc: usize, tval: usize, cause_bits: usize, hart_id: usize, switch (@as(AsyncCause, @enumFromInt(cause.num))) { .supervisor_software => w.print("Hart {d}: Software interrupt\r\n", .{hart_id}) catch while (true) {}, .supervisor_timer => { + if (status.previous_privilege == 0) { + // 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; + } + schedule() catch |err| { std.debug.panic("Hart {d}: Unable to schedule next process: {any}", .{ hart_id, err }); }; |