@@ -63,94 +63,112 @@ impl El1Mpu {
63
63
} )
64
64
}
65
65
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
+ {
69
125
return Err ( Error :: TooManyRegions ) ;
70
126
}
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) ?;
100
130
}
101
131
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 ;
122
141
let mair0 = mem_attr3 << 24 | mem_attr2 << 16 | mem_attr1 << 8 | mem_attr0;
123
142
unsafe {
124
143
register:: Mair0 :: write ( register:: Mair0 ( mair0) ) ;
125
144
}
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 ;
146
149
let mair1 = mem_attr3 << 24 | mem_attr2 << 16 | mem_attr1 << 8 | mem_attr0;
147
150
unsafe {
148
151
register:: Mair1 :: write ( register:: Mair1 ( mair1) ) ;
149
152
}
153
+ }
150
154
155
+ /// Enable or disable the background region
156
+ pub fn background_region_enable ( & mut self , enable : bool ) {
151
157
register:: Sctlr :: modify ( |r| {
152
- r. set_br ( config . background_config ) ;
158
+ r. set_br ( enable ) ;
153
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 ) ;
171
+
154
172
Ok ( ( ) )
155
173
}
156
174
0 commit comments