aboutsummaryrefslogtreecommitdiff
path: root/src/syscall.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/syscall.zig')
-rw-r--r--src/syscall.zig67
1 files changed, 60 insertions, 7 deletions
diff --git a/src/syscall.zig b/src/syscall.zig
index e3b54c9..3a346ab 100644
--- a/src/syscall.zig
+++ b/src/syscall.zig
@@ -25,10 +25,12 @@ pub fn handler(proc: *process.Info, trap_frame: *TrapFrame) !void {
100005 => trap_frame.setReturnValue(processId(proc)),
100006 => trap_frame.setReturnValue(threadId(proc)),
100007 => trap_frame.setReturnValue(devicesByKind(trap_frame)),
- 100008 => trap_frame.setReturnValue(join(proc, trap_frame)),
- 100009 => trap_frame.setReturnValue(leave(proc, trap_frame)),
- 100010 => trap_frame.setReturnValue(pass(proc, trap_frame)),
- 100011 => trap_frame.setReturnValue(receive(proc, trap_frame)),
+ 100008 => trap_frame.setReturnValue(unlock(proc, trap_frame)),
+ 100009 => trap_frame.setReturnValue(lock(proc, trap_frame)),
+ 100010 => trap_frame.setReturnValue(join(proc, trap_frame)),
+ 100011 => trap_frame.setReturnValue(leave(proc, trap_frame)),
+ 100012 => trap_frame.setReturnValue(pass(proc, trap_frame)),
+ 100013 => trap_frame.setReturnValue(receive(proc, trap_frame)),
else => return HandleError.UnknownSyscall,
}
}
@@ -135,7 +137,11 @@ fn threadId(proc: *const process.Info) usize {
return proc.thread_id;
}
-pub const DeviceError = error{KindNotUserManagable};
+pub const DeviceError = error{
+ KindNotUserManagable,
+ DeviceNotFound,
+ VirtualAddressOutOfRange,
+};
// devicesByKind(kind: hwinfo.DevKind, devices: [*]hwinfo.Dev, len: usize) !usize
fn devicesByKind(trap_frame: *const TrapFrame) !usize {
@@ -147,16 +153,63 @@ fn devicesByKind(trap_frame: *const TrapFrame) !usize {
var i: usize = 0;
var devs = try hwinfo.byKind(kind);
- while (try devs.next()) |dev| {
+ while (devs.next()) |device| {
if (i >= len) break;
- devices[i] = dev;
+ devices[i] = device;
i += 1;
}
return i;
}
+// unlock(reg_addr: usize, writable: bool) !usize
+fn unlock(proc: *process.Info, trap_frame: *const TrapFrame) !usize {
+ const reg_addr = trap_frame.general_purpose_registers[10];
+ const writable = trap_frame.general_purpose_registers[11] != 0;
+
+ const flags = if (writable) blk: {
+ break :blk paging.EntryFlags.userReadWrite;
+ } else blk: {
+ break :blk paging.EntryFlags.userReadOnly;
+ };
+
+ const vaddr = proc.next_mmio_vaddr;
+
+ const device = try hwinfo.byAddress(reg_addr, true) orelse return DeviceError.DeviceNotFound;
+ try proc.page_table.mapDevice(device.reg, &proc.next_mmio_vaddr, flags);
+ asm volatile (
+ \\ sfence.vma %[addr], %[asid]
+ :
+ : [addr] "r" (device.reg.addr),
+ [asid] "r" (proc.id),
+ );
+
+ return vaddr;
+}
+
+// lock(vaddr: usize) !void
+fn lock(proc: *const process.Info, trap_frame: *const TrapFrame) !void {
+ var vaddr = trap_frame.general_purpose_registers[10];
+
+ if (vaddr < process.mmio_start_vaddr) return DeviceError.VirtualAddressOutOfRange;
+
+ const reg_addr = proc.page_table.translate(vaddr, paging.EntryFlags.invalid) orelse {
+ const faulter: *volatile u8 = @ptrFromInt(vaddr);
+ _ = faulter.*;
+ unreachable;
+ };
+
+ const device = try hwinfo.byAddress(reg_addr, true) orelse return DeviceError.DeviceNotFound;
+ try proc.page_table.mapDevice(device.reg, &vaddr, paging.EntryFlags.invalid);
+ asm volatile (
+ \\ sfence.vma %[addr], %[asid]
+ :
+ : [addr] "r" (device.reg.addr),
+ [asid] "r" (proc.id),
+ );
+}
+
// join(channel: usize) !void
fn join(proc: *const process.Info, trap_frame: *const TrapFrame) !void {
const id = trap_frame.general_purpose_registers[10];