page_table_entry/arch/
arm.rs1use core::fmt;
9
10use memory_addr::PhysAddr;
11
12use crate::{GenericPTE, MappingFlags};
13
14bitflags::bitflags! {
15 #[derive(Debug, Clone, Copy)]
20 pub struct DescriptorAttr: u32 {
21 const TYPE_BIT0 = 1 << 0;
30
31 const TYPE_BIT1 = 1 << 1;
33
34 const B = 1 << 2;
38
39 const C = 1 << 3;
41
42 const XN_SMALL = 1 << 4;
44
45 const DOMAIN_MASK = 0b1111 << 5;
47
48 const IMP = 1 << 9;
50
51 const AP0 = 1 << 10;
61 const AP1 = 1 << 11;
63
64 const TEX0 = 1 << 12;
66 const TEX1 = 1 << 13;
68 const TEX2 = 1 << 14;
70
71 const AP2 = 1 << 15;
73
74 const S = 1 << 16;
76
77 const NG = 1 << 17;
79
80 const NS = 1 << 19;
82
83 const SECTION = Self::TYPE_BIT1.bits();
87
88 const PAGE_TABLE = Self::TYPE_BIT0.bits();
90
91 const SMALL_PAGE = Self::TYPE_BIT1.bits();
93
94 const NORMAL_MEMORY = Self::TEX0.bits() | Self::C.bits() | Self::B.bits();
97
98 const DEVICE_MEMORY = Self::B.bits();
101
102 const NORMAL_SHAREABLE = Self::NORMAL_MEMORY.bits() | Self::S.bits();
104
105 const AP_PRIV_RW = Self::AP0.bits();
107
108 const AP_USER_RW = Self::AP0.bits() | Self::AP1.bits();
110
111 const AP_PRIV_RO = Self::AP2.bits() | Self::AP0.bits();
113
114 const AP_USER_RO = Self::AP2.bits() | Self::AP0.bits() | Self::AP1.bits();
116 }
117}
118
119impl DescriptorAttr {
120 #[inline]
123 pub const fn common_flags(flags: MappingFlags) -> u32 {
124 let mut bits = 0;
125
126 if flags.contains(MappingFlags::DEVICE) {
128 bits |= Self::DEVICE_MEMORY.bits();
129 } else if flags.contains(MappingFlags::UNCACHED) {
130 bits |= Self::TEX0.bits();
132 } else {
133 bits |= Self::NORMAL_SHAREABLE.bits();
135 }
136
137 let has_write = flags.contains(MappingFlags::WRITE);
139 let has_user = flags.contains(MappingFlags::USER);
140
141 if has_user {
142 if has_write {
143 bits |= Self::AP_USER_RW.bits();
144 } else {
145 bits |= Self::AP_USER_RO.bits();
146 }
147 } else if has_write {
148 bits |= Self::AP_PRIV_RW.bits();
149 } else {
150 bits |= Self::AP_PRIV_RO.bits();
151 }
152
153 bits
154 }
155
156 #[inline]
158 pub const fn from_mapping_flags_section(flags: MappingFlags) -> Self {
159 let mut bits = Self::SECTION.bits();
160
161 if flags.is_empty() {
162 return Self::from_bits_retain(0);
163 }
164
165 bits |= Self::common_flags(flags);
166
167 if !flags.contains(MappingFlags::EXECUTE) {
171 bits |= Self::XN_SMALL.bits();
175 }
176
177 Self::from_bits_retain(bits)
178 }
179
180 #[inline]
182 pub const fn from_mapping_flags_small_page(flags: MappingFlags) -> Self {
183 let mut bits = Self::SMALL_PAGE.bits();
184
185 if flags.is_empty() {
186 return Self::from_bits_retain(0);
187 }
188
189 let attr = Self::common_flags(flags);
190
191 bits |= attr & (Self::B.bits() | Self::C.bits());
193
194 let shift_mask = Self::AP0.bits()
202 | Self::AP1.bits()
203 | Self::TEX0.bits()
204 | Self::TEX1.bits()
205 | Self::TEX2.bits()
206 | Self::AP2.bits()
207 | Self::S.bits()
208 | Self::NG.bits();
209
210 bits |= (attr & shift_mask) >> 6;
211
212 if !flags.contains(MappingFlags::EXECUTE) {
214 bits |= Self::TYPE_BIT0.bits();
215 }
216
217 Self::from_bits_retain(bits)
218 }
219
220 pub const fn descriptor_type(&self) -> u32 {
222 self.bits() & 0b11
223 }
224
225 pub const fn is_valid(&self) -> bool {
227 self.descriptor_type() != 0
228 }
229
230 pub const fn is_section(&self) -> bool {
232 self.descriptor_type() == 0b10
233 }
234
235 pub const fn is_page_table(&self) -> bool {
237 self.descriptor_type() == 0b01
238 }
239
240 pub const fn is_small_page(&self) -> bool {
242 self.descriptor_type() == 0b10
243 }
244}
245
246impl From<DescriptorAttr> for MappingFlags {
247 #[inline]
248 fn from(attr: DescriptorAttr) -> Self {
249 if !attr.is_valid() {
250 return Self::empty();
251 }
252
253 let mut flags = Self::READ;
254
255 let ap = ((attr.bits() >> 10) & 0b11) | (((attr.bits() >> 15) & 1) << 2);
257 match ap {
258 0b001 | 0b011 => flags |= Self::WRITE, _ => {}
260 }
261
262 if (ap & 0b10) != 0 {
264 flags |= Self::USER;
265 }
266
267 if !attr.contains(DescriptorAttr::XN_SMALL) {
269 flags |= Self::EXECUTE;
270 }
271
272 let tex = (attr.bits() >> 12) & 0b111;
274 let c = (attr.bits() >> 3) & 1;
275 let b = (attr.bits() >> 2) & 1;
276
277 if tex == 0 && c == 0 && b == 1 {
278 flags |= Self::DEVICE;
279 } else if tex == 1 && c == 0 && b == 0 {
280 flags |= Self::UNCACHED;
281 }
282
283 flags
284 }
285}
286
287#[derive(Clone, Copy)]
294#[repr(transparent)]
295pub struct A32PTE(u32);
296
297impl A32PTE {
298 const SECTION_ADDR_MASK: u32 = 0xfff0_0000;
300
301 const PAGE_TABLE_ADDR_MASK: u32 = 0xffff_fc00;
303
304 const SMALL_PAGE_ADDR_MASK: u32 = 0xffff_f000;
306
307 pub const fn empty() -> Self {
309 Self(0)
310 }
311
312 #[inline]
314 pub const fn new_section(paddr: PhysAddr, flags: MappingFlags) -> Self {
315 let attr = DescriptorAttr::from_mapping_flags_section(flags);
316 Self(attr.bits() | (paddr.as_usize() as u32 & Self::SECTION_ADDR_MASK))
317 }
318
319 #[inline]
321 pub const fn new_small_page(paddr: PhysAddr, flags: MappingFlags) -> Self {
322 let attr = DescriptorAttr::from_mapping_flags_small_page(flags);
323 Self(attr.bits() | (paddr.as_usize() as u32 & Self::SMALL_PAGE_ADDR_MASK))
324 }
325
326 pub const fn descriptor_type(&self) -> u32 {
328 self.0 & 0b11
329 }
330
331 pub const fn is_section(&self) -> bool {
333 (self.0 & 0b11) == 0b10
334 }
335}
336
337impl GenericPTE for A32PTE {
338 #[inline]
339 fn new_page(paddr: PhysAddr, flags: MappingFlags, is_huge: bool) -> Self {
340 if is_huge {
341 Self::new_section(paddr, flags)
343 } else {
344 Self::new_small_page(paddr, flags)
346 }
347 }
348
349 #[inline]
350 fn new_table(paddr: PhysAddr) -> Self {
351 let attr = DescriptorAttr::PAGE_TABLE;
353 Self(attr.bits() | (paddr.as_usize() as u32 & Self::PAGE_TABLE_ADDR_MASK))
354 }
355
356 fn paddr(&self) -> PhysAddr {
357 let desc_type = self.descriptor_type();
358 let addr = match desc_type {
359 0b01 => self.0 & Self::PAGE_TABLE_ADDR_MASK, 0b10 => {
361 if (self.0 & Self::SECTION_ADDR_MASK) >= 0x10_0000 {
362 self.0 & Self::SECTION_ADDR_MASK } else {
364 self.0 & Self::SMALL_PAGE_ADDR_MASK }
366 }
367 0b11 => self.0 & Self::SMALL_PAGE_ADDR_MASK, _ => 0,
369 };
370 PhysAddr::from(addr as usize)
371 }
372
373 fn flags(&self) -> MappingFlags {
374 DescriptorAttr::from_bits_truncate(self.0).into()
375 }
376
377 fn set_paddr(&mut self, paddr: PhysAddr) {
378 let desc_type = self.descriptor_type();
379 match desc_type {
380 0b01 => {
381 self.0 = (self.0 & !Self::PAGE_TABLE_ADDR_MASK)
383 | (paddr.as_usize() as u32 & Self::PAGE_TABLE_ADDR_MASK);
384 }
385 0b10 => {
386 if self.is_section() {
388 self.0 = (self.0 & !Self::SECTION_ADDR_MASK)
389 | (paddr.as_usize() as u32 & Self::SECTION_ADDR_MASK);
390 } else {
391 self.0 = (self.0 & !Self::SMALL_PAGE_ADDR_MASK)
392 | (paddr.as_usize() as u32 & Self::SMALL_PAGE_ADDR_MASK);
393 }
394 }
395 _ => {}
396 }
397 }
398
399 fn set_flags(&mut self, flags: MappingFlags, is_huge: bool) {
400 let paddr = self.paddr();
401 *self = if is_huge {
402 Self::new_section(paddr, flags)
403 } else {
404 Self::new_small_page(paddr, flags)
405 };
406 }
407
408 fn bits(self) -> usize {
409 self.0 as usize
410 }
411
412 fn is_unused(&self) -> bool {
413 self.0 == 0
414 }
415
416 fn is_present(&self) -> bool {
417 self.descriptor_type() != 0
418 }
419
420 fn is_huge(&self) -> bool {
421 self.is_section()
422 }
423
424 fn clear(&mut self) {
425 self.0 = 0;
426 }
427}
428
429impl fmt::Debug for A32PTE {
430 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
431 let mut f = f.debug_struct("A32PTE");
432 f.field("raw", &format_args!("{:#010x}", self.0))
433 .field(
434 "type",
435 &match self.descriptor_type() {
436 0b00 => "Invalid",
437 0b01 => "PageTable",
438 0b10 => {
439 if self.is_section() {
440 "Section"
441 } else {
442 "SmallPage"
443 }
444 }
445 0b11 => "Reserved",
446 _ => "Unknown",
447 },
448 )
449 .field("paddr", &self.paddr())
450 .field("flags", &self.flags())
451 .finish()
452 }
453}
454
455#[cfg(test)]
456mod tests {
457 use super::*;
458
459 #[test]
460 fn test_section_descriptor() {
461 let paddr = PhysAddr::from(0x4000_0000);
462 let flags = MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXECUTE;
463 let pte = A32PTE::new_section(paddr, flags);
464
465 assert!(pte.is_present());
466 assert!(pte.is_huge());
467 assert_eq!(pte.paddr(), paddr);
468 assert!(pte.flags().contains(MappingFlags::READ));
469 assert!(pte.flags().contains(MappingFlags::WRITE));
470 }
471
472 #[test]
473 fn test_small_page_descriptor() {
474 let paddr = PhysAddr::from(0x4000_1000);
475 let flags = MappingFlags::READ | MappingFlags::WRITE;
476 let pte = A32PTE::new_small_page(paddr, flags);
477
478 assert!(pte.is_present());
479 assert_eq!(pte.paddr(), paddr);
480 assert!(pte.flags().contains(MappingFlags::READ));
481 }
482
483 #[test]
484 fn test_page_table_descriptor() {
485 let paddr = PhysAddr::from(0x4000_0400);
486 let pte = A32PTE::new_table(paddr);
487
488 assert!(pte.is_present());
489 assert!(!pte.is_huge());
490 assert_eq!(pte.paddr(), paddr);
491 }
492}