From db9a02ec4110769b7300f45ade770205e70934de Mon Sep 17 00:00:00 2001 From: Hyungwoo Yang Date: Mon, 29 Oct 2018 10:16:28 -0700 Subject: 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 Tested-by: Hyungwoo Yang Reviewed-by: Caveh Jalali Reviewed-by: Jett Rink --- core/minute-ia/atomic.h | 29 +++++++++++++---------------- 1 file 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 */ -- cgit v1.2.1