qemu-arm
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [kvm-unit-tests PATCH v8 08/10] arm/barrier-litmus-tests: add simple


From: Andrew Jones
Subject: Re: [kvm-unit-tests PATCH v8 08/10] arm/barrier-litmus-tests: add simple mp and sal litmus tests
Date: Wed, 24 Nov 2021 17:14:53 +0100

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@linaro.org>
> CC: Will Deacon <will@kernel.org>
> 
> ---
> 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]