armv7-m,armv7-r,armv8-m:MPU Add mpu_reset and ARM_MPU_EARLY_RESET

When NuttX is booted from a foreign (non NuttX)
   bootloader. There as a possibility that the
   bootloader configured the MPU, in an
   incompatible way for the NuttX memory usage.

   The option to reset the MPU before it is initialized
   may not succeed if the bss and data initialization
   code violated the previous MPU configurations.

   Added herein are ARM_MPU_RESET and
   ARM_MPU_EARLY_RESET. The former can be used
   If the system is capable of booting and running
   NuttX MPU configuration code without an MPU
   violation. The latter is used if the system can
   not run the bss and data initialization code.

   These are options so that a NuttX may be configured to
   not clobber a bootloader MPU configuration in a system
   that is architected to share the MPU configuration task.
This commit is contained in:
David Sidrane 2021-09-22 10:28:35 -07:00 committed by Xiang Xiao
parent cf1a04d0a2
commit 9d8f7126f6
7 changed files with 289 additions and 0 deletions

View File

@ -879,6 +879,34 @@ config ARM_MPU_NREGIONS
---help---
This is the number of protection regions supported by the MPU.
config ARM_MPU_RESET
bool "MPU Reset before MPU initialization"
default n
depends on ARM_MPU
---help---
Configures the MPU initialization sequence to disable the MPU
before configuring it.
This may be needed in a system with a bootloader that has
configured the MPU prior to running NuttX. This may be all that is
needed to allow booting if the previous MPU configuration allow
the system to execute the MPU initialization code. If not use
ARM_MPU_EARLY_RESET.
config ARM_MPU_EARLY_RESET
bool "MPU Early Reset"
default n
depends on ARCH_HAVE_MPU
---help---
Configures the early system initialization sequence to disable the MPU.
This may be needed in a system with a bootloader that has
configured the MPU prior to running NuttX. This is useful if the system
faults during bbs, or data initialization or before the
stm32_mpuinitialize can be called.
Note: This can be used without MPU Support enabled.
config ARCH_HAVE_LOWVECTORS
bool

View File

@ -177,6 +177,33 @@ static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size)
return g_ls_regionmask[nsrs];
}
/****************************************************************************
* Name: mpu_reset_internal
*
* Description:
* Resets the MPU to disabled.
*
****************************************************************************/
#if defined(CONFIG_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET)
static void mpu_reset_internal()
{
int region;
int regions;
regions = (getreg32(MPU_TYPE) & MPU_TYPE_DREGION_MASK)
>> MPU_TYPE_DREGION_SHIFT;
for (region = 0; region < regions; region++)
{
putreg32(region, MPU_RNR);
putreg32(0, MPU_RASR);
putreg32(0, MPU_RBAR);
}
putreg32(0, MPU_CTRL);
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -387,3 +414,33 @@ void mpu_configure_region(uintptr_t base, size_t size,
flags;
putreg32(regval, MPU_RASR);
}
/****************************************************************************
* Name: mpu_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled during
* MPU initialization.
*
****************************************************************************/
#if defined(CONFIG_MPU_RESET)
void mpu_reset()
{
mpu_reset_internal();
}
#endif
/****************************************************************************
* Name: mpu_early_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled immediately
* after reset.
*
****************************************************************************/
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
void mpu_early_reset()
{
mpu_reset_internal();
}
#endif

View File

@ -132,6 +132,36 @@
# define MPU_RASR_AP_RORO (6 << MPU_RASR_AP_SHIFT) /* P:RO U:RO */
# define MPU_RASR_XN (1 << 28) /* Bit 28: Instruction access disable */
/****************************************************************************
* Name: mpu_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled during
* MPU initialization.
*
****************************************************************************/
#if defined(CONFIG_MPU_RESET)
void mpu_reset(void);
#else
# define mpu_reset() do { } while (0)
#endif
/****************************************************************************
* Name: mpu_early_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled immediately
* after reset.
*
****************************************************************************/
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
void mpu_early_reset(void);
#else
# define mpu_early_reset() do { } while (0)
#endif
#ifdef CONFIG_ARM_MPU
/****************************************************************************

View File

@ -177,6 +177,33 @@ static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size)
return g_ls_regionmask[nsrs];
}
/****************************************************************************
* Name: mpu_reset_internal
*
* Description:
* Resets the MPU to disabled.
*
****************************************************************************/
#if defined(CONFIG_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET)
static void mpu_reset_internal()
{
int region;
int regions;
regions = (getreg32(MPU_TYPE) & MPU_TYPE_DREGION_MASK)
>> MPU_TYPE_DREGION_SHIFT;
for (region = 0; region < regions; region++)
{
putreg32(region, MPU_RNR);
putreg32(0, MPU_RASR);
putreg32(0, MPU_RBAR);
}
putreg32(0, MPU_CTRL);
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -300,3 +327,33 @@ uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size)
ret |= mpu_subregion_ls(offset, l2size);
return ret;
}
/****************************************************************************
* Name: mpu_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled during
* MPU initialization.
*
****************************************************************************/
#if defined(CONFIG_MPU_RESET)
void mpu_reset()
{
mpu_reset_internal();
}
#endif
/****************************************************************************
* Name: mpu_early_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled immediately
* after reset.
*
****************************************************************************/
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
void mpu_early_reset()
{
mpu_reset_internal();
}
#endif

