1use crate::Translation;
9use crate::paging::LEAF_LEVEL;
10use crate::paging::PAGE_SIZE;
11use crate::paging::PageTableWithLevel;
12
13use bitflags::bitflags;
14use core::fmt::{self, Debug, Display, Formatter};
15use core::ops::{Add, Sub};
16use core::sync::atomic::{AtomicUsize, Ordering};
17
18#[derive(Copy, Clone, Default, Eq, Ord, PartialEq, PartialOrd)]
20#[repr(transparent)]
21pub struct VirtualAddress(pub usize);
22
23impl Display for VirtualAddress {
24 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
25 write!(f, "{:#018x}", self.0)
26 }
27}
28
29impl Debug for VirtualAddress {
30 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
31 write!(f, "VirtualAddress({})", self)
32 }
33}
34
35impl Sub for VirtualAddress {
36 type Output = usize;
37
38 fn sub(self, other: Self) -> Self::Output {
39 self.0 - other.0
40 }
41}
42
43impl Add<usize> for VirtualAddress {
44 type Output = Self;
45
46 fn add(self, other: usize) -> Self {
47 Self(self.0 + other)
48 }
49}
50
51impl Sub<usize> for VirtualAddress {
52 type Output = Self;
53
54 fn sub(self, other: usize) -> Self {
55 Self(self.0 - other)
56 }
57}
58
59#[derive(Copy, Clone, Default, Eq, Ord, PartialEq, PartialOrd)]
62#[repr(transparent)]
63pub struct PhysicalAddress(pub usize);
64
65impl Display for PhysicalAddress {
66 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
67 write!(f, "{:#018x}", self.0)
68 }
69}
70
71impl Debug for PhysicalAddress {
72 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
73 write!(f, "PhysicalAddress({})", self)
74 }
75}
76
77impl Sub for PhysicalAddress {
78 type Output = usize;
79
80 fn sub(self, other: Self) -> Self::Output {
81 self.0 - other.0
82 }
83}
84
85impl Add<usize> for PhysicalAddress {
86 type Output = Self;
87
88 fn add(self, other: usize) -> Self {
89 Self(self.0 + other)
90 }
91}
92
93impl Sub<usize> for PhysicalAddress {
94 type Output = Self;
95
96 fn sub(self, other: usize) -> Self {
97 Self(self.0 - other)
98 }
99}
100
101bitflags! {
102 #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
104 pub struct Attributes: usize {
105 const VALID = 1 << 0;
106 const TABLE_OR_PAGE = 1 << 1;
107
108 const ATTRIBUTE_INDEX_0 = 0 << 2;
109 const ATTRIBUTE_INDEX_1 = 1 << 2;
110 const ATTRIBUTE_INDEX_2 = 2 << 2;
111 const ATTRIBUTE_INDEX_3 = 3 << 2;
112 const ATTRIBUTE_INDEX_4 = 4 << 2;
113 const ATTRIBUTE_INDEX_5 = 5 << 2;
114 const ATTRIBUTE_INDEX_6 = 6 << 2;
115 const ATTRIBUTE_INDEX_7 = 7 << 2;
116
117 const OUTER_SHAREABLE = 2 << 8;
118 const INNER_SHAREABLE = 3 << 8;
119
120 const NS = 1 << 5;
121 const USER = 1 << 6;
122 const READ_ONLY = 1 << 7;
123 const ACCESSED = 1 << 10;
124 const NON_GLOBAL = 1 << 11;
125 const GP = 1 << 50;
127 const DBM = 1 << 51;
128 const PXN = 1 << 53;
130 const UXN = 1 << 54;
133
134 const SWFLAG_0 = 1 << 55;
136 const SWFLAG_1 = 1 << 56;
137 const SWFLAG_2 = 1 << 57;
138 const SWFLAG_3 = 1 << 58;
139
140 const PXN_TABLE = 1 << 59;
141 const XN_TABLE = 1 << 60;
142 const AP_TABLE_NO_EL0 = 1 << 61;
143 const AP_TABLE_NO_WRITE = 1 << 62;
144 const NS_TABLE = 1 << 63;
145 }
146}
147
148impl Attributes {
149 pub const SHAREABILITY_MASK: Self = Self::INNER_SHAREABLE;
151
152 pub const ATTRIBUTE_INDEX_MASK: Self = Self::ATTRIBUTE_INDEX_7;
154}
155
156pub(crate) type DescriptorBits = usize;
157
158#[repr(C)]
166pub struct Descriptor(pub(crate) AtomicUsize);
167
168impl Descriptor {
169 pub const EMPTY: Self = Self(AtomicUsize::new(0));
171
172 const PHYSICAL_ADDRESS_BITMASK: usize = !(PAGE_SIZE - 1) & !(0xffff << 48);
173
174 pub(crate) fn bits(&self) -> DescriptorBits {
177 self.0.load(Ordering::Acquire)
178 }
179
180 pub fn output_address(&self) -> PhysicalAddress {
185 Self::output_address_from_bits(self.bits())
186 }
187
188 fn output_address_from_bits(bits: DescriptorBits) -> PhysicalAddress {
189 PhysicalAddress(bits & Self::PHYSICAL_ADDRESS_BITMASK)
190 }
191
192 fn flags_from_bits(bits: DescriptorBits) -> Attributes {
193 Attributes::from_bits_retain(bits & !Self::PHYSICAL_ADDRESS_BITMASK)
194 }
195
196 pub fn flags(&self) -> Attributes {
199 Self::flags_from_bits(self.bits())
200 }
201
202 pub fn is_valid(&self) -> bool {
204 (self.bits() & Attributes::VALID.bits()) != 0
205 }
206
207 pub fn is_table_or_page(&self) -> bool {
209 self.flags()
210 .contains(Attributes::TABLE_OR_PAGE | Attributes::VALID)
211 }
212
213 pub(crate) fn set(&mut self, pa: PhysicalAddress, flags: Attributes) {
214 self.0.store(
215 (pa.0 & Self::PHYSICAL_ADDRESS_BITMASK) | flags.bits(),
216 Ordering::Release,
217 );
218 }
219
220 pub(crate) fn subtable<T: Translation>(
221 &self,
222 translation: &T,
223 level: usize,
224 ) -> Option<PageTableWithLevel<T>> {
225 if level < LEAF_LEVEL && self.is_table_or_page() {
226 let output_address = self.output_address();
227 let table = translation.physical_to_virtual(output_address);
228 return Some(PageTableWithLevel::from_pointer(table, level + 1));
229 }
230 None
231 }
232}
233
234impl Debug for Descriptor {
235 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
236 write!(f, "{:#016x}", self.bits())?;
237 if self.is_valid() {
238 write!(f, " ({}, {:?})", self.output_address(), self.flags())?;
239 }
240 Ok(())
241 }
242}
243
244enum DescriptorEnum<'a> {
245 Active(&'a mut Descriptor),
248
249 Inactive(&'a mut Descriptor),
252
253 ActiveClone(DescriptorBits),
257}
258
259pub struct UpdatableDescriptor<'a> {
260 descriptor: DescriptorEnum<'a>,
261 level: usize,
262 updated: bool,
263}
264
265impl<'a> UpdatableDescriptor<'a> {
266 pub(crate) fn new(desc: &'a mut Descriptor, level: usize, live: bool) -> Self {
268 Self {
269 descriptor: if live {
270 DescriptorEnum::Active(desc)
271 } else {
272 DescriptorEnum::Inactive(desc)
273 },
274 level: level,
275 updated: false,
276 }
277 }
278
279 pub(crate) fn clone_from(d: &Descriptor, level: usize) -> Self {
282 Self {
283 descriptor: DescriptorEnum::ActiveClone(d.bits()),
284 level: level,
285 updated: false,
286 }
287 }
288
289 pub fn level(&self) -> usize {
291 self.level
292 }
293
294 pub fn updated(&self) -> bool {
296 self.updated
297 }
298
299 pub fn is_table(&self) -> bool {
302 self.level < 3 && self.flags().contains(Attributes::TABLE_OR_PAGE)
303 }
304
305 pub fn bits(&self) -> DescriptorBits {
307 match &self.descriptor {
308 DescriptorEnum::Active(d) | DescriptorEnum::Inactive(d) => d.bits(),
309 DescriptorEnum::ActiveClone(d) => *d,
310 }
311 }
312
313 pub fn set(&mut self, pa: PhysicalAddress, flags: Attributes) -> Result<(), ()> {
316 if !self.bbm_permits_update(pa, flags) {
317 return Err(());
318 }
319 let val = (pa.0 & Descriptor::PHYSICAL_ADDRESS_BITMASK) | flags.bits();
320 match &mut self.descriptor {
321 DescriptorEnum::Active(d) | DescriptorEnum::Inactive(d) => {
322 self.updated |= val != d.0.swap(val, Ordering::Release)
323 }
324 DescriptorEnum::ActiveClone(d) => {
325 self.updated |= *d != val;
326 *d = val
327 }
328 };
329 Ok(())
330 }
331
332 pub fn output_address(&self) -> PhysicalAddress {
337 Descriptor::output_address_from_bits(self.bits())
338 }
339
340 pub fn flags(&self) -> Attributes {
342 Descriptor::flags_from_bits(self.bits())
343 }
344
345 fn is_live_and_valid(&self) -> bool {
349 match &self.descriptor {
350 DescriptorEnum::Inactive(_) => false,
351 _ => self.flags().contains(Attributes::VALID),
352 }
353 }
354
355 fn bbm_permits_update(&self, pa: PhysicalAddress, flags: Attributes) -> bool {
357 if !self.is_live_and_valid() || !flags.contains(Attributes::VALID) {
358 return true;
359 }
360
361 if pa != self.output_address() {
363 return false;
364 }
365
366 let clear_allowed_mask = Attributes::VALID
368 | Attributes::READ_ONLY
369 | Attributes::ACCESSED
370 | Attributes::DBM
371 | Attributes::PXN
372 | Attributes::UXN
373 | Attributes::SWFLAG_0
374 | Attributes::SWFLAG_1
375 | Attributes::SWFLAG_2
376 | Attributes::SWFLAG_3;
377 let set_allowed_mask = clear_allowed_mask | Attributes::NON_GLOBAL;
378
379 (!self.flags() & flags & !set_allowed_mask).is_empty()
380 && (self.flags() & !flags & !clear_allowed_mask).is_empty()
381 }
382
383 pub fn modify_flags(&mut self, set: Attributes, clear: Attributes) -> Result<(), ()> {
385 let oldval = self.flags();
386 let flags = (oldval | set) & !clear;
387
388 if (oldval ^ flags).contains(Attributes::TABLE_OR_PAGE) {
389 return Err(());
393 }
394 let oa = self.output_address();
395 self.set(oa, flags)
396 }
397}