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,
|
eflags: u32,
|
||||||
user_esp: u32,
|
user_esp: u32,
|
||||||
user_ss: 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
|
/// 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;
|
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) 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
|
/// Errors that syscall utility functions can throw
|
||||||
pub const Error = error{
|
pub const Error = error{
|
||||||
|
@ -64,7 +64,7 @@ fn handle(ctx: *arch.CpuState) usize {
|
||||||
const syscall = ctx.eax;
|
const syscall = ctx.eax;
|
||||||
if (isValidSyscall(syscall)) {
|
if (isValidSyscall(syscall)) {
|
||||||
if (handlers[syscall]) |handler| {
|
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| {
|
if (result) |res| {
|
||||||
ctx.eax = res;
|
ctx.eax = res;
|
||||||
ctx.ebx = 0;
|
ctx.ebx = 0;
|
||||||
|
@ -297,13 +297,13 @@ inline fn syscall5(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4:
|
||||||
/// 3 => esi and 4 => edi.
|
/// 3 => esi and 4 => edi.
|
||||||
///
|
///
|
||||||
/// Arguments:
|
/// 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.
|
/// IN arg_idx: comptime u32 - The argument index to get. Between 0 and 4.
|
||||||
///
|
///
|
||||||
/// Return: usize
|
/// Return: usize
|
||||||
/// The syscall argument from the given index.
|
/// 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) {
|
return switch (arg_idx) {
|
||||||
0 => ctx.ebx,
|
0 => ctx.ebx,
|
||||||
1 => ctx.ecx,
|
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 {
|
fn makeHandler(comptime syscall: syscalls.Syscall) Handler {
|
||||||
return struct {
|
return struct {
|
||||||
fn func(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
fn func(ctx: *const arch.CpuState, 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, ctx, arg1, arg2, arg3, arg4, arg5);
|
||||||
}
|
}
|
||||||
}.func;
|
}.func;
|
||||||
}
|
}
|
||||||
|
@ -360,8 +360,9 @@ 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) anyerror!usize {
|
fn testHandler0(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||||
// Suppress unused variable warnings
|
// Suppress unused variable warnings
|
||||||
|
_ = ctx;
|
||||||
_ = arg1;
|
_ = arg1;
|
||||||
_ = arg2;
|
_ = arg2;
|
||||||
_ = arg3;
|
_ = arg3;
|
||||||
|
@ -371,8 +372,9 @@ 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) anyerror!usize {
|
fn testHandler1(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||||
// Suppress unused variable warnings
|
// Suppress unused variable warnings
|
||||||
|
_ = ctx;
|
||||||
_ = arg2;
|
_ = arg2;
|
||||||
_ = arg3;
|
_ = arg3;
|
||||||
_ = arg4;
|
_ = arg4;
|
||||||
|
@ -381,8 +383,9 @@ 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) anyerror!usize {
|
fn testHandler2(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||||
// Suppress unused variable warnings
|
// Suppress unused variable warnings
|
||||||
|
_ = ctx;
|
||||||
_ = arg3;
|
_ = arg3;
|
||||||
_ = arg4;
|
_ = arg4;
|
||||||
_ = arg5;
|
_ = arg5;
|
||||||
|
@ -390,28 +393,32 @@ 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) anyerror!usize {
|
fn testHandler3(ctx: *const arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) anyerror!usize {
|
||||||
// Suppress unused variable warnings
|
// Suppress unused variable warnings
|
||||||
|
_ = ctx;
|
||||||
_ = arg4;
|
_ = arg4;
|
||||||
_ = arg5;
|
_ = arg5;
|
||||||
test_int += arg1 + arg2 + arg3;
|
test_int += arg1 + arg2 + arg3;
|
||||||
return 3;
|
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
|
// Suppress unused variable warnings
|
||||||
|
_ = ctx;
|
||||||
_ = 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) 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;
|
test_int += arg1 + arg2 + arg3 + arg4 + arg5;
|
||||||
return 5;
|
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
|
// Suppress unused variable warnings
|
||||||
|
_ = ctx;
|
||||||
_ = arg1;
|
_ = arg1;
|
||||||
_ = arg2;
|
_ = arg2;
|
||||||
_ = arg3;
|
_ = arg3;
|
||||||
|
|
|
@ -2,6 +2,7 @@ const std = @import("std");
|
||||||
const scheduler = @import("scheduler.zig");
|
const scheduler = @import("scheduler.zig");
|
||||||
const panic = @import("panic.zig").panic;
|
const panic = @import("panic.zig").panic;
|
||||||
const log = std.log.scoped(.syscalls);
|
const log = std.log.scoped(.syscalls);
|
||||||
|
const arch = @import("arch.zig").internals;
|
||||||
|
|
||||||
/// 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};
|
||||||
|
@ -46,7 +47,7 @@ pub const Syscall = enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 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 (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
|
/// 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
|
/// Error: Error
|
||||||
/// The error raised by the handler
|
/// The error raised by the handler
|
||||||
///
|
///
|
||||||
pub fn handle(syscall: Syscall, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize {
|
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()(arg1, arg2, arg3, arg4, arg5);
|
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
|
// Suppress unused variable warnings
|
||||||
|
_ = ctx;
|
||||||
_ = arg1;
|
_ = arg1;
|
||||||
_ = arg2;
|
_ = arg2;
|
||||||
_ = arg3;
|
_ = arg3;
|
||||||
|
@ -102,12 +104,14 @@ pub fn handleTest1(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usi
|
||||||
return 0;
|
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;
|
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
|
// Suppress unused variable warnings
|
||||||
|
_ = ctx;
|
||||||
_ = arg1;
|
_ = arg1;
|
||||||
_ = arg2;
|
_ = arg2;
|
||||||
_ = arg3;
|
_ = arg3;
|
||||||
|
@ -123,7 +127,8 @@ test "getHandler" {
|
||||||
}
|
}
|
||||||
|
|
||||||
test "handle" {
|
test "handle" {
|
||||||
try std.testing.expectEqual(@as(usize, 0), try handle(.Test1, 0, 0, 0, 0, 0));
|
const state = arch.CpuState.empty();
|
||||||
try std.testing.expectEqual(@as(usize, 1 + 2 + 3 + 4 + 5), try handle(.Test2, 1, 2, 3, 4, 5));
|
try std.testing.expectEqual(@as(usize, 0), try handle(.Test1, &state, 0, 0, 0, 0, 0));
|
||||||
try std.testing.expectError(Error.OutOfMemory, handle(.Test3, 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,
|
eflags: u32,
|
||||||
user_esp: u32,
|
user_esp: u32,
|
||||||
user_ss: 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) {
|
pub const VmmPayload = switch (builtin.cpu.arch) {
|
||||||
|
|
Loading…
Reference in a new issue