View File

@ -120,6 +120,36 @@ extern "C"
#define EXTERN extern
#endif
/****************************************************************************
* Name: mpu_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled during
* MPU initialization.
*
****************************************************************************/
#if defined(CONFIG_MPU_RESET)
void mpu_reset(void);
#else
# define mpu_reset() do { } while (0)
#endif
/****************************************************************************
* Name: mpu_early_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled immediately
* after reset.
*
****************************************************************************/
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
void mpu_early_reset(void);
#else
# define mpu_early_reset() do { } while (0)
#endif
/****************************************************************************
* Name: mpu_allocregion
*

View File

@ -71,6 +71,33 @@ unsigned int mpu_allocregion(void)
return (unsigned int)g_region++;
}
/****************************************************************************
* Name: mpu_reset_internal
*
* Description:
* Resets the MPU to disabled.
*
****************************************************************************/
#if defined(CONFIG_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET)
static void mpu_reset_internal()
{
int region;
int regions;
regions = (getreg32(MPU_TYPE) & MPU_TYPE_DREGION_MASK)
>> MPU_TYPE_DREGION_SHIFT;
for (region = 0; region < regions; region++)
{
putreg32(region, MPU_RNR);
putreg32(0, MPU_RASR);
putreg32(0, MPU_RBAR);
}
putreg32(0, MPU_CTRL);
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -148,3 +175,33 @@ void mpu_configure_region(uintptr_t base, size_t size,
putreg32(base | flags1, MPU_RBAR);
putreg32(limit | flags2 | MPU_RLAR_ENABLE, MPU_RLAR);
}
/****************************************************************************
* Name: mpu_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled during
* MPU initialization.
*
****************************************************************************/
#if defined(CONFIG_MPU_RESET)
void mpu_reset()
{
mpu_reset_internal();
}
#endif
/****************************************************************************
* Name: mpu_early_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled immediately
* after reset.
*
****************************************************************************/
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
void mpu_early_reset()
{
mpu_reset_internal();
}
#endif

View File

@ -171,6 +171,36 @@
MPU_MAIR_INNER_NT | MPU_MAIR_INNER_WB | \
MPU_MAIR_INNER_RA | MPU_MAIR_INNER_WA)
/****************************************************************************
* Name: mpu_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled during
* MPU initialization.
*
****************************************************************************/
#if defined(CONFIG_MPU_RESET)
void mpu_reset(void);
#else
# define mpu_reset() do { } while (0)
#endif
/****************************************************************************
* Name: mpu_early_reset
*
* Description:
* Conditional public interface that resets the MPU to disabled immediately
* after reset.
*
****************************************************************************/
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
void mpu_early_reset(void);
#else
# define mpu_early_reset() do { } while (0)
#endif
#ifdef CONFIG_ARM_MPU
/****************************************************************************