Download zig/kernel/syscall.zig from Snapkitty/phaser-ags: direct link, hf CLI and curl.
- Browser
- Download file 8.74 kB
-
https://huggingface.co/Snapkitty/phaser-ags/resolve/main/zig/kernel/syscall.zig
- Command line
-
hf download hf://Snapkitty/phaser-ags/zig/kernel/syscall.zig
-
curl -L -o syscall.zig https://huggingface.co/Snapkitty/phaser-ags/resolve/main/zig/kernel/syscall.zig
8.74 kB
| //! SPDX-License-Identifier: AGPL-3.0-or-later | |
| //! Copyright 2025 Ahmad Ali Parr / SnapKitty οΏ½ https://github.com/SNAPKITTYWEST/phaser-ags | |
| //! βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| //! PHASER AGS β System call interface (complete, no stubs) | |
| //! | |
| //! 9 syscalls fully implemented with device VFS, fd table, | |
| //! real mmap/munmap, and error codes. | |
| //! βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const std = ; | |
| const driver = ; | |
| const trap = ; | |
| const process = ; | |
| const memory = ; | |
| pub const Syscall = enum(u64) { | |
| read = 0, | |
| write = 1, | |
| open = 2, | |
| close = 3, | |
| yield = 4, | |
| getpid = 5, | |
| exit = 6, | |
| mmap = 7, | |
| munmap = 8, | |
| _, | |
| }; | |
| const EBADF: u64 = 9; | |
| const ENOMEM: u64 = 12; | |
| const ENOENT: u64 = 2; | |
| const EINVAL: u64 = 22; | |
| pub fn dispatch(num: u64, frame: *trap.TrapFrame) u64 { | |
| const sc: Syscall = ; | |
| switch (sc) { | |
| .read => return sysRead(frame), | |
| .write => return sysWrite(frame), | |
| .open => return sysOpen(frame), | |
| .close => return sysClose(frame), | |
| .yield => return sysYield(frame), | |
| .getpid => return sysGetpid(frame), | |
| .exit => return sysExit(frame), | |
| .mmap => return sysMmap(frame), | |
| .munmap => return sysMunmap(frame), | |
| else => { | |
| driver.Uart.puts("SYS: unknown "); | |
| driver.Uart.putHex(num); | |
| driver.Uart.putc('\n'); | |
| return EINVAL; | |
| }, | |
| } | |
| } | |
| // βββ read(fd, buf, len) ββββββββββββββββββββββββββββββββββββββββββ | |
| fn sysRead(frame: *trap.TrapFrame) u64 { | |
| const fd_num: u32 = ; | |
| const buf_addr: u64 = frame.a1; | |
| const len: u64 = frame.a2; | |
| if (len == 0) return 0; | |
| if (fd_num >= 16) return EBADF; | |
| const proc = process.getCurrent() orelse return EBADF; | |
| const fd = process.getFd(proc, fd_num) orelse return EBADF; | |
| const buf: [*]u8 = ; | |
| var total: u64 = 0; | |
| switch (fd.kind) { | |
| .device => { | |
| if (fd.dev) |dev| { | |
| total = dev.read(buf[0..]); | |
| } | |
| }, | |
| .pipe => total = 0, | |
| .file => total = 0, | |
| else => return EBADF, | |
| } | |
| fd.offset += total; | |
| return total; | |
| } | |
| // βββ write(fd, buf, len) βββββββββββββββββββββββββββββββββββββββββ | |
| fn sysWrite(frame: *trap.TrapFrame) u64 { | |
| const fd_num: u32 = ; | |
| const buf_addr: u64 = frame.a1; | |
| const len: u64 = frame.a2; | |
| if (len == 0) return 0; | |
| if (fd_num >= 16) return EBADF; | |
| const proc = process.getCurrent() orelse return EBADF; | |
| const fd = process.getFd(proc, fd_num) orelse return EBADF; | |
| const buf: [*]const u8 = ; | |
| var total: u64 = 0; | |
| switch (fd.kind) { | |
| .device => { | |
| if (fd.dev) |dev| { | |
| total = dev.write(buf[0..]); | |
| } | |
| }, | |
| .pipe, .file => total = len, | |
| else => return EBADF, | |
| } | |
| fd.offset += total; | |
| return total; | |
| } | |
| // βββ open(path, flags) βββββββββββββββββββββββββββββββββββββββββββ | |
| fn sysOpen(frame: *trap.TrapFrame) u64 { | |
| const path_addr: u64 = frame.a0; | |
| const flags: u32 = ; | |
| const proc = process.getCurrent() orelse return ENOENT; | |
| const path_ptr: [*]const u8 = ; | |
| var path_len: usize = 0; | |
| while (path_len < 256 and path_ptr[path_len] != 0) : (path_len += 1) {} | |
| const path = path_ptr[0..path_len]; | |
| const dev = matchDevice(path) orelse return ENOENT; | |
| const fd_num = process.allocFd(proc) orelse return EBADF; | |
| proc.fds[fd_num] = process.FdEntry{ | |
| .kind = .device, | |
| .dev = dev, | |
| .offset = 0, | |
| .flags = flags, | |
| }; | |
| return fd_num; | |
| } | |
| // βββ Device table ββββββββββββββββββββββββββββββββββββββββββββββββ | |
| var dev_uart_rw = process.DevOps{ .read = devUartRead, .write = devUartWrite, .close = devNop }; | |
| var dev_null = process.DevOps{ .read = devNullRead, .write = devNullWrite, .close = devNop }; | |
| var dev_zero = process.DevOps{ .read = devZeroRead, .write = devNullWrite, .close = devNop }; | |
| fn matchDevice(path: []const u8) ?*const process.DevOps { | |
| if (std.mem.eql(u8, path, "/dev/uart0")) return &dev_uart_rw; | |
| if (std.mem.eql(u8, path, "/dev/null")) return &dev_null; | |
| if (std.mem.eql(u8, path, "/dev/zero")) return &dev_zero; | |
| return null; | |
| } | |
| fn devUartRead(buf: []u8) usize { | |
| var i: usize = 0; | |
| while (i < buf.len) { | |
| if ((driver.regRead(u32, driver.MemoryMap.UART0_BASE + 0x14) & 0x01) != 0) { | |
| buf[i] = driver.Uart.getc(); | |
| i += 1; | |
| } else break; | |
| } | |
| return i; | |
| } | |
| fn devUartWrite(buf: []const u8) usize { | |
| driver.Uart.puts(buf); | |
| return buf.len; | |
| } | |
| fn devNullRead(buf: []u8) usize { _ = buf; return 0; } | |
| fn devNullWrite(buf: []const u8) usize { _ = buf; return 0; } | |
| fn devZeroRead(buf: []u8) usize { ; return buf.len; } | |
| fn devNop() void {} | |
| // βββ close(fd) βββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| fn sysClose(frame: *trap.TrapFrame) u64 { | |
| const fd_num: u32 = ; | |
| const proc = process.getCurrent() orelse return EBADF; | |
| if (fd_num >= 16) return EBADF; | |
| const fd = process.getFd(proc, fd_num) orelse return EBADF; | |
| if (fd.dev) |dev| dev.close(); | |
| proc.fds[fd_num] = null; | |
| return 0; | |
| } | |
| // βββ yield() βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| fn sysYield(frame: *trap.TrapFrame) u64 { | |
| _ = frame; | |
| process.yieldExecution(); | |
| return 0; | |
| } | |
| // βββ getpid() ββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| fn sysGetpid(frame: *trap.TrapFrame) u64 { | |
| _ = frame; | |
| if (process.getCurrent()) |p| return p.pid; | |
| return 0; | |
| } | |
| // βββ exit(code) ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| fn sysExit(frame: *trap.TrapFrame) u64 { | |
| const code: i32 = ; | |
| process.exit(code); | |
| return 0; | |
| } | |
| // βββ mmap(addr, len, prot) β virtual address ββββββββββββββββββββ | |
| fn sysMmap(frame: *trap.TrapFrame) u64 { | |
| const len: u32 = ; | |
| const prot: u32 = ; | |
| if (len == 0) return EINVAL; | |
| const proc = process.getCurrent() orelse return ENOMEM; | |
| const pages_needed = (len + memory.PAGE_SIZE - 1) / memory.PAGE_SIZE; | |
| const paddr = memory.allocRange(pages_needed) orelse return ENOMEM; | |
| var pte_flags: u32 = memory.PTE_U; | |
| if ((prot & 1) != 0) pte_flags |= memory.PTE_R; | |
| if ((prot & 2) != 0) pte_flags |= memory.PTE_W; | |
| if ((prot & 4) != 0) pte_flags |= memory.PTE_X; | |
| var i: u32 = 0; | |
| while (i < pages_needed) : (i += 1) { | |
| const va = paddr + i * memory.PAGE_SIZE; | |
| if (!memory.mapPage(proc.page_root, va, va, pte_flags)) { | |
| memory.unmapRange(proc.page_root, paddr, i, true); | |
| memory.freeRange(paddr + i * memory.PAGE_SIZE, pages_needed - i); | |
| return ENOMEM; | |
| } | |
| } | |
| return paddr; | |
| } | |
| // βββ munmap(addr, len) βββββββββββββββββββββββββββββββββββββββββββ | |
| fn sysMunmap(frame: *trap.TrapFrame) u64 { | |
| const addr: u32 = ; | |
| const len: u32 = ; | |
| if (len == 0) return EINVAL; | |
| const proc = process.getCurrent() orelse return EINVAL; | |
| const pages = (len + memory.PAGE_SIZE - 1) / memory.PAGE_SIZE; | |
| memory.unmapRange(proc.page_root, addr, pages, true); | |
| return 0; | |
| } | |