aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-07-27 16:52:20 +0200
committerHimbeer <himbeer@disroot.org>2024-07-27 16:52:20 +0200
commitd38a787c3b4cea11b5386b5cb5143c77c042656f (patch)
treebff6d1e17bfa7e02ebfe1a2df5427c88d942bc89
parent5104b1c599a8dd353a0b27a127aada17ee27695a (diff)
sysexchange: Simplify kernel-to-user error conversion (#64)
-rw-r--r--src/lib/syscall.zig12
-rw-r--r--src/lib/sysexchange.zig289
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);
+ }
}