Merge pull request #317 from ZystemOS/f/improve-syscall-error
Improve syscall error conversion
This commit is contained in:
commit
6eb0037694
2 changed files with 76 additions and 79 deletions
|
@ -17,7 +17,7 @@ pub const INTERRUPT: u16 = 0x80;
|
||||||
pub const NUM_HANDLERS: u16 = 256;
|
pub const NUM_HANDLERS: u16 = 256;
|
||||||
|
|
||||||
/// A syscall handler
|
/// 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
|
/// Errors that syscall utility functions can throw
|
||||||
pub const Error = error{
|
pub const Error = error{
|
||||||
|
@ -108,10 +108,10 @@ pub fn registerSyscall(syscall: usize, handler: Handler) Error!void {
|
||||||
/// Return: usize
|
/// Return: usize
|
||||||
/// The return value from the syscall.
|
/// 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.
|
/// 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 (
|
const res = asm volatile (
|
||||||
\\int $0x80
|
\\int $0x80
|
||||||
: [ret] "={eax}" (-> usize),
|
: [ret] "={eax}" (-> usize),
|
||||||
|
@ -119,7 +119,7 @@ inline fn syscall0(syscall: usize) syscalls.Error!usize {
|
||||||
: "ebx"
|
: "ebx"
|
||||||
);
|
);
|
||||||
const err = asm (""
|
const err = asm (""
|
||||||
: [ret] "={ebx}" (-> usize),
|
: [ret] "={ebx}" (-> u16),
|
||||||
);
|
);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return syscalls.fromErrorCode(err);
|
return syscalls.fromErrorCode(err);
|
||||||
|
@ -137,10 +137,10 @@ inline fn syscall0(syscall: usize) syscalls.Error!usize {
|
||||||
/// Return: usize
|
/// Return: usize
|
||||||
/// The return value from the syscall.
|
/// 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.
|
/// 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 (
|
const res = asm volatile (
|
||||||
\\int $0x80
|
\\int $0x80
|
||||||
: [ret] "={eax}" (-> usize),
|
: [ret] "={eax}" (-> usize),
|
||||||
|
@ -148,7 +148,7 @@ inline fn syscall1(syscall: usize, arg: usize) syscalls.Error!usize {
|
||||||
[arg1] "{ebx}" (arg),
|
[arg1] "{ebx}" (arg),
|
||||||
);
|
);
|
||||||
const err = asm (""
|
const err = asm (""
|
||||||
: [ret] "={ebx}" (-> usize),
|
: [ret] "={ebx}" (-> u16),
|
||||||
);
|
);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return syscalls.fromErrorCode(err);
|
return syscalls.fromErrorCode(err);
|
||||||
|
@ -167,10 +167,10 @@ inline fn syscall1(syscall: usize, arg: usize) syscalls.Error!usize {
|
||||||
/// Return: usize
|
/// Return: usize
|
||||||
/// The return value from the syscall.
|
/// 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.
|
/// 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 (
|
const res = asm volatile (
|
||||||
\\int $0x80
|
\\int $0x80
|
||||||
: [ret] "={eax}" (-> usize),
|
: [ret] "={eax}" (-> usize),
|
||||||
|
@ -179,7 +179,7 @@ inline fn syscall2(syscall: usize, arg1: usize, arg2: usize) syscalls.Error!usiz
|
||||||
[arg2] "{ecx}" (arg2),
|
[arg2] "{ecx}" (arg2),
|
||||||
);
|
);
|
||||||
const err = asm (""
|
const err = asm (""
|
||||||
: [ret] "={ebx}" (-> usize),
|
: [ret] "={ebx}" (-> u16),
|
||||||
);
|
);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return syscalls.fromErrorCode(err);
|
return syscalls.fromErrorCode(err);
|
||||||
|
@ -199,10 +199,10 @@ inline fn syscall2(syscall: usize, arg1: usize, arg2: usize) syscalls.Error!usiz
|
||||||
/// Return: usize
|
/// Return: usize
|
||||||
/// The return value from the syscall.
|
/// 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.
|
/// 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 (
|
const res = asm volatile (
|
||||||
\\int $0x80
|
\\int $0x80
|
||||||
: [ret] "={eax}" (-> usize),
|
: [ret] "={eax}" (-> usize),
|
||||||
|
@ -212,7 +212,7 @@ inline fn syscall3(syscall: usize, arg1: usize, arg2: usize, arg3: usize) syscal
|
||||||
[arg3] "{edx}" (arg3),
|
[arg3] "{edx}" (arg3),
|
||||||
);
|
);
|
||||||
const err = asm (""
|
const err = asm (""
|
||||||
: [ret] "={ebx}" (-> usize),
|
: [ret] "={ebx}" (-> u16),
|
||||||
);
|
);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return syscalls.fromErrorCode(err);
|
return syscalls.fromErrorCode(err);
|
||||||
|
@ -233,10 +233,10 @@ inline fn syscall3(syscall: usize, arg1: usize, arg2: usize, arg3: usize) syscal
|
||||||
/// Return: usize
|
/// Return: usize
|
||||||
/// The return value from the syscall.
|
/// 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.
|
/// 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 (
|
const res = asm volatile (
|
||||||
\\int $0x80
|
\\int $0x80
|
||||||
: [ret] "={eax}" (-> usize),
|
: [ret] "={eax}" (-> usize),
|
||||||
|
@ -247,7 +247,7 @@ inline fn syscall4(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4:
|
||||||
[arg4] "{esi}" (arg4),
|
[arg4] "{esi}" (arg4),
|
||||||
);
|
);
|
||||||
const err = asm (""
|
const err = asm (""
|
||||||
: [ret] "={ebx}" (-> usize),
|
: [ret] "={ebx}" (-> u16),
|
||||||
);
|
);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return syscalls.fromErrorCode(err);
|
return syscalls.fromErrorCode(err);
|
||||||
|
@ -269,10 +269,10 @@ inline fn syscall4(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4:
|
||||||
/// Return: usize
|
/// Return: usize
|
||||||
/// The return value from the syscall.
|
/// 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.
|
/// 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 (
|
const res = asm volatile (
|
||||||
\\int $0x80
|
\\int $0x80
|
||||||
: [ret] "={eax}" (-> usize),
|
: [ret] "={eax}" (-> usize),
|
||||||
|
@ -284,7 +284,7 @@ inline fn syscall5(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4:
|
||||||
[arg5] "{edi}" (arg5),
|
[arg5] "{edi}" (arg5),
|
||||||
);
|
);
|
||||||
const err = asm (""
|
const err = asm (""
|
||||||
: [ret] "={ebx}" (-> usize),
|
: [ret] "={ebx}" (-> u16),
|
||||||
);
|
);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return syscalls.fromErrorCode(err);
|
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 {
|
fn makeHandler(comptime syscall: syscalls.Syscall) Handler {
|
||||||
return struct {
|
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);
|
return syscalls.handle(syscall, arg1, arg2, arg3, arg4, arg5);
|
||||||
}
|
}
|
||||||
}.func;
|
}.func;
|
||||||
|
@ -344,9 +344,11 @@ pub fn init() void {
|
||||||
|
|
||||||
inline for (std.meta.fields(syscalls.Syscall)) |field| {
|
inline for (std.meta.fields(syscalls.Syscall)) |field| {
|
||||||
const syscall = @intToEnum(syscalls.Syscall, field.value);
|
const syscall = @intToEnum(syscalls.Syscall, field.value);
|
||||||
registerSyscall(field.value, makeHandler(syscall)) catch |e| {
|
if (!syscall.isTest()) {
|
||||||
panic(@errorReturnTrace(), "Failed to register syscall for '" ++ field.name ++ "': {}\n", .{e});
|
registerSyscall(field.value, makeHandler(syscall)) catch |e| {
|
||||||
};
|
panic(@errorReturnTrace(), "Failed to register syscall for '" ++ field.name ++ "': {}\n", .{e});
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (build_options.test_mode) {
|
switch (build_options.test_mode) {
|
||||||
|
@ -358,7 +360,7 @@ pub fn init() void {
|
||||||
/// Tests
|
/// Tests
|
||||||
var test_int: u32 = 0;
|
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
|
// Suppress unused variable warnings
|
||||||
_ = arg1;
|
_ = arg1;
|
||||||
_ = arg2;
|
_ = arg2;
|
||||||
|
@ -369,7 +371,7 @@ fn testHandler0(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize)
|
||||||
return 0;
|
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
|
// Suppress unused variable warnings
|
||||||
_ = arg2;
|
_ = arg2;
|
||||||
_ = arg3;
|
_ = arg3;
|
||||||
|
@ -379,7 +381,7 @@ fn testHandler1(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize)
|
||||||
return 1;
|
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
|
// Suppress unused variable warnings
|
||||||
_ = arg3;
|
_ = arg3;
|
||||||
_ = arg4;
|
_ = arg4;
|
||||||
|
@ -388,7 +390,7 @@ fn testHandler2(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize)
|
||||||
return 2;
|
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
|
// Suppress unused variable warnings
|
||||||
_ = arg4;
|
_ = arg4;
|
||||||
_ = arg5;
|
_ = arg5;
|
||||||
|
@ -396,26 +398,26 @@ fn testHandler3(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize)
|
||||||
return 3;
|
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
|
// Suppress unused variable warnings
|
||||||
_ = arg5;
|
_ = arg5;
|
||||||
test_int += arg1 + arg2 + arg3 + arg4;
|
test_int += arg1 + arg2 + arg3 + arg4;
|
||||||
return 4;
|
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;
|
test_int += arg1 + arg2 + arg3 + arg4 + arg5;
|
||||||
return 5;
|
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
|
// Suppress unused variable warnings
|
||||||
_ = arg1;
|
_ = arg1;
|
||||||
_ = arg2;
|
_ = arg2;
|
||||||
_ = arg3;
|
_ = arg3;
|
||||||
_ = arg4;
|
_ = arg4;
|
||||||
_ = arg5;
|
_ = arg5;
|
||||||
return syscalls.Error.OutOfMemory;
|
return error.OutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
test "registerSyscall returns SyscallExists" {
|
test "registerSyscall returns SyscallExists" {
|
||||||
|
@ -487,7 +489,7 @@ fn runtimeTests() void {
|
||||||
if (syscall0(121)) {
|
if (syscall0(121)) {
|
||||||
panic(@errorReturnTrace(), "FAILURE syscall6\n", .{});
|
panic(@errorReturnTrace(), "FAILURE syscall6\n", .{});
|
||||||
} else |e| {
|
} else |e| {
|
||||||
if (e != syscalls.Error.OutOfMemory) {
|
if (e != error.OutOfMemory) {
|
||||||
panic(@errorReturnTrace(), "FAILURE syscall6 returned the wrong error: {}\n", .{e});
|
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.
|
/// A compilation of all errors that syscall handlers could return.
|
||||||
pub const Error = error{OutOfMemory};
|
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
|
/// All implemented syscalls
|
||||||
pub const Syscall = enum {
|
pub const Syscall = enum {
|
||||||
Test1,
|
Test1,
|
||||||
|
@ -75,11 +28,53 @@ pub const Syscall = enum {
|
||||||
.Test3 => handleTest3,
|
.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
|
/// 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;
|
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
|
/// Handle a syscall and return a result or error
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in a new issue