aboutsummaryrefslogtreecommitdiff
path: root/src/lib/process.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/process.zig')
-rw-r--r--src/lib/process.zig57
1 files changed, 56 insertions, 1 deletions
diff --git a/src/lib/process.zig b/src/lib/process.zig
index c155243..aa3568c 100644
--- a/src/lib/process.zig
+++ b/src/lib/process.zig
@@ -58,11 +58,18 @@ pub const Info = struct {
pages: []align(paging.page_size) u8,
stack: []align(paging.page_size) u8,
pc: usize,
+ cleanup_hook: ?CleanupHook,
term_hook: ?TermHook,
page_table: *paging.Table,
state: State,
rds: std.AutoArrayHashMap(usize, vfs.ResourceDescriptor),
+ pub const CleanupHook = struct {
+ cleanupFn: *const fn (proc: *const Info, buffer: []u8, copy: []const u8) void,
+ buffer: []u8,
+ copy: []const u8,
+ };
+
pub const TermHook = struct {
hookFn: *const fn (context: *anyopaque, proc: *const Info) void,
context: *anyopaque,
@@ -122,6 +129,7 @@ pub const Info = struct {
.pages = self.pages,
.stack = stack,
.pc = self.pc,
+ .cleanup_hook = null,
.term_hook = null,
.page_table = self.page_table,
.state = .suspended,
@@ -135,7 +143,7 @@ pub const Info = struct {
return &proc_node.data;
}
- pub fn call(self: *Info, function: usize, args: anytype, term_hook: ?TermHook) noreturn {
+ pub fn call(self: *Info, function: usize, args: anytype, cleanup_hook: ?CleanupHook, term_hook: ?TermHook) noreturn {
const Container = struct {
fn terminate() linksection(".rethooks") callconv(.Naked) noreturn {
// Syscall #100011 is "terminate".
@@ -147,6 +155,7 @@ pub const Info = struct {
};
self.pc = function;
+ self.cleanup_hook = cleanup_hook;
self.term_hook = term_hook;
self.trap_frame.general_purpose_registers[1] = @intFromPtr(&Container.terminate);
inline for (args, 0..) |arg, i| {
@@ -184,6 +193,9 @@ pub const Info = struct {
self.rds.deinit();
}
+ if (self.cleanup_hook) |cleanup_hook| {
+ cleanup_hook.cleanupFn(self, cleanup_hook.buffer, cleanup_hook.copy);
+ }
if (self.term_hook) |term_hook| {
term_hook.hookFn(term_hook.context, self);
}
@@ -196,6 +208,48 @@ pub const Info = struct {
fn shouldRemoveThread(self: *const Info, candidate: *const Info) bool {
return candidate.thread_id == self.thread_id or self.thread_id == 0;
}
+
+ pub fn copyBytes(self: *const Info, bytes: []const u8) ![]align(paging.page_size) const u8 {
+ const aligned_len = std.mem.alignForward(usize, bytes.len, paging.page_size);
+ const num_pages = @divExact(aligned_len, paging.page_size);
+
+ const copy = try paging.zeroedAlloc(num_pages);
+ errdefer paging.free(copy);
+
+ var addr = @intFromPtr(copy.ptr);
+ const limit = addr + copy.len;
+ while (addr < limit) : (addr += paging.page_size) {
+ try self.page_table.map(addr, addr, paging.EntryFlags.userReadOnly, 0);
+ errdefer self.page_table.unmapEntry(addr);
+ }
+
+ paging.setUserMemoryAccess(true);
+ defer paging.setUserMemoryAccess(false);
+
+ @memcpy(copy[0..bytes.len], bytes);
+ return copy[0..bytes.len];
+ }
+
+ pub fn copyBuffer(self: *const Info, buffer: []u8) ![]align(paging.page_size) u8 {
+ const aligned_len = std.mem.alignForward(usize, buffer.len, paging.page_size);
+ const num_pages = @divExact(aligned_len, paging.page_size);
+
+ const copy = try paging.zeroedAlloc(num_pages);
+ errdefer paging.free(copy);
+
+ var addr = @intFromPtr(copy.ptr);
+ const limit = addr + copy.len;
+ while (addr < limit) : (addr += paging.page_size) {
+ try self.page_table.map(addr, addr, paging.EntryFlags.userReadWrite, 0);
+ errdefer self.page_table.unmapEntry(addr);
+ }
+
+ paging.setUserMemoryAccess(true);
+ defer paging.setUserMemoryAccess(false);
+
+ @memcpy(copy[0..buffer.len], buffer);
+ return copy[0..buffer.len];
+ }
};
pub fn next() ?*Info {
@@ -344,6 +398,7 @@ pub fn create(allocator: std.mem.Allocator, elf_buf: []align(@alignOf(elf.Elf64_
.pages = pages,
.stack = @ptrCast(stack),
.pc = hdr.entry,
+ .cleanup_hook = null,
.term_hook = null,
.page_table = procmem,
.state = .waiting,