diff options
author | Hyungwoo Yang <hyungwoo.yang@intel.com> | 2018-10-29 10:16:28 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-12-23 19:19:34 -0800 |
commit | db9a02ec4110769b7300f45ade770205e70934de (patch) | |
tree | 3b0b45c037f3afc0b4306fa009539be2fbdb4c1c | |
parent | 90b6c047fbfc50b6c85b5a0fd85482b50b131b86 (diff) | |
download | chrome-ec-db9a02ec4110769b7300f45ade770205e70934de.tar.gz |
core/minute-ia: fix atomics
this fixes a few wrong implementation on atomic.
atomic_read_clear() and atomic_clear() were functinally
broken. Due to this, key control flow which rely on these
functions were out of order.
Also modified ATOMIC_OP() and bool_compare_and_swap_u32()
to give more accurate directives to compiler.
BUG=b:119628522
BRANCH=none
TEST=tested on atlas
Change-Id: Ide8397e4f7b754a7094c66326ecc2450ef2f0cc9
Reviewed-on: https://chromium-review.googlesource.com/1305118
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Hyungwoo Yang <hyungwoo.yang@intel.com>
Reviewed-by: Caveh Jalali <caveh@google.com>
Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r-- | core/minute-ia/atomic.h | 29 |
1 files changed, 13 insertions, 16 deletions
diff --git a/core/minute-ia/atomic.h b/core/minute-ia/atomic.h index 696120ae1d..08f0888cdf 100644 --- a/core/minute-ia/atomic.h +++ b/core/minute-ia/atomic.h @@ -13,9 +13,9 @@ #define ATOMIC_OP(asm_op, a, v) do { \ __asm__ __volatile__ ( \ - "lock;" #asm_op " %0, %1\n" \ - : \ - : "r" (v), "m" (*a) \ + "lock;" #asm_op " %1, %0\n" \ + : "+m" (*a) \ + : "ir" (v) \ : "memory"); \ } while (0) @@ -24,10 +24,10 @@ static inline int bool_compare_and_swap_u32(uint32_t *var, uint32_t old_value, { uint32_t _old_value = old_value; - __asm__ __volatile__("cmpxchg %1, %2\n" - : "=a"(old_value) - : "r"(new_value), "m"(*var), "a" (old_value) - : "memory"); + __asm__ __volatile__("lock; cmpxchgl %2, %1" + : "=a" (old_value), "+m" (*var) + : "r" (new_value), "0" (old_value) + : "memory"); return (_old_value == old_value); } @@ -44,7 +44,7 @@ static inline void atomic_and_u8(uint8_t *addr, uint8_t bits) static inline void atomic_clear(uint32_t volatile *addr, uint32_t bits) { - ATOMIC_OP(btr, addr, bits >> 1); + ATOMIC_OP(andl, addr, ~bits); } static inline void atomic_or(uint32_t volatile *addr, uint32_t bits) @@ -69,19 +69,16 @@ static inline void atomic_sub(uint32_t volatile *addr, uint32_t value) static inline uint32_t atomic_read_clear(uint32_t volatile *addr) { - int loc = 0; + int ret = 0; if (*addr == 0) return 0; - asm volatile("bsr %1, %0\n" - "lock; btr %0, %1\n" - : "=&r" (loc) - : "m" (*addr) - : "memory" - ); + asm volatile("lock; xchgl %0, %1\n" + : "+r" (ret), "+m" (*addr) + : : "memory", "cc"); - return (1 << loc); + return ret; } #endif /* __CROS_EC_ATOMIC_H */ |