Merge pull request #319 from ZystemOS/f/syscall-ctx
Pass cpu state to syscall handler
This commit is contained in:
commit
9f98062eb3
4 changed files with 84 additions and 22 deletions
|
@ -87,6 +87,31 @@ pub const CpuState = packed struct {
|
|||
eflags: u32,
|
||||
user_esp: u32,
|
||||
user_ss: u32,
|
||||
|
||||
pub fn empty() CpuState {
|
||||
return .{
|
||||
.cr3 = undefined,
|
||||
.gs = undefined,
|
||||
.fs = undefined,
|
||||
.es = undefined,
|
||||
.ds = undefined,
|
||||
.edi = undefined,
|
||||
.esi = undefined,
|
||||
.ebp = undefined,
|
||||
.esp = undefined,
|
||||
.ebx = undefined,
|
||||
.edx = undefined,
|
||||
.ecx = undefined,
|
||||
.eax = undefined,
|
||||
.int_num = undefined,
|
||||
.error_code = undefined,
|
||||
.eip = undefined,
|
||||
.cs = undefined,
|
||||
.eflags = undefined,
|
||||
.user_esp = undefined,
|
||||
.user_ss = undefined,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// x86's boot payload is the multiboot info passed by grub
|
||||
|
|
|
@ -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) anyerror!usize;
|
||||
pub const Handler = fn (ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize;
|
||||
|
||||
/// Errors that syscall utility functions can throw
|
||||
pub const Error = error{
|
||||
|
@ -64,7 +64,7 @@ fn handle(ctx: *arch.CpuState) usize {
|
|||
const syscall = ctx.eax;
|
||||
if (isValidSyscall(syscall)) {
|
||||
if (handlers[syscall]) |handler| {
|
||||
const result = handler(syscallArg(ctx, 0), syscallArg(ctx, 1), syscallArg(ctx, 2), syscallArg(ctx, 3), syscallArg(ctx, 4));
|
||||
const result = handler(ctx, syscallArg(ctx, 0), syscallArg(ctx, 1), syscallArg(ctx, 2), syscallArg(ctx, 3), syscallArg(ctx, 4));
|
||||
if (result) |res| {
|
||||
ctx.eax = res;
|
||||
ctx.ebx = 0;
|
||||
|
@ -297,13 +297,13 @@ inline fn syscall5(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4:
|
|||
/// 3 => esi and 4 => edi.
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN ctx: *arch.CpuState - The interrupt context from which to get the argument
|
||||
/// IN ctx: *const arch.CpuState - The interrupt context from which to get the argument
|
||||
/// IN arg_idx: comptime u32 - The argument index to get. Between 0 and 4.
|
||||
///
|
||||
/// Return: usize
|
||||
/// The syscall argument from the given index.
|
||||
///
|
||||
inline fn syscallArg(ctx: *arch.CpuState, comptime arg_idx: u32) usize {
|
||||
inline fn syscallArg(ctx: *const arch.CpuState, comptime arg_idx: u32) usize {
|
||||
return switch (arg_idx) {
|
||||
0 => ctx.ebx,
|
||||
1 => ctx.ecx,
|
||||
|
@ -325,8 +325,8 @@ 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) anyerror!usize {
|
||||
return syscalls.handle(syscall, arg1, arg2, arg3, arg4, arg5);
|
||||
fn func(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
return syscalls.handle(syscall, ctx, arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
}.func;
|
||||
}
|
||||
|
@ -360,8 +360,9 @@ pub fn init() void {
|
|||
/// Tests
|
||||
var test_int: u32 = 0;
|
||||
|
||||
fn testHandler0(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
fn testHandler0(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = ctx;
|
||||
_ = arg1;
|
||||
_ = arg2;
|
||||
_ = arg3;
|
||||
|
@ -371,8 +372,9 @@ 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) anyerror!usize {
|
||||
fn testHandler1(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = ctx;
|
||||
_ = arg2;
|
||||
_ = arg3;
|
||||
_ = arg4;
|
||||
|
@ -381,8 +383,9 @@ 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) anyerror!usize {
|
||||
fn testHandler2(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = ctx;
|
||||
_ = arg3;
|
||||
_ = arg4;
|
||||
_ = arg5;
|
||||
|
@ -390,28 +393,32 @@ 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) anyerror!usize {
|
||||
fn testHandler3(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = ctx;
|
||||
_ = arg4;
|
||||
_ = arg5;
|
||||
test_int += arg1 + arg2 + arg3;
|
||||
return 3;
|
||||
}
|
||||
|
||||
fn testHandler4(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
fn testHandler4(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = ctx;
|
||||
_ = arg5;
|
||||
test_int += arg1 + arg2 + arg3 + arg4;
|
||||
return 4;
|
||||
}
|
||||
|
||||
fn testHandler5(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
fn testHandler5(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
_ = ctx;
|
||||
test_int += arg1 + arg2 + arg3 + arg4 + arg5;
|
||||
return 5;
|
||||
}
|
||||
|
||||
fn testHandler6(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
fn testHandler6(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||
// Suppress unused variable warnings
|
||||
_ = ctx;
|
||||
_ = arg1;
|
||||
_ = arg2;
|
||||
_ = arg3;
|
||||
|
|
|
@ -2,6 +2,7 @@ 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};
|
||||
|
@ -46,7 +47,7 @@ pub const Syscall = enum {
|
|||
};
|
||||
|
||||
/// 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 (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
|
||||
|
@ -88,12 +89,13 @@ pub fn toErrorCode(err: anyerror) u16 {
|
|||
/// Error: Error
|
||||
/// The error raised by the handler
|
||||
///
|
||||
pub fn handle(syscall: Syscall, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize {
|
||||
return try syscall.getHandler()(arg1, arg2, arg3, arg4, arg5);
|
||||
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(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize {
|
||||
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;
|
||||
|
@ -102,12 +104,14 @@ pub fn handleTest1(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usi
|
|||
return 0;
|
||||
}
|
||||
|
||||
pub fn handleTest2(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize {
|
||||
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(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize {
|
||||
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;
|
||||
|
@ -123,7 +127,8 @@ test "getHandler" {
|
|||
}
|
||||
|
||||
test "handle" {
|
||||
try std.testing.expectEqual(@as(usize, 0), try handle(.Test1, 0, 0, 0, 0, 0));
|
||||
try std.testing.expectEqual(@as(usize, 1 + 2 + 3 + 4 + 5), try handle(.Test2, 1, 2, 3, 4, 5));
|
||||
try std.testing.expectError(Error.OutOfMemory, handle(.Test3, 0, 0, 0, 0, 0));
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -54,6 +54,31 @@ pub const CpuState = struct {
|
|||
eflags: u32,
|
||||
user_esp: u32,
|
||||
user_ss: u32,
|
||||
|
||||
pub fn empty() CpuState {
|
||||
return .{
|
||||
.ss = undefined,
|
||||
.gs = undefined,
|
||||
.fs = undefined,
|
||||
.es = undefined,
|
||||
.ds = undefined,
|
||||
.edi = undefined,
|
||||
.esi = undefined,
|
||||
.ebp = undefined,
|
||||
.esp = undefined,
|
||||
.ebx = undefined,
|
||||
.edx = undefined,
|
||||
.ecx = undefined,
|
||||
.eax = undefined,
|
||||
.int_num = undefined,
|
||||
.error_code = undefined,
|
||||
.eip = undefined,
|
||||
.cs = undefined,
|
||||
.eflags = undefined,
|
||||
.user_esp = undefined,
|
||||
.user_ss = undefined,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const VmmPayload = switch (builtin.cpu.arch) {
|
||||
|
|
Loading…
Reference in a new issue