page_table_arm/
pte64.rs

1use crate::{MAIRKind, MAIRSetting};
2use aarch64_cpu::registers::*;
3
4pub struct MAIRDefault;
5
6impl MAIRDefault {
7    #[cfg(target_arch = "aarch64")]
8    pub const fn mair_value() -> u64 {
9        // Device-nGnRE memory
10        use aarch64_cpu::registers::*;
11        let attr0 = MAIR_EL1::Attr0_Device::nonGathering_nonReordering_EarlyWriteAck.value;
12        // Normal memory
13        let attr1 = MAIR_EL1::Attr1_Normal_Inner::WriteBack_NonTransient_ReadWriteAlloc.value
14            | MAIR_EL1::Attr1_Normal_Outer::WriteBack_NonTransient_ReadWriteAlloc.value;
15        let attr2 = MAIR_EL1::Attr2_Normal_Inner::NonCacheable.value
16            | MAIR_EL1::Attr2_Normal_Outer::NonCacheable.value;
17        attr0 | attr1 | attr2 // 0x44_ff_04
18    }
19
20    #[cfg(target_arch = "aarch64")]
21    pub fn mair_el1_apply() {
22        MAIR_EL1.set(Self::mair_value());
23    }
24
25    #[cfg(target_arch = "aarch64")]
26    pub fn mair_el2_apply() {
27        MAIR_EL2.set(Self::mair_value());
28    }
29}
30
31impl MAIRSetting for MAIRDefault {
32    fn get_idx(kind: MAIRKind) -> usize {
33        match kind {
34            MAIRKind::Device => 0,
35            MAIRKind::Normal => 1,
36            MAIRKind::NonCache => 2,
37        }
38    }
39
40    fn from_idx(idx: usize) -> MAIRKind {
41        match idx {
42            0 => MAIRKind::Device,
43            1 => MAIRKind::Normal,
44            2 => MAIRKind::NonCache,
45            _ => panic!("invalid mair index"),
46        }
47    }
48}
49
50#[derive(Clone, Copy)]
51#[repr(transparent)]
52pub struct PTE(u64);
53
54impl PTE {
55    const PHYS_ADDR_MASK: u64 = 0x0000_ffff_ffff_f000; // bits 12..48
56
57    pub const fn empty() -> Self {
58        PTE(0)
59    }
60
61    pub const fn from_paddr(paddr: usize) -> Self {
62        PTE(paddr as u64 & Self::PHYS_ADDR_MASK)
63    }
64
65    pub fn paddr(&self) -> usize {
66        (self.0 & Self::PHYS_ADDR_MASK) as _
67    }
68
69    pub fn set_flags(&mut self, flags: PTEFlags) {
70        self.0 |= flags.bits();
71    }
72
73    pub fn get_flags(&self) -> PTEFlags {
74        PTEFlags::from_bits_truncate(self.0)
75    }
76
77    pub fn set_mair_idx(&mut self, idx: usize) {
78        self.0 |= ((idx as u64) & 0b111) << 2;
79    }
80
81    pub fn get_mair_idx(&self) -> usize {
82        ((self.0 >> 2) & 0b111) as usize
83    }
84}
85
86impl From<u64> for PTE {
87    fn from(value: u64) -> Self {
88        Self(value)
89    }
90}
91
92impl From<PTE> for u64 {
93    fn from(value: PTE) -> Self {
94        value.0
95    }
96}
97
98bitflags::bitflags! {
99    /// Memory attribute fields in the VMSAv8-64 translation table format descriptors.
100    #[derive(Debug, Clone, Copy)]
101    pub struct PTEFlags: u64 {
102        // Attribute fields in stage 1 VMSAv8-64 Block and Page descriptors:
103
104        /// Whether the descriptor is valid.
105        const VALID =       1 << 0;
106        /// The descriptor gives the address of the next level of translation table or 4KB page.
107        /// (not a 2M, 1G block)
108        const NON_BLOCK =   1 << 1;
109
110        /// Non-secure bit. For memory accesses from Secure state, specifies whether the output
111        /// address is in Secure or Non-secure memory.
112        const NS =          1 << 5;
113        /// Access permission: accessable at EL0.
114        const AP_EL0 =      1 << 6;
115        /// Access permission: read-only.
116        const AP_RO =       1 << 7;
117        /// Shareability: Inner Shareable (otherwise Outer Shareable).
118        const INNER =       1 << 8;
119        /// Shareability: Inner or Outer Shareable (otherwise Non-shareable).
120        const SHAREABLE =   1 << 9;
121        /// The Access flag.
122        const AF =          1 << 10;
123        /// The not global bit.
124        const NG =          1 << 11;
125        /// Indicates that 16 adjacent translation table entries point to contiguous memory regions.
126        const CONTIGUOUS =  1 <<  52;
127        /// The Privileged execute-never field.
128        const PXN =         1 <<  53;
129        /// The Execute-never or Unprivileged execute-never field.
130        const UXN =         1 <<  54;
131
132        // Next-level attributes in stage 1 VMSAv8-64 Table descriptors:
133
134        /// PXN limit for subsequent levels of lookup.
135        const PXN_TABLE =           1 << 59;
136        /// XN limit for subsequent levels of lookup.
137        const XN_TABLE =            1 << 60;
138        /// Access permissions limit for subsequent levels of lookup: access at EL0 not permitted.
139        const AP_NO_EL0_TABLE =     1 << 61;
140        /// Access permissions limit for subsequent levels of lookup: write access not permitted.
141        const AP_NO_WRITE_TABLE =   1 << 62;
142        /// For memory accesses from Secure state, specifies the Security state for subsequent
143        /// levels of lookup.
144        const NS_TABLE =            1 << 63;
145    }
146}