Commit 36e2fd01 authored by Sandrine Bailleux's avatar Sandrine Bailleux
Browse files

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
parent 29e32cba
...@@ -44,20 +44,20 @@ ...@@ -44,20 +44,20 @@
static inline uint64_t read_ ## _name(void) \ static inline uint64_t read_ ## _name(void) \
{ \ { \
uint64_t v; \ uint64_t v; \
__asm__ ("mrs %0, " #_reg_name : "=r" (v)); \ __asm__ volatile ("mrs %0, " #_reg_name : "=r" (v)); \
return v; \ return v; \
} }
#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \ #define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \
static inline void write_ ## _name(uint64_t v) \ static inline void write_ ## _name(uint64_t v) \
{ \ { \
__asm__ ("msr " #_reg_name ", %0" : : "r" (v)); \ __asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v)); \
} }
#define _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _reg_name) \ #define _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _reg_name) \
static inline void write_ ## _name(const uint64_t v) \ static inline void write_ ## _name(const uint64_t v) \
{ \ { \
__asm__ ("msr " #_reg_name ", %0" : : "i" (v)); \ __asm__ volatile ("msr " #_reg_name ", %0" : : "i" (v)); \
} }
/* Define read function for system register */ /* Define read function for system register */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment