diff --git a/abi/abi.zig b/abi/abi.zig new file mode 100644 index 0000000..3b9e8f9 --- /dev/null +++ b/abi/abi.zig @@ -0,0 +1,3 @@ +pub const SyscallNumber = enum(usize) { SYS_debug_write = 1, SYS_exit = 2, _ }; + +pub const MAX_SYSCALL: usize = 32; diff --git a/build.zig b/build.zig index ee10aff..2fd002e 100644 --- a/build.zig +++ b/build.zig @@ -201,6 +201,13 @@ pub fn build(b: *std.Build) anyerror!void { }); kernel_module.addAnonymousImport("userspace", .{ .root_source_file = b.path("zig-out/bin/userspace.bin") }); + const abi_module = b.addModule("abi", .{ + .optimize = optimize, + .red_zone = false, + .target = kernel_target, + .code_model = kernel_code_model, + .root_source_file = b.path("abi/abi.zig"), + }); const user_module = b.addModule("userspace", .{ .optimize = optimize, .target = user_target, @@ -216,6 +223,9 @@ pub fn build(b: *std.Build) anyerror!void { }); kernel.pie = true; + user_module.addImport("abi", abi_module); + kernel_module.addImport("abi", abi_module); + const user = b.addExecutable(.{ .name = "userspace", .root_module = user_module, diff --git a/src/syscall.zig b/src/syscall.zig index 4a74a42..f58cc31 100644 --- a/src/syscall.zig +++ b/src/syscall.zig @@ -1,27 +1,43 @@ const kernel = @import("kernel.zig"); +const abi = @import("abi"); const thread = kernel.thread; +const Thread = thread.Thread; const log = kernel.log; -pub fn syscall_handler(func: usize, args: []usize) usize { - // TODO validation, etc - const cthread = thread.Thread.current(); - switch (func) { - // debug_print(text_data: [*]const u8, text_len: usize) - 1 => { - if (args[0] != 0 and args[1] != 0) { - const text = @as([*]u8, @ptrFromInt(args[0]))[0..args[1]]; - log.debug("{*}: {s}", .{ cthread, text }); - } - return 0; - }, - // exit(code: u32) - 2 => { - log.info("{*} exits with code {}", .{ cthread, args[0] }); - thread.Thread.exit_current(); - }, - else => { - @panic("Undefined syscall"); - }, - } +pub const SyscallFn = *const fn (*Thread, []usize) usize; + +pub const syscall_table: [abi.MAX_SYSCALL]?SyscallFn = make_syscall_table(); + +fn make_syscall_table() [abi.MAX_SYSCALL]?SyscallFn { + const SC = abi.SyscallNumber; + var array = [_]?SyscallFn{undefined} ** abi.MAX_SYSCALL; + array[@intFromEnum(SC.SYS_debug_write)] = sys_debug_write; + array[@intFromEnum(SC.SYS_exit)] = sys_exit; + return array; +} + +fn sys_exit(cthread: *Thread, args: []usize) usize { + log.info("{*} exits with code {}", .{ cthread, args[0] }); + Thread.exit_current(); +} + +fn sys_debug_write(cthread: *Thread, args: []usize) usize { + const message = @as([*]const u8, @ptrFromInt(args[0]))[0..args[1]]; + log.debug("{*}: {s}", .{ cthread, message }); + return 0; +} + +fn sys_undefined_syscall(cthread: *Thread, args: []usize) usize { + _ = args; + log.warn("{*} invoked an undefined syscall", .{cthread}); + Thread.exit_current(); +} + +pub fn syscall_handler(func: usize, args: []usize) usize { + const cthread = thread.Thread.current(); + const handler = if (func >= abi.MAX_SYSCALL) sys_undefined_syscall // + else syscall_table[func] // + orelse sys_undefined_syscall; + return handler(cthread, args); } diff --git a/user/arch/aarch64.zig b/user/arch/aarch64.zig index 69b0c24..c9a30c1 100644 --- a/user/arch/aarch64.zig +++ b/user/arch/aarch64.zig @@ -1,19 +1,21 @@ +const abi = @import("abi"); + pub const syscall = struct { - pub fn syscall1(func: usize, arg0: usize) usize { + pub fn syscall1(func: abi.SyscallNumber, arg0: usize) usize { return asm volatile ("svc #0" : [result] "={x0}" (-> usize), : [arg0] "{x0}" (arg0), - [func] "{x8}" (func), + [func] "{x8}" (@intFromEnum(func)), : "memory" ); } - pub fn syscall2(func: usize, arg0: usize, arg1: usize) usize { + pub fn syscall2(func: abi.SyscallNumber, arg0: usize, arg1: usize) usize { return asm volatile ("svc #0" : [result] "={x0}" (-> usize), : [arg0] "{x0}" (arg0), [arg1] "{x1}" (arg1), - [func] "{x8}" (func), + [func] "{x8}" (@intFromEnum(func)), : "memory" ); } diff --git a/user/arch/riscv64.zig b/user/arch/riscv64.zig index dcfc0a2..c9c9dfb 100644 --- a/user/arch/riscv64.zig +++ b/user/arch/riscv64.zig @@ -1,17 +1,19 @@ +const abi = @import("abi"); + pub const syscall = struct { - pub fn syscall1(func: usize, arg0: usize) usize { + pub fn syscall1(func: abi.SyscallNumber, arg0: usize) usize { return asm volatile ("ecall" : [result] "={a0}" (-> usize), - : [func] "{a0}" (func), + : [func] "{a0}" (@intFromEnum(func)), [arg0] "{a1}" (arg0), : "memory" ); } - pub fn syscall2(func: usize, arg0: usize, arg1: usize) usize { + pub fn syscall2(func: abi.SyscallNumber, arg0: usize, arg1: usize) usize { return asm volatile ("ecall" : [result] "={a0}" (-> usize), - : [func] "{a0}" (func), + : [func] "{a0}" (@intFromEnum(func)), [arg0] "{a1}" (arg0), [arg1] "{a2}" (arg1), : "memory" diff --git a/user/log.zig b/user/log.zig index 69209fe..b72de6b 100644 --- a/user/log.zig +++ b/user/log.zig @@ -23,6 +23,6 @@ pub fn println(comptime format: []const u8, args: anytype) void { var w = W{ .context = &context }; w.print(format, args) catch return; if (context.position != 0) { - syscall.debug_print(context.buffer[0..context.position]); + syscall.debug_write(context.buffer[0..context.position]); } } diff --git a/user/syscall.zig b/user/syscall.zig index 7ac13d3..87d16de 100644 --- a/user/syscall.zig +++ b/user/syscall.zig @@ -1,12 +1,14 @@ const arch = @import("arch.zig"); +const abi = @import("abi"); const sc = arch.syscall; +const SC = abi.SyscallNumber; pub fn exit(code: u32) noreturn { - _ = sc.syscall1(2, code); + _ = sc.syscall1(SC.SYS_exit, code); unreachable; } -pub fn debug_print(text: []const u8) void { - _ = sc.syscall2(1, @intFromPtr(text.ptr), text.len); +pub fn debug_write(text: []const u8) void { + _ = sc.syscall2(SC.SYS_debug_write, @intFromPtr(text.ptr), text.len); }