From: Jan Beulich <jbeulich@suse.com>
To: Oleksii <oleksii.kurochko@gmail.com>
Cc: Alistair Francis <alistair.francis@wdc.com>,
Bob Eshleman <bobbyeshleman@gmail.com>,
Connor Davis <connojdavis@gmail.com>,
Andrew Cooper <andrew.cooper3@citrix.com>,
George Dunlap <george.dunlap@citrix.com>,
Julien Grall <julien@xen.org>,
Stefano Stabellini <sstabellini@kernel.org>, Wei Liu <wl@xen.org>,
xen-devel@lists.xenproject.org
Subject: Re: [PATCH v5 11/23] xen/riscv: introduce cmpxchg.h
Date: Thu, 7 Mar 2024 11:46:39 +0100 [thread overview]
Message-ID: <dd45b338-7b43-442d-85cd-307b3d228d87@suse.com> (raw)
In-Reply-To: <f6e16589bfbcd94d6f62c34f080cbcd3406eca6f.camel@gmail.com>
On 07.03.2024 11:35, Oleksii wrote:
> On Wed, 2024-03-06 at 15:56 +0100, Jan Beulich wrote:
>> On 26.02.2024 18:38, Oleksii Kurochko wrote:
>>> The header was taken from Linux kernl 6.4.0-rc1.
>>>
>>> Addionally, were updated:
>>> * add emulation of {cmp}xchg for 1/2 byte types using 32-bit atomic
>>> access.
>>> * replace tabs with spaces
>>> * replace __* variale with *__
>>> * introduce generic version of xchg_* and cmpxchg_*.
>>>
>>> Implementation of 4- and 8-byte cases were left as it is done in
>>> Linux kernel as according to the RISC-V spec:
>>> ```
>>> Table A.5 ( only part of the table was copied here )
>>>
>>> Linux Construct RVWMO Mapping
>>> atomic <op> relaxed amo<op>.{w|d}
>>> atomic <op> acquire amo<op>.{w|d}.aq
>>> atomic <op> release amo<op>.{w|d}.rl
>>> atomic <op> amo<op>.{w|d}.aqrl
>>>
>>> Linux Construct RVWMO LR/SC Mapping
>>> atomic <op> relaxed loop: lr.{w|d}; <op>; sc.{w|d}; bnez loop
>>> atomic <op> acquire loop: lr.{w|d}.aq; <op>; sc.{w|d}; bnez loop
>>> atomic <op> release loop: lr.{w|d}; <op>; sc.{w|d}.aqrl∗ ; bnez
>>> loop OR
>>> fence.tso; loop: lr.{w|d}; <op>; sc.{w|d}∗ ;
>>> bnez loop
>>> atomic <op> loop: lr.{w|d}.aq; <op>; sc.{w|d}.aqrl; bnez
>>> loop
>>>
>>> The Linux mappings for release operations may seem stronger than
>>> necessary,
>>> but these mappings are needed to cover some cases in which Linux
>>> requires
>>> stronger orderings than the more intuitive mappings would provide.
>>> In particular, as of the time this text is being written, Linux is
>>> actively
>>> debating whether to require load-load, load-store, and store-store
>>> orderings
>>> between accesses in one critical section and accesses in a
>>> subsequent critical
>>> section in the same hart and protected by the same synchronization
>>> object.
>>> Not all combinations of FENCE RW,W/FENCE R,RW mappings with aq/rl
>>> mappings
>>> combine to provide such orderings.
>>> There are a few ways around this problem, including:
>>> 1. Always use FENCE RW,W/FENCE R,RW, and never use aq/rl. This
>>> suffices
>>> but is undesirable, as it defeats the purpose of the aq/rl
>>> modifiers.
>>> 2. Always use aq/rl, and never use FENCE RW,W/FENCE R,RW. This does
>>> not
>>> currently work due to the lack of load and store opcodes with aq
>>> and rl
>>> modifiers.
>>
>> As before I don't understand this point. Can you give an example of
>> what
>> sort of opcode / instruction is missing?
> If I understand the spec correctly then l{b|h|w|d} and s{b|h|w|d}
> instructions don't have aq or rl annotation.
How would load insns other that LR and store insns other than SC come
into play here?
>>> 3. Strengthen the mappings of release operations such that they
>>> would
>>> enforce sufficient orderings in the presence of either type of
>>> acquire mapping.
>>> This is the currently-recommended solution, and the one shown in
>>> Table A.5.
>>> ```
>>>
>>> But in Linux kenrel atomics were strengthen with fences:
>>> ```
>>> Atomics present the same issue with locking: release and acquire
>>> variants need to be strengthened to meet the constraints defined
>>> by the Linux-kernel memory consistency model [1].
>>>
>>> Atomics present a further issue: implementations of atomics such
>>> as atomic_cmpxchg() and atomic_add_unless() rely on LR/SC pairs,
>>> which do not give full-ordering with .aqrl; for example, current
>>> implementations allow the "lr-sc-aqrl-pair-vs-full-barrier" test
>>> below to end up with the state indicated in the "exists" clause.
>>>
>>> In order to "synchronize" LKMM and RISC-V's implementation, this
>>> commit strengthens the implementations of the atomics operations
>>> by replacing .rl and .aq with the use of ("lightweigth") fences,
>>> and by replacing .aqrl LR/SC pairs in sequences such as:
>>>
>>> 0: lr.w.aqrl %0, %addr
>>> bne %0, %old, 1f
>>> ...
>>> sc.w.aqrl %1, %new, %addr
>>> bnez %1, 0b
>>> 1:
>>>
>>> with sequences of the form:
>>>
>>> 0: lr.w %0, %addr
>>> bne %0, %old, 1f
>>> ...
>>> sc.w.rl %1, %new, %addr /* SC-release */
>>> bnez %1, 0b
>>> fence rw, rw /* "full" fence */
>>> 1:
>>>
>>> following Daniel's suggestion.
>>>
>>> These modifications were validated with simulation of the RISC-V
>>> memory consistency model.
>>>
>>> C lr-sc-aqrl-pair-vs-full-barrier
>>>
>>> {}
>>>
>>> P0(int *x, int *y, atomic_t *u)
>>> {
>>> int r0;
>>> int r1;
>>>
>>> WRITE_ONCE(*x, 1);
>>> r0 = atomic_cmpxchg(u, 0, 1);
>>> r1 = READ_ONCE(*y);
>>> }
>>>
>>> P1(int *x, int *y, atomic_t *v)
>>> {
>>> int r0;
>>> int r1;
>>>
>>> WRITE_ONCE(*y, 1);
>>> r0 = atomic_cmpxchg(v, 0, 1);
>>> r1 = READ_ONCE(*x);
>>> }
>>>
>>> exists (u=1 /\ v=1 /\ 0:r1=0 /\ 1:r1=0)
>>
>> While I'm entirely willing to trust this can happen, I can't bring
>> this
>> in line with the A extension spec.
>>
>> Additionally it's not clear to me in how far all of this applies when
>> you don't really use LR/SC in the 4- and 8-byte cases (and going
>> forward
>> likely also not in the 1- and 2-byte case, utilizing Zahba when
>> available).
> It just explain what combination of fences, lr/sc, amoswap, .aq and .rl
> annotation can be combined, and why combinations introduced in this
> patch are used.
Except that I don't understand that explanation, iow why said combination
of values could be observed even when using suffixes properly.
>>> + uint8_t new_val_pos = ((unsigned long)(ptr) & (0x4 -
>>> sizeof(*ptr))) * BITS_PER_BYTE; \
>>
>> Why uint8_t?
> It is enough to cover possible start bit position of value that should
> be updated, so I decided to use uint8_t.
Please take a look at the "Types" section in ./CODING_STYLE.
>>> + { \
>>> + case 1: \
>>> + case 2: \
>>> + ret__ = emulate_xchg_1_2(ptr, new__, sfx, pre, post); \
>>> + break; \
>>> + case 4: \
>>> + __amoswap_generic(ptr, new__, ret__,\
>>> + ".w" sfx, pre, post); \
>>> + break; \
>>> + case 8: \
>>> + __amoswap_generic(ptr, new__, ret__,\
>>> + ".d" sfx, pre, post); \
>>> + break; \
>>
>> In io.h you make sure to avoid rv64-only insns. Here you don't. The
>> build
>> would fail either way, but this still looks inconsistent.
>>
>> Also nit: Stray double blands (twice) ahead of "pre". Plus with this
>> style
>> of line continuation you want to consistently have exactly one blank
>> ahead
>> of each backslash.
>>
>>> + default: \
>>> + STATIC_ASSERT_UNREACHABLE(); \
>>> + } \
>>> + ret__; \
>>> +})
>>> +
>>> +#define xchg_relaxed(ptr, x) \
>>> +({ \
>>> + __typeof__(*(ptr)) x_ = (x); \
>>
>> What is the purpose of this, when __xchg_generic() already does this
>> same
>> type conversion?
>>
>>> + (__typeof__(*(ptr)))__xchg_generic(ptr, x_, sizeof(*(ptr)),
>>> "", "", ""); \
>>> +})
>>> +
>>> +#define xchg_acquire(ptr, x) \
>>> +({ \
>>> + __typeof__(*(ptr)) x_ = (x); \
>>> + (__typeof__(*(ptr)))__xchg_generic(ptr, x_, sizeof(*(ptr)), \
>>> + "", "",
>>> RISCV_ACQUIRE_BARRIER); \
>>> +})
>>> +
>>> +#define xchg_release(ptr, x) \
>>> +({ \
>>> + __typeof__(*(ptr)) x_ = (x); \
>>> + (__typeof__(*(ptr)))__xchg_generic(ptr, x_, sizeof(*(ptr)),\
>>> + "", RISCV_RELEASE_BARRIER,
>>> ""); \
>>> +})
>>
>> As asked before: Are there going to be any uses of these three?
>> Common
>> code doesn't require them. And not needing to provide them would
>> simplify things quite a bit, it seems.
> I checked my private branches and it looks to me that I introduced them
> only for the correspondent atomic operations ( which was copied from
> Linux Kernel ) which are not also used.
>
> So we could definitely drop these macros for now, but should
> xchg_generic() be updated as well? If to look at:
> #define xchg(ptr, x) __xchg_generic(ptr, (unsigned long)(x), sizeof(*
> (ptr)), \
> ".aqrl", "", "")
> Last two arguments start to be unneeded, but I've wanted to leave them,
> in case someone will needed to back xchg_{release, acquire, ...}. Does
> it make any sense?
It all depends on how it's justified in the description.
>>> +#define xchg(ptr, x) __xchg_generic(ptr, (unsigned long)(x),
>>> sizeof(*(ptr)), \
>>> + ".aqrl", "", "")
>>
>> According to the earlier comment (where I don't follow the example
>> given),
>> is .aqrl sufficient here? And even if it was for the 4- and 8-byte
>> cases,
>> is it sufficient in the 1- and 2-byte emulation case (where it then
>> is
>> appended to just the SC)?
> If I understand your question correctly then accroding to the spec.,
> .aqrl is enough for amo<op>.{w|d} instructions:
> Linux Construct RVWMO AMO Mapping
> atomic <op> relaxed amo<op>.{w|d}
> atomic <op> acquire amo<op>.{w|d}.aq
> atomic <op> release amo<op>.{w|d}.rl
> atomic <op> amo<op>.{w|d}.aqrl
> but in case of lr/sc you are right sc requires suffix too:
> Linux Construct RVWMO LR/SC Mapping
> atomic <op> relaxed loop: lr.{w|d}; <op>; sc.{w|d}; bnez loop
> atomic <op> acquire loop: lr.{w|d}.aq; <op>; sc.{w|d}; bnez loop
> atomic <op> release loop: lr.{w|d}; <op>; sc.{w|d}.aqrl∗ ; bnez
> loop OR fence.tso; loop: lr.{w|d}; <op>; sc.{w|d}∗ ; bnez loop
> atomic <op> loop: lr.{w|d}.aq; <op>; sc.{w|d}.aqrl; bnez
> loop
>
> I will add sc_sfx to emulate_xchg_1_2(). The only question is left if
> __xchg_generic(ptr, new, size, sfx, pre, post) should be changed to:
> __xchg_generic(ptr, new, size, sfx1, sfx2, pre, post) to cover both
> cases amo<op>.{w|d}.sfx1 and lr.{w|d}.sfx1 ... sc.{w|d}.sfx2?
I expect that's going to be necessary. In the end you'll see what's needed
when making the code adjustment.
Jan
next prev parent reply other threads:[~2024-03-07 10:46 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-26 17:38 [PATCH v5 00/23] [PATCH v4 00/30] Enable build of full Xen for RISC-V Oleksii Kurochko
2024-02-26 17:38 ` [PATCH v5 01/23] xen/riscv: disable unnecessary configs Oleksii Kurochko
2024-02-26 17:38 ` [PATCH v5 02/23] xen/riscv: use some asm-generic headers Oleksii Kurochko
2024-02-27 7:35 ` Jan Beulich
2024-02-26 17:38 ` [PATCH v5 03/23] xen/riscv: introduce nospec.h Oleksii Kurochko
2024-02-27 7:38 ` Jan Beulich
2024-02-28 9:59 ` Oleksii
2024-02-29 13:49 ` Julien Grall
2024-02-29 14:01 ` Jan Beulich
2024-02-29 16:09 ` Oleksii
2024-02-29 16:27 ` Jan Beulich
2024-02-26 17:38 ` [PATCH v5 04/23] xen/asm-generic: introduce generic fls() and flsl() functions Oleksii Kurochko
2024-02-29 13:54 ` Julien Grall
2024-02-29 14:03 ` Jan Beulich
2024-02-29 14:08 ` Julien Grall
2024-02-29 16:17 ` Oleksii
2024-02-29 15:52 ` Jan Beulich
2024-02-29 16:25 ` Andrew Cooper
2024-03-01 9:15 ` Oleksii
2024-02-26 17:38 ` [PATCH v5 05/23] xen/asm-generic: introduce generic find first set bit functions Oleksii Kurochko
2024-02-26 17:38 ` [PATCH v5 06/23] xen/asm-generic: introduce generic ffz() Oleksii Kurochko
2024-02-26 17:38 ` [PATCH v5 07/23] xen/asm-generic: introduce generic hweight64() Oleksii Kurochko
2024-02-26 17:38 ` [PATCH v5 08/23] xen/asm-generic: introduce generic non-atomic test_*bit() Oleksii Kurochko
2024-02-26 17:38 ` [PATCH v5 09/23] xen/riscv: introduce bitops.h Oleksii Kurochko
2024-02-26 17:38 ` [PATCH v5 10/23] xen/riscv: introduces acrquire, release and full barriers Oleksii Kurochko
2024-03-05 7:42 ` Jan Beulich
2024-02-26 17:38 ` [PATCH v5 11/23] xen/riscv: introduce cmpxchg.h Oleksii Kurochko
2024-03-06 14:56 ` Jan Beulich
2024-03-07 10:35 ` Oleksii
2024-03-07 10:46 ` Jan Beulich [this message]
2024-03-07 11:01 ` Oleksii
2024-03-07 11:11 ` Jan Beulich
2024-03-07 12:28 ` Oleksii
2024-02-26 17:38 ` [PATCH v5 12/23] xen/riscv: introduce io.h Oleksii Kurochko
2024-03-06 14:13 ` Jan Beulich
2024-03-07 13:01 ` Oleksii
2024-03-07 13:24 ` Jan Beulich
2024-03-07 13:44 ` Oleksii
2024-03-07 15:32 ` Jan Beulich
2024-03-07 16:21 ` Oleksii
2024-03-07 17:14 ` Jan Beulich
2024-03-07 20:49 ` Oleksii
2024-03-07 20:54 ` Oleksii
2024-03-08 7:26 ` Jan Beulich
2024-03-08 10:14 ` Oleksii
2024-03-08 11:49 ` Jan Beulich
2024-03-08 11:52 ` Jan Beulich
2024-03-08 12:17 ` Oleksii
2024-03-08 12:54 ` Jan Beulich
2024-03-08 7:18 ` Jan Beulich
2024-02-26 17:38 ` [PATCH v5 13/23] xen/riscv: introduce atomic.h Oleksii Kurochko
2024-03-06 15:31 ` Jan Beulich
2024-03-07 13:30 ` Oleksii
2024-03-07 15:40 ` Jan Beulich
2024-02-26 17:38 ` [PATCH v5 14/23] xen/riscv: introduce monitor.h Oleksii Kurochko
2024-02-26 17:38 ` [PATCH v5 15/23] xen/riscv: add definition of __read_mostly Oleksii Kurochko
2024-02-26 17:38 ` [PATCH v5 16/23] xen/riscv: add required things to current.h Oleksii Kurochko
2024-02-26 17:38 ` [PATCH v5 17/23] xen/riscv: add minimal stuff to page.h to build full Xen Oleksii Kurochko
2024-02-26 17:39 ` [PATCH v5 18/23] xen/riscv: add minimal stuff to processor.h " Oleksii Kurochko
2024-03-05 8:05 ` Jan Beulich
2024-03-05 17:34 ` Oleksii
2024-02-26 17:39 ` [PATCH v5 19/23] xen/riscv: add minimal stuff to mm.h " Oleksii Kurochko
2024-03-05 8:17 ` Jan Beulich
2024-03-05 16:46 ` Oleksii
2024-02-26 17:39 ` [PATCH v5 20/23] xen/riscv: introduce vm_event_*() functions Oleksii Kurochko
2024-02-26 17:39 ` [PATCH v5 21/23] xen/rirscv: add minimal amount of stubs to build full Xen Oleksii Kurochko
2024-03-05 8:40 ` Jan Beulich
2024-02-26 17:39 ` [PATCH v5 22/23] xen/riscv: enable full Xen build Oleksii Kurochko
2024-02-26 17:39 ` [PATCH v5 23/23] xen/README: add compiler and binutils versions for RISC-V64 Oleksii Kurochko
2024-02-27 7:55 ` Jan Beulich
2024-02-28 17:03 ` Oleksii
2024-02-28 22:58 ` Julien Grall
2024-02-28 23:11 ` Andrew Cooper
2024-02-29 17:00 ` Oleksii
2024-02-29 7:58 ` Jan Beulich
2024-02-29 10:23 ` Julien Grall
2024-02-29 11:56 ` Jan Beulich
2024-02-29 11:59 ` Jan Beulich
2024-02-29 12:05 ` Andrew Cooper
2024-02-29 12:17 ` Jan Beulich
2024-02-29 12:32 ` Julien Grall
2024-02-29 12:51 ` Jan Beulich
2024-02-29 13:44 ` Julien Grall
2024-02-29 14:07 ` Jan Beulich
2024-02-29 14:14 ` Julien Grall
2024-02-29 17:43 ` Stefano Stabellini
2024-02-29 12:27 ` Julien Grall
2024-02-29 16:54 ` Oleksii
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=dd45b338-7b43-442d-85cd-307b3d228d87@suse.com \
--to=jbeulich@suse.com \
--cc=alistair.francis@wdc.com \
--cc=andrew.cooper3@citrix.com \
--cc=bobbyeshleman@gmail.com \
--cc=connojdavis@gmail.com \
--cc=george.dunlap@citrix.com \
--cc=julien@xen.org \
--cc=oleksii.kurochko@gmail.com \
--cc=sstabellini@kernel.org \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.