bern_arch/cortex_m/
memory_protection.rs

1//! ARM Cortex-M implementation of [`IMemoryProtection`].
2
3use crate::arch::mpu::{self, Attributes, CachePolicy, Mpu, Permission, RegionNumber, Subregions};
4pub use crate::arch::mpu::{MemoryRegion, Size};
5use crate::arch::Arch;
6use crate::memory_protection::{Config, IMemoryProtection, Type};
7
8use bern_units::memory_size::{Byte, ExtByte};
9use cortex_m::asm;
10use cortex_m_rt::exception;
11
12impl IMemoryProtection for Arch {
13    type MemoryRegion = MemoryRegion;
14
15    fn enable_memory_protection() {
16        let mut mpu = unsafe { Mpu::take() };
17        mpu.enable();
18    }
19
20    fn disable_memory_protection() {
21        let mut mpu = unsafe { Mpu::take() };
22        mpu.disable();
23    }
24
25    fn enable_memory_region(region: u8, config: Config) {
26        let mut mpu = unsafe { Mpu::take() };
27
28        let memory_region = Self::prepare_memory_region(region, config);
29        mpu.set_region(&memory_region);
30    }
31
32    fn disable_memory_region(region: u8) {
33        let mut mpu = unsafe { Mpu::take() };
34        mpu.disable_region(region);
35    }
36
37    fn prepare_memory_region(region: u8, config: Config) -> Self::MemoryRegion {
38        let region_base_address =
39            Mpu::prepare_region_base_address(config.addr as u32, RegionNumber::Use(region));
40
41        let attributes = match config.memory {
42            Type::SramInternal => Attributes::Normal {
43                shareable: false,
44                cache_policy: (
45                    CachePolicy::WriteBack { wa: true },
46                    CachePolicy::WriteBack { wa: true },
47                ),
48            },
49            Type::SramExternal => Attributes::Normal {
50                shareable: false,
51                cache_policy: (
52                    CachePolicy::WriteBack { wa: true },
53                    CachePolicy::WriteBack { wa: true },
54                ),
55            },
56            Type::Flash => Attributes::Normal {
57                shareable: false,
58                cache_policy: (CachePolicy::WriteThrough, CachePolicy::WriteThrough),
59            },
60            Type::Peripheral => Attributes::Device { shareable: true },
61        };
62
63        let region_attributes = Mpu::prepare_region_attributes(
64            config.executable,
65            (
66                Permission::from(config.access.system),
67                Permission::from(config.access.user),
68            ),
69            attributes,
70            Subregions::ALL,
71            config.size.into(),
72        );
73
74        MemoryRegion {
75            region_base_address_reg: region_base_address,
76            region_attribute_size_reg: region_attributes,
77        }
78    }
79
80    fn prepare_unused_region(region: u8) -> Self::MemoryRegion {
81        MemoryRegion {
82            region_base_address_reg: mpu::MPU_REGION_VALID | region as u32,
83            region_attribute_size_reg: 0, // disable region
84        }
85    }
86
87    fn apply_regions(memory_regions: &[MemoryRegion; 3]) {
88        let mut mpu = unsafe { Mpu::take() };
89
90        mpu.set_regions(memory_regions);
91    }
92
93    fn min_region_size() -> Byte {
94        32.B()
95    }
96
97    // todo: read from MPU
98    fn n_memory_regions() -> u8 {
99        8
100    }
101}
102
103extern "Rust" {
104    /// Exception called on a memory protection violation.
105    ///
106    /// **Note:** Must be implemented in the kernel.
107    pub fn memory_protection_exception();
108}
109
110#[allow(non_snake_case)]
111#[no_mangle]
112pub unsafe extern "C" fn MemoryManagement() -> () {
113    unsafe {
114        memory_protection_exception();
115    }
116}
117
118////////////////////////////////////////////////////////////////////////////////
119
120#[repr(align(32))]
121pub struct A32;
122
123#[repr(align(64))]
124pub struct A64;
125
126#[repr(align(128))]
127pub struct A128;
128
129#[repr(align(256))]
130pub struct A256;
131
132#[repr(align(512))]
133pub struct A512;
134
135#[repr(align(1_024))]
136pub struct A1K;
137
138#[repr(align(2_048))]
139pub struct A2K;
140
141#[repr(align(4_096))]
142pub struct A4K;
143
144#[repr(align(8_192))]
145pub struct A8K;
146
147#[repr(align(16_384))]
148pub struct A16K;
149
150#[repr(align(32_768))]
151pub struct A32K;
152
153#[repr(align(65_536))]
154pub struct A64K;
155
156#[repr(align(131_072))]
157pub struct A128K;
158
159#[repr(align(262_144))]
160pub struct A256K;
161
162#[repr(align(524_288))]
163pub struct A512K;
164
165#[repr(align(1_048_576))]
166pub struct A1M;
167
168#[repr(align(2_097_152))]
169pub struct A2M;
170
171#[repr(align(4_194_304))]
172pub struct A4M;
173
174#[repr(align(8_388_608))]
175pub struct A8M;
176
177#[repr(align(16_777_216))]
178pub struct A16M;
179
180#[repr(align(33_554_432))]
181pub struct A32M;
182
183#[repr(align(67_108_864))]
184pub struct A64M;
185
186#[repr(align(134_217_728))]
187pub struct A128M;
188
189#[repr(align(268_435_456))]
190pub struct A256M;
191
192#[repr(align(536_870_912))]
193pub struct A512M;
194
195/// Return a valid memory protection alignment object from size in bytes.
196#[macro_export]
197macro_rules! alignment_from_size {
198    (32) => {
199        $crate::arch::memory_protection::A32
200    };
201    (64) => {
202        $crate::arch::memory_protection::A64
203    };
204    (128) => {
205        $crate::arch::memory_protection::A128
206    };
207    (256) => {
208        $crate::arch::memory_protection::A256
209    };
210    (512) => {
211        $crate::arch::memory_protection::A512
212    };
213    (1_024) => {
214        $crate::arch::memory_protection::A1K
215    };
216    (1024) => {
217        $crate::arch::memory_protection::A1K
218    };
219    (2_048) => {
220        $crate::arch::memory_protection::A2K
221    };
222    (2048) => {
223        $crate::arch::memory_protection::A2K
224    };
225    (4_096) => {
226        $crate::arch::memory_protection::A4K
227    };
228    (4096) => {
229        $crate::arch::memory_protection::A4K
230    };
231    (8_192) => {
232        $crate::arch::memory_protection::A8K
233    };
234    (8192) => {
235        $crate::arch::memory_protection::A8K
236    };
237    (16_384) => {
238        $crate::arch::memory_protection::A16K
239    };
240    (16384) => {
241        $crate::arch::memory_protection::A16K
242    };
243    (32_768) => {
244        $crate::arch::memory_protection::A32K
245    };
246    (32768) => {
247        $crate::arch::memory_protection::A32K
248    };
249    (65_536) => {
250        $crate::arch::memory_protection::A64K
251    };
252    (65536) => {
253        $crate::arch::memory_protection::A64K
254    };
255    (131_072) => {
256        $crate::arch::memory_protection::A128K
257    };
258    (131072) => {
259        $crate::arch::memory_protection::A128K
260    };
261    (262_144) => {
262        $crate::arch::memory_protection::A256K
263    };
264    (262144) => {
265        $crate::arch::memory_protection::A256K
266    };
267    (524_288) => {
268        $crate::arch::memory_protection::A512K
269    };
270    (524288) => {
271        $crate::arch::memory_protection::A512K
272    };
273    (1_048_576) => {
274        $crate::arch::memory_protection::A1M
275    };
276    (1048576) => {
277        $crate::arch::memory_protection::A1M
278    };
279    ($x:expr) => {
280        compile_error!(
281            "Size does not meet alignment requirements from the MPU. \
282        Compatible sizes are: 32B, 64B, 128B, 256B, 512B, 1KB, 2KB, 4KB, 16KB, \
283        32KB, 64KB, 128KB, 256KB, 512KB, 1M"
284        );
285    };
286}
287
288/// Return a valid memory protection size object from size in bytes.
289#[macro_export]
290macro_rules! size_from_raw {
291    (32) => {
292        $crate::arch::memory_protection::Size::S32
293    };
294    (64) => {
295        $crate::arch::memory_protection::Size::S64
296    };
297    (128) => {
298        $crate::arch::memory_protection::Size::S128
299    };
300    (256) => {
301        $crate::arch::memory_protection::Size::S256
302    };
303    (512) => {
304        $crate::arch::memory_protection::Size::S512
305    };
306    (1_024) => {
307        $crate::arch::memory_protection::Size::S1K
308    };
309    (1024) => {
310        $crate::arch::memory_protection::Size::S1K
311    };
312    (2_048) => {
313        $crate::arch::memory_protection::Size::S2K
314    };
315    (2048) => {
316        $crate::arch::memory_protection::Size::S2K
317    };
318    (4_096) => {
319        $crate::arch::memory_protection::Size::S4K
320    };
321    (4096) => {
322        $crate::arch::memory_protection::Size::S4K
323    };
324    (8_192) => {
325        $crate::arch::memory_protection::Size::S8K
326    };
327    (8192) => {
328        $crate::arch::memory_protection::Size::S8K
329    };
330    (16_384) => {
331        $crate::arch::memory_protection::Size::S16K
332    };
333    (16384) => {
334        $crate::arch::memory_protection::Size::S16K
335    };
336    (32_768) => {
337        $crate::arch::memory_protection::Size::S32K
338    };
339    (32768) => {
340        $crate::arch::memory_protection::Size::S32K
341    };
342    (65_536) => {
343        $crate::arch::memory_protection::Size::S64K
344    };
345    (65536) => {
346        $crate::arch::memory_protection::Size::S64K
347    };
348    (131_072) => {
349        $crate::arch::memory_protection::Size::S128K
350    };
351    (131072) => {
352        $crate::arch::memory_protection::Size::S128K
353    };
354    (262_144) => {
355        $crate::arch::memory_protection::Size::S256K
356    };
357    (262144) => {
358        $crate::arch::memory_protection::Size::S256K
359    };
360    (524_288) => {
361        $crate::arch::memory_protection::Size::S512K
362    };
363    (524288) => {
364        $crate::arch::memory_protection::Size::S512K
365    };
366    (1_048_576) => {
367        $crate::arch::memory_protection::Size::S1M
368    };
369    (1048576) => {
370        $crate::arch::memory_protection::Size::S1M
371    };
372    ($x:expr) => {
373        compile_error!(
374            "Size cannot be protected by MPU. \
375        Compatible sizes are: 32B, 64B, 128B, 256B, 512B, 1KB, 2KB, 4KB, 16KB, \
376        32KB, 64KB, 128KB, 256KB, 512KB, 1M"
377        );
378    };
379}