From: Sairaj Kodilkar <sarunkod@amd.com>
To: "H. Peter Anvin" <hpa@zytor.com>,
"Peter Zijlstra (Intel)" <peterz@infradead.org>,
Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
Ingo Molnar <mingo@redhat.com>,
"Mathieu Desnoyers" <mathieu.desnoyers@efficios.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Sairaj Kodilkar <sarunkod@amd.com>,
"Sean Christopherson" <seanjc@google.com>,
Thomas Gleixner <tglx@kernel.org>,
"Uros Bizjak" <ubizjak@gmail.com>, <kvm@vger.kernel.org>,
<linux-kernel@vger.kernel.org>, <x86@kernel.org>
Cc: <vasant.hegde@amd.com>, <suravee.suthikulpanit@amd.com>
Subject: [PATCH v2 1/2] x86/uaccess: Extend CMPXCHG user helpers to 128-bit operands
Date: Mon, 6 Jul 2026 12:00:34 +0530 [thread overview]
Message-ID: <20260706063035.1139-2-sarunkod@amd.com> (raw)
In-Reply-To: <20260706063035.1139-1-sarunkod@amd.com>
Extend the existing user CMPXCHG helpers to support 16-byte operands on
x86-64, using LOCK_PREFIX "cmpxchg16b". This mirrors the existing
__try_cmpxchg64_user_asm() / cmpxchg8b path provided for 32-bit kernels,
where KVM needs an atomic compare-exchange wider than the generic
cmpxchg helper can provide.
On 32-bit kernels, stub the helper to always return failure because cmpxchg16b
requires 64-bit GPRs and is not available.
KVM uses this to atomically emulate guest cmpxchg16b on guest RAM mapped
via userspace addresses.
Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
---
arch/x86/include/asm/uaccess.h | 56 +++++++++++++++++++++++++++++++++-
1 file changed, 55 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 367297b188c3..123755d47109 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -407,6 +407,25 @@ do { \
if (unlikely(!success)) \
*_old = __old; \
likely(success); })
+#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), \
+ [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
#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label) ({ \
@@ -463,6 +482,30 @@ do { \
if (unlikely(!__result)) \
*_old = __old; \
likely(__result); })
+#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), \
+ [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) (1)
+#else
#define __try_cmpxchg64_user_asm(_ptr, _oldp, _nval, _label) \
__try_cmpxchg_user_asm("q", "r", (_ptr), (_oldp), (_nval), _label)
+
#endif
+
/*
* Force the pointer to u<size> to match the size expected by the asm helper.
* clang/LLVM compiles all cases and only discards the unused paths after
@@ -580,6 +630,10 @@ extern void __try_cmpxchg_user_wrong_size(void);
case 8: __ret = __try_cmpxchg64_user_asm((__force u64 *)(_ptr), (_oldp),\
(_nval), _label); \
break; \
+ case 16: \
+ __ret = __try_cmpxchg128_user_asm((__force u128 *)(_ptr), \
+ (_oldp), (_nval), _label); \
+ break; \
default: __try_cmpxchg_user_wrong_size(); \
} \
__ret; })
--
2.34.1
next prev parent reply other threads:[~2026-07-06 6:32 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-06 6:30 [PATCH v2 0/2] Add support for cmpxchg16b emulation Sairaj Kodilkar
2026-07-06 6:30 ` Sairaj Kodilkar [this message]
2026-07-06 6:52 ` [PATCH v2 1/2] x86/uaccess: Extend CMPXCHG user helpers to 128-bit operands sashiko-bot
2026-07-06 8:00 ` Sairaj Kodilkar
2026-07-06 6:30 ` [PATCH v2 2/2] KVM: x86: Add support for cmpxchg16b emulation Sairaj Kodilkar
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=20260706063035.1139-2-sarunkod@amd.com \
--to=sarunkod@amd.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mingo@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=seanjc@google.com \
--cc=suravee.suthikulpanit@amd.com \
--cc=tglx@kernel.org \
--cc=ubizjak@gmail.com \
--cc=vasant.hegde@amd.com \
--cc=x86@kernel.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