Skip to content

Commit 62f598e

Browse files
crafcat7xiaoxiang781216
authored andcommitted
arm_mpu:Reentrant allocation Region
Changes have been completed: 1.armv7m 2.armv8m 3.armv7r 4.arm64 Signed-off-by: chenrun1 <[email protected]>
1 parent 3a25286 commit 62f598e

File tree

8 files changed

+1732
-672
lines changed

8 files changed

+1732
-672
lines changed

arch/arm/src/armv7-m/arm_mpu.c

Lines changed: 227 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <stdint.h>
2828
#include <assert.h>
29+
#include <debug.h>
2930

3031
#include "mpu.h"
3132
#include "arm_internal.h"
@@ -69,9 +70,9 @@ static const uint8_t g_ls_regionmask[9] =
6970
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
7071
};
7172

72-
/* The next available region number */
73+
/* The available region bitmap */
7374

74-
static uint8_t g_region;
75+
static unsigned int g_mpu_region;
7576

7677
/****************************************************************************
7778
* Private Functions
@@ -89,6 +90,13 @@ static uint8_t g_region;
8990
* l2size has the same properties as the return value from
9091
* mpu_log2regionceil()
9192
*
93+
* Input Parameters:
94+
* size: The size of the region.
95+
* l2size: The L2 size of the region.
96+
*
97+
* Returned Value:
98+
* The sub-region bitmask.
99+
*
92100
****************************************************************************/
93101

94102
static inline uint32_t mpu_subregion_ms(size_t size, uint8_t l2size)
@@ -140,6 +148,13 @@ static inline uint32_t mpu_subregion_ms(size_t size, uint8_t l2size)
140148
* l2size has the same properties as the return value from
141149
* mpu_log2regionceil()
142150
*
151+
* Input Parameters:
152+
* offset: The offset of the region.
153+
* l2size: The L2 size of the region.
154+
*
155+
* Returned Value:
156+
* The sub-region bitmask.
157+
*
143158
****************************************************************************/
144159

145160
static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size)
@@ -184,6 +199,12 @@ static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size)
184199
* Description:
185200
* Resets the MPU to disabled.
186201
*
202+
* Input Parameters:
203+
* None.
204+
*
205+
* Returned Value:
206+
* None.
207+
*
187208
****************************************************************************/
188209

189210
#if defined(CONFIG_ARM_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET)
@@ -218,17 +239,51 @@ static void mpu_reset_internal()
218239
* Description:
219240
* Allocate the next region
220241
*
221-
* Assumptions:
222-
* - Regions are never deallocated
223-
* - Regions are only allocated early in initialization, so no special
224-
* protection against re-entrancy is required;
242+
* Input Parameters:
243+
* None
244+
*
245+
* Returned Value:
246+
* The index of the allocated region.
225247
*
226248
****************************************************************************/
227249

228250
unsigned int mpu_allocregion(void)
229251
{
230-
DEBUGASSERT(g_region < CONFIG_ARM_MPU_NREGIONS);
231-
return (unsigned int)g_region++;
252+
unsigned int i = ffs(~g_mpu_region) - 1;
253+
254+
/* There are not enough regions to apply */
255+
256+
DEBUGASSERT(i < CONFIG_ARM_MPU_NREGIONS);
257+
g_mpu_region |= 1 << i;
258+
return i;
259+
}
260+
261+
/****************************************************************************
262+
* Name: mpu_freeregion
263+
*
264+
* Description:
265+
* Free target region.
266+
*
267+
* Input Parameters:
268+
* region - The index of the region to be freed.
269+
*
270+
* Returned Value:
271+
* None
272+
*
273+
****************************************************************************/
274+
275+
void mpu_freeregion(unsigned int region)
276+
{
277+
DEBUGASSERT(region < CONFIG_ARM_MPU_NREGIONS);
278+
279+
/* Clear and disable the given MPU Region */
280+
281+
putreg32(region, MPU_RNR);
282+
putreg32(0, MPU_RASR);
283+
putreg32(0, MPU_RBAR);
284+
g_mpu_region &= ~(1 << region);
285+
ARM_DSB();
286+
ARM_ISB();
232287
}
233288

