commit f0032e962f4cd48af67f1d78ca7f37c7c82f740e
parent 2257dee555b44129f375ce78d8b726414d521d8e
Author: Sylvia Ivory <git@sivory.net>
Date: Sun, 15 Mar 2026 12:48:35 -0700
Hello World from Linux
Diffstat:
5 files changed, 53 insertions(+), 56 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -3,3 +3,4 @@
/src/*.runner.zig
target
/sylveos/hello
+/sylveos/lua
diff --git a/sylveos/loader.zig b/sylveos/loader.zig
@@ -34,12 +34,6 @@ pub fn init(pt_alloc: std.mem.Allocator, heap_alloc: std.mem.Allocator, root: []
var elf_reader = std.Io.Reader.fixed(elf);
const header = try std.elf.Header.read(&elf_reader);
-
- uart.print("phnum: {d}\n", .{header.phnum});
- uart.print("elf len: {d}\n", .{elf.len});
- uart.print("seek: {d}\n", .{elf_reader.seek});
- uart.print("end: {d}\n", .{elf_reader.end});
-
var it: ProgramHeaderBufferIterator = .{
.elf_header = header,
.buf = elf,
@@ -54,12 +48,9 @@ pub fn init(pt_alloc: std.mem.Allocator, heap_alloc: std.mem.Allocator, root: []
const end = std.mem.alignForward(u32, @intCast(program_header.p_vaddr + program_header.p_memsz), memory.KB4);
while (va < end) : (va += memory.KB4) {
- uart.print("requesting 4kb: ", .{});
const pa = try memory.request_4kb(heap_alloc);
- uart.print("VA(0x{X:0>8}) -> PA(0x{X:0>8})\n", .{ va, pa });
try pages.map_4kb(va, pa, .{});
- uart.print(" mapped: VA(0x{X:0>8}) -> PA(0x{X:0>8})\n", .{ va, memory.translate(va) catch 0 });
// Zero page
const dst: [*]u8 = @ptrFromInt(va);
@@ -88,7 +79,6 @@ pub fn init(pt_alloc: std.mem.Allocator, heap_alloc: std.mem.Allocator, root: []
header_location = va + offset_in_page;
}
- uart.print(" writing to 0x{X} from 0x{X} (0x{X})\n", .{ va + offset_in_page, file_offset, copy_size });
@memcpy(dst[offset_in_page .. offset_in_page + copy_size], src);
}
}
@@ -106,9 +96,7 @@ pub fn init(pt_alloc: std.mem.Allocator, heap_alloc: std.mem.Allocator, root: []
{
const sp = stack_top - stack_size;
- uart.print("requesting 64kb: ", .{});
const pa = try memory.request_64kb(heap_alloc);
- uart.print("0x{X:0>8}\n", .{pa});
try pages.map_64kb(sp, pa, .{});
@@ -118,9 +106,7 @@ pub fn init(pt_alloc: std.mem.Allocator, heap_alloc: std.mem.Allocator, root: []
// kuser
{
- uart.print("requesting 4kb: ", .{});
const pa = try memory.request_4kb(heap_alloc);
- uart.print("0x{X:0>8}\n", .{pa});
// TODO; read only
try pages.map_4kb(0xFFFF_0000, pa, .{});
@@ -160,97 +146,79 @@ pub fn execute(self: *Program, pid: u24, args: []const []const u8, env: []const
// 6. Arguments
// 7. Argc
- uart.print("initial sp: {X}\n", .{sp});
-
sp = align_down(sp, 8);
- uart.print("initial alignment: {X}\n", .{sp});
// https://xkcd.com/221/
const at_random_ptr = push_stack_bytes(sp, &[_]u8{4} ** 16);
sp = at_random_ptr;
- uart.print("at_random ptr: {X}\n", .{sp});
const env_ptrs = try alloc.alloc(u32, env.len);
for (env, 0..) |e, idx| {
sp = push_cstring(sp, e);
env_ptrs[idx] = sp;
}
- uart.print("env ptrs: {X}\n", .{sp});
const arg_ptrs = try alloc.alloc(u32, args.len);
for (args, 0..) |a, idx| {
sp = push_cstring(sp, a);
arg_ptrs[idx] = sp;
}
- uart.print("arg ptrs: {X}\n", .{sp});
sp = align_down(sp, 8);
// AT_NULL
sp = push_u32(sp, 0);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_NULL));
- uart.print("at_null sp: {X}\n", .{sp});
// AT_PHDR
sp = push_u32(sp, self.header_location);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_PHDR));
- uart.print("at_phdr sp: {X}\n", .{sp});
// AT_PHENT
sp = push_u32(sp, self.elf_header.phentsize);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_PHENT));
- uart.print("at_phent sp: {X}\n", .{sp});
// AT_PHNUM
sp = push_u32(sp, self.elf_header.phnum);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_PHNUM));
- uart.print("at_phnum sp: {X}\n", .{sp});
// AT_PAGESZ
sp = push_u32(sp, memory.KB4);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_PAGESZ));
- uart.print("at_pagesz sp: {X}\n", .{sp});
// AT_ENTRY
sp = push_u32(sp, self.entrypoint);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_ENTRY));
- uart.print("at_entry sp: {X}\n", .{sp});
// AT_UID
// TODO; let user specify UID
sp = push_u32(sp, 0);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_UID));
- uart.print("at_uid sp: {X}\n", .{sp});
// AT_EUID
// TODO; let user specify EUID
sp = push_u32(sp, 0);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_EUID));
- uart.print("at_euid sp: {X}\n", .{sp});
// AT_GID
// TODO; let user specify GID
sp = push_u32(sp, 0);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_GID));
- uart.print("at_gid sp: {X}\n", .{sp});
// AT_EGID
// TODO; let user specify EUID
sp = push_u32(sp, 0);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_EGID));
- uart.print("at_egid sp: {X}\n", .{sp});
// AT_RANDOM
sp = push_u32(sp, at_random_ptr);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_RANDOM));
- uart.print("at_random sp: {X}\n", .{sp});
// AT_EXECFN
if (args.len != 0) {
sp = push_u32(sp, arg_ptrs[0]);
sp = push_u32(sp, @intFromEnum(AuxTag.AT_EXECFN));
}
- uart.print("at_execfn sp: {X}\n", .{sp});
// env_p
sp = push_u32(sp, 0);
@@ -258,7 +226,6 @@ pub fn execute(self: *Program, pid: u24, args: []const []const u8, env: []const
var i = env_ptrs.len;
while (i > 0) : (i -= 1) sp = push_u32(sp, env_ptrs[i - 1]);
}
- uart.print("envp sp: {X}\n", .{sp});
// arg_v
sp = push_u32(sp, 0);
@@ -266,19 +233,9 @@ pub fn execute(self: *Program, pid: u24, args: []const []const u8, env: []const
var i = arg_ptrs.len;
while (i > 0) : (i -= 1) sp = push_u32(sp, arg_ptrs[i - 1]);
}
- uart.print("argv sp: {X}\n", .{sp});
// arg_c
sp = push_u32(sp, args.len);
- uart.print("argc sp: {X}\n", .{sp});
-
- // sp = align_down(sp, 8);
- // uart.print("final sp: {X}\n", .{sp});
-
- var it = sp;
- while (it < self.stack_pointer) : (it += 4) {
- uart.print("0x{X:8>0}: {X}\n", .{ it, pi.mem.get_u32(@ptrFromInt(it)) });
- }
var psr = pi.PSR.get_c();
psr.mode = .User;
@@ -291,13 +248,6 @@ pub fn execute(self: *Program, pid: u24, args: []const []const u8, env: []const
.psr = psr,
};
- uart.print("switching into!\n", .{});
- uart.print("VA(0x{X}) -> PA(0x{X})\n", .{ self.entrypoint, memory.translate(self.entrypoint) catch 0 });
-
- for (0..16) |idx| {
- uart.print("{X:8>0}\n", .{pi.mem.get_u32(@ptrFromInt(self.entrypoint + idx * 4))});
- }
-
pi.switching.restore_state_privileged(®isters);
}
diff --git a/sylveos/memory.zig b/sylveos/memory.zig
@@ -190,7 +190,6 @@ pub fn get_allocator() std.heap.FixedBufferAllocator {
const heap = Region.heap();
const fba: std.heap.FixedBufferAllocator = .init(@ptrCast(heap.raw[MB..heap.size]));
- uart.print("Main alloc on 0x{X} (size: {Bi})\n", .{ @intFromPtr(fba.buffer.ptr), heap.size - MB });
return fba;
}
@@ -199,7 +198,6 @@ pub fn get_pt_allocator() std.heap.FixedBufferAllocator {
const p_pt = Region.process_page_table();
const fba: std.heap.FixedBufferAllocator = .init(@ptrCast(p_pt.raw[0..p_pt.size]));
- uart.print("PT alloc on 0x{X} (size: {Bi})\n", .{ @intFromPtr(fba.buffer.ptr), p_pt.size });
return fba;
}
diff --git a/sylveos/root.zig b/sylveos/root.zig
@@ -3,6 +3,7 @@ const pi = @import("pi");
const memory = @import("./memory.zig");
const loader = @import("./loader.zig");
+const syscall = @import("./syscall.zig");
const hello_binary = @embedFile("./hello");
const uart = pi.devices.mini_uart;
@@ -98,7 +99,7 @@ export fn abort() noreturn {
}
fn main() !void {
- uart.print("Hello World from VM!\n", .{});
+ interrupts.set_exception_handler(.SoftwareInterrupt, syscall.syscall_handler);
var heap_fba = memory.get_allocator();
const heap_alloc = heap_fba.allocator();
@@ -108,9 +109,6 @@ fn main() !void {
const pt = memory.get_page_table();
- // Just create a 1mb allocation we'll identity map
- uart.print("page_table @ 0x{X}\n", .{@intFromPtr(pt.ptr)});
-
var empty = try loader.init(pt_alloc, heap_alloc, pt, hello_binary);
uart.print(
\\Stack Pointer: {X:0>8}
diff --git a/sylveos/syscall.zig b/sylveos/syscall.zig
@@ -0,0 +1,50 @@
+const pi = @import("pi");
+
+const interrupts = pi.interrupts;
+const uart = pi.devices.mini_uart;
+
+pub fn syscall_handler(registers: interrupts.Registers, _: interrupts.ExceptionVector) void {
+ const n = registers.gp[7];
+
+ switch (n) {
+ // restart_syscall
+ 0 => {},
+ // exit
+ 1 => {
+ const error_code = registers.gp[0];
+
+ uart.print("[syscall] exit({d})\n", .{error_code});
+ pi.reboot();
+ },
+ // fork
+ 2 => {},
+ // read
+ 3 => {},
+ // write
+ 4 => {
+ const fd = registers.gp[0];
+ const buffer: [*]u8 = @ptrFromInt(registers.gp[1]);
+ const count = registers.gp[2];
+
+ uart.print("[syscall] write({d}, 0x{X}, {d})\n", .{ fd, @intFromPtr(buffer), count });
+
+ // stdout
+ if (fd == 1) {
+ uart.print("{s}", .{buffer[0..count]});
+ }
+ },
+ // open
+ 5 => {},
+ // close
+ 6 => {},
+ // exit_group
+ 248 => {},
+ // set_tid_address
+ 256 => {},
+ // ARM_set_tls
+ 983045 => {},
+ else => {
+ uart.print("Unhandled syscall: {d}\n", .{n});
+ },
+ }
+}