1 /* 2 * Copyright (c) 2017 Linaro Limited. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 #ifndef ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_MPU_ARM_CORE_MPU_DEV_H_ 7 #define ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_MPU_ARM_CORE_MPU_DEV_H_ 8 9 #include <zephyr/types.h> 10 #include <kernel_arch_data.h> 11 12 #ifdef __cplusplus 13 extern "C" { 14 #endif 15 16 #if defined(CONFIG_ARM_MPU) 17 struct k_thread; 18 19 #if defined(CONFIG_USERSPACE) 20 21 /** 22 * @brief Maximum number of memory domain partitions 23 * 24 * This internal macro returns the maximum number of memory partitions, which 25 * may be defined in a memory domain, given the amount of available HW MPU 26 * regions. 27 * 28 * @param mpu_regions_num the number of available HW MPU regions. 29 */ 30 #if defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS) && \ 31 defined(CONFIG_MPU_GAP_FILLING) 32 /* 33 * For ARM MPU architectures, where the domain partitions cannot be defined 34 * on top of the statically configured memory regions, the maximum number of 35 * memory domain partitions is set to half of the number of available MPU 36 * regions. This ensures that in the worst-case where there are gaps between 37 * the memory partitions of the domain, the desired memory map can still be 38 * programmed using the available number of HW MPU regions. 39 */ 40 #define ARM_CORE_MPU_MAX_DOMAIN_PARTITIONS_GET(mpu_regions_num) \ 41 (mpu_regions_num/2) 42 #else 43 /* 44 * For ARM MPU architectures, where the domain partitions can be defined 45 * on top of the statically configured memory regions, the maximum number 46 * of memory domain partitions is equal to the number of available MPU regions. 47 */ 48 #define ARM_CORE_MPU_MAX_DOMAIN_PARTITIONS_GET(mpu_regions_num) \ 49 (mpu_regions_num) 50 #endif /* CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS */ 51 52 /** 53 * @brief Maximum number of MPU regions required to configure a 54 * memory region for (user) Thread Stack. 55 */ 56 #if defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS) && \ 57 defined(CONFIG_MPU_GAP_FILLING) 58 /* When dynamic regions may not be defined on top of statically 59 * allocated memory regions, defining a region for a thread stack 60 * requires two additional MPU regions to be configured; one for 61 * defining the thread stack and an additional one for partitioning 62 * the underlying memory area. 63 */ 64 #define ARM_CORE_MPU_NUM_MPU_REGIONS_FOR_THREAD_STACK 2 65 #else 66 /* When dynamic regions may be defined on top of statically allocated 67 * memory regions, a thread stack area may be configured using a 68 * single MPU region. 69 */ 70 #define ARM_CORE_MPU_NUM_MPU_REGIONS_FOR_THREAD_STACK 1 71 #endif /* CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS */ 72 73 /** 74 * @brief Maximum number of MPU regions required to configure a 75 * memory region for a (supervisor) Thread Stack Guard. 76 */ 77 #if (defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS) && \ 78 defined(CONFIG_MPU_GAP_FILLING)) \ 79 || defined(CONFIG_CPU_HAS_NXP_SYSMPU) 80 /* 81 * When dynamic regions may not be defined on top of statically 82 * allocated memory regions, defining a region for a supervisor 83 * thread stack guard requires two additional MPU regions to be 84 * configured; one for defining the stack guard and an additional 85 * one for partitioning the underlying memory area. 86 * 87 * The same is required for the NXP MPU due to its OR-based decision 88 * policy; the MPU stack guard applies more restrictive permissions on 89 * the underlying (SRAM) regions, and, therefore, we need to partition 90 * the underlying SRAM region. 91 */ 92 #define ARM_CORE_MPU_NUM_MPU_REGIONS_FOR_MPU_STACK_GUARD 2 93 #elif defined(CONFIG_CPU_HAS_ARM_MPU) 94 /* When dynamic regions may be defined on top of statically allocated 95 * memory regions, a supervisor thread stack guard area may be configured 96 * using a single MPU region. 97 */ 98 #define ARM_CORE_MPU_NUM_MPU_REGIONS_FOR_MPU_STACK_GUARD 1 99 #endif /* CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS || CPU_HAS_NXP_SYSMPU */ 100 101 #endif /* CONFIG_USERSPACE */ 102 103 104 /* ARM Core MPU Driver API */ 105 106 /* 107 * This API has to be implemented by all the MPU drivers that have 108 * ARM_MPU support. 109 */ 110 111 /** 112 * @brief configure a set of fixed (static) MPU regions 113 * 114 * Internal API function to configure a set of static MPU memory regions, 115 * within a (background) memory area determined by start and end address. 116 * The total number of HW MPU regions to be programmed depends on the MPU 117 * architecture. 118 * 119 * The function shall be invoked once, upon system initialization. 120 * 121 * @param static_regions an array of pointers to memory partitions 122 * to be programmed 123 * @param regions_num the number of regions to be programmed 124 * @param background_area_start the start address of the background memory area 125 * @param background_area_end the end address of the background memory area 126 * 127 * The function shall assert if the operation cannot be not performed 128 * successfully. Therefore: 129 * - the number of HW MPU regions to be programmed shall not exceed the number 130 * of available MPU indices, 131 * - the size and alignment of the static regions shall comply with the 132 * requirements of the MPU hardware. 133 */ 134 void arm_core_mpu_configure_static_mpu_regions( 135 const struct z_arm_mpu_partition *static_regions, 136 const uint8_t regions_num, const uint32_t background_area_start, 137 const uint32_t background_area_end); 138 139 #if defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS) 140 141 /* Number of memory areas, inside which dynamic regions 142 * may be programmed in run-time. 143 */ 144 #define MPU_DYNAMIC_REGION_AREAS_NUM 1 145 146 /** 147 * @brief mark a set of memory regions as eligible for dynamic configuration 148 * 149 * Internal API function to configure a set of memory regions, determined 150 * by their start address and size, as memory areas eligible for dynamically 151 * programming MPU regions (such as a supervisor stack overflow guard) at 152 * run-time (for example, thread upon context-switch). 153 * 154 * The function shall be invoked once, upon system initialization. 155 * 156 * @param dyn_region_areas an array of z_arm_mpu_partition objects declaring the 157 * eligible memory areas for dynamic programming 158 * @param dyn_region_areas_num the number of eligible areas for dynamic 159 * programming. 160 * 161 * The function shall assert if the operation cannot be not performed 162 * successfully. Therefore, the requested areas shall correspond to 163 * static memory regions, configured earlier by 164 * arm_core_mpu_configure_static_mpu_regions(). 165 */ 166 void arm_core_mpu_mark_areas_for_dynamic_regions( 167 const struct z_arm_mpu_partition *dyn_region_areas, 168 const uint8_t dyn_region_areas_num); 169 170 #endif /* CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS */ 171 172 /** 173 * @brief configure a set of dynamic MPU regions 174 * 175 * Internal API function to configure a set of dynamic MPU memory regions 176 * within a (background) memory area. The total number of HW MPU regions 177 * to be programmed depends on the MPU architecture. 178 * 179 * @param dynamic_regions an array of pointers to memory partitions 180 * to be programmed 181 * @param regions_num the number of regions to be programmed 182 * 183 * The function shall assert if the operation cannot be not performed 184 * successfully. Therefore, the number of HW MPU regions to be programmed shall 185 * not exceed the number of (currently) available MPU indices. 186 */ 187 void arm_core_mpu_configure_dynamic_mpu_regions( 188 const struct z_arm_mpu_partition *dynamic_regions, 189 uint8_t regions_num); 190 191 #if defined(CONFIG_USERSPACE) 192 /** 193 * @brief update configuration of an active memory partition 194 * 195 * Internal API function to re-configure the access permissions of an 196 * active memory partition, i.e. a partition that has earlier been 197 * configured in the (current) thread context. 198 * 199 * @param partition Pointer to a structure holding the partition information 200 * (must be valid). 201 * @param new_attr New access permissions attribute for the partition. 202 * 203 * The function shall assert if the operation cannot be not performed 204 * successfully (e.g. the given partition can not be found). 205 */ 206 void arm_core_mpu_mem_partition_config_update( 207 struct z_arm_mpu_partition *partition, 208 k_mem_partition_attr_t *new_attr); 209 210 #endif /* CONFIG_USERSPACE */ 211 212 /** 213 * @brief configure the base address and size for an MPU region 214 * 215 * @param type MPU region type 216 * @param base base address in RAM 217 * @param size size of the region 218 */ 219 void arm_core_mpu_configure(uint8_t type, uint32_t base, uint32_t size); 220 221 /** 222 * @brief configure MPU regions for the memory partitions of the memory domain 223 * 224 * @param mem_domain memory domain that thread belongs to 225 */ 226 void arm_core_mpu_configure_mem_domain(struct k_mem_domain *mem_domain); 227 228 /** 229 * @brief configure MPU regions for a user thread's context 230 * 231 * @param thread thread to configure 232 */ 233 void arm_core_mpu_configure_user_context(struct k_thread *thread); 234 235 /** 236 * @brief configure MPU region for a single memory partition 237 * 238 * @param part_index memory partition index 239 * @param part memory partition info 240 */ 241 void arm_core_mpu_configure_mem_partition(uint32_t part_index, 242 struct z_arm_mpu_partition *part); 243 244 /** 245 * @brief Reset MPU region for a single memory partition 246 * 247 * @param part_index memory partition index 248 */ 249 void arm_core_mpu_mem_partition_remove(uint32_t part_index); 250 251 /** 252 * @brief Get the maximum number of available (free) MPU region indices 253 * for configuring dynamic MPU regions. 254 */ 255 int arm_core_mpu_get_max_available_dyn_regions(void); 256 257 /** 258 * @brief validate the given buffer is user accessible or not 259 * 260 * Note: Validation will always return failure, if the supplied buffer 261 * spans multiple enabled MPU regions (even if these regions all 262 * permit user access). 263 */ 264 int arm_core_mpu_buffer_validate(const void *addr, size_t size, int write); 265 266 #endif /* CONFIG_ARM_MPU */ 267 268 #ifdef __cplusplus 269 } 270 #endif 271 272 #endif /* ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_MPU_ARM_CORE_MPU_DEV_H_ */ 273