[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH for-4.14 1/3] xen/arm: atomic: Allow read_atomic() to be used in more cases
On Sat, 2 May 2020, Julien Grall wrote: > From: Julien Grall <jgrall@xxxxxxxxxx> > > The current implementation of read_atomic() on Arm will not allow to: > 1) Read a value from a pointer to const because the temporary > variable will be const and therefore it is not possible to assign > any value. This can be solved by using a union between the type and > a char[0]. > 2) Read a pointer value (e.g void *) because the switch contains > cast from other type than the size of a pointer. This can be solved by > by introducing a static inline for the switch and use void * for the > pointer. > > Reported-by: Juergen Gross <jgross@xxxxxxxx> > Signed-off-by: Julien Grall <jgrall@xxxxxxxxxx> > --- > xen/include/asm-arm/atomic.h | 37 +++++++++++++++++++++++++++--------- > 1 file changed, 28 insertions(+), 9 deletions(-) > > diff --git a/xen/include/asm-arm/atomic.h b/xen/include/asm-arm/atomic.h > index e81bf80e305c..3c3d6bb04ee8 100644 > --- a/xen/include/asm-arm/atomic.h > +++ b/xen/include/asm-arm/atomic.h > @@ -71,18 +71,37 @@ build_add_sized(add_u32_sized, "", WORD, uint32_t) > #undef build_atomic_write > #undef build_add_sized > > +void __bad_atomic_read(const volatile void *p, void *res); > void __bad_atomic_size(void); > > +static always_inline void read_atomic_size(const volatile void *p, > + void *res, > + unsigned int size) > +{ > + switch ( size ) > + { > + case 1: > + *(uint8_t *)res = read_u8_atomic(p); > + break; > + case 2: > + *(uint16_t *)res = read_u16_atomic(p); > + break; > + case 4: > + *(uint32_t *)res = read_u32_atomic(p); > + break; > + case 8: > + *(uint64_t *)res = read_u64_atomic(p); > + break; > + default: > + __bad_atomic_read(p, res); > + break; > + } > +} > + > #define read_atomic(p) ({ \ > - typeof(*p) __x; \ > - switch ( sizeof(*p) ) { \ > - case 1: __x = (typeof(*p))read_u8_atomic((uint8_t *)p); break; \ > - case 2: __x = (typeof(*p))read_u16_atomic((uint16_t *)p); break; \ > - case 4: __x = (typeof(*p))read_u32_atomic((uint32_t *)p); break; \ > - case 8: __x = (typeof(*p))read_u64_atomic((uint64_t *)p); break; \ > - default: __x = 0; __bad_atomic_size(); break; \ > - } \ > - __x; \ > + union { typeof(*p) val; char c[0]; } x_; \ > + read_atomic_size(p, x_.c, sizeof(*p)); \ Wouldn't it be better to pass x_ as follows: read_atomic_size(p, &x_, sizeof(*p)); ? In my tests both ways works. I prefer the version with &x_ but given that it works either way: Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx> > + x_.val; \ > }) > > #define write_atomic(p, x) ({ \ > -- > 2.17.1 >
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |