@@ -63,94 +63,112 @@ 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 {
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 ( ) ) ) ;
84+ }
85+ let end = * ( region. range . end ( ) ) as usize as u32 ;
86+ if end & 0x3F != 0x3F {
87+ return Err ( Error :: UnalignedRegion ( region. range . clone ( ) ) ) ;
88+ }
89+ if region. mair > 7 {
90+ return Err ( Error :: InvalidMair ( region. mair ) ) ;
91+ }
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
100+ } ) ;
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+
109+ Ok ( ( ) )
110+ }
111+
112+ /// Writes a subset of EL1 MPU regions starting from a specified index.
113+ ///
114+ /// ## Arguments
115+ ///
116+ /// - `regions_starting_idx`: The starting index for the regions to be reconfigured.
117+ /// - `regions`: A slice of [Region] objects that will overwrite the previous regions starting from `regions_starting_idx`.
118+ pub fn set_regions (
119+ & mut self ,
120+ regions_starting_idx : u8 ,
121+ regions : & [ Region ] ,
122+ ) -> Result < ( ) , Error > {
123+ if regions. len ( ) . saturating_add ( regions_starting_idx as usize ) > self . num_regions ( ) as usize
124+ {
69125 return Err ( Error :: TooManyRegions ) ;
70126 }
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- } ) ;
127+
128+ for ( idx, region) in regions. iter ( ) . enumerate ( ) {
129+ self . set_region ( idx as u8 + regions_starting_idx, region) ?;
100130 }
101131
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 ;
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 ;
122141 let mair0 = mem_attr3 << 24 | mem_attr2 << 16 | mem_attr1 << 8 | mem_attr0;
123142 unsafe {
124143 register:: Mair0 :: write ( register:: Mair0 ( mair0) ) ;
125144 }
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 ;
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 ;
146149 let mair1 = mem_attr3 << 24 | mem_attr2 << 16 | mem_attr1 << 8 | mem_attr0;
147150 unsafe {
148151 register:: Mair1 :: write ( register:: Mair1 ( mair1) ) ;
149152 }
153+ }
150154
155+ /// Enable or disable the background region
156+ pub fn background_region_enable ( & mut self , enable : bool ) {
151157 register:: Sctlr :: modify ( |r| {
152- r. set_br ( config . background_config ) ;
158+ r. set_br ( enable ) ;
153159 } ) ;
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 ) ;
171+
154172 Ok ( ( ) )
155173 }
156174
0 commit comments