diff options
author | Himbeer <himbeer@disroot.org> | 2024-07-27 16:52:20 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-07-27 16:52:20 +0200 |
commit | d38a787c3b4cea11b5386b5cb5143c77c042656f (patch) | |
tree | bff6d1e17bfa7e02ebfe1a2df5427c88d942bc89 | |
parent | 5104b1c599a8dd353a0b27a127aada17ee27695a (diff) |
sysexchange: Simplify kernel-to-user error conversion (#64)
-rw-r--r-- | src/lib/syscall.zig | 12 | ||||
-rw-r--r-- | src/lib/sysexchange.zig | 289 |
2 files changed, 24 insertions, 277 deletions
diff --git a/src/lib/syscall.zig b/src/lib/syscall.zig index 7ffadd7..4fed39b 100644 --- a/src/lib/syscall.zig +++ b/src/lib/syscall.zig @@ -22,12 +22,12 @@ pub const HandleError = error{ pub fn handler(proc: *process.Info, trap_frame: *trap.Frame) !void { const ret = sysexchange.frameReturn; switch (trap_frame.general_purpose_registers[17]) { - 100000 => ret(null, trap_frame, uprint(trap_frame)), - 100001 => ret(null, trap_frame, launch(trap_frame)), - 100002 => ret(null, trap_frame, end(proc)), - 100003 => ret(null, trap_frame, terminate(proc, trap_frame)), - 100004 => ret(null, trap_frame, processId(proc)), - 100005 => ret(null, trap_frame, threadId(proc)), + 100000 => ret(trap_frame, uprint(trap_frame)), + 100001 => ret(trap_frame, launch(trap_frame)), + 100002 => ret(trap_frame, end(proc)), + 100003 => ret(trap_frame, terminate(proc, trap_frame)), + 100004 => ret(trap_frame, processId(proc)), + 100005 => ret(trap_frame, threadId(proc)), else => return HandleError.UnknownSyscall, } } diff --git a/src/lib/sysexchange.zig b/src/lib/sysexchange.zig index b8cd62d..dd96f3b 100644 --- a/src/lib/sysexchange.zig +++ b/src/lib/sysexchange.zig @@ -6,282 +6,29 @@ const std = @import("std"); const trap = @import("trap.zig"); -pub const UserError = error{ - UserError, -}; - -pub const Status = enum(usize) { - success = 0, - hart_id_out_of_range, - no_cpus_hw_info, - no_tar_file_initializer, - no_console, - empty_schedule, - no_init, - too_many_threads, - too_many_resource_descriptors, - bad_rd_handle, - bad_endian, - bad_arch, - bad_bit_len, - not_static_exe, - size_mismatch, - mem_overrun, - branch_perms, - writable_code, - zero_size, - out_of_memory, - out_of_range, - double_free, - already_taken, - not_a_leaf, - no_plic, - plic_incompatible, - no_plic_reg, - interrupt_out_of_range, - context_out_of_range, - unimplemented, - unknown_syscall, - no_pci_controller, - sbi_failed, - sbi_not_supported, - sbi_invalid_param, - sbi_denied, - sbi_invalid_addr, - sbi_already_avail, - sbi_already_started, - sbi_already_stopped, - sbi_no_shared_mem, - sbi_invalid_state, - sbi_bad_range, - sbi_unknown, - hwi_missing_kind, - hwi_missing_reg_addr, - hwi_missing_reg_len, - hwi_unknown_dev_kind, - not_found, - relative_path_not_allowed, - not_a_directory, - no_absolute_containing_directory, - too_many_references, - read_not_supported, - write_not_supported, - in_use, - detached, - orphaned, - already_exists, - is_a_hook, - is_a_container, - provide_not_supported, - remove_not_supported, - user_error = user_range_start, - unknown = std.math.maxInt(usize), - _, - - pub const user_range_start = 0xffff0000_00000000; - pub const user_range_end = 0xffffffff_00000000; - - pub fn fromError(err: anyerror) Status { - return switch (err) { - error.HartIdOutOfRange => .hart_id_out_of_range, - error.NoCpusHwInfo => .no_cpus_hw_info, - error.NoTarFileInitializer => .no_tar_file_initializer, - error.NoConsole => .no_console, - error.EmptySchedule => .empty_schedule, - error.NoInit => .no_init, - error.TooManyThreads => .too_many_threads, - error.TooManyResourceDescriptors => .too_many_resource_descriptors, - error.BadRdHandle => .bad_rd_handle, - error.BadEndian => .bad_endian, - error.BadArch => .bad_arch, - error.BadBitLen => .bad_bit_len, - error.NotStaticExe => .not_static_exe, - error.SizeMismatch => .size_mismatch, - error.MemOverrun => .mem_overrun, - error.BranchPerms => .branch_perms, - error.WritableCode => .writable_code, - error.ZeroSize => .zero_size, - error.OutOfMemory => .out_of_memory, - error.OutOfRange => .out_of_range, - error.DoubleFree => .double_free, - error.AlreadyTaken => .already_taken, - error.NotALeaf => .not_a_leaf, - error.NoPlic => .no_plic, - error.PlicIncompatible => .plic_incompatible, - error.NoPlicReg => .no_plic_reg, - error.InterruptOutOfRange => .interrupt_out_of_range, - error.ContextOutOfRange => .context_out_of_range, - error.Unimplemented => .unimplemented, - error.UnknownSyscall => .unknown_syscall, - error.NoPciController => .no_pci_controller, - error.Failed => .sbi_failed, - error.NotSupported => .sbi_not_supported, - error.InvalidParam => .sbi_invalid_param, - error.Denied => .sbi_denied, - error.InvalidAddr => .sbi_invalid_addr, - error.AlreadyAvail => .sbi_already_avail, - error.AlreadyStarted => .sbi_already_started, - error.AlreadyStopped => .sbi_already_stopped, - error.NoSharedMem => .sbi_no_shared_mem, - error.InvalidState => .sbi_invalid_state, - error.BadRange => .sbi_bad_range, - error.SbiUnknown => .sbi_unknown, - error.MissingKind => .hwi_missing_kind, - error.MissingRegAddr => .hwi_missing_reg_addr, - error.MissingRegLen => .hwi_missing_reg_len, - error.UnknownDevKind => .hwi_unknown_dev_kind, - error.NotFound => .not_found, - error.RelativePathNotAllowed => .relative_path_not_allowed, - error.NotADirectory => .not_a_directory, - error.NoAbsoluteContainingDirectory => .no_absolute_containing_directory, - error.TooManyReferences => .too_many_references, - error.ReadNotSupported => .read_not_supported, - error.WriteNotSupported => .write_not_supported, - error.InUse => .in_use, - error.Detached => .detached, - error.Orphaned => .orphaned, - error.AlreadyExists => .already_exists, - error.IsAHook => .is_a_hook, - error.IsAContainer => .is_a_container, - error.ProvideNotSupported => .provide_not_supported, - error.RemoveNotSupported => .remove_not_supported, - error.UserError => .user_error, - else => .unknown, - }; - } - - // Calling this on the "success" variant is safety-checked - // undefined behavior at runtime. - pub fn toError(self: Status) anyerror { - return switch (self) { - .success => unreachable, - .hart_id_out_of_range => error.HartIdOutOfRange, - .no_cpus_hw_info => error.NoCpusHwInfo, - .no_tar_file_initializer => error.NoTarFileInitializer, - .no_console => error.NoConsole, - .empty_schedule => error.EmptySchedule, - .no_init => error.NoInit, - .too_many_threads => error.TooManyThreads, - .too_many_resource_descriptors => error.TooManyResourceDescriptors, - .bad_rd_handle => error.BadRdHandle, - .bad_endian => error.BadEndian, - .bad_arch => error.BadArch, - .bad_bit_len => error.BadBitLen, - .not_static_exe => error.NotStaticExe, - .size_mismatch => error.SizeMismatch, - .mem_overrun => error.MemOverrun, - .branch_perms => error.BranchPerms, - .writable_code => error.WritableCode, - .zero_size => error.ZeroSize, - .out_of_memory => error.OutOfMemory, - .out_of_range => error.OutOfRange, - .double_free => error.DoubleFree, - .already_taken => error.AlreadyTaken, - .not_a_leaf => error.NotALeaf, - .no_plic => error.NoPlic, - .plic_incompatible => error.PlicIncompatible, - .no_plic_reg => error.NoPlicReg, - .interrupt_out_of_range => error.InterruptOutOfRange, - .context_out_of_range => error.ContextOutOfRange, - .unimplemented => error.Unimplemented, - .unknown_syscall => error.UnknownSyscall, - .no_pci_controller => error.NoPciController, - .sbi_failed => error.Failed, - .sbi_not_supported => error.NotSupported, - .sbi_invalid_param => error.InvalidParam, - .sbi_denied => error.Denied, - .sbi_invalid_addr => error.InvalidAddr, - .sbi_already_avail => error.AlreadyAvail, - .sbi_already_started => error.AlreadyStarted, - .sbi_already_stopped => error.AlreadyStopped, - .sbi_no_shared_mem => error.NoSharedMem, - .sbi_invalid_state => error.InvalidState, - .sbi_bad_range => error.BadRange, - .sbi_unknown => error.SbiUnknown, - .hwi_missing_kind => error.MissingKind, - .hwi_missing_reg_addr => error.MissingRegAddr, - .hwi_missing_reg_len => error.MissingRegLen, - .hwi_unknown_dev_kind => error.UnknownDevKind, - .not_found => error.NotFound, - .relative_path_not_allowed => error.RelativePathNotAllowed, - .not_a_directory => error.NotADirectory, - .no_absolute_containing_directory => error.NoAbsoluteContainingDirectory, - .too_many_references => error.TooManyReferences, - .read_not_supported => error.ReadNotSupported, - .write_not_supported => error.WriteNotSupported, - .in_use => error.InUse, - .detached => error.Detached, - .orphaned => error.Orphaned, - .already_exists => error.AlreadyExists, - .is_a_hook => error.IsAHook, - .is_a_container => error.IsAContainer, - .provide_not_supported => error.ProvideNotSupported, - .remove_not_supported => error.RemoveNotSupported, - .user_error => error.UserError, - .unknown => error.Unknown, - _ => if (self.isUserError()) error.UserError else error.Unknown, - }; +pub fn frameReturn(trap_frame: *trap.Frame, value: anytype) void { + switch (@typeInfo(@TypeOf(value))) { + .ErrorUnion => returnErrorUnion(trap_frame, value), + .ErrorSet => returnError(trap_frame, value), + else => returnValue(trap_frame, value), } +} - pub inline fn isUserError(self: Status) bool { - const status = @intFromEnum(self); - return status > user_range_start and status < user_range_end; +fn returnErrorUnion(trap_frame: *trap.Frame, error_union: anytype) void { + if (error_union) |value| { + returnValue(trap_frame, value); + } else |err| { + returnError(trap_frame, err); } -}; - -pub fn Result(comptime T: type) type { - return extern struct { - value: T, - status: Status, - - const Self = @This(); - - pub fn fromAnyTypeOrError(value: anytype) Self { - return switch (@typeInfo(@TypeOf(value))) { - .ErrorUnion => if (value) |inner| - .{ - .value = inner, - .status = .success, - } - else |err| - .{ - .value = undefined, - .status = Status.fromError(err), - }, - .ErrorSet => .{ - .value = undefined, - .status = Status.fromError(value), - }, - else => .{ - .value = value, - .status = .success, - }, - }; - } - - pub fn toErrorUnion(self: Self) !T { - return if (self.status == .success) self.value else self.status.toError(); - } - }; } -pub fn frameReturnResult(comptime T: type, trap_frame: *trap.Frame, result: Result(T)) void { - const return_value = switch (@typeInfo(T)) { - .Void => undefined, - else => result.value, - }; - - trap_frame.general_purpose_registers[10] = return_value; - trap_frame.general_purpose_registers[11] = @intFromEnum(result.status); +fn returnError(trap_frame: *trap.Frame, err: anyerror) void { + trap_frame.general_purpose_registers[11] = @intFromError(err); } -pub fn frameReturn(comptime T: ?type, trap_frame: *trap.Frame, value: anytype) void { - const ValueType = @TypeOf(value); - const U = T orelse switch (@typeInfo(ValueType)) { - .ErrorUnion => |err_union| err_union.payload, - else => ValueType, - }; - - const result = Result(U).fromAnyTypeOrError(value); - frameReturnResult(U, trap_frame, result); +fn returnValue(trap_frame: *trap.Frame, value: anytype) void { + trap_frame.general_purpose_registers[11] = 0; + if (@typeInfo(@TypeOf(value)) != .Void) { + trap_frame.general_purpose_registers[10] = @bitCast(value); + } } |