diff options
Diffstat (limited to 'src/syscall.zig')
-rw-r--r-- | src/syscall.zig | 67 |
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]; |