blob: 24ed8df738266b33c710cd321c2b56a7f7631366 [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;
15
Imre Kis703482d2023-11-30 15:51:26 +010016/// Memory shareability
17#[derive(PrimitiveEnum_u8, Clone, Copy, Debug, PartialEq, Eq, Default)]
18pub enum Shareability {
19 #[default]
20 NonShareable = 0b00,
21 Outer = 0b10,
22 Inner = 0b11,
23}
24
25/// Data access permission
26#[derive(PrimitiveEnum_u8, Clone, Copy, Debug, PartialEq, Eq, Default)]
27pub enum DataAccessPermissions {
28 #[default]
29 ReadWrite_None = 0b00,
30 ReadWrite_ReadWrite = 0b01,
31 ReadOnly_None = 0b10,
32 ReadOnly_ReadOnly = 0b11,
33}
34
35/// Memory attributes
36#[derive(PackedStruct, Clone, Debug, PartialEq, Eq, Default)]
37#[packed_struct(size_bytes = "8", bit_numbering = "lsb0")]
38pub struct Attributes {
39 #[packed_field(bits = "54")]
40 pub uxn: bool,
41 #[packed_field(bits = "53")]
42 pub pxn: bool,
43 #[packed_field(bits = "52")]
44 pub contiguous: bool,
45 #[packed_field(bits = "11")]
46 pub not_global: bool,
47 #[packed_field(bits = "10")]
48 pub access_flag: bool,
49 #[packed_field(bits = "9..=8", ty = "enum")]
50 pub shareability: Shareability,
51 #[packed_field(bits = "7..=6", ty = "enum")]
52 pub data_access_permissions: DataAccessPermissions,
53 #[packed_field(bits = "5")]
54 pub non_secure: bool,
55 #[packed_field(bits = "4..=2", ty = "enum")]
56 pub mem_attr_index: MemoryAttributesIndex,
57}
58
59impl From<Attributes> for u64 {
60 fn from(attributes: Attributes) -> Self {
61 u64::from_be_bytes(attributes.pack().unwrap())
62 }
63}
64
65impl From<u64> for Attributes {
66 fn from(bits: u64) -> Self {
67 Self::unpack(&bits.to_be_bytes()).unwrap()
68 }
69}
70
71/// Next level attributes
72#[derive(PackedStruct, Clone, Debug, PartialEq, Eq, Default)]
73#[packed_struct(size_bytes = "8", bit_numbering = "lsb0")]
74pub struct NextLevelAttributes {
75 #[packed_field(bits = "63")]
76 ns_table: bool,
77 #[packed_field(bits = "62..=61")]
78 ap_table: Integer<u8, packed_bits::Bits<2>>,
79 #[packed_field(bits = "60")]
80 xn_table: bool,
81 #[packed_field(bits = "59")]
82 pxn_table: bool,
83}
84
85impl From<NextLevelAttributes> for u64 {
86 fn from(attributes: NextLevelAttributes) -> Self {
87 u64::from_be_bytes(attributes.pack().unwrap())
88 }
89}
90
91impl From<u64> for NextLevelAttributes {
92 fn from(bits: u64) -> Self {
93 Self::unpack(&bits.to_be_bytes()).unwrap()
94 }
95}
96
97/// Memory descriptor type
98#[derive(PartialEq, Eq, Debug)]
99pub enum DescriptorType {
100 Invalid,
101 Block,
102 Table,
103}
104
105/// Memory descriptor of a memory translation table
106#[repr(C)]
Imre Kisf5f6fa72024-04-18 14:04:21 +0200107#[derive(Default)]
Imre Kis703482d2023-11-30 15:51:26 +0100108pub struct Descriptor {
109 cell: UnsafeCell<u64>,
110}
111
112impl Descriptor {
113 const ATTR_MASK: u64 = 0xfff8_0000_0000_0ffc;
114 const DESCRIPTOR_TYPE_MASK: u64 = 0b11;
115 pub const GRANULE_SIZES: [usize; 4] = [0, 0x4000_0000, 0x0020_0000, 0x0000_1000];
116 const INVALID_DESCRIPTOR_VALUE: u64 = 0x0;
117 const NEXT_ATTR_MASK: u64 = 0xf800_0000_0000_0000;
118 const OA_MASK: u64 = 0x0000_ffff_ffff_f000;
119 const TABLE_BIT: u64 = 0b10;
120 const TABLE_ENTRY_COUNT: usize = 512;
121 const TA_MASK: u64 = 0x0000_ffff_ffff_f000;
122 const VALID_BIT: u64 = 0b01;
123
124 /// Query descriptor type
125 pub fn get_descriptor_type(&self, level: usize) -> DescriptorType {
126 assert!(level <= 3);
127
Imre Kisf5f6fa72024-04-18 14:04:21 +0200128 let desc_type_bits = self.get() & Self::DESCRIPTOR_TYPE_MASK;
Imre Kis703482d2023-11-30 15:51:26 +0100129 if desc_type_bits & Self::VALID_BIT != 0 {
130 if level == 3 {
131 assert_eq!(Self::TABLE_BIT, desc_type_bits & Self::TABLE_BIT);
132 DescriptorType::Block
133 } else if desc_type_bits & Self::TABLE_BIT != 0 {
134 DescriptorType::Table
135 } else {
136 DescriptorType::Block
137 }
138 } else {
139 DescriptorType::Invalid
140 }
141 }
142
143 // Invalid descriptor functions
144
145 /// Check if it is a valid descriptor
146 pub fn is_valid(&self) -> bool {
Imre Kisf5f6fa72024-04-18 14:04:21 +0200147 self.get() & Self::VALID_BIT != 0
Imre Kis703482d2023-11-30 15:51:26 +0100148 }
149
150 // Block descriptor functions
151
152 /// Set block descriptor
153 pub fn set_block_descriptor(
154 &mut self,
155 level: usize,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200156 output_address: PhysicalAddress,
Imre Kis703482d2023-11-30 15:51:26 +0100157 attributes: Attributes,
158 ) {
159 let attr: u64 = attributes.into();
160
161 assert!(level <= 3);
162 assert!(self.get_descriptor_type(level) != DescriptorType::Table);
Imre Kisd5b96fd2024-09-11 17:04:32 +0200163 assert_eq!(0, output_address.0 & !Self::get_oa_mask(level));
Imre Kis703482d2023-11-30 15:51:26 +0100164 assert_eq!(0, attr & !Self::ATTR_MASK);
165
166 let table_bit = if level < 3 { 0 } else { Self::TABLE_BIT };
167
Imre Kisd5b96fd2024-09-11 17:04:32 +0200168 self.set(Self::VALID_BIT | table_bit | output_address.0 as u64 | attr);
Imre Kis703482d2023-11-30 15:51:26 +0100169 }
170
171 /// Get output address from the block descriptor
Imre Kisd5b96fd2024-09-11 17:04:32 +0200172 pub fn get_block_output_address(&self, level: usize) -> PhysicalAddress {
Imre Kis703482d2023-11-30 15:51:26 +0100173 assert!(level <= 3);
174 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
175
Imre Kisd5b96fd2024-09-11 17:04:32 +0200176 PhysicalAddress((self.get() & Self::OA_MASK) as usize)
Imre Kis703482d2023-11-30 15:51:26 +0100177 }
178
179 /// Set the attributes of the block descriptor
180 pub fn set_block_attributes(&mut self, level: usize, attributes: Attributes) {
181 assert!(level <= 3);
182 let attr: u64 = attributes.into();
183 assert_eq!(0, attr & !Self::ATTR_MASK);
184 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
185
Imre Kisf5f6fa72024-04-18 14:04:21 +0200186 self.modify(|d| (d & !Self::ATTR_MASK) | attr);
Imre Kis703482d2023-11-30 15:51:26 +0100187 }
188
189 /// Get the attributes of the block descriptor
190 pub fn get_block_attributes(&self, level: usize) -> Attributes {
191 assert!(level <= 3);
192 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
193
Imre Kisf5f6fa72024-04-18 14:04:21 +0200194 Attributes::from(self.get() & Self::ATTR_MASK)
Imre Kis703482d2023-11-30 15:51:26 +0100195 }
196
197 /// Set block descriptor to invalid
198 pub fn set_block_descriptor_to_invalid(&mut self, level: usize) {
199 assert!(level <= 3);
200 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
201
Imre Kisf5f6fa72024-04-18 14:04:21 +0200202 self.set(Self::INVALID_DESCRIPTOR_VALUE)
Imre Kis703482d2023-11-30 15:51:26 +0100203 }
204
Imre Kis9a9d0492024-10-31 15:19:46 +0100205 /// Set block or invalid descriptor to invalid
206 pub fn set_block_or_invalid_descriptor_to_invalid(&mut self, level: usize) {
207 assert!(level <= 3);
208 assert!(DescriptorType::Table != self.get_descriptor_type(level));
209
210 self.set(Self::INVALID_DESCRIPTOR_VALUE)
211 }
212
Imre Kis703482d2023-11-30 15:51:26 +0100213 /// Set table descriptor
214 ///
Imre Kis9a9d0492024-10-31 15:19:46 +0100215 /// Safety: The caller has to ensure that the passed next level table has the same life as
Imre Kis703482d2023-11-30 15:51:26 +0100216 /// the descriptor.
217 pub unsafe fn set_table_descriptor(
218 &mut self,
219 level: usize,
220 next_level_table: &mut [Descriptor],
221 next_level_attributes: Option<NextLevelAttributes>,
222 ) {
223 assert!(level <= 2);
224 assert_eq!(Self::TABLE_ENTRY_COUNT, next_level_table.len());
225 assert!(self.get_descriptor_type(level) != DescriptorType::Table);
226
227 let table_addr = KernelSpace::kernel_to_pa(next_level_table.as_ptr() as u64);
228 assert_eq!(0, table_addr & !Self::TA_MASK);
229
230 let mut raw_desc_value = Self::VALID_BIT | Self::TABLE_BIT | table_addr;
231
232 if let Some(next_attr) = next_level_attributes {
233 let next_attr_bits: u64 = next_attr.into();
234 assert_eq!(0, next_attr_bits & !Self::NEXT_ATTR_MASK);
235 raw_desc_value |= next_attr_bits;
236 }
237
238 self.set(raw_desc_value);
239 }
240
241 /// Get next level table
242 ///
Imre Kis9a9d0492024-10-31 15:19:46 +0100243 /// Safety: The returned next level table is based on the address read from the descriptor.
Imre Kis703482d2023-11-30 15:51:26 +0100244 /// The caller has to ensure that no other references are being used of the table.
245 pub unsafe fn get_next_level_table(&self, level: usize) -> &[Descriptor] {
246 assert!(level <= 2);
247 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
248
249 let table_address =
250 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *const Descriptor;
251 core::slice::from_raw_parts(table_address, Self::TABLE_ENTRY_COUNT)
252 }
253
254 /// Get mutable next level table
255 ///
Imre Kis9a9d0492024-10-31 15:19:46 +0100256 /// Safety: The returned next level table is based on the address read from the descriptor.
Imre Kis703482d2023-11-30 15:51:26 +0100257 /// The caller has to ensure that no other references are being used of the table.
258 pub unsafe fn get_next_level_table_mut(&mut self, level: usize) -> &mut [Descriptor] {
259 assert!(level <= 2);
260 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
261
262 let table_address =
263 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *mut Descriptor;
264 core::slice::from_raw_parts_mut(table_address, Self::TABLE_ENTRY_COUNT)
265 }
266
267 /// Get next level attributes
268 pub fn get_next_level_attributes(&self, level: usize) -> NextLevelAttributes {
269 assert!(level <= 2);
270 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
271
Imre Kisf5f6fa72024-04-18 14:04:21 +0200272 NextLevelAttributes::from(self.get() & Self::NEXT_ATTR_MASK)
Imre Kis703482d2023-11-30 15:51:26 +0100273 }
274
275 /// Set table descriptor to invalid
276 ///
277 /// **Unsafe:** The returned descriptor reference must be released by the caller, i.e. release
278 /// to `PagePool`
279 pub unsafe fn set_table_descriptor_to_invalid(&mut self, level: usize) -> &mut [Descriptor] {
280 assert!(level <= 2);
281 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
282
283 let table_address =
284 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *mut Descriptor;
285 self.set(Self::INVALID_DESCRIPTOR_VALUE);
286 core::slice::from_raw_parts_mut(table_address, Self::TABLE_ENTRY_COUNT)
287 }
288
289 /// Get raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200290 fn get(&self) -> u64 {
291 unsafe { ptr::read_volatile(self.cell.get()) }
Imre Kis703482d2023-11-30 15:51:26 +0100292 }
293
294 /// Set raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200295 fn set(&mut self, value: u64) {
Imre Kis9a9d0492024-10-31 15:19:46 +0100296 // Safety: The cell should point to a valid address and the assembly code is just a data
297 // barrier.
298 unsafe {
299 ptr::write_volatile(self.cell.get(), value);
300 #[cfg(target_arch = "aarch64")]
301 core::arch::asm!("dsb nsh");
302 }
Imre Kis703482d2023-11-30 15:51:26 +0100303 }
304
305 /// Modify raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200306 fn modify<F>(&mut self, f: F)
Imre Kis703482d2023-11-30 15:51:26 +0100307 where
308 F: Fn(u64) -> u64,
309 {
310 self.set(f(self.get()))
311 }
312
313 /// Get output address mask
314 fn get_oa_mask(level: usize) -> usize {
315 Self::OA_MASK as usize & !(Self::GRANULE_SIZES[level] - 1)
316 }
317}
318
Imre Kis42935a22024-10-17 11:30:16 +0200319#[cfg(test)]
320mod tests {
321 use super::*;
Imre Kis703482d2023-11-30 15:51:26 +0100322
Imre Kis42935a22024-10-17 11:30:16 +0200323 #[test]
324 fn test_attributes() {
325 let attributes = Attributes::default();
326 assert_eq!(0u64, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100327
Imre Kis42935a22024-10-17 11:30:16 +0200328 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100329 uxn: true,
330 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200331 };
332 assert_eq!(1u64 << 54, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100333
Imre Kis42935a22024-10-17 11:30:16 +0200334 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100335 pxn: true,
336 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200337 };
338 assert_eq!(1u64 << 53, attributes.into());
339
340 let attributes = Attributes {
341 contiguous: true,
Imre Kis703482d2023-11-30 15:51:26 +0100342 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200343 };
344 assert_eq!(1u64 << 52, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100345
Imre Kis42935a22024-10-17 11:30:16 +0200346 let attributes = Attributes {
347 not_global: true,
348 ..Default::default()
349 };
350 assert_eq!(1u64 << 11, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100351
Imre Kis42935a22024-10-17 11:30:16 +0200352 let attributes = Attributes {
353 access_flag: true,
354 ..Default::default()
355 };
356 assert_eq!(1u64 << 10, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100357
Imre Kis42935a22024-10-17 11:30:16 +0200358 let attributes = Attributes {
359 non_secure: true,
360 ..Default::default()
361 };
362 assert_eq!(1u64 << 5, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100363
Imre Kis42935a22024-10-17 11:30:16 +0200364 let attributes = Attributes {
365 mem_attr_index: MemoryAttributesIndex::Normal_IWBWA_OWBWA,
366 ..Default::default()
367 };
368 assert_eq!(
369 (MemoryAttributesIndex::Normal_IWBWA_OWBWA as u64) << 2,
370 attributes.into()
371 );
Imre Kis703482d2023-11-30 15:51:26 +0100372
Imre Kis42935a22024-10-17 11:30:16 +0200373 let attributes: Attributes = 0.into();
374 assert!(!attributes.uxn);
375 assert!(!attributes.pxn);
376 assert!(!attributes.contiguous);
377 assert!(!attributes.not_global);
378 assert!(!attributes.access_flag);
379 assert_eq!(Shareability::NonShareable, attributes.shareability);
380 assert_eq!(
381 DataAccessPermissions::ReadWrite_None,
382 attributes.data_access_permissions
383 );
384 assert!(!attributes.non_secure);
385 assert_eq!(
386 MemoryAttributesIndex::Device_nGnRnE,
387 attributes.mem_attr_index
Imre Kis703482d2023-11-30 15:51:26 +0100388 );
389 }
Imre Kis703482d2023-11-30 15:51:26 +0100390
Imre Kis42935a22024-10-17 11:30:16 +0200391 #[test]
392 fn test_next_level_attributes() {
393 let next_level_attributes = NextLevelAttributes::default();
394 assert_eq!(0u64, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100395
Imre Kis42935a22024-10-17 11:30:16 +0200396 let next_level_attributes = NextLevelAttributes {
Imre Kis703482d2023-11-30 15:51:26 +0100397 ns_table: true,
398 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200399 };
400 assert_eq!(1u64 << 63, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100401
Imre Kis42935a22024-10-17 11:30:16 +0200402 let next_level_attributes = NextLevelAttributes {
403 ap_table: 3.into(),
404 ..Default::default()
405 };
406 assert_eq!(3u64 << 61, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100407
Imre Kis42935a22024-10-17 11:30:16 +0200408 let next_level_attributes = NextLevelAttributes {
409 xn_table: true,
410 ..Default::default()
411 };
412 assert_eq!(1u64 << 60, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100413
Imre Kis42935a22024-10-17 11:30:16 +0200414 let next_level_attributes = NextLevelAttributes {
415 pxn_table: true,
416 ..Default::default()
417 };
418 assert_eq!(1u64 << 59, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100419
Imre Kis42935a22024-10-17 11:30:16 +0200420 let next_level_attributes: NextLevelAttributes = 0.into();
421 assert!(!next_level_attributes.ns_table);
422 assert_eq!(0u8, next_level_attributes.ap_table.into());
423 assert!(!next_level_attributes.xn_table);
424 assert!(!next_level_attributes.pxn_table);
Imre Kis703482d2023-11-30 15:51:26 +0100425
Imre Kis42935a22024-10-17 11:30:16 +0200426 let next_level_attributes: NextLevelAttributes = u64::MAX.into();
427 assert!(next_level_attributes.ns_table);
428 assert_eq!(3u8, next_level_attributes.ap_table.into());
429 assert!(next_level_attributes.xn_table);
430 assert!(next_level_attributes.pxn_table);
431 }
Imre Kis703482d2023-11-30 15:51:26 +0100432
Imre Kis42935a22024-10-17 11:30:16 +0200433 #[test]
434 fn test_descriptor_get_type() {
435 let descriptor = Descriptor {
436 cell: UnsafeCell::new(0),
437 };
438 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(1));
439
440 let descriptor = Descriptor {
441 cell: UnsafeCell::new(1),
442 };
443 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(1));
444
445 let descriptor = Descriptor {
446 cell: UnsafeCell::new(3),
447 };
448 assert_eq!(DescriptorType::Table, descriptor.get_descriptor_type(1));
449
450 let descriptor = Descriptor {
451 cell: UnsafeCell::new(0),
452 };
453 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(3));
454
455 let descriptor = Descriptor {
456 cell: UnsafeCell::new(3),
457 };
458 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(3));
459 }
460
461 #[test]
462 fn test_descriptor_is_valid() {
463 let descriptor = Descriptor {
464 cell: UnsafeCell::new(0),
465 };
466 assert!(!descriptor.is_valid());
467
468 let descriptor = Descriptor {
469 cell: UnsafeCell::new(1),
470 };
471 assert!(descriptor.is_valid());
472 }
473
474 #[test]
475 fn test_descriptor_set_block_to_block_again() {
476 let mut descriptor = Descriptor {
477 cell: UnsafeCell::new(1),
478 };
479
Imre Kisd5b96fd2024-09-11 17:04:32 +0200480 descriptor.set_block_descriptor(1, PhysicalAddress(0), Attributes::default());
Imre Kis42935a22024-10-17 11:30:16 +0200481 assert_eq!(0x1, descriptor.get());
482 }
483
484 #[test]
485 #[should_panic]
486 fn test_descriptor_set_block_invalid_oa() {
487 let mut descriptor = Descriptor {
488 cell: UnsafeCell::new(0),
489 };
490
Imre Kisd5b96fd2024-09-11 17:04:32 +0200491 descriptor.set_block_descriptor(1, PhysicalAddress(1 << 63), Attributes::default());
Imre Kis42935a22024-10-17 11:30:16 +0200492 }
493
494 #[test]
495 fn test_descriptor_block() {
496 let mut descriptor = Descriptor {
497 cell: UnsafeCell::new(0),
498 };
499
500 descriptor.set_block_descriptor(
501 1,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200502 PhysicalAddress(0x0000000f_c0000000),
Imre Kis42935a22024-10-17 11:30:16 +0200503 Attributes {
504 uxn: true,
505 ..Default::default()
506 },
507 );
508 assert_eq!(0x0040000f_c0000001, descriptor.get());
509
510 let mut descriptor = Descriptor {
511 cell: UnsafeCell::new(0),
512 };
513
514 descriptor.set_block_descriptor(
515 3,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200516 PhysicalAddress(0x0000000f_fffff000),
Imre Kis42935a22024-10-17 11:30:16 +0200517 Attributes {
518 uxn: true,
519 ..Default::default()
520 },
521 );
522 assert_eq!(0x0040000f_fffff003, descriptor.get());
523
Imre Kisd5b96fd2024-09-11 17:04:32 +0200524 assert_eq!(
525 PhysicalAddress(0x0000000f_fffff000),
526 descriptor.get_block_output_address(3)
527 );
Imre Kis42935a22024-10-17 11:30:16 +0200528 assert_eq!(
529 Attributes {
530 uxn: true,
531 ..Default::default()
532 },
533 descriptor.get_block_attributes(3)
534 );
535
536 descriptor.set_block_attributes(
537 3,
538 Attributes {
539 pxn: true,
540 ..Default::default()
541 },
542 );
543 assert_eq!(
544 Attributes {
545 pxn: true,
546 ..Default::default()
547 },
548 descriptor.get_block_attributes(3)
549 );
550 }
551
552 #[test]
553 #[should_panic]
554 fn test_descriptor_invalid_block_to_invalid() {
555 let mut descriptor = Descriptor {
556 cell: UnsafeCell::new(0),
557 };
558
559 descriptor.set_block_descriptor_to_invalid(0);
560 }
561
562 #[test]
563 fn test_descriptor_block_to_invalid() {
564 let mut descriptor = Descriptor {
565 cell: UnsafeCell::new(3),
566 };
567
568 descriptor.set_block_descriptor_to_invalid(3);
569 assert_eq!(0, descriptor.get());
570 }
571
572 #[test]
Imre Kis9a9d0492024-10-31 15:19:46 +0100573 fn test_descriptor_block_or_invalid_block_to_invalid() {
574 let mut descriptor = Descriptor {
575 cell: UnsafeCell::new(0),
576 };
577
578 descriptor.set_block_or_invalid_descriptor_to_invalid(0);
579 assert_eq!(0, descriptor.get());
580
581 let mut descriptor = Descriptor {
582 cell: UnsafeCell::new(3),
583 };
584
585 descriptor.set_block_or_invalid_descriptor_to_invalid(3);
586 assert_eq!(0, descriptor.get());
587 }
588
589 #[test]
Imre Kis42935a22024-10-17 11:30:16 +0200590 #[should_panic]
591 fn test_descriptor_level3_to_table() {
592 let mut next_level_table = [Descriptor {
593 cell: UnsafeCell::new(0),
594 }];
595 let mut descriptor = Descriptor {
596 cell: UnsafeCell::new(0),
597 };
598
599 unsafe {
600 descriptor.set_table_descriptor(3, &mut next_level_table, None);
601 }
602 }
603
604 #[test]
605 fn test_descriptor_block_to_table() {
606 let next_level_table =
607 unsafe { core::slice::from_raw_parts_mut(0x1000 as *mut Descriptor, 512) };
608 let mut descriptor = Descriptor {
609 cell: UnsafeCell::new(1),
610 };
611
612 unsafe {
613 descriptor.set_table_descriptor(0, next_level_table, None);
614 }
615 assert_eq!(0x1003, descriptor.get());
616 }
617
618 #[test]
619 #[should_panic]
620 fn test_descriptor_table_invalid_count() {
621 let next_level_table =
622 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 511) };
623 let mut descriptor = Descriptor {
624 cell: UnsafeCell::new(0),
625 };
626
627 unsafe {
628 descriptor.set_table_descriptor(0, next_level_table, None);
629 }
630 }
631
632 #[test]
633 #[should_panic]
634 fn test_descriptor_table_non_aligned() {
635 let next_level_table =
636 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 512) };
637 let mut descriptor = Descriptor {
638 cell: UnsafeCell::new(0),
639 };
640
641 unsafe {
642 descriptor.set_table_descriptor(0, next_level_table, None);
643 }
644 }
645
646 #[test]
647 fn test_descriptor_table() {
648 let next_level_table = unsafe {
649 core::slice::from_raw_parts_mut(0x0000_000c_ba98_7000 as *mut Descriptor, 512)
650 };
651 let mut descriptor = Descriptor {
652 cell: UnsafeCell::new(0),
653 };
654
655 unsafe {
656 descriptor.set_table_descriptor(0, next_level_table, None);
657 }
658 assert_eq!(0x0000_000c_ba98_7003, descriptor.get());
659 }
660
661 #[test]
662 fn test_descriptor_table_next_level_attr() {
663 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
664 let next_level_table =
665 unsafe { core::slice::from_raw_parts_mut(NEXT_LEVEL_ADDR as *mut Descriptor, 512) };
666 let mut descriptor = Descriptor {
667 cell: UnsafeCell::new(0),
668 };
669
670 unsafe {
671 descriptor.set_table_descriptor(
672 0,
673 next_level_table,
674 Some(NextLevelAttributes {
675 ns_table: true,
676 ..Default::default()
677 }),
678 );
679 }
680 assert_eq!(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003, descriptor.get());
681 }
682
683 #[test]
684 fn test_descriptor_table_get_next_level_table() {
685 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
686 let descriptor = Descriptor {
687 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
688 };
689 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
690 descriptor.get_next_level_table(0).as_ptr() as u64
691 });
692 }
693
694 #[test]
695 fn test_descriptor_table_get_next_level_table_mut() {
696 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
697 let mut descriptor = Descriptor {
698 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
699 };
700 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
701 descriptor.get_next_level_table_mut(0).as_ptr() as *mut Descriptor as u64
702 });
703 }
704
705 #[test]
706 fn test_descriptor_table_get_next_level_attr() {
707 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
708 let descriptor = Descriptor {
709 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
710 };
711 assert_eq!(
712 NextLevelAttributes {
713 ns_table: true,
714 ..Default::default()
715 },
716 descriptor.get_next_level_attributes(0)
717 );
718 }
719
720 #[test]
721 fn test_descriptor_table_set_to_invalid() {
722 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
723 let mut descriptor = Descriptor {
724 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
725 };
726 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
727 descriptor.set_table_descriptor_to_invalid(0).as_ptr() as *mut Descriptor as u64
728 });
729 assert_eq!(0, descriptor.get());
730 }
731
732 #[test]
733 fn test_descriptor_raw_interface() {
734 let cell_value = 0x01234567_89abcdefu64;
735 let cell_new_value = 0x12345678_9abcdef0u64;
736
737 let mut descriptor = Descriptor {
738 cell: UnsafeCell::new(cell_value),
739 };
740
741 assert_eq!(cell_value, descriptor.get());
742
743 descriptor.set(cell_new_value);
744 assert_eq!(cell_new_value, descriptor.get());
745
746 descriptor.modify(|d| d + 1);
747 assert_eq!(cell_new_value + 1, descriptor.get());
748 }
Imre Kis703482d2023-11-30 15:51:26 +0100749}