diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:31:46 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:31:46 +0800 |
| commit | e90b72ec3082588b296956730bd2930cf8d5d671 (patch) | |
| tree | 36ff6916af9b4176ea5a9662219d11e721f0b691 /src/kernel/syscall.cc | |
| parent | 1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (diff) | |
| download | lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.gz lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.xz | |
refactor: promote new architecture to repository root
Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior.
Diffstat (limited to 'src/kernel/syscall.cc')
| -rw-r--r-- | src/kernel/syscall.cc | 698 |
1 files changed, 0 insertions, 698 deletions
diff --git a/src/kernel/syscall.cc b/src/kernel/syscall.cc deleted file mode 100644 index 0979c24..0000000 --- a/src/kernel/syscall.cc +++ /dev/null @@ -1,698 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2026 Richard Qin - */ -#include "kernel/syscall.h" -#include "common/types.h" -#include "common/fcntl.h" -#include "kernel/proc.h" -#include "kernel/riscv.h" -#include "drivers/uart.h" -#include "drivers/virtio.h" -#include "kernel/timer.h" -#include "kernel/mm.h" -#include "kernel/trap.h" -#include "kernel/slab.h" -#include "kernel/sbi.h" -#include "fs/fat32.h" -#include "fs/file.h" -#include "lib/string.h" -#include "lib/errno.h" - -extern "C++" int fork(); -namespace Exec -{ - int exec(char *path, char **argv); -} - -namespace ProcManager -{ - void exit(int status); - int wait(uint64_t addr); -} - -static uint64_t argraw(int n) -{ - Proc *p = myproc(); - switch (n) - { - case 0: - return p->tf->a0; - case 1: - return p->tf->a1; - case 2: - return p->tf->a2; - case 3: - return p->tf->a3; - case 4: - return p->tf->a4; - case 5: - return p->tf->a5; - default: - return static_cast<uint64_t>(-1); - } -} - -static int argint(int n, int *ip) -{ - *ip = static_cast<int>(argraw(n)); - return 0; -} - -static int argstr(int n, char *buf, int max) -{ - uint64 addr = argraw(n); - return VM::copyinstr(myproc()->pagetable, buf, addr, max); -} - -struct KernelArgv -{ - static const int MAX_ARGS = 32; - static const int MAX_ARG_LEN = 128; - char *args[MAX_ARGS]; - - KernelArgv() { memset(args, 0, sizeof(args)); } - ~KernelArgv() - { - for (int i = 0; i < MAX_ARGS; i++) - if (args[i]) - { - Slab::kfree(args[i]); - args[i] = nullptr; - } - } - KernelArgv(const KernelArgv &) = delete; - KernelArgv &operator=(const KernelArgv &) = delete; -}; - -static int fdalloc(struct file *f) -{ - struct Proc *p = myproc(); - for (int i = 0; i < NOFILE; i++) - { - if (p->ofile[i] == 0) - { - p->ofile[i] = f; - return i; - } - } - return -1; -} - -// sys_openat(int dfd, const char *filename, int flags, mode_t mode) -static uint64 sys_openat() -{ - char path[128]; - int dfd, omode, mode_unused; - int fd; - struct file *f; - Inode *ip; - - if (argint(0, &dfd) < 0 || argstr(1, path, 128) < 0 || argint(2, &omode) < 0 || argint(3, &mode_unused) < 0) - return -EINVAL; - - if (omode & O_CREATE) - { - ip = VFS::namei(path); - if (ip == nullptr) - { - char name[128]; - Inode *dp = VFS::nameiparent(path, name); - if (dp) - { - VFS::ilock(dp); - ip = dp->create(name, T_FILE, 0, 0); - VFS::iunlockput(dp); - } - } - } - else - { - ip = VFS::namei(path); - } - - if (ip == nullptr) - return -ENOENT; - - VFS::ilock(ip); - if ((omode & O_TRUNC) && ip->type == T_FILE) - { - ip->truncate(); - } - VFS::iunlock(ip); - - f = FileTable::alloc(); - if (f == nullptr) - { - VFS::iput(ip); - return -ENFILE; - } - - fd = fdalloc(f); - if (fd < 0) - { - f->ref = 0; - f->type = FD_NONE; - VFS::iput(ip); - return -EMFILE; - } - - f->type = FD_INODE; - f->ip = ip; - f->off = 0; - f->readable = !(omode & O_WRONLY); - f->writable = (omode & O_WRONLY) || (omode & O_RDWR); - - return fd; -} - -// sys_mkdirat(int dfd, const char *pathname, mode_t mode) -static uint64 sys_mkdirat() -{ - char path[128]; - int dfd, mode; - - if (argint(0, &dfd) < 0 || argstr(1, path, 128) < 0 || argint(2, &mode) < 0) - return -EINVAL; - - Inode *ip = VFS::namei(path); - if (ip != nullptr) - { - VFS::iput(ip); - return -EEXIST; - } - - char name[128]; - Inode *dp = VFS::nameiparent(path, name); - if (dp == nullptr) - return -ENOENT; - - VFS::ilock(dp); - ip = dp->create(name, T_DIR, 0, 0); - VFS::iunlockput(dp); - - if (ip == nullptr) - return -EIO; - - VFS::iput(ip); - return 0; -} - -static uint64 sys_chdir() -{ - char path[128]; - if (argstr(0, path, 128) < 0) - return -EFAULT; - - Inode *ip = VFS::namei(path); - if (ip == nullptr) - return -ENOENT; - - VFS::ilock(ip); - if (ip->type != T_DIR) - { - VFS::iunlockput(ip); - return -ENOTDIR; - } - VFS::iunlock(ip); - - struct Proc *p = myproc(); - if (p->cwd) - VFS::iput(p->cwd); - p->cwd = ip; - return 0; -} - -static uint64 sys_dup() -{ - int oldfd; - if (argint(0, &oldfd) < 0) - return -EINVAL; - - struct Proc *p = myproc(); - if (oldfd < 0 || oldfd >= NOFILE || p->ofile[oldfd] == nullptr) - return -EBADF; - - struct file *f = FileTable::dup(p->ofile[oldfd]); - int newfd = fdalloc(f); - if (newfd < 0) - { - FileTable::close(f); - return -EMFILE; - } - return newfd; -} - -static uint64 sys_fstat() -{ - int fd; - uint64 stat_addr; - - if (argint(0, &fd) < 0 || argint(1, (int *)&stat_addr) < 0) - return -EINVAL; - - struct Proc *p = myproc(); - if (fd < 0 || fd >= NOFILE || p->ofile[fd] == nullptr) - return -EBADF; - - if (FileTable::stat(p->ofile[fd], stat_addr) < 0) - return -EIO; - - return 0; -} - -// sys_mknodat(int dfd, const char *filename, mode_t mode, dev_t dev) -static uint64 sys_mknodat() -{ - char path[128]; - int dfd, mode, dev; - - if (argint(0, &dfd) < 0 || argstr(1, path, 128) < 0 || argint(2, &mode) < 0 || argint(3, &dev) < 0) - return -EINVAL; - - Inode *ip = VFS::namei(path); - if (ip != nullptr) - { - VFS::iput(ip); - return -EEXIST; - } - - char name[128]; - Inode *dp = VFS::nameiparent(path, name); - if (dp == nullptr) - return -ENOENT; - - // Decode dev_t (Assuming simplified minor/major for now) - int major = (dev >> 20) & 0xFFF; // Just a guess for Linux packing, or pass raw - int minor = dev & 0xFFFFF; - - // For Phase 1 compatibility with init.cc: - // init.cc passes raw major/minor. Shim will pack them. - // We just unpack naively or assume Shim passed us correct structure. - - VFS::ilock(dp); - ip = dp->create(name, T_DEVICE, major, minor); - VFS::iunlockput(dp); - - if (ip == nullptr) - return -EIO; - - VFS::iput(ip); - return 0; -} - -static uint64 sys_close() -{ - int fd; - if (argint(0, &fd) < 0) - return -EINVAL; - - struct Proc *p = myproc(); - if (fd < 0 || fd >= NOFILE || p->ofile[fd] == 0) - return -EBADF; - - FileTable::close(p->ofile[fd]); - p->ofile[fd] = 0; - return 0; -} - -static uint64 sys_pipe2() -{ - uint64 fdarray; - int flags; - struct file *rf, *wf; - int fd0, fd1; - struct Proc *p = myproc(); - - if (argint(0, (int *)&fdarray) < 0 || argint(1, &flags) < 0) - return -EFAULT; - - if (Pipe::create_pair(&rf, &wf) < 0) - return -ENFILE; - - if ((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0) - { - if (fd0 >= 0) - p->ofile[fd0] = nullptr; - FileTable::close(rf); - FileTable::close(wf); - return -EMFILE; - } - - if (VM::copyout(p->pagetable, fdarray, (char *)&fd0, sizeof(int)) < 0 || - VM::copyout(p->pagetable, fdarray + sizeof(int), (char *)&fd1, sizeof(int)) < 0) - { - p->ofile[fd0] = nullptr; - p->ofile[fd1] = nullptr; - FileTable::close(rf); - FileTable::close(wf); - return -EFAULT; - } - return 0; -} - -static uint64 sys_unlinkat() -{ - char path[128], name[128]; - int dfd, flag; - - if (argint(0, &dfd) < 0 || argstr(1, path, 128) < 0 || argint(2, &flag) < 0) - return -EINVAL; - - Inode *dp = VFS::nameiparent(path, name); - if (!dp) - return -ENOENT; - - VFS::ilock(dp); - int ret = dp->unlink(name); - VFS::iunlockput(dp); - - return (ret < 0) ? -EIO : 0; -} - -// sys_linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) -static uint64 sys_linkat() -{ - // FAT32 does not support hard links. - // Return Error to allow compilation/running to proceed (ln will fail gracefully). - return -EPERM; -} - -static uint64 sys_execve() -{ - char path[128]; - uint64 uargv_ptr; - - if (argstr(0, path, sizeof(path)) < 0) - return -EFAULT; - - uargv_ptr = argraw(1); - // uenvp_ptr = argraw(2); // Ignored - - KernelArgv kargv; - - for (int i = 0; i < KernelArgv::MAX_ARGS; ++i) - { - uint64 uarg_str_ptr; - if (VM::copyin(myproc()->pagetable, (char *)&uarg_str_ptr, uargv_ptr + i * sizeof(uint64), sizeof(uint64)) < 0) - { - return -EFAULT; - } - - if (uarg_str_ptr == 0) - { - kargv.args[i] = nullptr; - break; - } - - kargv.args[i] = (char *)Slab::kmalloc(KernelArgv::MAX_ARG_LEN); - if (kargv.args[i] == nullptr) - { - return -ENOMEM; - } - - if (VM::copyinstr(myproc()->pagetable, kargv.args[i], uarg_str_ptr, KernelArgv::MAX_ARG_LEN) < 0) - { - return -EFAULT; - } - } - return Exec::exec(path, kargv.args); -} - -static uint64 sys_exit() -{ - int n; - if (argint(0, &n) < 0) - return -EINVAL; - ProcManager::exit(n); - return 0; -} - -static uint64 sys_clone() -{ - return static_cast<uint64>(fork()); -} - -static uint64 sys_wait4() -{ - uint64 status_addr; - - // argraw(0) is pid (ignored) - status_addr = argraw(1); - // argraw(2) is options (ignored) - // argraw(3) is rusage (ignored) - - if (status_addr == static_cast<uint64>(-1)) - return -EINVAL; - - return static_cast<uint64>(ProcManager::wait(status_addr)); -} - -static uint64 sys_getpid() -{ - return static_cast<uint64>(myproc()->pid); -} - -static uint64 sys_putc() -{ - char c = static_cast<char>(argraw(0)); - Drivers::uart_putc(c); - return 0; -} - -static uint64 sys_write() -{ - struct file *f; - int n; - uint64 p; - int fd; - - if (argint(0, &fd) < 0 || argint(1, (int *)&p) < 0 || argint(2, &n) < 0) - return -EINVAL; - - p = argraw(1); - - struct Proc *proc = myproc(); - - if (fd == 1 && proc->ofile[fd] == nullptr) - { - constexpr int MAX_WRITE_BUF = 128; - char buf[MAX_WRITE_BUF]; - int i = 0; - - while (i < n) - { - int len = n - i; - if (len > MAX_WRITE_BUF) - len = MAX_WRITE_BUF; - - if (VM::copyin(proc->pagetable, buf, p + i, static_cast<uint64>(len)) < 0) - return -EFAULT; - - for (int j = 0; j < len; j++) - { - Drivers::uart_putc(buf[j]); - } - i += len; - } - return static_cast<uint64>(n); - } - - if (fd < 0 || fd >= NOFILE || (f = proc->ofile[fd]) == 0) - return -EBADF; - - return FileTable::write(f, p, n); -} - -static uint64_t sys_read() -{ - struct file *f; - int n; - uint64 p; - int fd; - - if (argint(0, &fd) < 0 || argint(1, (int *)&p) < 0 || argint(2, &n) < 0) - return -EINVAL; - - p = argraw(1); - - struct Proc *proc = myproc(); - if (fd == 0 && proc->ofile[fd] == nullptr) - return Drivers::console_read(p, n); - - if (fd < 0 || fd >= NOFILE || (f = proc->ofile[fd]) == 0) - return -EBADF; - - return FileTable::read(f, p, n); -} - -static uint64 sys_brk() -{ - int n; - if (argint(0, &n) < 0) - return -EINVAL; - - uint64 addr = myproc()->sz; - if (ProcManager::growproc(n) < 0) - return -ENOMEM; - - return addr; -} - -static uint64 sys_kill() -{ - int pid; - if (argint(0, &pid) < 0) - return -EINVAL; - return ProcManager::kill(pid); -} - -static uint64 sys_sleep() -{ - int n; - uint64 ticks0; - - if (argint(0, &n) < 0) - return -EINVAL; - - Spinlock *lk = Timer::get_lock(); - lk->acquire(); - ticks0 = Timer::get_ticks(); - while (Timer::get_ticks() - ticks0 < (uint64)n) - { - if (myproc()->killed) - { - lk->release(); - return -EINTR; - } - ProcManager::sleep(Timer::get_tick_chan(), lk); - } - lk->release(); - return 0; -} - -static uint64 sys_disk_test() -{ - // VirtIO::test_rw(); - // VirtIO::test_bio(); - fat32_test(); - return 0; -} - -static uint64 sys_lseek() -{ - int fd, offset, whence; - if (argint(0, &fd) < 0 || argint(1, &offset) < 0 || argint(2, &whence) < 0) - return -EINVAL; - - struct Proc *p = myproc(); - if (fd < 0 || fd >= NOFILE || p->ofile[fd] == 0) - return -EBADF; - - return FileTable::lseek(p->ofile[fd], offset, whence); -} - -static uint64 sys_reboot() -{ - SBI::sbi_shutdown(); - return 0; -} - -void syscall() -{ - Proc *p = myproc(); - int num = p->tf->a7; - uint64 ret = static_cast<uint64>(-ENOSYS); - - switch (num) - { - case SYS_mknodat: - ret = sys_mknodat(); - break; - case SYS_mkdirat: - ret = sys_mkdirat(); - break; - case SYS_unlinkat: - ret = sys_unlinkat(); - break; - case SYS_linkat: - ret = sys_linkat(); - break; - case SYS_chdir: - ret = sys_chdir(); - break; - case SYS_openat: - ret = sys_openat(); - break; - case SYS_dup: - ret = sys_dup(); - break; - case SYS_close: - ret = sys_close(); - break; - case SYS_pipe2: - ret = sys_pipe2(); - break; - case SYS_lseek: - ret = sys_lseek(); - break; - case SYS_read: - ret = sys_read(); - break; - case SYS_write: - ret = sys_write(); - break; - case SYS_fstat: - ret = sys_fstat(); - break; - case SYS_exit: - ret = sys_exit(); - break; - case SYS_exit_group: - ret = sys_exit(); - break; - case SYS_kill: - ret = sys_kill(); - break; - case SYS_getpid: - ret = sys_getpid(); - break; - case SYS_brk: - ret = sys_brk(); - break; - case SYS_clone: - ret = sys_clone(); - break; - case SYS_execve: - ret = sys_execve(); - if (ret == 0) - return; - break; - case SYS_wait4: - ret = sys_wait4(); - break; - - // Custom / Debug - case SYS_reboot: - ret = sys_reboot(); - break; - case SYS_putc: - ret = sys_putc(); - break; - case SYS_disk_test: - ret = sys_disk_test(); - break; - case SYS_nanosleep: - ret = sys_sleep(); - break; - - default: - Drivers::uart_puts("Unknown Syscall ID: "); - Drivers::print_hex(num); - Drivers::uart_puts("\n"); - ret = -ENOSYS; - break; - } - - p->tf->a0 = ret; -}
\ No newline at end of file |
