blob: c3ed68f49e4dcab8b38a75fc2e1b8171eee168a7 [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
Imre Kis703482d2023-11-30 15:51:26 +010011use crate::MemoryAttributesIndex;
12
Imre Kisd5b96fd2024-09-11 17:04:32 +020013use super::address::PhysicalAddress;
Imre Kis631127d2024-11-21 13:09:01 +010014use super::TranslationGranule;
Imre Kisd5b96fd2024-09-11 17:04:32 +020015
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
Imre Kis1278c9f2025-01-15 19:48:36 +010026#[allow(non_camel_case_types)]
Imre Kis703482d2023-11-30 15:51:26 +010027#[derive(PrimitiveEnum_u8, Clone, Copy, Debug, PartialEq, Eq, Default)]
28pub enum DataAccessPermissions {
29 #[default]
30 ReadWrite_None = 0b00,
31 ReadWrite_ReadWrite = 0b01,
32 ReadOnly_None = 0b10,
33 ReadOnly_ReadOnly = 0b11,
34}
35
36/// Memory attributes
37#[derive(PackedStruct, Clone, Debug, PartialEq, Eq, Default)]
38#[packed_struct(size_bytes = "8", bit_numbering = "lsb0")]
39pub struct Attributes {
40 #[packed_field(bits = "54")]
41 pub uxn: bool,
42 #[packed_field(bits = "53")]
43 pub pxn: bool,
44 #[packed_field(bits = "52")]
45 pub contiguous: bool,
46 #[packed_field(bits = "11")]
47 pub not_global: bool,
48 #[packed_field(bits = "10")]
49 pub access_flag: bool,
50 #[packed_field(bits = "9..=8", ty = "enum")]
51 pub shareability: Shareability,
52 #[packed_field(bits = "7..=6", ty = "enum")]
53 pub data_access_permissions: DataAccessPermissions,
54 #[packed_field(bits = "5")]
55 pub non_secure: bool,
56 #[packed_field(bits = "4..=2", ty = "enum")]
57 pub mem_attr_index: MemoryAttributesIndex,
58}
59
60impl From<Attributes> for u64 {
61 fn from(attributes: Attributes) -> Self {
62 u64::from_be_bytes(attributes.pack().unwrap())
63 }
64}
65
66impl From<u64> for Attributes {
67 fn from(bits: u64) -> Self {
68 Self::unpack(&bits.to_be_bytes()).unwrap()
69 }
70}
71
72/// Next level attributes
73#[derive(PackedStruct, Clone, Debug, PartialEq, Eq, Default)]
74#[packed_struct(size_bytes = "8", bit_numbering = "lsb0")]
75pub struct NextLevelAttributes {
76 #[packed_field(bits = "63")]
77 ns_table: bool,
78 #[packed_field(bits = "62..=61")]
79 ap_table: Integer<u8, packed_bits::Bits<2>>,
80 #[packed_field(bits = "60")]
81 xn_table: bool,
82 #[packed_field(bits = "59")]
83 pxn_table: bool,
84}
85
86impl From<NextLevelAttributes> for u64 {
87 fn from(attributes: NextLevelAttributes) -> Self {
88 u64::from_be_bytes(attributes.pack().unwrap())
89 }
90}
91
92impl From<u64> for NextLevelAttributes {
93 fn from(bits: u64) -> Self {
94 Self::unpack(&bits.to_be_bytes()).unwrap()
95 }
96}
97
98/// Memory descriptor type
99#[derive(PartialEq, Eq, Debug)]
100pub enum DescriptorType {
101 Invalid,
102 Block,
103 Table,
104}
105
106/// Memory descriptor of a memory translation table
107#[repr(C)]
Imre Kisf5f6fa72024-04-18 14:04:21 +0200108#[derive(Default)]
Imre Kis703482d2023-11-30 15:51:26 +0100109pub struct Descriptor {
110 cell: UnsafeCell<u64>,
111}
112
113impl Descriptor {
114 const ATTR_MASK: u64 = 0xfff8_0000_0000_0ffc;
115 const DESCRIPTOR_TYPE_MASK: u64 = 0b11;
Imre Kis703482d2023-11-30 15:51:26 +0100116 const INVALID_DESCRIPTOR_VALUE: u64 = 0x0;
117 const NEXT_ATTR_MASK: u64 = 0xf800_0000_0000_0000;
Imre Kis703482d2023-11-30 15:51:26 +0100118 const TABLE_BIT: u64 = 0b10;
Imre Kis703482d2023-11-30 15:51:26 +0100119 const TA_MASK: u64 = 0x0000_ffff_ffff_f000;
120 const VALID_BIT: u64 = 0b01;
121
122 /// Query descriptor type
Imre Kis631127d2024-11-21 13:09:01 +0100123 pub fn get_descriptor_type(&self, level: isize) -> DescriptorType {
Imre Kis703482d2023-11-30 15:51:26 +0100124 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
Imre Kis631127d2024-11-21 13:09:01 +0100151 pub fn set_block_descriptor<const VA_BITS: usize>(
Imre Kis703482d2023-11-30 15:51:26 +0100152 &mut self,
Imre Kis631127d2024-11-21 13:09:01 +0100153 granule: TranslationGranule<VA_BITS>,
154 level: isize,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200155 output_address: PhysicalAddress,
Imre Kis703482d2023-11-30 15:51:26 +0100156 attributes: Attributes,
157 ) {
158 let attr: u64 = attributes.into();
159
160 assert!(level <= 3);
161 assert!(self.get_descriptor_type(level) != DescriptorType::Table);
Imre Kis703482d2023-11-30 15:51:26 +0100162 assert_eq!(0, attr & !Self::ATTR_MASK);
163
Imre Kis631127d2024-11-21 13:09:01 +0100164 let oa_granule_mask = !(granule.block_size_at_level(level) - 1);
165
166 // Figure D8-14 VMSAv8-64 Block descriptor formats
167 let oa_bits = match granule {
168 // 4KB and 16KB granules, 52-bit OA
169 #[cfg(feature = "feat_lpa2")]
170 TranslationGranule::Granule4k | TranslationGranule::Granule16k => {
171 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_f000;
172 assert_eq!(0, output_address.0 & !oa_mask);
173
174 let address = output_address.0 & oa_mask;
175
176 // OA[49:n] remains in place, OA[51:50] is mapped to [9:8]
177 let lsbs = address & 0x0003_ffff_ffff_f000;
178 let msbs = ((address >> 50) & 0x3) << 8;
179
180 lsbs | msbs
181 }
182
183 // 64KB granule, 52-bit OA
184 #[cfg(feature = "feat_lpa")]
185 TranslationGranule::Granule64k => {
186 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_0000;
187 assert_eq!(0, output_address.0 & !oa_mask);
188
189 let address = output_address.0 & oa_mask;
190
191 // OA[47:n] remains in place, OA[51:48] is mapped to [15:12]
192 let lsbs = address & 0x0000_ffff_ffff_0000;
193 let msbs = ((address >> 48) & 0xf) << 12;
194
195 lsbs | msbs
196 }
197
198 // 4KB, 16KB, and 64KB granules, 48-bit OA
199 #[cfg(not(all(feature = "feat_lpa", feature = "feat_lpa2")))]
200 _ => {
201 let oa_mask = oa_granule_mask & 0x0000_ffff_ffff_f000;
202 assert_eq!(0, output_address.0 & !oa_mask);
203 output_address.0 & oa_mask
204 }
205 };
206
Imre Kis703482d2023-11-30 15:51:26 +0100207 let table_bit = if level < 3 { 0 } else { Self::TABLE_BIT };
208
Imre Kis631127d2024-11-21 13:09:01 +0100209 self.set(Self::VALID_BIT | table_bit | oa_bits as u64 | attr);
Imre Kis703482d2023-11-30 15:51:26 +0100210 }
211
212 /// Get output address from the block descriptor
Imre Kis631127d2024-11-21 13:09:01 +0100213 pub fn get_block_output_address<const VA_BITS: usize>(
214 &self,
215 granule: TranslationGranule<VA_BITS>,
216 level: isize,
217 ) -> PhysicalAddress {
Imre Kis703482d2023-11-30 15:51:26 +0100218 assert!(level <= 3);
219 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
220
Imre Kis631127d2024-11-21 13:09:01 +0100221 let oa_granule_mask = !(granule.block_size_at_level(level) - 1);
222 let descriptor_value = self.get();
223
224 // Figure D8-14 VMSAv8-64 Block descriptor formats
225 let pa = match granule {
226 // 4KB and 16KB granules, 52-bit OA
227 #[cfg(feature = "feat_lpa2")]
228 TranslationGranule::Granule4k | TranslationGranule::Granule16k => {
229 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_f000;
230
231 // OA[49:n] remains in place, OA[51:50] is mapped from [9:8]
232 let lsbs = descriptor_value & 0x0003_ffff_ffff_f000;
233 let msbs = ((descriptor_value >> 8) & 0x3) << 50;
234
235 (lsbs | msbs) as usize & oa_mask
236 }
237
238 // 64KB granule, 52-bit OA
239 #[cfg(feature = "feat_lpa")]
240 TranslationGranule::Granule64k => {
241 let oa_mask = oa_granule_mask & 0x000f_ffff_ffff_0000;
242
243 // OA[47:n] remains in place, OA[51:48] is mapped from [15:12]
244 let lsbs = descriptor_value & 0x0003_ffff_ffff_0000;
245 let msbs = ((descriptor_value >> 12) & 0xf) << 48;
246
247 (lsbs | msbs) as usize & oa_mask
248 }
249
250 // 4KB, 16KB, and 64KB granules, 48-bit OA
251 #[cfg(not(all(feature = "feat_lpa", feature = "feat_lpa2")))]
252 _ => {
253 let oa_mask = oa_granule_mask & 0x0000_ffff_ffff_f000;
254 descriptor_value as usize & oa_mask
255 }
256 };
257
258 PhysicalAddress(pa)
Imre Kis703482d2023-11-30 15:51:26 +0100259 }
260
261 /// Set the attributes of the block descriptor
Imre Kis631127d2024-11-21 13:09:01 +0100262 pub fn set_block_attributes(&mut self, level: isize, attributes: Attributes) {
Imre Kis703482d2023-11-30 15:51:26 +0100263 assert!(level <= 3);
264 let attr: u64 = attributes.into();
265 assert_eq!(0, attr & !Self::ATTR_MASK);
266 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
267
Imre Kisf5f6fa72024-04-18 14:04:21 +0200268 self.modify(|d| (d & !Self::ATTR_MASK) | attr);
Imre Kis703482d2023-11-30 15:51:26 +0100269 }
270
271 /// Get the attributes of the block descriptor
Imre Kis631127d2024-11-21 13:09:01 +0100272 pub fn get_block_attributes(&self, level: isize) -> Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100273 assert!(level <= 3);
274 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
275
Imre Kisf5f6fa72024-04-18 14:04:21 +0200276 Attributes::from(self.get() & Self::ATTR_MASK)
Imre Kis703482d2023-11-30 15:51:26 +0100277 }
278
279 /// Set block descriptor to invalid
Imre Kis631127d2024-11-21 13:09:01 +0100280 pub fn set_block_descriptor_to_invalid(&mut self, level: isize) {
Imre Kis703482d2023-11-30 15:51:26 +0100281 assert!(level <= 3);
282 assert_eq!(DescriptorType::Block, self.get_descriptor_type(level));
283
Imre Kisf5f6fa72024-04-18 14:04:21 +0200284 self.set(Self::INVALID_DESCRIPTOR_VALUE)
Imre Kis703482d2023-11-30 15:51:26 +0100285 }
286
Imre Kis9a9d0492024-10-31 15:19:46 +0100287 /// Set block or invalid descriptor to invalid
Imre Kis631127d2024-11-21 13:09:01 +0100288 pub fn set_block_or_invalid_descriptor_to_invalid(&mut self, level: isize) {
Imre Kis9a9d0492024-10-31 15:19:46 +0100289 assert!(level <= 3);
290 assert!(DescriptorType::Table != self.get_descriptor_type(level));
291
292 self.set(Self::INVALID_DESCRIPTOR_VALUE)
293 }
294
Imre Kis703482d2023-11-30 15:51:26 +0100295 /// Set table descriptor
Imre Kisa7ef6842025-01-17 13:12:52 +0100296 pub fn set_table_descriptor(
Imre Kis703482d2023-11-30 15:51:26 +0100297 &mut self,
Imre Kis631127d2024-11-21 13:09:01 +0100298 level: isize,
Imre Kisa7ef6842025-01-17 13:12:52 +0100299 next_level_table: PhysicalAddress,
Imre Kis703482d2023-11-30 15:51:26 +0100300 next_level_attributes: Option<NextLevelAttributes>,
301 ) {
302 assert!(level <= 2);
Imre Kis703482d2023-11-30 15:51:26 +0100303 assert!(self.get_descriptor_type(level) != DescriptorType::Table);
304
Imre Kisa7ef6842025-01-17 13:12:52 +0100305 let table_addr = next_level_table.0 as u64;
Imre Kis703482d2023-11-30 15:51:26 +0100306 assert_eq!(0, table_addr & !Self::TA_MASK);
307
308 let mut raw_desc_value = Self::VALID_BIT | Self::TABLE_BIT | table_addr;
309
310 if let Some(next_attr) = next_level_attributes {
311 let next_attr_bits: u64 = next_attr.into();
312 assert_eq!(0, next_attr_bits & !Self::NEXT_ATTR_MASK);
313 raw_desc_value |= next_attr_bits;
314 }
315
316 self.set(raw_desc_value);
317 }
318
319 /// Get next level table
Imre Kisa7ef6842025-01-17 13:12:52 +0100320 pub fn get_next_level_table(&self, level: isize) -> PhysicalAddress {
Imre Kis703482d2023-11-30 15:51:26 +0100321 assert!(level <= 2);
322 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
323
Imre Kisa7ef6842025-01-17 13:12:52 +0100324 PhysicalAddress((self.get() & Self::TA_MASK) as usize)
Imre Kis703482d2023-11-30 15:51:26 +0100325 }
326
327 /// Get next level attributes
Imre Kis631127d2024-11-21 13:09:01 +0100328 pub fn get_next_level_attributes(&self, level: isize) -> NextLevelAttributes {
Imre Kis703482d2023-11-30 15:51:26 +0100329 assert!(level <= 2);
330 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
331
Imre Kisf5f6fa72024-04-18 14:04:21 +0200332 NextLevelAttributes::from(self.get() & Self::NEXT_ATTR_MASK)
Imre Kis703482d2023-11-30 15:51:26 +0100333 }
334
335 /// Set table descriptor to invalid
Imre Kisa7ef6842025-01-17 13:12:52 +0100336 pub fn set_table_descriptor_to_invalid(&mut self, level: isize) -> PhysicalAddress {
Imre Kis703482d2023-11-30 15:51:26 +0100337 assert!(level <= 2);
338 assert_eq!(DescriptorType::Table, self.get_descriptor_type(level));
339
Imre Kisa7ef6842025-01-17 13:12:52 +0100340 let pa = PhysicalAddress((self.get() & Self::TA_MASK) as usize);
Imre Kis703482d2023-11-30 15:51:26 +0100341 self.set(Self::INVALID_DESCRIPTOR_VALUE);
Imre Kisa7ef6842025-01-17 13:12:52 +0100342 pa
Imre Kis703482d2023-11-30 15:51:26 +0100343 }
344
345 /// Get raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200346 fn get(&self) -> u64 {
347 unsafe { ptr::read_volatile(self.cell.get()) }
Imre Kis703482d2023-11-30 15:51:26 +0100348 }
349
350 /// Set raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200351 fn set(&mut self, value: u64) {
Imre Kis9a9d0492024-10-31 15:19:46 +0100352 // Safety: The cell should point to a valid address and the assembly code is just a data
353 // barrier.
354 unsafe {
355 ptr::write_volatile(self.cell.get(), value);
356 #[cfg(target_arch = "aarch64")]
Imre Kisf2020642025-03-07 13:38:30 +0100357 core::arch::asm!("dsb ishst");
Imre Kis9a9d0492024-10-31 15:19:46 +0100358 }
Imre Kis703482d2023-11-30 15:51:26 +0100359 }
360
361 /// Modify raw descriptor value
Imre Kisf5f6fa72024-04-18 14:04:21 +0200362 fn modify<F>(&mut self, f: F)
Imre Kis703482d2023-11-30 15:51:26 +0100363 where
364 F: Fn(u64) -> u64,
365 {
366 self.set(f(self.get()))
367 }
Imre Kis703482d2023-11-30 15:51:26 +0100368}
369
Imre Kis42935a22024-10-17 11:30:16 +0200370#[cfg(test)]
371mod tests {
372 use super::*;
Imre Kis703482d2023-11-30 15:51:26 +0100373
Imre Kis42935a22024-10-17 11:30:16 +0200374 #[test]
375 fn test_attributes() {
376 let attributes = Attributes::default();
377 assert_eq!(0u64, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100378
Imre Kis42935a22024-10-17 11:30:16 +0200379 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100380 uxn: true,
381 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200382 };
383 assert_eq!(1u64 << 54, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100384
Imre Kis42935a22024-10-17 11:30:16 +0200385 let attributes = Attributes {
Imre Kis703482d2023-11-30 15:51:26 +0100386 pxn: true,
387 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200388 };
389 assert_eq!(1u64 << 53, attributes.into());
390
391 let attributes = Attributes {
392 contiguous: true,
Imre Kis703482d2023-11-30 15:51:26 +0100393 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200394 };
395 assert_eq!(1u64 << 52, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100396
Imre Kis42935a22024-10-17 11:30:16 +0200397 let attributes = Attributes {
398 not_global: true,
399 ..Default::default()
400 };
401 assert_eq!(1u64 << 11, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100402
Imre Kis42935a22024-10-17 11:30:16 +0200403 let attributes = Attributes {
404 access_flag: true,
405 ..Default::default()
406 };
407 assert_eq!(1u64 << 10, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100408
Imre Kis42935a22024-10-17 11:30:16 +0200409 let attributes = Attributes {
410 non_secure: true,
411 ..Default::default()
412 };
413 assert_eq!(1u64 << 5, attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100414
Imre Kis42935a22024-10-17 11:30:16 +0200415 let attributes = Attributes {
416 mem_attr_index: MemoryAttributesIndex::Normal_IWBWA_OWBWA,
417 ..Default::default()
418 };
419 assert_eq!(
420 (MemoryAttributesIndex::Normal_IWBWA_OWBWA as u64) << 2,
421 attributes.into()
422 );
Imre Kis703482d2023-11-30 15:51:26 +0100423
Imre Kis42935a22024-10-17 11:30:16 +0200424 let attributes: Attributes = 0.into();
425 assert!(!attributes.uxn);
426 assert!(!attributes.pxn);
427 assert!(!attributes.contiguous);
428 assert!(!attributes.not_global);
429 assert!(!attributes.access_flag);
430 assert_eq!(Shareability::NonShareable, attributes.shareability);
431 assert_eq!(
432 DataAccessPermissions::ReadWrite_None,
433 attributes.data_access_permissions
434 );
435 assert!(!attributes.non_secure);
436 assert_eq!(
437 MemoryAttributesIndex::Device_nGnRnE,
438 attributes.mem_attr_index
Imre Kis703482d2023-11-30 15:51:26 +0100439 );
440 }
Imre Kis703482d2023-11-30 15:51:26 +0100441
Imre Kis42935a22024-10-17 11:30:16 +0200442 #[test]
443 fn test_next_level_attributes() {
444 let next_level_attributes = NextLevelAttributes::default();
445 assert_eq!(0u64, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100446
Imre Kis42935a22024-10-17 11:30:16 +0200447 let next_level_attributes = NextLevelAttributes {
Imre Kis703482d2023-11-30 15:51:26 +0100448 ns_table: true,
449 ..Default::default()
Imre Kis42935a22024-10-17 11:30:16 +0200450 };
451 assert_eq!(1u64 << 63, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100452
Imre Kis42935a22024-10-17 11:30:16 +0200453 let next_level_attributes = NextLevelAttributes {
454 ap_table: 3.into(),
455 ..Default::default()
456 };
457 assert_eq!(3u64 << 61, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100458
Imre Kis42935a22024-10-17 11:30:16 +0200459 let next_level_attributes = NextLevelAttributes {
460 xn_table: true,
461 ..Default::default()
462 };
463 assert_eq!(1u64 << 60, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100464
Imre Kis42935a22024-10-17 11:30:16 +0200465 let next_level_attributes = NextLevelAttributes {
466 pxn_table: true,
467 ..Default::default()
468 };
469 assert_eq!(1u64 << 59, next_level_attributes.into());
Imre Kis703482d2023-11-30 15:51:26 +0100470
Imre Kis42935a22024-10-17 11:30:16 +0200471 let next_level_attributes: NextLevelAttributes = 0.into();
472 assert!(!next_level_attributes.ns_table);
473 assert_eq!(0u8, next_level_attributes.ap_table.into());
474 assert!(!next_level_attributes.xn_table);
475 assert!(!next_level_attributes.pxn_table);
Imre Kis703482d2023-11-30 15:51:26 +0100476
Imre Kis42935a22024-10-17 11:30:16 +0200477 let next_level_attributes: NextLevelAttributes = u64::MAX.into();
478 assert!(next_level_attributes.ns_table);
479 assert_eq!(3u8, next_level_attributes.ap_table.into());
480 assert!(next_level_attributes.xn_table);
481 assert!(next_level_attributes.pxn_table);
482 }
Imre Kis703482d2023-11-30 15:51:26 +0100483
Imre Kis42935a22024-10-17 11:30:16 +0200484 #[test]
485 fn test_descriptor_get_type() {
486 let descriptor = Descriptor {
487 cell: UnsafeCell::new(0),
488 };
489 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(1));
490
491 let descriptor = Descriptor {
492 cell: UnsafeCell::new(1),
493 };
494 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(1));
495
496 let descriptor = Descriptor {
497 cell: UnsafeCell::new(3),
498 };
499 assert_eq!(DescriptorType::Table, descriptor.get_descriptor_type(1));
500
501 let descriptor = Descriptor {
502 cell: UnsafeCell::new(0),
503 };
504 assert_eq!(DescriptorType::Invalid, descriptor.get_descriptor_type(3));
505
506 let descriptor = Descriptor {
507 cell: UnsafeCell::new(3),
508 };
509 assert_eq!(DescriptorType::Block, descriptor.get_descriptor_type(3));
510 }
511
512 #[test]
513 fn test_descriptor_is_valid() {
514 let descriptor = Descriptor {
515 cell: UnsafeCell::new(0),
516 };
517 assert!(!descriptor.is_valid());
518
519 let descriptor = Descriptor {
520 cell: UnsafeCell::new(1),
521 };
522 assert!(descriptor.is_valid());
523 }
524
525 #[test]
526 fn test_descriptor_set_block_to_block_again() {
527 let mut descriptor = Descriptor {
528 cell: UnsafeCell::new(1),
529 };
530
Imre Kis631127d2024-11-21 13:09:01 +0100531 descriptor.set_block_descriptor::<48>(
532 TranslationGranule::Granule4k,
533 1,
534 PhysicalAddress(0),
535 Attributes::default(),
536 );
Imre Kis42935a22024-10-17 11:30:16 +0200537 assert_eq!(0x1, descriptor.get());
538 }
539
540 #[test]
541 #[should_panic]
542 fn test_descriptor_set_block_invalid_oa() {
543 let mut descriptor = Descriptor {
544 cell: UnsafeCell::new(0),
545 };
546
Imre Kis631127d2024-11-21 13:09:01 +0100547 descriptor.set_block_descriptor::<48>(
548 TranslationGranule::Granule4k,
549 1,
550 PhysicalAddress(1 << 63),
551 Attributes::default(),
552 );
Imre Kis42935a22024-10-17 11:30:16 +0200553 }
554
555 #[test]
556 fn test_descriptor_block() {
Imre Kis631127d2024-11-21 13:09:01 +0100557 let granule: TranslationGranule<48> = TranslationGranule::Granule4k;
Imre Kis42935a22024-10-17 11:30:16 +0200558 let mut descriptor = Descriptor {
559 cell: UnsafeCell::new(0),
560 };
561
562 descriptor.set_block_descriptor(
Imre Kis631127d2024-11-21 13:09:01 +0100563 granule,
Imre Kis42935a22024-10-17 11:30:16 +0200564 1,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200565 PhysicalAddress(0x0000000f_c0000000),
Imre Kis42935a22024-10-17 11:30:16 +0200566 Attributes {
567 uxn: true,
568 ..Default::default()
569 },
570 );
571 assert_eq!(0x0040000f_c0000001, descriptor.get());
572
573 let mut descriptor = Descriptor {
574 cell: UnsafeCell::new(0),
575 };
576
577 descriptor.set_block_descriptor(
Imre Kis631127d2024-11-21 13:09:01 +0100578 granule,
Imre Kis42935a22024-10-17 11:30:16 +0200579 3,
Imre Kisd5b96fd2024-09-11 17:04:32 +0200580 PhysicalAddress(0x0000000f_fffff000),
Imre Kis42935a22024-10-17 11:30:16 +0200581 Attributes {
582 uxn: true,
583 ..Default::default()
584 },
585 );
586 assert_eq!(0x0040000f_fffff003, descriptor.get());
587
Imre Kisd5b96fd2024-09-11 17:04:32 +0200588 assert_eq!(
589 PhysicalAddress(0x0000000f_fffff000),
Imre Kis631127d2024-11-21 13:09:01 +0100590 descriptor.get_block_output_address(granule, 3)
Imre Kisd5b96fd2024-09-11 17:04:32 +0200591 );
Imre Kis42935a22024-10-17 11:30:16 +0200592 assert_eq!(
593 Attributes {
594 uxn: true,
595 ..Default::default()
596 },
597 descriptor.get_block_attributes(3)
598 );
599
600 descriptor.set_block_attributes(
601 3,
602 Attributes {
603 pxn: true,
604 ..Default::default()
605 },
606 );
607 assert_eq!(
608 Attributes {
609 pxn: true,
610 ..Default::default()
611 },
612 descriptor.get_block_attributes(3)
613 );
614 }
615
616 #[test]
617 #[should_panic]
618 fn test_descriptor_invalid_block_to_invalid() {
619 let mut descriptor = Descriptor {
620 cell: UnsafeCell::new(0),
621 };
622
623 descriptor.set_block_descriptor_to_invalid(0);
624 }
625
626 #[test]
627 fn test_descriptor_block_to_invalid() {
628 let mut descriptor = Descriptor {
629 cell: UnsafeCell::new(3),
630 };
631
632 descriptor.set_block_descriptor_to_invalid(3);
633 assert_eq!(0, descriptor.get());
634 }
635
636 #[test]
Imre Kis9a9d0492024-10-31 15:19:46 +0100637 fn test_descriptor_block_or_invalid_block_to_invalid() {
638 let mut descriptor = Descriptor {
639 cell: UnsafeCell::new(0),
640 };
641
642 descriptor.set_block_or_invalid_descriptor_to_invalid(0);
643 assert_eq!(0, descriptor.get());
644
645 let mut descriptor = Descriptor {
646 cell: UnsafeCell::new(3),
647 };
648
649 descriptor.set_block_or_invalid_descriptor_to_invalid(3);
650 assert_eq!(0, descriptor.get());
651 }
652
653 #[test]
Imre Kis42935a22024-10-17 11:30:16 +0200654 #[should_panic]
655 fn test_descriptor_level3_to_table() {
Imre Kis42935a22024-10-17 11:30:16 +0200656 let mut descriptor = Descriptor {
657 cell: UnsafeCell::new(0),
658 };
659
Imre Kisa7ef6842025-01-17 13:12:52 +0100660 descriptor.set_table_descriptor(3, PhysicalAddress(0), None);
Imre Kis42935a22024-10-17 11:30:16 +0200661 }
662
663 #[test]
664 fn test_descriptor_block_to_table() {
Imre Kisa7ef6842025-01-17 13:12:52 +0100665 let next_level_table = PhysicalAddress(0x1000);
Imre Kis42935a22024-10-17 11:30:16 +0200666 let mut descriptor = Descriptor {
667 cell: UnsafeCell::new(1),
668 };
669
Imre Kisa7ef6842025-01-17 13:12:52 +0100670 descriptor.set_table_descriptor(0, next_level_table, None);
Imre Kis42935a22024-10-17 11:30:16 +0200671 assert_eq!(0x1003, descriptor.get());
672 }
673
674 #[test]
675 #[should_panic]
Imre Kis42935a22024-10-17 11:30:16 +0200676 fn test_descriptor_table_non_aligned() {
Imre Kisa7ef6842025-01-17 13:12:52 +0100677 let next_level_table = PhysicalAddress(0x800);
Imre Kis42935a22024-10-17 11:30:16 +0200678 let mut descriptor = Descriptor {
679 cell: UnsafeCell::new(0),
680 };
681
Imre Kisa7ef6842025-01-17 13:12:52 +0100682 descriptor.set_table_descriptor(0, next_level_table, None);
Imre Kis42935a22024-10-17 11:30:16 +0200683 }
684
685 #[test]
686 fn test_descriptor_table() {
Imre Kisa7ef6842025-01-17 13:12:52 +0100687 let next_level_table = PhysicalAddress(0x0000_000c_ba98_7000);
Imre Kis42935a22024-10-17 11:30:16 +0200688 let mut descriptor = Descriptor {
689 cell: UnsafeCell::new(0),
690 };
691
Imre Kisa7ef6842025-01-17 13:12:52 +0100692 descriptor.set_table_descriptor(0, next_level_table, None);
Imre Kis42935a22024-10-17 11:30:16 +0200693 assert_eq!(0x0000_000c_ba98_7003, descriptor.get());
694 }
695
696 #[test]
697 fn test_descriptor_table_next_level_attr() {
698 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
Imre Kisa7ef6842025-01-17 13:12:52 +0100699 let next_level_table = PhysicalAddress(0x0000_000c_ba98_7000);
Imre Kis42935a22024-10-17 11:30:16 +0200700 let mut descriptor = Descriptor {
701 cell: UnsafeCell::new(0),
702 };
703
Imre Kisa7ef6842025-01-17 13:12:52 +0100704 descriptor.set_table_descriptor(
705 0,
706 next_level_table,
707 Some(NextLevelAttributes {
708 ns_table: true,
709 ..Default::default()
710 }),
711 );
Imre Kis42935a22024-10-17 11:30:16 +0200712 assert_eq!(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003, descriptor.get());
713 }
714
715 #[test]
716 fn test_descriptor_table_get_next_level_table() {
717 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
718 let descriptor = Descriptor {
719 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
720 };
Imre Kisa7ef6842025-01-17 13:12:52 +0100721 assert_eq!(NEXT_LEVEL_ADDR, descriptor.get_next_level_table(0).0 as u64);
Imre Kis42935a22024-10-17 11:30:16 +0200722 }
723
724 #[test]
725 fn test_descriptor_table_get_next_level_attr() {
726 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
727 let descriptor = Descriptor {
728 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
729 };
730 assert_eq!(
731 NextLevelAttributes {
732 ns_table: true,
733 ..Default::default()
734 },
735 descriptor.get_next_level_attributes(0)
736 );
737 }
738
739 #[test]
740 fn test_descriptor_table_set_to_invalid() {
741 const NEXT_LEVEL_ADDR: u64 = 0x0000_000c_ba98_7000;
742 let mut descriptor = Descriptor {
743 cell: UnsafeCell::new(NEXT_LEVEL_ADDR | 0x8000_0000_0000_0003),
744 };
Imre Kisa7ef6842025-01-17 13:12:52 +0100745 assert_eq!(
746 NEXT_LEVEL_ADDR,
747 descriptor.set_table_descriptor_to_invalid(0).0 as u64
748 );
Imre Kis42935a22024-10-17 11:30:16 +0200749 assert_eq!(0, descriptor.get());
750 }
751
752 #[test]
753 fn test_descriptor_raw_interface() {
754 let cell_value = 0x01234567_89abcdefu64;
755 let cell_new_value = 0x12345678_9abcdef0u64;
756
757 let mut descriptor = Descriptor {
758 cell: UnsafeCell::new(cell_value),
759 };
760
761 assert_eq!(cell_value, descriptor.get());
762
763 descriptor.set(cell_new_value);
764 assert_eq!(cell_new_value, descriptor.get());
765
766 descriptor.modify(|d| d + 1);
767 assert_eq!(cell_new_value + 1, descriptor.get());
768 }
Imre Kis703482d2023-11-30 15:51:26 +0100769}