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),
+            )
         }
     }