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();
174 }
175
176 Self::from_bits_retain(bits)
177 }
178
179 #[inline]
181 pub const fn from_mapping_flags_small_page(flags: MappingFlags) -> Self {
182 let mut bits = Self::SMALL_PAGE.bits();
183
184 if flags.is_empty() {
185 return Self::from_bits_retain(0);
186 }
187
188 let attr = Self::common_flags(flags);
189
190 bits |= attr & (Self::B.bits() | Self::C.bits());
192
193 let shift_mask = Self::AP0.bits()
201 | Self::AP1.bits()
202 | Self::TEX0.bits()
203 | Self::TEX1.bits()
204 | Self::TEX2.bits()
205 | Self::AP2.bits()
206 | Self::S.bits()
207 | Self::NG.bits();
208
209 bits |= (attr & shift_mask) >> 6;
210
211 if !flags.contains(MappingFlags::EXECUTE) {
213 bits |= Self::TYPE_BIT0.bits();
214 }
215
216 Self::from_bits_retain(bits)
217 }
218
219 pub const fn descriptor_type(&self) -> u32 {
221 self.bits() & 0b11
222 }
223
224 pub const fn is_valid(&self) -> bool {
226 self.descriptor_type() != 0
227 }
228
229 pub const fn is_section(&self) -> bool {
231 self.descriptor_type() == 0b10
232 }
233
234 pub const fn is_page_table(&self) -> bool {
236 self.descriptor_type() == 0b01
237 }
238
239 pub const fn is_small_page(&self) -> bool {
241 self.descriptor_type() == 0b10
242 }
243}
244
245impl From<DescriptorAttr> for MappingFlags {
246 #[inline]
247 fn from(attr: DescriptorAttr) -> Self {
248 if !attr.is_valid() {
249 return Self::empty();
250 }
251
252 let mut flags = Self::READ;
253
254 let ap = ((attr.bits() >> 10) & 0b11) | (((attr.bits() >> 15) & 1) << 2);
256 match ap {
257 0b001 | 0b011 => flags |= Self::WRITE, _ => {}
259 }
260
261 if (ap & 0b10) != 0 {
263 flags |= Self::USER;
264 }
265
266 if !attr.contains(DescriptorAttr::XN_SMALL) {
268 flags |= Self::EXECUTE;
269 }
270
271 let tex = (attr.bits() >> 12) & 0b111;
273 let c = (attr.bits() >> 3) & 1;
274 let b = (attr.bits() >> 2) & 1;
275
276 if tex == 0 && c == 0 && b == 1 {
277 flags |= Self::DEVICE;
278 } else if tex == 1 && c == 0 && b == 0 {
279 flags |= Self::UNCACHED;
280 }
281
282 flags
283 }
284}
285
286#[derive(Clone, Copy)]
293#[repr(transparent)]
294pub struct A32PTE(u32);
295
296impl A32PTE {
297 const SECTION_ADDR_MASK: u32 = 0xfff0_0000;
299
300 const PAGE_TABLE_ADDR_MASK: u32 = 0xffff_fc00;
302
303 const SMALL_PAGE_ADDR_MASK: u32 = 0xffff_f000;
305
306 pub const fn empty() -> Self {
308 Self(0)
309 }
310
311 #[inline]
313 pub const fn new_section(paddr: PhysAddr, flags: MappingFlags) -> Self {
314 let attr = DescriptorAttr::from_mapping_flags_section(flags);
315 Self(attr.bits() | (paddr.as_usize() as u32 & Self::SECTION_ADDR_MASK))
316 }
317
318 #[inline]
320 pub const fn new_small_page(paddr: PhysAddr, flags: MappingFlags) -> Self {
321 let attr = DescriptorAttr::from_mapping_flags_small_page(flags);
322 Self(attr.bits() | (paddr.as_usize() as u32 & Self::SMALL_PAGE_ADDR_MASK))
323 }
324
325 pub const fn descriptor_type(&self) -> u32 {
327 self.0 & 0b11
328 }
329
330 pub const fn is_section(&self) -> bool {
332 (self.0 & 0b11) == 0b10
333 }
334}
335
336impl GenericPTE for A32PTE {
337 #[inline]
338 fn new_page(paddr: PhysAddr, flags: MappingFlags, is_huge: bool) -> Self {
339 if is_huge {
340 Self::new_section(paddr, flags)
342 } else {
343 Self::new_small_page(paddr, flags)
345 }
346 }
347
348 #[inline]
349 fn new_table(paddr: PhysAddr) -> Self {
350 let attr = DescriptorAttr::PAGE_TABLE;
352 Self(attr.bits() | (paddr.as_usize() as u32 & Self::PAGE_TABLE_ADDR_MASK))
353 }
354
355 fn paddr(&self) -> PhysAddr {
356 let desc_type = self.descriptor_type();
357 let addr = match desc_type {
358 0b01 => self.0 & Self::PAGE_TABLE_ADDR_MASK, 0b10 => {
360 if (self.0 & Self::SECTION_ADDR_MASK) >= 0x10_0000 {
361 self.0 & Self::SECTION_ADDR_MASK } else {
363 self.0 & Self::SMALL_PAGE_ADDR_MASK }
365 }
366 0b11 => self.0 & Self::SMALL_PAGE_ADDR_MASK, _ => 0,
368 };
369 PhysAddr::from(addr as usize)
370 }
371
372 fn flags(&self) -> MappingFlags {
373 DescriptorAttr::from_bits_truncate(self.0).into()
374 }
375
376 fn set_paddr(&mut self, paddr: PhysAddr) {
377 let desc_type = self.descriptor_type();
378 match desc_type {
379 0b01 => {
380 self.0 = (self.0 & !Self::PAGE_TABLE_ADDR_MASK)
382 | (paddr.as_usize() as u32 & Self::PAGE_TABLE_ADDR_MASK);
383 }
384 0b10 => {
385 if self.is_section() {
387 self.0 = (self.0 & !Self::SECTION_ADDR_MASK)
388 | (paddr.as_usize() as u32 & Self::SECTION_ADDR_MASK);
389 } else {
390 self.0 = (self.0 & !Self::SMALL_PAGE_ADDR_MASK)
391 | (paddr.as_usize() as u32 & Self::SMALL_PAGE_ADDR_MASK);
392 }
393 }
394 _ => {}
395 }
396 }
397
398 fn set_flags(&mut self, flags: MappingFlags, is_huge: bool) {
399 let paddr = self.paddr();
400 *self = if is_huge {
401 Self::new_section(paddr, flags)
402 } else {
403 Self::new_small_page(paddr, flags)
404 };
405 }
406
407 fn bits(self) -> usize {
408 self.0 as usize
409 }
410
411 fn is_unused(&self) -> bool {
412 self.0 == 0
413 }
414
415 fn is_present(&self) -> bool {
416 self.descriptor_type() != 0
417 }
418
419 fn is_huge(&self) -> bool {
420 self.is_section()
421 }
422
423 fn clear(&mut self) {
424 self.0 = 0;
425 }
426}
427
428impl fmt::Debug for A32PTE {
429 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
430 let mut f = f.debug_struct("A32PTE");
431 f.field("raw", &format_args!("{:#010x}", self.0))
432 .field(
433 "type",
434 &match self.descriptor_type() {
435 0b00 => "Invalid",
436 0b01 => "PageTable",
437 0b10 => {
438 if self.is_section() {
439 "Section"
440 } else {
441 "SmallPage"
442 }
443 }
444 0b11 => "Reserved",
445 _ => "Unknown",
446 },
447 )
448 .field("paddr", &self.paddr())
449 .field("flags", &self.flags())
450 .finish()
451 }
452}
453
454#[cfg(test)]
455mod tests {
456 use super::*;
457
458 #[test]
459 fn test_section_descriptor() {
460 let paddr = PhysAddr::from(0x4000_0000);
461 let flags = MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXECUTE;
462 let pte = A32PTE::new_section(paddr, flags);
463
464 assert!(pte.is_present());
465 assert!(pte.is_huge());
466 assert_eq!(pte.paddr(), paddr);
467 assert!(pte.flags().contains(MappingFlags::READ));
468 assert!(pte.flags().contains(MappingFlags::WRITE));
469 }
470
471 #[test]
472 fn test_small_page_descriptor() {
473 let paddr = PhysAddr::from(0x4000_1000);
474 let flags = MappingFlags::READ | MappingFlags::WRITE;
475 let pte = A32PTE::new_small_page(paddr, flags);
476
477 assert!(pte.is_present());
478 assert_eq!(pte.paddr(), paddr);
479 assert!(pte.flags().contains(MappingFlags::READ));
480 }
481
482 #[test]
483 fn test_page_table_descriptor() {
484 let paddr = PhysAddr::from(0x4000_0400);
485 let pte = A32PTE::new_table(paddr);
486
487 assert!(pte.is_present());
488 assert!(!pte.is_huge());
489 assert_eq!(pte.paddr(), paddr);
490 }
491}