blob: 6f370ecd935fabaaa46a781fa5e997be43fb803c [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
Imre Kis42935a22024-10-17 11:30:16 +0200303#[cfg(test)]
304mod tests {
305 use super::*;
Imre Kis703482d2023-11-30 15:51:26 +0100306
Imre Kis42935a22024-10-17 11:30:16 +0200307 #[test]
308 fn test_attributes() {
309 let attributes = Attributes::default();
310 assert_eq!(0u64, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100311
Imre Kis42935a22024-10-17 11:30:16 +0200312 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100313 uxn: true,
314 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200315 };
316 assert_eq!(1u64 << 54, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100317
Imre Kis42935a22024-10-17 11:30:16 +0200318 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100319 pxn: true,
320 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200321 };
322 assert_eq!(1u64 << 53, attributes.into());
323
324 let attributes = Attributes {
325 contiguous: true,
Imre Kis703482d2023-11-30 15:51:26 +0100326 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200327 };
328 assert_eq!(1u64 << 52, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100329
Imre Kis42935a22024-10-17 11:30:16 +0200330 let attributes = Attributes {
331 not_global: true,
332 ..Default::default()
333 };
334 assert_eq!(1u64 << 11, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100335
Imre Kis42935a22024-10-17 11:30:16 +0200336 let attributes = Attributes {
337 access_flag: true,
338 ..Default::default()
339 };
340 assert_eq!(1u64 << 10, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100341
Imre Kis42935a22024-10-17 11:30:16 +0200342 let attributes = Attributes {
343 non_secure: true,
344 ..Default::default()
345 };
346 assert_eq!(1u64 << 5, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100347
Imre Kis42935a22024-10-17 11:30:16 +0200348 let attributes = Attributes {
349 mem_attr_index: MemoryAttributesIndex::Normal_IWBWA_OWBWA,
350 ..Default::default()
351 };
352 assert_eq!(
353 (MemoryAttributesIndex::Normal_IWBWA_OWBWA as u64) << 2,
354 attributes.into()
355 );
Imre Kis703482d2023-11-30 15:51:26 +0100356
Imre Kis42935a22024-10-17 11:30:16 +0200357 let attributes: Attributes = 0.into();
358 assert!(!attributes.uxn);
359 assert!(!attributes.pxn);
360 assert!(!attributes.contiguous);
361 assert!(!attributes.not_global);
362 assert!(!attributes.access_flag);
363 assert_eq!(Shareability::NonShareable, attributes.shareability);
364 assert_eq!(
365 DataAccessPermissions::ReadWrite_None,
366 attributes.data_access_permissions
367 );
368 assert!(!attributes.non_secure);
369 assert_eq!(
370 MemoryAttributesIndex::Device_nGnRnE,
371 attributes.mem_attr_index
Imre Kis703482d2023-11-30 15:51:26 +0100372 );
373 }
Imre Kis703482d2023-11-30 15:51:26 +0100374
Imre Kis42935a22024-10-17 11:30:16 +0200375 #[test]
376 fn test_next_level_attributes() {
377 let next_level_attributes = NextLevelAttributes::default();
378 assert_eq!(0u64, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100379
Imre Kis42935a22024-10-17 11:30:16 +0200380 let next_level_attributes = NextLevelAttributes {
Imre Kis703482d2023-11-30 15:51:26 +0100381 ns_table: true,
382 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200383 };
384 assert_eq!(1u64 << 63, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100385
Imre Kis42935a22024-10-17 11:30:16 +0200386 let next_level_attributes = NextLevelAttributes {
387 ap_table: 3.into(),
388 ..Default::default()
389 };
390 assert_eq!(3u64 << 61, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100391
Imre Kis42935a22024-10-17 11:30:16 +0200392 let next_level_attributes = NextLevelAttributes {
393 xn_table: true,
394 ..Default::default()
395 };
396 assert_eq!(1u64 << 60, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100397
Imre Kis42935a22024-10-17 11:30:16 +0200398 let next_level_attributes = NextLevelAttributes {
399 pxn_table: true,
400 ..Default::default()
401 };
402 assert_eq!(1u64 << 59, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100403
Imre Kis42935a22024-10-17 11:30:16 +0200404 let next_level_attributes: NextLevelAttributes = 0.into();
405 assert!(!next_level_attributes.ns_table);
406 assert_eq!(0u8, next_level_attributes.ap_table.into());
407 assert!(!next_level_attributes.xn_table);
408 assert!(!next_level_attributes.pxn_table);
Imre Kis703482d2023-11-30 15:51:26 +0100409
Imre Kis42935a22024-10-17 11:30:16 +0200410 let next_level_attributes: NextLevelAttributes = u64::MAX.into();
411 assert!(next_level_attributes.ns_table);
412 assert_eq!(3u8, next_level_attributes.ap_table.into());
413 assert!(next_level_attributes.xn_table);
414 assert!(next_level_attributes.pxn_table);
415 }
Imre Kis703482d2023-11-30 15:51:26 +0100416
Imre Kis42935a22024-10-17 11:30:16 +0200417 #[test]
418 fn test_descriptor_get_type() {
419 let descriptor = Descriptor {
420 cell: UnsafeCell::new(0),
421 };
422 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(1));
423
424 let descriptor = Descriptor {
425 cell: UnsafeCell::new(1),
426 };
427 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(1));
428
429 let descriptor = Descriptor {
430 cell: UnsafeCell::new(3),
431 };
432 assert_eq!(DescriptorType::Table, descriptor.get_descriptor_type(1));
433
434 let descriptor = Descriptor {
435 cell: UnsafeCell::new(0),
436 };
437 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(3));
438
439 let descriptor = Descriptor {
440 cell: UnsafeCell::new(3),
441 };
442 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(3));
443 }
444
445 #[test]
446 fn test_descriptor_is_valid() {
447 let descriptor = Descriptor {
448 cell: UnsafeCell::new(0),
449 };
450 assert!(!descriptor.is_valid());
451
452 let descriptor = Descriptor {
453 cell: UnsafeCell::new(1),
454 };
455 assert!(descriptor.is_valid());
456 }
457
458 #[test]
459 fn test_descriptor_set_block_to_block_again() {
460 let mut descriptor = Descriptor {
461 cell: UnsafeCell::new(1),
462 };
463
464 descriptor.set_block_descriptor(1, 0, Attributes::default());
465 assert_eq!(0x1, descriptor.get());
466 }
467
468 #[test]
469 #[should_panic]
470 fn test_descriptor_set_block_invalid_oa() {
471 let mut descriptor = Descriptor {
472 cell: UnsafeCell::new(0),
473 };
474
475 descriptor.set_block_descriptor(1, 1 << 63, Attributes::default());
476 }
477
478 #[test]
479 fn test_descriptor_block() {
480 let mut descriptor = Descriptor {
481 cell: UnsafeCell::new(0),
482 };
483
484 descriptor.set_block_descriptor(
485 1,
486 0x0000000f_c0000000,
487 Attributes {
488 uxn: true,
489 ..Default::default()
490 },
491 );
492 assert_eq!(0x0040000f_c0000001, descriptor.get());
493
494 let mut descriptor = Descriptor {
495 cell: UnsafeCell::new(0),
496 };
497
498 descriptor.set_block_descriptor(
499 3,
500 0x0000000f_fffff000,
501 Attributes {
502 uxn: true,
503 ..Default::default()
504 },
505 );
506 assert_eq!(0x0040000f_fffff003, descriptor.get());
507
508 assert_eq!(0x0000000f_fffff000, descriptor.get_block_output_address(3));
509 assert_eq!(
510 Attributes {
511 uxn: true,
512 ..Default::default()
513 },
514 descriptor.get_block_attributes(3)
515 );
516
517 descriptor.set_block_attributes(
518 3,
519 Attributes {
520 pxn: true,
521 ..Default::default()
522 },
523 );
524 assert_eq!(
525 Attributes {
526 pxn: true,
527 ..Default::default()
528 },
529 descriptor.get_block_attributes(3)
530 );
531 }
532
533 #[test]
534 #[should_panic]
535 fn test_descriptor_invalid_block_to_invalid() {
536 let mut descriptor = Descriptor {
537 cell: UnsafeCell::new(0),
538 };
539
540 descriptor.set_block_descriptor_to_invalid(0);
541 }
542
543 #[test]
544 fn test_descriptor_block_to_invalid() {
545 let mut descriptor = Descriptor {
546 cell: UnsafeCell::new(3),
547 };
548
549 descriptor.set_block_descriptor_to_invalid(3);
550 assert_eq!(0, descriptor.get());
551 }
552
553 #[test]
554 #[should_panic]
555 fn test_descriptor_level3_to_table() {
556 let mut next_level_table = [Descriptor {
557 cell: UnsafeCell::new(0),
558 }];
559 let mut descriptor = Descriptor {
560 cell: UnsafeCell::new(0),
561 };
562
563 unsafe {
564 descriptor.set_table_descriptor(3, &mut next_level_table, None);
565 }
566 }
567
568 #[test]
569 fn test_descriptor_block_to_table() {
570 let next_level_table =
571 unsafe { core::slice::from_raw_parts_mut(0x1000 as *mut Descriptor, 512) };
572 let mut descriptor = Descriptor {
573 cell: UnsafeCell::new(1),
574 };
575
576 unsafe {
577 descriptor.set_table_descriptor(0, next_level_table, None);
578 }
579 assert_eq!(0x1003, descriptor.get());
580 }
581
582 #[test]
583 #[should_panic]
584 fn test_descriptor_table_invalid_count() {
585 let next_level_table =
586 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 511) };
587 let mut descriptor = Descriptor {
588 cell: UnsafeCell::new(0),
589 };
590
591 unsafe {
592 descriptor.set_table_descriptor(0, next_level_table, None);
593 }
594 }
595
596 #[test]
597 #[should_panic]
598 fn test_descriptor_table_non_aligned() {
599 let next_level_table =
600 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 512) };
601 let mut descriptor = Descriptor {
602 cell: UnsafeCell::new(0),
603 };
604
605 unsafe {
606 descriptor.set_table_descriptor(0, next_level_table, None);
607 }
608 }
609
610 #[test]
611 fn test_descriptor_table() {
612 let next_level_table = unsafe {
613 core::slice::from_raw_parts_mut(0x0000_000c_ba98_7000 as *mut Descriptor, 512)
614 };
615 let mut descriptor = Descriptor {
616 cell: UnsafeCell::new(0),
617 };
618
619 unsafe {
620 descriptor.set_table_descriptor(0, next_level_table, None);
621 }
622 assert_eq!(0x0000_000c_ba98_7003, descriptor.get());
623 }
624
625 #[test]
626 fn test_descriptor_table_next_level_attr() {
627 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
628 let next_level_table =
629 unsafe { core::slice::from_raw_parts_mut(NEXT_LEVEL_ADDR as *mut Descriptor, 512) };
630 let mut descriptor = Descriptor {
631 cell: UnsafeCell::new(0),
632 };
633
634 unsafe {
635 descriptor.set_table_descriptor(
636 0,
637 next_level_table,
638 Some(NextLevelAttributes {
639 ns_table: true,
640 ..Default::default()
641 }),
642 );
643 }
644 assert_eq!(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003, descriptor.get());
645 }
646
647 #[test]
648 fn test_descriptor_table_get_next_level_table() {
649 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
650 let descriptor = Descriptor {
651 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
652 };
653 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
654 descriptor.get_next_level_table(0).as_ptr() as u64
655 });
656 }
657
658 #[test]
659 fn test_descriptor_table_get_next_level_table_mut() {
660 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
661 let mut descriptor = Descriptor {
662 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
663 };
664 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
665 descriptor.get_next_level_table_mut(0).as_ptr() as *mut Descriptor as u64
666 });
667 }
668
669 #[test]
670 fn test_descriptor_table_get_next_level_attr() {
671 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
672 let descriptor = Descriptor {
673 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
674 };
675 assert_eq!(
676 NextLevelAttributes {
677 ns_table: true,
678 ..Default::default()
679 },
680 descriptor.get_next_level_attributes(0)
681 );
682 }
683
684 #[test]
685 fn test_descriptor_table_set_to_invalid() {
686 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
687 let mut descriptor = Descriptor {
688 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
689 };
690 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
691 descriptor.set_table_descriptor_to_invalid(0).as_ptr() as *mut Descriptor as u64
692 });
693 assert_eq!(0, descriptor.get());
694 }
695
696 #[test]
697 fn test_descriptor_raw_interface() {
698 let cell_value = 0x01234567_89abcdefu64;
699 let cell_new_value = 0x12345678_9abcdef0u64;
700
701 let mut descriptor = Descriptor {
702 cell: UnsafeCell::new(cell_value),
703 };
704
705 assert_eq!(cell_value, descriptor.get());
706
707 descriptor.set(cell_new_value);
708 assert_eq!(cell_new_value, descriptor.get());
709
710 descriptor.modify(|d| d + 1);
711 assert_eq!(cell_new_value + 1, descriptor.get());
712 }
Imre Kis703482d2023-11-30 15:51:26 +0100713}