sylveos

Toy Operating System
Log | Files | Refs

commit a0e84bf32460b7868e293d9aa2daf5a9879b3cd3
parent ab2d3ee79f760a36c0bb12ca2ceb8b44c01d84a4
Author: Sylvia Ivory <git@sivory.net>
Date:   Fri, 23 Jan 2026 20:17:55 -0800

Add syscall-2 (new root needed)

Diffstat:
Mpi/cpsr.zig | 15++++++++++++++-
Mpi/interrupts.zig | 8++++----
Asrc/labs/4-syscall-2.zig | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main.zig | 2+-
4 files changed, 99 insertions(+), 6 deletions(-)

diff --git a/pi/cpsr.zig b/pi/cpsr.zig @@ -33,13 +33,26 @@ pub inline fn get() CPSR { ); } +pub inline fn get_s() CPSR { + return asm volatile ("MRS %[result], spsr" + : [result] "=r" (-> CPSR), + ); +} + pub inline fn set(cpsr: CPSR) void { - return asm volatile ("MSR cpsr_c, %[value]" + return asm volatile ("MSR cpsr_cxsf, %[value]" : : [value] "r" (@as(u32, @bitCast(cpsr))), : .{ .cpsr = true }); } +pub inline fn set_s(cpsr: CPSR) CPSR { + return asm volatile ("MRS spsr_cxsf, %[value]" + : + : [value] "r" (cpsr), + : .{ .cpsr = true }); +} + pub inline fn enable_interrupts() void { var cpsr = get(); cpsr.i = true; diff --git a/pi/interrupts.zig b/pi/interrupts.zig @@ -102,13 +102,13 @@ comptime { \\ .global software_interrupt; \\ .type software_interrupt, %function; \\ software_interrupt: - \\ push {r0-r2, lr} - \\ mov r1, r0 + \\ push {r0-r12, lr} \\ sub lr, lr, #4 + \\ mov r1, r0 \\ mov r0, lr \\ bl syscall_handler - \\ pop {r0-r2, lr} - \\ subs pc, lr, #0 + \\ pop {r0-r12, lr} + \\ movs pc, lr ); } extern fn software_interrupt() void; diff --git a/src/labs/4-syscall-2.zig b/src/labs/4-syscall-2.zig @@ -0,0 +1,80 @@ +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 {}; + + const spsr = pi.cpsr.get_s(); + uart.writer.print("saved spsr mode = {t}\n", .{spsr.mode}) 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; + } + + syscall_return(0); + return 0; + }, + else => { + uart.writer.print("illegal system call: {d}!\n", .{syscall.num}) catch {}; + syscall_return(-1); + return -1; + }, + } +} + +pub fn main() !void { + // Switch to user + var cpsr = pi.cpsr.get(); + cpsr.mode = .User; + pi.cpsr.set(cpsr); + + try uart.writer.print("current stack pointer = 0x{x}\n", .{pi.get_sp()}); + try uart.writer.print("current cpsr mode = {t}\n", .{cpsr.mode}); + + 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 @@ -pub fn main() !void {} +fn main() !void {}