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