refactor(adapter-riscv): restructure into hw/, mmu/, trap/ modules with board constants

Add Priority::DEFAULT and TimeSlice::DEFAULT to types crate.
All QEMU virt addresses consolidated in board.rs.
Structure mirrors future adapter-arm/ layout.
This commit is contained in:
2026-10-18 02:05:57 +02:00
parent 66a730b2fe
commit d327794d33
13 changed files with 100 additions and 109 deletions

View File

@@ -0,0 +1,19 @@
use super::page_table::{PageTable, PAGE_SIZE};
// Boot-time bump allocator for page tables.
// Only used during init before the scheduler starts.
static mut NEXT_FREE: usize = 0;
pub fn init_allocator(start: usize) {
unsafe { NEXT_FREE = start; }
}
pub fn alloc_page_table() -> &'static mut PageTable {
unsafe {
let addr = NEXT_FREE;
NEXT_FREE += PAGE_SIZE;
let table = &mut *(addr as *mut PageTable);
table.zero();
table
}
}

View File

@@ -0,0 +1,5 @@
pub mod allocator;
pub mod page_table;
pub use allocator::init_allocator;
pub use page_table::{activate, init_kernel_page_table, create_user_page_table, PageTable, PAGE_SIZE};

View File

@@ -0,0 +1,149 @@
use crate::board;
use super::allocator::alloc_page_table;
pub const PAGE_SIZE: usize = 4096;
const PTE_V: u64 = 1 << 0;
const PTE_R: u64 = 1 << 1;
const PTE_W: u64 = 1 << 2;
const PTE_X: u64 = 1 << 3;
const PTE_U: u64 = 1 << 4;
const PTE_G: u64 = 1 << 5;
const PTE_A: u64 = 1 << 6;
const PTE_D: u64 = 1 << 7;
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct PageTableEntry(u64);
impl PageTableEntry {
pub fn empty() -> Self {
Self(0)
}
pub fn new_leaf(ppn: u64, read: bool, write: bool, exec: bool, user: bool, global: bool) -> Self {
let mut flags = PTE_V | PTE_A | PTE_D;
if read { flags |= PTE_R; }
if write { flags |= PTE_W; }
if exec { flags |= PTE_X; }
if user { flags |= PTE_U; }
if global { flags |= PTE_G; }
Self(flags | (ppn << 10))
}
pub fn new_branch(ppn: u64) -> Self {
Self(PTE_V | (ppn << 10))
}
pub fn is_valid(&self) -> bool {
self.0 & PTE_V != 0
}
pub fn ppn(&self) -> u64 {
(self.0 >> 10) & 0xFFF_FFFF_FFFF
}
}
#[repr(C, align(4096))]
pub struct PageTable {
pub entries: [PageTableEntry; 512],
}
impl PageTable {
pub fn zero(&mut self) {
for entry in &mut self.entries {
*entry = PageTableEntry::empty();
}
}
}
fn vpn(va: usize, level: usize) -> usize {
(va >> (12 + 9 * level)) & 0x1FF
}
fn map_page(root: &mut PageTable, va: usize, pa: usize, read: bool, write: bool, exec: bool, user: bool, global: bool) {
let vpn2 = vpn(va, 2);
let vpn1 = vpn(va, 1);
let vpn0 = vpn(va, 0);
if !root.entries[vpn2].is_valid() {
let table = alloc_page_table();
let ppn = (table as *const PageTable as u64) >> 12;
root.entries[vpn2] = PageTableEntry::new_branch(ppn);
}
let l1_addr = (root.entries[vpn2].ppn() << 12) as *mut PageTable;
let l1 = unsafe { &mut *l1_addr };
if !l1.entries[vpn1].is_valid() {
let table = alloc_page_table();
let ppn = (table as *const PageTable as u64) >> 12;
l1.entries[vpn1] = PageTableEntry::new_branch(ppn);
}
let l0_addr = (l1.entries[vpn1].ppn() << 12) as *mut PageTable;
let l0 = unsafe { &mut *l0_addr };
let ppn = (pa as u64) >> 12;
l0.entries[vpn0] = PageTableEntry::new_leaf(ppn, read, write, exec, user, global);
}
fn map_range(root: &mut PageTable, va_start: usize, pa_start: usize, pages: usize, read: bool, write: bool, exec: bool, user: bool, global: bool) {
for i in 0..pages {
let offset = i * PAGE_SIZE;
map_page(root, va_start + offset, pa_start + offset, read, write, exec, user, global);
}
}
pub fn init_kernel_page_table() -> &'static mut PageTable {
let root = alloc_page_table();
let ram_pages = board::RAM_SIZE / PAGE_SIZE;
map_range(root, board::RAM_BASE, board::RAM_BASE, ram_pages, true, true, true, false, true);
map_range(root, board::UART_BASE, board::UART_BASE, 1, true, true, false, false, true);
let plic_pages = 0x400000 / PAGE_SIZE;
map_range(root, board::PLIC_BASE, board::PLIC_BASE, plic_pages, true, true, false, false, true);
let clint_pages = 0x10000 / PAGE_SIZE;
map_range(root, board::CLINT_BASE, board::CLINT_BASE, clint_pages, true, true, false, false, true);
root
}
pub fn activate(root: &PageTable) {
let ppn = (root as *const PageTable as u64) >> 12;
let satp = (8u64 << 60) | ppn;
unsafe {
core::arch::asm!(
"csrw satp, {0}",
"sfence.vma",
in(reg) satp,
);
}
}
pub fn create_user_page_table(
kernel_root: &PageTable,
program_pa: usize,
program_pages: usize,
user_va: usize,
) -> &'static mut PageTable {
let root = alloc_page_table();
for i in 0..512 {
if kernel_root.entries[i].is_valid() {
root.entries[i] = kernel_root.entries[i];
}
}
map_range(root, user_va, program_pa, program_pages, true, false, true, true, false);
let stack_va = user_va.wrapping_sub(PAGE_SIZE);
let stack_table = alloc_page_table();
let stack_pa = stack_table as *const PageTable as usize;
map_range(root, stack_va, stack_pa, 1, true, true, false, true, false);
root
}