blob: ef78d132f8b90f0becb3dc02895a6c76e658f94c [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
14/// Memory shareability
15#[derive(PrimitiveEnum_u8, Clone, Copy, Debug, PartialEq, Eq, Default)]
16pub enum Shareability {
17 #[default]
18 NonShareable = 0b00,
19 Outer = 0b10,
20 Inner = 0b11,
21}
22
23/// Data access permission
24#[derive(PrimitiveEnum_u8, Clone, Copy, Debug, PartialEq, Eq, Default)]
25pub enum DataAccessPermissions {
26 #[default]
27 ReadWrite_None = 0b00,
28 ReadWrite_ReadWrite = 0b01,
29 ReadOnly_None = 0b10,
30 ReadOnly_ReadOnly = 0b11,
31}
32
33/// Memory attributes
34#[derive(PackedStruct, Clone, Debug, PartialEq, Eq, Default)]
35#[packed_struct(size_bytes = "8", bit_numbering = "lsb0")]
36pub struct Attributes {
37 #[packed_field(bits = "54")]
38 pub uxn: bool,
39 #[packed_field(bits = "53")]
40 pub pxn: bool,
41 #[packed_field(bits = "52")]
42 pub contiguous: bool,
43 #[packed_field(bits = "11")]
44 pub not_global: bool,
45 #[packed_field(bits = "10")]
46 pub access_flag: bool,
47 #[packed_field(bits = "9..=8", ty = "enum")]
48 pub shareability: Shareability,
49 #[packed_field(bits = "7..=6", ty = "enum")]
50 pub data_access_permissions: DataAccessPermissions,
51 #[packed_field(bits = "5")]
52 pub non_secure: bool,
53 #[packed_field(bits = "4..=2", ty = "enum")]
54 pub mem_attr_index: MemoryAttributesIndex,
55}
56
57impl From<Attributes> for u64 {
58 fn from(attributes: Attributes) -> Self {
59 u64::from_be_bytes(attributes.pack().unwrap())
60 }
61}
62
63impl From<u64> for Attributes {
64 fn from(bits: u64) -> Self {
65 Self::unpack(&bits.to_be_bytes()).unwrap()
66 }
67}
68
69/// Next level attributes
70#[derive(PackedStruct, Clone, Debug, PartialEq, Eq, Default)]
71#[packed_struct(size_bytes = "8", bit_numbering = "lsb0")]
72pub struct NextLevelAttributes {
73 #[packed_field(bits = "63")]
74 ns_table: bool,
75 #[packed_field(bits = "62..=61")]
76 ap_table: Integer<u8, packed_bits::Bits<2>>,
77 #[packed_field(bits = "60")]
78 xn_table: bool,
79 #[packed_field(bits = "59")]
80 pxn_table: bool,
81}
82
83impl From<NextLevelAttributes> for u64 {
84 fn from(attributes: NextLevelAttributes) -> Self {
85 u64::from_be_bytes(attributes.pack().unwrap())
86 }
87}
88
89impl From<u64> for NextLevelAttributes {
90 fn from(bits: u64) -> Self {
91 Self::unpack(&bits.to_be_bytes()).unwrap()
92 }
93}
94
95/// Memory descriptor type
96#[derive(PartialEq, Eq, Debug)]
97pub enum DescriptorType {
98 Invalid,
99 Block,
100 Table,
101}
102
103/// Memory descriptor of a memory translation table
104#[repr(C)]
Imre Kisf5f6fa72024-04-18 14:04:21 +0200105#[derive(Default)]
Imre Kis703482d2023-11-30 15:51:26 +0100106pub struct Descriptor {
107 cell: UnsafeCell<u64>,
108}
109
110impl Descriptor {
111 const ATTR_MASK: u64 = 0xfff8_0000_0000_0ffc;
112 const DESCRIPTOR_TYPE_MASK: u64 = 0b11;
113 pub const GRANULE_SIZES: [usize; 4] = [0, 0x4000_0000, 0x0020_0000, 0x0000_1000];
114 const INVALID_DESCRIPTOR_VALUE: u64 = 0x0;
115 const NEXT_ATTR_MASK: u64 = 0xf800_0000_0000_0000;
116 const OA_MASK: u64 = 0x0000_ffff_ffff_f000;
117 const TABLE_BIT: u64 = 0b10;
118 const TABLE_ENTRY_COUNT: usize = 512;
119 const TA_MASK: u64 = 0x0000_ffff_ffff_f000;
120 const VALID_BIT: u64 = 0b01;
121
122 /// Query descriptor type
123 pub fn get_descriptor_type(&self, level: usize) -> DescriptorType {
124 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
151 pub fn set_block_descriptor(
152 &mut self,
153 level: usize,
154 output_address: usize,
155 attributes: Attributes,
156 ) {
157 let attr: u64 = attributes.into();
158
159 assert!(level <= 3);
160 assert!(self.get_descriptor_type(level) != DescriptorType::Table);
161 assert_eq!(0, output_address & !Self::get_oa_mask(level));
162 assert_eq!(0, attr & !Self::ATTR_MASK);
163
164 let table_bit = if level < 3 { 0 } else { Self::TABLE_BIT };
165
Imre Kisf5f6fa72024-04-18 14:04:21 +0200166 self.set(Self::VALID_BIT | table_bit | output_address as u64 | attr);
Imre Kis703482d2023-11-30 15:51:26 +0100167 }
168
169 /// Get output address from the block descriptor
170 pub fn get_block_output_address(&self, level: usize) -> usize {
171 assert!(level <= 3);
172 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
173
Imre Kisf5f6fa72024-04-18 14:04:21 +0200174 (self.get() & Self::OA_MASK) as usize
Imre Kis703482d2023-11-30 15:51:26 +0100175 }
176
177 /// Set the attributes of the block descriptor
178 pub fn set_block_attributes(&mut self, level: usize, attributes: Attributes) {
179 assert!(level <= 3);
180 let attr: u64 = attributes.into();
181 assert_eq!(0, attr & !Self::ATTR_MASK);
182 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
183
Imre Kisf5f6fa72024-04-18 14:04:21 +0200184 self.modify(|d| (d & !Self::ATTR_MASK) | attr);
Imre Kis703482d2023-11-30 15:51:26 +0100185 }
186
187 /// Get the attributes of the block descriptor
188 pub fn get_block_attributes(&self, level: usize) -> Attributes {
189 assert!(level <= 3);
190 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
191
Imre Kisf5f6fa72024-04-18 14:04:21 +0200192 Attributes::from(self.get() & Self::ATTR_MASK)
Imre Kis703482d2023-11-30 15:51:26 +0100193 }
194
195 /// Set block descriptor to invalid
196 pub fn set_block_descriptor_to_invalid(&mut self, level: usize) {
197 assert!(level <= 3);
198 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
199
Imre Kisf5f6fa72024-04-18 14:04:21 +0200200 self.set(Self::INVALID_DESCRIPTOR_VALUE)
Imre Kis703482d2023-11-30 15:51:26 +0100201 }
202
203 /// Set table descriptor
204 ///
205 /// **Unsafe**: The caller has to ensure that the passed next level table has the same life as
206 /// the descriptor.
207 pub unsafe fn set_table_descriptor(
208 &mut self,
209 level: usize,
210 next_level_table: &mut [Descriptor],
211 next_level_attributes: Option<NextLevelAttributes>,
212 ) {
213 assert!(level <= 2);
214 assert_eq!(Self::TABLE_ENTRY_COUNT, next_level_table.len());
215 assert!(self.get_descriptor_type(level) != DescriptorType::Table);
216
217 let table_addr = KernelSpace::kernel_to_pa(next_level_table.as_ptr() as u64);
218 assert_eq!(0, table_addr & !Self::TA_MASK);
219
220 let mut raw_desc_value = Self::VALID_BIT | Self::TABLE_BIT | table_addr;
221
222 if let Some(next_attr) = next_level_attributes {
223 let next_attr_bits: u64 = next_attr.into();
224 assert_eq!(0, next_attr_bits & !Self::NEXT_ATTR_MASK);
225 raw_desc_value |= next_attr_bits;
226 }
227
228 self.set(raw_desc_value);
229 }
230
231 /// Get next level table
232 ///
233 /// **Unsafe**: The returned next level table is based on the address read from the descriptor.
234 /// The caller has to ensure that no other references are being used of the table.
235 pub unsafe fn get_next_level_table(&self, level: usize) -> &[Descriptor] {
236 assert!(level <= 2);
237 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
238
239 let table_address =
240 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *const Descriptor;
241 core::slice::from_raw_parts(table_address, Self::TABLE_ENTRY_COUNT)
242 }
243
244 /// Get mutable next level table
245 ///
246 /// **Unsafe**: The returned next level table is based on the address read from the descriptor.
247 /// The caller has to ensure that no other references are being used of the table.
248 pub unsafe fn get_next_level_table_mut(&mut self, level: usize) -> &mut [Descriptor] {
249 assert!(level <= 2);
250 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
251
252 let table_address =
253 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *mut Descriptor;
254 core::slice::from_raw_parts_mut(table_address, Self::TABLE_ENTRY_COUNT)
255 }
256
257 /// Get next level attributes
258 pub fn get_next_level_attributes(&self, level: usize) -> NextLevelAttributes {
259 assert!(level <= 2);
260 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
261
Imre Kisf5f6fa72024-04-18 14:04:21 +0200262 NextLevelAttributes::from(self.get() & Self::NEXT_ATTR_MASK)
Imre Kis703482d2023-11-30 15:51:26 +0100263 }
264
265 /// Set table descriptor to invalid
266 ///
267 /// **Unsafe:** The returned descriptor reference must be released by the caller, i.e. release
268 /// to `PagePool`
269 pub unsafe fn set_table_descriptor_to_invalid(&mut self, level: usize) -> &mut [Descriptor] {
270 assert!(level <= 2);
271 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
272
273 let table_address =
274 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *mut Descriptor;
275 self.set(Self::INVALID_DESCRIPTOR_VALUE);
276 core::slice::from_raw_parts_mut(table_address, Self::TABLE_ENTRY_COUNT)
277 }
278
279 /// Get raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200280 fn get(&self) -> u64 {
281 unsafe { ptr::read_volatile(self.cell.get()) }
Imre Kis703482d2023-11-30 15:51:26 +0100282 }
283
284 /// Set raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200285 fn set(&mut self, value: u64) {
286 unsafe { ptr::write_volatile(self.cell.get(), value) }
Imre Kis703482d2023-11-30 15:51:26 +0100287 }
288
289 /// Modify raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200290 fn modify<F>(&mut self, f: F)
Imre Kis703482d2023-11-30 15:51:26 +0100291 where
292 F: Fn(u64) -> u64,
293 {
294 self.set(f(self.get()))
295 }
296
297 /// Get output address mask
298 fn get_oa_mask(level: usize) -> usize {
299 Self::OA_MASK as usize & !(Self::GRANULE_SIZES[level] - 1)
300 }
301}
302
303#[test]
304fn test_attributes() {
305 let attributes = Attributes::default();
306 assert_eq!(0u64, attributes.into());
307
308 let attributes = Attributes {
309 uxn: true,
310 ..Default::default()
311 };
312 assert_eq!(1u64 << 54, attributes.into());
313
314 let attributes = Attributes {
315 pxn: true,
316 ..Default::default()
317 };
318 assert_eq!(1u64 << 53, attributes.into());
319
320 let attributes = Attributes {
321 contiguous: true,
322 ..Default::default()
323 };
324 assert_eq!(1u64 << 52, attributes.into());
325
326 let attributes = Attributes {
327 not_global: true,
328 ..Default::default()
329 };
330 assert_eq!(1u64 << 11, attributes.into());
331
332 let attributes = Attributes {
333 access_flag: true,
334 ..Default::default()
335 };
336 assert_eq!(1u64 << 10, attributes.into());
337
338 let attributes = Attributes {
339 non_secure: true,
340 ..Default::default()
341 };
342 assert_eq!(1u64 << 5, attributes.into());
343
344 let attributes = Attributes {
345 mem_attr_index: MemoryAttributesIndex::Normal_IWBWA_OWBWA,
346 ..Default::default()
347 };
348 assert_eq!(
349 (MemoryAttributesIndex::Normal_IWBWA_OWBWA as u64) << 2,
350 attributes.into()
351 );
352
353 let attributes: Attributes = 0.into();
354 assert!(!attributes.uxn);
355 assert!(!attributes.pxn);
356 assert!(!attributes.contiguous);
357 assert!(!attributes.not_global);
358 assert!(!attributes.access_flag);
359 assert_eq!(Shareability::NonShareable, attributes.shareability);
360 assert_eq!(
361 DataAccessPermissions::ReadWrite_None,
362 attributes.data_access_permissions
363 );
364 assert!(!attributes.non_secure);
365 assert_eq!(
366 MemoryAttributesIndex::Device_nGnRnE,
367 attributes.mem_attr_index
368 );
369}
370
371#[test]
372fn test_next_level_attributes() {
373 let next_level_attributes = NextLevelAttributes::default();
374 assert_eq!(0u64, next_level_attributes.into());
375
376 let next_level_attributes = NextLevelAttributes {
377 ns_table: true,
378 ..Default::default()
379 };
380 assert_eq!(1u64 << 63, next_level_attributes.into());
381
382 let next_level_attributes = NextLevelAttributes {
383 ap_table: 3.into(),
384 ..Default::default()
385 };
386 assert_eq!(3u64 << 61, next_level_attributes.into());
387
388 let next_level_attributes = NextLevelAttributes {
389 xn_table: true,
390 ..Default::default()
391 };
392 assert_eq!(1u64 << 60, next_level_attributes.into());
393
394 let next_level_attributes = NextLevelAttributes {
395 pxn_table: true,
396 ..Default::default()
397 };
398 assert_eq!(1u64 << 59, next_level_attributes.into());
399
400 let next_level_attributes: NextLevelAttributes = 0.into();
401 assert!(!next_level_attributes.ns_table);
402 assert_eq!(0u8, next_level_attributes.ap_table.into());
403 assert!(!next_level_attributes.xn_table);
404 assert!(!next_level_attributes.pxn_table);
405
406 let next_level_attributes: NextLevelAttributes = u64::MAX.into();
407 assert!(next_level_attributes.ns_table);
408 assert_eq!(3u8, next_level_attributes.ap_table.into());
409 assert!(next_level_attributes.xn_table);
410 assert!(next_level_attributes.pxn_table);
411}
412
413#[test]
414fn test_descriptor_get_type() {
415 let descriptor = Descriptor {
416 cell: UnsafeCell::new(0),
417 };
418 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(1));
419
420 let descriptor = Descriptor {
421 cell: UnsafeCell::new(1),
422 };
423 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(1));
424
425 let descriptor = Descriptor {
426 cell: UnsafeCell::new(3),
427 };
428 assert_eq!(DescriptorType::Table, descriptor.get_descriptor_type(1));
429
430 let descriptor = Descriptor {
431 cell: UnsafeCell::new(0),
432 };
433 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(3));
434
435 let descriptor = Descriptor {
436 cell: UnsafeCell::new(3),
437 };
438 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(3));
439}
440
441#[test]
442fn test_descriptor_is_valid() {
443 let descriptor = Descriptor {
444 cell: UnsafeCell::new(0),
445 };
446 assert!(!descriptor.is_valid());
447
448 let descriptor = Descriptor {
449 cell: UnsafeCell::new(1),
450 };
451 assert!(descriptor.is_valid());
452}
453
454#[test]
455fn test_descriptor_set_block_to_block_again() {
456 let mut descriptor = Descriptor {
457 cell: UnsafeCell::new(1),
458 };
459
460 descriptor.set_block_descriptor(1, 0, Attributes::default());
Imre Kisf5f6fa72024-04-18 14:04:21 +0200461 assert_eq!(0x1, descriptor.get());
Imre Kis703482d2023-11-30 15:51:26 +0100462}
463
464#[test]
465#[should_panic]
466fn test_descriptor_set_block_invalid_oa() {
467 let mut descriptor = Descriptor {
468 cell: UnsafeCell::new(0),
469 };
470
471 descriptor.set_block_descriptor(1, 1 << 63, Attributes::default());
472}
473
474#[test]
475fn test_descriptor_block() {
476 let mut descriptor = Descriptor {
477 cell: UnsafeCell::new(0),
478 };
479
480 descriptor.set_block_descriptor(
481 1,
482 0x0000000f_c0000000,
483 Attributes {
484 uxn: true,
485 ..Default::default()
486 },
487 );
Imre Kisf5f6fa72024-04-18 14:04:21 +0200488 assert_eq!(0x0040000f_c0000001, descriptor.get());
Imre Kis703482d2023-11-30 15:51:26 +0100489
490 let mut descriptor = Descriptor {
491 cell: UnsafeCell::new(0),
492 };
493
494 descriptor.set_block_descriptor(
495 3,
496 0x0000000f_fffff000,
497 Attributes {
498 uxn: true,
499 ..Default::default()
500 },
501 );
Imre Kisf5f6fa72024-04-18 14:04:21 +0200502 assert_eq!(0x0040000f_fffff003, descriptor.get());
Imre Kis703482d2023-11-30 15:51:26 +0100503
504 assert_eq!(0x0000000f_fffff000, descriptor.get_block_output_address(3));
505 assert_eq!(
506 Attributes {
507 uxn: true,
508 ..Default::default()
509 },
510 descriptor.get_block_attributes(3)
511 );
512
513 descriptor.set_block_attributes(
514 3,
515 Attributes {
516 pxn: true,
517 ..Default::default()
518 },
519 );
520 assert_eq!(
521 Attributes {
522 pxn: true,
523 ..Default::default()
524 },
525 descriptor.get_block_attributes(3)
526 );
527}
528
529#[test]
530#[should_panic]
531fn test_descriptor_invalid_block_to_invalid() {
532 let mut descriptor = Descriptor {
533 cell: UnsafeCell::new(0),
534 };
535
536 descriptor.set_block_descriptor_to_invalid(0);
537}
538
539#[test]
540fn test_descriptor_block_to_invalid() {
541 let mut descriptor = Descriptor {
542 cell: UnsafeCell::new(3),
543 };
544
545 descriptor.set_block_descriptor_to_invalid(3);
Imre Kisf5f6fa72024-04-18 14:04:21 +0200546 assert_eq!(0, descriptor.get());
Imre Kis703482d2023-11-30 15:51:26 +0100547}
548
549#[test]
550#[should_panic]
551fn test_descriptor_level3_to_table() {
552 let mut next_level_table = [Descriptor {
553 cell: UnsafeCell::new(0),
554 }];
555 let mut descriptor = Descriptor {
556 cell: UnsafeCell::new(0),
557 };
558
559 unsafe {
560 descriptor.set_table_descriptor(3, &mut next_level_table, None);
561 }
562}
563
564#[test]
565fn test_descriptor_block_to_table() {
566 let next_level_table =
567 unsafe { core::slice::from_raw_parts_mut(0x1000 as *mut Descriptor, 512) };
568 let mut descriptor = Descriptor {
569 cell: UnsafeCell::new(1),
570 };
571
572 unsafe {
573 descriptor.set_table_descriptor(0, next_level_table, None);
574 }
Imre Kisf5f6fa72024-04-18 14:04:21 +0200575 assert_eq!(0x1003, descriptor.get());
Imre Kis703482d2023-11-30 15:51:26 +0100576}
577
578#[test]
579#[should_panic]
580fn test_descriptor_table_invalid_count() {
581 let next_level_table =
582 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 511) };
583 let mut descriptor = Descriptor {
584 cell: UnsafeCell::new(0),
585 };
586
587 unsafe {
588 descriptor.set_table_descriptor(0, next_level_table, None);
589 }
590}
591
592#[test]
593#[should_panic]
594fn test_descriptor_table_non_aligned() {
595 let next_level_table =
596 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 512) };
597 let mut descriptor = Descriptor {
598 cell: UnsafeCell::new(0),
599 };
600
601 unsafe {
602 descriptor.set_table_descriptor(0, next_level_table, None);
603 }
604}
605
606#[test]
607fn test_descriptor_table() {
608 let next_level_table =
609 unsafe { core::slice::from_raw_parts_mut(0x0000_000c_ba98_7000 as *mut Descriptor, 512) };
610 let mut descriptor = Descriptor {
611 cell: UnsafeCell::new(0),
612 };
613
614 unsafe {
615 descriptor.set_table_descriptor(0, next_level_table, None);
616 }
Imre Kisf5f6fa72024-04-18 14:04:21 +0200617 assert_eq!(0x0000_000c_ba98_7003, descriptor.get());
Imre Kis703482d2023-11-30 15:51:26 +0100618}
619
620#[test]
621fn test_descriptor_table_next_level_attr() {
622 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
623 let next_level_table =
624 unsafe { core::slice::from_raw_parts_mut(NEXT_LEVEL_ADDR as *mut Descriptor, 512) };
625 let mut descriptor = Descriptor {
626 cell: UnsafeCell::new(0),
627 };
628
629 unsafe {
630 descriptor.set_table_descriptor(
631 0,
632 next_level_table,
633 Some(NextLevelAttributes {
634 ns_table: true,
635 ..Default::default()
636 }),
637 );
638 }
Imre Kisf5f6fa72024-04-18 14:04:21 +0200639 assert_eq!(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003, descriptor.get());
Imre Kis703482d2023-11-30 15:51:26 +0100640}
641
642#[test]
643fn test_descriptor_table_get_next_level_table() {
644 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
645 let descriptor = Descriptor {
646 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
647 };
648 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
649 descriptor.get_next_level_table(0).as_ptr() as u64
650 });
651}
652
653#[test]
654fn test_descriptor_table_get_next_level_table_mut() {
655 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
656 let mut descriptor = Descriptor {
657 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
658 };
659 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
660 descriptor.get_next_level_table_mut(0).as_ptr() as *mut Descriptor as u64
661 });
662}
663
664#[test]
665fn test_descriptor_table_get_next_level_attr() {
666 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
667 let descriptor = Descriptor {
668 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
669 };
670 assert_eq!(
671 NextLevelAttributes {
672 ns_table: true,
673 ..Default::default()
674 },
675 descriptor.get_next_level_attributes(0)
676 );
677}
678
679#[test]
680fn test_descriptor_table_set_to_invalid() {
681 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
682 let mut descriptor = Descriptor {
683 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
684 };
685 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
686 descriptor.set_table_descriptor_to_invalid(0).as_ptr() as *mut Descriptor as u64
687 });
Imre Kisf5f6fa72024-04-18 14:04:21 +0200688 assert_eq!(0, descriptor.get());
Imre Kis703482d2023-11-30 15:51:26 +0100689}
690
691#[test]
692fn test_descriptor_raw_interface() {
693 let cell_value = 0x01234567_89abcdefu64;
694 let cell_new_value = 0x12345678_9abcdef0u64;
695
696 let mut descriptor = Descriptor {
697 cell: UnsafeCell::new(cell_value),
698 };
699
Imre Kisf5f6fa72024-04-18 14:04:21 +0200700 assert_eq!(cell_value, descriptor.get());
Imre Kis703482d2023-11-30 15:51:26 +0100701
Imre Kisf5f6fa72024-04-18 14:04:21 +0200702 descriptor.set(cell_new_value);
703 assert_eq!(cell_new_value, descriptor.get());
Imre Kis703482d2023-11-30 15:51:26 +0100704
Imre Kisf5f6fa72024-04-18 14:04:21 +0200705 descriptor.modify(|d| d + 1);
706 assert_eq!(cell_new_value + 1, descriptor.get());
Imre Kis703482d2023-11-30 15:51:26 +0100707}