| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/06 07:01 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"em_cmpxchg8b",
"emulator_cmpxchg_emulated"
],
"Reasoning": "The patch adds support for emulating the cmpxchg16b instruction in KVM. It modifies the instruction emulator and the memory access callbacks to handle 16-byte atomic compare-and-exchange operations. This is a functional change to the core KVM emulation logic that is reachable by a guest executing the cmpxchg16b instruction, and thus should be fuzzed.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/06 07:01 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 67e06426857d03d607b3c4f08a5969dd15e8fe70\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Jul 6 07:01:45 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h\nindex 367297b188c39c..123755d4710997 100644\n--- a/arch/x86/include/asm/uaccess.h\n+++ b/arch/x86/include/asm/uaccess.h\n@@ -407,6 +407,25 @@ do {\t\t\t\t\t\t\t\t\t\\\n \tif (unlikely(!success))\t\t\t\t\t\t\\\n \t\t*_old = __old;\t\t\t\t\t\t\\\n \tlikely(success);\t\t\t\t\t})\n+#else // !CONFIG_X86_32\n+#define __try_cmpxchg128_user_asm(_ptr, _pold, _new, label)\t({\t\\\n+\tbool success;\t\t\t\t\t\t\t\\\n+\t__typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);\t\t\\\n+\t__typeof__(*(_ptr)) __old = *_old;\t\t\t\t\\\n+\t__typeof__(*(_ptr)) __new = (_new);\t\t\t\t\\\n+\tasm_goto_output(\"\\n\"\t\t\t\t\t\t\\\n+\t\t \"1: \" LOCK_PREFIX \"cmpxchg16b %[ptr]\\n\"\t\t\\\n+\t\t _ASM_EXTABLE_UA(1b, %l[label])\t\t\t\\\n+\t\t : \"=@ccz\" (success),\t\t\t\t\\\n+\t\t \"+A\" (__old),\t\t\t\t\t\\\n+\t\t [ptr] \"+m\" (*_ptr)\t\t\t\t\\\n+\t\t : \"b\" ((u64)__new),\t\t\t\t\\\n+\t\t \"c\" ((u64)((u128)__new \u003e\u003e 64))\t\t\t\\\n+\t\t : \"memory\"\t\t\t\t\t\t\\\n+\t\t : label);\t\t\t\t\t\t\\\n+\tif (unlikely(!success))\t\t\t\t\t\t\\\n+\t\t*_old = __old;\t\t\t\t\t\t\\\n+\tlikely(success);\t\t\t\t\t})\n #endif // CONFIG_X86_32\n #else // !CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT\n #define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label)\t({ \\\n@@ -463,6 +482,30 @@ do {\t\t\t\t\t\t\t\t\t\\\n \tif (unlikely(!__result))\t\t\t\t\t\\\n \t\t*_old = __old;\t\t\t\t\t\t\\\n \tlikely(__result);\t\t\t\t\t})\n+#else //!CONFIG_X86_32\n+#define __try_cmpxchg128_user_asm(_ptr, _pold, _new, label)\t({\t\\\n+\tint __result;\t\t\t\t\t\t\t\\\n+\t__typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);\t\t\\\n+\t__typeof__(*(_ptr)) __old = *_old;\t\t\t\t\\\n+\t__typeof__(*(_ptr)) __new = (_new);\t\t\t\t\\\n+\tasm volatile(\"\\n\"\t\t\t\t\t\t\\\n+\t\t \"1: \" LOCK_PREFIX \"cmpxchg16b %[ptr]\\n\"\t\t\\\n+\t\t \"mov $0, %[result]\\n\\t\"\t\t\t\t\\\n+\t\t \"setz %b[result]\\n\"\t\t\t\t\\\n+\t\t \"2:\\n\"\t\t\t\t\t\t\\\n+\t\t _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG,\t\\\n+\t\t\t\t\t %[result])\t\t\t\\\n+\t\t : [result] \"=q\" (__result),\t\t\t\\\n+\t\t \"+A\" (__old),\t\t\t\t\t\\\n+\t\t [ptr] \"+m\" (*_ptr)\t\t\t\t\\\n+\t\t : \"b\" ((u64)__new),\t\t\t\t\\\n+\t\t \"c\" ((u64)((u128)__new \u003e\u003e 64))\t\t\t\\\n+\t\t : \"memory\", \"cc\");\t\t\t\t\t\\\n+\tif (unlikely(__result \u003c 0))\t\t\t\t\t\\\n+\t\tgoto label;\t\t\t\t\t\t\\\n+\tif (unlikely(!__result))\t\t\t\t\t\\\n+\t\t*_old = __old;\t\t\t\t\t\t\\\n+\tlikely(__result);\t\t\t\t\t})\n #endif // CONFIG_X86_32\n #endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT\n \n@@ -551,11 +594,18 @@ do {\t\t\t\t\t\t\t\t\t\t\\\n \n extern void __try_cmpxchg_user_wrong_size(void);\n \n-#ifndef CONFIG_X86_32\n+#ifdef CONFIG_X86_32\n+/* Always fail on 32 bit arch as it do not support 128 cmpxchg (i.e. cmpxchg16b\n+ * instruction).\n+ */\n+#define __try_cmpxchg128_user_asm(_ptr, _pold, _new, label) (1)\n+#else\n #define __try_cmpxchg64_user_asm(_ptr, _oldp, _nval, _label)\t\t\\\n \t__try_cmpxchg_user_asm(\"q\", \"r\", (_ptr), (_oldp), (_nval), _label)\n+\n #endif\n \n+\n /*\n * Force the pointer to u\u003csize\u003e to match the size expected by the asm helper.\n * clang/LLVM compiles all cases and only discards the unused paths after\n@@ -580,6 +630,10 @@ extern void __try_cmpxchg_user_wrong_size(void);\n \tcase 8:\t__ret = __try_cmpxchg64_user_asm((__force u64 *)(_ptr), (_oldp),\\\n \t\t\t\t\t\t (_nval), _label);\t\t\\\n \t\tbreak;\t\t\t\t\t\t\t\t\\\n+\tcase 16:\t\t\t\t\t\t\t\t\\\n+\t\t__ret = __try_cmpxchg128_user_asm((__force u128 *)(_ptr),\t\\\n+\t\t\t\t\t\t (_oldp), (_nval), _label);\t\\\n+\t\tbreak;\t\t\t\t\t\t\t\t\\\n \tdefault: __try_cmpxchg_user_wrong_size();\t\t\t\t\\\n \t}\t\t\t\t\t\t\t\t\t\\\n \t__ret;\t\t\t\t\t\t})\ndiff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c\nindex c8e292e9a24dfe..9df55b3c562765 100644\n--- a/arch/x86/kvm/emulate.c\n+++ b/arch/x86/kvm/emulate.c\n@@ -2188,24 +2188,36 @@ static int em_call_near_abs(struct x86_emulate_ctxt *ctxt)\n \treturn rc;\n }\n \n+#define em_cmpxchg8b_16b(__c, rbits, mbits)\\\n+do {\t\t\t\t\t\t\t\t\t\t\t\t\\\n+\tu##mbits old = __c-\u003edst.orig_val##mbits;\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\t\t\t\\\n+\tBUILD_BUG_ON(rbits * 2 != mbits);\t\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\t\t\t\\\n+\tif (((u##rbits) (old \u003e\u003e 0) != (u##rbits) reg_read(ctxt, VCPU_REGS_RAX)) ||\t\t\\\n+\t ((u##rbits) (old \u003e\u003e rbits) != (u##rbits) reg_read(ctxt, VCPU_REGS_RDX))) {\t\t\\\n+\t\t*reg_write(ctxt, VCPU_REGS_RAX) = (u##rbits) (old \u003e\u003e 0);\t\t\t\\\n+\t\t*reg_write(ctxt, VCPU_REGS_RDX) = (u##rbits) (old \u003e\u003e rbits);\t\t\t\\\n+\t\tctxt-\u003eeflags \u0026= ~X86_EFLAGS_ZF;\t\t\t\t\t\t\t\\\n+\t} else {\t\t\t\t\t\t\t\t\t\t\\\n+\t\tctxt-\u003edst.val##mbits = ((u##mbits)reg_read(ctxt, VCPU_REGS_RCX) \u003c\u003c rbits) |\t\\\n+\t\t\t\t\t(u##rbits) reg_read(ctxt, VCPU_REGS_RBX);\t\t\\\n+\t\t\t\t\t\t\t\t\t\t\t\t\\\n+\t\tctxt-\u003eeflags |= X86_EFLAGS_ZF;\t\t\t\t\t\t\t\\\n+\t}\t\t\t\t\t\t\t\t\t\t\t\\\n+} while(0)\n+\n static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt)\n {\n-\tu64 old = ctxt-\u003edst.orig_val64;\n-\n-\tif (ctxt-\u003edst.bytes == 16)\n+\tif (WARN_ON_ONCE(8 + !!(ctxt-\u003erex_bits \u0026 REX_W) * 8 != ctxt-\u003edst.bytes))\n \t\treturn X86EMUL_UNHANDLEABLE;\n \n-\tif (((u32) (old \u003e\u003e 0) != (u32) reg_read(ctxt, VCPU_REGS_RAX)) ||\n-\t ((u32) (old \u003e\u003e 32) != (u32) reg_read(ctxt, VCPU_REGS_RDX))) {\n-\t\t*reg_write(ctxt, VCPU_REGS_RAX) = (u32) (old \u003e\u003e 0);\n-\t\t*reg_write(ctxt, VCPU_REGS_RDX) = (u32) (old \u003e\u003e 32);\n-\t\tctxt-\u003eeflags \u0026= ~X86_EFLAGS_ZF;\n-\t} else {\n-\t\tctxt-\u003edst.val64 = ((u64)reg_read(ctxt, VCPU_REGS_RCX) \u003c\u003c 32) |\n-\t\t\t(u32) reg_read(ctxt, VCPU_REGS_RBX);\n-\n-\t\tctxt-\u003eeflags |= X86_EFLAGS_ZF;\n-\t}\n+\tif (!(ctxt-\u003erex_bits \u0026 REX_W))\n+\t\tem_cmpxchg8b_16b(ctxt, 32, 64);\n+#ifdef CONFIG_X86_64\n+\telse\n+\t\tem_cmpxchg8b_16b(ctxt, 64, 128);\n+#endif\n \treturn X86EMUL_CONTINUE;\n }\n \n@@ -5405,8 +5417,14 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt, bool check_intercepts)\n \t\t\tgoto done;\n \t\t}\n \t}\n-\t/* Copy full 64-bit value for CMPXCHG8B. */\n-\tctxt-\u003edst.orig_val64 = ctxt-\u003edst.val64;\n+\t/* Copy full 64/128-bit value for CMPXCHG8B. */\n+\n+#ifdef CONFIG_X86_64\n+\tif (ctxt-\u003edst.bytes == 16)\n+\t\tctxt-\u003edst.orig_val128 = ctxt-\u003edst.val128;\n+\telse\n+#endif\n+\t\tctxt-\u003edst.orig_val64 = ctxt-\u003edst.val64;\n \n special_insn:\n \ndiff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h\nindex fb3dab4b5a53e7..a51677217ada43 100644\n--- a/arch/x86/kvm/kvm_emulate.h\n+++ b/arch/x86/kvm/kvm_emulate.h\n@@ -255,6 +255,9 @@ struct operand {\n \tunion {\n \t\tunsigned long orig_val;\n \t\tu64 orig_val64;\n+#ifdef CONFIG_X86_64\n+\t\tu128 orig_val128;\n+#endif\n \t};\n \tunion {\n \t\tunsigned long *reg;\n@@ -268,6 +271,9 @@ struct operand {\n \tunion {\n \t\tunsigned long val;\n \t\tu64 val64;\n+#ifdef CONFIG_X86_64\n+\t\tu128 val128;\n+#endif\n \t\tchar valptr[sizeof(avx256_t)];\n \t\tsse128_t vec_val;\n \t\tavx256_t vec_val2;\ndiff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c\nindex 3fb64905d19071..40c84f8c491294 100644\n--- a/arch/x86/kvm/x86.c\n+++ b/arch/x86/kvm/x86.c\n@@ -8322,7 +8322,7 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,\n \tint r;\n \n \t/* guests cmpxchg8b have to be emulated atomically */\n-\tif (bytes \u003e 8 || (bytes \u0026 (bytes - 1)))\n+\tif (bytes \u003e 2 * sizeof(unsigned long) || (bytes \u0026 (bytes - 1)))\n \t\tgoto emul_write;\n \n \tgpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, NULL);\n@@ -8362,6 +8362,11 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,\n \tcase 8:\n \t\tr = emulator_try_cmpxchg_user(u64, hva, old, new);\n \t\tbreak;\n+#ifdef CONFIG_X86_64\n+\tcase 16:\n+\t\tr = emulator_try_cmpxchg_user(u128, hva, old, new);\n+\t\tbreak;\n+#endif\n \tdefault:\n \t\tBUG();\n \t}\n"
} |
| 2/1 | 2026/07/06 07:01 | agent | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"em_cmpxchg8b",
"emulator_cmpxchg_emulated"
],
"Reasoning": "The patch adds support for emulating the cmpxchg16b instruction in KVM. It modifies the instruction emulator and the memory access callbacks to handle 16-byte atomic compare-and-exchange operations. This is a functional change to the core KVM emulation logic that is reachable by a guest executing the cmpxchg16b instruction, and thus should be fuzzed.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 67e06426857d03d607b3c4f08a5969dd15e8fe70
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Jul 6 07:01:45 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 367297b188c39c..123755d4710997 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; })
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index c8e292e9a24dfe..9df55b3c562765 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2188,24 +2188,36 @@ static int em_call_near_abs(struct x86_emulate_ctxt *ctxt)
return rc;
}
+#define em_cmpxchg8b_16b(__c, rbits, mbits)\
+do { \
+ u##mbits old = __c->dst.orig_val##mbits; \
+ \
+ BUILD_BUG_ON(rbits * 2 != mbits); \
+ \
+ if (((u##rbits) (old >> 0) != (u##rbits) reg_read(ctxt, VCPU_REGS_RAX)) || \
+ ((u##rbits) (old >> rbits) != (u##rbits) reg_read(ctxt, VCPU_REGS_RDX))) { \
+ *reg_write(ctxt, VCPU_REGS_RAX) = (u##rbits) (old >> 0); \
+ *reg_write(ctxt, VCPU_REGS_RDX) = (u##rbits) (old >> rbits); \
+ ctxt->eflags &= ~X86_EFLAGS_ZF; \
+ } else { \
+ ctxt->dst.val##mbits = ((u##mbits)reg_read(ctxt, VCPU_REGS_RCX) << rbits) | \
+ (u##rbits) reg_read(ctxt, VCPU_REGS_RBX); \
+ \
+ ctxt->eflags |= X86_EFLAGS_ZF; \
+ } \
+} while(0)
+
static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt)
{
- u64 old = ctxt->dst.orig_val64;
-
- if (ctxt->dst.bytes == 16)
+ if (WARN_ON_ONCE(8 + !!(ctxt->rex_bits & REX_W) * 8 != ctxt->dst.bytes))
return X86EMUL_UNHANDLEABLE;
- if (((u32) (old >> 0) != (u32) reg_read(ctxt, VCPU_REGS_RAX)) ||
- ((u32) (old >> 32) != (u32) reg_read(ctxt, VCPU_REGS_RDX))) {
- *reg_write(ctxt, VCPU_REGS_RAX) = (u32) (old >> 0);
- *reg_write(ctxt, VCPU_REGS_RDX) = (u32) (old >> 32);
- ctxt->eflags &= ~X86_EFLAGS_ZF;
- } else {
- ctxt->dst.val64 = ((u64)reg_read(ctxt, VCPU_REGS_RCX) << 32) |
- (u32) reg_read(ctxt, VCPU_REGS_RBX);
-
- ctxt->eflags |= X86_EFLAGS_ZF;
- }
+ if (!(ctxt->rex_bits & REX_W))
+ em_cmpxchg8b_16b(ctxt, 32, 64);
+#ifdef CONFIG_X86_64
+ else
+ em_cmpxchg8b_16b(ctxt, 64, 128);
+#endif
return X86EMUL_CONTINUE;
}
@@ -5405,8 +5417,14 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt, bool check_intercepts)
goto done;
}
}
- /* Copy full 64-bit value for CMPXCHG8B. */
- ctxt->dst.orig_val64 = ctxt->dst.val64;
+ /* Copy full 64/128-bit value for CMPXCHG8B. */
+
+#ifdef CONFIG_X86_64
+ if (ctxt->dst.bytes == 16)
+ ctxt->dst.orig_val128 = ctxt->dst.val128;
+ else
+#endif
+ ctxt->dst.orig_val64 = ctxt->dst.val64;
special_insn:
diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
index fb3dab4b5a53e7..a51677217ada43 100644
--- a/arch/x86/kvm/kvm_emulate.h
+++ b/arch/x86/kvm/kvm_emulate.h
@@ -255,6 +255,9 @@ struct operand {
union {
unsigned long orig_val;
u64 orig_val64;
+#ifdef CONFIG_X86_64
+ u128 orig_val128;
+#endif
};
union {
unsigned long *reg;
@@ -268,6 +271,9 @@ struct operand {
union {
unsigned long val;
u64 val64;
+#ifdef CONFIG_X86_64
+ u128 val128;
+#endif
char valptr[sizeof(avx256_t)];
sse128_t vec_val;
avx256_t vec_val2;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 3fb64905d19071..40c84f8c491294 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -8322,7 +8322,7 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
int r;
/* guests cmpxchg8b have to be emulated atomically */
- if (bytes > 8 || (bytes & (bytes - 1)))
+ if (bytes > 2 * sizeof(unsigned long) || (bytes & (bytes - 1)))
goto emul_write;
gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, NULL);
@@ -8362,6 +8362,11 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
case 8:
r = emulator_try_cmpxchg_user(u64, hva, old, new);
break;
+#ifdef CONFIG_X86_64
+ case 16:
+ r = emulator_try_cmpxchg_user(u128, hva, old, new);
+ break;
+#endif
default:
BUG();
}
|
| 3/2 | 2026/07/06 07:01 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5033 output: 22 thoughts: 473 Thoughts: **My Assessment of the cmpxchg16b KVM Patch** Okay, so I've been reviewing this patch that introduces 128-bit compare-and-swap (cmpxchg16b) support into the x86 uaccess and KVM emulation layers. The core of it seems sound. They've added `__try_cmpxchg128_user_asm` to `arch/x86/include/asm/uaccess.h`, which is the expected location. Crucially, the KVM emulation components have been modified: `arch/x86/kvm/emulate.c`, `arch/x86/kvm/kvm_emulate.h`, and `arch/x86/kvm/x86.c` all see changes to handle the cmpxchg16b instruction. My initial thought is this is *definitely* reachable and functional *within the KVM context*. They've updated `em_cmpxchg8b` in `emulate.c` to conditionally handle the 128-bit version when `REX_W` is set (which is standard for 64-bit instructions). Also, `emulator_cmpxchg_emulated` in `x86.c` now supports the 16-byte compare-and-swap, which makes sense. I see the flow; it’s all connected. Now, my focus shifts to fuzzing. We absolutely need to subject this to rigorous testing. Let's identify the critical entry points for fuzzing. We'll be targeting: * `em_cmpxchg8b` in `arch/x86/kvm/emulate.c` * `emulator_cmpxchg_emulated` in `arch/x86/kvm/x86.c` Next, I need to verify the build configuration dependencies. I see the standard guards: `#ifdef CONFIG_X86_64` and `#ifndef CONFIG_X86_32`, which is expected for 64-bit architecture support. Given the KVM involvement, `CONFIG_KVM` is, naturally, a prerequisite. That all looks correct. Finally, just to be thorough, I will use `grepper` on the codebase to look for any related functions that may have been overlooked during this patch. I want to ensure we've got a comprehensive view of the change's impact. Specifically, it would be useful to check all call sites to `emulator_cmpxchg_emulated` and `em_cmpxchg8b` in order to determine any potential side effects. I want to double-check that they didn't miss something. |
| 4/2 | 2026/07/06 07:01 | tool | grepper |
0mArgs:{
"Expression": "em_cmpxchg8b"
}Results: {
"Output": "arch/x86/kvm/emulate.c=2177=static int em_call_near_abs(struct x86_emulate_ctxt *ctxt)\n--\narch/x86/kvm/emulate.c-2190-\narch/x86/kvm/emulate.c:2191:#define em_cmpxchg8b_16b(__c, rbits, mbits)\\\narch/x86/kvm/emulate.c-2192-do {\t\t\t\t\t\t\t\t\t\t\t\t\\\n--\narch/x86/kvm/emulate.c-2209-\narch/x86/kvm/emulate.c:2210:static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt)\narch/x86/kvm/emulate.c-2211-{\n--\narch/x86/kvm/emulate.c-2215-\tif (!(ctxt-\u003erex_bits \u0026 REX_W))\narch/x86/kvm/emulate.c:2216:\t\tem_cmpxchg8b_16b(ctxt, 32, 64);\narch/x86/kvm/emulate.c-2217-#ifdef CONFIG_X86_64\narch/x86/kvm/emulate.c-2218-\telse\narch/x86/kvm/emulate.c:2219:\t\tem_cmpxchg8b_16b(ctxt, 64, 128);\narch/x86/kvm/emulate.c-2220-#endif\n--\narch/x86/kvm/emulate.c=4111=static const struct group_dual group9 = { {\narch/x86/kvm/emulate.c:4112:\tN, I(DstMem64 | Lock | PageTable, em_cmpxchg8b), N, N, N, N, N, N,\narch/x86/kvm/emulate.c-4113-}, {\n"
} |
| 5/2 | 2026/07/06 07:02 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 6660 output: 23 thoughts: 54 Thoughts: Okay, here's my interpretation of those code snippets, summarized in the first person, as you requested: **Navigating the `em_cmpxchg8b` Landscape** Right, so I'm looking at this `em_cmpxchg8b` function, and it's flagged as being part of the `group9` instruction group. That immediately tells me this is something core, probably related to atomic operations, specifically on 8-byte values. Given the context, I'm guessing this function is deeply intertwined with concurrency primitives within the virtual machine. I need to dig deeper into what `group9` actually *is* within this codebase, but my initial hunch is that it's handling memory synchronization concerns. Then, I see `emulator_cmpxchg_emulated` mentioned, which is located in `arch/x86/kvm/x86.c`. Ah, right, that points to the emulation layer within the KVM hypervisor on x86 architectures. This is the part that interests me the most, considering my experience. It strongly implies that `em_cmpxchg8b` (which is presumably emulating the CMpxchg8b instruction) is handled in a software fallback path. This is likely to be used in older processors or when certain architectural features are disabled. I want to look into how the emulated version handles the complexities of this instruction (load-linked/store-conditional and memory ordering), especially around the nuances of handling atomic operations in a virtualized environment. This suggests the kernel is likely running the emulated version rather than directly using the native hardware instruction to maintain compatibility. |
| 6/2 | 2026/07/06 07:02 | tool | grepper |
0mArgs:{
"Expression": "emulator_cmpxchg_emulated"
}Results: {
"Output": "arch/x86/kvm/x86.c=8298=static int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,\n--\narch/x86/kvm/x86.c-8310-\narch/x86/kvm/x86.c:8311:static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,\narch/x86/kvm/x86.c-8312-\t\t\t\t unsigned long addr,\n--\narch/x86/kvm/x86.c=8899=static const struct x86_emulate_ops emulate_ops = {\n--\narch/x86/kvm/x86.c-8907-\t.write_emulated = emulator_write_emulated,\narch/x86/kvm/x86.c:8908:\t.cmpxchg_emulated = emulator_cmpxchg_emulated,\narch/x86/kvm/x86.c-8909-\t.invlpg = emulator_invlpg,\n"
} |
| 7/2 | 2026/07/06 07:02 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7388 output: 139 thoughts: 305 Thoughts: **My Analysis of KVM's cmpxchg16b Emulation for Fuzzing** Okay, so I'm digging into this `cmpxchg16b` KVM emulation patch, and my initial focus is on the core functions. From what I see, `em_cmpxchg8b` and `emulator_cmpxchg_emulated` are the primary ones dealing with this instruction. The KVM configuration, naturally, is `KVM`. That's the baseline. Let me just quickly verify if any other configurations are relevant here. I'm noting that `CONFIG_X86_64` is required for the 128-bit compare-and-exchange logic, but since Syzkaller, which this is likely for, primarily operates on x86_64, that's not a major concern. The primary focus remains on `CONFIG_KVM`. Now, let's break down the rationale behind fuzzing this. The patch's core function is emulating the `cmpxchg16b` instruction within KVM. It's touching the instruction emulator itself, as well as the memory access callbacks, specifically to handle atomic 16-byte compare-and-exchange operations. This represents a functional modification to the very heart of the KVM emulation. Critically, this functionality is directly accessible to a guest that executes the `cmpxchg16b` instruction. Therefore, fuzzing is absolutely warranted. It is a critical path. So, the key symbols I need to concentrate on for fuzzing remain `em_cmpxchg8b` and `emulator_cmpxchg_emulated`. I've already confirmed `KVM` as the essential config. I'll double-check for any other potentially relevant functions, but I think that's it. Looking deeper now: I'm seeing that `__try_cmpxchg128_user_asm` is a macro, and so is `em_cmpxchg8b_16b`. So, no, the focus symbols are correct. That solidifies things. I am satisfied with my analysis. I'm calling set-results. |
| 8/2 | 2026/07/06 07:02 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"em_cmpxchg8b",
"emulator_cmpxchg_emulated"
],
"Reasoning": "The patch adds support for emulating the cmpxchg16b instruction in KVM. It modifies the instruction emulator and the memory access callbacks to handle 16-byte atomic compare-and-exchange operations. This is a functional change to the core KVM emulation logic that is reachable by a guest executing the cmpxchg16b instruction, and thus should be fuzzed.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"em_cmpxchg8b",
"emulator_cmpxchg_emulated"
],
"Reasoning": "The patch adds support for emulating the cmpxchg16b instruction in KVM. It modifies the instruction emulator and the memory access callbacks to handle 16-byte atomic compare-and-exchange operations. This is a functional change to the core KVM emulation logic that is reachable by a guest executing the cmpxchg16b instruction, and thus should be fuzzed.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|