use super::{PAGE_SHIFT, PGD_MASK, PGD_SHIFT, PGD_SIZE, PTRS_PER_TABLE, PageLevel, PageProt};
const PA_BITS: usize = 48;
#[allow(non_upper_case_globals)]
pub const MT_DEVICE_nGnRnE: usize = 0;
#[allow(non_upper_case_globals)]
pub const MT_DEVICE_nGnRE: usize = 1;
pub const MT_DEVICE_GRE: usize = 2;
pub const MT_NORMAL_NC: usize = 3;
pub const MT_NORMAL: usize = 4;
pub const MT_NORMAL_WT: usize = 5;
pub const MAIR_ATTR: usize = (0x04 << (MT_DEVICE_nGnRE * 8))
| (0x0c << (MT_DEVICE_GRE * 8))
| (0x44 << (MT_NORMAL_NC * 8))
| (0xff << (MT_NORMAL * 8))
| (0xbb << (MT_NORMAL_WT * 8));
pub const PGD_TYPE_TABLE: usize = 3;
pub const PGD_TABLE_PXN: usize = 1 << 59;
pub const PGD_TABLE_UXN: usize = 1 << 60;
pub const PGD_TYPE_SECT: usize = 1 << 0;
pub const PGD_SECT_AF: usize = 1 << 10;
pub const PGD_SECT_S: usize = 3 << 8;
pub const PGD_SECT_PXN: usize = 1 << 53;
pub const SWAPPER_PGD_FLAGS: usize = PGD_TYPE_SECT | PGD_SECT_AF | PGD_SECT_S;
pub const SWAPPER_MM_NORMALFLAGS: usize = (MT_NORMAL << 2) | SWAPPER_PGD_FLAGS;
pub const SWAPPER_MM_NORMAL_PXN_FLAGS: usize = (MT_NORMAL << 2) | SWAPPER_PGD_FLAGS | PGD_SECT_PXN;
pub const SWAPPER_MM_IOFLAGS: usize = (MT_DEVICE_nGnRE << 2) | SWAPPER_PGD_FLAGS | PGD_SECT_PXN;
pub const PUD_TYPE_TABLE: usize = PGD_TYPE_TABLE;
pub const PUD_TABLE_PXN: usize = 1 << 59;
pub const PUD_TABLE_UXN: usize = 1 << 58;
pub const PUD_SHIFT: usize = PGD_SHIFT;
pub const PUD_SIZE: usize = PGD_SIZE;
pub const PUD_MASK: usize = PGD_MASK;
pub const PTRS_PER_PUD: usize = PTRS_PER_PGD;
pub const PMD_TYPE_TABLE: usize = 3;
pub const PMD_TABLE_PXN: usize = 1 << 59;
pub const PMD_TABLE_UXN: usize = 1 << 58;
pub const PTRS_PER_PGD: usize = PTRS_PER_TABLE;
pub const PTRS_PER_PMD: usize = PTRS_PER_TABLE;
pub const PTRS_PER_PTE: usize = PTRS_PER_TABLE;
const DESC_TABLE: usize = 0b11;
const DESC_BLOCK: usize = 0b01;
const DESC_PAGE: usize = 0b11;
const DESC_VALID: usize = 0b01;
const PTE_USER: usize = 1 << 6; const PTE_RDONLY: usize = 1 << 7; const PTE_SHARED: usize = 3 << 8; const PTE_AF: usize = 1 << 10; const PTE_NG: usize = 1 << 11; const PTE_DBM: usize = 1 << 51; const PTE_PXN: usize = 1 << 53; const PTE_UXN: usize = 1 << 54;
const PTE_WRITE: usize = PTE_DBM;
const fn attrindx(t: usize) -> usize {
t << 2
}
const ADDR_MASK: usize = ((1usize << (PA_BITS - PAGE_SHIFT)) - 1) << PAGE_SHIFT;
#[inline(always)]
pub(crate) fn paddr_to_table(paddr: usize) -> usize {
debug_assert_eq!(paddr & !ADDR_MASK, 0);
paddr | DESC_TABLE
}
#[inline(always)]
pub(crate) fn table_to_paddr(entry: usize) -> usize {
entry & ADDR_MASK
}
#[inline(always)]
pub(crate) fn paddr_to_leaf(paddr: usize, prot: PageProt, level: PageLevel) -> usize {
let desc_type = match level {
PageLevel::Page4K => DESC_PAGE,
PageLevel::Page2M | PageLevel::Page1G => DESC_BLOCK,
};
let attr = prot_to_attr(prot);
(paddr & ADDR_MASK) | attr | desc_type
}
#[inline(always)]
pub(crate) fn leaf_to_paddr(entry: usize) -> usize {
entry & ADDR_MASK
}
#[inline(always)]
pub(crate) fn entry_is_valid(entry: usize) -> bool {
entry & DESC_VALID != 0
}
#[inline(always)]
pub(crate) fn entry_is_leaf(entry: usize) -> bool {
entry & DESC_VALID != 0 && entry & 0b10 == 0
}
const BASE: usize = PTE_AF | PTE_SHARED;
#[allow(clippy::fn_params_excessive_bools, clippy::if_not_else)]
const fn mk_normal(bits: usize) -> usize {
let wr = bits & 2 != 0;
let ex = bits & 4 != 0;
let us = bits & 8 != 0;
let mut attr = BASE | attrindx(MT_NORMAL);
if us {
attr |= PTE_USER | PTE_NG;
}
if wr {
attr |= PTE_WRITE;
} else {
attr |= PTE_RDONLY;
}
if !ex {
attr |= PTE_PXN | PTE_UXN;
} else if !us {
attr |= PTE_UXN;
}
attr
}
#[allow(clippy::fn_params_excessive_bools, clippy::if_not_else)]
const fn mk_device(bits: usize) -> usize {
let wr = bits & 2 != 0;
let us = bits & 8 != 0;
let mut attr = BASE | attrindx(MT_DEVICE_nGnRE) | PTE_UXN | PTE_PXN;
if us {
attr |= PTE_USER | PTE_NG;
}
if wr {
attr |= PTE_WRITE;
} else {
attr |= PTE_RDONLY;
}
attr
}
const fn build_table(device: bool) -> [usize; 16] {
let mut table = [0usize; 16];
let mut idx = 0usize;
while idx < 16 {
table[idx] = if device { mk_device(idx) } else { mk_normal(idx) };
idx += 1;
}
table
}
const NORMAL_TABLE: [usize; 16] = build_table(false);
const DEVICE_TABLE: [usize; 16] = build_table(true);
#[inline(always)]
fn prot_to_attr(prot: PageProt) -> usize {
let idx = prot.bits() & 0xF;
if prot.contains(PageProt::IO) { DEVICE_TABLE[idx] } else { NORMAL_TABLE[idx] }
}