234289
/****************************************************************************
@@ -240,6 +295,12 @@ unsigned int mpu_allocregion(void)
240295
*
241296
* size <= (1 << l2size)
242297
*
298+
* Input Parameters:
299+
* size - The size of the region.
300+
*
301+
* Returned Value:
302+
* The logarithm base 2 of the ceiling value for the MPU region size.
303+
*
243304
****************************************************************************/
244305

245306
uint8_t mpu_log2regionceil(size_t size)
@@ -261,6 +322,12 @@ uint8_t mpu_log2regionceil(size_t size)
261322
*
262323
* size >= (1 << l2size)
263324
*
325+
* Input Parameters:
326+
* size - The size of the region.
327+
*
328+
* Returned Value:
329+
* The logarithm base 2 of the floor value for the MPU region size.
330+
*
264331
****************************************************************************/
265332

266333
uint8_t mpu_log2regionfloor(size_t size)
@@ -287,6 +354,14 @@ uint8_t mpu_log2regionfloor(size_t size)
287354
* l2size has the same properties as the return value from
288355
* mpu_log2regionceil()
289356
*
357+
* Input Parameters:
358+
* base - The base address of the region.
359+
* size - The size of the region.
360+
* l2size - Log2 of the actual region size is <= (1 << l2size).
361+
*
362+
* Returned Value:
363+
* The subregion settings as a 32-bit value.
364+
*
290365
****************************************************************************/
291366

292367
uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size)
@@ -338,6 +413,16 @@ uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size)
338413
* Description:
339414
* Configure and enable (or disable) the MPU
340415
*
416+
* Input Parameters:
417+
* enable - Flag indicating whether to enable the MPU.
418+
* hfnmiena - Flag indicating whether to enable the MPU during hard
419+
* fult, NMI, and FAULTMAS.
420+
* privdefena - Flag indicating whether to enable privileged access to
421+
* the default memory map.
422+
*
423+
* Returned Value:
424+
* None.
425+
*
341426
****************************************************************************/
342427

343428
void mpu_control(bool enable, bool hfnmiena, bool privdefena)
@@ -368,22 +453,34 @@ void mpu_control(bool enable, bool hfnmiena, bool privdefena)
368453
}
369454

370455
/****************************************************************************
371-
* Name: mpu_configure_region
456+
* Name: mpu_modify_region
372457
*
373458
* Description:
374-
* Configure a region for privileged, strongly ordered memory
459+
* Modify a region for privileged, strongly ordered memory
460+
*
461+
* Input Parameters:
462+
* region - Region number to modify.
463+
* base - Base address of the region.
464+
* size - Size of the region.
465+
* flags - Flags to configure the region.
466+
*
467+
* Returned Value:
468+
* None.
375469
*
376470
****************************************************************************/
377471

