From 8cace3f05003c6cb4d38c36890055f03151c2ad4 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Fri, 16 Oct 2026 02:39:56 +0800 Subject: Remove old code Signed-off-by: Richard Qin --- kernel/trap.cc | 258 --------------------------------------------------------- 1 file changed, 258 deletions(-) delete mode 100644 kernel/trap.cc (limited to 'kernel/trap.cc') diff --git a/kernel/trap.cc b/kernel/trap.cc deleted file mode 100644 index 2116d91..0000000 --- a/kernel/trap.cc +++ /dev/null @@ -1,258 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * Trap MI Layer — Machine-Independent Semantic Dispatcher - * - * Receives a translated TrapCause from the MD layer and routes to - * the appropriate handler. - * - * *** MI INVARIANT: This file contains ZERO inline assembly, - * ZERO arch-specific constants (no CSR reads, no scause codes). *** - * arch/trapframe.h is included because TrapFrame is the cross-layer - * data contract defined in docs/specs/arch_abstraction.md §3.2. - * - * Reference: docs/specs/trap.md §4 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* TrapFrame: cross-layer data contract */ -#include /* search_extable: kernel fault recovery */ - -/* ======================================================================== - * trap_handle() — MI-layer dispatcher for traps - * - * Called by MD layer after scause → TrapInfo translation. - * ======================================================================== */ - -static TrapStats g_trap_stats = {}; - -static uint32 trap_cause_index(TrapCause cause) -{ - uint32 raw = static_cast(cause); - - /* Exceptions 0-7 map directly to indices 0-7 */ - if (raw <= 7) { - return raw; - } - /* IRQs 16-18 map to indices 8-10 */ - if (raw >= 16 && raw <= 18) { - return raw - 16 + 8; - } - /* Unknown / out-of-range */ - return 11; -} - -static void trap_record(const TrapInfo& info) -{ - uint32 idx = trap_cause_index(info.cause); - __atomic_fetch_add(&g_trap_stats.total, 1, __ATOMIC_RELAXED); - __atomic_fetch_add(&g_trap_stats.by_cause[idx], 1, __ATOMIC_RELAXED); - g_trap_stats.last_cause = info.cause; - g_trap_stats.last_class = info.cls; - g_trap_stats.last_origin = info.origin; - g_trap_stats.last_val = info.val; - g_trap_stats.last_epc = info.epc; - g_trap_stats.last_scause = info.scause; -} - -static VmFaultCause vm_fault_cause_from_trap(TrapCause cause) -{ - switch (cause) { - case TrapCause::PageFaultStore: - return VmFaultCause::Write; - case TrapCause::PageFaultExec: - return VmFaultCause::Exec; - case TrapCause::PageFaultLoad: - default: - return VmFaultCause::Read; - } -} - -void trap_stats_get(TrapStats* out) -{ - if (!out) { - return; - } - *out = g_trap_stats; -} - -void trap_stats_reset() -{ - g_trap_stats = {}; -} - -void trap_handle(arch::TrapFrame* tf, const TrapInfo& info) -{ - trap_record(info); - - /* ---- Kernel exception handling ---- - * Interrupts are always allowed through. For exceptions: - * - Page faults: handled in the switch below (extable fixup path) - * - Other exceptions: try extable, then panic. - * - * This replaces the old blanket kernel_panic, enabling - * copy_from_user/copy_to_user to safely fault on user pages. */ - if (info.origin == TrapOrigin::FromKernel && - info.cls != TrapClass::Interrupt) { - - /* Page faults are dispatched in the switch — let them through */ - bool is_page_fault = - (info.cause == TrapCause::PageFaultLoad || - info.cause == TrapCause::PageFaultStore || - info.cause == TrapCause::PageFaultExec); - - if (!is_page_fault) { - /* Non-page-fault kernel exception: try extable fixup */ - uint64 fixup = search_extable(info.epc); - if (fixup != 0) { - tf->epc = fixup; - return; - } - kprintf("[trap] fatal kernel exception: cause=%u epc=0x%llx val=0x%llx\n", - static_cast(info.cause), info.epc, info.val); - kernel_panic("unrecoverable kernel exception"); - } - } - - switch (info.cause) { - /* ---- Page Faults ---- */ - case TrapCause::PageFaultLoad: - case TrapCause::PageFaultStore: - case TrapCause::PageFaultExec: - if (info.origin == TrapOrigin::FromUser) { - TaskControlBlock* curr = current_task(); - if (!curr || !curr->mm) { - kernel_panic("user page fault with no current mm"); - } - - int ret = vmm_handle_page_fault(curr->mm, info.val, - vm_fault_cause_from_trap(info.cause)); - if (ret == -EFAULT) { - kprintf("[trap] user SIGSEGV (MAPERR) epc=0x%llx addr=0x%llx\n", - info.epc, info.val); - force_sig_fault(SIGSEGV, 1 /* SEGV_MAPERR */, info.val); - } else if (ret == -ENOMEM) { - kprintf("[trap] user SIGKILL (OOM) epc=0x%llx addr=0x%llx\n", - info.epc, info.val); - force_sig_fault(SIGKILL, 0, info.val); - } else if (ret < 0) { - kprintf("[trap] user SIGSEGV (ACCERR) epc=0x%llx addr=0x%llx\n", - info.epc, info.val); - force_sig_fault(SIGSEGV, 2 /* SEGV_ACCERR */, info.val); - } - break; - } - - /* Kernel page fault — try exception table fixup. - * This is the path used by copy_from_user/copy_to_user when - * accessing unmapped or faulting user addresses from S-mode. */ - { - uint64 fixup = search_extable(info.epc); - if (fixup != 0) { - tf->epc = fixup; - break; - } - } - kprintf("[trap] kernel page fault: epc=0x%llx addr=0x%llx\n", - info.epc, info.val); - { - TaskControlBlock* curr = current_task(); - if (curr) { - kprintf("[trap] pid=%d state=%d\n", - curr->pid, static_cast(curr->state)); - kprintf("[trap] tf->epc=%llx tf->ra=%llx tf->sp=%llx\n", - tf->epc, tf->ra, tf->sp); - } - } - kernel_panic("unhandled kernel page fault (no extable entry)"); - break; - - /* ---- System Call ---- */ - case TrapCause::Syscall: - syscall_dispatch_md(tf); - break; - - /* ---- Interrupts ---- */ - case TrapCause::IrqTimer: - /* Timer tick */ - timer_tick(); - break; - - case TrapCause::IrqExternal: { - /* External interrupt: generic claim → dispatch → complete */ - uint32 irq = g_irq_manager.claim(); - if (irq != 0) { - g_irq_manager.dispatch(irq); - g_irq_manager.complete(irq); - } - break; - } - - case TrapCause::IrqSoftware: - /* S-mode software interrupt = IPI from another hart */ - smp_handle_ipi(); - break; - - /* ---- Fatal exceptions ---- */ - case TrapCause::IllegalInst: - if (info.origin == TrapOrigin::FromUser) { - kprintf("[trap] user illegal instruction at epc=0x%llx stval=0x%llx\n", - info.epc, info.val); - force_sig_fault(SIGILL, 1 /* ILL_ILLOPC */, info.epc); - } else { - kprintf("[trap] illegal instruction at epc=0x%llx\n", info.epc); - kernel_panic("illegal instruction in kernel mode"); - } - break; - - case TrapCause::AccessFault: - kprintf("[trap] access fault\n"); - kernel_panic("access fault"); - break; - - case TrapCause::AlignFault: - kprintf("[trap] alignment fault\n"); - kernel_panic("alignment fault"); - break; - - case TrapCause::Breakpoint: - kprintf("[trap] breakpoint\n"); - /* ebreak advance is handled by MD layer (arch-specific instruction size) */ - break; - - case TrapCause::Unknown: - default: - kprintf("[trap] unknown trap\n"); - kernel_panic("unknown trap"); - break; - } - - /* Process pending signals before returning to user mode */ - if (info.origin == TrapOrigin::FromUser) { - do_signal(tf); - } - - /* Preemption check on return from any interrupt. - * This is the kernel's equivalent of Linux's retint_kernel path: - * if a timer tick (or IPI) set need_resched, we must call schedule() - * before returning — otherwise the idle loop never yields to - * runnable tasks like PID 1. */ - if (info.cls == TrapClass::Interrupt) { - sched_check_preempt(); - } -} -- cgit v1.2.3