diff options
author | Himbeer <himbeer@disroot.org> | 2024-07-17 22:32:03 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-07-17 22:32:03 +0200 |
commit | ce729578bd4fbf4108ebcdeda8186d606d1c803e (patch) | |
tree | 33413f3cbb84f977fad53eeef055e811062ff630 /src | |
parent | b084e65f9f5d63b968081ecf82bf5d64d7d9f613 (diff) |
syscall: Replace terminate() with /process/self/terminate VFS hook
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/process.zig | 15 | ||||
-rw-r--r-- | src/lib/resources.zig | 28 | ||||
-rw-r--r-- | src/lib/rethooks.zig | 11 | ||||
-rw-r--r-- | src/lib/syscall.zig | 9 | ||||
-rw-r--r-- | src/lib/vfs.zig | 6 |
5 files changed, 55 insertions, 14 deletions
diff --git a/src/lib/process.zig b/src/lib/process.zig index d7ecd5f..85d6522 100644 --- a/src/lib/process.zig +++ b/src/lib/process.zig @@ -458,6 +458,21 @@ fn usizeFromArg(arg: anytype) usize { }; } +pub fn findThread(pid: u16, thread_id: usize) ?*Info { + var node = list.first; + while (node) |proc_node| : (node = proc_node.next) { + if (proc_node.data.id == pid and proc_node.data.thread_id == thread_id) { + return &proc_node.data; + } + } + + return null; +} + +pub fn mainThread(pid: u16) ?*Info { + return findThread(pid, 0); +} + pub fn latestThread(pid: u16) ?*Info { var latest: ?*Info = null; diff --git a/src/lib/resources.zig b/src/lib/resources.zig index f73c751..92a28b6 100644 --- a/src/lib/resources.zig +++ b/src/lib/resources.zig @@ -45,6 +45,18 @@ const iofs = struct { }; }; +const processfs = struct { + const self = struct { + fn terminate(pid: u16, thread_id: usize, _: usize) callconv(.C) sysexchange.Result(usize) { + const proc = process.findThread(pid, thread_id).?; + proc.terminate(); + process.schedule() catch |err| { + std.debug.panic("Unable to schedule because all processes are terminated: {any}", .{err}); + }; + } + }; +}; + pub const Error = error{ NoTarFileInitializer, NoConsole, @@ -53,9 +65,12 @@ pub const Error = error{ pub fn provideBuiltin() !void { try addDir("/io"); try addDir("/userinit"); + try addDir("/process"); + try addDir("/process/self"); try provideConsole(); try provideUserinit(); + try provideProcessSelf(); } fn provideConsole() !void { @@ -95,6 +110,19 @@ fn provideUserinit() !void { } } +fn provideProcessSelf() !void { + try vfs.provideResource("/process/self/terminate", .{ + .tag = .hook, + .data = .{ + .hook = .{ + .callback = processfs.self.terminate, + }, + }, + }, 0, .{ + .reclaimable = false, + }); +} + fn addFile(path: []const u8, file: File) !void { const allocator = vfs.treeRoot().allocator; diff --git a/src/lib/rethooks.zig b/src/lib/rethooks.zig index bad4d55..e81125a 100644 --- a/src/lib/rethooks.zig +++ b/src/lib/rethooks.zig @@ -3,9 +3,16 @@ // SPDX-License-Identifier: AGPL-3.0-or-later pub fn terminate() linksection(".rethooks") callconv(.Naked) noreturn { - // Syscall #100011 is "terminate". + // Syscall #100001 is "open". + // Use the "/process/self/terminate" hook to terminate the thread. asm volatile ( - \\ li a7, 100011 + \\ mv a0, a2 + \\ mv a1, a3 + \\ mv t0, a0 + \\ li a7, 100001 \\ ecall + : + : [path_c] "{t0}" ("/process/self/terminate\x00".ptr), + : "a0", "a2", "a3", "a7" ); } diff --git a/src/lib/syscall.zig b/src/lib/syscall.zig index 1533cd4..5cbc9f2 100644 --- a/src/lib/syscall.zig +++ b/src/lib/syscall.zig @@ -32,7 +32,6 @@ pub fn handler(proc: *process.Info, trap_frame: *trap.Frame) !void { 100008 => remove(trap_frame), 100009 => read(proc, trap_frame), 100010 => write(proc, trap_frame), - 100011 => terminate(proc), else => return HandleError.UnknownSyscall, } } @@ -269,11 +268,3 @@ fn write(proc: *process.Info, trap_frame: *trap.Frame) void { }; sysexchange.frameReturn(usize, trap_frame, result); } - -// terminate() noreturn -fn terminate(proc: *process.Info) noreturn { - proc.terminate(); - process.schedule() catch |err| { - std.debug.panic("Unable to schedule because all processes are terminated: {any}", .{err}); - }; -} diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig index 71dda98..46f01d6 100644 --- a/src/lib/vfs.zig +++ b/src/lib/vfs.zig @@ -72,7 +72,7 @@ pub const File = extern struct { pub const Hook = extern struct { callback: Callback, - pub const Callback = *allowzero const fn (pid: u16, data: usize) callconv(.C) sysexchange.Result(usize); + pub const Callback = *allowzero const fn (pid: u16, thread_id: usize, data: usize) callconv(.C) sysexchange.Result(usize); }; // A directory hook is a resource that provides other resources via driver callbacks. @@ -380,8 +380,8 @@ fn call(proc: *process.Info, function: *const anyopaque, args: anytype, cleanup_ fn crossProcessReturn(context: *anyopaque, driver: *const process.Info) void { const proc: *process.Info = @alignCast(@ptrCast(context)); - proc.trap_frame.general_purpose_registers[10] = driver.trap_frame.general_purpose_registers[10]; - proc.trap_frame.general_purpose_registers[11] = driver.trap_frame.general_purpose_registers[11]; + proc.trap_frame.general_purpose_registers[10] = driver.trap_frame.general_purpose_registers[12]; + proc.trap_frame.general_purpose_registers[11] = driver.trap_frame.general_purpose_registers[13]; proc.pc += 4; // Skip ecall instruction proc.state = .waiting; // Scheduler is called by the "terminate" syscall after two layers of returning. |