Remove KernelSpace usage from Descriptor
Descriptor now simply returns or sets PhysicalAddress instead of
using &[Descriptor]. Converting the physical address to a kernel
space virtual address is now handled by Xlat.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I955c3493a8da424649599889962192a3955f4a5b
diff --git a/src/lib.rs b/src/lib.rs
index 202776d..b5f95d6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -516,15 +516,15 @@
)?;
}
DescriptorType::Table => {
- let next_level_table =
- unsafe { descriptor.get_next_level_table(granule, level) };
+ let table_pa = descriptor.get_next_level_table(level);
writeln!(
f,
"{} {:#010x} Table -> {:#010x}",
- level_prefix,
- va,
- next_level_table.as_ptr() as usize
+ level_prefix, va, table_pa.0
)?;
+
+ let next_level_table =
+ unsafe { Self::get_table_from_pa(table_pa, granule, level + 1) };
Self::dump_table(f, level + 1, va, next_level_table, granule)?;
}
_ => {}
@@ -672,7 +672,10 @@
if result.is_ok() {
// Set table descriptor if the table is configured properly
- unsafe { descriptor.set_table_descriptor(level, next_table, None) };
+ let next_table_pa = PhysicalAddress(KernelSpace::kernel_to_pa(
+ next_table.as_ptr() as u64,
+ ) as usize);
+ descriptor.set_table_descriptor(level, next_table_pa, None);
} else {
// Release next level table on error and keep invalid descriptor on current level
page_pool.release_pages(page).unwrap();
@@ -743,12 +746,16 @@
);
if result.is_ok() {
+ let next_table_pa = PhysicalAddress(KernelSpace::kernel_to_pa(
+ next_table.as_ptr() as u64,
+ ) as usize);
+
// Follow break-before-make sequence
descriptor.set_block_or_invalid_descriptor_to_invalid(level);
Self::invalidate(regime, Some(current_va));
// Set table descriptor if the table is configured properly
- unsafe { descriptor.set_table_descriptor(level, next_table, None) };
+ descriptor.set_table_descriptor(level, next_table_pa, None);
} else {
// Release next level table on error and keep invalid descriptor on current level
page_pool.release_pages(page).unwrap();
@@ -756,17 +763,27 @@
result
}
- DescriptorType::Table => Self::set_block_descriptor_recursively(
- attributes,
- pa,
- va.mask_for_level(granule, level),
- block_size,
- level + 1,
- unsafe { descriptor.get_next_level_table_mut(granule, level) },
- page_pool,
- regime,
- granule,
- ),
+ DescriptorType::Table => {
+ let next_level_table = unsafe {
+ Self::get_table_from_pa_mut(
+ descriptor.get_next_level_table(level),
+ granule,
+ level + 1,
+ )
+ };
+
+ Self::set_block_descriptor_recursively(
+ attributes,
+ pa,
+ va.mask_for_level(granule, level),
+ block_size,
+ level + 1,
+ next_level_table,
+ page_pool,
+ regime,
+ granule,
+ )
+ }
}
}
@@ -823,8 +840,14 @@
panic!("Cannot remove block with different block size");
}
DescriptorType::Table => {
- let next_level_table =
- unsafe { descriptor.get_next_level_table_mut(granule, level) };
+ let next_level_table = unsafe {
+ Self::get_table_from_pa_mut(
+ descriptor.get_next_level_table(level),
+ granule,
+ level + 1,
+ )
+ };
+
Self::remove_block_descriptor_recursively(
va.mask_for_level(granule, level),
block_size,
@@ -838,10 +861,11 @@
if next_level_table.iter().all(|d| !d.is_valid()) {
// Empty table
let mut page = unsafe {
- Pages::from_slice(
- descriptor.set_table_descriptor_to_invalid(granule, level),
- )
+ let table_pa = descriptor.set_table_descriptor_to_invalid(level);
+ let next_table = Self::get_table_from_pa_mut(table_pa, granule, level + 1);
+ Pages::from_slice(next_table)
};
+
page.zero_init();
page_pool.release_pages(page).unwrap();
}
@@ -881,13 +905,61 @@
DescriptorType::Block => {
panic!("Cannot split existing block descriptor to table");
}
- DescriptorType::Table => Self::walk_descriptors(
- va.mask_for_level(granule, level),
- block_size,
- level + 1,
- unsafe { descriptor.get_next_level_table_mut(granule, level) },
- granule,
- ),
+ DescriptorType::Table => {
+ let next_level_table = unsafe {
+ Self::get_table_from_pa_mut(
+ descriptor.get_next_level_table(level),
+ granule,
+ level + 1,
+ )
+ };
+
+ Self::walk_descriptors(
+ va.mask_for_level(granule, level),
+ block_size,
+ level + 1,
+ next_level_table,
+ granule,
+ )
+ }
+ }
+ }
+
+ /// Create a translation table descriptor slice from a physical address.
+ ///
+ /// # Safety
+ /// The caller must ensure that the physical address points to a valid translation table and
+ /// it it mapped into the virtual address space of the running kernel context.
+ unsafe fn get_table_from_pa<'a>(
+ pa: PhysicalAddress,
+ granule: TranslationGranule<VA_BITS>,
+ level: isize,
+ ) -> &'a [Descriptor] {
+ let table_va = KernelSpace::pa_to_kernel(pa.0 as u64);
+ unsafe {
+ core::slice::from_raw_parts(
+ table_va as *const Descriptor,
+ granule.entry_count_at_level(level),
+ )
+ }
+ }
+
+ /// Create a mutable translation table descriptor slice from a physical address.
+ ///
+ /// # Safety
+ /// The caller must ensure that the physical address points to a valid translation table and
+ /// it it mapped into the virtual address space of the running kernel context.
+ unsafe fn get_table_from_pa_mut<'a>(
+ pa: PhysicalAddress,
+ granule: TranslationGranule<VA_BITS>,
+ level: isize,
+ ) -> &'a mut [Descriptor] {
+ let table_va = KernelSpace::pa_to_kernel(pa.0 as u64);
+ unsafe {
+ core::slice::from_raw_parts_mut(
+ table_va as *mut Descriptor,
+ granule.entry_count_at_level(level),
+ )
}
}