aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-05-13 23:27:24 +0200
committerHimbeer <himbeer@disroot.org>2024-05-13 23:27:24 +0200
commit17abd1049d12f335012578426ccfaab21b1e94c5 (patch)
tree373abe4495ec95c65758110f4f21494abbb40f71 /src
parentb016bb0b246f71d7c487320b9a12dcd7368f8054 (diff)
process: Update pc when trapping from U-mode
This fixes an issue where the same instruction of a U-mode process is executed multiple times if it's scheduled in consecutive time slices.
Diffstat (limited to 'src')
-rw-r--r--src/interrupts.zig32
-rw-r--r--src/process.zig3
2 files changed, 33 insertions, 2 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 });
};
diff --git a/src/process.zig b/src/process.zig
index 61e42de..5cec65f 100644
--- a/src/process.zig
+++ b/src/process.zig
@@ -12,10 +12,11 @@ const trap = @import("trap.zig");
pub const schedule_interval_millis = 1;
+pub var list = std.mem.zeroInit(std.DoublyLinkedList(Info), .{});
+
const num_stack_pages = 2;
var next_pid: u16 = 1;
-var list = std.mem.zeroInit(std.DoublyLinkedList(Info), .{});
pub const Error = error{
EmptySchedule,