moa_mm 0.1.3

内存管理基础(页表、虚拟地址布局)
Documentation
//! RISC-V 64 页表编解码(`Sv39`/`Sv48`)

use super::{PAGE_SHIFT, PTRS_PER_TABLE, PageLevel, PageProt};

const PA_BITS: usize = 56;

/// Sv39 PTE Valid
pub const PTE_V: usize = 1 << 0;
/// Sv39 PTE Read
pub const PTE_R: usize = 1 << 1;
/// Sv39 PTE Write
pub const PTE_W: usize = 1 << 2;
/// Sv39 PTE Execute
pub const PTE_X: usize = 1 << 3;
/// Sv39 PTE User
pub const PTE_U: usize = 1 << 4;
/// Sv39 PTE Global
pub const PTE_G: usize = 1 << 5;
/// Sv39 PTE Accessed
pub const PTE_A: usize = 1 << 6;
/// Sv39 PTE Dirty
pub const PTE_D: usize = 1 << 7;

/// boot 内核代码映射 flags(VRWXGAD)
pub const SWAPPER_MM_NORMALFLAGS: usize = PTE_V | PTE_R | PTE_W | PTE_X | PTE_G | PTE_A | PTE_D;
/// boot 内核数据映射 flags(VRWGAD,不可执行)
pub const SWAPPER_MM_NORMAL_PXN_FLAGS: usize = PTE_V | PTE_R | PTE_W | PTE_G | PTE_A | PTE_D;
/// boot IO 映射 flags(VRWGAD,不可执行)
pub const SWAPPER_MM_IOFLAGS: usize = PTE_V | PTE_R | PTE_W | PTE_G | PTE_A | PTE_D;

/// pgd entry 数量
pub const PTRS_PER_PGD: usize = PTRS_PER_TABLE;
/// pmd entry 数量
pub const PTRS_PER_PMD: usize = PTRS_PER_TABLE;
/// pte entry 数量
pub const PTRS_PER_PTE: usize = PTRS_PER_TABLE;

// ---- PPN 编解码 ----

const PPN_SHIFT: usize = 10;
const PPN_MASK: usize = (1usize << (PA_BITS - PAGE_SHIFT)) - 1;

#[inline(always)]
fn paddr_to_ppn(paddr: usize) -> usize {
    (paddr >> PAGE_SHIFT) << PPN_SHIFT
}

#[inline(always)]
fn ppn_to_paddr(entry: usize) -> usize {
    ((entry >> PPN_SHIFT) & PPN_MASK) << PAGE_SHIFT
}

// ---- table pointer 编解码 ----

#[inline(always)]
pub(crate) fn paddr_to_table(paddr: usize) -> usize {
    paddr_to_ppn(paddr) | PTE_V
}

#[inline(always)]
pub(crate) fn table_to_paddr(entry: usize) -> usize {
    ppn_to_paddr(entry)
}

// ---- leaf 编解码 ----

#[inline(always)]
pub(crate) fn paddr_to_leaf(paddr: usize, prot: PageProt, _level: PageLevel) -> usize {
    paddr_to_ppn(paddr) | prot_to_attr(prot)
}

#[inline(always)]
pub(crate) fn leaf_to_paddr(entry: usize) -> usize {
    ppn_to_paddr(entry)
}

// ---- valid / leaf 判定 ----

#[inline(always)]
pub(crate) fn entry_is_valid(entry: usize) -> bool {
    entry & PTE_V != 0
}

#[inline(always)]
pub(crate) fn entry_is_leaf(entry: usize) -> bool {
    entry & PTE_V != 0 && entry & (PTE_R | PTE_X) != 0
}

// ---- PageProt → Sv39 硬件属性位(const 查找表) ----

// 索引: PageProt 低 4 位 [U:X:W:R]

const fn mk_attr(bits: usize) -> usize {
    let mut flags = PTE_V | PTE_A;
    if bits & 1 != 0 {
        flags |= PTE_R;
    }
    if bits & 2 != 0 {
        flags |= PTE_W | PTE_D;
    }
    if bits & 4 != 0 {
        flags |= PTE_X;
    }
    if bits & 8 != 0 {
        flags |= PTE_U;
    }
    flags
}

const fn build_table() -> [usize; 16] {
    let mut table = [0usize; 16];
    let mut idx = 0usize;
    while idx < 16 {
        table[idx] = mk_attr(idx);
        idx += 1;
    }
    table
}

const ATTR_TABLE: [usize; 16] = build_table();

#[inline(always)]
fn prot_to_attr(prot: PageProt) -> usize {
    ATTR_TABLE[prot.bits() & 0xF]
}