Skip to content

Commit c29258b

Browse files
Refactor pmsav8 EL1 MPU methods
New methods - set_region - set_attributes - background_region_enable Renamed reconfigure_regions to set_regions and removed the disable/enable lines for consistency. Refactored the configure method to use the new methods internally.
1 parent 762a18a commit c29258b

File tree

1 file changed

+84
-119
lines changed

1 file changed

+84
-119
lines changed

cortex-ar/src/pmsav8.rs

Lines changed: 84 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -63,146 +63,111 @@ impl El1Mpu {
6363
})
6464
}
6565

66-
/// Configure the EL1 MPU
67-
pub fn configure(&mut self, config: &Config) -> Result<(), Error> {
68-
if config.regions.len() > self.num_regions() as usize {
69-
return Err(Error::TooManyRegions);
66+
/// Write a single region to the EL1 MPU
67+
///
68+
/// ## Arguments
69+
///
70+
/// - `region`: The [Region] object containing the configuration for the MPU region.
71+
/// - `idx`: The index of the region to be configured.
72+
///
73+
/// ## Errors
74+
///
75+
/// Returns:
76+
/// - [Error::UnalignedRegion] if the region's start address is not 64-byte aligned.
77+
/// - [Error::UnalignedRegion] if the region's end address is not 63-byte aligned.
78+
/// - [Error::InvalidMair] if the region's MAIR index is invalid (greater than 7).
79+
pub fn set_region(&mut self, idx: u8, region: &Region) -> Result<(), Error> {
80+
let start = *(region.range.start()) as usize as u32;
81+
// Check for 64-byte alignment (0x3F is six bits)
82+
if start & 0x3F != 0 {
83+
return Err(Error::UnalignedRegion(region.range.clone()));
7084
}
71-
for (idx, region) in config.regions.iter().enumerate() {
72-
let start = *(region.range.start()) as usize as u32;
73-
// Check for 64-byte alignment (0x3F is six bits)
74-
if start & 0x3F != 0 {
75-
return Err(Error::UnalignedRegion(region.range.clone()));
76-
}
77-
let end = *(region.range.end()) as usize as u32;
78-
if end & 0x3F != 0x3F {
79-
return Err(Error::UnalignedRegion(region.range.clone()));
80-
}
81-
if region.mair > 7 {
82-
return Err(Error::InvalidMair(region.mair));
83-
}
84-
register::Prselr::write(register::Prselr(idx as u32));
85-
register::Prbar::write({
86-
let mut bar = register::Prbar::new_with_raw_value(0);
87-
bar.set_base(u26::from_u32(start >> 6));
88-
bar.set_access_perms(region.access);
89-
bar.set_nx(region.no_exec);
90-
bar.set_shareability(region.shareability);
91-
bar
92-
});
93-
register::Prlar::write({
94-
let mut lar = register::Prlar::new_with_raw_value(0);
95-
lar.set_limit(u26::from_u32(end >> 6));
96-
lar.set_enabled(region.enable);
97-
lar.set_mair(u3::from_u8(region.mair));
98-
lar
99-
});
85+
let end = *(region.range.end()) as usize as u32;
86+
if end & 0x3F != 0x3F {
87+
return Err(Error::UnalignedRegion(region.range.clone()));
10088
}
101-
102-
let mem_attr0 = config
103-
.memory_attributes
104-
.get(0)
105-
.map(|m| m.to_bits())
106-
.unwrap_or(0) as u32;
107-
let mem_attr1 = config
108-
.memory_attributes
109-
.get(1)
110-
.map(|m| m.to_bits())
111-
.unwrap_or(0) as u32;
112-
let mem_attr2 = config
113-
.memory_attributes
114-
.get(2)
115-
.map(|m| m.to_bits())
116-
.unwrap_or(0) as u32;
117-
let mem_attr3 = config
118-
.memory_attributes
119-
.get(3)
120-
.map(|m| m.to_bits())
121-
.unwrap_or(0) as u32;
122-
let mair0 = mem_attr3 << 24 | mem_attr2 << 16 | mem_attr1 << 8 | mem_attr0;
123-
unsafe {
124-
register::Mair0::write(register::Mair0(mair0));
125-
}
126-
let mem_attr0 = config
127-
.memory_attributes
128-
.get(4)
129-
.map(|m| m.to_bits())
130-
.unwrap_or(0) as u32;
131-
let mem_attr1 = config
132-
.memory_attributes
133-
.get(5)
134-
.map(|m| m.to_bits())
135-
.unwrap_or(0) as u32;
136-
let mem_attr2 = config
137-
.memory_attributes
138-
.get(6)
139-
.map(|m| m.to_bits())
140-
.unwrap_or(0) as u32;
141-
let mem_attr3 = config
142-
.memory_attributes
143-
.get(7)
144-
.map(|m| m.to_bits())
145-
.unwrap_or(0) as u32;
146-
let mair1 = mem_attr3 << 24 | mem_attr2 << 16 | mem_attr1 << 8 | mem_attr0;
147-
unsafe {
148-
register::Mair1::write(register::Mair1(mair1));
89+
if region.mair > 7 {
90+
return Err(Error::InvalidMair(region.mair));
14991
}
150-
151-
register::Sctlr::modify(|r| {
152-
r.set_br(config.background_config);
92+
register::Prselr::write(register::Prselr(idx as u32));
93+
register::Prbar::write({
94+
let mut bar = register::Prbar::new_with_raw_value(0);
95+
bar.set_base(u26::from_u32(start >> 6));
96+
bar.set_access_perms(region.access);
97+
bar.set_nx(region.no_exec);
98+
bar.set_shareability(region.shareability);
99+
bar
153100
});
101+
register::Prlar::write({
102+
let mut lar = register::Prlar::new_with_raw_value(0);
103+
lar.set_limit(u26::from_u32(end >> 6));
104+
lar.set_enabled(region.enable);
105+
lar.set_mair(u3::from_u8(region.mair));
106+
lar
107+
});
108+
154109
Ok(())
155110
}
156111

157-
/// Reconfigure a subset of EL1 MPU regions starting from a specified index.
112+
/// Writes a subset of EL1 MPU regions starting from a specified index.
158113
///
159114
/// ## Arguments
160115
///
161116
/// - `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(
117+
/// - `regions`: A slice of [Region] objects that will overwrite the previous regions starting from `regions_starting_idx`.
118+
pub fn set_regions(
164119
&mut self,
165120
regions_starting_idx: u8,
166121
regions: &[Region],
167122
) -> Result<(), Error> {
168-
self.disable();
169-
170-
if regions.len() as u8 + regions_starting_idx > self.num_regions() {
123+
if regions.len().saturating_add(regions_starting_idx as usize) > self.num_regions() as usize
124+
{
171125
return Err(Error::TooManyRegions);
172126
}
173127

174128
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-
});
129+
self.set_region(idx as u8 + regions_starting_idx, region)?;
203130
}
204131

205-
self.enable();
132+
Ok(())
133+
}
134+
135+
/// Set the memory attributes to MAIR0 and MAIR1
136+
pub fn set_attributes(&mut self, memattrs: &[MemAttr]) {
137+
let mem_attr0 = memattrs.get(0).map(|m| m.to_bits()).unwrap_or(0) as u32;
138+
let mem_attr1 = memattrs.get(1).map(|m| m.to_bits()).unwrap_or(0) as u32;
139+
let mem_attr2 = memattrs.get(2).map(|m| m.to_bits()).unwrap_or(0) as u32;
140+
let mem_attr3 = memattrs.get(3).map(|m| m.to_bits()).unwrap_or(0) as u32;
141+
let mair0 = mem_attr3 << 24 | mem_attr2 << 16 | mem_attr1 << 8 | mem_attr0;
142+
unsafe {
143+
register::Mair0::write(register::Mair0(mair0));
144+
}
145+
let mem_attr0 = memattrs.get(4).map(|m| m.to_bits()).unwrap_or(0) as u32;
146+
let mem_attr1 = memattrs.get(5).map(|m| m.to_bits()).unwrap_or(0) as u32;
147+
let mem_attr2 = memattrs.get(6).map(|m| m.to_bits()).unwrap_or(0) as u32;
148+
let mem_attr3 = memattrs.get(7).map(|m| m.to_bits()).unwrap_or(0) as u32;
149+
let mair1 = mem_attr3 << 24 | mem_attr2 << 16 | mem_attr1 << 8 | mem_attr0;
150+
unsafe {
151+
register::Mair1::write(register::Mair1(mair1));
152+
}
153+
}
154+
155+
/// Enable or disable the background region
156+
pub fn background_region_enable(&mut self, enable: bool) {
157+
register::Sctlr::modify(|r| {
158+
r.set_br(enable);
159+
});
160+
}
161+
162+
/// Configure the EL1 MPU
163+
///
164+
/// Write regions, attributes and enable/disable the background region with a single [Config] struct.
165+
pub fn configure(&mut self, config: &Config) -> Result<(), Error> {
166+
self.set_regions(0, config.regions)?;
167+
168+
self.set_attributes(config.memory_attributes);
169+
170+
self.background_region_enable(config.background_config);
206171

207172
Ok(())
208173
}

0 commit comments

Comments
 (0)