From 18928e7f60e5458387d59d725e36c5421c4e68c0 Mon Sep 17 00:00:00 2001 From: Andrew Boie Date: Fri, 2 Dec 2016 14:04:47 -0800 Subject: 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 15bc537712abaeb5dfbb27ced924fe6ccc1f611c for the ARM fix for a complete description of the issue and fix. Change-Id: I1d96fe0088d90150f0888c2893d017155fc0a0a7 Signed-off-by: Andrew Boie (cherry picked from commit bba445b31ff2ed815a1953d3d74d0daca1d7e993) --- include/arch/nios2/arch.h | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/include/arch/nios2/arch.h b/include/arch/nios2/arch.h index 7a98c1524..cc33f2a95 100644 --- a/include/arch/nios2/arch.h +++ b/include/arch/nios2/arch.h @@ -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 } -- cgit v1.2.3