From 3a6a23d157e8c1823e79188a526328af88cc3e56 Mon Sep 17 00:00:00 2001 From: chenrun1 Date: Fri, 17 May 2024 18:00:35 +0800 Subject: [PATCH] xtensa_mpu:Modify the specified Region attributes Due to the xtensa mpu feature, the size of the Region depends on the Base of the next Region. e.g. Region[1] = 0x20000000 Region[0] = 0x30000000 Then Region[1] length = Region[0] - Region[1] So this approach is not suitable to implement the behavior of cleaning up the Region and such a configuration will result in affecting the very beginning (the higher) Region Therefore, to address this feature, in this change we return the Region value and implement the ability to modify the target Region's attributes Signed-off-by: chenrun1 --- arch/xtensa/src/common/mpu.h | 195 ++++++++++++++++++---------- arch/xtensa/src/common/xtensa_mpu.c | 121 ++++++++++++++++- 2 files changed, 244 insertions(+), 72 deletions(-) diff --git a/arch/xtensa/src/common/mpu.h b/arch/xtensa/src/common/mpu.h index 606568374a..9d692806d2 100644 --- a/arch/xtensa/src/common/mpu.h +++ b/arch/xtensa/src/common/mpu.h @@ -50,6 +50,14 @@ (((ENCODE_MEMORY_TYPE(memtype)) << (12)) | \ (((access) & (0xf)) << (8))) +struct mpu_region_s +{ + uintptr_t base; /* Region Base Address */ + size_t size; /* Unused */ + uint32_t acc; /* Access permissions */ + uint32_t memtype; /* memory type */ +}; + /**************************************************************************** * MPU access rights constants ****************************************************************************/ @@ -185,7 +193,18 @@ extern "C" * Name: mpu_allocregion * * Description: - * Allocate the next region + * Allocate the next region + * + * Assumptions: + * - Regions are never deallocated + * - Regions are only allocated early in initialization, so no special + * protection against re-entrancy is required; + * + * Input Parameters: + * None. + * + * Returned Value: + * The index of the allocated region. * ****************************************************************************/ @@ -197,20 +216,91 @@ unsigned int mpu_allocregion(void); * Description: * Configure and enable (or disable) the MPU * + * Input Parameters: + * enable - Flag indicating whether to enable the MPU. + * + * Returned Value: + * None. + * ****************************************************************************/ void mpu_control(bool enable); +/**************************************************************************** + * Name: mpu_modify_region + * + * Description: + * Modify a region for privileged, strongly ordered memory + * + * Input Parameters: + * region - Region number to modify. + * base - Base address of the region. + * size - Unused. + * acc - A uint32_t value representing the access permissions of + * the region. + * memtype - A uint32_t value representing the memory type of the region. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void mpu_modify_region(unsigned int region, uintptr_t base, size_t size, + uint32_t acc, uint32_t memtype); + /**************************************************************************** * Name: mpu_configure_region * * Description: + * Configure a region + * + * Input Parameters: + * base - Base address of the region. + * size - Unused. + * acc - A uint32_t value representing the access permissions of + * the region. + * memtype - A uint32_t value representing the memory type of the region. + * + * Returned Value: + * The region number allocated for the configured region. + * + ****************************************************************************/ + +unsigned int mpu_configure_region(uintptr_t base, size_t size, + uint32_t acc, uint32_t memtype); + +/**************************************************************************** + * Name: mpu_initialize + * + * Description: * Configure a region for privileged, strongly ordered memory * + * Input Parameters: + * table - MPU initialization table. + * count - Initialize the number of entries in the region table. + * + * Returned Value: + * NULL. + * ****************************************************************************/ -void mpu_configure_region(uintptr_t base, size_t size, - uint32_t acc, uint32_t memtype); +void mpu_initialize(const struct mpu_region_s *table, size_t count); + +/**************************************************************************** + * Name: mpu_dump_region + * + * Description: + * Dump the region that has been used. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void mpu_dump_region(void); /**************************************************************************** * Name: mpu_priv_stronglyordered @@ -221,13 +311,10 @@ void mpu_configure_region(uintptr_t base, size_t size, ****************************************************************************/ #define mpu_priv_stronglyordered(base, size) \ - do \ - { \ - /* The configure the region */ \ - mpu_configure_region(base, size, \ - MPU_AR_RWX, \ - MPU_MEM_DEVICE); \ - } while (0) + /* The configure the region */ \ + mpu_configure_region(base, size, \ + MPU_AR_RWX, \ + MPU_MEM_DEVICE) /**************************************************************************** * Name: mpu_user_flash @@ -238,13 +325,10 @@ void mpu_configure_region(uintptr_t base, size_t size, ****************************************************************************/ #define mpu_user_flash(base, size) \ - do \ - { \ - /* The configure the region */ \ - mpu_configure_region(base, size, \ - MPU_AR_RXrx, \ - MPU_MEM_WRITEBACK);\ - } while (0) + /* The configure the region */ \ + mpu_configure_region(base, size, \ + MPU_AR_RXrx, \ + MPU_MEM_WRITEBACK) /**************************************************************************** * Name: mpu_priv_flash @@ -255,13 +339,10 @@ void mpu_configure_region(uintptr_t base, size_t size, ****************************************************************************/ #define mpu_priv_flash(base, size) \ - do \ - { \ - /* The configure the region */ \ - mpu_configure_region(base, size, \ - MPU_AR_RX, \ - MPU_MEM_WRITEBACK);\ - } while (0) + /* The configure the region */ \ + mpu_configure_region(base, size, \ + MPU_AR_RX, \ + MPU_MEM_WRITEBACK) /**************************************************************************** * Name: mpu_user_intsram @@ -272,13 +353,10 @@ void mpu_configure_region(uintptr_t base, size_t size, ****************************************************************************/ #define mpu_user_intsram(base, size) \ - do \ - { \ - /* The configure the region */ \ - mpu_configure_region(base, size, \ - MPU_AR_RWXrwx, \ - MPU_MEM_WRITEBACK);\ - } while (0) + /* The configure the region */ \ + mpu_configure_region(base, size, \ + MPU_AR_RWXrwx, \ + MPU_MEM_WRITEBACK) /**************************************************************************** * Name: mpu_priv_intsram @@ -289,13 +367,10 @@ void mpu_configure_region(uintptr_t base, size_t size, ****************************************************************************/ #define mpu_priv_intsram(base, size) \ - do \ - { \ - /* The configure the region */ \ - mpu_configure_region(base, size,\ - MPU_AR_RWX, \ - MPU_MEM_WRITEBACK);\ - } while (0) + /* The configure the region */ \ + mpu_configure_region(base, size,\ + MPU_AR_RWX, \ + MPU_MEM_WRITEBACK) /**************************************************************************** * Name: mpu_user_extsram @@ -306,13 +381,10 @@ void mpu_configure_region(uintptr_t base, size_t size, ****************************************************************************/ #define mpu_user_extsram(base, size) \ - do \ - { \ - /* The configure the region */ \ - mpu_configure_region(base, size, \ - MPU_AR_RWXrwx, \ - MPU_MEM_WRITEBACK);\ - } while (0) + /* The configure the region */ \ + mpu_configure_region(base, size, \ + MPU_AR_RWXrwx, \ + MPU_MEM_WRITEBACK) /**************************************************************************** * Name: mpu_priv_extsram @@ -323,13 +395,10 @@ void mpu_configure_region(uintptr_t base, size_t size, ****************************************************************************/ #define mpu_priv_extsram(base, size) \ - do \ - { \ - /* The configure the region */ \ - mpu_configure_region(base, size, \ - MPU_AR_RWX, \ - MPU_MEM_WRITEBACK);\ - } while (0) + /* The configure the region */ \ + mpu_configure_region(base, size, \ + MPU_AR_RWX, \ + MPU_MEM_WRITEBACK) /**************************************************************************** * Name: mpu_peripheral @@ -340,13 +409,10 @@ void mpu_configure_region(uintptr_t base, size_t size, ****************************************************************************/ #define mpu_peripheral(base, size) \ - do \ - { \ - /* Then configure the region */ \ - mpu_configure_region(base, size, \ - MPU_AR_RW, \ - MPU_MEM_DEVICE);\ - } while (0) + /* Then configure the region */ \ + mpu_configure_region(base, size, \ + MPU_AR_RW, \ + MPU_MEM_DEVICE) /**************************************************************************** * Name: mpu_user_peripheral @@ -357,13 +423,10 @@ void mpu_configure_region(uintptr_t base, size_t size, ****************************************************************************/ #define mpu_user_peripheral(base, size) \ - do \ - { \ - /* Then configure the region */ \ - mpu_configure_region(base, size, \ - MPU_AR_RWrw, \ - MPU_MEM_DEVICE);\ - } while (0) + /* Then configure the region */ \ + mpu_configure_region(base, size, \ + MPU_AR_RWrw, \ + MPU_MEM_DEVICE) #undef EXTERN #if defined(__cplusplus) diff --git a/arch/xtensa/src/common/xtensa_mpu.c b/arch/xtensa/src/common/xtensa_mpu.c index 338dce8642..2905d2ad51 100644 --- a/arch/xtensa/src/common/xtensa_mpu.c +++ b/arch/xtensa/src/common/xtensa_mpu.c @@ -23,6 +23,7 @@ ****************************************************************************/ #include +#include #include "mpu.h" @@ -55,6 +56,12 @@ static uint8_t g_region = XCHAL_MPU_ENTRIES; * - Regions are only allocated early in initialization, so no special * protection against re-entrancy is required; * + * Input Parameters: + * None. + * + * Returned Value: + * The index of the allocated region. + * ****************************************************************************/ unsigned int mpu_allocregion(void) @@ -69,6 +76,12 @@ unsigned int mpu_allocregion(void) * Description: * Configure and enable (or disable) the MPU * + * Input Parameters: + * enable - Flag indicating whether to enable the MPU. + * + * Returned Value: + * None. + * ****************************************************************************/ void mpu_control(bool enable) @@ -88,17 +101,27 @@ void mpu_control(bool enable) } /**************************************************************************** - * Name: mpu_configure_region + * Name: mpu_modify_region * * Description: - * Configure a region + * Modify a region for privileged, strongly ordered memory + * + * Input Parameters: + * region - Region number to modify. + * base - Base address of the region. + * size - Unused. + * acc - A uint32_t value representing the access permissions of + * the region. + * memtype - A uint32_t value representing the memory type of the region. + * + * Returned Value: + * None. * ****************************************************************************/ -void mpu_configure_region(uintptr_t base, size_t size, - uint32_t acc, uint32_t memtype) +void mpu_modify_region(unsigned int region, uintptr_t base, size_t size, + uint32_t acc, uint32_t memtype) { - unsigned int region = mpu_allocregion(); uint32_t at; uint32_t as; @@ -124,7 +147,7 @@ void mpu_configure_region(uintptr_t base, size_t size, at |= region; - /* update mpu entry .. requires an memw on same cache line */ + /* Update mpu entry .. requires an memw on same cache line */ __asm__ __volatile__ ( @@ -136,7 +159,93 @@ void mpu_configure_region(uintptr_t base, size_t size, : "a" (at), "a"(as) ); + /* Save base information for check overlap */ + xtensa_mpu_base[region] = base; } +/**************************************************************************** + * Name: mpu_configure_region + * + * Description: + * Configure a region + * + * Input Parameters: + * base - Base address of the region. + * size - Unused. + * acc - A uint32_t value representing the access permissions of + * the region. + * memtype - A uint32_t value representing the memory type of the region. + * + * Returned Value: + * The region number allocated for the configured region. + * + ****************************************************************************/ + +unsigned int mpu_configure_region(uintptr_t base, size_t size, + uint32_t acc, uint32_t memtype) +{ + unsigned int region = mpu_allocregion(); + mpu_modify_region(region, base, size, acc, memtype); + return region; +} + +/**************************************************************************** + * Name: mpu_initialize + * + * Description: + * Configure a region for privileged, strongly ordered memory + * + * Input Parameters: + * table - MPU initialization table. + * count - Initialize the number of entries in the region table. + * + * Returned Value: + * NULL. + * + ****************************************************************************/ + +void mpu_initialize(const struct mpu_region_s *table, size_t count) +{ + const struct mpu_region_s *conf; + size_t index; + + mpu_control(false); + for (index = 0; index < count; index++) + { + conf = &table[index]; + mpu_configure_region(conf->base, conf->size, conf->acc, conf->memtype); + } + + mpu_control(true); +} + +/**************************************************************************** + * Name: mpu_dump_region + * + * Description: + * Dump the region that has been used. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void mpu_dump_region(void) +{ + int i; + + for (i = XCHAL_MPU_ENTRIES - 1; i >= g_region; i--) + { + _info("MPU-Index(%d) Enable, Base:%" PRIu32 "\n", i, + xtensa_mpu_base[i]); + } + + _info("Total Use Region:%d, Remaining Available:%d\n", + XCHAL_MPU_ENTRIES - g_region, g_region); +} + #endif /* defined(XCHAL_MPU_ENTRIES) && XCHAL_MPU_ENTRIES > 0 */