From b875108cd0388aed17d8ce3889659cb49db3cbde Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Fri, 16 Apr 2021 16:07:11 +0200 Subject: [PATCH] Add R/W memory and instruction barrier after mstatus access Fast subsequent reads and writes to the mstatus csr lead to illegal instruction exceptions on the nucleisys bumblee core of the gd32vf103. This behavior only occurred in high load situations e.g. interrupt frequency of 5khz but reliably let to these errors. Adding the instruction and memory barriers solved the problem. There is some negligible performance impact. --- os/common/ports/RISCV-ECLIC/chcore.h | 26 ++++++++++++++----- .../RISCV-ECLIC/compilers/GCC/chcoreasm.S | 20 +++++++++----- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/os/common/ports/RISCV-ECLIC/chcore.h b/os/common/ports/RISCV-ECLIC/chcore.h index 83d982ab8d..03285efb9b 100644 --- a/os/common/ports/RISCV-ECLIC/chcore.h +++ b/os/common/ports/RISCV-ECLIC/chcore.h @@ -377,7 +377,9 @@ static inline void port_init(void) {} * @return The interrupts status. */ static inline syssts_t port_get_irq_status(void) { - return (syssts_t)__RV_CSR_READ(CSR_MSTATUS); + syssts_t mstatus = __RV_CSR_READ(CSR_MSTATUS); + __RWMB(); + return mstatus; } /** @@ -399,7 +401,9 @@ static inline bool port_irq_enabled(syssts_t sts) { return sts & MSTATUS_MIE; } * @retval true running in ISR mode. */ static inline bool port_is_isr_context(void) { - return __RV_CSR_READ(CSR_MSUBM) & MSUBM_TYP; + bool is_irq_context = (__RV_CSR_READ(CSR_MSUBM) & MSUBM_TYP) != 0; + __RWMB(); + return is_irq_context; } /** @@ -407,14 +411,22 @@ static inline bool port_is_isr_context(void) { * @details Usually this function just disables interrupts but may perform more * actions. */ -static inline void port_lock(void) { __disable_irq(); } +static inline void port_lock(void) { + __disable_irq(); + __RWMB(); + __FENCE_I(); +} /** * @brief Kernel-unlock action. * @details Usually this function just enables interrupts but may perform more * actions. */ -static inline void port_unlock(void) { __enable_irq(); } +static inline void port_unlock(void) { + __enable_irq(); + __RWMB(); + __FENCE_I(); +} /** * @brief Kernel-lock action from an interrupt handler. @@ -436,18 +448,18 @@ static inline void port_unlock_from_isr(void) { port_unlock(); } * @brief Disables all the interrupt sources. * @note Of course non-maskable interrupt sources are not included. */ -static inline void port_disable(void) { __disable_irq(); } +static inline void port_disable(void) { port_lock(); } /** * @brief Disables the interrupt sources below kernel-level priority. * @note Interrupt sources above kernel level remains enabled. */ -static inline void port_suspend(void) { __disable_irq(); } +static inline void port_suspend(void) { port_lock(); } /** * @brief Enables all the interrupt sources. */ -static inline void port_enable(void) { __enable_irq(); } +static inline void port_enable(void) { port_unlock(); } /** * @details The function is meant to return when an interrupt becomes pending. diff --git a/os/common/ports/RISCV-ECLIC/compilers/GCC/chcoreasm.S b/os/common/ports/RISCV-ECLIC/compilers/GCC/chcoreasm.S index 2625fa9125..2794328289 100644 --- a/os/common/ports/RISCV-ECLIC/compilers/GCC/chcoreasm.S +++ b/os/common/ports/RISCV-ECLIC/compilers/GCC/chcoreasm.S @@ -56,26 +56,34 @@ # Disable Interrupts globally. .macro DISABLE_MIE - csrc CSR_MSTATUS, MSTATUS_MIE + csrc CSR_MSTATUS, MSTATUS_MIE + fence iorw, iorw + fence.i .endm # Enable Interrupts globally. .macro ENABLE_MIE - csrs CSR_MSTATUS, MSTATUS_MIE + csrs CSR_MSTATUS, MSTATUS_MIE + fence iorw, iorw + fence.i .endm # Clear previous machine interrupt enable bit in mstatus (mstatus.mpie). # On machine return (mret) mstatus.mie is assigned this value. # Clearing this bit disables interrupts when leaving interrupt processing mode. .macro DISABLE_MPIE - li a0, MSTATUS_MPIE - csrc CSR_MSTATUS, a0 + li a0, MSTATUS_MPIE + csrc CSR_MSTATUS, a0 + fence iorw, iorw + fence.i .endm # Set previous machine interrupt enable bit in mstatus (mstatus.mpie). .macro ENABLE_MPIE - li a0, MSTATUS_MPIE - csrs CSR_MSTATUS, a0 + li a0, MSTATUS_MPIE + csrs CSR_MSTATUS, a0 + fence iorw, iorw + fence.i .endm # --------------------------------------------------------------------------