From: Stefano Stabellini <sstabellini@kernel.org>
To: Julien Grall <julien@xen.org>
Cc: xen-devel@lists.xenproject.org,
"Julien Grall" <jgrall@amazon.com>,
"Stefano Stabellini" <sstabellini@kernel.org>,
"Volodymyr Babchuk" <Volodymyr_Babchuk@epam.com>,
"Jan Beulich" <jbeulich@suse.com>,
"Andrew Cooper" <andrew.cooper3@citrix.com>,
"Wei Liu" <wl@xen.org>, "Roger Pau Monné" <roger.pau@citrix.com>,
"Oleksandr Tyshchenko" <oleksandr_tyshchenko@epam.com>
Subject: Re: [PATCH] xen: Introduce cmpxchg64() and guest_cmpxchg64()
Date: Mon, 17 Aug 2020 15:56:23 -0700 (PDT) [thread overview]
Message-ID: <alpine.DEB.2.21.2008171327020.15985@sstabellini-ThinkPad-T480s> (raw)
In-Reply-To: <20200815172143.1327-1-julien@xen.org>
On Sat, 15 Aug 2020, Julien Grall wrote:
> From: Julien Grall <jgrall@amazon.com>
>
> The IOREQ code is using cmpxchg() with 64-bit value. At the moment, this
> is x86 code, but there is plan to make it common.
>
> To cater 32-bit arch, introduce two new helpers to deal with 64-bit
> cmpxchg.
>
> The Arm 32-bit implementation of cmpxchg64() is based on the __cmpxchg64
> in Linux v5.8 (arch/arm/include/asm/cmpxchg.h).
>
> Signed-off-by: Julien Grall <jgrall@amazon.com>
> Cc: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
> ---
> xen/include/asm-arm/arm32/cmpxchg.h | 68 +++++++++++++++++++++++++++++
> xen/include/asm-arm/arm64/cmpxchg.h | 5 +++
> xen/include/asm-arm/guest_atomics.h | 22 ++++++++++
> xen/include/asm-x86/guest_atomics.h | 2 +
> xen/include/asm-x86/x86_64/system.h | 2 +
> 5 files changed, 99 insertions(+)
>
> diff --git a/xen/include/asm-arm/arm32/cmpxchg.h b/xen/include/asm-arm/arm32/cmpxchg.h
> index 0770f272ee99..5e2fa6ee38a0 100644
> --- a/xen/include/asm-arm/arm32/cmpxchg.h
> +++ b/xen/include/asm-arm/arm32/cmpxchg.h
> @@ -87,6 +87,38 @@ __CMPXCHG_CASE(b, 1)
> __CMPXCHG_CASE(h, 2)
> __CMPXCHG_CASE( , 4)
>
> +static inline bool __cmpxchg_case_8(volatile uint64_t *ptr,
> + uint64_t *old,
> + uint64_t new,
> + bool timeout,
> + unsigned int max_try)
> +{
> + uint64_t oldval;
> + uint64_t res;
> +
> + do {
> + asm volatile(
> + " ldrexd %1, %H1, [%3]\n"
> + " teq %1, %4\n"
> + " teqeq %H1, %H4\n"
> + " movne %0, #0\n"
> + " movne %H0, #0\n"
> + " bne 2f\n"
> + " strexd %0, %5, %H5, [%3]\n"
> + " teq %0, #0\n"
Apologies if I am misreading this code, but this last "teq" instruction
doesn't seem to be useful?
> + "2:"
> + : "=&r" (res), "=&r" (oldval), "+Qo" (*ptr)
^ not used ?
> + : "r" (ptr), "r" (*old), "r" (new)
> + : "memory", "cc");
> + if (!res)
> + break;
> + } while (!timeout || ((--max_try) > 0));
> +
> + *old = oldval;
> +
> + return !res;
> +}
> +
> static always_inline bool __int_cmpxchg(volatile void *ptr, unsigned long *old,
> unsigned long new, int size,
> bool timeout, unsigned int max_try)
> @@ -156,6 +188,30 @@ static always_inline bool __cmpxchg_mb_timeout(volatile void *ptr,
> return ret;
> }
>
> +/*
> + * The helper may fail to update the memory if the action takes too long.
> + *
> + * @old: On call the value pointed contains the expected old value. It will be
> + * updated to the actual old value.
> + * @max_try: Maximum number of iterations
> + *
> + * The helper will return true when the update has succeeded (i.e no
> + * timeout) and false if the update has failed.
> + */
> +static always_inline bool __cmpxchg64_mb_timeout(volatile uint64_t *ptr,
> + uint64_t *old,
> + uint64_t new,
> + unsigned int max_try)
> +{
> + bool ret;
> +
> + smp_mb();
> + ret = __cmpxchg_case_8(ptr, old, new, true, max_try);
> + smp_mb();
> +
> + return ret;
> +}
> +
> #define cmpxchg(ptr,o,n) \
> ((__typeof__(*(ptr)))__cmpxchg_mb((ptr), \
> (unsigned long)(o), \
> @@ -167,6 +223,18 @@ static always_inline bool __cmpxchg_mb_timeout(volatile void *ptr,
> (unsigned long)(o), \
> (unsigned long)(n), \
> sizeof(*(ptr))))
> +
> +static inline uint64_t cmpxchg64(volatile uint64_t *ptr,
> + uint64_t old,
> + uint64_t new)
> +{
> + smp_mb();
I was looking at the existing code I noticed that we don't have a
corresponding smp_mb(); in this position. Is it needed here because of
the 64bit-ness?
> + if (!__cmpxchg_case_8(ptr, &old, new, false, 0))
> + ASSERT_UNREACHABLE();
> +
> + return old;
> +}
> +
> #endif
> /*
> * Local variables:
> diff --git a/xen/include/asm-arm/arm64/cmpxchg.h b/xen/include/asm-arm/arm64/cmpxchg.h
> index fc5c60f0bd74..de9cd0ee2b07 100644
> --- a/xen/include/asm-arm/arm64/cmpxchg.h
> +++ b/xen/include/asm-arm/arm64/cmpxchg.h
> @@ -187,6 +187,11 @@ static always_inline bool __cmpxchg_mb_timeout(volatile void *ptr,
> __ret; \
> })
>
> +#define cmpxchg64(ptr, o, n) cmpxchg(ptr, o, n)
> +
> +#define __cmpxchg64_mb_timeout(ptr, old, new, max_try) \
> + __cmpxchg_mb_timeout(ptr, old, new, 8, max_try)
> +
> #endif
> /*
> * Local variables:
> diff --git a/xen/include/asm-arm/guest_atomics.h b/xen/include/asm-arm/guest_atomics.h
> index af27cc627bf3..28ce402bea79 100644
> --- a/xen/include/asm-arm/guest_atomics.h
> +++ b/xen/include/asm-arm/guest_atomics.h
> @@ -115,6 +115,28 @@ static inline unsigned long __guest_cmpxchg(struct domain *d,
> (unsigned long)(n),\
> sizeof (*(ptr))))
>
> +static inline uint64_t guest_cmpxchg64(struct domain *d,
> + volatile uint64_t *ptr,
> + uint64_t old,
> + uint64_t new)
> +{
> + uint64_t oldval = old;
> +
> + perfc_incr(atomics_guest);
> +
> + if ( __cmpxchg64_mb_timeout(ptr, &oldval, new,
> + this_cpu(guest_safe_atomic_max)) )
> + return oldval;
> +
> + perfc_incr(atomics_guest_paused);
> +
> + domain_pause_nosync(d);
> + oldval = cmpxchg64(ptr, old, new);
> + domain_unpause(d);
> +
> + return oldval;
> +}
> +
> #endif /* _ARM_GUEST_ATOMICS_H */
> /*
> * Local variables:
> diff --git a/xen/include/asm-x86/guest_atomics.h b/xen/include/asm-x86/guest_atomics.h
> index 029417c8ffc1..f4de9d3631ff 100644
> --- a/xen/include/asm-x86/guest_atomics.h
> +++ b/xen/include/asm-x86/guest_atomics.h
> @@ -20,6 +20,8 @@
> ((void)(d), test_and_change_bit(nr, p))
>
> #define guest_cmpxchg(d, ptr, o, n) ((void)(d), cmpxchg(ptr, o, n))
> +#define guest_cmpxchg64(d, ptr, o, n) ((void)(d), cmpxchg64(ptr, o, n))
> +
>
> #endif /* _X86_GUEST_ATOMICS_H */
> /*
> diff --git a/xen/include/asm-x86/x86_64/system.h b/xen/include/asm-x86/x86_64/system.h
> index f471859c19cc..c1b16105e9f2 100644
> --- a/xen/include/asm-x86/x86_64/system.h
> +++ b/xen/include/asm-x86/x86_64/system.h
> @@ -5,6 +5,8 @@
> ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o), \
> (unsigned long)(n),sizeof(*(ptr))))
>
> +#define cmpxchg64(ptr, o, n) cmpxchg(ptr, o, n)
> +
> /*
> * Atomic 16 bytes compare and exchange. Compare OLD with MEM, if
> * identical, store NEW in MEM. Return the initial value in MEM.
> --
> 2.17.1
>
next prev parent reply other threads:[~2020-08-17 22:56 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-15 17:21 [PATCH] xen: Introduce cmpxchg64() and guest_cmpxchg64() Julien Grall
2020-08-16 19:26 ` Oleksandr
2020-08-17 9:24 ` Roger Pau Monné
2020-08-17 9:42 ` Julien Grall
2020-08-17 10:33 ` Roger Pau Monné
2020-08-17 11:05 ` Julien Grall
2020-08-17 11:50 ` Roger Pau Monné
2020-08-17 13:03 ` Julien Grall
2020-08-17 14:20 ` Roger Pau Monné
2020-08-19 9:22 ` Jan Beulich
2020-08-20 9:14 ` Julien Grall
2020-08-20 9:25 ` Jan Beulich
2020-08-20 9:34 ` Julien Grall
2020-08-19 9:18 ` Jan Beulich
2020-08-17 22:56 ` Stefano Stabellini [this message]
2020-08-18 10:30 ` Julien Grall
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.DEB.2.21.2008171327020.15985@sstabellini-ThinkPad-T480s \
--to=sstabellini@kernel.org \
--cc=Volodymyr_Babchuk@epam.com \
--cc=andrew.cooper3@citrix.com \
--cc=jbeulich@suse.com \
--cc=jgrall@amazon.com \
--cc=julien@xen.org \
--cc=oleksandr_tyshchenko@epam.com \
--cc=roger.pau@citrix.com \
--cc=wl@xen.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).