134 lines
4 KiB
Zig
134 lines
4 KiB
Zig
const std = @import("std");
|
|
const scheduler = @import("scheduler.zig");
|
|
const panic = @import("panic.zig").panic;
|
|
const log = std.log.scoped(.syscalls);
|
|
const arch = @import("arch.zig").internals;
|
|
|
|
/// A compilation of all errors that syscall handlers could return.
|
|
pub const Error = error{OutOfMemory};
|
|
|
|
/// All implemented syscalls
|
|
pub const Syscall = enum {
|
|
Test1,
|
|
Test2,
|
|
Test3,
|
|
|
|
///
|
|
/// Get the handler associated with the syscall
|
|
///
|
|
/// Arguments:
|
|
/// IN self: Syscall - The syscall to get the handler for
|
|
///
|
|
/// Return: Handler
|
|
/// The handler that takes care of this syscall
|
|
///
|
|
fn getHandler(self: @This()) Handler {
|
|
return switch (self) {
|
|
.Test1 => handleTest1,
|
|
.Test2 => handleTest2,
|
|
.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 (ctx: *const arch.CpuState, 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
|
|
///
|
|
/// Arguments:
|
|
/// IN syscall: Syscall - The syscall to handle
|
|
/// IN argX: usize - The xth argument that was passed to the syscall
|
|
///
|
|
/// Return: usize
|
|
/// The syscall result
|
|
///
|
|
/// Error: Error
|
|
/// The error raised by the handler
|
|
///
|
|
pub fn handle(syscall: Syscall, ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize {
|
|
return try syscall.getHandler()(ctx, arg1, arg2, arg3, arg4, arg5);
|
|
}
|
|
|
|
pub fn handleTest1(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize {
|
|
// Suppress unused variable warnings
|
|
_ = ctx;
|
|
_ = arg1;
|
|
_ = arg2;
|
|
_ = arg3;
|
|
_ = arg4;
|
|
_ = arg5;
|
|
return 0;
|
|
}
|
|
|
|
pub fn handleTest2(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize {
|
|
_ = ctx;
|
|
return arg1 + arg2 + arg3 + arg4 + arg5;
|
|
}
|
|
|
|
pub fn handleTest3(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize {
|
|
// Suppress unused variable warnings
|
|
_ = ctx;
|
|
_ = arg1;
|
|
_ = arg2;
|
|
_ = arg3;
|
|
_ = arg4;
|
|
_ = arg5;
|
|
return std.mem.Allocator.Error.OutOfMemory;
|
|
}
|
|
|
|
test "getHandler" {
|
|
try std.testing.expectEqual(Syscall.Test1.getHandler(), handleTest1);
|
|
try std.testing.expectEqual(Syscall.Test2.getHandler(), handleTest2);
|
|
try std.testing.expectEqual(Syscall.Test3.getHandler(), handleTest3);
|
|
}
|
|
|
|
test "handle" {
|
|
const state = arch.CpuState.empty();
|
|
try std.testing.expectEqual(@as(usize, 0), try handle(.Test1, &state, 0, 0, 0, 0, 0));
|
|
try std.testing.expectEqual(@as(usize, 1 + 2 + 3 + 4 + 5), try handle(.Test2, &state, 1, 2, 3, 4, 5));
|
|
try std.testing.expectError(Error.OutOfMemory, handle(.Test3, &state, 0, 0, 0, 0, 0));
|
|
}
|