sys: add abi module to bridge kernel<->userspace

This commit is contained in:
2025-03-27 11:35:03 +02:00
parent 0f157caf5c
commit d25e1c0346
7 changed files with 68 additions and 33 deletions
+3
View File
@@ -0,0 +1,3 @@
pub const SyscallNumber = enum(usize) { SYS_debug_write = 1, SYS_exit = 2, _ };
pub const MAX_SYSCALL: usize = 32;
+10
View File
@@ -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,
+37 -21
View File
@@ -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);
}
+6 -4
View File
@@ -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"
);
}
+6 -4
View File
@@ -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"
+1 -1
View File
@@ -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]);
}
}
+5 -3
View File
@@ -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);
}