378-
void mpu_configure_region(uintptr_t base, size_t size,
379-
uint32_t flags)
472+
void mpu_modify_region(unsigned int region, uintptr_t base, size_t size,
473+
uint32_t flags)
380474
{
381-
unsigned int region = mpu_allocregion();
382475
uint32_t regval;
383476
uint8_t l2size;
384477
uint8_t subregions;
385478
uintptr_t alignedbase;
386479

480+
/* Check that the region is valid */
481+
482+
DEBUGASSERT(g_mpu_region & (1 << region));
483+
387484
/* Ensure the base address alignment
388485
*
389486
* ARMv7-M Architecture Reference Manual
@@ -429,13 +526,124 @@ void mpu_configure_region(uintptr_t base, size_t size,
429526
ARM_ISB();
430527
}
431528

529+
/****************************************************************************
530+
* Name: mpu_configure_region
531+
*
532+
* Description:
533+
* Configure a region for privileged, strongly ordered memory
534+
*
535+
* Input Parameters:
536+
* base - Base address of the region.
537+
* size - Size of the region.
538+
* flags - Flags to configure the region.
539+
*
540+
* Returned Value:
541+
* The region number allocated for the configured region.
542+
*
543+
****************************************************************************/
544+
545+
unsigned int mpu_configure_region(uintptr_t base, size_t size,
546+
uint32_t flags)
547+
{
548+
unsigned int region = mpu_allocregion();
549+
mpu_modify_region(region, base, size, flags);
550+
return region;
551+
}
552+
553+
/****************************************************************************
554+
* Name: mpu_initialize
555+
*
556+
* Description:
557+
* Configure a region for privileged, strongly ordered memory
558+
*
559+
* Input Parameters:
560+
* table - MPU initialization table.
561+
* hfnmiena - A boolean indicating whether the MPU should enable the
562+
* HFNMIENA bit.
563+
* privdefena - A boolean indicating whether the MPU should enable the
564+
* PRIVDEFENA bit.
565+
*
566+
* Returned Value:
567+
* NULL.
568+
*
569+
****************************************************************************/
570+
571+
void mpu_initialize(const struct mpu_region_s *table, bool hfnmiena,
572+
bool privdefena)
573+
{
574+
const struct mpu_region_s *conf;
575+
int index;
576+
577+
mpu_control(false, false, false);
578+
for (index = 0; index < nitems(table); index++)
579+
{
580+
conf = &table[index];
581+
mpu_configure_region(conf->base, conf->size, conf->flags);
582+
}
583+
584+
mpu_control(true, hfnmiena, privdefena);
585+
}
586+
587+
/****************************************************************************
588+
* Name: mpu_dump_region
589+
*
590+
* Description:
591+
* Dump the region that has been used.
592+
*
593+
* Input Parameters:
594+
* None.
595+
*
596+
* Returned Value:
597+
* None.
598+
*
599+
****************************************************************************/
600+
601+
void mpu_dump_region(void)
602+
{
603+
int i;
604+
int count = 0;
605+
uint32_t rasr;
606+
uint32_t rbar;
607+
uint32_t ctrl;
608+
609+
/* Get free region */
610+
611+
ctrl = getreg32(MPU_CTRL);
612+
_info("MPU-CTRL Enable:%" PRIu32 ", HFNMIENA:%"PRIu32","
613+
"PRIVDEFENA:%" PRIu32 "\n", ctrl & MPU_CTRL_ENABLE,
614+
ctrl & MPU_CTRL_HFNMIENA, ctrl & MPU_CTRL_PRIVDEFENA);
615+
for (i = 0; i < CONFIG_ARM_MPU_NREGIONS; i++)
616+
{
617+
putreg32(i, MPU_RNR);
618+
rasr = getreg32(MPU_RASR);
619+
rbar = getreg32(MPU_RBAR);
620+
_info("MPU-%d, alignedbase=0%08X l2size=%"PRIu32" SRD=%X"
621+
"AP=%X XN=%u\n", i, rbar & MPU_RBAR_ADDR_MASK,
622+
rasr & MPU_RASR_SIZE_MASK, rasr & MPU_RASR_SRD_MASK,
623+
rasr & MPU_RASR_AP_MASK, rasr & MPU_RASR_XN);
624+
if (rasr & MPU_RASR_ENABLE)
625+
{
626+
count++;
627+
}
628+
}
629+
630+
_info("Total Use Region:%d, Remaining Available:%d\n", count,
631+
CONFIG_ARM_MPU_NREGIONS - count);
632+
}
633+
432634
/****************************************************************************
433635
* Name: mpu_reset
434636
*
435637
* Description:
436638
* Conditional public interface that resets the MPU to disabled during
437639
* MPU initialization.
438640
*
641+
* Input Parameters:
642+
* None.
643+
*
644+
* Returned Value:
645+
* None.
646+
*
439647
****************************************************************************/
440648
#if defined(CONFIG_ARM_MPU_RESET)
441649
void mpu_reset()
@@ -451,6 +659,12 @@ void mpu_reset()
451659
* Conditional public interface that resets the MPU to disabled immediately
452660
* after reset.
453661
*
662+
* Input Parameters:
663+
* None.
664+
*
665+
* Returned Value:
666+
* None.
667+
*
454668
****************************************************************************/
455669
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
456670
void mpu_early_reset()

0 commit comments

Comments
 (0)