blob: bf103803dc93c3e85b7e011cd0345c398cac40bd [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
205 /// Set table descriptor
206 ///
207 /// **Unsafe**: The caller has to ensure that the passed next level table has the same life as
208 /// the descriptor.
209 pub unsafe fn set_table_descriptor(
210 &mut self,
211 level: usize,
212 next_level_table: &mut [Descriptor],
213 next_level_attributes: Option<NextLevelAttributes>,
214 ) {
215 assert!(level <= 2);
216 assert_eq!(Self::TABLE_ENTRY_COUNT, next_level_table.len());
217 assert!(self.get_descriptor_type(level) != DescriptorType::Table);
218
219 let table_addr = KernelSpace::kernel_to_pa(next_level_table.as_ptr() as u64);
220 assert_eq!(0, table_addr & !Self::TA_MASK);
221
222 let mut raw_desc_value = Self::VALID_BIT | Self::TABLE_BIT | table_addr;
223
224 if let Some(next_attr) = next_level_attributes {
225 let next_attr_bits: u64 = next_attr.into();
226 assert_eq!(0, next_attr_bits & !Self::NEXT_ATTR_MASK);
227 raw_desc_value |= next_attr_bits;
228 }
229
230 self.set(raw_desc_value);
231 }
232
233 /// Get next level table
234 ///
235 /// **Unsafe**: The returned next level table is based on the address read from the descriptor.
236 /// The caller has to ensure that no other references are being used of the table.
237 pub unsafe fn get_next_level_table(&self, level: usize) -> &[Descriptor] {
238 assert!(level <= 2);
239 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
240
241 let table_address =
242 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *const Descriptor;
243 core::slice::from_raw_parts(table_address, Self::TABLE_ENTRY_COUNT)
244 }
245
246 /// Get mutable next level table
247 ///
248 /// **Unsafe**: The returned next level table is based on the address read from the descriptor.
249 /// The caller has to ensure that no other references are being used of the table.
250 pub unsafe fn get_next_level_table_mut(&mut self, level: usize) -> &mut [Descriptor] {
251 assert!(level <= 2);
252 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
253
254 let table_address =
255 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *mut Descriptor;
256 core::slice::from_raw_parts_mut(table_address, Self::TABLE_ENTRY_COUNT)
257 }
258
259 /// Get next level attributes
260 pub fn get_next_level_attributes(&self, level: usize) -> NextLevelAttributes {
261 assert!(level <= 2);
262 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
263
Imre Kisf5f6fa72024-04-18 14:04:21 +0200264 NextLevelAttributes::from(self.get() & Self::NEXT_ATTR_MASK)
Imre Kis703482d2023-11-30 15:51:26 +0100265 }
266
267 /// Set table descriptor to invalid
268 ///
269 /// **Unsafe:** The returned descriptor reference must be released by the caller, i.e. release
270 /// to `PagePool`
271 pub unsafe fn set_table_descriptor_to_invalid(&mut self, level: usize) -> &mut [Descriptor] {
272 assert!(level <= 2);
273 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
274
275 let table_address =
276 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *mut Descriptor;
277 self.set(Self::INVALID_DESCRIPTOR_VALUE);
278 core::slice::from_raw_parts_mut(table_address, Self::TABLE_ENTRY_COUNT)
279 }
280
281 /// Get raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200282 fn get(&self) -> u64 {
283 unsafe { ptr::read_volatile(self.cell.get()) }
Imre Kis703482d2023-11-30 15:51:26 +0100284 }
285
286 /// Set raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200287 fn set(&mut self, value: u64) {
288 unsafe { ptr::write_volatile(self.cell.get(), value) }
Imre Kis703482d2023-11-30 15:51:26 +0100289 }
290
291 /// Modify raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200292 fn modify<F>(&mut self, f: F)
Imre Kis703482d2023-11-30 15:51:26 +0100293 where
294 F: Fn(u64) -> u64,
295 {
296 self.set(f(self.get()))
297 }
298
299 /// Get output address mask
300 fn get_oa_mask(level: usize) -> usize {
301 Self::OA_MASK as usize & !(Self::GRANULE_SIZES[level] - 1)
302 }
303}
304
Imre Kis42935a22024-10-17 11:30:16 +0200305#[cfg(test)]
306mod tests {
307 use super::*;
Imre Kis703482d2023-11-30 15:51:26 +0100308
Imre Kis42935a22024-10-17 11:30:16 +0200309 #[test]
310 fn test_attributes() {
311 let attributes = Attributes::default();
312 assert_eq!(0u64, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100313
Imre Kis42935a22024-10-17 11:30:16 +0200314 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100315 uxn: true,
316 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200317 };
318 assert_eq!(1u64 << 54, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100319
Imre Kis42935a22024-10-17 11:30:16 +0200320 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100321 pxn: true,
322 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200323 };
324 assert_eq!(1u64 << 53, attributes.into());
325
326 let attributes = Attributes {
327 contiguous: true,
Imre Kis703482d2023-11-30 15:51:26 +0100328 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200329 };
330 assert_eq!(1u64 << 52, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100331
Imre Kis42935a22024-10-17 11:30:16 +0200332 let attributes = Attributes {
333 not_global: true,
334 ..Default::default()
335 };
336 assert_eq!(1u64 << 11, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100337
Imre Kis42935a22024-10-17 11:30:16 +0200338 let attributes = Attributes {
339 access_flag: true,
340 ..Default::default()
341 };
342 assert_eq!(1u64 << 10, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100343
Imre Kis42935a22024-10-17 11:30:16 +0200344 let attributes = Attributes {
345 non_secure: true,
346 ..Default::default()
347 };
348 assert_eq!(1u64 << 5, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100349
Imre Kis42935a22024-10-17 11:30:16 +0200350 let attributes = Attributes {
351 mem_attr_index: MemoryAttributesIndex::Normal_IWBWA_OWBWA,
352 ..Default::default()
353 };
354 assert_eq!(
355 (MemoryAttributesIndex::Normal_IWBWA_OWBWA as u64) << 2,
356 attributes.into()
357 );
Imre Kis703482d2023-11-30 15:51:26 +0100358
Imre Kis42935a22024-10-17 11:30:16 +0200359 let attributes: Attributes = 0.into();
360 assert!(!attributes.uxn);
361 assert!(!attributes.pxn);
362 assert!(!attributes.contiguous);
363 assert!(!attributes.not_global);
364 assert!(!attributes.access_flag);
365 assert_eq!(Shareability::NonShareable, attributes.shareability);
366 assert_eq!(
367 DataAccessPermissions::ReadWrite_None,
368 attributes.data_access_permissions
369 );
370 assert!(!attributes.non_secure);
371 assert_eq!(
372 MemoryAttributesIndex::Device_nGnRnE,
373 attributes.mem_attr_index
Imre Kis703482d2023-11-30 15:51:26 +0100374 );
375 }
Imre Kis703482d2023-11-30 15:51:26 +0100376
Imre Kis42935a22024-10-17 11:30:16 +0200377 #[test]
378 fn test_next_level_attributes() {
379 let next_level_attributes = NextLevelAttributes::default();
380 assert_eq!(0u64, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100381
Imre Kis42935a22024-10-17 11:30:16 +0200382 let next_level_attributes = NextLevelAttributes {
Imre Kis703482d2023-11-30 15:51:26 +0100383 ns_table: true,
384 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200385 };
386 assert_eq!(1u64 << 63, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100387
Imre Kis42935a22024-10-17 11:30:16 +0200388 let next_level_attributes = NextLevelAttributes {
389 ap_table: 3.into(),
390 ..Default::default()
391 };
392 assert_eq!(3u64 << 61, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100393
Imre Kis42935a22024-10-17 11:30:16 +0200394 let next_level_attributes = NextLevelAttributes {
395 xn_table: true,
396 ..Default::default()
397 };
398 assert_eq!(1u64 << 60, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100399
Imre Kis42935a22024-10-17 11:30:16 +0200400 let next_level_attributes = NextLevelAttributes {
401 pxn_table: true,
402 ..Default::default()
403 };
404 assert_eq!(1u64 << 59, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100405
Imre Kis42935a22024-10-17 11:30:16 +0200406 let next_level_attributes: NextLevelAttributes = 0.into();
407 assert!(!next_level_attributes.ns_table);
408 assert_eq!(0u8, next_level_attributes.ap_table.into());
409 assert!(!next_level_attributes.xn_table);
410 assert!(!next_level_attributes.pxn_table);
Imre Kis703482d2023-11-30 15:51:26 +0100411
Imre Kis42935a22024-10-17 11:30:16 +0200412 let next_level_attributes: NextLevelAttributes = u64::MAX.into();
413 assert!(next_level_attributes.ns_table);
414 assert_eq!(3u8, next_level_attributes.ap_table.into());
415 assert!(next_level_attributes.xn_table);
416 assert!(next_level_attributes.pxn_table);
417 }
Imre Kis703482d2023-11-30 15:51:26 +0100418
Imre Kis42935a22024-10-17 11:30:16 +0200419 #[test]
420 fn test_descriptor_get_type() {
421 let descriptor = Descriptor {
422 cell: UnsafeCell::new(0),
423 };
424 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(1));
425
426 let descriptor = Descriptor {
427 cell: UnsafeCell::new(1),
428 };
429 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(1));
430
431 let descriptor = Descriptor {
432 cell: UnsafeCell::new(3),
433 };
434 assert_eq!(DescriptorType::Table, descriptor.get_descriptor_type(1));
435
436 let descriptor = Descriptor {
437 cell: UnsafeCell::new(0),
438 };
439 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(3));
440
441 let descriptor = Descriptor {
442 cell: UnsafeCell::new(3),
443 };
444 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(3));
445 }
446
447 #[test]
448 fn test_descriptor_is_valid() {
449 let descriptor = Descriptor {
450 cell: UnsafeCell::new(0),
451 };
452 assert!(!descriptor.is_valid());
453
454 let descriptor = Descriptor {
455 cell: UnsafeCell::new(1),
456 };
457 assert!(descriptor.is_valid());
458 }
459
460 #[test]
461 fn test_descriptor_set_block_to_block_again() {
462 let mut descriptor = Descriptor {
463 cell: UnsafeCell::new(1),
464 };
465
Imre Kisd5b96fd2024-09-11 17:04:32 +0200466 descriptor.set_block_descriptor(1, PhysicalAddress(0), Attributes::default());
Imre Kis42935a22024-10-17 11:30:16 +0200467 assert_eq!(0x1, descriptor.get());
468 }
469
470 #[test]
471 #[should_panic]
472 fn test_descriptor_set_block_invalid_oa() {
473 let mut descriptor = Descriptor {
474 cell: UnsafeCell::new(0),
475 };
476
Imre Kisd5b96fd2024-09-11 17:04:32 +0200477 descriptor.set_block_descriptor(1, PhysicalAddress(1 << 63), Attributes::default());
Imre Kis42935a22024-10-17 11:30:16 +0200478 }
479
480 #[test]
481 fn test_descriptor_block() {
482 let mut descriptor = Descriptor {
483 cell: UnsafeCell::new(0),
484 };
485
486 descriptor.set_block_descriptor(
487 1,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200488 PhysicalAddress(0x0000000f_c0000000),
Imre Kis42935a22024-10-17 11:30:16 +0200489 Attributes {
490 uxn: true,
491 ..Default::default()
492 },
493 );
494 assert_eq!(0x0040000f_c0000001, descriptor.get());
495
496 let mut descriptor = Descriptor {
497 cell: UnsafeCell::new(0),
498 };
499
500 descriptor.set_block_descriptor(
501 3,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200502 PhysicalAddress(0x0000000f_fffff000),
Imre Kis42935a22024-10-17 11:30:16 +0200503 Attributes {
504 uxn: true,
505 ..Default::default()
506 },
507 );
508 assert_eq!(0x0040000f_fffff003, descriptor.get());
509
Imre Kisd5b96fd2024-09-11 17:04:32 +0200510 assert_eq!(
511 PhysicalAddress(0x0000000f_fffff000),
512 descriptor.get_block_output_address(3)
513 );
Imre Kis42935a22024-10-17 11:30:16 +0200514 assert_eq!(
515 Attributes {
516 uxn: true,
517 ..Default::default()
518 },
519 descriptor.get_block_attributes(3)
520 );
521
522 descriptor.set_block_attributes(
523 3,
524 Attributes {
525 pxn: true,
526 ..Default::default()
527 },
528 );
529 assert_eq!(
530 Attributes {
531 pxn: true,
532 ..Default::default()
533 },
534 descriptor.get_block_attributes(3)
535 );
536 }
537
538 #[test]
539 #[should_panic]
540 fn test_descriptor_invalid_block_to_invalid() {
541 let mut descriptor = Descriptor {
542 cell: UnsafeCell::new(0),
543 };
544
545 descriptor.set_block_descriptor_to_invalid(0);
546 }
547
548 #[test]
549 fn test_descriptor_block_to_invalid() {
550 let mut descriptor = Descriptor {
551 cell: UnsafeCell::new(3),
552 };
553
554 descriptor.set_block_descriptor_to_invalid(3);
555 assert_eq!(0, descriptor.get());
556 }
557
558 #[test]
559 #[should_panic]
560 fn test_descriptor_level3_to_table() {
561 let mut next_level_table = [Descriptor {
562 cell: UnsafeCell::new(0),
563 }];
564 let mut descriptor = Descriptor {
565 cell: UnsafeCell::new(0),
566 };
567
568 unsafe {
569 descriptor.set_table_descriptor(3, &mut next_level_table, None);
570 }
571 }
572
573 #[test]
574 fn test_descriptor_block_to_table() {
575 let next_level_table =
576 unsafe { core::slice::from_raw_parts_mut(0x1000 as *mut Descriptor, 512) };
577 let mut descriptor = Descriptor {
578 cell: UnsafeCell::new(1),
579 };
580
581 unsafe {
582 descriptor.set_table_descriptor(0, next_level_table, None);
583 }
584 assert_eq!(0x1003, descriptor.get());
585 }
586
587 #[test]
588 #[should_panic]
589 fn test_descriptor_table_invalid_count() {
590 let next_level_table =
591 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 511) };
592 let mut descriptor = Descriptor {
593 cell: UnsafeCell::new(0),
594 };
595
596 unsafe {
597 descriptor.set_table_descriptor(0, next_level_table, None);
598 }
599 }
600
601 #[test]
602 #[should_panic]
603 fn test_descriptor_table_non_aligned() {
604 let next_level_table =
605 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 512) };
606 let mut descriptor = Descriptor {
607 cell: UnsafeCell::new(0),
608 };
609
610 unsafe {
611 descriptor.set_table_descriptor(0, next_level_table, None);
612 }
613 }
614
615 #[test]
616 fn test_descriptor_table() {
617 let next_level_table = unsafe {
618 core::slice::from_raw_parts_mut(0x0000_000c_ba98_7000 as *mut Descriptor, 512)
619 };
620 let mut descriptor = Descriptor {
621 cell: UnsafeCell::new(0),
622 };
623
624 unsafe {
625 descriptor.set_table_descriptor(0, next_level_table, None);
626 }
627 assert_eq!(0x0000_000c_ba98_7003, descriptor.get());
628 }
629
630 #[test]
631 fn test_descriptor_table_next_level_attr() {
632 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
633 let next_level_table =
634 unsafe { core::slice::from_raw_parts_mut(NEXT_LEVEL_ADDR as *mut Descriptor, 512) };
635 let mut descriptor = Descriptor {
636 cell: UnsafeCell::new(0),
637 };
638
639 unsafe {
640 descriptor.set_table_descriptor(
641 0,
642 next_level_table,
643 Some(NextLevelAttributes {
644 ns_table: true,
645 ..Default::default()
646 }),
647 );
648 }
649 assert_eq!(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003, descriptor.get());
650 }
651
652 #[test]
653 fn test_descriptor_table_get_next_level_table() {
654 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
655 let descriptor = Descriptor {
656 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
657 };
658 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
659 descriptor.get_next_level_table(0).as_ptr() as u64
660 });
661 }
662
663 #[test]
664 fn test_descriptor_table_get_next_level_table_mut() {
665 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
666 let mut descriptor = Descriptor {
667 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
668 };
669 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
670 descriptor.get_next_level_table_mut(0).as_ptr() as *mut Descriptor as u64
671 });
672 }
673
674 #[test]
675 fn test_descriptor_table_get_next_level_attr() {
676 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
677 let descriptor = Descriptor {
678 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
679 };
680 assert_eq!(
681 NextLevelAttributes {
682 ns_table: true,
683 ..Default::default()
684 },
685 descriptor.get_next_level_attributes(0)
686 );
687 }
688
689 #[test]
690 fn test_descriptor_table_set_to_invalid() {
691 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
692 let mut descriptor = Descriptor {
693 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
694 };
695 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
696 descriptor.set_table_descriptor_to_invalid(0).as_ptr() as *mut Descriptor as u64
697 });
698 assert_eq!(0, descriptor.get());
699 }
700
701 #[test]
702 fn test_descriptor_raw_interface() {
703 let cell_value = 0x01234567_89abcdefu64;
704 let cell_new_value = 0x12345678_9abcdef0u64;
705
706 let mut descriptor = Descriptor {
707 cell: UnsafeCell::new(cell_value),
708 };
709
710 assert_eq!(cell_value, descriptor.get());
711
712 descriptor.set(cell_new_value);
713 assert_eq!(cell_new_value, descriptor.get());
714
715 descriptor.modify(|d| d + 1);
716 assert_eq!(cell_new_value + 1, descriptor.get());
717 }
Imre Kis703482d2023-11-30 15:51:26 +0100718}