Commit 18928e7f authored by Andrew Boie's avatar Andrew Boie Committed by Anas Nashif
Browse files

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 15bc5377 for the
ARM fix for a complete description of the issue and fix.

Change-Id: I1d96fe0088d90150f0888c2893d017155fc0a0a7
Signed-off-by: default avatarAndrew Boie <andrew.p.boie@intel.com>
(cherry picked from commit bba445b3)
parent d39e0a92
Loading
Loading
Loading
Loading
+21 −14
Original line number Diff line number Diff line
@@ -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
}