blob: 0731856e46227e001c86f95e7948bf496ea9b565 [file] [log] [blame]
Imre Kis703482d2023-11-30 15:51:26 +01001// SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Memory descriptor
5
6use packed_struct::prelude::*;
7
8use core::cell::UnsafeCell;
9use core::ptr;
10
11use crate::kernel_space::KernelSpace;
12use crate::MemoryAttributesIndex;
13
Imre Kisd5b96fd2024-09-11 17:04:32 +020014use super::address::PhysicalAddress;
Imre Kis631127d2024-11-21 13:09:01 +010015use super::TranslationGranule;
Imre Kisd5b96fd2024-09-11 17:04:32 +020016
Imre Kis703482d2023-11-30 15:51:26 +010017/// Memory shareability
18#[derive(PrimitiveEnum_u8, Clone, Copy, Debug, PartialEq, Eq, Default)]
19pub enum Shareability {
20 #[default]
21 NonShareable = 0b00,
22 Outer = 0b10,
23 Inner = 0b11,
24}
25
26/// Data access permission
27#[derive(PrimitiveEnum_u8, Clone, Copy, Debug, PartialEq, Eq, Default)]
28pub enum DataAccessPermissions {
29 #[default]
30 ReadWrite_None = 0b00,
31 ReadWrite_ReadWrite = 0b01,
32 ReadOnly_None = 0b10,
33 ReadOnly_ReadOnly = 0b11,
34}
35
36/// Memory attributes
37#[derive(PackedStruct, Clone, Debug, PartialEq, Eq, Default)]
38#[packed_struct(size_bytes = "8", bit_numbering = "lsb0")]
39pub struct Attributes {
40 #[packed_field(bits = "54")]
41 pub uxn: bool,
42 #[packed_field(bits = "53")]
43 pub pxn: bool,
44 #[packed_field(bits = "52")]
45 pub contiguous: bool,
46 #[packed_field(bits = "11")]
47 pub not_global: bool,
48 #[packed_field(bits = "10")]
49 pub access_flag: bool,
50 #[packed_field(bits = "9..=8", ty = "enum")]
51 pub shareability: Shareability,
52 #[packed_field(bits = "7..=6", ty = "enum")]
53 pub data_access_permissions: DataAccessPermissions,
54 #[packed_field(bits = "5")]
55 pub non_secure: bool,
56 #[packed_field(bits = "4..=2", ty = "enum")]
57 pub mem_attr_index: MemoryAttributesIndex,
58}
59
60impl From<Attributes> for u64 {
61 fn from(attributes: Attributes) -> Self {
62 u64::from_be_bytes(attributes.pack().unwrap())
63 }
64}
65
66impl From<u64> for Attributes {
67 fn from(bits: u64) -> Self {
68 Self::unpack(&bits.to_be_bytes()).unwrap()
69 }
70}
71
72/// Next level attributes
73#[derive(PackedStruct, Clone, Debug, PartialEq, Eq, Default)]
74#[packed_struct(size_bytes = "8", bit_numbering = "lsb0")]
75pub struct NextLevelAttributes {
76 #[packed_field(bits = "63")]
77 ns_table: bool,
78 #[packed_field(bits = "62..=61")]
79 ap_table: Integer<u8, packed_bits::Bits<2>>,
80 #[packed_field(bits = "60")]
81 xn_table: bool,
82 #[packed_field(bits = "59")]
83 pxn_table: bool,
84}
85
86impl From<NextLevelAttributes> for u64 {
87 fn from(attributes: NextLevelAttributes) -> Self {
88 u64::from_be_bytes(attributes.pack().unwrap())
89 }
90}
91
92impl From<u64> for NextLevelAttributes {
93 fn from(bits: u64) -> Self {
94 Self::unpack(&bits.to_be_bytes()).unwrap()
95 }
96}
97
98/// Memory descriptor type
99#[derive(PartialEq, Eq, Debug)]
100pub enum DescriptorType {
101 Invalid,
102 Block,
103 Table,
104}
105
106/// Memory descriptor of a memory translation table
107#[repr(C)]
Imre Kisf5f6fa72024-04-18 14:04:21 +0200108#[derive(Default)]
Imre Kis703482d2023-11-30 15:51:26 +0100109pub struct Descriptor {
110 cell: UnsafeCell<u64>,
111}
112
113impl Descriptor {
114 const ATTR_MASK: u64 = 0xfff8_0000_0000_0ffc;
115 const DESCRIPTOR_TYPE_MASK: u64 = 0b11;
Imre Kis703482d2023-11-30 15:51:26 +0100116 const INVALID_DESCRIPTOR_VALUE: u64 = 0x0;
117 const NEXT_ATTR_MASK: u64 = 0xf800_0000_0000_0000;
Imre Kis703482d2023-11-30 15:51:26 +0100118 const TABLE_BIT: u64 = 0b10;
Imre Kis703482d2023-11-30 15:51:26 +0100119 const TA_MASK: u64 = 0x0000_ffff_ffff_f000;
120 const VALID_BIT: u64 = 0b01;
121
122 /// Query descriptor type
Imre Kis631127d2024-11-21 13:09:01 +0100123 pub fn get_descriptor_type(&self, level: isize) -> DescriptorType {
Imre Kis703482d2023-11-30 15:51:26 +0100124 assert!(level <= 3);
125
Imre Kisf5f6fa72024-04-18 14:04:21 +0200126 let desc_type_bits = self.get() & Self::DESCRIPTOR_TYPE_MASK;
Imre Kis703482d2023-11-30 15:51:26 +0100127 if desc_type_bits & Self::VALID_BIT != 0 {
128 if level == 3 {
129 assert_eq!(Self::TABLE_BIT, desc_type_bits & Self::TABLE_BIT);
130 DescriptorType::Block
131 } else if desc_type_bits & Self::TABLE_BIT != 0 {
132 DescriptorType::Table
133 } else {
134 DescriptorType::Block
135 }
136 } else {
137 DescriptorType::Invalid
138 }
139 }
140
141 // Invalid descriptor functions
142
143 /// Check if it is a valid descriptor
144 pub fn is_valid(&self) -> bool {
Imre Kisf5f6fa72024-04-18 14:04:21 +0200145 self.get() & Self::VALID_BIT != 0
Imre Kis703482d2023-11-30 15:51:26 +0100146 }
147
148 // Block descriptor functions
149
150 /// Set block descriptor
Imre Kis631127d2024-11-21 13:09:01 +0100151 pub fn set_block_descriptor<const VA_BITS: usize>(
Imre Kis703482d2023-11-30 15:51:26 +0100152 &mut self,
Imre Kis631127d2024-11-21 13:09:01 +0100153 granule: TranslationGranule<VA_BITS>,
154 level: isize,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200155 output_address: PhysicalAddress,
Imre Kis703482d2023-11-30 15:51:26 +0100156 attributes: Attributes,
157 ) {
158 let attr: u64 = attributes.into();
159
160 assert!(level <= 3);
161 assert!(self.get_descriptor_type(level) != DescriptorType::Table);
Imre Kis703482d2023-11-30 15:51:26 +0100162 assert_eq!(0, attr & !Self::ATTR_MASK);
163
Imre Kis631127d2024-11-21 13:09:01 +0100164 let oa_granule_mask = !(granule.block_size_at_level(level) - 1);
165
166 // Figure D8-14 VMSAv8-64 Block descriptor formats
167 let oa_bits = match granule {
168 // 4KB and 16KB granules, 52-bit OA
169 #[cfg(feature = "feat_lpa2")]
170 TranslationGranule::Granule4k | TranslationGranule::Granule16k => {
171 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_f000;
172 assert_eq!(0, output_address.0 & !oa_mask);
173
174 let address = output_address.0 & oa_mask;
175
176 // OA[49:n] remains in place, OA[51:50] is mapped to [9:8]
177 let lsbs = address & 0x0003_ffff_ffff_f000;
178 let msbs = ((address >> 50) & 0x3) << 8;
179
180 lsbs | msbs
181 }
182
183 // 64KB granule, 52-bit OA
184 #[cfg(feature = "feat_lpa")]
185 TranslationGranule::Granule64k => {
186 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_0000;
187 assert_eq!(0, output_address.0 & !oa_mask);
188
189 let address = output_address.0 & oa_mask;
190
191 // OA[47:n] remains in place, OA[51:48] is mapped to [15:12]
192 let lsbs = address & 0x0000_ffff_ffff_0000;
193 let msbs = ((address >> 48) & 0xf) << 12;
194
195 lsbs | msbs
196 }
197
198 // 4KB, 16KB, and 64KB granules, 48-bit OA
199 #[cfg(not(all(feature = "feat_lpa", feature = "feat_lpa2")))]
200 _ => {
201 let oa_mask = oa_granule_mask & 0x0000_ffff_ffff_f000;
202 assert_eq!(0, output_address.0 & !oa_mask);
203 output_address.0 & oa_mask
204 }
205 };
206
Imre Kis703482d2023-11-30 15:51:26 +0100207 let table_bit = if level < 3 { 0 } else { Self::TABLE_BIT };
208
Imre Kis631127d2024-11-21 13:09:01 +0100209 self.set(Self::VALID_BIT | table_bit | oa_bits as u64 | attr);
Imre Kis703482d2023-11-30 15:51:26 +0100210 }
211
212 /// Get output address from the block descriptor
Imre Kis631127d2024-11-21 13:09:01 +0100213 pub fn get_block_output_address<const VA_BITS: usize>(
214 &self,
215 granule: TranslationGranule<VA_BITS>,
216 level: isize,
217 ) -> PhysicalAddress {
Imre Kis703482d2023-11-30 15:51:26 +0100218 assert!(level <= 3);
219 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
220
Imre Kis631127d2024-11-21 13:09:01 +0100221 let oa_granule_mask = !(granule.block_size_at_level(level) - 1);
222 let descriptor_value = self.get();
223
224 // Figure D8-14 VMSAv8-64 Block descriptor formats
225 let pa = match granule {
226 // 4KB and 16KB granules, 52-bit OA
227 #[cfg(feature = "feat_lpa2")]
228 TranslationGranule::Granule4k | TranslationGranule::Granule16k => {
229 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_f000;
230
231 // OA[49:n] remains in place, OA[51:50] is mapped from [9:8]
232 let lsbs = descriptor_value & 0x0003_ffff_ffff_f000;
233 let msbs = ((descriptor_value >> 8) & 0x3) << 50;
234
235 (lsbs | msbs) as usize & oa_mask
236 }
237
238 // 64KB granule, 52-bit OA
239 #[cfg(feature = "feat_lpa")]
240 TranslationGranule::Granule64k => {
241 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_0000;
242
243 // OA[47:n] remains in place, OA[51:48] is mapped from [15:12]
244 let lsbs = descriptor_value & 0x0003_ffff_ffff_0000;
245 let msbs = ((descriptor_value >> 12) & 0xf) << 48;
246
247 (lsbs | msbs) as usize & oa_mask
248 }
249
250 // 4KB, 16KB, and 64KB granules, 48-bit OA
251 #[cfg(not(all(feature = "feat_lpa", feature = "feat_lpa2")))]
252 _ => {
253 let oa_mask = oa_granule_mask & 0x0000_ffff_ffff_f000;
254 descriptor_value as usize & oa_mask
255 }
256 };
257
258 PhysicalAddress(pa)
Imre Kis703482d2023-11-30 15:51:26 +0100259 }
260
261 /// Set the attributes of the block descriptor
Imre Kis631127d2024-11-21 13:09:01 +0100262 pub fn set_block_attributes(&mut self, level: isize, attributes: Attributes) {
Imre Kis703482d2023-11-30 15:51:26 +0100263 assert!(level <= 3);
264 let attr: u64 = attributes.into();
265 assert_eq!(0, attr & !Self::ATTR_MASK);
266 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
267
Imre Kisf5f6fa72024-04-18 14:04:21 +0200268 self.modify(|d| (d & !Self::ATTR_MASK) | attr);
Imre Kis703482d2023-11-30 15:51:26 +0100269 }
270
271 /// Get the attributes of the block descriptor
Imre Kis631127d2024-11-21 13:09:01 +0100272 pub fn get_block_attributes(&self, level: isize) -> Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100273 assert!(level <= 3);
274 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
275
Imre Kisf5f6fa72024-04-18 14:04:21 +0200276 Attributes::from(self.get() & Self::ATTR_MASK)
Imre Kis703482d2023-11-30 15:51:26 +0100277 }
278
279 /// Set block descriptor to invalid
Imre Kis631127d2024-11-21 13:09:01 +0100280 pub fn set_block_descriptor_to_invalid(&mut self, level: isize) {
Imre Kis703482d2023-11-30 15:51:26 +0100281 assert!(level <= 3);
282 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
283
Imre Kisf5f6fa72024-04-18 14:04:21 +0200284 self.set(Self::INVALID_DESCRIPTOR_VALUE)
Imre Kis703482d2023-11-30 15:51:26 +0100285 }
286
Imre Kis9a9d0492024-10-31 15:19:46 +0100287 /// Set block or invalid descriptor to invalid
Imre Kis631127d2024-11-21 13:09:01 +0100288 pub fn set_block_or_invalid_descriptor_to_invalid(&mut self, level: isize) {
Imre Kis9a9d0492024-10-31 15:19:46 +0100289 assert!(level <= 3);
290 assert!(DescriptorType::Table != self.get_descriptor_type(level));
291
292 self.set(Self::INVALID_DESCRIPTOR_VALUE)
293 }
294
Imre Kis703482d2023-11-30 15:51:26 +0100295 /// Set table descriptor
296 ///
Imre Kis9a9d0492024-10-31 15:19:46 +0100297 /// Safety: The caller has to ensure that the passed next level table has the same life as
Imre Kis703482d2023-11-30 15:51:26 +0100298 /// the descriptor.
299 pub unsafe fn set_table_descriptor(
300 &mut self,
Imre Kis631127d2024-11-21 13:09:01 +0100301 level: isize,
Imre Kis703482d2023-11-30 15:51:26 +0100302 next_level_table: &mut [Descriptor],
303 next_level_attributes: Option<NextLevelAttributes>,
304 ) {
305 assert!(level <= 2);
Imre Kis703482d2023-11-30 15:51:26 +0100306 assert!(self.get_descriptor_type(level) != DescriptorType::Table);
307
308 let table_addr = KernelSpace::kernel_to_pa(next_level_table.as_ptr() as u64);
309 assert_eq!(0, table_addr & !Self::TA_MASK);
310
311 let mut raw_desc_value = Self::VALID_BIT | Self::TABLE_BIT | table_addr;
312
313 if let Some(next_attr) = next_level_attributes {
314 let next_attr_bits: u64 = next_attr.into();
315 assert_eq!(0, next_attr_bits & !Self::NEXT_ATTR_MASK);
316 raw_desc_value |= next_attr_bits;
317 }
318
319 self.set(raw_desc_value);
320 }
321
322 /// Get next level table
323 ///
Imre Kis9a9d0492024-10-31 15:19:46 +0100324 /// Safety: The returned next level table is based on the address read from the descriptor.
Imre Kis703482d2023-11-30 15:51:26 +0100325 /// The caller has to ensure that no other references are being used of the table.
Imre Kis631127d2024-11-21 13:09:01 +0100326 pub unsafe fn get_next_level_table<const VA_BITS: usize>(
327 &self,
328 granule: TranslationGranule<VA_BITS>,
329 level: isize,
330 ) -> &[Descriptor] {
Imre Kis703482d2023-11-30 15:51:26 +0100331 assert!(level <= 2);
332 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
333
334 let table_address =
335 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *const Descriptor;
Imre Kis631127d2024-11-21 13:09:01 +0100336 core::slice::from_raw_parts(table_address, granule.entry_count_at_level(level + 1))
Imre Kis703482d2023-11-30 15:51:26 +0100337 }
338
339 /// Get mutable next level table
340 ///
Imre Kis9a9d0492024-10-31 15:19:46 +0100341 /// Safety: The returned next level table is based on the address read from the descriptor.
Imre Kis703482d2023-11-30 15:51:26 +0100342 /// The caller has to ensure that no other references are being used of the table.
Imre Kis631127d2024-11-21 13:09:01 +0100343 pub unsafe fn get_next_level_table_mut<const VA_BITS: usize>(
344 &mut self,
345 granule: TranslationGranule<VA_BITS>,
346 level: isize,
347 ) -> &mut [Descriptor] {
Imre Kis703482d2023-11-30 15:51:26 +0100348 assert!(level <= 2);
349 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
350
351 let table_address =
352 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *mut Descriptor;
Imre Kis631127d2024-11-21 13:09:01 +0100353 core::slice::from_raw_parts_mut(table_address, granule.entry_count_at_level(level + 1))
Imre Kis703482d2023-11-30 15:51:26 +0100354 }
355
356 /// Get next level attributes
Imre Kis631127d2024-11-21 13:09:01 +0100357 pub fn get_next_level_attributes(&self, level: isize) -> NextLevelAttributes {
Imre Kis703482d2023-11-30 15:51:26 +0100358 assert!(level <= 2);
359 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
360
Imre Kisf5f6fa72024-04-18 14:04:21 +0200361 NextLevelAttributes::from(self.get() & Self::NEXT_ATTR_MASK)
Imre Kis703482d2023-11-30 15:51:26 +0100362 }
363
364 /// Set table descriptor to invalid
365 ///
366 /// **Unsafe:** The returned descriptor reference must be released by the caller, i.e. release
367 /// to `PagePool`
Imre Kis631127d2024-11-21 13:09:01 +0100368 pub unsafe fn set_table_descriptor_to_invalid<const VA_BITS: usize>(
369 &mut self,
370 granule: TranslationGranule<VA_BITS>,
371 level: isize,
372 ) -> &mut [Descriptor] {
Imre Kis703482d2023-11-30 15:51:26 +0100373 assert!(level <= 2);
374 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
375
376 let table_address =
377 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *mut Descriptor;
378 self.set(Self::INVALID_DESCRIPTOR_VALUE);
Imre Kis631127d2024-11-21 13:09:01 +0100379 core::slice::from_raw_parts_mut(table_address, granule.entry_count_at_level(level + 1))
Imre Kis703482d2023-11-30 15:51:26 +0100380 }
381
382 /// Get raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200383 fn get(&self) -> u64 {
384 unsafe { ptr::read_volatile(self.cell.get()) }
Imre Kis703482d2023-11-30 15:51:26 +0100385 }
386
387 /// Set raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200388 fn set(&mut self, value: u64) {
Imre Kis9a9d0492024-10-31 15:19:46 +0100389 // Safety: The cell should point to a valid address and the assembly code is just a data
390 // barrier.
391 unsafe {
392 ptr::write_volatile(self.cell.get(), value);
393 #[cfg(target_arch = "aarch64")]
394 core::arch::asm!("dsb nsh");
395 }
Imre Kis703482d2023-11-30 15:51:26 +0100396 }
397
398 /// Modify raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200399 fn modify<F>(&mut self, f: F)
Imre Kis703482d2023-11-30 15:51:26 +0100400 where
401 F: Fn(u64) -> u64,
402 {
403 self.set(f(self.get()))
404 }
Imre Kis703482d2023-11-30 15:51:26 +0100405}
406
Imre Kis42935a22024-10-17 11:30:16 +0200407#[cfg(test)]
408mod tests {
409 use super::*;
Imre Kis703482d2023-11-30 15:51:26 +0100410
Imre Kis42935a22024-10-17 11:30:16 +0200411 #[test]
412 fn test_attributes() {
413 let attributes = Attributes::default();
414 assert_eq!(0u64, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100415
Imre Kis42935a22024-10-17 11:30:16 +0200416 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100417 uxn: true,
418 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200419 };
420 assert_eq!(1u64 << 54, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100421
Imre Kis42935a22024-10-17 11:30:16 +0200422 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100423 pxn: true,
424 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200425 };
426 assert_eq!(1u64 << 53, attributes.into());
427
428 let attributes = Attributes {
429 contiguous: true,
Imre Kis703482d2023-11-30 15:51:26 +0100430 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200431 };
432 assert_eq!(1u64 << 52, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100433
Imre Kis42935a22024-10-17 11:30:16 +0200434 let attributes = Attributes {
435 not_global: true,
436 ..Default::default()
437 };
438 assert_eq!(1u64 << 11, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100439
Imre Kis42935a22024-10-17 11:30:16 +0200440 let attributes = Attributes {
441 access_flag: true,
442 ..Default::default()
443 };
444 assert_eq!(1u64 << 10, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100445
Imre Kis42935a22024-10-17 11:30:16 +0200446 let attributes = Attributes {
447 non_secure: true,
448 ..Default::default()
449 };
450 assert_eq!(1u64 << 5, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100451
Imre Kis42935a22024-10-17 11:30:16 +0200452 let attributes = Attributes {
453 mem_attr_index: MemoryAttributesIndex::Normal_IWBWA_OWBWA,
454 ..Default::default()
455 };
456 assert_eq!(
457 (MemoryAttributesIndex::Normal_IWBWA_OWBWA as u64) << 2,
458 attributes.into()
459 );
Imre Kis703482d2023-11-30 15:51:26 +0100460
Imre Kis42935a22024-10-17 11:30:16 +0200461 let attributes: Attributes = 0.into();
462 assert!(!attributes.uxn);
463 assert!(!attributes.pxn);
464 assert!(!attributes.contiguous);
465 assert!(!attributes.not_global);
466 assert!(!attributes.access_flag);
467 assert_eq!(Shareability::NonShareable, attributes.shareability);
468 assert_eq!(
469 DataAccessPermissions::ReadWrite_None,
470 attributes.data_access_permissions
471 );
472 assert!(!attributes.non_secure);
473 assert_eq!(
474 MemoryAttributesIndex::Device_nGnRnE,
475 attributes.mem_attr_index
Imre Kis703482d2023-11-30 15:51:26 +0100476 );
477 }
Imre Kis703482d2023-11-30 15:51:26 +0100478
Imre Kis42935a22024-10-17 11:30:16 +0200479 #[test]
480 fn test_next_level_attributes() {
481 let next_level_attributes = NextLevelAttributes::default();
482 assert_eq!(0u64, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100483
Imre Kis42935a22024-10-17 11:30:16 +0200484 let next_level_attributes = NextLevelAttributes {
Imre Kis703482d2023-11-30 15:51:26 +0100485 ns_table: true,
486 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200487 };
488 assert_eq!(1u64 << 63, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100489
Imre Kis42935a22024-10-17 11:30:16 +0200490 let next_level_attributes = NextLevelAttributes {
491 ap_table: 3.into(),
492 ..Default::default()
493 };
494 assert_eq!(3u64 << 61, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100495
Imre Kis42935a22024-10-17 11:30:16 +0200496 let next_level_attributes = NextLevelAttributes {
497 xn_table: true,
498 ..Default::default()
499 };
500 assert_eq!(1u64 << 60, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100501
Imre Kis42935a22024-10-17 11:30:16 +0200502 let next_level_attributes = NextLevelAttributes {
503 pxn_table: true,
504 ..Default::default()
505 };
506 assert_eq!(1u64 << 59, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100507
Imre Kis42935a22024-10-17 11:30:16 +0200508 let next_level_attributes: NextLevelAttributes = 0.into();
509 assert!(!next_level_attributes.ns_table);
510 assert_eq!(0u8, next_level_attributes.ap_table.into());
511 assert!(!next_level_attributes.xn_table);
512 assert!(!next_level_attributes.pxn_table);
Imre Kis703482d2023-11-30 15:51:26 +0100513
Imre Kis42935a22024-10-17 11:30:16 +0200514 let next_level_attributes: NextLevelAttributes = u64::MAX.into();
515 assert!(next_level_attributes.ns_table);
516 assert_eq!(3u8, next_level_attributes.ap_table.into());
517 assert!(next_level_attributes.xn_table);
518 assert!(next_level_attributes.pxn_table);
519 }
Imre Kis703482d2023-11-30 15:51:26 +0100520
Imre Kis42935a22024-10-17 11:30:16 +0200521 #[test]
522 fn test_descriptor_get_type() {
523 let descriptor = Descriptor {
524 cell: UnsafeCell::new(0),
525 };
526 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(1));
527
528 let descriptor = Descriptor {
529 cell: UnsafeCell::new(1),
530 };
531 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(1));
532
533 let descriptor = Descriptor {
534 cell: UnsafeCell::new(3),
535 };
536 assert_eq!(DescriptorType::Table, descriptor.get_descriptor_type(1));
537
538 let descriptor = Descriptor {
539 cell: UnsafeCell::new(0),
540 };
541 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(3));
542
543 let descriptor = Descriptor {
544 cell: UnsafeCell::new(3),
545 };
546 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(3));
547 }
548
549 #[test]
550 fn test_descriptor_is_valid() {
551 let descriptor = Descriptor {
552 cell: UnsafeCell::new(0),
553 };
554 assert!(!descriptor.is_valid());
555
556 let descriptor = Descriptor {
557 cell: UnsafeCell::new(1),
558 };
559 assert!(descriptor.is_valid());
560 }
561
562 #[test]
563 fn test_descriptor_set_block_to_block_again() {
564 let mut descriptor = Descriptor {
565 cell: UnsafeCell::new(1),
566 };
567
Imre Kis631127d2024-11-21 13:09:01 +0100568 descriptor.set_block_descriptor::<48>(
569 TranslationGranule::Granule4k,
570 1,
571 PhysicalAddress(0),
572 Attributes::default(),
573 );
Imre Kis42935a22024-10-17 11:30:16 +0200574 assert_eq!(0x1, descriptor.get());
575 }
576
577 #[test]
578 #[should_panic]
579 fn test_descriptor_set_block_invalid_oa() {
580 let mut descriptor = Descriptor {
581 cell: UnsafeCell::new(0),
582 };
583
Imre Kis631127d2024-11-21 13:09:01 +0100584 descriptor.set_block_descriptor::<48>(
585 TranslationGranule::Granule4k,
586 1,
587 PhysicalAddress(1 << 63),
588 Attributes::default(),
589 );
Imre Kis42935a22024-10-17 11:30:16 +0200590 }
591
592 #[test]
593 fn test_descriptor_block() {
Imre Kis631127d2024-11-21 13:09:01 +0100594 let granule: TranslationGranule<48> = TranslationGranule::Granule4k;
Imre Kis42935a22024-10-17 11:30:16 +0200595 let mut descriptor = Descriptor {
596 cell: UnsafeCell::new(0),
597 };
598
599 descriptor.set_block_descriptor(
Imre Kis631127d2024-11-21 13:09:01 +0100600 granule,
Imre Kis42935a22024-10-17 11:30:16 +0200601 1,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200602 PhysicalAddress(0x0000000f_c0000000),
Imre Kis42935a22024-10-17 11:30:16 +0200603 Attributes {
604 uxn: true,
605 ..Default::default()
606 },
607 );
608 assert_eq!(0x0040000f_c0000001, descriptor.get());
609
610 let mut descriptor = Descriptor {
611 cell: UnsafeCell::new(0),
612 };
613
614 descriptor.set_block_descriptor(
Imre Kis631127d2024-11-21 13:09:01 +0100615 granule,
Imre Kis42935a22024-10-17 11:30:16 +0200616 3,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200617 PhysicalAddress(0x0000000f_fffff000),
Imre Kis42935a22024-10-17 11:30:16 +0200618 Attributes {
619 uxn: true,
620 ..Default::default()
621 },
622 );
623 assert_eq!(0x0040000f_fffff003, descriptor.get());
624
Imre Kisd5b96fd2024-09-11 17:04:32 +0200625 assert_eq!(
626 PhysicalAddress(0x0000000f_fffff000),
Imre Kis631127d2024-11-21 13:09:01 +0100627 descriptor.get_block_output_address(granule, 3)
Imre Kisd5b96fd2024-09-11 17:04:32 +0200628 );
Imre Kis42935a22024-10-17 11:30:16 +0200629 assert_eq!(
630 Attributes {
631 uxn: true,
632 ..Default::default()
633 },
634 descriptor.get_block_attributes(3)
635 );
636
637 descriptor.set_block_attributes(
638 3,
639 Attributes {
640 pxn: true,
641 ..Default::default()
642 },
643 );
644 assert_eq!(
645 Attributes {
646 pxn: true,
647 ..Default::default()
648 },
649 descriptor.get_block_attributes(3)
650 );
651 }
652
653 #[test]
654 #[should_panic]
655 fn test_descriptor_invalid_block_to_invalid() {
656 let mut descriptor = Descriptor {
657 cell: UnsafeCell::new(0),
658 };
659
660 descriptor.set_block_descriptor_to_invalid(0);
661 }
662
663 #[test]
664 fn test_descriptor_block_to_invalid() {
665 let mut descriptor = Descriptor {
666 cell: UnsafeCell::new(3),
667 };
668
669 descriptor.set_block_descriptor_to_invalid(3);
670 assert_eq!(0, descriptor.get());
671 }
672
673 #[test]
Imre Kis9a9d0492024-10-31 15:19:46 +0100674 fn test_descriptor_block_or_invalid_block_to_invalid() {
675 let mut descriptor = Descriptor {
676 cell: UnsafeCell::new(0),
677 };
678
679 descriptor.set_block_or_invalid_descriptor_to_invalid(0);
680 assert_eq!(0, descriptor.get());
681
682 let mut descriptor = Descriptor {
683 cell: UnsafeCell::new(3),
684 };
685
686 descriptor.set_block_or_invalid_descriptor_to_invalid(3);
687 assert_eq!(0, descriptor.get());
688 }
689
690 #[test]
Imre Kis42935a22024-10-17 11:30:16 +0200691 #[should_panic]
692 fn test_descriptor_level3_to_table() {
693 let mut next_level_table = [Descriptor {
694 cell: UnsafeCell::new(0),
695 }];
696 let mut descriptor = Descriptor {
697 cell: UnsafeCell::new(0),
698 };
699
700 unsafe {
701 descriptor.set_table_descriptor(3, &mut next_level_table, None);
702 }
703 }
704
705 #[test]
706 fn test_descriptor_block_to_table() {
707 let next_level_table =
708 unsafe { core::slice::from_raw_parts_mut(0x1000 as *mut Descriptor, 512) };
709 let mut descriptor = Descriptor {
710 cell: UnsafeCell::new(1),
711 };
712
713 unsafe {
714 descriptor.set_table_descriptor(0, next_level_table, None);
715 }
716 assert_eq!(0x1003, descriptor.get());
717 }
718
719 #[test]
720 #[should_panic]
721 fn test_descriptor_table_invalid_count() {
722 let next_level_table =
723 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 511) };
724 let mut descriptor = Descriptor {
725 cell: UnsafeCell::new(0),
726 };
727
728 unsafe {
729 descriptor.set_table_descriptor(0, next_level_table, None);
730 }
731 }
732
733 #[test]
734 #[should_panic]
735 fn test_descriptor_table_non_aligned() {
736 let next_level_table =
737 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 512) };
738 let mut descriptor = Descriptor {
739 cell: UnsafeCell::new(0),
740 };
741
742 unsafe {
743 descriptor.set_table_descriptor(0, next_level_table, None);
744 }
745 }
746
747 #[test]
748 fn test_descriptor_table() {
749 let next_level_table = unsafe {
750 core::slice::from_raw_parts_mut(0x0000_000c_ba98_7000 as *mut Descriptor, 512)
751 };
752 let mut descriptor = Descriptor {
753 cell: UnsafeCell::new(0),
754 };
755
756 unsafe {
757 descriptor.set_table_descriptor(0, next_level_table, None);
758 }
759 assert_eq!(0x0000_000c_ba98_7003, descriptor.get());
760 }
761
762 #[test]
763 fn test_descriptor_table_next_level_attr() {
764 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
765 let next_level_table =
766 unsafe { core::slice::from_raw_parts_mut(NEXT_LEVEL_ADDR as *mut Descriptor, 512) };
767 let mut descriptor = Descriptor {
768 cell: UnsafeCell::new(0),
769 };
770
771 unsafe {
772 descriptor.set_table_descriptor(
773 0,
774 next_level_table,
775 Some(NextLevelAttributes {
776 ns_table: true,
777 ..Default::default()
778 }),
779 );
780 }
781 assert_eq!(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003, descriptor.get());
782 }
783
784 #[test]
785 fn test_descriptor_table_get_next_level_table() {
786 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
787 let descriptor = Descriptor {
788 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
789 };
790 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
Imre Kis631127d2024-11-21 13:09:01 +0100791 descriptor
792 .get_next_level_table::<36>(TranslationGranule::Granule4k, 0)
793 .as_ptr() as u64
Imre Kis42935a22024-10-17 11:30:16 +0200794 });
795 }
796
797 #[test]
798 fn test_descriptor_table_get_next_level_table_mut() {
799 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
800 let mut descriptor = Descriptor {
801 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
802 };
803 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
Imre Kis631127d2024-11-21 13:09:01 +0100804 descriptor
805 .get_next_level_table_mut::<36>(TranslationGranule::Granule4k, 0)
806 .as_ptr() as *mut Descriptor as u64
Imre Kis42935a22024-10-17 11:30:16 +0200807 });
808 }
809
810 #[test]
811 fn test_descriptor_table_get_next_level_attr() {
812 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
813 let descriptor = Descriptor {
814 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
815 };
816 assert_eq!(
817 NextLevelAttributes {
818 ns_table: true,
819 ..Default::default()
820 },
821 descriptor.get_next_level_attributes(0)
822 );
823 }
824
825 #[test]
826 fn test_descriptor_table_set_to_invalid() {
827 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
828 let mut descriptor = Descriptor {
829 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
830 };
831 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
Imre Kis631127d2024-11-21 13:09:01 +0100832 descriptor
833 .set_table_descriptor_to_invalid::<36>(TranslationGranule::Granule4k, 0)
834 .as_ptr() as *mut Descriptor as u64
Imre Kis42935a22024-10-17 11:30:16 +0200835 });
836 assert_eq!(0, descriptor.get());
837 }
838
839 #[test]
840 fn test_descriptor_raw_interface() {
841 let cell_value = 0x01234567_89abcdefu64;
842 let cell_new_value = 0x12345678_9abcdef0u64;
843
844 let mut descriptor = Descriptor {
845 cell: UnsafeCell::new(cell_value),
846 };
847
848 assert_eq!(cell_value, descriptor.get());
849
850 descriptor.set(cell_new_value);
851 assert_eq!(cell_new_value, descriptor.get());
852
853 descriptor.modify(|d| d + 1);
854 assert_eq!(cell_new_value + 1, descriptor.get());
855 }
Imre Kis703482d2023-11-30 15:51:26 +0100856}