diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:24:56 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:24:56 +0800 |
| commit | 1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (patch) | |
| tree | 0f5e01cd7c7a05abb6b1c7472d7f00f49caf02cc /na/arch/riscv/include | |
| parent | 63dc025705f6533b91fb1a7d26e6ed864efd9900 (diff) | |
| download | lume-1767d390fbf3d0c65389de46caf0b6d43ef3b6ad.tar.gz lume-1767d390fbf3d0c65389de46caf0b6d43ef3b6ad.tar.xz | |
feat: establish bootable new architecture checkpoint
Replace the compressed boot path with a relocatable higher-half RISC-V entry, expand memory and SMP support, and add the driver, TTY, VFS, exec, signal, syscall, initramfs, and self-test infrastructure needed for a bootable kernel checkpoint.
Diffstat (limited to 'na/arch/riscv/include')
| -rw-r--r-- | na/arch/riscv/include/arch/config.h | 5 | ||||
| -rw-r--r-- | na/arch/riscv/include/arch/cpu.h | 16 | ||||
| -rw-r--r-- | na/arch/riscv/include/arch/fpstate.h | 94 | ||||
| -rw-r--r-- | na/arch/riscv/include/arch/mmu.h | 15 | ||||
| -rw-r--r-- | na/arch/riscv/include/arch/pmap.h | 1 | ||||
| -rw-r--r-- | na/arch/riscv/include/arch/sbi.h | 80 | ||||
| -rw-r--r-- | na/arch/riscv/include/arch/tlb.h | 19 | ||||
| -rw-r--r-- | na/arch/riscv/include/arch/trap.h | 12 | ||||
| -rw-r--r-- | na/arch/riscv/include/arch/trapframe.h | 48 | ||||
| -rw-r--r-- | na/arch/riscv/include/asm/csr.h | 37 | ||||
| -rw-r--r-- | na/arch/riscv/include/asm/page.h | 62 | ||||
| -rw-r--r-- | na/arch/riscv/include/asm/pgtable.h | 55 | ||||
| -rw-r--r-- | na/arch/riscv/include/asm/sections.h | 50 |
13 files changed, 490 insertions, 4 deletions
diff --git a/na/arch/riscv/include/arch/config.h b/na/arch/riscv/include/arch/config.h index 0949c41..8ae0502 100644 --- a/na/arch/riscv/include/arch/config.h +++ b/na/arch/riscv/include/arch/config.h @@ -35,6 +35,11 @@ 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 * diff --git a/na/arch/riscv/include/arch/cpu.h b/na/arch/riscv/include/arch/cpu.h index d16cf2d..8c573ec 100644 --- a/na/arch/riscv/include/arch/cpu.h +++ b/na/arch/riscv/include/arch/cpu.h @@ -76,4 +76,20 @@ 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/fpstate.h b/na/arch/riscv/include/arch/fpstate.h new file mode 100644 index 0000000..4b42a22 --- /dev/null +++ b/na/arch/riscv/include/arch/fpstate.h @@ -0,0 +1,94 @@ +/* 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 index a0ee1ed..f4c9b26 100644 --- a/na/arch/riscv/include/arch/mmu.h +++ b/na/arch/riscv/include/arch/mmu.h @@ -50,6 +50,14 @@ static inline uint64 get_page_table() { 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"); @@ -60,4 +68,11 @@ 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 index a99825a..0b43b9e 100644 --- a/na/arch/riscv/include/arch/pmap.h +++ b/na/arch/riscv/include/arch/pmap.h @@ -35,6 +35,7 @@ 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); diff --git a/na/arch/riscv/include/arch/sbi.h b/na/arch/riscv/include/arch/sbi.h index b65c37e..80a6d7c 100644 --- a/na/arch/riscv/include/arch/sbi.h +++ b/na/arch/riscv/include/arch/sbi.h @@ -3,6 +3,15 @@ #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 { @@ -12,7 +21,20 @@ struct sbiret { long value; }; -static inline sbiret sbi_ecall(int ext, int fid, uint64 arg0, uint64 arg1, uint64 arg2, uint64 arg3, uint64 arg4, uint64 arg5) { +/* 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; @@ -23,7 +45,7 @@ static inline sbiret sbi_ecall(int ext, int fid, uint64 arg0, uint64 arg1, uint6 register uint64 a6 asm("a6") = fid; register uint64 a7 asm("a7") = ext; __asm__ volatile("ecall" - : "+r"(a0), "=r"(a1) + : "+r"(a0), "+r"(a1) : "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6), "r"(a7) : "memory"); ret.error = static_cast<long>(a0); @@ -31,9 +53,59 @@ static inline sbiret sbi_ecall(int ext, int fid, uint64 arg0, uint64 arg1, uint6 return ret; } +/* ---- Timer Extension (EID 0x54494D45) ---- */ + static inline void set_timer(uint64 stime_value) { - // Standard SBI TIME Extension (EID 0x54494D45) - sbi_ecall(0x54494D45, 0, stime_value, 0, 0, 0, 0, 0); + 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 new file mode 100644 index 0000000..46c6b97 --- /dev/null +++ b/na/arch/riscv/include/arch/tlb.h @@ -0,0 +1,19 @@ +/* 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 index c99d8cb..8e55250 100644 --- a/na/arch/riscv/include/arch/trap.h +++ b/na/arch/riscv/include/arch/trap.h @@ -79,4 +79,16 @@ 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 index de49e9c..b198646 100644 --- a/na/arch/riscv/include/arch/trapframe.h +++ b/na/arch/riscv/include/arch/trapframe.h @@ -61,6 +61,7 @@ #ifndef __ASSEMBLER__ #include <lume/types.h> +#include <arch/cpu.h> namespace arch { @@ -89,4 +90,51 @@ static_assert(sizeof(TrapFrame) == 296, "TrapFrame size mismatch with assembly o } // 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 new file mode 100644 index 0000000..42f1eb4 --- /dev/null +++ b/na/arch/riscv/include/asm/csr.h @@ -0,0 +1,37 @@ +/* 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 new file mode 100644 index 0000000..7b9f155 --- /dev/null +++ b/na/arch/riscv/include/asm/page.h @@ -0,0 +1,62 @@ +/* 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 new file mode 100644 index 0000000..28fc4c5 --- /dev/null +++ b/na/arch/riscv/include/asm/pgtable.h @@ -0,0 +1,55 @@ +/* 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 new file mode 100644 index 0000000..454d9de --- /dev/null +++ b/na/arch/riscv/include/asm/sections.h @@ -0,0 +1,50 @@ +/* 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 */ |
