Skip to content

Commit 4cc9739

Browse files
peter-mitsishenrikbrixandersen
authored andcommitted
arch: Update arch_is_in_isr() SMP implementations
Fixes a flaw in implementations of arch_is_in_isr() that could manifest on SMP systems. If the reading of the current CPU's nested interrupt count is not fully atomic on an SMP system, then an ill-timed context switch could occur leaving the caller reading the nested interrupt count of a different CPU. This also applies a little defensive programming to cortex_a_r's arch_is_in_nested_exception(). Although this routine is presently only called with interrupts locked (which will prevent the thread from migrating), switching to use _current_cpu instead of arch_curr_cpu() is safer as should the routine ever be called without meeting the locking criteria, it can be detected and fixed. Signed-off-by: Peter Mitsis <[email protected]>
1 parent 85b8ae9 commit 4cc9739

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

arch/arm/include/cortex_a_r/exception.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,24 @@ extern "C" {
3232
extern volatile irq_offload_routine_t offload_routine;
3333
#endif
3434

35-
/* Check the CPSR mode bits to see if we are in IRQ or FIQ mode */
3635
static ALWAYS_INLINE bool arch_is_in_isr(void)
3736
{
38-
return (arch_curr_cpu()->nested != 0U);
37+
uint32_t nested;
38+
#ifdef CONFIG_SMP
39+
unsigned int key;
40+
41+
key = arch_irq_lock();
42+
#endif
43+
nested = arch_curr_cpu()->nested;
44+
#ifdef CONFIG_SMP
45+
arch_irq_unlock(key);
46+
#endif
47+
return nested != 0U;
3948
}
4049

4150
static ALWAYS_INLINE bool arch_is_in_nested_exception(const struct arch_esf *esf)
4251
{
43-
return (arch_curr_cpu()->arch.exc_depth > 1U) ? (true) : (false);
52+
return (_current_cpu->arch.exc_depth > 1U) ? (true) : (false);
4453
}
4554

4655
/**

arch/arm64/include/exception.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,17 @@ extern "C" {
2828

2929
static ALWAYS_INLINE bool arch_is_in_isr(void)
3030
{
31-
return arch_curr_cpu()->nested != 0U;
31+
uint32_t nested;
32+
#ifdef CONFIG_SMP
33+
unsigned int key;
34+
35+
key = arch_irq_lock();
36+
#endif
37+
nested = arch_curr_cpu()->nested;
38+
#ifdef CONFIG_SMP
39+
arch_irq_unlock(key);
40+
#endif
41+
return nested != 0U;
3242
}
3343

3444
#ifdef __cplusplus

0 commit comments

Comments
 (0)