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 <chenrun1@xiaomi.com>
This commit is contained in:
chenrun1 2024-05-17 18:00:35 +08:00 committed by Xiang Xiao
parent 054c564a2d
commit 3a6a23d157
2 changed files with 244 additions and 72 deletions

View File

@ -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)

View File

@ -23,6 +23,7 @@
****************************************************************************/
#include <nuttx/config.h>
#include <debug.h>
#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 */