summaryrefslogtreecommitdiff
path: root/na/arch/riscv/include
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
commite90b72ec3082588b296956730bd2930cf8d5d671 (patch)
tree36ff6916af9b4176ea5a9662219d11e721f0b691 /na/arch/riscv/include
parent1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (diff)
downloadlume-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 'na/arch/riscv/include')
-rw-r--r--na/arch/riscv/include/arch/config.h106
-rw-r--r--na/arch/riscv/include/arch/context.h33
-rw-r--r--na/arch/riscv/include/arch/cpu.h95
-rw-r--r--na/arch/riscv/include/arch/extable.h55
-rw-r--r--na/arch/riscv/include/arch/fpstate.h94
-rw-r--r--na/arch/riscv/include/arch/mmu.h78
-rw-r--r--na/arch/riscv/include/arch/pmap.h49
-rw-r--r--na/arch/riscv/include/arch/random.h27
-rw-r--r--na/arch/riscv/include/arch/sbi.h111
-rw-r--r--na/arch/riscv/include/arch/tlb.h19
-rw-r--r--na/arch/riscv/include/arch/trap.h94
-rw-r--r--na/arch/riscv/include/arch/trapframe.h140
-rw-r--r--na/arch/riscv/include/asm/csr.h37
-rw-r--r--na/arch/riscv/include/asm/page.h62
-rw-r--r--na/arch/riscv/include/asm/pgtable.h55
-rw-r--r--na/arch/riscv/include/asm/sections.h50
16 files changed, 0 insertions, 1105 deletions
diff --git a/na/arch/riscv/include/arch/config.h b/na/arch/riscv/include/arch/config.h
deleted file mode 100644
index 8ae0502..0000000
--- a/na/arch/riscv/include/arch/config.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-/*
- * RISC-V Architecture Configuration
- *
- * These constants define the architecture-specific memory layout.
- * Each arch/ implementation must provide this header with the same symbols.
- *
- * KASLR: At boot, kaslr_init() randomises g_direct_map_base and
- * g_vmemmap_base. All MI code must read these runtime variables
- * (via pa_to_va / vmm helpers) rather than the static defaults.
- */
-
-#include <lume/types.h>
-
-namespace arch {
-
-/* ================================================================
- * Default (compile-time) virtual addresses
- *
- * SV39 gives a 512GB virtual address space.
- * Higher-half layout (defaults before KASLR):
- *
- * 0xFFFFFFC0_00000000 (256) Direct map (PA+offset)
- * 0xFFFFFFD0_00000000 (320) Vmemmap (Page array)
- *
- * The 64GB gap between them is the KASLR slide range.
- * ================================================================ */
-inline constexpr uint64 kDirectMapBaseDefault = 0xFFFFFFC000000000ULL;
-inline constexpr uint64 kVmemmapBaseDefault = 0xFFFFFFD000000000ULL;
-
-/* Physical memory base (where RAM starts on RISC-V virt platform) */
-inline constexpr uint64 kPhysBase = 0x80000000ULL;
-
-/* Kernel physical load address (= PHYS_BASE in linker script).
- * Everything in [kPhysBase, kPhysStart) is firmware territory (PMP-protected).
- * Analogous to Linux's CONFIG_PHYSICAL_START. */
-inline constexpr uint64 kPhysStart = 0x80200000ULL;
-
-/* ================================================================
- * Runtime (post-KASLR) virtual addresses
- *
- * These start equal to the defaults above. If CONFIG_KASLR is
- * enabled, kaslr_init() adds a random, 1GB-aligned offset
- * to each, sliding both regions upward in VA space.
- * ================================================================ */
-extern uint64 g_direct_map_base;
-extern uint64 g_vmemmap_base;
-
-/* ================================================================
- * KASLR Layout Structure (Phase A: Unified KASLR State)
- *
- * This struct holds all KASLR results: the random seed, derived
- * hash, selected slot, and the randomised virtual address bases.
- * It serves as the single source of truth for all KASLR decisions
- * and is filled once during boot and read-only thereafter.
- * ================================================================ */
-
-enum class KaslrSeedSource : uint8 {
- kFdt = 0, /* Loaded from FDT /random node */
- kHardware = 1, /* From hardware RNG (e.g., RDRAND) */
- kCycle = 2, /* Fallback: CPU cycle counter */
-};
-
-struct KaslrLayout {
- /* Seed and provenance */
- uint64 seed; /* 64-bit random seed value */
- uint64 seed_hash; /* Non-plaintext derived hash (splitmix64) */
- KaslrSeedSource source; /* Seed provenance (fdt/hw/cycle) */
-
- /* Randomisation parameters */
- uint64 slot; /* Slot index: [0, 63] */
- uint64 slide_bytes; /* Byte offset: slot * 1GB */
-
- /* Build-time policy */
- uint32 policy_id; /* CONFIG_KASLR_POLICY_ID at build time */
-
- /* Randomised base addresses (post-KASLR) */
- uint64 direct_map_base; /* Direct map VA (kDirectMapBaseDefault + slide) */
- uint64 vmemmap_base; /* Vmemmap VA (kVmemmapBaseDefault + slide) */
-
- /* Validation flags (for debug logging) */
- bool canonical_ok; /* All VA ranges passed canonical check */
- bool overlap_ok; /* No overlaps detected between regions */
-};
-
-/* ================================================================
- * KASLR entry point
- *
- * Must be called AFTER random_early_init() and BEFORE vmm_init().
- * Fills g_kaslr_layout with randomised bases and self-check results.
- * When CONFIG_KASLR is disabled this is a no-op.
- * ================================================================ */
-extern KaslrLayout g_kaslr_layout;
-
-void kaslr_init();
-
-/* Helper to query the KASLR layout safely */
-static inline const KaslrLayout& kaslr_layout_get() {
- return g_kaslr_layout;
-}
-
-} // namespace arch
diff --git a/na/arch/riscv/include/arch/context.h b/na/arch/riscv/include/arch/context.h
deleted file mode 100644
index 3d935fa..0000000
--- a/na/arch/riscv/include/arch/context.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-/*
- * Context Switch Structure (RISC-V 64)
- *
- * Holds only callee-saved registers for voluntary (non-preemptive)
- * context switches between kernel threads / tasks.
- *
- * Used by: arch::context_switch() in swtch.S
- * Reference: docs/specs/arch_abstraction.md §3.1
- */
-
-#include <lume/types.h>
-
-namespace arch {
-
-struct Context {
- uint64 ra; // 0: Return address
- uint64 sp; // 8: Stack pointer
- uint64 s[12]; // 16: s0-s11 (callee-saved registers)
-};
-
-static_assert(sizeof(Context) == 112);
-
-// Assembly-implemented context switch.
-// Saves current CPU registers to old_ctx, loads next_ctx into CPU.
-// Defined in arch/riscv/trap/swtch.S
-extern "C" void context_switch(Context* old_ctx, Context* next_ctx);
-
-} // namespace arch
diff --git a/na/arch/riscv/include/arch/cpu.h b/na/arch/riscv/include/arch/cpu.h
deleted file mode 100644
index 8c573ec..0000000
--- a/na/arch/riscv/include/arch/cpu.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-/*
- * CPU Control & Status Primitives (RISC-V 64)
- *
- * Provides interrupt enable/disable, CPU ID, timer, and halt.
- * All functions are static inline — zero call overhead.
- *
- * Precondition: tp register must be initialized with CPU ID
- * by entry.S before any of these functions are called.
- *
- * Reference: docs/specs/arch_abstraction.md §4.1
- */
-
-#include <lume/types.h>
-
-/* RISC-V sstatus register bit definitions */
-#define SSTATUS_SIE (1UL << 1) /* Supervisor Interrupt Enable */
-#define SSTATUS_SPIE (1UL << 5) /* Supervisor Previous Interrupt Enable */
-#define SSTATUS_SPP (1UL << 8) /* Supervisor Previous Privilege (0=U, 1=S) */
-
-/* RISC-V sie register bit definitions */
-#define SIE_SSIE (1UL << 1) /* Supervisor Software Interrupt Enable */
-#define SIE_STIE (1UL << 5) /* Supervisor Timer Interrupt Enable */
-#define SIE_SEIE (1UL << 9) /* Supervisor External Interrupt Enable */
-
-namespace arch::cpu {
-
-// Get current CPU ID (from tp register, set by entry.S)
-static inline uint64 id() {
- uint64 val;
- __asm__ volatile("mv %0, tp" : "=r"(val));
- return val;
-}
-
-// Enable interrupts (set sstatus.SIE = 1)
-static inline void intr_on() {
- __asm__ volatile("csrs sstatus, %0" :: "r"(SSTATUS_SIE));
-}
-
-// Disable interrupts (clear sstatus.SIE = 0)
-static inline void intr_off() {
- __asm__ volatile("csrc sstatus, %0" :: "r"(SSTATUS_SIE));
-}
-
-// Check if interrupts are currently enabled
-static inline bool intr_enabled() {
- uint64 sstatus;
- __asm__ volatile("csrr %0, sstatus" : "=r"(sstatus));
- return (sstatus & SSTATUS_SIE) != 0;
-}
-
-// Halt CPU until next interrupt (wfi instruction)
-static inline void halt_until_interrupt() {
- __asm__ volatile("wfi");
-}
-
-// Read hardware monotonic timer (rdtime instruction)
-// Returns ticks since boot; frequency from FDT timebase-frequency.
-static inline uint64 read_time() {
- uint64 val;
- __asm__ volatile("rdtime %0" : "=r"(val));
- return val;
-}
-
-// Enable timer interrupt in sie (sie.STIE = 1)
-static inline void timer_intr_on() {
- __asm__ volatile("csrs sie, %0" :: "r"(SIE_STIE));
-}
-
-// Disable timer interrupt in sie (sie.STIE = 0)
-static inline void timer_intr_off() {
- __asm__ volatile("csrc sie, %0" :: "r"(SIE_STIE));
-}
-
-// Enable software interrupt in sie (sie.SSIE = 1) — needed for IPI
-static inline void software_intr_on() {
- __asm__ volatile("csrs sie, %0" :: "r"(SIE_SSIE));
-}
-
-// Enable external interrupt in sie (sie.SEIE = 1) — needed for PLIC (UART, etc.)
-static inline void external_intr_on() {
- __asm__ volatile("csrs sie, %0" :: "r"(SIE_SEIE));
-}
-
-// Clear S-mode software interrupt pending bit (sip.SSIP = 0)
-// Must be called in the IPI handler to acknowledge the interrupt.
-static inline void clear_sip_ssip() {
- __asm__ volatile("csrc sip, %0" :: "r"(1UL << 1));
-}
-
-} // namespace arch::cpu
diff --git a/na/arch/riscv/include/arch/extable.h b/na/arch/riscv/include/arch/extable.h
deleted file mode 100644
index eb2daac..0000000
--- a/na/arch/riscv/include/arch/extable.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-#ifndef __ASSEMBLER__
-
-#include <lume/types.h>
-
-/*
- * Exception table entry.
- * insn: offset from this struct to the faulting instruction.
- * fixup: offset from this struct to the fixup code.
- *
- * Using relative offsets avoids absolute relocations and saves space.
- */
-struct ExceptionTableEntry {
- int32 insn;
- int32 fixup;
-};
-
-/* Search the exception table for a given PC. Returns fixup address, or 0 if not found. */
-uint64 search_extable(uint64 pc);
-
-/* Sorts the exception table at boot for binary search O(log N). */
-void extable_init();
-
-#endif /* __ASSEMBLER__ */
-
-/*
- * EXTABLE macro for assembly usage.
- * Appends an entry to the .extable section.
- */
-#ifdef __ASSEMBLER__
-
-#define EXTABLE(insn, fixup) \
- .pushsection .extable, "a"; \
- .balign 4; \
- .long insn - .; \
- .long fixup - .; \
- .popsection
-
-#else /* !__ASSEMBLER__ */
-
-/* Stringified macro for inline assembly */
-#define _ASM_EXTABLE(insn, fixup) \
- ".pushsection .extable, \"a\"\n" \
- ".balign 4\n" \
- ".long " #insn " - .\n" \
- ".long " #fixup " - .\n" \
- ".popsection\n"
-
-#define EXTABLE(insn, fixup) _ASM_EXTABLE(insn, fixup)
-
-#endif /* __ASSEMBLER__ */
diff --git a/na/arch/riscv/include/arch/fpstate.h b/na/arch/riscv/include/arch/fpstate.h
deleted file mode 100644
index 4b42a22..0000000
--- a/na/arch/riscv/include/arch/fpstate.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-/*
- * FPU State — Floating-Point Register Context
- *
- * Pre-reserved structure for RISC-V F/D extension floating-point state.
- * MUST be allocated in every TaskControlBlock so that future FPU
- * save/restore logic has a stable destination without restructuring TCB.
- *
- * RISC-V F/D extension state:
- * - 32 FP registers (f0-f31), each 64 bits for D extension
- * - fcsr (Floating-point Control and Status Register)
- *
- * sstatus.FS field management:
- * - FS=0 (Off): FPU disabled, any FP instruction traps
- * - FS=1 (Initial): FPU enabled, registers are initial state
- * - FS=2 (Clean): FPU enabled, registers not modified since last save
- * - FS=3 (Dirty): FPU enabled, registers modified (need save)
- *
- * Current status: Structure defined, save/restore NOT implemented.
- * When implemented, trap_dispatch and swtch.S will use lazy
- * save/restore based on sstatus.FS dirty tracking.
- *
- * Reference: RISC-V ISA Manual §3.1.6.5 (FS field)
- */
-
-#include <lume/types.h>
-
-namespace arch {
-
-struct FpState {
- uint64 f[32]; // f0-f31 (64-bit each for D extension)
- uint32 fcsr; // Floating-point CSR (frm + fflags)
- uint32 _pad; // Alignment padding
-};
-
-static_assert(sizeof(FpState) == 32 * 8 + 8, "FpState must be 264 bytes");
-
-/*
- * sstatus.FS field constants
- */
-inline constexpr uint64 kSstatusFS_Off = 0ULL << 13;
-inline constexpr uint64 kSstatusFS_Initial = 1ULL << 13;
-inline constexpr uint64 kSstatusFS_Clean = 2ULL << 13;
-inline constexpr uint64 kSstatusFS_Dirty = 3ULL << 13;
-inline constexpr uint64 kSstatusFS_Mask = 3ULL << 13;
-
-/*
- * Check if sstatus indicates FPU state is dirty (needs save).
- */
-inline bool fpu_state_dirty(uint64 sstatus) {
- return (sstatus & kSstatusFS_Mask) == kSstatusFS_Dirty;
-}
-
-/*
- * Check if FPU is enabled (FS != Off).
- */
-inline bool fpu_enabled(uint64 sstatus) {
- return (sstatus & kSstatusFS_Mask) != kSstatusFS_Off;
-}
-
-} // namespace arch
-
-/* Assembly routines for FPU register save/restore (fpu.S) */
-extern "C" void fpu_save(arch::FpState* state);
-extern "C" void fpu_restore(arch::FpState* state);
-
-namespace arch {
-
-/*
- * Read sstatus.FS field (current FPU state)
- */
-inline uint64 fpu_get_fs() {
- uint64 sstatus;
- __asm__ volatile("csrr %0, sstatus" : "=r"(sstatus));
- return sstatus & kSstatusFS_Mask;
-}
-
-/*
- * Set sstatus.FS field.
- * @fs: one of kSstatusFS_Off, kSstatusFS_Initial, kSstatusFS_Clean, kSstatusFS_Dirty
- */
-inline void fpu_set_fs(uint64 fs) {
- __asm__ volatile(
- "csrc sstatus, %0\n"
- "csrs sstatus, %1\n"
- :: "r"(kSstatusFS_Mask), "r"(fs)
- );
-}
-
-} // namespace arch
diff --git a/na/arch/riscv/include/arch/mmu.h b/na/arch/riscv/include/arch/mmu.h
deleted file mode 100644
index f4c9b26..0000000
--- a/na/arch/riscv/include/arch/mmu.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-/*
- * MMU Hardware Primitives (RISC-V SV39)
- *
- * Page table switching, TLB flushing, and fault address reading.
- * All functions are static inline — zero call overhead.
- *
- * Note on SMP: flush_tlb_page() only flushes the LOCAL CPU's TLB.
- * Cross-CPU TLB shootdown via IPI is not yet implemented.
- *
- * Reference: docs/specs/arch_abstraction.md §4.2
- */
-
-#include <lume/types.h>
-
-/* SATP register: mode field for SV39 */
-#define SATP_SV39 (8UL << 60)
-
-/* SATP PPN mask (bits 43:0) */
-#define SATP_PPN_MASK ((1UL << 44) - 1)
-
-namespace arch::mmu {
-
-// Read the faulting virtual address from stval (set by HW on page fault)
-static inline uint64 get_fault_address() {
- uint64 val;
- __asm__ volatile("csrr %0, stval" : "=r"(val));
- return val;
-}
-
-// Switch the top-level page table.
-// Takes a PHYSICAL ADDRESS (not PPN); internally shifts right by 12
-// and combines with SV39 mode bits before writing to satp.
-static inline void set_page_table(uint64 physical_pgdir_addr) {
- uint64 ppn = physical_pgdir_addr >> 12;
- uint64 satp_val = SATP_SV39 | ppn;
- __asm__ volatile("csrw satp, %0" :: "r"(satp_val));
- // Note: caller should call flush_tlb_all() after this
-}
-
-// Read the current page table physical address.
-// Extracts PPN from satp and converts back to physical address.
-static inline uint64 get_page_table() {
- uint64 satp_val;
- __asm__ volatile("csrr %0, satp" : "=r"(satp_val));
- return (satp_val & SATP_PPN_MASK) << 12;
-}
-
-// Read the raw satp CSR value (mode + PPN).
-// Used when the caller needs the exact register value (e.g. for TrapFrame metadata).
-static inline uint64 read_satp() {
- uint64 val;
- __asm__ volatile("csrr %0, satp" : "=r"(val));
- return val;
-}
-
-// Flush the entire TLB (all ASIDs, all addresses)
-static inline void flush_tlb_all() {
- __asm__ volatile("sfence.vma zero, zero" ::: "memory");
-}
-
-// Flush a single TLB entry for the given virtual address
-static inline void flush_tlb_page(uint64 vaddr) {
- __asm__ volatile("sfence.vma %0, zero" :: "r"(vaddr) : "memory");
-}
-
-// Flush the instruction cache.
-// Required after loading executable code into memory (e.g. ELF loading).
-// sfence.vma only flushes the TLB; fence.i is needed for the I-cache.
-static inline void flush_icache() {
- __asm__ volatile("fence.i" ::: "memory");
-}
-
-} // namespace arch::mmu
diff --git a/na/arch/riscv/include/arch/pmap.h b/na/arch/riscv/include/arch/pmap.h
deleted file mode 100644
index 0b43b9e..0000000
--- a/na/arch/riscv/include/arch/pmap.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-/*
- * pmap — SV39 page table interface (MD layer)
- *
- * Namespace functions, zero runtime overhead.
- * Implementation: arch/riscv/mm/pmap.cc
- *
- * Reference: docs/specs/vmm.md §3.2
- */
-
-#include <lume/types.h>
-
-namespace pmap {
-
-/* PTE permission bits */
-inline constexpr uint64 PTE_V = 1ULL << 0;
-inline constexpr uint64 PTE_R = 1ULL << 1;
-inline constexpr uint64 PTE_W = 1ULL << 2;
-inline constexpr uint64 PTE_X = 1ULL << 3;
-inline constexpr uint64 PTE_U = 1ULL << 4;
-inline constexpr uint64 PTE_G = 1ULL << 5;
-inline constexpr uint64 PTE_A = 1ULL << 6;
-inline constexpr uint64 PTE_D = 1ULL << 7;
-inline constexpr uint64 PTE_COW = 1ULL << 8; /* Custom RSW bit for Copy-On-Write */
-
-uint64 create();
-void destroy(uint64 root_pa);
-int map(uint64 root_pa, uint64 va, uint64 pa, uint64 perm);
-int map_2mb(uint64 root_pa, uint64 va, uint64 pa, uint64 perm);
-void unmap(uint64 root_pa, uint64 va);
-int protect(uint64 root_pa, uint64 va, uint64 perm);
-int protect_range(uint64 root_pa, uint64 start, uint64 end, uint64 perm);
-bool lookup(uint64 root_pa, uint64 va, uint64* pa_out);
-uint64 lookup_pte(uint64 root_pa, uint64 va);
-bool is_cow(uint64 root_pa, uint64 va);
-int make_cow(uint64 root_pa, uint64 va);
-void activate(uint64 root_pa);
-
-/*
- * Translate MI-layer VM_* permission flags to hardware PTE bits.
- * Called by vma.cc when faulting in a page.
- */
-uint64 vm_perm_to_pte(uint64 vm_perm);
-
-} // namespace pmap
diff --git a/na/arch/riscv/include/arch/random.h b/na/arch/riscv/include/arch/random.h
deleted file mode 100644
index 8c8c051..0000000
--- a/na/arch/riscv/include/arch/random.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-#include <lume/types.h>
-
-namespace arch {
-
-/*
- * Get a random 64-bit value from the hardware TRNG.
- * Returns true if supported and successful, false otherwise.
- */
-bool get_hw_random(uint64& value);
-
-/*
- * Get the current high-resolution hardware cycle counter.
- * Used as an entropy fallback (Jitter/Timer).
- */
-inline uint64 get_cycles()
-{
- uint64 cycles;
- __asm__ volatile("rdcycle %0" : "=r"(cycles));
- return cycles;
-}
-
-} // namespace arch
diff --git a/na/arch/riscv/include/arch/sbi.h b/na/arch/riscv/include/arch/sbi.h
deleted file mode 100644
index 80a6d7c..0000000
--- a/na/arch/riscv/include/arch/sbi.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-/*
- * sbi.h — RISC-V Supervisor Binary Interface (SBI) wrappers
- *
- * Provides inline ecall wrappers for SBI calls from S-mode.
- * Uses the SBI v1.0+ extension-based calling convention.
- *
- * Reference: RISC-V SBI Specification v2.0
- */
-
-#include <lume/types.h>
-
-namespace arch::sbi {
-
-struct sbiret {
- long error;
- long value;
-};
-
-/* SBI error codes */
-inline constexpr long SBI_SUCCESS = 0;
-inline constexpr long SBI_ERR_NOT_SUPPORTED = -2;
-
-/* Extension IDs */
-inline constexpr int SBI_EXT_TIME = 0x54494D45; /* "TIME" */
-inline constexpr int SBI_EXT_IPI = 0x735049; /* "sPI" */
-inline constexpr int SBI_EXT_RFENCE = 0x52464E43; /* "RFNC" */
-inline constexpr int SBI_EXT_HSM = 0x48534D; /* "HSM" */
-
-static inline sbiret sbi_ecall(int ext, int fid, uint64 arg0 = 0,
- uint64 arg1 = 0, uint64 arg2 = 0,
- uint64 arg3 = 0, uint64 arg4 = 0,
- uint64 arg5 = 0) {
- sbiret ret;
- register uint64 a0 asm("a0") = arg0;
- register uint64 a1 asm("a1") = arg1;
- register uint64 a2 asm("a2") = arg2;
- register uint64 a3 asm("a3") = arg3;
- register uint64 a4 asm("a4") = arg4;
- register uint64 a5 asm("a5") = arg5;
- register uint64 a6 asm("a6") = fid;
- register uint64 a7 asm("a7") = ext;
- __asm__ volatile("ecall"
- : "+r"(a0), "+r"(a1)
- : "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6), "r"(a7)
- : "memory");
- ret.error = static_cast<long>(a0);
- ret.value = static_cast<long>(a1);
- return ret;
-}
-
-/* ---- Timer Extension (EID 0x54494D45) ---- */
-
-static inline void set_timer(uint64 stime_value) {
- sbi_ecall(SBI_EXT_TIME, 0, stime_value);
-}
-
-/* ---- IPI Extension (EID 0x735049) ---- */
-
-/*
- * sbi_send_ipi — Send S-mode software interrupt to target harts
- *
- * @hart_mask: bitmask of target harts (relative to hart_mask_base)
- * @hart_mask_base: base hart ID for the mask (0 = harts 0-63)
- */
-static inline sbiret sbi_send_ipi(uint64 hart_mask,
- uint64 hart_mask_base = 0) {
- return sbi_ecall(SBI_EXT_IPI, 0, hart_mask, hart_mask_base);
-}
-
-/* ---- Remote Fence Extension (EID 0x52464E43) ---- */
-
-/*
- * sbi_remote_sfence_vma — Execute SFENCE.VMA on target harts
- *
- * @hart_mask/base: target harts
- * @start_addr: start of VA range to invalidate
- * @size: size of range (use ~0UL for full flush)
- */
-static inline sbiret sbi_remote_sfence_vma(uint64 hart_mask,
- uint64 hart_mask_base,
- uint64 start_addr,
- uint64 size) {
- return sbi_ecall(SBI_EXT_RFENCE, 1,
- hart_mask, hart_mask_base,
- start_addr, size);
-}
-
-/* ---- HSM Extension (EID 0x48534D) ---- */
-
-/*
- * sbi_hart_start — Start (wake) a hart that is in STOPPED state
- *
- * @hartid: target hart ID to start
- * @start_addr: PHYSICAL address where the hart should begin execution
- * @opaque: passed in a1 register to the hart (e.g. FDT pointer)
- *
- * OpenSBI v1.0+ parks non-boot harts; they must be explicitly started.
- */
-static inline sbiret sbi_hart_start(uint64 hartid,
- uint64 start_addr,
- uint64 opaque) {
- return sbi_ecall(SBI_EXT_HSM, 0, hartid, start_addr, opaque);
-}
-
-} // namespace arch::sbi
-
diff --git a/na/arch/riscv/include/arch/tlb.h b/na/arch/riscv/include/arch/tlb.h
deleted file mode 100644
index 46c6b97..0000000
--- a/na/arch/riscv/include/arch/tlb.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-#include <lume/types.h>
-
-namespace arch::tlb {
-
-/*
- * Perform a cross-CPU TLB flush (shootdown).
- *
- * @param cpu_mask: Bitmask of CPUs to target.
- * @param start: Start virtual address, or 0 for full address space.
- * @param size: Size in bytes, or ~0ULL for full address space.
- */
-void flush_remote(uint64 cpu_mask, uint64 start, uint64 size);
-
-} // namespace arch::tlb
diff --git a/na/arch/riscv/include/arch/trap.h b/na/arch/riscv/include/arch/trap.h
deleted file mode 100644
index 8e55250..0000000
--- a/na/arch/riscv/include/arch/trap.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-/*
- * Trap Vector Control Primitives (RISC-V 64)
- *
- * Set/read the S-mode trap vector (stvec), trap cause (scause),
- * and trap value (stval) registers.
- *
- * Reference: docs/specs/arch_abstraction.md §4.3
- */
-
-#include <lume/types.h>
-
-/* scause interrupt bit (bit 63): 1 = interrupt, 0 = exception */
-#define SCAUSE_INTERRUPT (1UL << 63)
-
-/* Exception cause codes (scause with bit 63 = 0) */
-#define EXC_INST_MISALIGNED 0
-#define EXC_INST_ACCESS_FAULT 1
-#define EXC_ILLEGAL_INST 2
-#define EXC_BREAKPOINT 3
-#define EXC_LOAD_MISALIGNED 4
-#define EXC_LOAD_ACCESS_FAULT 5
-#define EXC_STORE_MISALIGNED 6
-#define EXC_STORE_ACCESS_FAULT 7
-#define EXC_ECALL_FROM_U 8
-#define EXC_ECALL_FROM_S 9
-#define EXC_INST_PAGE_FAULT 12
-#define EXC_LOAD_PAGE_FAULT 13
-#define EXC_STORE_PAGE_FAULT 15
-
-/* Interrupt cause codes (scause with bit 63 = 1, lower bits) */
-#define IRQ_S_SOFTWARE 1
-#define IRQ_S_TIMER 5
-#define IRQ_S_EXTERNAL 9
-
-namespace arch::trap {
-
-// Set S-mode trap vector base address (writes stvec).
-// Mode: Direct (all traps go to handler_addr).
-static inline void set_vector(uint64 handler_addr) {
- // Lowest 2 bits of stvec = mode. 0 = Direct.
- __asm__ volatile("csrw stvec, %0" :: "r"(handler_addr));
-}
-
-// Read current trap vector base address
-static inline uint64 get_vector() {
- uint64 val;
- __asm__ volatile("csrr %0, stvec" : "=r"(val));
- return val;
-}
-
-// Read trap cause register (scause)
-// Bit 63: 1=interrupt, 0=exception. Lower bits: cause code.
-static inline uint64 get_cause() {
- uint64 val;
- __asm__ volatile("csrr %0, scause" : "=r"(val));
- return val;
-}
-
-// Read trap value register (stval)
-// Contains faulting address (page faults) or faulting instruction.
-static inline uint64 get_value() {
- uint64 val;
- __asm__ volatile("csrr %0, stval" : "=r"(val));
- return val;
-}
-
-// Check if a scause value represents an interrupt (vs exception)
-static inline bool is_interrupt(uint64 cause) {
- return (cause & SCAUSE_INTERRUPT) != 0;
-}
-
-// Extract the cause code (strip the interrupt bit)
-static inline uint64 cause_code(uint64 cause) {
- return cause & ~SCAUSE_INTERRUPT;
-}
-
-// Enable Supervisor User Memory access (set SUM bit in sstatus).
-// When SUM=1, S-mode can read/write pages marked PTE_U.
-// This is needed for syscall handlers to access user-space buffers.
-static inline void enable_sum() {
- __asm__ volatile("csrs sstatus, %0" :: "r"(1UL << 18));
-}
-
-// Disable Supervisor User Memory access (clear SUM bit in sstatus).
-static inline void disable_sum() {
- __asm__ volatile("csrc sstatus, %0" :: "r"(1UL << 18));
-}
-
-} // namespace arch::trap
diff --git a/na/arch/riscv/include/arch/trapframe.h b/na/arch/riscv/include/arch/trapframe.h
deleted file mode 100644
index b198646..0000000
--- a/na/arch/riscv/include/arch/trapframe.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#pragma once
-
-/*
- * Trap Frame Structure (RISC-V 64)
- *
- * Saved/restored by the assembly trap_vector on every interrupt,
- * exception, or system call. Contains the full CPU snapshot needed
- * to resume execution after trap handling.
- *
- * Layout must match the assembly offsets in trap_vector.S exactly.
- * Reference: docs/specs/arch_abstraction.md §3.2
- */
-
-/*
- * TrapFrame field offsets for use in assembly.
- * These must be kept in sync with the struct layout below.
- * Placed before any C++ code so assembly can #include this file.
- */
-#define TF_KERNEL_SATP 0
-#define TF_KERNEL_SP 8
-#define TF_KERNEL_TRAP 16
-#define TF_KERNEL_CPUID 24
-#define TF_EPC 32
-#define TF_SSTATUS 40
-#define TF_RA 48
-#define TF_SP 56
-#define TF_GP 64
-#define TF_TP 72
-#define TF_T0 80
-#define TF_T1 88
-#define TF_T2 96
-#define TF_T3 104
-#define TF_T4 112
-#define TF_T5 120
-#define TF_T6 128
-#define TF_S0 136
-#define TF_S1 144
-#define TF_S2 152
-#define TF_S3 160
-#define TF_S4 168
-#define TF_S5 176
-#define TF_S6 184
-#define TF_S7 192
-#define TF_S8 200
-#define TF_S9 208
-#define TF_S10 216
-#define TF_S11 224
-#define TF_A0 232
-#define TF_A1 240
-#define TF_A2 248
-#define TF_A3 256
-#define TF_A4 264
-#define TF_A5 272
-#define TF_A6 280
-#define TF_A7 288
-#define TF_SIZE 296
-
-#ifndef __ASSEMBLER__
-
-#include <lume/types.h>
-#include <arch/cpu.h>
-
-namespace arch {
-
-struct TrapFrame {
- /* ---- Kernel metadata (offset 0-39) ---- */
- uint64 kernel_satp; // 0: Kernel page table (written to satp on trap entry)
- uint64 kernel_sp; // 8: Top of kernel stack for this task
- uint64 kernel_trap; // 16: Address of C++ trap_handler function
- uint64 kernel_cpu_id; // 24: CPU ID (loaded into tp on trap entry)
- uint64 epc; // 32: Interrupted instruction address (sepc)
-
- /* ---- CSR backup (offset 40-47) ---- */
- uint64 sstatus; // 40: Privilege status (SPP, SPIE bits)
-
- /* ---- General-purpose registers (offset 48-295) ---- */
- uint64 ra; // 48: x1 - Return address
- uint64 sp; // 56: x2 - User stack pointer
- uint64 gp; // 64: x3 - Global pointer
- uint64 tp; // 72: x4 - Thread pointer
- uint64 t[7]; // 80: x5-x7, x28-x31 (t0-t6, caller-saved temporaries)
- uint64 s[12]; // 136: x8-x9, x18-x27 (s0-s11, callee-saved)
- uint64 a[8]; // 232: x10-x17 (a0-a7, arguments / syscall params)
-};
-
-static_assert(sizeof(TrapFrame) == 296, "TrapFrame size mismatch with assembly offsets");
-
-} // namespace arch
-
-/* Forward declaration — defined in trap_md.cc.
- * Must be after TrapFrame definition. */
-extern "C" [[noreturn]] void trap_dispatch(arch::TrapFrame*);
-
-namespace arch {
-
-/*
- * trapframe_init_user — prepare a TrapFrame for returning to user mode.
- *
- * Sets arch-specific sstatus:
- * SPP = 0 (return to U-mode on sret)
- * SPIE = 1 (enable interrupts in U-mode)
- * FS = Initial (allow FP instructions)
- *
- * Called from MI exec.cc instead of setting sstatus directly.
- */
-static inline void trapframe_init_user(TrapFrame* tf, uint64 entry, uint64 sp)
-{
- /* Clear all registers */
- for (auto& t : tf->t) { t = 0; }
- for (auto& s : tf->s) { s = 0; }
- for (auto& a : tf->a) { a = 0; }
- tf->ra = 0;
- tf->gp = 0;
- tf->tp = 0;
-
- tf->epc = entry;
- tf->sp = sp;
-
- /* sstatus: SPP=0 (U-mode), SPIE=1 (interrupts), FS=Initial (FP ok) */
- constexpr uint64 kSPIE = (1ULL << 5);
- constexpr uint64 kFS_Initial = (1ULL << 13);
- tf->sstatus = kSPIE | kFS_Initial;
-
- /* Kernel metadata used by trap_vector.S on every trap from U-mode.
- * These are RISC-V specific — trap_vector reads them from the
- * TrapFrame to switch to kernel context. */
- uint64 satp;
- asm volatile("csrr %0, satp" : "=r"(satp));
- tf->kernel_satp = satp;
- tf->kernel_sp = reinterpret_cast<uint64>(tf);
- tf->kernel_trap = reinterpret_cast<uint64>(&trap_dispatch);
- tf->kernel_cpu_id = cpu::id();
-}
-
-} // namespace arch
-
-#endif /* __ASSEMBLER__ */
diff --git a/na/arch/riscv/include/asm/csr.h b/na/arch/riscv/include/asm/csr.h
deleted file mode 100644
index 42f1eb4..0000000
--- a/na/arch/riscv/include/asm/csr.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#ifndef _ASM_RISCV_CSR_H
-#define _ASM_RISCV_CSR_H
-
-/*
- * RISC-V CSR (Control & Status Register) definitions used by the early
- * boot / MMU-switch path.
- *
- * LumeOS-native subset of Linux arch/riscv/include/asm/csr.h. Only the
- * symbols head.S and mm/init.cc actually reference are defined — adding
- * the rest is straightforward when new code needs them, and skipping the
- * Linux ALTERNATIVE / vendor-extension machinery keeps the cascade flat.
- */
-
-/* SATP (Supervisor Address Translation and Protection) layout — RV64 */
-#define SATP_PPN_MASK 0x00000FFFFFFFFFFFUL /* bits [43:0] = root PPN */
-#define SATP_ASID_SHIFT 44
-#define SATP_MODE_SHIFT 60
-
-/* SATP MODE encodings (RV64) */
-#define SATP_MODE_BARE (0UL << SATP_MODE_SHIFT)
-#define SATP_MODE_SV39 (8UL << SATP_MODE_SHIFT)
-#define SATP_MODE_SV48 (9UL << SATP_MODE_SHIFT)
-
-/* Compose a SATP value from a page-table physical address.
- * Result: MODE | (root_ppn) where root_ppn = pgd_pa >> PAGE_SHIFT. */
-#define MAKE_SATP(mode, pgd_pa) ((mode) | (((pgd_pa) >> 12) & SATP_PPN_MASK))
-
-/* SSTATUS bits we touch at boot — disable FP / vector at entry so that an
- * accidental FP / V instruction in early code traps cleanly rather than
- * silently using dirty state from before reset. */
-#define SR_FS_OFF (0UL << 13)
-#define SR_VS_OFF (0UL << 9)
-
-#endif /* _ASM_RISCV_CSR_H */
diff --git a/na/arch/riscv/include/asm/page.h b/na/arch/riscv/include/asm/page.h
deleted file mode 100644
index 7b9f155..0000000
--- a/na/arch/riscv/include/asm/page.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#ifndef _ASM_RISCV_PAGE_H
-#define _ASM_RISCV_PAGE_H
-
-/*
- * RISC-V page / virtual-memory layout constants.
- *
- * Mirrors the subset of Linux arch/riscv/include/asm/page.h that LumeOS's
- * early boot path needs:
- * - PAGE_SIZE / PAGE_SHIFT / PAGE_MASK
- * - PAGE_OFFSET (start of the higher-half direct map)
- * - KERNEL_LINK_ADDR (link-time VA of _start)
- * - SV39 PTE flag bits
- * - PTRS_PER_PGD (512 for SV39)
- *
- * Values match Linux RISC-V SV39 defaults so that struct kernel_mapping
- * (filled by setup_vm in arch/riscv/mm/init.cc) carries the same numeric
- * relations Linux's mm/init.c maintains.
- */
-
-#define PAGE_SHIFT 12
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE - 1))
-
-/* Higher-half base of the kernel direct map. Bottom of the SV39 supervisor
- * address space minus the unmapped guard region. Identical to Linux's
- * CONFIG_PAGE_OFFSET default on RV64. */
-#define PAGE_OFFSET 0xFFFFFFC000000000UL
-
-/* Where _start was linked. OpenSBI hands control to PHYS_BASE; the kernel
- * runs at KERNEL_LINK_ADDR after relocate_enable_mmu jumps to higher-half. */
-#define PHYS_BASE 0x80200000UL
-#define KERNEL_LINK_ADDR 0xFFFFFFC080200000UL
-
-/* SATP mode field — SV39 = 8, shifted to bits [63:60]. */
-#define SATP_MODE_SV39 (8UL << 60)
-
-#define PTRS_PER_PGD 512
-
-/* 1 GB superpage size — entry.S used to build the early page table with
- * these; setup_vm in arch/riscv/mm/init.cc now does the same. */
-#define PGDIR_SHIFT 30
-#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK (~(PGDIR_SIZE - 1))
-
-/* SV39 PTE flag bits (one byte). */
-#define _PAGE_PRESENT (1UL << 0) /* aka VALID — historic Linux name */
-#define _PAGE_READ (1UL << 1)
-#define _PAGE_WRITE (1UL << 2)
-#define _PAGE_EXEC (1UL << 3)
-#define _PAGE_USER (1UL << 4)
-#define _PAGE_GLOBAL (1UL << 5)
-#define _PAGE_ACCESSED (1UL << 6)
-#define _PAGE_DIRTY (1UL << 7)
-
-#define PAGE_KERNEL_EXEC \
- (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC | \
- _PAGE_ACCESSED | _PAGE_DIRTY)
-
-#endif /* _ASM_RISCV_PAGE_H */
diff --git a/na/arch/riscv/include/asm/pgtable.h b/na/arch/riscv/include/asm/pgtable.h
deleted file mode 100644
index 28fc4c5..0000000
--- a/na/arch/riscv/include/asm/pgtable.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#ifndef _ASM_RISCV_PGTABLE_H
-#define _ASM_RISCV_PGTABLE_H
-
-/*
- * Early page-table construction API used by arch/riscv/mm/init.cc::setup_vm.
- *
- * Mirrors the create_pgd_mapping interface from Linux's
- * arch/riscv/mm/init.c — same name, same semantics:
- *
- * create_pgd_mapping(pgdir, va, pa, sz, prot)
- *
- * pgdir : root of the page table to populate
- * va : virtual address to map
- * pa : physical address to map to
- * sz : mapping size — must be a supported leaf size (PAGE_SIZE,
- * 2 MiB megapage, or 1 GiB gigapage)
- * prot : PTE flag bits (PAGE_KERNEL_EXEC etc., from <asm/page.h>)
- *
- * The boot-time variant in this file only supports gigapage (1 GiB)
- * mappings — that is all setup_vm needs for the early_pg_dir / trampoline_pg_dir
- * built before the slab allocator exists. Finer-grained mappings come
- * later via vmm_init().
- */
-
-#include <lume/types.h>
-#include <asm/page.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct { unsigned long pgd; } pgd_t;
-
-/* Linker-provided early page-table storage (defined in lumeos.lds.S
- * ARCH_BSS_EXTRA, lives in .bss so it's zero-initialized). Allocating
- * them in the linker script — not in C — mirrors Linux and keeps the
- * symbols visible from head.S without a forward C decl mismatch. */
-extern pgd_t early_pg_dir[PTRS_PER_PGD];
-extern pgd_t trampoline_pg_dir[PTRS_PER_PGD];
-extern pgd_t fixmap_pg_dir[PTRS_PER_PGD];
-
-/* Install a single PGD entry mapping `va` → `pa` with size `sz` and PTE
- * flags `prot`. Only sz == PGDIR_SIZE (1 GiB) is supported in this early
- * variant — vmm_init() takes over with create_pgd_mapping_pmd later. */
-void create_pgd_mapping(pgd_t *pgdir, unsigned long va, unsigned long pa,
- unsigned long sz, unsigned long prot);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ASM_RISCV_PGTABLE_H */
diff --git a/na/arch/riscv/include/asm/sections.h b/na/arch/riscv/include/asm/sections.h
deleted file mode 100644
index 454d9de..0000000
--- a/na/arch/riscv/include/asm/sections.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-#ifndef _ASM_RISCV_SECTIONS_H
-#define _ASM_RISCV_SECTIONS_H
-
-/*
- * Linker-emitted symbols that bracket each section of the kernel image.
- *
- * The lumeos.lds.S linker script defines these as the start / end
- * addresses of contiguous regions. Code that walks a section
- * (relocate_kernel walks .rela.dyn, the C++ ctor loop walks
- * .init_array, the VMM mapping code walks .text vs .rodata, ...)
- * imports the pair via this header.
- *
- * Mirrors Linux arch/riscv/include/asm/sections.h / asm-generic/sections.h.
- * Each name and pair is identical to Linux so that direct ports of mm/init.c
- * relocate_kernel logic compile unchanged against LumeOS.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern char _start[];
-extern char _end[];
-
-extern char _stext[];
-extern char _etext[];
-extern char _srodata[];
-extern char _erodata[];
-extern char _sdata[];
-extern char _edata[];
-extern char _sbss[];
-extern char _ebss[];
-
-extern char __init_array_start[];
-extern char __init_array_end[];
-
-/* .rela.dyn — array of Elf64_Rela entries emitted by the linker under
- * `-shared -Bsymbolic`. relocate_kernel walks this range and patches
- * each R_RISCV_RELATIVE slot. */
-extern char __rela_dyn_start[];
-extern char __rela_dyn_end[];
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ASM_RISCV_SECTIONS_H */