rustubs/arch/x86_64/paging/
pagetable.rs1use bitflags::bitflags;
5
6#[repr(align(4096))]
7#[repr(C)]
8#[derive(Clone)]
9pub struct Pagetable {
10 pub entries: [PTE; Self::ENTRY_COUNT],
11}
12
13#[derive(Clone)]
14#[repr(transparent)]
15pub struct PTE {
16 pub entry: u64,
17}
18
19bitflags! {
20#[derive(Debug, Copy, Clone)]
21pub struct PTEFlags:u64 {
22 const ZERO = 0;
23 const PRESENT = 1 << 0;
24 const WRITABLE = 1 << 1;
25 const USER = 1 << 2;
26 const WT = 1 << 3;
27 const NC = 1 << 4;
28 const ACCESSED = 1 << 5;
29 const DIRTY = 1 << 6;
30 const HUGE_PAGE = 1 << 7;
31 const GLOBAL = 1 << 8;
32 const B9 = 1 << 9;
33 const B10 = 1 << 10;
34 const B11 = 1 << 11;
35 const NE = 1 << 63;
39}
40}
41
42impl Pagetable {
43 const ENTRY_COUNT: usize = 512;
44 #[inline]
46 pub const fn new() -> Self {
47 const EMPTY: PTE = PTE::new();
48 Pagetable { entries: [EMPTY; Self::ENTRY_COUNT] }
49 }
50
51 #[inline]
53 pub fn zero(&mut self) {
54 for entry in self.iter_mut() {
55 entry.set_unused();
56 }
57 }
58
59 #[inline]
61 pub fn iter(&self) -> impl Iterator<Item = &PTE> {
62 (0..512).map(move |i| &self.entries[i])
63 }
64
65 #[inline]
67 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut PTE> {
68 let ptr = self.entries.as_mut_ptr();
83 (0..512).map(move |i| unsafe { &mut *ptr.add(i) })
84 }
85
86 #[inline]
88 pub fn is_empty(&self) -> bool {
89 self.iter().all(|entry| entry.is_unused())
90 }
91}
92
93impl PTE {
94 #[inline]
95 pub const fn new() -> Self { PTE { entry: 0 } }
96
97 #[inline]
98 pub const fn is_unused(&self) -> bool { self.entry == 0 }
99
100 #[inline]
101 pub fn set_unused(&mut self) { self.entry = 0; }
102
103 #[inline]
104 pub const fn flags(&self) -> PTEFlags {
105 PTEFlags::from_bits_truncate(self.entry)
107 }
108
109 #[inline]
110 pub const fn addr(&self) -> u64 { self.entry & 0x000f_ffff_ffff_f000 }
111
112 #[inline]
113 pub fn set(&mut self, pa: u64, flags: PTEFlags) {
114 self.entry = pa | flags.bits();
115 }
116}
117
118const ID_MASK: u64 = 0x1ff;
119#[inline]
120pub fn p4idx(addr: u64) -> u16 {
121 ((addr >> 12 >> 9 >> 9 >> 9) & ID_MASK) as u16
122}
123#[inline]
124pub fn p3idx(addr: u64) -> u16 { ((addr >> 12 >> 9 >> 9) & ID_MASK) as u16 }
125#[inline]
126pub fn p2idx(addr: u64) -> u16 { ((addr >> 12 >> 9) & ID_MASK) as u16 }
127#[inline]
128pub fn p1idx(addr: u64) -> u16 { ((addr >> 12) & ID_MASK) as u16 }