From 36e2fd0139b9e1a69cffb0766dee5651ec63e8f3 Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Wed, 7 Jan 2015 16:36:11 +0000 Subject: [PATCH] Prevent optimisation of sysregs accessors calls Calls to system register read accessors functions may be optimised out by the compiler if called twice in a row for the same register. This is because the compiler is not aware that the result from the instruction may be modified by external agents. Therefore, if nothing modifies the register between the 2 reads as far as the compiler knows then it might consider that it is useless to read it twice and emit only 1 call. This behaviour is faulty for registers that may not have the same value if read twice in succession. E.g.: counters, timer control/countdown registers, GICv3 interrupt status registers and so on. The same problem happens for calls to system register write accessors functions. The compiler might optimise out some calls if it considers that it will produce the same result. Again, this behaviour is faulty for cases where intermediate writes to these registers make a difference in the system. This patch fixes the problem by making these assembly register accesses volatile. Fixes ARM-software/tf-issues#273 Change-Id: I33903bc4cc4eea8a8d87bc2c757909fbb0138925 --- include/lib/aarch64/arch_helpers.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h index d431baaf8..7320a0af4 100644 --- a/include/lib/aarch64/arch_helpers.h +++ b/include/lib/aarch64/arch_helpers.h @@ -40,24 +40,24 @@ * registers *********************************************************************/ -#define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ -static inline uint64_t read_ ## _name(void) \ -{ \ - uint64_t v; \ - __asm__ ("mrs %0, " #_reg_name : "=r" (v)); \ - return v; \ +#define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ +static inline uint64_t read_ ## _name(void) \ +{ \ + uint64_t v; \ + __asm__ volatile ("mrs %0, " #_reg_name : "=r" (v)); \ + return v; \ } -#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \ -static inline void write_ ## _name(uint64_t v) \ -{ \ - __asm__ ("msr " #_reg_name ", %0" : : "r" (v)); \ +#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \ +static inline void write_ ## _name(uint64_t v) \ +{ \ + __asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v)); \ } #define _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _reg_name) \ -static inline void write_ ## _name(const uint64_t v) \ -{ \ - __asm__ ("msr " #_reg_name ", %0" : : "i" (v)); \ +static inline void write_ ## _name(const uint64_t v) \ +{ \ + __asm__ volatile ("msr " #_reg_name ", %0" : : "i" (v)); \ } /* Define read function for system register */