I'm getting intermittent run-time failures such as:
syscall z_hdlr_k_uptime_get failed check: Memory region 0x0002ff70 (size 8) write access denied
***** Hardware exception *****
Current thread ID = 0x000221b0
Faulting instruction address = 0x1a
Fatal fault in thread 0x000221b0! Aborting.
In this example, k_uptime_get() was called, which is going to save its 64-bit return value into memory (due to the syscall macros). The syscall gear is checking to see if the memory
address is valid. The routines wind down into mpu_buffer_validate(), which will call is_user_accessible_region() and finally into get_region_ap(). The code
is failing because get_region_ap() has a critical code section which is not wrapped with an irq_lock()/irq_unlock(). In this failure, we write the MPU index register, then
take an external interrupt, go off to another thread for a while ( which is going to re-load the MPU entries), return to the current thread (again re-loading the MPU entries), and read the attribute register (for the wrong index) and fail.
In reading the current Cortex-M code, I don't see it protecting these critical sections either, so I'm left wondering if the 'M' class will save the index register during
interrupt processing. If so, I would like to fix the 'R' code in a similar fashion.
There are several of these utility subroutines with this same critical code sections.
For reference, I've included the diff of get_region_ap() that I am going to be testing with locally where I do irq_lock() and irq_unlock().
/**
* This internal function returns the access permissions of an MPU region
* specified by its region index.
@@ -133,7 +136,17 @@ static inline int is_enabled_region(u32_t index)
*/
static inline u32_t get_region_ap(u32_t r_index)
{
- set_region_number(r_index);
+ int
+ attr,
+ key = irq_lock();
+
+ set_region_number(r_index);
+
+ attr = get_region_attributes();
- return (get_region_attributes() & MPU_RASR_AP_Msk) >> MPU_RASR_AP_Pos;
+ irq_unlock(key);
+
+ return (attr & MPU_RASR_AP_Msk) >> MPU_RASR_AP_Pos;
}
+