blob: 627799cbb49c57e97f724ebb668a529cc98401a4 [file] [log] [blame]
Imre Kis703482d2023-11-30 15:51:26 +01001// SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Memory descriptor
5
6use packed_struct::prelude::*;
7
8use core::cell::UnsafeCell;
9use core::ptr;
10
11use crate::kernel_space::KernelSpace;
12use crate::MemoryAttributesIndex;
13
Imre Kisd5b96fd2024-09-11 17:04:32 +020014use super::address::PhysicalAddress;
Imre Kis631127d2024-11-21 13:09:01 +010015use super::TranslationGranule;
Imre Kisd5b96fd2024-09-11 17:04:32 +020016
Imre Kis703482d2023-11-30 15:51:26 +010017/// Memory shareability
18#[derive(PrimitiveEnum_u8, Clone, Copy, Debug, PartialEq, Eq, Default)]
19pub enum Shareability {
20 #[default]
21 NonShareable = 0b00,
22 Outer = 0b10,
23 Inner = 0b11,
24}
25
26/// Data access permission
Imre Kis1278c9f2025-01-15 19:48:36 +010027#[allow(non_camel_case_types)]
Imre Kis703482d2023-11-30 15:51:26 +010028#[derive(PrimitiveEnum_u8, Clone, Copy, Debug, PartialEq, Eq, Default)]
29pub enum DataAccessPermissions {
30 #[default]
31 ReadWrite_None = 0b00,
32 ReadWrite_ReadWrite = 0b01,
33 ReadOnly_None = 0b10,
34 ReadOnly_ReadOnly = 0b11,
35}
36
37/// Memory attributes
38#[derive(PackedStruct, Clone, Debug, PartialEq, Eq, Default)]
39#[packed_struct(size_bytes = "8", bit_numbering = "lsb0")]
40pub struct Attributes {
41 #[packed_field(bits = "54")]
42 pub uxn: bool,
43 #[packed_field(bits = "53")]
44 pub pxn: bool,
45 #[packed_field(bits = "52")]
46 pub contiguous: bool,
47 #[packed_field(bits = "11")]
48 pub not_global: bool,
49 #[packed_field(bits = "10")]
50 pub access_flag: bool,
51 #[packed_field(bits = "9..=8", ty = "enum")]
52 pub shareability: Shareability,
53 #[packed_field(bits = "7..=6", ty = "enum")]
54 pub data_access_permissions: DataAccessPermissions,
55 #[packed_field(bits = "5")]
56 pub non_secure: bool,
57 #[packed_field(bits = "4..=2", ty = "enum")]
58 pub mem_attr_index: MemoryAttributesIndex,
59}
60
61impl From<Attributes> for u64 {
62 fn from(attributes: Attributes) -> Self {
63 u64::from_be_bytes(attributes.pack().unwrap())
64 }
65}
66
67impl From<u64> for Attributes {
68 fn from(bits: u64) -> Self {
69 Self::unpack(&bits.to_be_bytes()).unwrap()
70 }
71}
72
73/// Next level attributes
74#[derive(PackedStruct, Clone, Debug, PartialEq, Eq, Default)]
75#[packed_struct(size_bytes = "8", bit_numbering = "lsb0")]
76pub struct NextLevelAttributes {
77 #[packed_field(bits = "63")]
78 ns_table: bool,
79 #[packed_field(bits = "62..=61")]
80 ap_table: Integer<u8, packed_bits::Bits<2>>,
81 #[packed_field(bits = "60")]
82 xn_table: bool,
83 #[packed_field(bits = "59")]
84 pxn_table: bool,
85}
86
87impl From<NextLevelAttributes> for u64 {
88 fn from(attributes: NextLevelAttributes) -> Self {
89 u64::from_be_bytes(attributes.pack().unwrap())
90 }
91}
92
93impl From<u64> for NextLevelAttributes {
94 fn from(bits: u64) -> Self {
95 Self::unpack(&bits.to_be_bytes()).unwrap()
96 }
97}
98
99/// Memory descriptor type
100#[derive(PartialEq, Eq, Debug)]
101pub enum DescriptorType {
102 Invalid,
103 Block,
104 Table,
105}
106
107/// Memory descriptor of a memory translation table
108#[repr(C)]
Imre Kisf5f6fa72024-04-18 14:04:21 +0200109#[derive(Default)]
Imre Kis703482d2023-11-30 15:51:26 +0100110pub struct Descriptor {
111 cell: UnsafeCell<u64>,
112}
113
114impl Descriptor {
115 const ATTR_MASK: u64 = 0xfff8_0000_0000_0ffc;
116 const DESCRIPTOR_TYPE_MASK: u64 = 0b11;
Imre Kis703482d2023-11-30 15:51:26 +0100117 const INVALID_DESCRIPTOR_VALUE: u64 = 0x0;
118 const NEXT_ATTR_MASK: u64 = 0xf800_0000_0000_0000;
Imre Kis703482d2023-11-30 15:51:26 +0100119 const TABLE_BIT: u64 = 0b10;
Imre Kis703482d2023-11-30 15:51:26 +0100120 const TA_MASK: u64 = 0x0000_ffff_ffff_f000;
121 const VALID_BIT: u64 = 0b01;
122
123 /// Query descriptor type
Imre Kis631127d2024-11-21 13:09:01 +0100124 pub fn get_descriptor_type(&self, level: isize) -> DescriptorType {
Imre Kis703482d2023-11-30 15:51:26 +0100125 assert!(level <= 3);
126
Imre Kisf5f6fa72024-04-18 14:04:21 +0200127 let desc_type_bits = self.get() & Self::DESCRIPTOR_TYPE_MASK;
Imre Kis703482d2023-11-30 15:51:26 +0100128 if desc_type_bits & Self::VALID_BIT != 0 {
129 if level == 3 {
130 assert_eq!(Self::TABLE_BIT, desc_type_bits & Self::TABLE_BIT);
131 DescriptorType::Block
132 } else if desc_type_bits & Self::TABLE_BIT != 0 {
133 DescriptorType::Table
134 } else {
135 DescriptorType::Block
136 }
137 } else {
138 DescriptorType::Invalid
139 }
140 }
141
142 // Invalid descriptor functions
143
144 /// Check if it is a valid descriptor
145 pub fn is_valid(&self) -> bool {
Imre Kisf5f6fa72024-04-18 14:04:21 +0200146 self.get() & Self::VALID_BIT != 0
Imre Kis703482d2023-11-30 15:51:26 +0100147 }
148
149 // Block descriptor functions
150
151 /// Set block descriptor
Imre Kis631127d2024-11-21 13:09:01 +0100152 pub fn set_block_descriptor<const VA_BITS: usize>(
Imre Kis703482d2023-11-30 15:51:26 +0100153 &mut self,
Imre Kis631127d2024-11-21 13:09:01 +0100154 granule: TranslationGranule<VA_BITS>,
155 level: isize,
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 Kis703482d2023-11-30 15:51:26 +0100163 assert_eq!(0, attr & !Self::ATTR_MASK);
164
Imre Kis631127d2024-11-21 13:09:01 +0100165 let oa_granule_mask = !(granule.block_size_at_level(level) - 1);
166
167 // Figure D8-14 VMSAv8-64 Block descriptor formats
168 let oa_bits = match granule {
169 // 4KB and 16KB granules, 52-bit OA
170 #[cfg(feature = "feat_lpa2")]
171 TranslationGranule::Granule4k | TranslationGranule::Granule16k => {
172 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_f000;
173 assert_eq!(0, output_address.0 & !oa_mask);
174
175 let address = output_address.0 & oa_mask;
176
177 // OA[49:n] remains in place, OA[51:50] is mapped to [9:8]
178 let lsbs = address & 0x0003_ffff_ffff_f000;
179 let msbs = ((address >> 50) & 0x3) << 8;
180
181 lsbs | msbs
182 }
183
184 // 64KB granule, 52-bit OA
185 #[cfg(feature = "feat_lpa")]
186 TranslationGranule::Granule64k => {
187 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_0000;
188 assert_eq!(0, output_address.0 & !oa_mask);
189
190 let address = output_address.0 & oa_mask;
191
192 // OA[47:n] remains in place, OA[51:48] is mapped to [15:12]
193 let lsbs = address & 0x0000_ffff_ffff_0000;
194 let msbs = ((address >> 48) & 0xf) << 12;
195
196 lsbs | msbs
197 }
198
199 // 4KB, 16KB, and 64KB granules, 48-bit OA
200 #[cfg(not(all(feature = "feat_lpa", feature = "feat_lpa2")))]
201 _ => {
202 let oa_mask = oa_granule_mask & 0x0000_ffff_ffff_f000;
203 assert_eq!(0, output_address.0 & !oa_mask);
204 output_address.0 & oa_mask
205 }
206 };
207
Imre Kis703482d2023-11-30 15:51:26 +0100208 let table_bit = if level < 3 { 0 } else { Self::TABLE_BIT };
209
Imre Kis631127d2024-11-21 13:09:01 +0100210 self.set(Self::VALID_BIT | table_bit | oa_bits as u64 | attr);
Imre Kis703482d2023-11-30 15:51:26 +0100211 }
212
213 /// Get output address from the block descriptor
Imre Kis631127d2024-11-21 13:09:01 +0100214 pub fn get_block_output_address<const VA_BITS: usize>(
215 &self,
216 granule: TranslationGranule<VA_BITS>,
217 level: isize,
218 ) -> PhysicalAddress {
Imre Kis703482d2023-11-30 15:51:26 +0100219 assert!(level <= 3);
220 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
221
Imre Kis631127d2024-11-21 13:09:01 +0100222 let oa_granule_mask = !(granule.block_size_at_level(level) - 1);
223 let descriptor_value = self.get();
224
225 // Figure D8-14 VMSAv8-64 Block descriptor formats
226 let pa = match granule {
227 // 4KB and 16KB granules, 52-bit OA
228 #[cfg(feature = "feat_lpa2")]
229 TranslationGranule::Granule4k | TranslationGranule::Granule16k => {
230 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_f000;
231
232 // OA[49:n] remains in place, OA[51:50] is mapped from [9:8]
233 let lsbs = descriptor_value & 0x0003_ffff_ffff_f000;
234 let msbs = ((descriptor_value >> 8) & 0x3) << 50;
235
236 (lsbs | msbs) as usize & oa_mask
237 }
238
239 // 64KB granule, 52-bit OA
240 #[cfg(feature = "feat_lpa")]
241 TranslationGranule::Granule64k => {
242 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_0000;
243
244 // OA[47:n] remains in place, OA[51:48] is mapped from [15:12]
245 let lsbs = descriptor_value & 0x0003_ffff_ffff_0000;
246 let msbs = ((descriptor_value >> 12) & 0xf) << 48;
247
248 (lsbs | msbs) as usize & oa_mask
249 }
250
251 // 4KB, 16KB, and 64KB granules, 48-bit OA
252 #[cfg(not(all(feature = "feat_lpa", feature = "feat_lpa2")))]
253 _ => {
254 let oa_mask = oa_granule_mask & 0x0000_ffff_ffff_f000;
255 descriptor_value as usize & oa_mask
256 }
257 };
258
259 PhysicalAddress(pa)
Imre Kis703482d2023-11-30 15:51:26 +0100260 }
261
262 /// Set the attributes of the block descriptor
Imre Kis631127d2024-11-21 13:09:01 +0100263 pub fn set_block_attributes(&mut self, level: isize, attributes: Attributes) {
Imre Kis703482d2023-11-30 15:51:26 +0100264 assert!(level <= 3);
265 let attr: u64 = attributes.into();
266 assert_eq!(0, attr & !Self::ATTR_MASK);
267 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
268
Imre Kisf5f6fa72024-04-18 14:04:21 +0200269 self.modify(|d| (d & !Self::ATTR_MASK) | attr);
Imre Kis703482d2023-11-30 15:51:26 +0100270 }
271
272 /// Get the attributes of the block descriptor
Imre Kis631127d2024-11-21 13:09:01 +0100273 pub fn get_block_attributes(&self, level: isize) -> Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100274 assert!(level <= 3);
275 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
276
Imre Kisf5f6fa72024-04-18 14:04:21 +0200277 Attributes::from(self.get() & Self::ATTR_MASK)
Imre Kis703482d2023-11-30 15:51:26 +0100278 }
279
280 /// Set block descriptor to invalid
Imre Kis631127d2024-11-21 13:09:01 +0100281 pub fn set_block_descriptor_to_invalid(&mut self, level: isize) {
Imre Kis703482d2023-11-30 15:51:26 +0100282 assert!(level <= 3);
283 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
284
Imre Kisf5f6fa72024-04-18 14:04:21 +0200285 self.set(Self::INVALID_DESCRIPTOR_VALUE)
Imre Kis703482d2023-11-30 15:51:26 +0100286 }
287
Imre Kis9a9d0492024-10-31 15:19:46 +0100288 /// Set block or invalid descriptor to invalid
Imre Kis631127d2024-11-21 13:09:01 +0100289 pub fn set_block_or_invalid_descriptor_to_invalid(&mut self, level: isize) {
Imre Kis9a9d0492024-10-31 15:19:46 +0100290 assert!(level <= 3);
291 assert!(DescriptorType::Table != self.get_descriptor_type(level));
292
293 self.set(Self::INVALID_DESCRIPTOR_VALUE)
294 }
295
Imre Kis703482d2023-11-30 15:51:26 +0100296 /// Set table descriptor
297 ///
Imre Kis9a9d0492024-10-31 15:19:46 +0100298 /// Safety: The caller has to ensure that the passed next level table has the same life as
Imre Kis703482d2023-11-30 15:51:26 +0100299 /// the descriptor.
300 pub unsafe fn set_table_descriptor(
301 &mut self,
Imre Kis631127d2024-11-21 13:09:01 +0100302 level: isize,
Imre Kis703482d2023-11-30 15:51:26 +0100303 next_level_table: &mut [Descriptor],
304 next_level_attributes: Option<NextLevelAttributes>,
305 ) {
306 assert!(level <= 2);
Imre Kis703482d2023-11-30 15:51:26 +0100307 assert!(self.get_descriptor_type(level) != DescriptorType::Table);
308
309 let table_addr = KernelSpace::kernel_to_pa(next_level_table.as_ptr() as u64);
310 assert_eq!(0, table_addr & !Self::TA_MASK);
311
312 let mut raw_desc_value = Self::VALID_BIT | Self::TABLE_BIT | table_addr;
313
314 if let Some(next_attr) = next_level_attributes {
315 let next_attr_bits: u64 = next_attr.into();
316 assert_eq!(0, next_attr_bits & !Self::NEXT_ATTR_MASK);
317 raw_desc_value |= next_attr_bits;
318 }
319
320 self.set(raw_desc_value);
321 }
322
323 /// Get next level table
324 ///
Imre Kis9a9d0492024-10-31 15:19:46 +0100325 /// Safety: The returned next level table is based on the address read from the descriptor.
Imre Kis703482d2023-11-30 15:51:26 +0100326 /// The caller has to ensure that no other references are being used of the table.
Imre Kis631127d2024-11-21 13:09:01 +0100327 pub unsafe fn get_next_level_table<const VA_BITS: usize>(
328 &self,
329 granule: TranslationGranule<VA_BITS>,
330 level: isize,
331 ) -> &[Descriptor] {
Imre Kis703482d2023-11-30 15:51:26 +0100332 assert!(level <= 2);
333 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
334
335 let table_address =
336 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *const Descriptor;
Imre Kis631127d2024-11-21 13:09:01 +0100337 core::slice::from_raw_parts(table_address, granule.entry_count_at_level(level + 1))
Imre Kis703482d2023-11-30 15:51:26 +0100338 }
339
340 /// Get mutable next level table
341 ///
Imre Kis9a9d0492024-10-31 15:19:46 +0100342 /// Safety: The returned next level table is based on the address read from the descriptor.
Imre Kis703482d2023-11-30 15:51:26 +0100343 /// The caller has to ensure that no other references are being used of the table.
Imre Kis631127d2024-11-21 13:09:01 +0100344 pub unsafe fn get_next_level_table_mut<const VA_BITS: usize>(
345 &mut self,
346 granule: TranslationGranule<VA_BITS>,
347 level: isize,
348 ) -> &mut [Descriptor] {
Imre Kis703482d2023-11-30 15:51:26 +0100349 assert!(level <= 2);
350 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
351
352 let table_address =
353 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *mut Descriptor;
Imre Kis631127d2024-11-21 13:09:01 +0100354 core::slice::from_raw_parts_mut(table_address, granule.entry_count_at_level(level + 1))
Imre Kis703482d2023-11-30 15:51:26 +0100355 }
356
357 /// Get next level attributes
Imre Kis631127d2024-11-21 13:09:01 +0100358 pub fn get_next_level_attributes(&self, level: isize) -> NextLevelAttributes {
Imre Kis703482d2023-11-30 15:51:26 +0100359 assert!(level <= 2);
360 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
361
Imre Kisf5f6fa72024-04-18 14:04:21 +0200362 NextLevelAttributes::from(self.get() & Self::NEXT_ATTR_MASK)
Imre Kis703482d2023-11-30 15:51:26 +0100363 }
364
365 /// Set table descriptor to invalid
366 ///
367 /// **Unsafe:** The returned descriptor reference must be released by the caller, i.e. release
368 /// to `PagePool`
Imre Kis631127d2024-11-21 13:09:01 +0100369 pub unsafe fn set_table_descriptor_to_invalid<const VA_BITS: usize>(
370 &mut self,
371 granule: TranslationGranule<VA_BITS>,
372 level: isize,
373 ) -> &mut [Descriptor] {
Imre Kis703482d2023-11-30 15:51:26 +0100374 assert!(level <= 2);
375 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
376
377 let table_address =
378 KernelSpace::pa_to_kernel(self.get() & Self::TA_MASK) as *mut Descriptor;
379 self.set(Self::INVALID_DESCRIPTOR_VALUE);
Imre Kis631127d2024-11-21 13:09:01 +0100380 core::slice::from_raw_parts_mut(table_address, granule.entry_count_at_level(level + 1))
Imre Kis703482d2023-11-30 15:51:26 +0100381 }
382
383 /// Get raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200384 fn get(&self) -> u64 {
385 unsafe { ptr::read_volatile(self.cell.get()) }
Imre Kis703482d2023-11-30 15:51:26 +0100386 }
387
388 /// Set raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200389 fn set(&mut self, value: u64) {
Imre Kis9a9d0492024-10-31 15:19:46 +0100390 // Safety: The cell should point to a valid address and the assembly code is just a data
391 // barrier.
392 unsafe {
393 ptr::write_volatile(self.cell.get(), value);
394 #[cfg(target_arch = "aarch64")]
395 core::arch::asm!("dsb nsh");
396 }
Imre Kis703482d2023-11-30 15:51:26 +0100397 }
398
399 /// Modify raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200400 fn modify<F>(&mut self, f: F)
Imre Kis703482d2023-11-30 15:51:26 +0100401 where
402 F: Fn(u64) -> u64,
403 {
404 self.set(f(self.get()))
405 }
Imre Kis703482d2023-11-30 15:51:26 +0100406}
407
Imre Kis42935a22024-10-17 11:30:16 +0200408#[cfg(test)]
409mod tests {
410 use super::*;
Imre Kis703482d2023-11-30 15:51:26 +0100411
Imre Kis42935a22024-10-17 11:30:16 +0200412 #[test]
413 fn test_attributes() {
414 let attributes = Attributes::default();
415 assert_eq!(0u64, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100416
Imre Kis42935a22024-10-17 11:30:16 +0200417 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100418 uxn: true,
419 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200420 };
421 assert_eq!(1u64 << 54, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100422
Imre Kis42935a22024-10-17 11:30:16 +0200423 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100424 pxn: true,
425 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200426 };
427 assert_eq!(1u64 << 53, attributes.into());
428
429 let attributes = Attributes {
430 contiguous: true,
Imre Kis703482d2023-11-30 15:51:26 +0100431 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200432 };
433 assert_eq!(1u64 << 52, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100434
Imre Kis42935a22024-10-17 11:30:16 +0200435 let attributes = Attributes {
436 not_global: true,
437 ..Default::default()
438 };
439 assert_eq!(1u64 << 11, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100440
Imre Kis42935a22024-10-17 11:30:16 +0200441 let attributes = Attributes {
442 access_flag: true,
443 ..Default::default()
444 };
445 assert_eq!(1u64 << 10, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100446
Imre Kis42935a22024-10-17 11:30:16 +0200447 let attributes = Attributes {
448 non_secure: true,
449 ..Default::default()
450 };
451 assert_eq!(1u64 << 5, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100452
Imre Kis42935a22024-10-17 11:30:16 +0200453 let attributes = Attributes {
454 mem_attr_index: MemoryAttributesIndex::Normal_IWBWA_OWBWA,
455 ..Default::default()
456 };
457 assert_eq!(
458 (MemoryAttributesIndex::Normal_IWBWA_OWBWA as u64) << 2,
459 attributes.into()
460 );
Imre Kis703482d2023-11-30 15:51:26 +0100461
Imre Kis42935a22024-10-17 11:30:16 +0200462 let attributes: Attributes = 0.into();
463 assert!(!attributes.uxn);
464 assert!(!attributes.pxn);
465 assert!(!attributes.contiguous);
466 assert!(!attributes.not_global);
467 assert!(!attributes.access_flag);
468 assert_eq!(Shareability::NonShareable, attributes.shareability);
469 assert_eq!(
470 DataAccessPermissions::ReadWrite_None,
471 attributes.data_access_permissions
472 );
473 assert!(!attributes.non_secure);
474 assert_eq!(
475 MemoryAttributesIndex::Device_nGnRnE,
476 attributes.mem_attr_index
Imre Kis703482d2023-11-30 15:51:26 +0100477 );
478 }
Imre Kis703482d2023-11-30 15:51:26 +0100479
Imre Kis42935a22024-10-17 11:30:16 +0200480 #[test]
481 fn test_next_level_attributes() {
482 let next_level_attributes = NextLevelAttributes::default();
483 assert_eq!(0u64, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100484
Imre Kis42935a22024-10-17 11:30:16 +0200485 let next_level_attributes = NextLevelAttributes {
Imre Kis703482d2023-11-30 15:51:26 +0100486 ns_table: true,
487 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200488 };
489 assert_eq!(1u64 << 63, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100490
Imre Kis42935a22024-10-17 11:30:16 +0200491 let next_level_attributes = NextLevelAttributes {
492 ap_table: 3.into(),
493 ..Default::default()
494 };
495 assert_eq!(3u64 << 61, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100496
Imre Kis42935a22024-10-17 11:30:16 +0200497 let next_level_attributes = NextLevelAttributes {
498 xn_table: true,
499 ..Default::default()
500 };
501 assert_eq!(1u64 << 60, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100502
Imre Kis42935a22024-10-17 11:30:16 +0200503 let next_level_attributes = NextLevelAttributes {
504 pxn_table: true,
505 ..Default::default()
506 };
507 assert_eq!(1u64 << 59, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100508
Imre Kis42935a22024-10-17 11:30:16 +0200509 let next_level_attributes: NextLevelAttributes = 0.into();
510 assert!(!next_level_attributes.ns_table);
511 assert_eq!(0u8, next_level_attributes.ap_table.into());
512 assert!(!next_level_attributes.xn_table);
513 assert!(!next_level_attributes.pxn_table);
Imre Kis703482d2023-11-30 15:51:26 +0100514
Imre Kis42935a22024-10-17 11:30:16 +0200515 let next_level_attributes: NextLevelAttributes = u64::MAX.into();
516 assert!(next_level_attributes.ns_table);
517 assert_eq!(3u8, next_level_attributes.ap_table.into());
518 assert!(next_level_attributes.xn_table);
519 assert!(next_level_attributes.pxn_table);
520 }
Imre Kis703482d2023-11-30 15:51:26 +0100521
Imre Kis42935a22024-10-17 11:30:16 +0200522 #[test]
523 fn test_descriptor_get_type() {
524 let descriptor = Descriptor {
525 cell: UnsafeCell::new(0),
526 };
527 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(1));
528
529 let descriptor = Descriptor {
530 cell: UnsafeCell::new(1),
531 };
532 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(1));
533
534 let descriptor = Descriptor {
535 cell: UnsafeCell::new(3),
536 };
537 assert_eq!(DescriptorType::Table, descriptor.get_descriptor_type(1));
538
539 let descriptor = Descriptor {
540 cell: UnsafeCell::new(0),
541 };
542 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(3));
543
544 let descriptor = Descriptor {
545 cell: UnsafeCell::new(3),
546 };
547 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(3));
548 }
549
550 #[test]
551 fn test_descriptor_is_valid() {
552 let descriptor = Descriptor {
553 cell: UnsafeCell::new(0),
554 };
555 assert!(!descriptor.is_valid());
556
557 let descriptor = Descriptor {
558 cell: UnsafeCell::new(1),
559 };
560 assert!(descriptor.is_valid());
561 }
562
563 #[test]
564 fn test_descriptor_set_block_to_block_again() {
565 let mut descriptor = Descriptor {
566 cell: UnsafeCell::new(1),
567 };
568
Imre Kis631127d2024-11-21 13:09:01 +0100569 descriptor.set_block_descriptor::<48>(
570 TranslationGranule::Granule4k,
571 1,
572 PhysicalAddress(0),
573 Attributes::default(),
574 );
Imre Kis42935a22024-10-17 11:30:16 +0200575 assert_eq!(0x1, descriptor.get());
576 }
577
578 #[test]
579 #[should_panic]
580 fn test_descriptor_set_block_invalid_oa() {
581 let mut descriptor = Descriptor {
582 cell: UnsafeCell::new(0),
583 };
584
Imre Kis631127d2024-11-21 13:09:01 +0100585 descriptor.set_block_descriptor::<48>(
586 TranslationGranule::Granule4k,
587 1,
588 PhysicalAddress(1 << 63),
589 Attributes::default(),
590 );
Imre Kis42935a22024-10-17 11:30:16 +0200591 }
592
593 #[test]
594 fn test_descriptor_block() {
Imre Kis631127d2024-11-21 13:09:01 +0100595 let granule: TranslationGranule<48> = TranslationGranule::Granule4k;
Imre Kis42935a22024-10-17 11:30:16 +0200596 let mut descriptor = Descriptor {
597 cell: UnsafeCell::new(0),
598 };
599
600 descriptor.set_block_descriptor(
Imre Kis631127d2024-11-21 13:09:01 +0100601 granule,
Imre Kis42935a22024-10-17 11:30:16 +0200602 1,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200603 PhysicalAddress(0x0000000f_c0000000),
Imre Kis42935a22024-10-17 11:30:16 +0200604 Attributes {
605 uxn: true,
606 ..Default::default()
607 },
608 );
609 assert_eq!(0x0040000f_c0000001, descriptor.get());
610
611 let mut descriptor = Descriptor {
612 cell: UnsafeCell::new(0),
613 };
614
615 descriptor.set_block_descriptor(
Imre Kis631127d2024-11-21 13:09:01 +0100616 granule,
Imre Kis42935a22024-10-17 11:30:16 +0200617 3,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200618 PhysicalAddress(0x0000000f_fffff000),
Imre Kis42935a22024-10-17 11:30:16 +0200619 Attributes {
620 uxn: true,
621 ..Default::default()
622 },
623 );
624 assert_eq!(0x0040000f_fffff003, descriptor.get());
625
Imre Kisd5b96fd2024-09-11 17:04:32 +0200626 assert_eq!(
627 PhysicalAddress(0x0000000f_fffff000),
Imre Kis631127d2024-11-21 13:09:01 +0100628 descriptor.get_block_output_address(granule, 3)
Imre Kisd5b96fd2024-09-11 17:04:32 +0200629 );
Imre Kis42935a22024-10-17 11:30:16 +0200630 assert_eq!(
631 Attributes {
632 uxn: true,
633 ..Default::default()
634 },
635 descriptor.get_block_attributes(3)
636 );
637
638 descriptor.set_block_attributes(
639 3,
640 Attributes {
641 pxn: true,
642 ..Default::default()
643 },
644 );
645 assert_eq!(
646 Attributes {
647 pxn: true,
648 ..Default::default()
649 },
650 descriptor.get_block_attributes(3)
651 );
652 }
653
654 #[test]
655 #[should_panic]
656 fn test_descriptor_invalid_block_to_invalid() {
657 let mut descriptor = Descriptor {
658 cell: UnsafeCell::new(0),
659 };
660
661 descriptor.set_block_descriptor_to_invalid(0);
662 }
663
664 #[test]
665 fn test_descriptor_block_to_invalid() {
666 let mut descriptor = Descriptor {
667 cell: UnsafeCell::new(3),
668 };
669
670 descriptor.set_block_descriptor_to_invalid(3);
671 assert_eq!(0, descriptor.get());
672 }
673
674 #[test]
Imre Kis9a9d0492024-10-31 15:19:46 +0100675 fn test_descriptor_block_or_invalid_block_to_invalid() {
676 let mut descriptor = Descriptor {
677 cell: UnsafeCell::new(0),
678 };
679
680 descriptor.set_block_or_invalid_descriptor_to_invalid(0);
681 assert_eq!(0, descriptor.get());
682
683 let mut descriptor = Descriptor {
684 cell: UnsafeCell::new(3),
685 };
686
687 descriptor.set_block_or_invalid_descriptor_to_invalid(3);
688 assert_eq!(0, descriptor.get());
689 }
690
691 #[test]
Imre Kis42935a22024-10-17 11:30:16 +0200692 #[should_panic]
693 fn test_descriptor_level3_to_table() {
694 let mut next_level_table = [Descriptor {
695 cell: UnsafeCell::new(0),
696 }];
697 let mut descriptor = Descriptor {
698 cell: UnsafeCell::new(0),
699 };
700
701 unsafe {
702 descriptor.set_table_descriptor(3, &mut next_level_table, None);
703 }
704 }
705
706 #[test]
707 fn test_descriptor_block_to_table() {
708 let next_level_table =
709 unsafe { core::slice::from_raw_parts_mut(0x1000 as *mut Descriptor, 512) };
710 let mut descriptor = Descriptor {
711 cell: UnsafeCell::new(1),
712 };
713
714 unsafe {
715 descriptor.set_table_descriptor(0, next_level_table, None);
716 }
717 assert_eq!(0x1003, descriptor.get());
718 }
719
720 #[test]
721 #[should_panic]
722 fn test_descriptor_table_invalid_count() {
723 let next_level_table =
724 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 511) };
725 let mut descriptor = Descriptor {
726 cell: UnsafeCell::new(0),
727 };
728
729 unsafe {
730 descriptor.set_table_descriptor(0, next_level_table, None);
731 }
732 }
733
734 #[test]
735 #[should_panic]
736 fn test_descriptor_table_non_aligned() {
737 let next_level_table =
738 unsafe { core::slice::from_raw_parts_mut(0x800 as *mut Descriptor, 512) };
739 let mut descriptor = Descriptor {
740 cell: UnsafeCell::new(0),
741 };
742
743 unsafe {
744 descriptor.set_table_descriptor(0, next_level_table, None);
745 }
746 }
747
748 #[test]
749 fn test_descriptor_table() {
750 let next_level_table = unsafe {
751 core::slice::from_raw_parts_mut(0x0000_000c_ba98_7000 as *mut Descriptor, 512)
752 };
753 let mut descriptor = Descriptor {
754 cell: UnsafeCell::new(0),
755 };
756
757 unsafe {
758 descriptor.set_table_descriptor(0, next_level_table, None);
759 }
760 assert_eq!(0x0000_000c_ba98_7003, descriptor.get());
761 }
762
763 #[test]
764 fn test_descriptor_table_next_level_attr() {
765 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
766 let next_level_table =
767 unsafe { core::slice::from_raw_parts_mut(NEXT_LEVEL_ADDR as *mut Descriptor, 512) };
768 let mut descriptor = Descriptor {
769 cell: UnsafeCell::new(0),
770 };
771
772 unsafe {
773 descriptor.set_table_descriptor(
774 0,
775 next_level_table,
776 Some(NextLevelAttributes {
777 ns_table: true,
778 ..Default::default()
779 }),
780 );
781 }
782 assert_eq!(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003, descriptor.get());
783 }
784
785 #[test]
786 fn test_descriptor_table_get_next_level_table() {
787 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
788 let descriptor = Descriptor {
789 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
790 };
791 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
Imre Kis631127d2024-11-21 13:09:01 +0100792 descriptor
793 .get_next_level_table::<36>(TranslationGranule::Granule4k, 0)
794 .as_ptr() as u64
Imre Kis42935a22024-10-17 11:30:16 +0200795 });
796 }
797
798 #[test]
799 fn test_descriptor_table_get_next_level_table_mut() {
800 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
801 let mut descriptor = Descriptor {
802 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
803 };
804 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
Imre Kis631127d2024-11-21 13:09:01 +0100805 descriptor
806 .get_next_level_table_mut::<36>(TranslationGranule::Granule4k, 0)
807 .as_ptr() as *mut Descriptor as u64
Imre Kis42935a22024-10-17 11:30:16 +0200808 });
809 }
810
811 #[test]
812 fn test_descriptor_table_get_next_level_attr() {
813 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
814 let descriptor = Descriptor {
815 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
816 };
817 assert_eq!(
818 NextLevelAttributes {
819 ns_table: true,
820 ..Default::default()
821 },
822 descriptor.get_next_level_attributes(0)
823 );
824 }
825
826 #[test]
827 fn test_descriptor_table_set_to_invalid() {
828 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
829 let mut descriptor = Descriptor {
830 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
831 };
832 assert_eq!(KernelSpace::pa_to_kernel(NEXT_LEVEL_ADDR), unsafe {
Imre Kis631127d2024-11-21 13:09:01 +0100833 descriptor
834 .set_table_descriptor_to_invalid::<36>(TranslationGranule::Granule4k, 0)
835 .as_ptr() as *mut Descriptor as u64
Imre Kis42935a22024-10-17 11:30:16 +0200836 });
837 assert_eq!(0, descriptor.get());
838 }
839
840 #[test]
841 fn test_descriptor_raw_interface() {
842 let cell_value = 0x01234567_89abcdefu64;
843 let cell_new_value = 0x12345678_9abcdef0u64;
844
845 let mut descriptor = Descriptor {
846 cell: UnsafeCell::new(cell_value),
847 };
848
849 assert_eq!(cell_value, descriptor.get());
850
851 descriptor.set(cell_new_value);
852 assert_eq!(cell_new_value, descriptor.get());
853
854 descriptor.modify(|d| d + 1);
855 assert_eq!(cell_new_value + 1, descriptor.get());
856 }
Imre Kis703482d2023-11-30 15:51:26 +0100857}