Thread (18 messages) 18 messages, 3 authors, 2019-08-28

Re: [PATCH v3 2/5] arm64: Use correct ll/sc atomic constraints

From: Mark Rutland <mark.rutland@arm.com>
Date: 2019-08-22 15:32:33

Hi Andrew,

On Mon, Aug 12, 2019 at 03:36:22PM +0100, Andrew Murray wrote:
For many of the ll/sc atomic operations we use the 'I' machine constraint
regardless to the instruction used - this may not be optimal.

Let's add an additional parameter to the ATOMIC_xx macros that allows the
caller to specify an appropriate machine constraint.

Let's also improve __CMPXCHG_CASE by replacing the 'K' constraint with a
caller provided constraint. Please note that whilst we would like to use
the 'K' constraint on 32 bit operations, we choose not to provide any
constraint to avoid a GCC bug which results in a build error.

Earlier versions of GCC (no later than 8.1.0) appear to incorrectly handle
the 'K' constraint for the value 4294967295.
From reading the above, it's difficult to discern what's a fix and
what's an improvement, and I think we need to be more explicit about
that. It would also be helpful to have the necessary context up-front.

How about:

| The A64 ISA accepts distinct (but overlapping) ranges of immediates for:
| 
| * add arithmetic instructions ('I' machine constraint)
| * sub arithmetic instructions ('J' machine constraint)
| * 32-bit logical instructions ('K' machine constraint)
| * 64-bit logical instructions ('L' machine constraint)
| 
| ... but we currently use the 'I' constraint for many atomic operations
| using sub or logical instructions, which is not always valid.
| 
| When CONFIG_ARM64_LSE_ATOMICS is not set, this allows invalid immediates
| to be passed to instructions, potentially resulting in a build failure.
| When CONFIG_ARM64_LSE_ATOMICS is selected the out-of-line ll/sc atomics
| always use a register as they have no visibility of the value passed by
| the caller.
|
| This patch adds a constraint parameter to the ATOMIC_xx and
| __CMPXCHG_CASE macros so that we can pass appropriate constraints for
| each case, with uses updated accordingly.
| 
| Unfortunately prior to GCC 8.1.0 the 'K' constraint erroneously accepted
| 0xffffffff, so we must instead force the use of a register.
 
Given we haven't had any bug reports, I'm not sure whether this needs a
Fixes tag or Cc stable. This has been a latent issue for a long time,
but upstream code doesn't seem to have tickled it.

[...]
-ATOMIC_OPS(and, and)
-ATOMIC_OPS(andnot, bic)
-ATOMIC_OPS(or, orr)
-ATOMIC_OPS(xor, eor)
+ATOMIC_OPS(and, and, K)
+ATOMIC_OPS(andnot, bic, )
+ATOMIC_OPS(or, orr, K)
+ATOMIC_OPS(xor, eor, K)
Surely it's not safe to use the K constraint here, either? AFAICT code
like:

  atomic_xor(~0, &atom);

... would suffer from the same problem as described for cmpxchg.

[...]
-ATOMIC64_OPS(and, and)
-ATOMIC64_OPS(andnot, bic)
-ATOMIC64_OPS(or, orr)
-ATOMIC64_OPS(xor, eor)
+ATOMIC64_OPS(and, and, K)
+ATOMIC64_OPS(andnot, bic, )
+ATOMIC64_OPS(or, orr, K)
+ATOMIC64_OPS(xor, eor, K)
Shouldn't these be 'L'?

IIUC K is a subset of L, so if that's deliberate we should call that out
explicitly...
+__CMPXCHG_CASE(w, b,     ,  8,        ,  ,  ,         , )
+__CMPXCHG_CASE(w, h,     , 16,        ,  ,  ,         , )
+__CMPXCHG_CASE(w,  ,     , 32,        ,  ,  ,         , )
+__CMPXCHG_CASE( ,  ,     , 64,        ,  ,  ,         , L)
+__CMPXCHG_CASE(w, b, acq_,  8,        , a,  , "memory", )
+__CMPXCHG_CASE(w, h, acq_, 16,        , a,  , "memory", )
+__CMPXCHG_CASE(w,  , acq_, 32,        , a,  , "memory", )
+__CMPXCHG_CASE( ,  , acq_, 64,        , a,  , "memory", L)
+__CMPXCHG_CASE(w, b, rel_,  8,        ,  , l, "memory", )
+__CMPXCHG_CASE(w, h, rel_, 16,        ,  , l, "memory", )
+__CMPXCHG_CASE(w,  , rel_, 32,        ,  , l, "memory", )
+__CMPXCHG_CASE( ,  , rel_, 64,        ,  , l, "memory", L)
+__CMPXCHG_CASE(w, b,  mb_,  8, dmb ish,  , l, "memory", )
+__CMPXCHG_CASE(w, h,  mb_, 16, dmb ish,  , l, "memory", )
+__CMPXCHG_CASE(w,  ,  mb_, 32, dmb ish,  , l, "memory", )
+__CMPXCHG_CASE( ,  ,  mb_, 64, dmb ish,  , l, "memory", L)
... but these uses imply that's not the case.

Otherwise this looks good to me.

Thanks,
Mark.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help