On Thu, Nov 18, 2021 at 06:46:48PM +0000, Alex Bennée wrote: > This adds a framework for adding simple barrier litmus tests against > ARM. The litmus tests aren't as comprehensive as the academic exercises > which will attempt to do all sorts of things to keep racing CPUs synced > up. These tests do honour the "sync" parameter to do a poor-mans > equivalent. > > The two litmus tests are: > - message passing > - store-after-load > > They both have case that should fail (although won't on single-threaded > TCG setups). If barriers aren't working properly the store-after-load > test will fail even on an x86 backend as x86 allows re-ording of non > aliased stores. > > I've imported a few more of the barrier primatives from the Linux source > tree so we consistently use macros. > > The arm64 barrier primitives trip up on -Wstrict-aliasing so this is > disabled in the Makefile. > > Signed-off-by: Alex Bennée <alex.bennee@xxxxxxxxxx> > CC: Will Deacon <will@xxxxxxxxxx> > > --- > v8 > - move to mttcgtests.cfg > - fix checkpatch issues > - fix report usage > v7 > - merge in store-after-load > - clean-up sync-up code > - use new counter api > - fix xfail for sal test > v6 > - add a unittest.cfg > - -fno-strict-aliasing > --- > arm/Makefile.common | 1 + > lib/arm/asm/barrier.h | 61 ++++++ > lib/arm64/asm/barrier.h | 50 +++++ > arm/barrier-litmus-test.c | 450 ++++++++++++++++++++++++++++++++++++++ > arm/mttcgtests.cfg | 33 +++ > 5 files changed, 595 insertions(+) > create mode 100644 arm/barrier-litmus-test.c > > diff --git a/arm/Makefile.common b/arm/Makefile.common > index f905971..861e5c7 100644 > --- a/arm/Makefile.common > +++ b/arm/Makefile.common > @@ -13,6 +13,7 @@ tests-common += $(TEST_DIR)/sieve.flat > tests-common += $(TEST_DIR)/pl031.flat > tests-common += $(TEST_DIR)/tlbflush-code.flat > tests-common += $(TEST_DIR)/locking-test.flat > +tests-common += $(TEST_DIR)/barrier-litmus-test.flat > > tests-all = $(tests-common) $(tests) > all: directories $(tests-all) > diff --git a/lib/arm/asm/barrier.h b/lib/arm/asm/barrier.h > index 7f86831..2870080 100644 > --- a/lib/arm/asm/barrier.h > +++ b/lib/arm/asm/barrier.h > @@ -8,6 +8,8 @@ > * This work is licensed under the terms of the GNU GPL, version 2. > */ > > +#include <stdint.h> > + > #define sev() asm volatile("sev" : : : "memory") > #define wfe() asm volatile("wfe" : : : "memory") > #define wfi() asm volatile("wfi" : : : "memory") > @@ -25,4 +27,63 @@ > #define smp_rmb() smp_mb() > #define smp_wmb() dmb(ishst) > > +extern void abort(void); > + > +static inline void __write_once_size(volatile void *p, void *res, int size) > +{ > + switch (size) { > + case 1: *(volatile uint8_t *)p = *(uint8_t *)res; break; > + case 2: *(volatile uint16_t *)p = *(uint16_t *)res; break; > + case 4: *(volatile uint32_t *)p = *(uint32_t *)res; break; > + case 8: *(volatile uint64_t *)p = *(uint64_t *)res; break; > + default: > + /* unhandled case */ > + abort(); > + } > +} > + > +#define WRITE_ONCE(x, val) \ > +({ \ > + union { typeof(x) __val; char __c[1]; } __u = \ > + { .__val = (typeof(x)) (val) }; \ > + __write_once_size(&(x), __u.__c, sizeof(x)); \ > + __u.__val; \ > +}) > + > +#define smp_store_release(p, v) \ > +do { \ > + smp_mb(); \ > + WRITE_ONCE(*p, v); \ > +} while (0) > + > + > +static inline > +void __read_once_size(const volatile void *p, void *res, int size) > +{ > + switch (size) { > + case 1: *(uint8_t *)res = *(volatile uint8_t *)p; break; > + case 2: *(uint16_t *)res = *(volatile uint16_t *)p; break; > + case 4: *(uint32_t *)res = *(volatile uint32_t *)p; break; > + case 8: *(uint64_t *)res = *(volatile uint64_t *)p; break; > + default: > + /* unhandled case */ > + abort(); > + } > +} > + > +#define READ_ONCE(x) \ > +({ \ > + union { typeof(x) __val; char __c[1]; } __u; \ > + __read_once_size(&(x), __u.__c, sizeof(x)); \ > + __u.__val; \ > +}) WRITE_ONCE and READ_ONCE are already defined in lib/linux/compiler.h Thanks, drew