Skip to main content

ax_cpu/
paging.rs

1//! Page-table metadata for the active architecture.
2
3pub use page_table_generic::{PageTableEntry, TableMeta};
4#[cfg(target_arch = "x86_64")]
5pub use x86_64::structures::paging::{PageOffset, PageTableIndex, page_table::PageTableLevel};
6
7use crate::VirtAddr;
8
9bitflags::bitflags! {
10    /// Runtime stage-1 mapping permissions and memory attributes.
11    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
12    pub struct MappingFlags: usize {
13        /// The memory is readable.
14        const READ = 1 << 0;
15        /// The memory is writable.
16        const WRITE = 1 << 1;
17        /// The memory is executable.
18        const EXECUTE = 1 << 2;
19        /// The memory is accessible from a lower-privileged context.
20        const USER = 1 << 3;
21        /// The memory is device memory.
22        const DEVICE = 1 << 4;
23        /// The memory is uncached.
24        const UNCACHED = 1 << 5;
25    }
26}
27
28impl From<crate::trap::PageFaultFlags> for MappingFlags {
29    fn from(fault: crate::trap::PageFaultFlags) -> Self {
30        let mut flags = Self::empty();
31        flags.set(
32            Self::READ,
33            fault.contains(crate::trap::PageFaultFlags::READ),
34        );
35        flags.set(
36            Self::WRITE,
37            fault.contains(crate::trap::PageFaultFlags::WRITE),
38        );
39        flags.set(
40            Self::EXECUTE,
41            fault.contains(crate::trap::PageFaultFlags::EXECUTE),
42        );
43        flags.set(
44            Self::USER,
45            fault.contains(crate::trap::PageFaultFlags::USER),
46        );
47        flags
48    }
49}
50
51pub use crate::arch::current::paging::{DescriptorFlags, Pte};
52#[cfg(target_arch = "aarch64")]
53pub use crate::arch::current::paging::{
54    El1Pte, El2PagingMeta, El2Pte, Stage1Pte, Stage1Regime, Stage2Pte,
55};
56#[cfg(target_arch = "x86_64")]
57pub use crate::arch::current::paging::{EptEntry, EptFlags, EptMemoryType, NptEntry};
58use crate::arch::current::paging::{
59    LEVEL_BITS as ARCH_LEVEL_BITS, MAX_BLOCK_LEVEL as ARCH_MAX_BLOCK_LEVEL,
60    PAGE_SIZE as ARCH_PAGE_SIZE,
61};
62
63/// Page-table metadata for the active target architecture.
64#[derive(Clone, Copy)]
65pub struct ArchPagingMeta;
66
67impl TableMeta for ArchPagingMeta {
68    type P = Pte;
69
70    const PAGE_SIZE: usize = ARCH_PAGE_SIZE;
71    const LEVEL_BITS: &'static [usize] = ARCH_LEVEL_BITS;
72    const MAX_BLOCK_LEVEL: usize = ARCH_MAX_BLOCK_LEVEL;
73
74    fn canonicalize_vaddr(vaddr: VirtAddr) -> VirtAddr {
75        let address_bits = ARCH_PAGE_SIZE.trailing_zeros() as usize
76            + ARCH_LEVEL_BITS.iter().copied().sum::<usize>();
77        let mask = (1usize << address_bits) - 1;
78        let address = vaddr.as_usize() & mask;
79        if address & (1usize << (address_bits - 1)) == 0 {
80            VirtAddr::from_usize(address)
81        } else {
82            VirtAddr::from_usize(address | !mask)
83        }
84    }
85
86    fn flush(vaddr: Option<VirtAddr>) {
87        crate::asm::flush_tlb(vaddr);
88    }
89}