Improve syscall error conversion
This commit is contained in:
parent
765c07a457
commit
b42357d31d
2 changed files with 76 additions and 79 deletions
|
@ -17,7 +17,7 @@ pub const INTERRUPT: u16 = 0x80;
|
|||
pub const NUM_HANDLERS: u16 = 256;
|
||||
|
||||
/// A syscall handler
|
||||
pub const Handler = fn (arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize;
|
||||
pub const Handler = fn (arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize;
|
||||
|
||||
/// Errors that syscall utility functions can throw
|
||||
pub const Error = error{
|
||||
|
@ -108,10 +108,10 @@ pub fn registerSyscall(syscall: usize, handler: Handler) Error!void {
|
|||
/// Return: usize
|
||||
/// The return value from the syscall.
|
||||
///
|
||||
/// Error: syscalls.Error
|
||||
/// Error: anyerror
|
||||
/// This function will return the error that the syscall handler returns. See the documentation for the syscall for details.
|
||||
///
|
||||
inline fn syscall0(syscall: usize) syscalls.Error!usize {
|
||||
inline fn syscall0(syscall: usize) anyerror!usize {
|
||||
const res = asm volatile (
|
||||
\\int $0x80
|
||||
: [ret] "={eax}" (-> usize),
|
||||
|
@ -119,7 +119,7 @@ inline fn syscall0(syscall: usize) syscalls.Error!usize {
|
|||
: "ebx"
|
||||
);
|
||||
const err = asm (""
|
||||
: [ret] "={ebx}" (-> usize),
|
||||
: [ret] "={ebx}" (-> u16),
|
||||
);
|
||||
if (err != 0) {
|
||||
return syscalls.fromErrorCode(err);
|
||||
|
@ -137,10 +137,10 @@ inline fn syscall0(syscall: usize) syscalls.Error!usize {
|
|||
/// Return: usize
|
||||
/// The return value from the syscall.
|
||||
///
|
||||
/// Error: syscalls.Error
|
||||
/// Error: anyerror
|
||||
/// This function will return the error that the syscall handler returns. See the documentation for the syscall for details.
|
||||
///
|
||||
inline fn syscall1(syscall: usize, arg: usize) syscalls.Error!usize {
|
||||
inline fn syscall1(syscall: usize, arg: usize) anyerror!usize {
|
||||
const res = asm volatile (
|
||||
\\int $0x80
|
||||
: [ret] "={eax}" (-> usize),
|
||||
|
@ -148,7 +148,7 @@ inline fn syscall1(syscall: usize, arg: usize) syscalls.Error!usize {
|
|||
[arg1] "{ebx}" (arg),
|
||||
);
|
||||
const err = asm (""
|
||||
: [ret] "={ebx}" (-> usize),
|
||||
: [ret] "={ebx}" (-> u16),
|
||||
);
|
||||
if (err != 0) {
|
||||
return syscalls.fromErrorCode(err);
|
||||
|
@ -167,10 +167,10 @@ inline fn syscall1(syscall: usize, arg: usize) syscalls.Error!usize {
|
|||
/// Return: usize
|
||||
/// The return value from the syscall.
|
||||
///
|
||||
/// Error: syscalls.Error
|
||||
/// Error: anyerror
|
||||
/// This function will return the error that the syscall handler returns. See the documentation for the syscall for details.
|
||||
///
|
||||
inline fn syscall2(syscall: usize, arg1: usize, arg2: usize) syscalls.Error!usize {
|
||||
inline fn syscall2(syscall: usize, arg1: usize, arg2: usize) anyerror!usize {
|
||||
const res = asm volatile (
|
||||
\\int $0x80
|
||||
: [ret] "={eax}" (-> usize),
|
||||
|
@ -179,7 +179,7 @@ inline fn syscall2(syscall: usize, arg1: usize, arg2: usize) syscalls.Error!usiz
|
|||
[arg2] "{ecx}" (arg2),
|
||||
);
|
||||
const err = asm (""
|
||||
: [ret] "={ebx}" (-> usize),
|
||||
: [ret] "={ebx}" (-> u16),
|
||||
);
|
||||
if (err != 0) {
|
||||
return syscalls.fromErrorCode(err);
|
||||
|
@ -199,10 +199,10 @@ inline fn syscall2(syscall: usize, arg1: usize, arg2: usize) syscalls.Error!usiz
|
|||
/// Return: usize
|
||||
/// The return value from the syscall.
|
||||
///
|
||||
/// Error: syscalls.Error
|
||||
/// Error: anyerror
|
||||
/// This function will return the error that the syscall handler returns. See the documentation for the syscall for details.
|
||||
///
|
||||
inline fn syscall3(syscall: usize, arg1: usize, arg2: usize, arg3: usize) syscalls.Error!usize {
|
||||
inline fn syscall3(syscall: usize, arg1: usize, arg2: usize, arg3: usize) anyerror!usize {
|
||||
const res = asm volatile (
|
||||
\\int $0x80
|
||||
: [ret] "={eax}" (-> usize),
|
||||
|
@ -212,7 +212,7 @@ inline fn syscall3(syscall: usize, arg1: usize, arg2: usize, arg3: usize) syscal
|
|||
[arg3] "{edx}" (arg3),
|
||||
);
|
||||
const err = asm (""
|
||||
: [ret] "={ebx}" (-> usize),
|
||||
: [ret] "={ebx}" (-> u16),
|
||||
);
|
||||
if (err != 0) {
|
||||
return syscalls.fromErrorCode(err);
|
||||
|
@ -233,10 +233,10 @@ inline fn syscall3(syscall: usize, arg1: usize, arg2: usize, arg3: usize) syscal
|
|||
/// Return: usize
|
||||
/// The return value from the syscall.
|
||||
///
|
||||
/// Error: syscalls.Error
|
||||
/// Error: anyerror
|
||||
/// This function will return the error that the syscall handler returns. See the documentation for the syscall for details.
|
||||
///
|
||||
inline fn syscall4(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) syscalls.Error!usize {
|
||||
inline fn syscall4(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) anyerror!usize {
|
||||
const res = asm volatile (
|
||||
\\int $0x80
|
||||
: [ret] "={eax}" (-> usize),
|
||||
|
@ -247,7 +247,7 @@ inline fn syscall4(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4:
|
|||
[arg4] "{esi}" (arg4),
|
||||
);
|
||||
const err = asm (""
|
||||
: [ret] "={ebx}" (-> usize),
|
||||
: [ret] "={ebx}" (-> u16),
|
||||
);
|
||||
if (err != 0) {
|
||||
return syscalls.fromErrorCode(err);
|
||||
|
@ -269,10 +269,10 @@ inline fn syscall4(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4:
|
|||
/// Return: usize
|
||||
/// The return value from the syscall.
|
||||
///
|
||||
/// Error: syscalls.Error
|
||||
/// Error: anyerror
|
||||
/// This function will return the error that the syscall handler returns. See the documentation for the syscall for details.
|
||||
///
|
||||
inline fn syscall5(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize {
|
||||
inline fn syscall5(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
const res = asm volatile (
|
||||
\\int $0x80
|
||||
: [ret] "={eax}" (-> usize),
|
||||
|
@ -284,7 +284,7 @@ inline fn syscall5(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4:
|
|||
[arg5] "{edi}" (arg5),
|
||||
);
|
||||
const err = asm (""
|
||||
: [ret] "={ebx}" (-> usize),
|
||||
: [ret] "={ebx}" (-> u16),
|
||||
);
|
||||
if (err != 0) {
|
||||
return syscalls.fromErrorCode(err);
|
||||
|
@ -325,7 +325,7 @@ inline fn syscallArg(ctx: *arch.CpuState, comptime arg_idx: u32) usize {
|
|||
///
|
||||
fn makeHandler(comptime syscall: syscalls.Syscall) Handler {
|
||||
return struct {
|
||||
fn func(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize {
|
||||
fn func(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
return syscalls.handle(syscall, arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
}.func;
|
||||
|
@ -344,10 +344,12 @@ pub fn init() void {
|
|||
|
||||
inline for (std.meta.fields(syscalls.Syscall)) |field| {
|
||||
const syscall = @intToEnum(syscalls.Syscall, field.value);
|
||||
if (!syscall.isTest()) {
|
||||
registerSyscall(field.value, makeHandler(syscall)) catch |e| {
|
||||
panic(@errorReturnTrace(), "Failed to register syscall for '" ++ field.name ++ "': {}\n", .{e});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
switch (build_options.test_mode) {
|
||||
.Initialisation => runtimeTests(),
|
||||
|
@ -358,7 +360,7 @@ pub fn init() void {
|
|||
/// Tests
|
||||
var test_int: u32 = 0;
|
||||
|
||||
fn testHandler0(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize {
|
||||
fn testHandler0(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = arg1;
|
||||
_ = arg2;
|
||||
|
@ -369,7 +371,7 @@ fn testHandler0(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
fn testHandler1(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize {
|
||||
fn testHandler1(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = arg2;
|
||||
_ = arg3;
|
||||
|
@ -379,7 +381,7 @@ fn testHandler1(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize)
|
|||
return 1;
|
||||
}
|
||||
|
||||
fn testHandler2(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize {
|
||||
fn testHandler2(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = arg3;
|
||||
_ = arg4;
|
||||
|
@ -388,7 +390,7 @@ fn testHandler2(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize)
|
|||
return 2;
|
||||
}
|
||||
|
||||
fn testHandler3(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize {
|
||||
fn testHandler3(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = arg4;
|
||||
_ = arg5;
|
||||
|
@ -396,26 +398,26 @@ fn testHandler3(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize)
|
|||
return 3;
|
||||
}
|
||||
|
||||
fn testHandler4(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize {
|
||||
fn testHandler4(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = arg5;
|
||||
test_int += arg1 + arg2 + arg3 + arg4;
|
||||
return 4;
|
||||
}
|
||||
|
||||
fn testHandler5(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize {
|
||||
fn testHandler5(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
test_int += arg1 + arg2 + arg3 + arg4 + arg5;
|
||||
return 5;
|
||||
}
|
||||
|
||||
fn testHandler6(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize {
|
||||
fn testHandler6(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = arg1;
|
||||
_ = arg2;
|
||||
_ = arg3;
|
||||
_ = arg4;
|
||||
_ = arg5;
|
||||
return syscalls.Error.OutOfMemory;
|
||||
return error.OutOfMemory;
|
||||
}
|
||||
|
||||
test "registerSyscall returns SyscallExists" {
|
||||
|
@ -487,7 +489,7 @@ fn runtimeTests() void {
|
|||
if (syscall0(121)) {
|
||||
panic(@errorReturnTrace(), "FAILURE syscall6\n", .{});
|
||||
} else |e| {
|
||||
if (e != syscalls.Error.OutOfMemory) {
|
||||
if (e != error.OutOfMemory) {
|
||||
panic(@errorReturnTrace(), "FAILURE syscall6 returned the wrong error: {}\n", .{e});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,53 +6,6 @@ const log = std.log.scoped(.syscalls);
|
|||
/// A compilation of all errors that syscall handlers could return.
|
||||
pub const Error = error{OutOfMemory};
|
||||
|
||||
///
|
||||
/// Convert an error code to an instance of Error. The conversion must be synchronised with toErrorCode
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN code: usize - The erorr code to convert
|
||||
///
|
||||
/// Return: Error
|
||||
/// The error corresponding to the error code
|
||||
///
|
||||
pub fn fromErrorCode(code: usize) Error {
|
||||
return switch (code) {
|
||||
1 => Error.OutOfMemory,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
///
|
||||
/// Convert an instance of Error to an error code. The conversion must be synchronised with fromErrorCode
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN err: Error - The erorr to convert
|
||||
///
|
||||
/// Return: usize
|
||||
/// The error code corresponding to the error
|
||||
///
|
||||
pub fn toErrorCode(err: Error) usize {
|
||||
return switch (err) {
|
||||
Error.OutOfMemory => 1,
|
||||
};
|
||||
}
|
||||
|
||||
comptime {
|
||||
// Make sure toErrorCode and fromErrorCode are synchronised, and that no errors share the same error code
|
||||
inline for (@typeInfo(Error).ErrorSet.?) |err| {
|
||||
const error_instance = @field(Error, err.name);
|
||||
if (fromErrorCode(toErrorCode(error_instance)) != error_instance) {
|
||||
@compileError("toErrorCode and fromErrorCode are not synchronised for syscall error '" ++ err.name ++ "'\n");
|
||||
}
|
||||
inline for (@typeInfo(Error).ErrorSet.?) |err2| {
|
||||
const error2_instance = @field(Error, err2.name);
|
||||
if (error_instance != error2_instance and toErrorCode(error_instance) == toErrorCode(error2_instance)) {
|
||||
@compileError("Syscall errors '" ++ err.name ++ "' and '" ++ err2.name ++ "' share the same error code\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// All implemented syscalls
|
||||
pub const Syscall = enum {
|
||||
Test1,
|
||||
|
@ -75,11 +28,53 @@ pub const Syscall = enum {
|
|||
.Test3 => handleTest3,
|
||||
};
|
||||
}
|
||||
|
||||
///
|
||||
/// Check if the syscall is just used for testing, and therefore shouldn't be exposed at runtime
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN self: Syscall - The syscall to check
|
||||
///
|
||||
/// Return: bool
|
||||
/// true if the syscall is only to be used for testing, else false
|
||||
///
|
||||
pub fn isTest(self: @This()) bool {
|
||||
return switch (self) {
|
||||
.Test1, .Test2, .Test3 => true,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// A function that can handle a syscall and return a result or an error
|
||||
pub const Handler = fn (arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize;
|
||||
|
||||
///
|
||||
/// Convert an error code to an instance of Error. The conversion must be synchronised with toErrorCode
|
||||
/// Passing an error code that does not correspond to an error results in safety-protected undefined behaviour
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN code: u16 - The erorr code to convert
|
||||
///
|
||||
/// Return: Error
|
||||
/// The error corresponding to the error code
|
||||
///
|
||||
pub fn fromErrorCode(code: u16) anyerror {
|
||||
return @intToError(code);
|
||||
}
|
||||
|
||||
///
|
||||
/// Convert an instance of Error to an error code. The conversion must be synchronised with fromErrorCode
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN err: Error - The erorr to convert
|
||||
///
|
||||
/// Return: u16
|
||||
/// The error code corresponding to the error
|
||||
///
|
||||
pub fn toErrorCode(err: anyerror) u16 {
|
||||
return @errorToInt(err);
|
||||
}
|
||||
|
||||
///
|
||||
/// Handle a syscall and return a result or error
|
||||
///
|
||||
|
|
Loading…
Reference in a new issue