Skip to content

Commit 03501fe

Browse files
committed
avoid manual bitshifting for MMU API
1 parent 53091c4 commit 03501fe

File tree

1 file changed

+52
-37
lines changed

1 file changed

+52
-37
lines changed

cortex-ar/src/mmu.rs

Lines changed: 52 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,15 @@ pub enum AccessPermissions {
2020
}
2121

2222
impl AccessPermissions {
23+
#[inline]
24+
pub const fn new(apx: bool, ap: u2) -> Self {
25+
Self::new_with_raw_value(u3::new(((apx as u8) << 2) | ap.value()))
26+
}
27+
2328
/// AP bit for the given access permission.
2429
#[inline]
25-
pub const fn ap(&self) -> u8 {
26-
(*self as u8) & 0b11
30+
pub const fn ap(&self) -> u2 {
31+
u2::new((*self as u8) & 0b11)
2732
}
2833

2934
/// APX bit for the given access permission.
@@ -152,49 +157,46 @@ pub struct SectionAttributes {
152157
}
153158

154159
impl SectionAttributes {
155-
/// Lower 18 bits of the L1 section entry.
156-
#[inline]
157-
pub const fn raw(&self) -> u32 {
158-
((self.non_global as u32) << 17)
159-
| ((self.shareable as u32) << 16)
160-
| ((self.access.apx() as u32) << 15)
161-
| ((self.memory_attrs.type_extensions.value() as u32) << 12)
162-
| ((self.access.ap() as u32) << 10)
163-
| ((self.p_bit as u32) << 9)
164-
| ((self.domain.value() as u32) << 5)
165-
| ((self.execute_never as u32) << 4)
166-
| ((self.memory_attrs.c as u32) << 3)
167-
| ((self.memory_attrs.b as u32) << 2)
168-
| L1EntryType::Section as u32
169-
}
170-
171160
/// Extract the section attributes from a raw L1 section entry.
172161
#[inline]
173-
pub fn from_raw(raw: u32) -> Result<Self, InvalidL1EntryType> {
162+
fn from_raw(raw: u32) -> Result<Self, InvalidL1EntryType> {
174163
let section_type = L1EntryType::new_with_raw_value(u2::new((raw & 0b11) as u8));
175164
if section_type != L1EntryType::Section {
176165
return Err(InvalidL1EntryType(section_type));
177166
}
178167
Ok(Self::from_raw_unchecked(raw))
179168
}
180169

170+
/// Retrieves the corresponding L1 section part without the section base address being set.
171+
const fn l1_section_part(&self) -> L1Section {
172+
L1Section::builder()
173+
.with_base_addr(u12::new(0))
174+
.with_ng(self.non_global)
175+
.with_s(self.shareable)
176+
.with_apx(self.access.apx())
177+
.with_tex(self.memory_attrs.type_extensions)
178+
.with_ap(self.access.ap())
179+
.with_p_bit(self.p_bit)
180+
.with_domain(self.domain)
181+
.with_xn(self.execute_never)
182+
.with_c(self.memory_attrs.c)
183+
.with_b(self.memory_attrs.b)
184+
.with_entry_type(L1EntryType::Section)
185+
.build()
186+
}
187+
181188
/// Extract the section attributes without checking the entry type bits.
182189
#[inline]
183-
pub const fn from_raw_unchecked(raw: u32) -> Self {
190+
const fn from_raw_unchecked(raw: u32) -> Self {
191+
let l1 = L1Section::new_with_raw_value(raw);
184192
Self {
185-
non_global: (raw >> 17) & 0x1 != 0,
186-
shareable: (raw >> 16) & 0x1 != 0,
187-
p_bit: (raw >> 9) & 0x1 != 0,
188-
access: AccessPermissions::new_with_raw_value(u3::new(
189-
((((raw >> 15) & 0b1) as u8) << 2) | (((raw >> 10) & 0b11) as u8),
190-
)),
191-
memory_attrs: MemoryRegionAttributesRaw::new(
192-
u3::new(((raw >> 12) & 0b111) as u8),
193-
((raw >> 3) & 0b1) != 0,
194-
((raw >> 2) & 0b1) as u8 != 0,
195-
),
196-
domain: u4::new(((raw >> 5) & 0b1111) as u8),
197-
execute_never: ((raw >> 4) & 0b1) != 0,
193+
non_global: l1.ng(),
194+
shareable: l1.s(),
195+
p_bit: l1.p_bit(),
196+
access: AccessPermissions::new(l1.apx(), l1.ap()),
197+
memory_attrs: MemoryRegionAttributesRaw::new(l1.tex(), l1.c(), l1.b()),
198+
domain: l1.domain(),
199+
execute_never: l1.xn(),
198200
}
199201
}
200202
}
@@ -203,14 +205,14 @@ impl SectionAttributes {
203205
///
204206
/// The ARM Cortex-A architecture programmers manual chapter 9.4 (p.163) specifies these attributes
205207
/// in more detail.
206-
#[bitbybit::bitfield(u32)]
208+
#[bitbybit::bitfield(u32, default = 0x00)]
207209
#[derive(PartialEq, Eq)]
208210
pub struct L1Section {
209211
/// Section base address.
210212
#[bits(20..=31, rw)]
211213
base_addr: u12,
212214
/// Non-global bit.
213-
#[bit(16, rw)]
215+
#[bit(17, rw)]
214216
ng: bool,
215217
/// Shareable bit.
216218
#[bit(16, rw)]
@@ -265,12 +267,25 @@ impl L1Section {
265267
/// # Panics
266268
///
267269
/// Physcal address not aligned to 1 MB.
268-
pub const fn new(phys_addr: u32, section_attrs: SectionAttributes) -> Self {
270+
pub const fn new_with_addr_and_attrs(phys_addr: u32, section_attrs: SectionAttributes) -> Self {
269271
// Must be aligned to 1 MB
270272
if phys_addr & 0x000F_FFFF != 0 {
271273
panic!("physical base address for L1 section must be aligned to 1 MB");
272274
}
273275
let higher_bits = phys_addr >> 20;
274-
Self::new_with_raw_value((higher_bits << 20) | section_attrs.raw())
276+
Self::new_with_raw_value((higher_bits << 20) | section_attrs.l1_section_part().raw_value())
277+
}
278+
279+
/// Retrieve the section attributes.
280+
#[inline]
281+
pub fn section_attrs(&self) -> Result<SectionAttributes, InvalidL1EntryType> {
282+
SectionAttributes::from_raw(self.raw_value())
283+
}
284+
285+
/// Set the section attributes without changing the address.
286+
#[inline]
287+
pub const fn set_section_attrs(&mut self, section_attrs: SectionAttributes) {
288+
self.raw_value =
289+
((self.base_addr().value() as u32) << 20) | section_attrs.l1_section_part().raw_value();
275290
}
276291
}

0 commit comments

Comments
 (0)