Merge pull request #319 from ZystemOS/f/syscall-ctx

Pass cpu state to syscall handler
This commit is contained in:
Sam Tebbs 2022-06-03 10:01:11 +01:00 committed by GitHub
commit 9f98062eb3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 22 deletions

View file

@ -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

View file

@ -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;

View file

@ -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));
} }

View file

@ -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) {