1use crate::{MAIRKind, MAIRSetting};
2
3pub struct MAIRDefault;
4
5#[cfg(target_arch = "aarch64")]
6impl MAIRDefault {
7 pub const fn mair_value() -> u64 {
8 use aarch64_cpu::registers::*;
10 let attr0 = MAIR_EL1::Attr0_Device::nonGathering_nonReordering_noEarlyWriteAck.value;
11 let attr1 = MAIR_EL1::Attr1_Normal_Inner::WriteBack_NonTransient_ReadWriteAlloc.value
13 | MAIR_EL1::Attr1_Normal_Outer::WriteBack_NonTransient_ReadWriteAlloc.value;
14 let attr2 = MAIR_EL1::Attr2_Normal_Inner::NonCacheable.value
15 | MAIR_EL1::Attr2_Normal_Outer::NonCacheable.value;
16 attr0 | attr1 | attr2
17 }
18 pub const fn mair_el2_value() -> u64 {
19 use aarch64_cpu::registers::*;
21 let attr0 = MAIR_EL2::Attr0_Device::nonGathering_nonReordering_noEarlyWriteAck.value;
22 let attr1 = MAIR_EL2::Attr1_Normal_Inner::WriteBack_NonTransient_ReadWriteAlloc.value
24 | MAIR_EL2::Attr1_Normal_Outer::WriteBack_NonTransient_ReadWriteAlloc.value;
25 let attr2 = MAIR_EL2::Attr2_Normal_Inner::NonCacheable.value
26 | MAIR_EL2::Attr2_Normal_Outer::NonCacheable.value;
27 attr0 | attr1 | attr2
28 }
29 pub fn mair_el1_apply() {
30 use aarch64_cpu::registers::*;
31 MAIR_EL1.set(Self::mair_value());
32 }
33
34 pub fn mair_el2_apply() {
35 use aarch64_cpu::registers::*;
36 MAIR_EL2.set(Self::mair_el2_value());
37 }
38}
39
40impl MAIRSetting for MAIRDefault {
41 fn get_idx(kind: MAIRKind) -> usize {
42 match kind {
43 MAIRKind::Device => 0,
44 MAIRKind::Normal => 1,
45 MAIRKind::NonCache => 2,
46 }
47 }
48
49 fn from_idx(idx: usize) -> MAIRKind {
50 match idx {
51 0 => MAIRKind::Device,
52 1 => MAIRKind::Normal,
53 2 => MAIRKind::NonCache,
54 _ => panic!("invalid mair index"),
55 }
56 }
57}
58
59#[derive(Clone, Copy)]
60#[repr(transparent)]
61pub struct PTE(u64);
62
63impl PTE {
64 const PHYS_ADDR_MASK: u64 = 0x0000_ffff_ffff_f000; pub const fn empty() -> Self {
67 PTE(0)
68 }
69
70 pub const fn from_paddr(paddr: usize) -> Self {
71 PTE(paddr as u64 & Self::PHYS_ADDR_MASK)
72 }
73
74 pub fn set_paddr(&mut self, paddr: usize) {
75 self.0 = (paddr as u64 & Self::PHYS_ADDR_MASK) | self.0 & !Self::PHYS_ADDR_MASK;
76 }
77
78 pub fn paddr(&self) -> usize {
79 (self.0 & Self::PHYS_ADDR_MASK) as _
80 }
81
82 pub fn set_flags(&mut self, flags: PTEFlags) {
83 self.0 |= flags.bits();
84 }
85
86 pub fn get_flags(&self) -> PTEFlags {
87 PTEFlags::from_bits_truncate(self.0)
88 }
89
90 pub fn set_mair_idx(&mut self, idx: usize) {
91 self.0 |= ((idx as u64) & 0b111) << 2;
92 }
93
94 pub fn get_mair_idx(&self) -> usize {
95 ((self.0 >> 2) & 0b111) as usize
96 }
97}
98
99impl From<u64> for PTE {
100 fn from(value: u64) -> Self {
101 Self(value)
102 }
103}
104
105impl From<PTE> for u64 {
106 fn from(value: PTE) -> Self {
107 value.0
108 }
109}
110
111bitflags::bitflags! {
112 #[derive(Debug, Clone, Copy)]
114 pub struct PTEFlags: u64 {
115 const VALID = 1 << 0;
119 const NON_BLOCK = 1 << 1;
122
123 const NS = 1 << 5;
126 const AP_EL0 = 1 << 6;
128 const AP_RO = 1 << 7;
130 const INNER = 1 << 8;
132 const SHAREABLE = 1 << 9;
134 const AF = 1 << 10;
136 const NG = 1 << 11;
138 const CONTIGUOUS = 1 << 52;
140 const PXN = 1 << 53;
142 const UXN = 1 << 54;
144
145 const PXN_TABLE = 1 << 59;
149 const XN_TABLE = 1 << 60;
151 const AP_NO_EL0_TABLE = 1 << 61;
153 const AP_NO_WRITE_TABLE = 1 << 62;
155 const NS_TABLE = 1 << 63;
158 }
159}