arm: de-couple MPU code from k_mem_partition
k_mem_partition is part of the CONFIG_USERSPACE abstraction, but some older MPU code was depending on it even if user mode isn't enabled. Use a new structure z_arm_mpu_partition instead, which will insulate this code from any changes to the core kernel definition of k_mem_partition. The logic in z_arm_configure_dynamic_mpu_regions has been adjusted to copy the necessary information out of the memory domain instead of passing the addresses of the domain structures directly to the lower-level MPU code. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
35264cc214
commit
00cdb597ff
7 changed files with 184 additions and 186 deletions
|
@ -50,6 +50,50 @@ LOG_MODULE_REGISTER(mpu);
|
|||
extern K_THREAD_STACK_DEFINE(z_main_stack, CONFIG_MAIN_STACK_SIZE);
|
||||
#endif
|
||||
|
||||
static const struct z_arm_mpu_partition static_regions[] = {
|
||||
#if defined(CONFIG_COVERAGE_GCOV) && defined(CONFIG_USERSPACE)
|
||||
{
|
||||
/* GCOV code coverage accounting area. Needs User permissions
|
||||
* to function
|
||||
*/
|
||||
.start = (uint32_t)&__gcov_bss_start,
|
||||
.size = (uint32_t)&__gcov_bss_size,
|
||||
.attr = K_MEM_PARTITION_P_RW_U_RW,
|
||||
},
|
||||
#endif /* CONFIG_COVERAGE_GCOV && CONFIG_USERSPACE */
|
||||
#if defined(CONFIG_NOCACHE_MEMORY)
|
||||
{
|
||||
/* Special non-cacheable RAM area */
|
||||
.start = (uint32_t)&_nocache_ram_start,
|
||||
.size = (uint32_t)&_nocache_ram_size,
|
||||
.attr = K_MEM_PARTITION_P_RW_U_NA_NOCACHE,
|
||||
},
|
||||
#endif /* CONFIG_NOCACHE_MEMORY */
|
||||
#if defined(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT)
|
||||
{
|
||||
/* Special RAM area for program text */
|
||||
.start = (uint32_t)&_ramfunc_ram_start,
|
||||
.size = (uint32_t)&_ramfunc_ram_size,
|
||||
.attr = K_MEM_PARTITION_P_RX_U_RX,
|
||||
},
|
||||
#endif /* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT */
|
||||
#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_MPU_STACK_GUARD)
|
||||
/* Main stack MPU guard to detect overflow.
|
||||
* Note:
|
||||
* FPU_SHARING and USERSPACE are not supported features
|
||||
* under CONFIG_MULTITHREADING=n, so the MPU guard (if
|
||||
* exists) is reserved aside of CONFIG_MAIN_STACK_SIZE
|
||||
* and there is no requirement for larger guard area (FP
|
||||
* context is not stacked).
|
||||
*/
|
||||
{
|
||||
.start = (uint32_t)z_main_stack,
|
||||
.size = (uint32_t)MPU_GUARD_ALIGN_AND_SIZE,
|
||||
.attr = K_MEM_PARTITION_P_RO_U_NA,
|
||||
},
|
||||
#endif /* !CONFIG_MULTITHREADING && CONFIG_MPU_STACK_GUARD */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Use the HW-specific MPU driver to program
|
||||
* the static MPU regions.
|
||||
|
@ -65,65 +109,6 @@ extern K_THREAD_STACK_DEFINE(z_main_stack, CONFIG_MAIN_STACK_SIZE);
|
|||
*/
|
||||
void z_arm_configure_static_mpu_regions(void)
|
||||
{
|
||||
#if defined(CONFIG_COVERAGE_GCOV) && defined(CONFIG_USERSPACE)
|
||||
const struct k_mem_partition gcov_region =
|
||||
{
|
||||
.start = (uint32_t)&__gcov_bss_start,
|
||||
.size = (uint32_t)&__gcov_bss_size,
|
||||
.attr = K_MEM_PARTITION_P_RW_U_RW,
|
||||
};
|
||||
#endif /* CONFIG_COVERAGE_GCOV && CONFIG_USERSPACE */
|
||||
#if defined(CONFIG_NOCACHE_MEMORY)
|
||||
const struct k_mem_partition nocache_region =
|
||||
{
|
||||
.start = (uint32_t)&_nocache_ram_start,
|
||||
.size = (uint32_t)&_nocache_ram_size,
|
||||
.attr = K_MEM_PARTITION_P_RW_U_NA_NOCACHE,
|
||||
};
|
||||
#endif /* CONFIG_NOCACHE_MEMORY */
|
||||
#if defined(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT)
|
||||
const struct k_mem_partition ramfunc_region =
|
||||
{
|
||||
.start = (uint32_t)&_ramfunc_ram_start,
|
||||
.size = (uint32_t)&_ramfunc_ram_size,
|
||||
.attr = K_MEM_PARTITION_P_RX_U_RX,
|
||||
};
|
||||
#endif /* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT */
|
||||
|
||||
#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_MPU_STACK_GUARD)
|
||||
/* Main stack MPU guard to detect overflow.
|
||||
* Note:
|
||||
* FPU_SHARING and USERSPACE are not supported features
|
||||
* under CONFIG_MULTITHREADING=n, so the MPU guard (if
|
||||
* exists) is reserved aside of CONFIG_MAIN_STACK_SIZE
|
||||
* and there is no requirement for larger guard area (FP
|
||||
* context is not stacked).
|
||||
*/
|
||||
const struct k_mem_partition main_stack_guard_region = {
|
||||
.start = (uint32_t)z_main_stack,
|
||||
.size = (uint32_t)MPU_GUARD_ALIGN_AND_SIZE,
|
||||
.attr = K_MEM_PARTITION_P_RO_U_NA,
|
||||
};
|
||||
#endif /* !CONFIG_MULTITHREADING && CONFIG_MPU_STACK_GUARD */
|
||||
/* Define a constant array of k_mem_partition objects
|
||||
* to hold the configuration of the respective static
|
||||
* MPU regions.
|
||||
*/
|
||||
const struct k_mem_partition *static_regions[] = {
|
||||
#if defined(CONFIG_COVERAGE_GCOV) && defined(CONFIG_USERSPACE)
|
||||
&gcov_region,
|
||||
#endif /* CONFIG_COVERAGE_GCOV && CONFIG_USERSPACE */
|
||||
#if defined(CONFIG_NOCACHE_MEMORY)
|
||||
&nocache_region,
|
||||
#endif /* CONFIG_NOCACHE_MEMORY */
|
||||
#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_MPU_STACK_GUARD)
|
||||
&main_stack_guard_region,
|
||||
#endif /* !CONFIG_MULTITHREADING && CONFIG_MPU_STACK_GUARD */
|
||||
#if defined(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT)
|
||||
&ramfunc_region
|
||||
#endif /* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT */
|
||||
};
|
||||
|
||||
/* Configure the static MPU regions within firmware SRAM boundaries.
|
||||
* Start address of the image is given by _image_ram_start. The end
|
||||
* of the firmware SRAM area is marked by __kernel_ram_end, taking
|
||||
|
@ -136,12 +121,12 @@ void z_arm_configure_static_mpu_regions(void)
|
|||
|
||||
#if defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS) && \
|
||||
defined(CONFIG_MULTITHREADING)
|
||||
/* Define a constant array of k_mem_partition objects that holds the
|
||||
/* Define a constant array of z_arm_mpu_partition objects that holds the
|
||||
* boundaries of the areas, inside which dynamic region programming
|
||||
* is allowed. The information is passed to the underlying driver at
|
||||
* initialization.
|
||||
*/
|
||||
const struct k_mem_partition dyn_region_areas[] = {
|
||||
const struct z_arm_mpu_partition dyn_region_areas[] = {
|
||||
{
|
||||
.start = _MPU_DYNAMIC_REGIONS_AREA_START,
|
||||
.size = _MPU_DYNAMIC_REGIONS_AREA_SIZE,
|
||||
|
@ -164,10 +149,13 @@ void z_arm_configure_static_mpu_regions(void)
|
|||
*
|
||||
* For some MPU architectures, such as the unmodified ARMv8-M MPU,
|
||||
* the function must execute with MPU enabled.
|
||||
*
|
||||
* This function is not inherently thread-safe, but the memory domain
|
||||
* spinlock needs to be held anyway.
|
||||
*/
|
||||
void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
|
||||
{
|
||||
/* Define an array of k_mem_partition objects to hold the configuration
|
||||
/* Define an array of z_arm_mpu_partition objects to hold the configuration
|
||||
* of the respective dynamic MPU regions to be programmed for
|
||||
* the given thread. The array of partitions (along with its
|
||||
* actual size) will be supplied to the underlying MPU driver.
|
||||
|
@ -187,13 +175,12 @@ void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
|
|||
* thread->stack_info.start. On a K_USER thread, the guard is defined
|
||||
* in front of the privilege mode stack, thread->arch.priv_stack_start.
|
||||
*/
|
||||
struct k_mem_partition *dynamic_regions[_MAX_DYNAMIC_MPU_REGIONS_NUM];
|
||||
static struct z_arm_mpu_partition
|
||||
dynamic_regions[_MAX_DYNAMIC_MPU_REGIONS_NUM];
|
||||
|
||||
uint8_t region_num = 0U;
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
struct k_mem_partition thread_stack;
|
||||
|
||||
/* Memory domain */
|
||||
LOG_DBG("configure thread %p's domain", thread);
|
||||
struct k_mem_domain *mem_domain = thread->mem_domain_info.mem_domain;
|
||||
|
@ -201,25 +188,27 @@ void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
|
|||
if (mem_domain) {
|
||||
LOG_DBG("configure domain: %p", mem_domain);
|
||||
uint32_t num_partitions = mem_domain->num_partitions;
|
||||
struct k_mem_partition partition;
|
||||
struct k_mem_partition *partition;
|
||||
int i;
|
||||
|
||||
LOG_DBG("configure domain: %p", mem_domain);
|
||||
|
||||
for (i = 0; i < CONFIG_MAX_DOMAIN_PARTITIONS; i++) {
|
||||
partition = mem_domain->partitions[i];
|
||||
if (partition.size == 0) {
|
||||
partition = &mem_domain->partitions[i];
|
||||
if (partition->size == 0) {
|
||||
/* Zero size indicates a non-existing
|
||||
* memory partition.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
LOG_DBG("set region 0x%lx 0x%x",
|
||||
partition.start, partition.size);
|
||||
partition->start, partition->size);
|
||||
__ASSERT(region_num < _MAX_DYNAMIC_MPU_REGIONS_NUM,
|
||||
"Out-of-bounds error for dynamic region map.");
|
||||
dynamic_regions[region_num] =
|
||||
&mem_domain->partitions[i];
|
||||
|
||||
dynamic_regions[region_num].start = partition->start;
|
||||
dynamic_regions[region_num].size = partition->size;
|
||||
dynamic_regions[region_num].attr = partition->attr;
|
||||
|
||||
region_num++;
|
||||
num_partitions--;
|
||||
|
@ -232,16 +221,16 @@ void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
|
|||
LOG_DBG("configure user thread %p's context", thread);
|
||||
if (thread->arch.priv_stack_start) {
|
||||
/* K_USER thread stack needs a region */
|
||||
uint32_t base = (uint32_t)thread->stack_obj;
|
||||
uint32_t size = thread->stack_info.size +
|
||||
uintptr_t base = (uintptr_t)thread->stack_obj;
|
||||
size_t size = thread->stack_info.size +
|
||||
(thread->stack_info.start - base);
|
||||
|
||||
__ASSERT(region_num < _MAX_DYNAMIC_MPU_REGIONS_NUM,
|
||||
"Out-of-bounds error for dynamic region map.");
|
||||
thread_stack = (const struct k_mem_partition)
|
||||
{base, size, K_MEM_PARTITION_P_RW_U_RW};
|
||||
|
||||
dynamic_regions[region_num] = &thread_stack;
|
||||
dynamic_regions[region_num].start = base;
|
||||
dynamic_regions[region_num].size = size;
|
||||
dynamic_regions[region_num].attr = K_MEM_PARTITION_P_RW_U_RW;
|
||||
|
||||
region_num++;
|
||||
}
|
||||
|
@ -252,11 +241,10 @@ void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
|
|||
* supervisor/privilege mode stack depending on the type of thread
|
||||
* being mapped.
|
||||
*/
|
||||
struct k_mem_partition guard;
|
||||
|
||||
/* Privileged stack guard */
|
||||
uint32_t guard_start;
|
||||
uint32_t guard_size = MPU_GUARD_ALIGN_AND_SIZE;
|
||||
uintptr_t guard_start;
|
||||
size_t guard_size = MPU_GUARD_ALIGN_AND_SIZE;
|
||||
|
||||
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
|
||||
if ((thread->base.user_options & K_FP_REGS) != 0) {
|
||||
|
@ -272,39 +260,36 @@ void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
|
|||
*/
|
||||
guard_start = thread->arch.priv_stack_start - guard_size;
|
||||
|
||||
__ASSERT((uint32_t)&z_priv_stacks_ram_start <= guard_start,
|
||||
"Guard start: (0x%x) below privilege stacks boundary: (0x%x)",
|
||||
guard_start, (uint32_t)&z_priv_stacks_ram_start);
|
||||
} else {
|
||||
__ASSERT((uintptr_t)&z_priv_stacks_ram_start <= guard_start,
|
||||
"Guard start: (0x%lx) below privilege stacks boundary: (%p)",
|
||||
guard_start, &z_priv_stacks_ram_start);
|
||||
} else
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
{
|
||||
/* A supervisor thread only has the normal thread stack to
|
||||
* protect with a stack guard.
|
||||
*/
|
||||
guard_start = thread->stack_info.start - guard_size;
|
||||
__ASSERT((uint32_t)thread->stack_obj == guard_start,
|
||||
"Guard start (0x%x) not beginning at stack object (0x%x)\n",
|
||||
guard_start, (uint32_t)thread->stack_obj);
|
||||
}
|
||||
#else
|
||||
guard_start = thread->stack_info.start - guard_size;
|
||||
#ifdef CONFIG_USERSPACE
|
||||
__ASSERT((uintptr_t)thread->stack_obj == guard_start,
|
||||
"Guard start (0x%lx) not beginning at stack object (%p)\n",
|
||||
guard_start, thread->stack_obj);
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
}
|
||||
|
||||
__ASSERT(region_num < _MAX_DYNAMIC_MPU_REGIONS_NUM,
|
||||
"Out-of-bounds error for dynamic region map.");
|
||||
guard = (const struct k_mem_partition)
|
||||
{
|
||||
guard_start,
|
||||
guard_size,
|
||||
K_MEM_PARTITION_P_RO_U_NA
|
||||
};
|
||||
dynamic_regions[region_num] = &guard;
|
||||
|
||||
dynamic_regions[region_num].start = guard_start;
|
||||
dynamic_regions[region_num].size = guard_size;
|
||||
dynamic_regions[region_num].attr = K_MEM_PARTITION_P_RO_U_NA;
|
||||
|
||||
region_num++;
|
||||
#endif /* CONFIG_MPU_STACK_GUARD */
|
||||
|
||||
/* Configure the dynamic MPU regions */
|
||||
arm_core_mpu_configure_dynamic_mpu_regions(
|
||||
(const struct k_mem_partition **)dynamic_regions,
|
||||
region_num);
|
||||
arm_core_mpu_configure_dynamic_mpu_regions(dynamic_regions,
|
||||
region_num);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
|
|
|
@ -7,14 +7,13 @@
|
|||
#define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_CORTEX_M_MPU_ARM_CORE_MPU_DEV_H_
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <kernel_arch_data.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARM_MPU)
|
||||
struct k_mem_domain;
|
||||
struct k_mem_partition;
|
||||
struct k_thread;
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
|
@ -133,8 +132,9 @@ struct k_thread;
|
|||
* requirements of the MPU hardware.
|
||||
*/
|
||||
void arm_core_mpu_configure_static_mpu_regions(
|
||||
const struct k_mem_partition *static_regions[], const uint8_t regions_num,
|
||||
const uint32_t background_area_start, const uint32_t background_area_end);
|
||||
const struct z_arm_mpu_partition static_regions[],
|
||||
const uint8_t regions_num, const uint32_t background_area_start,
|
||||
const uint32_t background_area_end);
|
||||
|
||||
#if defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS)
|
||||
|
||||
|
@ -153,7 +153,7 @@ void arm_core_mpu_configure_static_mpu_regions(
|
|||
*
|
||||
* The function shall be invoked once, upon system initialization.
|
||||
*
|
||||
* @param dyn_region_areas an array of k_mem_partition objects declaring the
|
||||
* @param dyn_region_areas an array of z_arm_mpu_partition objects declaring the
|
||||
* eligible memory areas for dynamic programming
|
||||
* @param dyn_region_areas_num the number of eligible areas for dynamic
|
||||
* programming.
|
||||
|
@ -164,7 +164,7 @@ void arm_core_mpu_configure_static_mpu_regions(
|
|||
* arm_core_mpu_configure_static_mpu_regions().
|
||||
*/
|
||||
void arm_core_mpu_mark_areas_for_dynamic_regions(
|
||||
const struct k_mem_partition dyn_region_areas[],
|
||||
const struct z_arm_mpu_partition dyn_region_areas[],
|
||||
const uint8_t dyn_region_areas_num);
|
||||
|
||||
#endif /* CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS */
|
||||
|
@ -185,7 +185,8 @@ void arm_core_mpu_mark_areas_for_dynamic_regions(
|
|||
* not exceed the number of (currently) available MPU indices.
|
||||
*/
|
||||
void arm_core_mpu_configure_dynamic_mpu_regions(
|
||||
const struct k_mem_partition *dynamic_regions[], uint8_t regions_num);
|
||||
const struct z_arm_mpu_partition dynamic_regions[],
|
||||
uint8_t regions_num);
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/**
|
||||
|
@ -203,7 +204,7 @@ void arm_core_mpu_configure_dynamic_mpu_regions(
|
|||
* successfully (e.g. the given partition can not be found).
|
||||
*/
|
||||
void arm_core_mpu_mem_partition_config_update(
|
||||
struct k_mem_partition *partition,
|
||||
struct z_arm_mpu_partition *partition,
|
||||
k_mem_partition_attr_t *new_attr);
|
||||
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
|
@ -238,7 +239,7 @@ void arm_core_mpu_configure_user_context(struct k_thread *thread);
|
|||
* @param part memory partition info
|
||||
*/
|
||||
void arm_core_mpu_configure_mem_partition(uint32_t part_index,
|
||||
struct k_mem_partition *part);
|
||||
struct z_arm_mpu_partition *part);
|
||||
|
||||
/**
|
||||
* @brief Reset MPU region for a single memory partition
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <soc.h>
|
||||
#include "arm_core_mpu_dev.h"
|
||||
#include <linker/linker-defs.h>
|
||||
#include <kernel_arch_data.h>
|
||||
|
||||
#define LOG_LEVEL CONFIG_MPU_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
|
@ -99,7 +100,7 @@ static int region_allocate_and_init(const uint8_t index,
|
|||
* of a given configuration at a given MPU index.
|
||||
*/
|
||||
static int mpu_configure_region(const uint8_t index,
|
||||
const struct k_mem_partition *new_region)
|
||||
const struct z_arm_mpu_partition *new_region)
|
||||
{
|
||||
struct arm_mpu_region region_conf;
|
||||
|
||||
|
@ -107,7 +108,7 @@ static int mpu_configure_region(const uint8_t index,
|
|||
|
||||
/* Populate internal ARM MPU region configuration structure. */
|
||||
region_conf.base = new_region->start;
|
||||
get_region_attr_from_k_mem_partition_info(®ion_conf.attr,
|
||||
get_region_attr_from_mpu_partition_info(®ion_conf.attr,
|
||||
&new_region->attr, new_region->start, new_region->size);
|
||||
|
||||
/* Allocate and program region */
|
||||
|
@ -121,26 +122,26 @@ static int mpu_configure_region(const uint8_t index,
|
|||
* over a background memory area, optionally performing a
|
||||
* sanity check of the memory regions to be programmed.
|
||||
*/
|
||||
static int mpu_configure_regions(const struct k_mem_partition
|
||||
*regions[], uint8_t regions_num, uint8_t start_reg_index,
|
||||
static int mpu_configure_regions(const struct z_arm_mpu_partition
|
||||
regions[], uint8_t regions_num, uint8_t start_reg_index,
|
||||
bool do_sanity_check)
|
||||
{
|
||||
int i;
|
||||
int reg_index = start_reg_index;
|
||||
|
||||
for (i = 0; i < regions_num; i++) {
|
||||
if (regions[i]->size == 0U) {
|
||||
if (regions[i].size == 0U) {
|
||||
continue;
|
||||
}
|
||||
/* Non-empty region. */
|
||||
|
||||
if (do_sanity_check &&
|
||||
(!mpu_partition_is_valid(regions[i]))) {
|
||||
(!mpu_partition_is_valid(®ions[i]))) {
|
||||
LOG_ERR("Partition %u: sanity check failed.", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reg_index = mpu_configure_region(reg_index, regions[i]);
|
||||
reg_index = mpu_configure_region(reg_index, ®ions[i]);
|
||||
|
||||
if (reg_index == -EINVAL) {
|
||||
return reg_index;
|
||||
|
@ -188,7 +189,7 @@ void arm_core_mpu_disable(void)
|
|||
* @brief update configuration of an active memory partition
|
||||
*/
|
||||
void arm_core_mpu_mem_partition_config_update(
|
||||
struct k_mem_partition *partition,
|
||||
struct z_arm_mpu_partition *partition,
|
||||
k_mem_partition_attr_t *new_attr)
|
||||
{
|
||||
/* Find the partition. ASSERT if not found. */
|
||||
|
@ -249,8 +250,8 @@ int arm_core_mpu_buffer_validate(void *addr, size_t size, int write)
|
|||
/**
|
||||
* @brief configure fixed (static) MPU regions.
|
||||
*/
|
||||
void arm_core_mpu_configure_static_mpu_regions(const struct k_mem_partition
|
||||
*static_regions[], const uint8_t regions_num,
|
||||
void arm_core_mpu_configure_static_mpu_regions(const struct z_arm_mpu_partition
|
||||
static_regions[], const uint8_t regions_num,
|
||||
const uint32_t background_area_start, const uint32_t background_area_end)
|
||||
{
|
||||
if (mpu_configure_static_mpu_regions(static_regions, regions_num,
|
||||
|
@ -266,7 +267,7 @@ void arm_core_mpu_configure_static_mpu_regions(const struct k_mem_partition
|
|||
* @brief mark memory areas for dynamic region configuration
|
||||
*/
|
||||
void arm_core_mpu_mark_areas_for_dynamic_regions(
|
||||
const struct k_mem_partition dyn_region_areas[],
|
||||
const struct z_arm_mpu_partition dyn_region_areas[],
|
||||
const uint8_t dyn_region_areas_num)
|
||||
{
|
||||
if (mpu_mark_areas_for_dynamic_regions(dyn_region_areas,
|
||||
|
@ -281,8 +282,8 @@ void arm_core_mpu_mark_areas_for_dynamic_regions(
|
|||
/**
|
||||
* @brief configure dynamic MPU regions.
|
||||
*/
|
||||
void arm_core_mpu_configure_dynamic_mpu_regions(const struct k_mem_partition
|
||||
*dynamic_regions[], uint8_t regions_num)
|
||||
void arm_core_mpu_configure_dynamic_mpu_regions(const struct z_arm_mpu_partition
|
||||
dynamic_regions[], uint8_t regions_num)
|
||||
{
|
||||
if (mpu_configure_dynamic_mpu_regions(dynamic_regions, regions_num)
|
||||
== -EINVAL) {
|
||||
|
|
|
@ -46,7 +46,7 @@ static void region_init(const uint32_t index,
|
|||
* @param part Pointer to the data structure holding the partition
|
||||
* information (must be valid).
|
||||
*/
|
||||
static int mpu_partition_is_valid(const struct k_mem_partition *part)
|
||||
static int mpu_partition_is_valid(const struct z_arm_mpu_partition *part)
|
||||
{
|
||||
/* Partition size must be power-of-two,
|
||||
* and greater or equal to the minimum
|
||||
|
@ -96,7 +96,7 @@ static inline uint32_t size_to_mpu_rasr_size(uint32_t size)
|
|||
* region attribute configuration and size and fill-in a driver-specific
|
||||
* structure with the correct MPU region configuration.
|
||||
*/
|
||||
static inline void get_region_attr_from_k_mem_partition_info(
|
||||
static inline void get_region_attr_from_mpu_partition_info(
|
||||
arm_mpu_region_attr_t *p_attr,
|
||||
const k_mem_partition_attr_t *attr, uint32_t base, uint32_t size)
|
||||
{
|
||||
|
@ -283,10 +283,10 @@ static inline int mpu_buffer_validate(void *addr, size_t size, int write)
|
|||
#endif /* CONFIG_USERSPACE */
|
||||
|
||||
static int mpu_configure_region(const uint8_t index,
|
||||
const struct k_mem_partition *new_region);
|
||||
const struct z_arm_mpu_partition *new_region);
|
||||
|
||||
static int mpu_configure_regions(const struct k_mem_partition
|
||||
*regions[], uint8_t regions_num, uint8_t start_reg_index,
|
||||
static int mpu_configure_regions(const struct z_arm_mpu_partition
|
||||
regions[], uint8_t regions_num, uint8_t start_reg_index,
|
||||
bool do_sanity_check);
|
||||
|
||||
/* This internal function programs the static MPU regions.
|
||||
|
@ -297,8 +297,8 @@ static int mpu_configure_regions(const struct k_mem_partition
|
|||
* If the static MPU regions configuration has not been successfully
|
||||
* performed, the error signal is propagated to the caller of the function.
|
||||
*/
|
||||
static int mpu_configure_static_mpu_regions(const struct k_mem_partition
|
||||
*static_regions[], const uint8_t regions_num,
|
||||
static int mpu_configure_static_mpu_regions(const struct z_arm_mpu_partition
|
||||
static_regions[], const uint8_t regions_num,
|
||||
const uint32_t background_area_base,
|
||||
const uint32_t background_area_end)
|
||||
{
|
||||
|
@ -326,8 +326,8 @@ static int mpu_configure_static_mpu_regions(const struct k_mem_partition
|
|||
* If the dynamic MPU regions configuration has not been successfully
|
||||
* performed, the error signal is propagated to the caller of the function.
|
||||
*/
|
||||
static int mpu_configure_dynamic_mpu_regions(const struct k_mem_partition
|
||||
*dynamic_regions[], uint8_t regions_num)
|
||||
static int mpu_configure_dynamic_mpu_regions(const struct z_arm_mpu_partition
|
||||
dynamic_regions[], uint8_t regions_num)
|
||||
{
|
||||
int mpu_reg_index = static_regions_num;
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ static void region_init(const uint32_t index,
|
|||
* @param part Pointer to the data structure holding the partition
|
||||
* information (must be valid).
|
||||
* */
|
||||
static int mpu_partition_is_valid(const struct k_mem_partition *part)
|
||||
static int mpu_partition_is_valid(const struct z_arm_mpu_partition *part)
|
||||
{
|
||||
/* Partition size must be a multiple of the minimum MPU region
|
||||
* size. Start address of the partition must align with the
|
||||
|
@ -191,7 +191,7 @@ static inline void mpu_region_get_conf(const uint32_t index,
|
|||
* region attribute configuration and size and fill-in a driver-specific
|
||||
* structure with the correct MPU region configuration.
|
||||
*/
|
||||
static inline void get_region_attr_from_k_mem_partition_info(
|
||||
static inline void get_region_attr_from_mpu_partition_info(
|
||||
arm_mpu_region_attr_t *p_attr,
|
||||
const k_mem_partition_attr_t *attr, uint32_t base, uint32_t size)
|
||||
{
|
||||
|
@ -316,11 +316,11 @@ static int region_allocate_and_init(const uint8_t index,
|
|||
const struct arm_mpu_region *region_conf);
|
||||
|
||||
static int mpu_configure_region(const uint8_t index,
|
||||
const struct k_mem_partition *new_region);
|
||||
const struct z_arm_mpu_partition *new_region);
|
||||
|
||||
#if !defined(CONFIG_MPU_GAP_FILLING)
|
||||
static int mpu_configure_regions(const struct k_mem_partition
|
||||
*regions[], uint8_t regions_num, uint8_t start_reg_index,
|
||||
static int mpu_configure_regions(const struct z_arm_mpu_partition
|
||||
regions[], uint8_t regions_num, uint8_t start_reg_index,
|
||||
bool do_sanity_check);
|
||||
#endif
|
||||
|
||||
|
@ -331,21 +331,21 @@ static int mpu_configure_regions(const struct k_mem_partition
|
|||
* The function performs a full partition of the background memory
|
||||
* area, effectively, leaving no space in this area uncovered by MPU.
|
||||
*/
|
||||
static int mpu_configure_regions_and_partition(const struct k_mem_partition
|
||||
*regions[], uint8_t regions_num, uint8_t start_reg_index,
|
||||
static int mpu_configure_regions_and_partition(const struct z_arm_mpu_partition
|
||||
regions[], uint8_t regions_num, uint8_t start_reg_index,
|
||||
bool do_sanity_check)
|
||||
{
|
||||
int i;
|
||||
int reg_index = start_reg_index;
|
||||
|
||||
for (i = 0; i < regions_num; i++) {
|
||||
if (regions[i]->size == 0U) {
|
||||
if (regions[i].size == 0U) {
|
||||
continue;
|
||||
}
|
||||
/* Non-empty region. */
|
||||
|
||||
if (do_sanity_check &&
|
||||
(!mpu_partition_is_valid(regions[i]))) {
|
||||
(!mpu_partition_is_valid(®ions[i]))) {
|
||||
LOG_ERR("Partition %u: sanity check failed.", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ static int mpu_configure_regions_and_partition(const struct k_mem_partition
|
|||
* inside which the new region will be configured.
|
||||
*/
|
||||
int u_reg_index =
|
||||
get_region_index(regions[i]->start, regions[i]->size);
|
||||
get_region_index(regions[i].start, regions[i].size);
|
||||
|
||||
if ((u_reg_index == -EINVAL) ||
|
||||
(u_reg_index > (reg_index - 1))) {
|
||||
|
@ -369,9 +369,9 @@ static int mpu_configure_regions_and_partition(const struct k_mem_partition
|
|||
*/
|
||||
uint32_t u_reg_base = mpu_region_get_base(u_reg_index);
|
||||
uint32_t u_reg_last = mpu_region_get_last_addr(u_reg_index);
|
||||
uint32_t reg_last = regions[i]->start + regions[i]->size - 1;
|
||||
uint32_t reg_last = regions[i].start + regions[i].size - 1;
|
||||
|
||||
if ((regions[i]->start == u_reg_base) &&
|
||||
if ((regions[i].start == u_reg_base) &&
|
||||
(reg_last == u_reg_last)) {
|
||||
/* The new region overlaps entirely with the
|
||||
* underlying region. In this case we simply
|
||||
|
@ -379,17 +379,17 @@ static int mpu_configure_regions_and_partition(const struct k_mem_partition
|
|||
* underlying region with those of the new
|
||||
* region.
|
||||
*/
|
||||
mpu_configure_region(u_reg_index, regions[i]);
|
||||
} else if (regions[i]->start == u_reg_base) {
|
||||
mpu_configure_region(u_reg_index, ®ions[i]);
|
||||
} else if (regions[i].start == u_reg_base) {
|
||||
/* The new region starts exactly at the start of the
|
||||
* underlying region; the start of the underlying
|
||||
* region needs to be set to the end of the new region.
|
||||
*/
|
||||
mpu_region_set_base(u_reg_index,
|
||||
regions[i]->start + regions[i]->size);
|
||||
regions[i].start + regions[i].size);
|
||||
|
||||
reg_index =
|
||||
mpu_configure_region(reg_index, regions[i]);
|
||||
mpu_configure_region(reg_index, ®ions[i]);
|
||||
|
||||
if (reg_index == -EINVAL) {
|
||||
return reg_index;
|
||||
|
@ -403,10 +403,10 @@ static int mpu_configure_regions_and_partition(const struct k_mem_partition
|
|||
* new region.
|
||||
*/
|
||||
mpu_region_set_limit(u_reg_index,
|
||||
regions[i]->start - 1);
|
||||
regions[i].start - 1);
|
||||
|
||||
reg_index =
|
||||
mpu_configure_region(reg_index, regions[i]);
|
||||
mpu_configure_region(reg_index, ®ions[i]);
|
||||
|
||||
if (reg_index == -EINVAL) {
|
||||
return reg_index;
|
||||
|
@ -419,10 +419,10 @@ static int mpu_configure_regions_and_partition(const struct k_mem_partition
|
|||
* into two regions.
|
||||
*/
|
||||
mpu_region_set_limit(u_reg_index,
|
||||
regions[i]->start - 1);
|
||||
regions[i].start - 1);
|
||||
|
||||
reg_index =
|
||||
mpu_configure_region(reg_index, regions[i]);
|
||||
mpu_configure_region(reg_index, ®ions[i]);
|
||||
|
||||
if (reg_index == -EINVAL) {
|
||||
return reg_index;
|
||||
|
@ -437,11 +437,11 @@ static int mpu_configure_regions_and_partition(const struct k_mem_partition
|
|||
|
||||
mpu_region_get_access_attr(u_reg_index,
|
||||
&fill_region.attr);
|
||||
fill_region.base = regions[i]->start +
|
||||
regions[i]->size;
|
||||
fill_region.base = regions[i].start +
|
||||
regions[i].size;
|
||||
fill_region.attr.r_limit =
|
||||
REGION_LIMIT_ADDR((regions[i]->start +
|
||||
regions[i]->size), (u_reg_last - reg_last));
|
||||
REGION_LIMIT_ADDR((regions[i].start +
|
||||
regions[i].size), (u_reg_last - reg_last));
|
||||
|
||||
reg_index =
|
||||
region_allocate_and_init(reg_index,
|
||||
|
@ -467,8 +467,8 @@ static int mpu_configure_regions_and_partition(const struct k_mem_partition
|
|||
* If the static MPU regions configuration has not been successfully
|
||||
* performed, the error signal is propagated to the caller of the function.
|
||||
*/
|
||||
static int mpu_configure_static_mpu_regions(const struct k_mem_partition
|
||||
*static_regions[], const uint8_t regions_num,
|
||||
static int mpu_configure_static_mpu_regions(const struct z_arm_mpu_partition
|
||||
static_regions[], const uint8_t regions_num,
|
||||
const uint32_t background_area_base,
|
||||
const uint32_t background_area_end)
|
||||
{
|
||||
|
@ -494,7 +494,7 @@ static int mpu_configure_static_mpu_regions(const struct k_mem_partition
|
|||
* -EINVAL on error.
|
||||
*/
|
||||
static int mpu_mark_areas_for_dynamic_regions(
|
||||
const struct k_mem_partition dyn_region_areas[],
|
||||
const struct z_arm_mpu_partition dyn_region_areas[],
|
||||
const uint8_t dyn_region_areas_num)
|
||||
{
|
||||
/* In ARMv8-M architecture we need to store the index values
|
||||
|
@ -538,8 +538,8 @@ static int mpu_mark_areas_for_dynamic_regions(
|
|||
* If the dynamic MPU regions configuration has not been successfully
|
||||
* performed, the error signal is propagated to the caller of the function.
|
||||
*/
|
||||
static int mpu_configure_dynamic_mpu_regions(const struct k_mem_partition
|
||||
*dynamic_regions[], uint8_t regions_num)
|
||||
static int mpu_configure_dynamic_mpu_regions(const struct z_arm_mpu_partition
|
||||
dynamic_regions[], uint8_t regions_num)
|
||||
{
|
||||
int mpu_reg_index = static_regions_num;
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ static inline uint8_t get_num_regions(void)
|
|||
* @param part Pointer to the data structure holding the partition
|
||||
* information (must be valid).
|
||||
*/
|
||||
static int mpu_partition_is_valid(const struct k_mem_partition *part)
|
||||
static int mpu_partition_is_valid(const struct z_arm_mpu_partition *part)
|
||||
{
|
||||
/* Partition size must be a multiple of the minimum MPU region
|
||||
* size. Start address of the partition must align with the
|
||||
|
@ -138,7 +138,7 @@ static int region_allocate_and_init(const uint8_t index,
|
|||
* region attribute configuration and size and fill-in a driver-specific
|
||||
* structure with the correct MPU region attribute configuration.
|
||||
*/
|
||||
static inline void get_region_attr_from_k_mem_partition_info(
|
||||
static inline void get_region_attr_from_mpu_partition_info(
|
||||
nxp_mpu_region_attr_t *p_attr,
|
||||
const k_mem_partition_attr_t *attr, uint32_t base, uint32_t size)
|
||||
{
|
||||
|
@ -155,7 +155,7 @@ static inline void get_region_attr_from_k_mem_partition_info(
|
|||
* of a given configuration at a given MPU index.
|
||||
*/
|
||||
static int mpu_configure_region(const uint8_t index,
|
||||
const struct k_mem_partition *new_region)
|
||||
const struct z_arm_mpu_partition *new_region)
|
||||
{
|
||||
struct nxp_mpu_region region_conf;
|
||||
|
||||
|
@ -164,7 +164,7 @@ static int mpu_configure_region(const uint8_t index,
|
|||
/* Populate internal NXP MPU region configuration structure. */
|
||||
region_conf.base = new_region->start;
|
||||
region_conf.end = (new_region->start + new_region->size - 1);
|
||||
get_region_attr_from_k_mem_partition_info(®ion_conf.attr,
|
||||
get_region_attr_from_mpu_partition_info(®ion_conf.attr,
|
||||
&new_region->attr, new_region->start, new_region->size);
|
||||
|
||||
/* Allocate and program region */
|
||||
|
@ -175,7 +175,7 @@ static int mpu_configure_region(const uint8_t index,
|
|||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
/* This internal function partitions the SRAM MPU region */
|
||||
static int mpu_sram_partitioning(uint8_t index,
|
||||
const struct k_mem_partition *p_region)
|
||||
const struct z_arm_mpu_partition *p_region)
|
||||
{
|
||||
/*
|
||||
* The NXP MPU manages the permissions of the overlapping regions
|
||||
|
@ -233,27 +233,27 @@ static int mpu_sram_partitioning(uint8_t index,
|
|||
* over a background memory area, optionally performing a
|
||||
* sanity check of the memory regions to be programmed.
|
||||
*/
|
||||
static int mpu_configure_regions(const struct k_mem_partition
|
||||
*regions[], uint8_t regions_num, uint8_t start_reg_index,
|
||||
bool do_sanity_check)
|
||||
static int mpu_configure_regions(const struct z_arm_mpu_partition regions[],
|
||||
uint8_t regions_num, uint8_t start_reg_index,
|
||||
bool do_sanity_check)
|
||||
{
|
||||
int i;
|
||||
int reg_index = start_reg_index;
|
||||
|
||||
for (i = 0; i < regions_num; i++) {
|
||||
if (regions[i]->size == 0U) {
|
||||
if (regions[i].size == 0U) {
|
||||
continue;
|
||||
}
|
||||
/* Non-empty region. */
|
||||
|
||||
if (do_sanity_check &&
|
||||
(!mpu_partition_is_valid(regions[i]))) {
|
||||
(!mpu_partition_is_valid(®ions[i]))) {
|
||||
LOG_ERR("Partition %u: sanity check failed.", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
if (regions[i]->attr.ap_attr == MPU_REGION_SU_RX) {
|
||||
if (regions[i].attr.ap_attr == MPU_REGION_SU_RX) {
|
||||
unsigned int key;
|
||||
|
||||
/* Attempt to configure an MPU Stack Guard region; this
|
||||
|
@ -263,7 +263,7 @@ static int mpu_configure_regions(const struct k_mem_partition
|
|||
*/
|
||||
key = irq_lock();
|
||||
reg_index =
|
||||
mpu_sram_partitioning(reg_index, regions[i]);
|
||||
mpu_sram_partitioning(reg_index, ®ions[i]);
|
||||
irq_unlock(key);
|
||||
}
|
||||
#endif /* CONFIG_MPU_STACK_GUARD */
|
||||
|
@ -272,7 +272,7 @@ static int mpu_configure_regions(const struct k_mem_partition
|
|||
return reg_index;
|
||||
}
|
||||
|
||||
reg_index = mpu_configure_region(reg_index, regions[i]);
|
||||
reg_index = mpu_configure_region(reg_index, ®ions[i]);
|
||||
|
||||
if (reg_index == -EINVAL) {
|
||||
return reg_index;
|
||||
|
@ -293,9 +293,9 @@ static int mpu_configure_regions(const struct k_mem_partition
|
|||
* If the static MPU regions configuration has not been successfully
|
||||
* performed, the error signal is propagated to the caller of the function.
|
||||
*/
|
||||
static int mpu_configure_static_mpu_regions(const struct k_mem_partition
|
||||
*static_regions[], const uint8_t regions_num,
|
||||
const uint32_t background_area_base,
|
||||
static int mpu_configure_static_mpu_regions(
|
||||
const struct z_arm_mpu_partition static_regions[],
|
||||
const uint8_t regions_num, const uint32_t background_area_base,
|
||||
const uint32_t background_area_end)
|
||||
{
|
||||
int mpu_reg_index = static_regions_num;
|
||||
|
@ -322,8 +322,9 @@ static int mpu_configure_static_mpu_regions(const struct k_mem_partition
|
|||
* If the dynamic MPU regions configuration has not been successfully
|
||||
* performed, the error signal is propagated to the caller of the function.
|
||||
*/
|
||||
static int mpu_configure_dynamic_mpu_regions(const struct k_mem_partition
|
||||
*dynamic_regions[], uint8_t regions_num)
|
||||
static int mpu_configure_dynamic_mpu_regions(
|
||||
const struct z_arm_mpu_partition dynamic_regions[],
|
||||
uint8_t regions_num)
|
||||
{
|
||||
unsigned int key;
|
||||
|
||||
|
@ -470,7 +471,7 @@ static inline int is_in_region(uint32_t r_index, uint32_t start, uint32_t size)
|
|||
* @brief update configuration of an active memory partition
|
||||
*/
|
||||
void arm_core_mpu_mem_partition_config_update(
|
||||
struct k_mem_partition *partition,
|
||||
struct z_arm_mpu_partition *partition,
|
||||
k_mem_partition_attr_t *new_attr)
|
||||
{
|
||||
/* Find the partition. ASSERT if not found. */
|
||||
|
@ -564,12 +565,14 @@ int arm_core_mpu_buffer_validate(void *addr, size_t size, int write)
|
|||
/**
|
||||
* @brief configure fixed (static) MPU regions.
|
||||
*/
|
||||
void arm_core_mpu_configure_static_mpu_regions(const struct k_mem_partition
|
||||
*static_regions[], const uint8_t regions_num,
|
||||
const uint32_t background_area_start, const uint32_t background_area_end)
|
||||
void arm_core_mpu_configure_static_mpu_regions(
|
||||
const struct z_arm_mpu_partition static_regions[],
|
||||
const uint8_t regions_num, const uint32_t background_area_start,
|
||||
const uint32_t background_area_end)
|
||||
{
|
||||
if (mpu_configure_static_mpu_regions(static_regions, regions_num,
|
||||
background_area_start, background_area_end) == -EINVAL) {
|
||||
background_area_start,
|
||||
background_area_end) == -EINVAL) {
|
||||
|
||||
__ASSERT(0, "Configuring %u static MPU regions failed\n",
|
||||
regions_num);
|
||||
|
@ -579,11 +582,11 @@ void arm_core_mpu_configure_static_mpu_regions(const struct k_mem_partition
|
|||
/**
|
||||
* @brief configure dynamic MPU regions.
|
||||
*/
|
||||
void arm_core_mpu_configure_dynamic_mpu_regions(const struct k_mem_partition
|
||||
*dynamic_regions[], uint8_t regions_num)
|
||||
void arm_core_mpu_configure_dynamic_mpu_regions(
|
||||
const struct z_arm_mpu_partition dynamic_regions[], uint8_t regions_num)
|
||||
{
|
||||
if (mpu_configure_dynamic_mpu_regions(dynamic_regions, regions_num)
|
||||
== -EINVAL) {
|
||||
if (mpu_configure_dynamic_mpu_regions(dynamic_regions,
|
||||
regions_num) == -EINVAL) {
|
||||
|
||||
__ASSERT(0, "Configuring %u dynamic MPU regions failed\n",
|
||||
regions_num);
|
||||
|
|
|
@ -47,6 +47,14 @@ extern "C" {
|
|||
typedef struct __esf _esf_t;
|
||||
typedef struct __basic_sf _basic_sf_t;
|
||||
|
||||
#ifdef CONFIG_ARM_MPU
|
||||
struct z_arm_mpu_partition {
|
||||
uintptr_t start;
|
||||
size_t size;
|
||||
k_mem_partition_attr_t attr;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue