From e90b72ec3082588b296956730bd2930cf8d5d671 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Fri, 10 Jul 2026 11:31:46 +0800 Subject: 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. --- na/kernel/sys_misc.cc | 360 -------------------------------------------------- 1 file changed, 360 deletions(-) delete mode 100644 na/kernel/sys_misc.cc (limited to 'na/kernel/sys_misc.cc') diff --git a/na/kernel/sys_misc.cc b/na/kernel/sys_misc.cc deleted file mode 100644 index 48eb47b..0000000 --- a/na/kernel/sys_misc.cc +++ /dev/null @@ -1,360 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * Miscellaneous System Calls — busybox bootstrap set - * - * Each syscall follows the Linux kernel semantics exactly. - * Reference: Linux kernel/sys.c, kernel/signal.c, kernel/time/posix-timers.c - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* ====================================================================== - * sys_reboot — Linux kernel/reboot.c - * - * Validates magic numbers and performs the requested action. - * For now, we only support LINUX_REBOOT_CMD_CAD_ON/OFF (ignore) - * and reject everything else with -EPERM (no CAP_SYS_BOOT). - * ====================================================================== */ - -static constexpr uint32 LINUX_REBOOT_MAGIC1 = 0xfee1dead; -static constexpr uint32 LINUX_REBOOT_MAGIC2 = 672274793; /* 0x28121969 */ -static constexpr uint32 LINUX_REBOOT_MAGIC2A = 85072278; -static constexpr uint32 LINUX_REBOOT_MAGIC2B = 369367448; -static constexpr uint32 LINUX_REBOOT_MAGIC2C = 537993216; - -int64 sys_reboot(uint64 magic1, uint64 magic2, uint64 cmd, - uint64, uint64, uint64) -{ - /* Linux: kernel/reboot.c — validate magic numbers first */ - if (static_cast(magic1) != LINUX_REBOOT_MAGIC1) - return -EINVAL; - if (static_cast(magic2) != LINUX_REBOOT_MAGIC2 && - static_cast(magic2) != LINUX_REBOOT_MAGIC2A && - static_cast(magic2) != LINUX_REBOOT_MAGIC2B && - static_cast(magic2) != LINUX_REBOOT_MAGIC2C) - return -EINVAL; - - /* We don't have CAP_SYS_BOOT yet — reject with -EPERM. - * This matches Linux behavior for unprivileged callers. - * Busybox handles this gracefully and continues. */ - (void)cmd; - printk(KERN_INFO "reboot: cmd=%llu (not implemented, returning -EPERM)\n", cmd); - return -EPERM; -} - -/* ====================================================================== - * sys_prctl — Linux kernel/sys.c - * - * Process control. Most options are optional for early boot. - * We implement the minimum set busybox needs. - * ====================================================================== */ - -/* prctl option constants (from ) */ -static constexpr int PR_SET_NAME = 15; -static constexpr int PR_GET_NAME = 16; -static constexpr int PR_SET_PDEATHSIG = 1; -static constexpr int PR_GET_PDEATHSIG = 2; - -int64 sys_prctl(uint64 option, uint64 arg2, uint64 arg3, - uint64 arg4, uint64 arg5, uint64) -{ - switch (static_cast(option)) { - case PR_SET_PDEATHSIG: - /* Linux: set signal delivered when parent dies. - * Silently accept — we don't track pdeath_signal yet. */ - return 0; - case PR_GET_PDEATHSIG: { - /* Linux: return current pdeath_signal (0 = none) */ - int32 zero = 0; - if (copy_to_user(arg2, &zero, sizeof(zero)) != 0) - return -EFAULT; - return 0; - } - case PR_SET_NAME: { - /* Linux: set comm (task name), max 16 chars */ - /* TODO: copy_from_user the string */ - return 0; - } - case PR_GET_NAME: { - /* Linux: get comm (task name) */ - TaskControlBlock* curr = current_task(); - if (!curr) return -ESRCH; - const char* name = curr->name ? curr->name : ""; - uint64 len = 0; - while (name[len] && len < 15) len++; - char buf[16] = {}; - for (uint64 i = 0; i < len; i++) buf[i] = name[i]; - if (copy_to_user(arg2, buf, 16) != 0) - return -EFAULT; - return 0; - } - default: - /* Unknown prctl — Linux returns -EINVAL for unrecognized options */ - return -EINVAL; - } -} - -/* ====================================================================== - * Session / Process-Group syscalls - * - * All four operate on the caller's signal_struct (or a target task's). - * Identity lives in signal_struct, so these become straightforward reads - * and pgrp-hash updates. We mirror Linux kernel/sys.c semantics closely. - * ====================================================================== */ - -static TaskControlBlock* find_task_by_pid(int32 pid) -{ - extern list_node g_all_tasks; - extern Spinlock g_task_list_lock; - LockGuard guard(g_task_list_lock); - list_node* node = g_all_tasks.next; - while (node != &g_all_tasks) { - auto* task = list_entry(node); - if (task->pid == pid) return task; - node = node->next; - } - return nullptr; -} - -/* - * sys_setsid — Linux kernel/sys.c:ksys_setsid() - * - * Caller becomes leader of a new session+pgrp. Refused if a pgrp with - * id == caller pid already exists with members other than the caller — - * that's Linux's "process group id already exists" check, which prevents - * collisions when a non-leader tries to setsid. - */ -int64 sys_setsid(uint64, uint64, uint64, uint64, uint64, uint64) -{ - TaskControlBlock* curr = current_task(); - if (!curr || !curr->signal) return -ESRCH; - - /* Detect collision: another pgrp already uses our pid as pgid. */ - bool conflict = false; - for_each_pgrp_member(curr->pid, [&](signal_struct* sig) { - if (sig != curr->signal) conflict = true; - }); - if (conflict) return -EPERM; - - /* Move to new pgrp (creates one if missing), update sid, drop ctty. */ - change_pgid(curr->signal, curr->pid); - - /* Detach the controlling terminal. If this task is the session - * leader that owns the tty (tty->session == caller's old sid), - * also clear the tty's session/pgrp so the next session-leader - * that opens the device can claim it. Without this, tty->session - * permanently sticks to the abandoned sid and every subsequent - * tty_acquire_ctty() bails with "owned by another session" — - * which is exactly what kept BusyBox's child sh from picking the - * console back up after init's setsid(). - * - * Linux's behavior is similar in spirit (disassociate_ctty when - * the leader exits), but it triggers from exit, not setsid. Our - * simpler "clear-on-give-up" matches the way our acquisition path - * is written. */ - tty_struct* old_tty = nullptr; - int32 old_sid = 0; - { - LockGuard guard(curr->signal->lock); - old_tty = curr->signal->tty; - old_sid = curr->signal->sid; - curr->signal->sid = curr->pid; - curr->signal->tty = nullptr; - curr->signal->tty_old_pgrp = 0; - } - if (old_tty) { - LockGuard guard(old_tty->lock); - if (old_tty->session == old_sid) { - old_tty->session = 0; - old_tty->pgrp = 0; - } - } - return curr->pid; -} - -/* - * sys_setpgid — Linux kernel/sys.c:ksys_setpgid() - * - * Move a process between groups within the same session. Allowed: - * - caller targeting self or a child - * - target is not a session leader - * - target stays in caller's session - * - target hasn't exec()'d (we don't track did_exec yet, so skip) - * - new pgid is either == target's pid (new group) or names a pgrp - * that already exists in the same session - */ -int64 sys_setpgid(uint64 pid, uint64 pgid, uint64, uint64, uint64, uint64) -{ - TaskControlBlock* curr = current_task(); - if (!curr || !curr->signal) return -ESRCH; - - int32 target_pid = static_cast(pid); - int32 target_pgid = static_cast(pgid); - - if (target_pid == 0) target_pid = curr->pid; - if (target_pgid == 0) target_pgid = target_pid; - if (target_pgid < 0) return -EINVAL; - - TaskControlBlock* target = (target_pid == curr->pid) - ? curr - : find_task_by_pid(target_pid); - if (!target || !target->signal) return -ESRCH; - - /* Target must be caller or a child of caller. */ - if (target != curr && target->parent != curr) return -ESRCH; - - /* Same session as caller. */ - if (target->signal->sid != curr->signal->sid) return -EPERM; - - /* Cannot move a session leader into a different pgrp. */ - if (target->signal->sid == target->pid) return -EPERM; - - /* If target_pgid != target_pid, the pgrp must already exist in - * the same session. pgrp existence == any signal_struct with - * pgid == target_pgid AND sid == caller's sid. */ - if (target_pgid != target->pid) { - bool found = false; - for_each_pgrp_member(target_pgid, [&](signal_struct* sig) { - if (sig->sid == curr->signal->sid) found = true; - }); - if (!found) return -EPERM; - } - - change_pgid(target->signal, target_pgid); - return 0; -} - -/* - * sys_getpgid — return process group ID of `pid` (0 = self). - */ -int64 sys_getpgid(uint64 pid, uint64, uint64, uint64, uint64, uint64) -{ - TaskControlBlock* curr = current_task(); - if (!curr || !curr->signal) return -ESRCH; - - if (pid == 0) return curr->signal->pgid; - - TaskControlBlock* target = find_task_by_pid(static_cast(pid)); - if (!target || !target->signal) return -ESRCH; - return target->signal->pgid; -} - -/* - * sys_getsid — return session ID of `pid` (0 = self). - */ -int64 sys_getsid(uint64 pid, uint64, uint64, uint64, uint64, uint64) -{ - TaskControlBlock* curr = current_task(); - if (!curr || !curr->signal) return -ESRCH; - - if (pid == 0) return curr->signal->sid; - - TaskControlBlock* target = find_task_by_pid(static_cast(pid)); - if (!target || !target->signal) return -ESRCH; - - /* Linux: -EPERM if target's session differs from caller's and we're - * in a different namespace. We have one namespace, so always allow. */ - return target->signal->sid; -} - -/* ====================================================================== - * sys_geteuid / sys_getegid — Linux kernel/sys.c - * - * Return effective UID/GID. We run everything as root (0). - * ====================================================================== */ - -int64 sys_geteuid(uint64, uint64, uint64, uint64, uint64, uint64) -{ - /* Linux: return current_euid(). We are always root. */ - return 0; -} - -int64 sys_getegid(uint64, uint64, uint64, uint64, uint64, uint64) -{ - /* Linux: return current_egid(). We are always root. */ - return 0; -} - -/* ====================================================================== - * sys_sigaltstack — Linux kernel/signal.c - * - * Set/get alternate signal stack. For now, accept and ignore - * (busybox doesn't critically need it for shell operation). - * ====================================================================== */ - -int64 sys_sigaltstack(uint64 uss_ptr, uint64 uoss_ptr, - uint64, uint64, uint64, uint64) -{ - /* Linux: if uoss != NULL, return current alt stack info. - * We don't have alt stacks yet — report SS_DISABLE. */ - if (uoss_ptr != 0) { - /* stack_t { void* ss_sp; int ss_flags; size_t ss_size; } - * On RISC-V LP64: 8 + 4 + padding + 8 = 24 bytes typically, - * but the ABI packs it as {uint64, int32, pad, uint64}. */ - struct { - uint64 ss_sp; - int32 ss_flags; - int32 _pad; - uint64 ss_size; - } oss = { 0, 2 /* SS_DISABLE */, 0, 0 }; - if (copy_to_user(uoss_ptr, &oss, sizeof(oss)) != 0) - return -EFAULT; - } - - /* uss: silently accept (we'll need it for proper signal handling later) */ - (void)uss_ptr; - return 0; -} - -/* ====================================================================== - * sys_clock_gettime — Linux kernel/time/posix-timers.c - * - * Get the current time for a given clock. - * We use the RISC-V cycle counter as a monotonic source. - * ====================================================================== */ - -static constexpr int CLOCK_REALTIME = 0; -static constexpr int CLOCK_MONOTONIC = 1; - -int64 sys_clock_gettime(uint64 clk_id, uint64 tp_ptr, - uint64, uint64, uint64, uint64) -{ - if (tp_ptr == 0) return -EFAULT; - - /* Read RISC-V time CSR (mtime mapped to SBI) */ - uint64 ticks = arch::cpu::read_time(); - - /* Convert to seconds + nanoseconds. - * QEMU virt timebase-frequency is 10MHz. */ - constexpr uint64 kTimebaseHz = 10'000'000ULL; - uint64 sec = ticks / kTimebaseHz; - uint64 nsec = (ticks % kTimebaseHz) * (1'000'000'000ULL / kTimebaseHz); - - struct timespec64 { - int64 tv_sec; - int64 tv_nsec; - }; - - timespec64 ts; - ts.tv_sec = static_cast(sec); - ts.tv_nsec = static_cast(nsec); - - (void)clk_id; /* We treat all clocks as monotonic for now */ - - if (copy_to_user(tp_ptr, &ts, sizeof(ts)) != 0) - return -EFAULT; - - return 0; -} -- cgit v1.2.3