Implement dynamic kernel memory mapping

Extend KernelSpace to build the kernel address space memory mapping
runtime.

Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I7a27540f58a032ff49ba35f5f43afb5a8c9e5be8
diff --git a/src/lib.rs b/src/lib.rs
index 4986ceb..c70824e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,6 +9,7 @@
 
 use core::arch::asm;
 use core::iter::zip;
+use core::ops::Range;
 use core::{fmt, panic};
 
 use alloc::boxed::Box;
@@ -85,6 +86,7 @@
 
         const USER = 0b00010000;
         const DEVICE = 0b00100000;
+        const GLOBAL = 0b01000000;
     }
 }
 
@@ -112,7 +114,7 @@
             pxn: !access_rights.contains(MemoryAccessRights::X)
                 || access_rights.contains(MemoryAccessRights::USER),
             contiguous: false,
-            not_global: true,
+            not_global: !access_rights.contains(MemoryAccessRights::GLOBAL),
             access_flag: true,
             shareability: Shareability::NonShareable,
             data_access_permissions,
@@ -146,6 +148,12 @@
     }
 }
 
+/// Enum for selecting TTBR0_EL1 or TTBR1_EL1
+pub enum TTBR {
+    TTBR0_EL1,
+    TTBR1_EL1,
+}
+
 pub struct Xlat {
     base_table: Box<BaseTable>,
     page_pool: PagePool,
@@ -178,16 +186,12 @@
 /// * unmap block
 /// * set access rights of block
 impl Xlat {
-    const BASE_VA: usize = 0x4000_0000;
     pub const GRANULE_SIZES: [usize; 4] = [0, 0x4000_0000, 0x0020_0000, 0x0000_1000];
 
-    pub fn new(page_pool: PagePool) -> Self {
+    pub fn new(page_pool: PagePool, va_range: Range<usize>) -> Self {
         let mut regions = RegionPool::new();
         regions
-            .add(VirtualRegion::new(
-                Self::BASE_VA,
-                0x1_0000_0000 - Self::BASE_VA,
-            ))
+            .add(VirtualRegion::new(va_range.start, va_range.len()))
             .unwrap();
         Self {
             base_table: Box::new(BaseTable::new()),
@@ -358,16 +362,29 @@
     /// Activate memory mapping represented by the object
     /// # Arguments
     /// * asid: ASID of the table base address
-    pub fn activate(&self, asid: u8) {
+    /// * ttbr: Selects TTBR0_EL1/TTBR1_EL1
+    pub fn activate(&self, asid: u8, ttbr: TTBR) {
         let base_table_pa = KernelSpace::kernel_to_pa(self.base_table.descriptors.as_ptr() as u64);
-        let ttbr = ((asid as u64) << 48) | base_table_pa;
-        unsafe {
-            #[cfg(target_arch = "aarch64")]
-            asm!(
-                "msr ttbr0_el1, {0}
-                 isb",
-                in(reg) ttbr)
-        };
+        let ttbr_value = ((asid as u64) << 48) | base_table_pa;
+        #[cfg(target_arch = "aarch64")]
+        match ttbr {
+            TTBR::TTBR0_EL1 => unsafe {
+                asm!(
+                    "msr ttbr0_el1, {0}
+                     isb",
+                    in(reg) ttbr_value)
+            },
+            TTBR::TTBR1_EL1 => unsafe {
+                asm!(
+                    "msr ttbr1_el1, {0}
+                    isb
+
+                    tlbi	vmalle1
+                    dsb	sy
+                    isb",
+                    in(reg) ttbr_value)
+            },
+        }
     }
 
     /// Prints the translation tables to debug console recursively