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:
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 {}