Skip to content

Commit 762a18a

Browse files
Reconfigure EL1 MPU regions at runtime
Added method to the EL1 MPU that allows to reconfigure a only range of regions after the mpu was configured, without rewriting memory indirection attributes.
1 parent 6f287c1 commit 762a18a

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

cortex-ar/src/pmsav8.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,59 @@ impl El1Mpu {
154154
Ok(())
155155
}
156156

157+
/// Reconfigure a subset of EL1 MPU regions starting from a specified index.
158+
///
159+
/// ## Arguments
160+
///
161+
/// - `regions_starting_idx`: The starting index for the regions to be reconfigured.
162+
/// - `regions`: A slice of `Region` objects that will overwrite the previous regions starting from `regions_starting_idx`.
163+
pub fn reconfigure_regions(
164+
&mut self,
165+
regions_starting_idx: u8,
166+
regions: &[Region],
167+
) -> Result<(), Error> {
168+
self.disable();
169+
170+
if regions.len() as u8 + regions_starting_idx > self.num_regions() {
171+
return Err(Error::TooManyRegions);
172+
}
173+
174+
for (idx, region) in regions.iter().enumerate() {
175+
let start = *(region.range.start()) as usize as u32;
176+
// Check for 64-byte alignment (0x3F is six bits)
177+
if start & 0x3F != 0 {
178+
return Err(Error::UnalignedRegion(region.range.clone()));
179+
}
180+
let end = *(region.range.end()) as usize as u32;
181+
if end & 0x3F != 0x3F {
182+
return Err(Error::UnalignedRegion(region.range.clone()));
183+
}
184+
if region.mair > 7 {
185+
return Err(Error::InvalidMair(region.mair));
186+
}
187+
register::Prselr::write(register::Prselr(idx as u32 + regions_starting_idx as u32));
188+
register::Prbar::write({
189+
let mut bar = register::Prbar::new_with_raw_value(0);
190+
bar.set_base(u26::from_u32(start >> 6));
191+
bar.set_access_perms(region.access);
192+
bar.set_nx(region.no_exec);
193+
bar.set_shareability(region.shareability);
194+
bar
195+
});
196+
register::Prlar::write({
197+
let mut lar = register::Prlar::new_with_raw_value(0);
198+
lar.set_limit(u26::from_u32(end >> 6));
199+
lar.set_enabled(region.enable);
200+
lar.set_mair(u3::from_u8(region.mair));
201+
lar
202+
});
203+
}
204+
205+
self.enable();
206+
207+
Ok(())
208+
}
209+
157210
/// Enable the EL1 MPU
158211
pub fn enable(&mut self) {
159212
register::Sctlr::modify(|r| {

0 commit comments

Comments
 (0)