sylveos

Toy Operating System
Log | Files | Refs

commit ab2d3ee79f760a36c0bb12ca2ceb8b44c01d84a4
parent 9beb46c3b84eb98217324f06fb4a752e23665930
Author: Sylvia Ivory <git@sivory.net>
Date:   Thu, 22 Jan 2026 21:35:03 -0800

Add syscall-1 (new root needed)

Diffstat:
Mpi/interrupts.zig | 38++++++++++++++++++++++++++++++--------
Mpi/root.zig | 6++++++
Asrc/labs/4-syscall-1.zig | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main.zig | 2+-
4 files changed, 109 insertions(+), 9 deletions(-)

diff --git a/pi/interrupts.zig b/pi/interrupts.zig @@ -53,19 +53,25 @@ pub inline fn pending_basic(i: BasicInterrupt) bool { } fn empty(lr: u32) void { - @import("boot").uart.write_slice("default handler called\n"); _ = lr; } +// TODO; r1-r6 +fn empty_swi(n: u32, r0: u32) callconv(.c) i32 { + _ = n; + _ = r0; + return -1; +} + var reset_handler: *const fn (u32) void = empty; var undefined_instruction_handler: *const fn (u32) void = empty; -var software_interrupt_handler: *const fn (u32) void = empty; +export var software_interrupt_handler: *const fn (u32, u32) callconv(.c) i32 = empty_swi; var prefetch_abort_handler: *const fn (u32) void = empty; var data_abort_handler: *const fn (u32) void = empty; var interrupt_handler: *const fn (u32) void = empty; var fast_interrupt_handler: *const fn (u32) void = empty; -fn get_lr() u32 { +inline fn get_lr() u32 { return asm volatile ("mov %[result], lr" : [result] "=r" (-> u32), ); @@ -77,9 +83,6 @@ export fn reset() callconv(.{ .arm_interrupt = .{ .type = .generic } }) void { export fn undefined_instruction() callconv(.{ .arm_interrupt = .{ .type = .undef } }) void { undefined_instruction_handler(get_lr() - 4); } -export fn software_interrupt() callconv(.{ .arm_interrupt = .{ .type = .swi } }) void { - software_interrupt_handler(get_lr() - 4); -} export fn prefetch_abort() callconv(.{ .arm_interrupt = .{ .type = .abort } }) void { prefetch_abort_handler(get_lr() - 8); } @@ -93,6 +96,23 @@ export fn fast_interrupt() callconv(.{ .arm_interrupt = .{ .type = .fiq } }) voi fast_interrupt_handler(get_lr() - 4); } +// TODO; fix +comptime { + asm ( + \\ .global software_interrupt; + \\ .type software_interrupt, %function; + \\ software_interrupt: + \\ push {r0-r2, lr} + \\ mov r1, r0 + \\ sub lr, lr, #4 + \\ mov r0, lr + \\ bl syscall_handler + \\ pop {r0-r2, lr} + \\ subs pc, lr, #0 + ); +} +extern fn software_interrupt() void; + // https://leiradel.github.io/2019/02/09/Initialization.html pub fn setup_exception_vector() void { var exception_vector: usize = 0; @@ -131,7 +151,6 @@ pub fn setup_exception_vector() void { const ExceptionVector = enum { Reset, UndefinedInstruction, - SoftwareInterrupt, PrefetchAbort, DataAbort, IRQ, @@ -142,10 +161,13 @@ pub fn set_exception_handler(vector: ExceptionVector, handler: *const fn (u32) v switch (vector) { .Reset => reset_handler = handler, .UndefinedInstruction => undefined_instruction_handler = handler, - .SoftwareInterrupt => software_interrupt_handler = handler, .PrefetchAbort => prefetch_abort_handler = handler, .DataAbort => data_abort_handler = handler, .IRQ => interrupt_handler = handler, .FIQ => fast_interrupt_handler = handler, } } + +pub fn set_software_interrupt(handler: *const fn (u32, u32) callconv(.c) i32) void { + software_interrupt_handler = handler; +} diff --git a/pi/root.zig b/pi/root.zig @@ -23,6 +23,12 @@ pub inline fn set_sp(sp: *usize) void { : .{ .r13 = true }); // sp } +pub inline fn get_sp() usize { + return asm volatile ("mov %[result], sp" + : [result] "=r" (-> usize), + ); +} + // TODO; should do something better var svc_stack: [2024]usize align(8) = .{0} ** 2024; var abort_stack: [32]usize align(8) = .{0} ** 32; diff --git a/src/labs/4-syscall-1.zig b/src/labs/4-syscall-1.zig @@ -0,0 +1,72 @@ +const pi = @import("pi"); + +const uart = @import("devices/mini-uart.zig"); + +comptime { + asm ( + \\ .global syscall_hello; + \\ .type syscall_hello, %function; + \\ syscall_hello: + \\ push {lr} + \\ swi 1 + \\ pop {lr} + \\ bx lr + \\ + \\ .global syscall_illegal; + \\ .type syscall_illegal, %function; + \\ syscall_illegal: + \\ push {lr} + \\ swi 2 + \\ pop {lr} + \\ bx lr + ); +} + +extern fn syscall_hello(msg: *const u8) i32; +extern fn syscall_illegal() i32; + +const Syscall = packed struct(u32) { + num: u24, + _: u4, + cond: u4, +}; + +export fn syscall_handler(pc: u32, r0: u32) i32 { + const syscall: Syscall = @bitCast(pi.mem.get_u32(@ptrFromInt(pc))); + + uart.writer.print("instruction=0x{X}, number={d}\n", .{ @as(u32, @bitCast(syscall)), syscall.num }) catch {}; + + switch (syscall.num) { + 1 => { + uart.write_slice("syscall: "); + const str: [*]const u8 = @ptrFromInt(r0); + var i: usize = 0; + + while (str[i] != 0) { + uart.write_byte(str[i]); + i += 1; + } + + return 0; + }, + else => { + uart.writer.print("illegal system call: {d}!\n", .{syscall.num}) catch {}; + return -1; + }, + } +} + +pub fn main() !void { + try uart.writer.print("current stack pointer = 0x{x}\n", .{pi.get_sp()}); + + pi.interrupts.set_software_interrupt(syscall_handler); + pi.interrupts.enable_interrupts(); + + try uart.writer.print("running syscall hello\n", .{}); + const res_hello = syscall_hello(@ptrCast("hello world!\n")); + try uart.writer.print("result of calling syscall: {d}\n", .{res_hello}); + + try uart.writer.print("running illegal call\n", .{}); + const res_illegal = syscall_illegal(); + try uart.writer.print("result of illegal syscall: {d}\n", .{res_illegal}); +} diff --git a/src/main.zig b/src/main.zig @@ -1 +1 @@ -fn main() void {} +pub fn main() !void {}