From: Sairaj Kodilkar <sarunkod@amd.com>
To: <sashiko-reviews@lists.linux.dev>
Cc: <sarunkod@amd.com>, <kvm@vger.kernel.org>
Subject: Re: [PATCH v3 1/2] x86/uaccess: Extend CMPXCHG user helpers to 128-bit operands
Date: Wed, 26 Aug 2026 14:24:17 +0530 [thread overview]
Message-ID: <3adb04c2-a35e-4b9d-ab06-2408fabd0a89@amd.com> (raw)
In-Reply-To: <20260826072350.8D6991F000E9@smtp.kernel.org>
On 8/26/2026 12:53 PM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [High] The inline assembly for 128-bit cmpxchg uses the unreliable `+A` constraint on x86-64, risking silent memory corruption or build failures.
> - [Medium] The 32-bit stub for `__try_cmpxchg128_user_asm` relies on `BUILD_BUG_ON(1)`, which will break the 32-bit build for all callers of `unsafe_try_cmpxchg_user`.
> --
>
> commit 778924f40bf568ddfaeffc09239d3c0e2a09bba6
> Author: Sairaj Kodilkar <sarunkod@amd.com>
>
> x86/uaccess: Extend CMPXCHG user helpers to 128-bit operands
>
> This commit extends the existing user CMPXCHG helpers to support 16-byte
> operands on x86-64 using the "cmpxchg16b" instruction. On 32-bit kernels,
> it stubs the helper to fail, as cmpxchg16b requires 64-bit registers. KVM
> uses this to atomically emulate guest cmpxchg16b on guest RAM mapped via
> userspace addresses.
>
>> diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
>> index 3a0dd3c2b233e..39bcf327664ea 100644
>> --- a/arch/x86/include/asm/uaccess.h
>> +++ b/arch/x86/include/asm/uaccess.h
>> @@ -407,6 +407,25 @@ do { \
> [ ... ]
>> +#else // !CONFIG_X86_32
>> +#define __try_cmpxchg128_user_asm(_ptr, _pold, _new, label) ({ \
>> + bool success; \
>> + __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \
>> + __typeof__(*(_ptr)) __old = *_old; \
>> + __typeof__(*(_ptr)) __new = (_new); \
>> + asm_goto_output("\n" \
>> + "1: " LOCK_PREFIX "cmpxchg16b %[ptr]\n" \
>> + _ASM_EXTABLE_UA(1b, %l[label]) \
>> + : "=@ccz" (success), \
>> + "+A" (__old), \
>
> [Severity: High]
> Does using the "+A" constraint for a 128-bit value provide the strict
> rdx:rax register ordering required by the cmpxchg16b instruction?
>
> The kernel documents in arch/x86/include/asm/asm.h that the "A" constraint
> on x86-64 means rax or rdx, rather than the rdx:rax pair. If the compiler
> does not guarantee the rdx:rax ordering for __int128/u128 with "+A", could
> this lead to silent memory corruption with swapped operands, or outright
> build failures on compilers like Clang?
>
> The standard pattern used elsewhere (like __arch_cmpxchg128 in
> arch/x86/include/asm/cmpxchg_64.h) splits the 128-bit value into a union
> of two 64-bit halves and explicitly binds them to "+a" (rax) and "+d" (rdx).
> Would it be safer to use that pattern here?
It is easy to misread/misunderstand the official gcc documentations [1].
It specifically mentions that
"Single word values will be allocated either in ax or dx".
Here on x86_64 arch, the __old is 128 bit (i.e. it cannot fit in single
register) so the compiler will always split it in rdx:rax pair.
>> + [ptr] "+m" (*_ptr) \
>> + : "b" ((u64)__new), \
>> + "c" ((u64)((u128)__new >> 64)) \
>> + : "memory" \
>> + : label); \
>> + if (unlikely(!success)) \
>> + *_old = __old; \
>> + likely(success); })
>> #endif // CONFIG_X86_32
>> #else // !CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
> [ ... ]
>> +#else //!CONFIG_X86_32
>> +#define __try_cmpxchg128_user_asm(_ptr, _pold, _new, label) ({ \
>> + int __result; \
>> + __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \
>> + __typeof__(*(_ptr)) __old = *_old; \
>> + __typeof__(*(_ptr)) __new = (_new); \
>> + asm volatile("\n" \
>> + "1: " LOCK_PREFIX "cmpxchg16b %[ptr]\n" \
>> + "mov $0, %[result]\n\t" \
>> + "setz %b[result]\n" \
>> + "2:\n" \
>> + _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, \
>> + %[result]) \
>> + : [result] "=q" (__result), \
>> + "+A" (__old), \
>
> [Severity: High]
> Similar to the asm_goto_output block above, this fallback path also binds
> the 128-bit __old variable to the "+A" constraint.
>
>> + [ptr] "+m" (*_ptr) \
>> + : "b" ((u64)__new), \
>> + "c" ((u64)((u128)__new >> 64)) \
>> + : "memory", "cc"); \
>> + if (unlikely(__result < 0)) \
>> + goto label; \
>> + if (unlikely(!__result)) \
>> + *_old = __old; \
>> + likely(__result); })
>> #endif // CONFIG_X86_32
>> #endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
> [ ... ]
>> @@ -551,11 +594,18 @@ do { \
>>
>> extern void __try_cmpxchg_user_wrong_size(void);
>>
>> -#ifndef CONFIG_X86_32
>> +#ifdef CONFIG_X86_32
>> +/* Always fail on 32 bit arch as it do not support 128 cmpxchg (i.e. cmpxchg16b
>> + * instruction).
>> + */
>> +#define __try_cmpxchg128_user_asm(_ptr, _pold, _new, label) ({ BUILD_BUG_ON(1); 0; })
>
> [Severity: Medium]
> Will this BUILD_BUG_ON(1) break 32-bit x86 builds that call the
> unsafe_try_cmpxchg_user() macro for perfectly valid 32-bit or 64-bit sizes?
>
> Because unsafe_try_cmpxchg_user() dispatches via a switch(sizeof(*(_ptr)))
> statement, compilers like Clang/LLVM eagerly evaluate all branches during
> semantic analysis, including the 16-byte branch. If evaluated on 32-bit
> builds, BUILD_BUG_ON(1) will trigger a compile-time error regardless of
> whether the 16-byte path is actually reachable.
>
> Since the commit message says "stub the helper to always return failure",
> would it be better to return a runtime error code here instead of using
> a build bug?
>
The BUILD_BUG_ON(1) will only cause compile failure if there the code is
getting used. As sean mentioned in the previous version, compiler
elimiates this code if it is not used.
Thanks
Sairaj
>> +#else
>> #define __try_cmpxchg64_user_asm(_ptr, _oldp, _nval, _label) \
>> __try_cmpxchg_user_asm("q", "r", (_ptr), (_oldp), (_nval), _label)
>
next prev parent reply other threads:[~2026-08-26 8:54 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-26 7:00 [PATCH v3 0/2] Add support for cmpxchg16b emulation Sairaj Kodilkar
2026-08-26 7:00 ` [PATCH v3 1/2] x86/uaccess: Extend CMPXCHG user helpers to 128-bit operands Sairaj Kodilkar
2026-08-26 7:23 ` sashiko-bot
2026-08-26 8:54 ` Sairaj Kodilkar [this message]
2026-08-26 12:30 ` Dave Hansen
2026-08-26 13:19 ` Uros Bizjak
2026-08-26 13:28 ` Sairaj Kodilkar
2026-08-27 9:01 ` David Laight
2026-08-26 7:00 ` [PATCH v3 2/2] KVM: x86: Add support for cmpxchg16b emulation Sairaj Kodilkar
2026-08-26 7:31 ` sashiko-bot
2026-08-26 9:17 ` Sairaj Kodilkar
2026-08-26 12:50 ` Mathieu Desnoyers
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=3adb04c2-a35e-4b9d-ab06-2408fabd0a89@amd.com \
--to=sarunkod@amd.com \
--cc=kvm@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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