Handle top bits in upper VA ranges
Set and enforce top bits in virtual address if Upper VA range is
selected for EL1/0 or EL2/0 (VHE). This means that the top bits must
match the selected VA range and Xlat will also return matching virtual
addresses.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I44c2a326a9d3fdd4d82ec01e8f95d1c8f7d305b1
diff --git a/src/lib.rs b/src/lib.rs
index b5f95d6..c8abbdd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -114,13 +114,13 @@
}
}
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
pub enum RegimeVaRange {
Lower,
Upper,
}
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
pub enum TranslationRegime {
EL1_0(RegimeVaRange, u8), // EL1 and EL0 stage 1, TTBRx_EL1
#[cfg(target_feature = "vh")]
@@ -129,6 +129,17 @@
EL3, // EL3, TTBR0_EL3
}
+impl TranslationRegime {
+ fn is_upper_va_range(&self) -> bool {
+ match self {
+ TranslationRegime::EL1_0(RegimeVaRange::Upper, _) => true,
+ #[cfg(target_feature = "vh")]
+ EL2_0(RegimeVaRange::Upper, _) => true,
+ _ => false,
+ }
+ }
+}
+
pub type TranslationGranule<const VA_BITS: usize> = granule::TranslationGranule<VA_BITS>;
pub struct Xlat<const VA_BITS: usize> {
@@ -173,6 +184,15 @@
) -> Self {
let initial_lookup_level = granule.initial_lookup_level();
+ if !address.start.is_valid_in_regime::<VA_BITS>(regime)
+ || !address.end.is_valid_in_regime::<VA_BITS>(regime)
+ {
+ panic!(
+ "Invalid address range {:?} for regime {:?}",
+ address, regime
+ );
+ }
+
let base_table = page_pool
.allocate_pages(
granule.table_size::<Descriptor>(initial_lookup_level),
@@ -547,7 +567,7 @@
) -> Result<VirtualAddress, XlatError> {
let blocks = BlockIterator::new(
region.get_pa(),
- region.base(),
+ region.base().remove_upper_bits::<VA_BITS>(),
region.length(),
self.granule,
)?;
@@ -565,7 +585,7 @@
fn unmap_region(&mut self, region: &VirtualRegion) -> Result<(), XlatError> {
let blocks = BlockIterator::new(
region.get_pa(),
- region.base(),
+ region.base().remove_upper_bits::<VA_BITS>(),
region.length(),
self.granule,
)?;