@@ -140,6 +140,56 @@ static inline u32_t _size_to_mpu_rasr_size(u32_t size)
140
140
return (find_msb_set (size ) - 2 ) << 1 ;
141
141
}
142
142
143
+ /**
144
+ * This internal function check if region is enabled or not
145
+ */
146
+ static inline int _is_enabled_region (u32_t r_index )
147
+ {
148
+ ARM_MPU_DEV -> rnr = r_index ;
149
+
150
+ return ARM_MPU_DEV -> rasr & REGION_ENABLE_MASK ;
151
+ }
152
+
153
+ /**
154
+ * This internal function check if the given buffer in in the region
155
+ */
156
+ static inline int _is_in_region (u32_t r_index , u32_t start , u32_t size )
157
+ {
158
+ u32_t r_addr_start ;
159
+ u32_t r_size_lshift ;
160
+ u32_t r_addr_end ;
161
+
162
+ ARM_MPU_DEV -> rnr = r_index ;
163
+ r_addr_start = ARM_MPU_DEV -> rbar & REGION_BASE_ADDR_MASK ;
164
+ r_size_lshift = ((ARM_MPU_DEV -> rasr & REGION_SIZE_MASK ) >>
165
+ REGION_SIZE_OFFSET ) + 1 ;
166
+ r_addr_end = r_addr_start + (1 << r_size_lshift ) - 1 ;
167
+
168
+ if (start >= r_addr_start && (start + size - 1 ) <= r_addr_end ) {
169
+ return 1 ;
170
+ }
171
+
172
+ return 0 ;
173
+ }
174
+
175
+ /**
176
+ * This internal function check if the region is user accessible or not
177
+ */
178
+ static inline int _is_user_accessible_region (u32_t r_index , int write )
179
+ {
180
+ u32_t r_ap ;
181
+
182
+ ARM_MPU_DEV -> rnr = r_index ;
183
+ r_ap = ARM_MPU_DEV -> rasr & ACCESS_PERMS_MASK ;
184
+
185
+ if (write ) {
186
+ return r_ap == P_RW_U_RW ;
187
+ }
188
+
189
+ /* For all user accessible permissions, their AP[1] bit is l */
190
+ return r_ap & (0x2 << ACCESS_PERMS_OFFSET );
191
+ }
192
+
143
193
/* ARM Core MPU Driver API Implementation for ARM MPU */
144
194
145
195
/**
@@ -292,6 +342,35 @@ int arm_core_mpu_get_max_domain_partition_regions(void)
292
342
return _get_num_regions () -
293
343
_get_region_index_by_type (THREAD_DOMAIN_PARTITION_REGION );
294
344
}
345
+
346
+ /**
347
+ * @brief validate the given buffer is user accessible or not
348
+ */
349
+ int arm_core_mpu_buffer_validate (void * addr , size_t size , int write )
350
+ {
351
+ u32_t r_index ;
352
+
353
+ /* Iterate all mpu regions in reversed order */
354
+ for (r_index = _get_num_regions () + 1 ; r_index -- > 0 ;) {
355
+ if (!_is_enabled_region (r_index ) ||
356
+ !_is_in_region (r_index , (u32_t )addr , size )) {
357
+ continue ;
358
+ }
359
+
360
+ /* For ARM MPU, higher region number takes priority.
361
+ * Since we iterate all mpu regions in reversed order, so
362
+ * we can stop the iteration immediately once we find the
363
+ * matched region that grants permission or denies access.
364
+ */
365
+ if (_is_user_accessible_region (r_index , write )) {
366
+ return 0 ;
367
+ } else {
368
+ return - EPERM ;
369
+ }
370
+ }
371
+
372
+ return - EPERM ;
373
+ }
295
374
#endif /* CONFIG_USERSPACE */
296
375
297
376
/* ARM MPU Driver Initial Setup */
0 commit comments