nios2: fix irq_lock/unlock ordering bug

Memory accesses could be reordered before an irq_lock() or
after an irq_unlock() without the memory barriers.

See commit 15bc537712 for the
ARM fix for a complete description of the issue and fix.

Change-Id: I1d96fe0088d90150f0888c2893d017155fc0a0a7
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2016-12-02 14:04:47 -08:00 committed by Anas Nashif
commit bba445b31f

View file

@ -94,10 +94,15 @@ typedef unsigned int vaddr_t;
static ALWAYS_INLINE unsigned int _arch_irq_lock(void)
{
unsigned int key;
unsigned int key, tmp;
key = _nios2_creg_read(NIOS2_CR_STATUS);
_nios2_creg_write(NIOS2_CR_STATUS, key & ~NIOS2_STATUS_PIE_MSK);
__asm__ volatile (
"rdctl %[key], status\n\t"
"movi %[tmp], -2\n\t"
"and %[tmp], %[key], %[tmp]\n\t"
"wrctl status, %[tmp]\n\t"
: [key] "=r" (key), [tmp] "=r" (tmp)
: : "memory");
return key;
}
@ -117,18 +122,20 @@ static ALWAYS_INLINE void _arch_irq_unlock(unsigned int key)
(defined ALT_CPU_EIC_PRESENT) || \
(defined ALT_CPU_MMU_PRESENT) || \
(defined ALT_CPU_MPU_PRESENT)
uint32_t status_reg;
/* Interrupts were already locked when irq_lock() was called,
* so don't do anything
*/
if (!(key & NIOS2_STATUS_PIE_MSK))
return;
status_reg = _nios2_creg_read(NIOS2_CR_STATUS);
_nios2_creg_write(NIOS2_CR_STATUS, status_reg | NIOS2_STATUS_PIE_MSK);
__asm__ volatile (
"andi %[key], %[key], 1\n\t"
"beq %[key], zero, 1f\n\t"
"rdctl %[key], status\n\t"
"ori %[key], %[key], 1\n\t"
"wrctl status, %[key]\n\t"
"1:\n\t"
: [key] "+r" (key)
: : "memory");
#else
_nios2_creg_write(NIOS2_CR_STATUS, key);
__asm__ volatile (
"wrctl status, %[key]"
: : [key] "r" (key)
: "memory");
#endif
}