From: Julien Grall Date: Sat, 2 May 2020 15:39:58 +0000 (+0100) Subject: xen/arm: atomic: Rewrite write_atomic() X-Git-Tag: archive/raspbian/4.14.0+80-gd101b417b7-1+rpi1^2~63^2~287 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=52ffcfb73997e43717fa05802acc4503483d2d71;p=xen.git xen/arm: atomic: Rewrite write_atomic() The current implementation of write_atomic has two issues: 1) It cannot be used to write pointer value because the switch contains cast to other size than the size of the pointer. 2) It will happily allow to write to a pointer to const. Additionally, the Arm implementation is returning a value when the x86 implementation does not anymore. This was introduced in commit 2934148a0773 "x86: simplify a few macros / inline functions". There are no users of the return value, so it is fine to drop it. The switch is now moved in a static inline helper allowing the compiler to prevent use of const pointer and also allow to write pointer value. Signed-off-by: Julien Grall Reviewed-by: Stefano Stabellini --- diff --git a/xen/include/asm-arm/atomic.h b/xen/include/asm-arm/atomic.h index 3c3d6bb04e..ac2798d095 100644 --- a/xen/include/asm-arm/atomic.h +++ b/xen/include/asm-arm/atomic.h @@ -98,23 +98,41 @@ static always_inline void read_atomic_size(const volatile void *p, } } +static always_inline void write_atomic_size(volatile void *p, + void *val, + unsigned int size) +{ + switch ( size ) + { + case 1: + write_u8_atomic(p, *(uint8_t *)val); + break; + case 2: + write_u16_atomic(p, *(uint16_t *)val); + break; + case 4: + write_u32_atomic(p, *(uint32_t *)val); + break; + case 8: + write_u64_atomic(p, *(uint64_t *)val); + break; + default: + __bad_atomic_size(); + break; + } +} + #define read_atomic(p) ({ \ union { typeof(*p) val; char c[0]; } x_; \ read_atomic_size(p, x_.c, sizeof(*p)); \ x_.val; \ }) -#define write_atomic(p, x) ({ \ - typeof(*p) __x = (x); \ - switch ( sizeof(*p) ) { \ - case 1: write_u8_atomic((uint8_t *)p, (uint8_t)__x); break; \ - case 2: write_u16_atomic((uint16_t *)p, (uint16_t)__x); break; \ - case 4: write_u32_atomic((uint32_t *)p, (uint32_t)__x); break; \ - case 8: write_u64_atomic((uint64_t *)p, (uint64_t)__x); break; \ - default: __bad_atomic_size(); break; \ - } \ - __x; \ -}) +#define write_atomic(p, x) \ + do { \ + typeof(*p) x_ = (x); \ + write_atomic_size(p, &x_, sizeof(*p)); \ + } while ( false ) #define add_sized(p, x) ({ \ typeof(*(p)) __x = (x); \