Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2017 Linaro Limited.
3 : : * Copyright (c) 2018 Nordic Semiconductor ASA.
4 : : *
5 : : * SPDX-License-Identifier: Apache-2.0
6 : : */
7 : :
8 : : #ifndef ZEPHYR_ARCH_ARM_CORE_AARCH32_MPU_ARM_MPU_V8_INTERNAL_H_
9 : : #define ZEPHYR_ARCH_ARM_CORE_AARCH32_MPU_ARM_MPU_V8_INTERNAL_H_
10 : :
11 : : #include <aarch32/cortex_m/cmse.h>
12 : : #define LOG_LEVEL CONFIG_MPU_LOG_LEVEL
13 : : #include <logging/log.h>
14 : :
15 : : /**
16 : : * @brief internal structure holding information of
17 : : * memory areas where dynamic MPU programming
18 : : * is allowed.
19 : : */
20 : : struct dynamic_region_info {
21 : : int index;
22 : : struct arm_mpu_region region_conf;
23 : : };
24 : :
25 : : /**
26 : : * Global array, holding the MPU region index of
27 : : * the memory region inside which dynamic memory
28 : : * regions may be configured.
29 : : */
30 : : static struct dynamic_region_info dyn_reg_info[MPU_DYNAMIC_REGION_AREAS_NUM];
31 : :
32 : :
33 : : /* Global MPU configuration at system initialization. */
34 : 1 : static void mpu_init(void)
35 : : {
36 : : /* Configure the cache-ability attributes for all the
37 : : * different types of memory regions.
38 : : */
39 : :
40 : : /* Flash region(s): Attribute-0
41 : : * SRAM region(s): Attribute-1
42 : : * SRAM no cache-able regions(s): Attribute-2
43 : : */
44 : 1 : MPU->MAIR0 =
45 : : ((MPU_MAIR_ATTR_FLASH << MPU_MAIR0_Attr0_Pos) &
46 : : MPU_MAIR0_Attr0_Msk)
47 : : |
48 : : ((MPU_MAIR_ATTR_SRAM << MPU_MAIR0_Attr1_Pos) &
49 : : MPU_MAIR0_Attr1_Msk)
50 : : |
51 : : ((MPU_MAIR_ATTR_SRAM_NOCACHE << MPU_MAIR0_Attr2_Pos) &
52 : : MPU_MAIR0_Attr2_Msk);
53 : 1 : }
54 : :
55 : : /* This internal function performs MPU region initialization.
56 : : *
57 : : * Note:
58 : : * The caller must provide a valid region index.
59 : : */
60 : 2 : static void region_init(const uint32_t index,
61 : : const struct arm_mpu_region *region_conf)
62 : : {
63 : 2 : ARM_MPU_SetRegion(
64 : : /* RNR */
65 : : index,
66 : : /* RBAR */
67 : 2 : (region_conf->base & MPU_RBAR_BASE_Msk)
68 : 2 : | (region_conf->attr.rbar &
69 : : (MPU_RBAR_XN_Msk | MPU_RBAR_AP_Msk | MPU_RBAR_SH_Msk)),
70 : : /* RLAR */
71 : 2 : (region_conf->attr.r_limit & MPU_RLAR_LIMIT_Msk)
72 : 2 : | ((region_conf->attr.mair_idx << MPU_RLAR_AttrIndx_Pos)
73 : 2 : & MPU_RLAR_AttrIndx_Msk)
74 : 2 : | MPU_RLAR_EN_Msk
75 : : );
76 : :
77 [ + - ]: 2 : LOG_DBG("[%d] 0x%08x 0x%08x 0x%08x 0x%08x",
78 : : index, region_conf->base, region_conf->attr.rbar,
79 : : region_conf->attr.mair_idx, region_conf->attr.r_limit);
80 : 2 : }
81 : :
82 : : /* @brief Partition sanity check
83 : : *
84 : : * This internal function performs run-time sanity check for
85 : : * MPU region start address and size.
86 : : *
87 : : * @param part Pointer to the data structure holding the partition
88 : : * information (must be valid).
89 : : * */
90 : 0 : static int mpu_partition_is_valid(const struct z_arm_mpu_partition *part)
91 : : {
92 : : /* Partition size must be a multiple of the minimum MPU region
93 : : * size. Start address of the partition must align with the
94 : : * minimum MPU region size.
95 : : */
96 : 0 : int partition_is_valid =
97 : 0 : (part->size >= CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE)
98 : 0 : &&
99 : 0 : ((part->size &
100 : : (~(CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE - 1)))
101 [ # # ]: 0 : == part->size)
102 [ # # ]: 0 : &&
103 [ # # ]: 0 : ((part->start &
104 : : (CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE - 1)) == 0U);
105 : :
106 : 0 : return partition_is_valid;
107 : : }
108 : :
109 : : /**
110 : : * This internal function returns the MPU region, in which a
111 : : * buffer, specified by its start address and size, lies. If
112 : : * a valid MPU region cannot be derived the function returns
113 : : * -EINVAL.
114 : : *
115 : : * Note that, for the function to work properly, the ARM MPU
116 : : * needs to be enabled.
117 : : *
118 : : */
119 : 1 : static inline int get_region_index(uint32_t start, uint32_t size)
120 : : {
121 : 1 : uint32_t region_start_addr = arm_cmse_mpu_region_get(start);
122 : 1 : uint32_t region_end_addr = arm_cmse_mpu_region_get(start + size - 1);
123 : :
124 : : /* MPU regions are contiguous so return the region number,
125 : : * if both start and end address are in the same region.
126 : : */
127 [ + - ]: 1 : if (region_start_addr == region_end_addr) {
128 : 1 : return region_start_addr;
129 : : }
130 : 0 : return -EINVAL;
131 : : }
132 : :
133 : 0 : static inline uint32_t mpu_region_get_base(const uint32_t index)
134 : : {
135 : 0 : MPU->RNR = index;
136 : 0 : return MPU->RBAR & MPU_RBAR_BASE_Msk;
137 : : }
138 : :
139 : 0 : static inline void mpu_region_set_base(const uint32_t index, const uint32_t base)
140 : : {
141 : 0 : MPU->RNR = index;
142 : 0 : MPU->RBAR = (MPU->RBAR & (~MPU_RBAR_BASE_Msk))
143 : 0 : | (base & MPU_RBAR_BASE_Msk);
144 : 0 : }
145 : :
146 : 0 : static inline uint32_t mpu_region_get_last_addr(const uint32_t index)
147 : : {
148 : 0 : MPU->RNR = index;
149 : 0 : return (MPU->RLAR & MPU_RLAR_LIMIT_Msk) | (~MPU_RLAR_LIMIT_Msk);
150 : : }
151 : :
152 : 0 : static inline void mpu_region_set_limit(const uint32_t index, const uint32_t limit)
153 : : {
154 : 0 : MPU->RNR = index;
155 : 0 : MPU->RLAR = (MPU->RLAR & (~MPU_RLAR_LIMIT_Msk))
156 : 0 : | (limit & MPU_RLAR_LIMIT_Msk);
157 : 0 : }
158 : :
159 : 1 : static inline void mpu_region_get_access_attr(const uint32_t index,
160 : : arm_mpu_region_attr_t *attr)
161 : : {
162 : 1 : MPU->RNR = index;
163 : :
164 : 1 : attr->rbar = MPU->RBAR &
165 : : (MPU_RBAR_XN_Msk | MPU_RBAR_AP_Msk | MPU_RBAR_SH_Msk);
166 : 1 : attr->mair_idx = (MPU->RLAR & MPU_RLAR_AttrIndx_Msk) >>
167 : : MPU_RLAR_AttrIndx_Pos;
168 : 1 : }
169 : :
170 : 1 : static inline void mpu_region_get_conf(const uint32_t index,
171 : : struct arm_mpu_region *region_conf)
172 : : {
173 : 1 : MPU->RNR = index;
174 : :
175 : : /* Region attribution:
176 : : * - Cache-ability
177 : : * - Share-ability
178 : : * - Access Permissions
179 : : */
180 : 1 : mpu_region_get_access_attr(index, ®ion_conf->attr);
181 : :
182 : : /* Region base address */
183 : 1 : region_conf->base = (MPU->RBAR & MPU_RBAR_BASE_Msk);
184 : :
185 : : /* Region limit address */
186 : 1 : region_conf->attr.r_limit = MPU->RLAR & MPU_RLAR_LIMIT_Msk;
187 : 1 : }
188 : :
189 : : /**
190 : : * This internal function is utilized by the MPU driver to combine a given
191 : : * region attribute configuration and size and fill-in a driver-specific
192 : : * structure with the correct MPU region configuration.
193 : : */
194 : 0 : static inline void get_region_attr_from_mpu_partition_info(
195 : : arm_mpu_region_attr_t *p_attr,
196 : : const k_mem_partition_attr_t *attr, uint32_t base, uint32_t size)
197 : : {
198 : 0 : p_attr->rbar = attr->rbar &
199 : : (MPU_RBAR_XN_Msk | MPU_RBAR_AP_Msk | MPU_RBAR_SH_Msk);
200 : 0 : p_attr->mair_idx = attr->mair_idx;
201 : 0 : p_attr->r_limit = REGION_LIMIT_ADDR(base, size);
202 : 0 : }
203 : :
204 : : #if defined(CONFIG_USERSPACE)
205 : :
206 : : /**
207 : : * This internal function returns the minimum HW MPU region index
208 : : * that may hold the configuration of a dynamic memory region.
209 : : *
210 : : * Browse through the memory areas marked for dynamic MPU programming,
211 : : * pick the one with the minimum MPU region index. Return that index.
212 : : *
213 : : * The function is optimized for the (most common) use-case of a single
214 : : * marked area for dynamic memory regions.
215 : : */
216 : : static inline int get_dyn_region_min_index(void)
217 : : {
218 : : int dyn_reg_min_index = dyn_reg_info[0].index;
219 : : #if MPU_DYNAMIC_REGION_AREAS_NUM > 1
220 : : for (int i = 1; i < MPU_DYNAMIC_REGION_AREAS_NUM; i++) {
221 : : if ((dyn_reg_info[i].index != -EINVAL) &&
222 : : (dyn_reg_info[i].index < dyn_reg_min_index)
223 : : ) {
224 : : dyn_reg_min_index = dyn_reg_info[i].index;
225 : : }
226 : : }
227 : : #endif
228 : : return dyn_reg_min_index;
229 : : }
230 : :
231 : : static inline uint32_t mpu_region_get_size(uint32_t index)
232 : : {
233 : : return mpu_region_get_last_addr(index) + 1
234 : : - mpu_region_get_base(index);
235 : : }
236 : :
237 : : /**
238 : : * This internal function checks if region is enabled or not.
239 : : *
240 : : * Note:
241 : : * The caller must provide a valid region number.
242 : : */
243 : : static inline int is_enabled_region(uint32_t index)
244 : : {
245 : : MPU->RNR = index;
246 : :
247 : : return (MPU->RLAR & MPU_RLAR_EN_Msk) ? 1 : 0;
248 : : }
249 : :
250 : : /**
251 : : * This internal function validates whether a given memory buffer
252 : : * is user accessible or not.
253 : : *
254 : : * Note: [Doc. number: ARM-ECM-0359818]
255 : : * "Some SAU, IDAU, and MPU configurations block the efficient implementation
256 : : * of an address range check. The CMSE intrinsic operates under the assumption
257 : : * that the configuration of the SAU, IDAU, and MPU is constrained as follows:
258 : : * - An object is allocated in a single MPU/SAU/IDAU region.
259 : : * - A stack is allocated in a single region.
260 : : *
261 : : * These points imply that the memory buffer does not span across multiple MPU,
262 : : * SAU, or IDAU regions."
263 : : *
264 : : * MPU regions are configurable, however, some platforms might have fixed-size
265 : : * SAU or IDAU regions. So, even if a buffer is allocated inside a single MPU
266 : : * region, it might span across multiple SAU/IDAU regions, which will make the
267 : : * TT-based address range check fail.
268 : : *
269 : : * Therefore, the function performs a second check, which is based on MPU only,
270 : : * in case the fast address range check fails.
271 : : *
272 : : */
273 : : static inline int mpu_buffer_validate(void *addr, size_t size, int write)
274 : : {
275 : : uint32_t _addr = (uint32_t)addr;
276 : : uint32_t _size = (uint32_t)size;
277 : :
278 : : if (write) {
279 : : if (arm_cmse_addr_range_readwrite_ok(_addr, _size, 1)) {
280 : : return 0;
281 : : }
282 : : } else {
283 : : if (arm_cmse_addr_range_read_ok(_addr, _size, 1)) {
284 : : return 0;
285 : : }
286 : : }
287 : :
288 : : #if defined(CONFIG_CPU_HAS_TEE)
289 : : /*
290 : : * Validation failure may be due to SAU/IDAU presence.
291 : : * We re-check user accessibility based on MPU only.
292 : : */
293 : : int32_t r_index_base = arm_cmse_mpu_region_get(_addr);
294 : : int32_t r_index_last = arm_cmse_mpu_region_get(_addr + _size - 1);
295 : :
296 : : if ((r_index_base != -EINVAL) && (r_index_base == r_index_last)) {
297 : : /* Valid MPU region, check permissions on base address only. */
298 : : if (write) {
299 : : if (arm_cmse_addr_readwrite_ok(_addr, 1)) {
300 : : return 0;
301 : : }
302 : : } else {
303 : : if (arm_cmse_addr_read_ok(_addr, 1)) {
304 : : return 0;
305 : : }
306 : : }
307 : : }
308 : : #endif /* CONFIG_CPU_HAS_TEE */
309 : : return -EPERM;
310 : : }
311 : :
312 : :
313 : : #endif /* CONFIG_USERSPACE */
314 : :
315 : : static int region_allocate_and_init(const uint8_t index,
316 : : const struct arm_mpu_region *region_conf);
317 : :
318 : : static int mpu_configure_region(const uint8_t index,
319 : : const struct z_arm_mpu_partition *new_region);
320 : :
321 : : #if !defined(CONFIG_MPU_GAP_FILLING)
322 : : static int mpu_configure_regions(const struct z_arm_mpu_partition
323 : : regions[], uint8_t regions_num, uint8_t start_reg_index,
324 : : bool do_sanity_check);
325 : : #endif
326 : :
327 : : /* This internal function programs a set of given MPU regions
328 : : * over a background memory area, optionally performing a
329 : : * sanity check of the memory regions to be programmed.
330 : : *
331 : : * The function performs a full partition of the background memory
332 : : * area, effectively, leaving no space in this area uncovered by MPU.
333 : : */
334 : 1 : static int mpu_configure_regions_and_partition(const struct z_arm_mpu_partition
335 : : regions[], uint8_t regions_num, uint8_t start_reg_index,
336 : : bool do_sanity_check)
337 : : {
338 : : int i;
339 : 1 : int reg_index = start_reg_index;
340 : :
341 [ + + ]: 2 : for (i = 0; i < regions_num; i++) {
342 [ + - ]: 1 : if (regions[i].size == 0U) {
343 : 1 : continue;
344 : : }
345 : : /* Non-empty region. */
346 : :
347 [ # # # # ]: 0 : if (do_sanity_check &&
348 : 0 : (!mpu_partition_is_valid(®ions[i]))) {
349 [ # # ]: 0 : LOG_ERR("Partition %u: sanity check failed.", i);
350 : 0 : return -EINVAL;
351 : : }
352 : :
353 : : /* Derive the index of the underlying MPU region,
354 : : * inside which the new region will be configured.
355 : : */
356 : : int u_reg_index =
357 : 0 : get_region_index(regions[i].start, regions[i].size);
358 : :
359 [ # # # # ]: 0 : if ((u_reg_index == -EINVAL) ||
360 : : (u_reg_index > (reg_index - 1))) {
361 [ # # ]: 0 : LOG_ERR("Invalid underlying region index %u",
362 : : u_reg_index);
363 : 0 : return -EINVAL;
364 : : }
365 : :
366 : : /*
367 : : * The new memory region is to be placed inside the underlying
368 : : * region, possibly splitting the underlying region into two.
369 : : */
370 : 0 : uint32_t u_reg_base = mpu_region_get_base(u_reg_index);
371 : 0 : uint32_t u_reg_last = mpu_region_get_last_addr(u_reg_index);
372 : 0 : uint32_t reg_last = regions[i].start + regions[i].size - 1;
373 : :
374 [ # # # # ]: 0 : if ((regions[i].start == u_reg_base) &&
375 : : (reg_last == u_reg_last)) {
376 : : /* The new region overlaps entirely with the
377 : : * underlying region. In this case we simply
378 : : * update the partition attributes of the
379 : : * underlying region with those of the new
380 : : * region.
381 : : */
382 : 0 : mpu_configure_region(u_reg_index, ®ions[i]);
383 [ # # ]: 0 : } else if (regions[i].start == u_reg_base) {
384 : : /* The new region starts exactly at the start of the
385 : : * underlying region; the start of the underlying
386 : : * region needs to be set to the end of the new region.
387 : : */
388 : 0 : mpu_region_set_base(u_reg_index,
389 : 0 : regions[i].start + regions[i].size);
390 : :
391 : : reg_index =
392 : 0 : mpu_configure_region(reg_index, ®ions[i]);
393 : :
394 [ # # ]: 0 : if (reg_index == -EINVAL) {
395 : 0 : return reg_index;
396 : : }
397 : :
398 : 0 : reg_index++;
399 [ # # ]: 0 : } else if (reg_last == u_reg_last) {
400 : : /* The new region ends exactly at the end of the
401 : : * underlying region; the end of the underlying
402 : : * region needs to be set to the start of the
403 : : * new region.
404 : : */
405 : 0 : mpu_region_set_limit(u_reg_index,
406 : 0 : regions[i].start - 1);
407 : :
408 : : reg_index =
409 : 0 : mpu_configure_region(reg_index, ®ions[i]);
410 : :
411 [ # # ]: 0 : if (reg_index == -EINVAL) {
412 : 0 : return reg_index;
413 : : }
414 : :
415 : 0 : reg_index++;
416 : : } else {
417 : : /* The new regions lies strictly inside the
418 : : * underlying region, which needs to split
419 : : * into two regions.
420 : : */
421 : 0 : mpu_region_set_limit(u_reg_index,
422 : 0 : regions[i].start - 1);
423 : :
424 : : reg_index =
425 : 0 : mpu_configure_region(reg_index, ®ions[i]);
426 : :
427 [ # # ]: 0 : if (reg_index == -EINVAL) {
428 : 0 : return reg_index;
429 : : }
430 : 0 : reg_index++;
431 : :
432 : : /* The additional region shall have the same
433 : : * access attributes as the initial underlying
434 : : * region.
435 : : */
436 : : struct arm_mpu_region fill_region;
437 : :
438 : 0 : mpu_region_get_access_attr(u_reg_index,
439 : : &fill_region.attr);
440 : 0 : fill_region.base = regions[i].start +
441 : 0 : regions[i].size;
442 : 0 : fill_region.attr.r_limit =
443 : 0 : REGION_LIMIT_ADDR((regions[i].start +
444 : : regions[i].size), (u_reg_last - reg_last));
445 : :
446 : : reg_index =
447 : 0 : region_allocate_and_init(reg_index,
448 : : (const struct arm_mpu_region *)
449 : : &fill_region);
450 : :
451 [ # # ]: 0 : if (reg_index == -EINVAL) {
452 : 0 : return reg_index;
453 : : }
454 : :
455 : 0 : reg_index++;
456 : : }
457 : : }
458 : :
459 : 1 : return reg_index;
460 : : }
461 : :
462 : : /* This internal function programs the static MPU regions.
463 : : *
464 : : * It returns the number of MPU region indices configured.
465 : : *
466 : : * Note:
467 : : * If the static MPU regions configuration has not been successfully
468 : : * performed, the error signal is propagated to the caller of the function.
469 : : */
470 : 1 : static int mpu_configure_static_mpu_regions(const struct z_arm_mpu_partition
471 : : static_regions[], const uint8_t regions_num,
472 : : const uint32_t background_area_base,
473 : : const uint32_t background_area_end)
474 : : {
475 : 1 : int mpu_reg_index = static_regions_num;
476 : :
477 : : /* In ARMv8-M architecture the static regions are programmed on SRAM,
478 : : * forming a full partition of the background area, specified by the
479 : : * given boundaries.
480 : : */
481 : : ARG_UNUSED(background_area_base);
482 : : ARG_UNUSED(background_area_end);
483 : :
484 : 1 : mpu_reg_index = mpu_configure_regions_and_partition(static_regions,
485 : : regions_num, mpu_reg_index, true);
486 : :
487 : 1 : static_regions_num = mpu_reg_index;
488 : :
489 : 1 : return mpu_reg_index;
490 : : }
491 : :
492 : : /* This internal function marks and stores the configuration of memory areas
493 : : * where dynamic region programming is allowed. Return zero on success, or
494 : : * -EINVAL on error.
495 : : */
496 : 1 : static int mpu_mark_areas_for_dynamic_regions(
497 : : const struct z_arm_mpu_partition dyn_region_areas[],
498 : : const uint8_t dyn_region_areas_num)
499 : : {
500 : : /* In ARMv8-M architecture we need to store the index values
501 : : * and the default configuration of the MPU regions, inside
502 : : * which dynamic memory regions may be programmed at run-time.
503 : : */
504 [ + + ]: 2 : for (int i = 0; i < dyn_region_areas_num; i++) {
505 [ - + ]: 1 : if (dyn_region_areas[i].size == 0U) {
506 : 0 : continue;
507 : : }
508 : : /* Non-empty area */
509 : :
510 : : /* Retrieve HW MPU region index */
511 : 1 : dyn_reg_info[i].index =
512 : 1 : get_region_index(dyn_region_areas[i].start,
513 : 1 : dyn_region_areas[i].size);
514 : :
515 [ - + ]: 1 : if (dyn_reg_info[i].index == -EINVAL) {
516 : :
517 : 0 : return -EINVAL;
518 : : }
519 : :
520 [ - + ]: 1 : if (dyn_reg_info[i].index >= static_regions_num) {
521 : :
522 : 0 : return -EINVAL;
523 : : }
524 : :
525 : : /* Store default configuration */
526 : 1 : mpu_region_get_conf(dyn_reg_info[i].index,
527 : : &dyn_reg_info[i].region_conf);
528 : : }
529 : :
530 : 1 : return 0;
531 : : }
532 : :
533 : : /**
534 : : * Get the number of supported MPU regions.
535 : : */
536 : 1 : static inline uint8_t get_num_regions(void)
537 : : {
538 : : #if defined(NUM_MPU_REGIONS)
539 : : /* Retrieve the number of regions from DTS configuration. */
540 : 1 : return NUM_MPU_REGIONS;
541 : : #else
542 : : uint32_t type = MPU->TYPE;
543 : :
544 : : type = (type & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
545 : :
546 : : return (uint8_t)type;
547 : : #endif /* NUM_MPU_REGIONS */
548 : : }
549 : :
550 : : /* This internal function programs the dynamic MPU regions.
551 : : *
552 : : * It returns the number of MPU region indices configured.
553 : : *
554 : : * Note:
555 : : * If the dynamic MPU regions configuration has not been successfully
556 : : * performed, the error signal is propagated to the caller of the function.
557 : : */
558 : 0 : static int mpu_configure_dynamic_mpu_regions(const struct z_arm_mpu_partition
559 : : dynamic_regions[], uint8_t regions_num)
560 : : {
561 : 0 : int mpu_reg_index = static_regions_num;
562 : :
563 : : /* Disable all MPU regions except for the static ones. */
564 [ # # ]: 0 : for (int i = mpu_reg_index; i < get_num_regions(); i++) {
565 : 0 : ARM_MPU_ClrRegion(i);
566 : : }
567 : :
568 : : #if defined(CONFIG_MPU_GAP_FILLING)
569 : : /* Reset MPU regions inside which dynamic memory regions may
570 : : * be programmed.
571 : : */
572 [ # # ]: 0 : for (int i = 0; i < MPU_DYNAMIC_REGION_AREAS_NUM; i++) {
573 : 0 : region_init(dyn_reg_info[i].index,
574 : 0 : &dyn_reg_info[i].region_conf);
575 : : }
576 : :
577 : : /* In ARMv8-M architecture the dynamic regions are programmed on SRAM,
578 : : * forming a full partition of the background area, specified by the
579 : : * given boundaries.
580 : : */
581 : 0 : mpu_reg_index = mpu_configure_regions_and_partition(dynamic_regions,
582 : : regions_num, mpu_reg_index, true);
583 : : #else
584 : :
585 : : /* We are going to skip the full partition of the background areas.
586 : : * So we can disable MPU regions inside which dynamic memory regions
587 : : * may be programmed.
588 : : */
589 : : for (int i = 0; i < MPU_DYNAMIC_REGION_AREAS_NUM; i++) {
590 : : ARM_MPU_ClrRegion(dyn_reg_info[i].index);
591 : : }
592 : :
593 : : /* The dynamic regions are now programmed on top of
594 : : * existing SRAM region configuration.
595 : : */
596 : : mpu_reg_index = mpu_configure_regions(dynamic_regions,
597 : : regions_num, mpu_reg_index, true);
598 : :
599 : : #endif /* CONFIG_MPU_GAP_FILLING */
600 : 0 : return mpu_reg_index;
601 : : }
602 : :
603 : : #endif /* ZEPHYR_ARCH_ARM_CORE_AARCH32_MPU_ARM_MPU_V8_INTERNAL_H_ */
|