x86/registers/bits32/
paging.rs
1use core::fmt;
10use core::ops;
11use kernel::utilities::registers::register_bitfields;
12use tock_registers::LocalRegisterCopy;
13
14#[repr(transparent)]
16#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
17pub struct PAddr(pub u32);
18
19impl From<u32> for PAddr {
20 fn from(num: u32) -> Self {
21 PAddr(num)
22 }
23}
24
25impl From<usize> for PAddr {
26 fn from(num: usize) -> Self {
27 PAddr(num as u32)
28 }
29}
30
31impl From<i32> for PAddr {
32 fn from(num: i32) -> Self {
33 PAddr(num as u32)
34 }
35}
36
37#[allow(clippy::from_over_into)]
38impl Into<u32> for PAddr {
39 fn into(self) -> u32 {
40 self.0
41 }
42}
43
44#[allow(clippy::from_over_into)]
45impl Into<usize> for PAddr {
46 fn into(self) -> usize {
47 self.0 as usize
48 }
49}
50
51impl ops::Rem for PAddr {
52 type Output = PAddr;
53
54 fn rem(self, rhs: PAddr) -> Self::Output {
55 PAddr(self.0 % rhs.0)
56 }
57}
58
59impl ops::Rem<u32> for PAddr {
60 type Output = u32;
61
62 fn rem(self, rhs: u32) -> Self::Output {
63 self.0 % rhs
64 }
65}
66
67impl ops::Rem<usize> for PAddr {
68 type Output = u32;
69
70 fn rem(self, rhs: usize) -> Self::Output {
71 self.0 % (rhs as u32)
72 }
73}
74
75impl ops::BitAnd for PAddr {
76 type Output = Self;
77
78 fn bitand(self, rhs: Self) -> Self {
79 PAddr(self.0 & rhs.0)
80 }
81}
82
83impl ops::BitAnd<u32> for PAddr {
84 type Output = u32;
85
86 fn bitand(self, rhs: u32) -> Self::Output {
87 Into::<u32>::into(self) & rhs
88 }
89}
90
91impl ops::BitOr for PAddr {
92 type Output = PAddr;
93
94 fn bitor(self, rhs: PAddr) -> Self::Output {
95 PAddr(self.0 | rhs.0)
96 }
97}
98
99impl ops::BitOr<u32> for PAddr {
100 type Output = u32;
101
102 fn bitor(self, rhs: u32) -> Self::Output {
103 self.0 | rhs
104 }
105}
106
107impl fmt::LowerHex for PAddr {
108 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109 self.0.fmt(f)
110 }
111}
112
113#[repr(transparent)]
115#[derive(Clone, Copy)]
116pub struct PDEntry(pub u32);
117
118impl fmt::Debug for PDEntry {
119 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120 write!(f, "PDEntry {{ {:#x}, {:?} }}", self.address(), self.flags())
121 }
122}
123
124register_bitfields![u32,
125 pub PDFLAGS [
127 P OFFSET(0) NUMBITS(1),
129 RW OFFSET(1) NUMBITS(1),
131 US OFFSET(2) NUMBITS(1),
133 PWT OFFSET(3) NUMBITS(1),
135 PCD OFFSET(4) NUMBITS(1),
137 A OFFSET(5) NUMBITS(1),
139 D OFFSET(6) NUMBITS(1),
141 PS OFFSET(7) NUMBITS(1),
143 G OFFSET(8) NUMBITS(1),
145 PAT OFFSET(12) NUMBITS(1),
148 ],
149 pub PTFLAGS [
150 P OFFSET(0) NUMBITS(1),
152 RW OFFSET(1) NUMBITS(1),
154 US OFFSET(2) NUMBITS(1),
156 PWT OFFSET(3) NUMBITS(1),
158 PCD OFFSET(4) NUMBITS(1),
160 A OFFSET(5) NUMBITS(1),
162 D OFFSET(6) NUMBITS(1),
164 PAT OFFSET(7) NUMBITS(1),
167 G OFFSET(8) NUMBITS(1),
169 ],
170];
171
172pub type PDFlags = LocalRegisterCopy<u32, PDFLAGS::Register>;
173pub type PTFlags = LocalRegisterCopy<u32, PTFLAGS::Register>;
174
175const ADDRESS_MASK: u32 = !0xfff;
177const ADDRESS_MASK_PSE: u32 = !0x3fffff;
178
179pub const BASE_PAGE_SIZE: usize = 4096;
181
182pub const PAGE_SIZE_ENTRIES: usize = 1024;
184
185pub type PD = [PDEntry; PAGE_SIZE_ENTRIES];
187
188pub type PT = [PTEntry; PAGE_SIZE_ENTRIES];
190
191impl PDEntry {
192 pub fn new(pt: PAddr, flags: LocalRegisterCopy<u32, PDFLAGS::Register>) -> PDEntry {
203 let mask = if flags.is_set(PDFLAGS::PS) {
204 ADDRESS_MASK_PSE
205 } else {
206 ADDRESS_MASK
207 };
208 let pt_val = pt & mask;
209 assert!(pt_val == pt.into());
210 assert!(pt % BASE_PAGE_SIZE == 0);
211 PDEntry(pt_val | flags.get())
212 }
213
214 pub fn address(self) -> PAddr {
216 if self.flags().is_set(PDFLAGS::PS) {
217 PAddr::from(self.0 & ADDRESS_MASK_PSE)
218 } else {
219 PAddr::from(self.0 & ADDRESS_MASK)
220 }
221 }
222
223 pub fn flags(self) -> LocalRegisterCopy<u32, PDFLAGS::Register> {
225 LocalRegisterCopy::new(self.0)
226 }
227}
228
229#[repr(transparent)]
231#[derive(Clone, Copy)]
232pub struct PTEntry(pub u32);
233
234impl fmt::Debug for PTEntry {
235 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
236 write!(f, "PTEntry {{ {:#x}, {:?} }}", self.address(), self.flags())
237 }
238}
239
240impl PTEntry {
241 pub fn new(page: PAddr, flags: LocalRegisterCopy<u32, PTFLAGS::Register>) -> PTEntry {
248 let page_val = page & ADDRESS_MASK;
249 assert!(page_val == page.into());
250 assert!(page % BASE_PAGE_SIZE == 0);
251 PTEntry(page_val | flags.get())
252 }
253
254 pub fn address(self) -> PAddr {
256 PAddr::from(self.0 & ADDRESS_MASK)
257 }
258
259 pub fn flags(self) -> LocalRegisterCopy<u32, PTFLAGS::Register> {
261 LocalRegisterCopy::new(self.0)
262 }
263}