AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/08/04 20:52 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies KVM selftests in tools/testing/selftests/kvm/, which are user-space test programs and do not change any kernel logic to be fuzzed.",
  "WorthFuzzing": false
}

1/1 2026/08/04 20:52 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 6138ff6a94bb57837baad721cc7b8be942517f0a\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Tue Aug 4 20:52:44 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h\nindex e8356ee54d7b9..a6a3e16578959 100644\n--- a/tools/testing/selftests/kvm/include/test_util.h\n+++ b/tools/testing/selftests/kvm/include/test_util.h\n@@ -135,8 +135,8 @@ static inline u64 kvm_random_u64(struct kvm_random_state *state)\n \treturn ((u64)kvm_random_u32(state) \u003c\u003c 32) | kvm_random_u32(state);\n }\n \n-u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min,\n-\t\t\t    u64 max);\n+u32 kvm_random_u32_in_range(struct kvm_random_state *state, u32 min, u32 max);\n+u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min, u64 max);\n \n enum vm_mem_backing_src_type {\n \tVM_MEM_SRC_ANONYMOUS,\ndiff --git a/tools/testing/selftests/kvm/lib/test_util.c b/tools/testing/selftests/kvm/lib/test_util.c\nindex 6b00ab11f3c02..4dff72f6bd346 100644\n--- a/tools/testing/selftests/kvm/lib/test_util.c\n+++ b/tools/testing/selftests/kvm/lib/test_util.c\n@@ -43,12 +43,26 @@ u32 kvm_random_u32(struct kvm_random_state *state)\n \treturn state-\u003eseed;\n }\n \n+/* Returns a random u32 in the inclusive range [min, max] */\n+u32 kvm_random_u32_in_range(struct kvm_random_state *state, u32 min, u32 max)\n+{\n+\tu32 value, range;\n+\n+\tTEST_ASSERT(min \u003c= max, \"PEBKAC, min = 0x%x, max = 0x%x\", min, max);\n+\n+\tvalue = kvm_random_u32(state);\n+\n+\trange = max - min;\n+\tif (range == UINT_MAX)\n+\t\treturn value;\n+\n+\treturn min + (value % (range + 1));\n+}\n+\n /* Returns a random u64 in the inclusive range [min, max] */\n-u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min,\n-\t\t\t    u64 max)\n+u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min, u64 max)\n {\n-\tu64 value;\n-\tu64 range;\n+\tu64 value, range;\n \n \tTEST_ASSERT(min \u003c= max, \"PEBKAC, min = 0x%lx, max = 0x%lx\", min, max);\n \ndiff --git a/tools/testing/selftests/kvm/x86/pmu_counters_test.c b/tools/testing/selftests/kvm/x86/pmu_counters_test.c\nindex dc6afac3aa919..c7c5662203815 100644\n--- a/tools/testing/selftests/kvm/x86/pmu_counters_test.c\n+++ b/tools/testing/selftests/kvm/x86/pmu_counters_test.c\n@@ -87,14 +87,18 @@ static struct kvm_intel_pmu_event intel_event_to_feature(u8 idx)\n \treturn __intel_event_to_feature[idx];\n }\n \n-static struct kvm_vm *pmu_vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,\n-\t\t\t\t\t\t  void *guest_code,\n-\t\t\t\t\t\t  u8 pmu_version,\n-\t\t\t\t\t\t  u64 perf_capabilities)\n+static struct kvm_vm *pmu_vm_create_with_vcpus(u32 nr_vcpus, void *guest_code,\n+\t\t\t\t\t       u8 pmu_version,\n+\t\t\t\t\t       u64 perf_capabilities,\n+\t\t\t\t\t       struct kvm_vcpu **__vcpus[])\n {\n+\tstruct kvm_vcpu **vcpus = calloc(nr_vcpus, sizeof(struct kvm_vcpu));\n \tstruct kvm_vm *vm;\n+\tint i;\n \n-\tvm = vm_create_with_one_vcpu(vcpu, guest_code);\n+\t*__vcpus = vcpus;\n+\n+\tvm = vm_create_with_vcpus(nr_vcpus, guest_code, vcpus);\n \tsync_global_to_guest(vm, kvm_pmu_version);\n \tsync_global_to_guest(vm, hardware_pmu_arch_events);\n \n@@ -102,13 +106,22 @@ static struct kvm_vm *pmu_vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,\n \t * Set PERF_CAPABILITIES before PMU version as KVM disallows enabling\n \t * features via PERF_CAPABILITIES if the guest doesn't have a vPMU.\n \t */\n-\tif (kvm_has_perf_caps)\n-\t\tvcpu_set_msr(*vcpu, MSR_IA32_PERF_CAPABILITIES, perf_capabilities);\n+\tfor (i = 0; i \u003c nr_vcpus; i++) {\n+\t\tif (kvm_has_perf_caps)\n+\t\t\tvcpu_set_msr(vcpus[i], MSR_IA32_PERF_CAPABILITIES, perf_capabilities);\n+\n+\t\tvcpu_set_cpuid_property(vcpus[i], X86_PROPERTY_PMU_VERSION, pmu_version);\n+\t}\n \n-\tvcpu_set_cpuid_property(*vcpu, X86_PROPERTY_PMU_VERSION, pmu_version);\n \treturn vm;\n }\n \n+static void pmu_vm_free(struct kvm_vm *vm, struct kvm_vcpu **vcpus)\n+{\n+\tkvm_vm_free(vm);\n+\tfree(vcpus);\n+}\n+\n static void run_vcpu(struct kvm_vcpu *vcpu)\n {\n \tstruct ucall uc;\n@@ -273,6 +286,7 @@ static void guest_test_arch_event(u8 idx)\n \tstruct kvm_x86_pmu_feature gp_event, fixed_event;\n \tu32 base_pmc_msr;\n \tunsigned int i;\n+\tu64 eventsel;\n \n \t/* The host side shouldn't invoke this without a guest PMU. */\n \tGUEST_ASSERT(pmu_version);\n@@ -287,19 +301,16 @@ static void guest_test_arch_event(u8 idx)\n \tGUEST_ASSERT_EQ(idx, gp_event.f.bit);\n \n \tGUEST_ASSERT(nr_gp_counters);\n+\ti = kvm_random_u32_in_range(\u0026kvm_rng, 0, nr_gp_counters - 1);\n \n-\tfor (i = 0; i \u003c nr_gp_counters; i++) {\n-\t\tu64 eventsel = ARCH_PERFMON_EVENTSEL_OS |\n-\t\t\t\t    ARCH_PERFMON_EVENTSEL_ENABLE |\n-\t\t\t\t    intel_pmu_arch_events[idx];\n+\teventsel = ARCH_PERFMON_EVENTSEL_OS | ARCH_PERFMON_EVENTSEL_ENABLE |\n+\t\t   intel_pmu_arch_events[idx];\n \n-\t\twrmsr(MSR_P6_EVNTSEL0 + i, 0);\n-\t\tif (guest_has_perf_global_ctrl)\n-\t\t\twrmsr(MSR_CORE_PERF_GLOBAL_CTRL, BIT_ULL(i));\n+\twrmsr(MSR_P6_EVNTSEL0 + i, 0);\n+\tif (guest_has_perf_global_ctrl)\n+\t\twrmsr(MSR_CORE_PERF_GLOBAL_CTRL, BIT_ULL(i));\n \n-\t\t__guest_test_arch_event(idx, i, base_pmc_msr + i,\n-\t\t\t\t\tMSR_P6_EVNTSEL0 + i, eventsel);\n-\t}\n+\t__guest_test_arch_event(idx, i, base_pmc_msr + i, MSR_P6_EVNTSEL0 + i, eventsel);\n \n \tif (!guest_has_perf_global_ctrl)\n \t\treturn;\n@@ -328,30 +339,72 @@ static void guest_test_arch_events(void)\n \tGUEST_DONE();\n }\n \n-static void test_arch_events(u8 pmu_version, u64 perf_capabilities,\n-\t\t\t     u8 length, u32 unavailable_mask)\n+static void __test_arch_events(struct kvm_vcpu *vcpu, u64 perf_capabilities,\n+\t\t\t       u8 length, u32 unavailable_mask)\n {\n-\tstruct kvm_vcpu *vcpu;\n-\tstruct kvm_vm *vm;\n-\n-\t/* Testing arch events requires a vPMU (there are no negative tests). */\n-\tif (!pmu_version)\n-\t\treturn;\n-\n \tunavailable_mask \u0026= GENMASK(X86_PROPERTY_PMU_EVENTS_MASK.hi_bit,\n \t\t\t\t    X86_PROPERTY_PMU_EVENTS_MASK.lo_bit);\n \n-\tvm = pmu_vm_create_with_one_vcpu(\u0026vcpu, guest_test_arch_events,\n-\t\t\t\t\t pmu_version, perf_capabilities);\n-\n \tvcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH,\n \t\t\t\tlength);\n \tvcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_EVENTS_MASK,\n \t\t\t\tunavailable_mask);\n \n \trun_vcpu(vcpu);\n+}\n \n-\tkvm_vm_free(vm);\n+static void test_arch_events(u8 pmu_version, u64 perf_capabilities)\n+{\n+\tstruct kvm_vcpu **vcpus;\n+\tstruct kvm_vm *vm;\n+\tint i = 0;\n+\tu32 k;\n+\tu8 j;\n+\n+\t/*\n+\t * To keep the total runtime reasonable, test only a handful of select,\n+\t * semi-arbitrary values for the mask of unavailable PMU events.  Test\n+\t * 0 (all events available) and all ones (no events available) as well\n+\t * as alternating bit sequencues, e.g. to detect if KVM is checking the\n+\t * wrong bit(s).\n+\t */\n+\tconst u32 unavailable_masks[] = {\n+\t\t0x0,\n+\t\t0xffffffffu,\n+\t\t0xaaaaaaaau,\n+\t\t0x55555555u,\n+\t\t0xf0f0f0f0u,\n+\t\t0x0f0f0f0fu,\n+\t\t0xa0a0a0a0u,\n+\t\t0x0a0a0a0au,\n+\t\t0x50505050u,\n+\t\t0x05050505u,\n+\t};\n+\n+\tpr_info(\"Testing arch events, PMU version %u, perf_caps = %lx\\n\",\n+\t\tpmu_version, perf_capabilities);\n+\n+\t/* Testing arch events requires a vPMU (there are no negative tests). */\n+\tif (!pmu_version)\n+\t\treturn;\n+\n+\tvm = pmu_vm_create_with_vcpus((NR_INTEL_ARCH_EVENTS + 2) * ARRAY_SIZE(unavailable_masks),\n+\t\t\t\t      guest_test_arch_events, pmu_version,\n+\t\t\t\t      perf_capabilities, \u0026vcpus);\n+\n+\t/*\n+\t * Test single bits for all PMU version and lengths up the number of\n+\t * events +1 (to verify KVM doesn't do weird things if the guest length\n+\t * is greater than the host length).  Explicitly test a mask of '0' and\n+\t * all ones i.e. all events being available and unavailable.\n+\t */\n+\tfor (j = 0; j \u003c= NR_INTEL_ARCH_EVENTS + 1; j++) {\n+\t\tfor (k = 1; k \u003c ARRAY_SIZE(unavailable_masks); k++)\n+\t\t\t__test_arch_events(vcpus[i++], perf_capabilities, j,\n+\t\t\t\t\t   unavailable_masks[k]);\n+\t}\n+\n+\tpmu_vm_free(vm, vcpus);\n }\n \n /*\n@@ -495,21 +548,27 @@ static void guest_test_gp_counters(void)\n \tGUEST_DONE();\n }\n \n-static void test_gp_counters(u8 pmu_version, u64 perf_capabilities,\n-\t\t\t     u8 nr_gp_counters)\n+static void test_gp_counters(u8 pmu_version, u64 perf_capabilities)\n {\n-\tstruct kvm_vcpu *vcpu;\n+\tu8 nr_gp_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);\n+\tstruct kvm_vcpu **vcpus;\n \tstruct kvm_vm *vm;\n+\tu8 j;\n \n-\tvm = pmu_vm_create_with_one_vcpu(\u0026vcpu, guest_test_gp_counters,\n-\t\t\t\t\t pmu_version, perf_capabilities);\n+\tpr_info(\"Testing %u GP counters, PMU version %u, perf_caps = %lx\\n\",\n+\t\tnr_gp_counters, pmu_version, perf_capabilities);\n \n-\tvcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_NR_GP_COUNTERS,\n-\t\t\t\tnr_gp_counters);\n+\tvm = pmu_vm_create_with_vcpus(nr_gp_counters + 1, guest_test_gp_counters,\n+\t\t\t\t      pmu_version, perf_capabilities, \u0026vcpus);\n \n-\trun_vcpu(vcpu);\n+\tfor (j = 0; j \u003c= nr_gp_counters; j++) {\n+\t\tvcpu_set_cpuid_property(vcpus[j], X86_PROPERTY_PMU_NR_GP_COUNTERS,\n+\t\t\t\t\tnr_gp_counters);\n \n-\tkvm_vm_free(vm);\n+\t\trun_vcpu(vcpus[j]);\n+\t}\n+\n+\tpmu_vm_free(vm, vcpus);\n }\n \n static void guest_test_fixed_counters(void)\n@@ -561,59 +620,53 @@ static void guest_test_fixed_counters(void)\n \tGUEST_DONE();\n }\n \n-static void test_fixed_counters(u8 pmu_version, u64 perf_capabilities,\n-\t\t\t\tu8 nr_fixed_counters, u32 supported_bitmask)\n+static void __test_fixed_counters(struct kvm_vcpu *vcpu, u8 nr_fixed_counters,\n+\t\t\t\t  u32 supported_bitmask)\n {\n-\tstruct kvm_vcpu *vcpu;\n-\tstruct kvm_vm *vm;\n-\n-\tvm = pmu_vm_create_with_one_vcpu(\u0026vcpu, guest_test_fixed_counters,\n-\t\t\t\t\t pmu_version, perf_capabilities);\n-\n \tvcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_FIXED_COUNTERS_BITMASK,\n \t\t\t\tsupported_bitmask);\n \tvcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_NR_FIXED_COUNTERS,\n \t\t\t\tnr_fixed_counters);\n \n \trun_vcpu(vcpu);\n+}\n \n-\tkvm_vm_free(vm);\n+static void test_fixed_counters(u8 pmu_version, u64 perf_capabilities)\n+{\n+\tu8 nr_fixed_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNTERS);\n+\tstruct kvm_vcpu **vcpus;\n+\tstruct kvm_vm *vm;\n+\tint i = 0;\n+\tu32 k;\n+\tu8 j;\n+\n+\tpr_info(\"Testing %u fixed counters, PMU version %u, perf_caps = %lx\\n\",\n+\t\tnr_fixed_counters, pmu_version, perf_capabilities);\n+\n+\n+\tvm = pmu_vm_create_with_vcpus((nr_fixed_counters + 1) * BIT(nr_fixed_counters),\n+\t\t\t\t      guest_test_fixed_counters,\n+\t\t\t\t      pmu_version, perf_capabilities, \u0026vcpus);\n+\n+\tfor (j = 0; j \u003c= nr_fixed_counters; j++) {\n+\t\tfor (k = 0; k \u003c= (BIT(nr_fixed_counters) - 1); k++)\n+\t\t\t__test_fixed_counters(vcpus[i++], j, k);\n+\t}\n+\n+\tpmu_vm_free(vm, vcpus);\n }\n \n static void test_intel_counters(void)\n {\n-\tu8 nr_fixed_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNTERS);\n-\tu8 nr_gp_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);\n \tu8 pmu_version = kvm_cpu_property(X86_PROPERTY_PMU_VERSION);\n \tunsigned int i;\n-\tu8 v, j;\n-\tu32 k;\n+\tu8 v;\n \n \tconst u64 perf_caps[] = {\n \t\t0,\n \t\tPMU_CAP_FW_WRITES,\n \t};\n \n-\t/*\n-\t * To keep the total runtime reasonable, test only a handful of select,\n-\t * semi-arbitrary values for the mask of unavailable PMU events.  Test\n-\t * 0 (all events available) and all ones (no events available) as well\n-\t * as alternating bit sequencues, e.g. to detect if KVM is checking the\n-\t * wrong bit(s).\n-\t */\n-\tconst u32 unavailable_masks[] = {\n-\t\t0x0,\n-\t\t0xffffffffu,\n-\t\t0xaaaaaaaau,\n-\t\t0x55555555u,\n-\t\t0xf0f0f0f0u,\n-\t\t0x0f0f0f0fu,\n-\t\t0xa0a0a0a0u,\n-\t\t0x0a0a0a0au,\n-\t\t0x50505050u,\n-\t\t0x05050505u,\n-\t};\n-\n \t/*\n \t * Test up to PMU v5, which is the current maximum version defined by\n \t * Intel, i.e. is the last version that is guaranteed to be backwards\n@@ -649,32 +702,9 @@ static void test_intel_counters(void)\n \t\t\tif (!kvm_has_perf_caps \u0026\u0026 perf_caps[i])\n \t\t\t\tcontinue;\n \n-\t\t\tpr_info(\"Testing arch events, PMU version %u, perf_caps = %lx\\n\",\n-\t\t\t\tv, perf_caps[i]);\n-\n-\t\t\t/*\n-\t\t\t * Test single bits for all PMU version and lengths up\n-\t\t\t * the number of events +1 (to verify KVM doesn't do\n-\t\t\t * weird things if the guest length is greater than the\n-\t\t\t * host length).  Explicitly test a mask of '0' and all\n-\t\t\t * ones i.e. all events being available and unavailable.\n-\t\t\t */\n-\t\t\tfor (j = 0; j \u003c= NR_INTEL_ARCH_EVENTS + 1; j++) {\n-\t\t\t\tfor (k = 1; k \u003c ARRAY_SIZE(unavailable_masks); k++)\n-\t\t\t\t\ttest_arch_events(v, perf_caps[i], j, unavailable_masks[k]);\n-\t\t\t}\n-\n-\t\t\tpr_info(\"Testing GP counters, PMU version %u, perf_caps = %lx\\n\",\n-\t\t\t\tv, perf_caps[i]);\n-\t\t\tfor (j = 0; j \u003c= nr_gp_counters; j++)\n-\t\t\t\ttest_gp_counters(v, perf_caps[i], j);\n-\n-\t\t\tpr_info(\"Testing fixed counters, PMU version %u, perf_caps = %lx\\n\",\n-\t\t\t\tv, perf_caps[i]);\n-\t\t\tfor (j = 0; j \u003c= nr_fixed_counters; j++) {\n-\t\t\t\tfor (k = 0; k \u003c= (BIT(nr_fixed_counters) - 1); k++)\n-\t\t\t\t\ttest_fixed_counters(v, perf_caps[i], j, k);\n-\t\t\t}\n+\t\t\ttest_arch_events(v, perf_caps[i]);\n+\t\t\ttest_gp_counters(v, perf_caps[i]);\n+\t\t\ttest_fixed_counters(v, perf_caps[i]);\n \t\t}\n \t}\n }\n"
}

2/1 2026/08/04 20:52 agent patch-evaluator
0m Model:
best-expensive

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies KVM selftests in tools/testing/selftests/kvm/, which are user-space test programs and do not change any kernel logic to be fuzzed.",
  "WorthFuzzing": false
}

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).
- Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed,
  ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU.
- Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove)
  that are executed only during PCI hot-unplug or sysfs driver unbind operations.

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.
   Prefer non-static, non-inlined API entrypoint functions over internal static helper functions
   (which are inlined by the compiler and do not have distinct symbol addresses).
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.
   Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs
   needed for Kbuild to compile the code statically into vmlinux. 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 6138ff6a94bb57837baad721cc7b8be942517f0a
Author: syz-cluster <triage@syzkaller.com>
Date:   Tue Aug 4 20:52:44 2026 +0000

    syz-cluster: applied patch under review

diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h
index e8356ee54d7b9..a6a3e16578959 100644
--- a/tools/testing/selftests/kvm/include/test_util.h
+++ b/tools/testing/selftests/kvm/include/test_util.h
@@ -135,8 +135,8 @@ static inline u64 kvm_random_u64(struct kvm_random_state *state)
 	return ((u64)kvm_random_u32(state) << 32) | kvm_random_u32(state);
 }
 
-u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min,
-			    u64 max);
+u32 kvm_random_u32_in_range(struct kvm_random_state *state, u32 min, u32 max);
+u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min, u64 max);
 
 enum vm_mem_backing_src_type {
 	VM_MEM_SRC_ANONYMOUS,
diff --git a/tools/testing/selftests/kvm/lib/test_util.c b/tools/testing/selftests/kvm/lib/test_util.c
index 6b00ab11f3c02..4dff72f6bd346 100644
--- a/tools/testing/selftests/kvm/lib/test_util.c
+++ b/tools/testing/selftests/kvm/lib/test_util.c
@@ -43,12 +43,26 @@ u32 kvm_random_u32(struct kvm_random_state *state)
 	return state->seed;
 }
 
+/* Returns a random u32 in the inclusive range [min, max] */
+u32 kvm_random_u32_in_range(struct kvm_random_state *state, u32 min, u32 max)
+{
+	u32 value, range;
+
+	TEST_ASSERT(min <= max, "PEBKAC, min = 0x%x, max = 0x%x", min, max);
+
+	value = kvm_random_u32(state);
+
+	range = max - min;
+	if (range == UINT_MAX)
+		return value;
+
+	return min + (value % (range + 1));
+}
+
 /* Returns a random u64 in the inclusive range [min, max] */
-u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min,
-			    u64 max)
+u64 kvm_random_u64_in_range(struct kvm_random_state *state, u64 min, u64 max)
 {
-	u64 value;
-	u64 range;
+	u64 value, range;
 
 	TEST_ASSERT(min <= max, "PEBKAC, min = 0x%lx, max = 0x%lx", min, max);
 
diff --git a/tools/testing/selftests/kvm/x86/pmu_counters_test.c b/tools/testing/selftests/kvm/x86/pmu_counters_test.c
index dc6afac3aa919..c7c5662203815 100644
--- a/tools/testing/selftests/kvm/x86/pmu_counters_test.c
+++ b/tools/testing/selftests/kvm/x86/pmu_counters_test.c
@@ -87,14 +87,18 @@ static struct kvm_intel_pmu_event intel_event_to_feature(u8 idx)
 	return __intel_event_to_feature[idx];
 }
 
-static struct kvm_vm *pmu_vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
-						  void *guest_code,
-						  u8 pmu_version,
-						  u64 perf_capabilities)
+static struct kvm_vm *pmu_vm_create_with_vcpus(u32 nr_vcpus, void *guest_code,
+					       u8 pmu_version,
+					       u64 perf_capabilities,
+					       struct kvm_vcpu **__vcpus[])
 {
+	struct kvm_vcpu **vcpus = calloc(nr_vcpus, sizeof(struct kvm_vcpu));
 	struct kvm_vm *vm;
+	int i;
 
-	vm = vm_create_with_one_vcpu(vcpu, guest_code);
+	*__vcpus = vcpus;
+
+	vm = vm_create_with_vcpus(nr_vcpus, guest_code, vcpus);
 	sync_global_to_guest(vm, kvm_pmu_version);
 	sync_global_to_guest(vm, hardware_pmu_arch_events);
 
@@ -102,13 +106,22 @@ static struct kvm_vm *pmu_vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
 	 * Set PERF_CAPABILITIES before PMU version as KVM disallows enabling
 	 * features via PERF_CAPABILITIES if the guest doesn't have a vPMU.
 	 */
-	if (kvm_has_perf_caps)
-		vcpu_set_msr(*vcpu, MSR_IA32_PERF_CAPABILITIES, perf_capabilities);
+	for (i = 0; i < nr_vcpus; i++) {
+		if (kvm_has_perf_caps)
+			vcpu_set_msr(vcpus[i], MSR_IA32_PERF_CAPABILITIES, perf_capabilities);
+
+		vcpu_set_cpuid_property(vcpus[i], X86_PROPERTY_PMU_VERSION, pmu_version);
+	}
 
-	vcpu_set_cpuid_property(*vcpu, X86_PROPERTY_PMU_VERSION, pmu_version);
 	return vm;
 }
 
+static void pmu_vm_free(struct kvm_vm *vm, struct kvm_vcpu **vcpus)
+{
+	kvm_vm_free(vm);
+	free(vcpus);
+}
+
 static void run_vcpu(struct kvm_vcpu *vcpu)
 {
 	struct ucall uc;
@@ -273,6 +286,7 @@ static void guest_test_arch_event(u8 idx)
 	struct kvm_x86_pmu_feature gp_event, fixed_event;
 	u32 base_pmc_msr;
 	unsigned int i;
+	u64 eventsel;
 
 	/* The host side shouldn't invoke this without a guest PMU. */
 	GUEST_ASSERT(pmu_version);
@@ -287,19 +301,16 @@ static void guest_test_arch_event(u8 idx)
 	GUEST_ASSERT_EQ(idx, gp_event.f.bit);
 
 	GUEST_ASSERT(nr_gp_counters);
+	i = kvm_random_u32_in_range(&kvm_rng, 0, nr_gp_counters - 1);
 
-	for (i = 0; i < nr_gp_counters; i++) {
-		u64 eventsel = ARCH_PERFMON_EVENTSEL_OS |
-				    ARCH_PERFMON_EVENTSEL_ENABLE |
-				    intel_pmu_arch_events[idx];
+	eventsel = ARCH_PERFMON_EVENTSEL_OS | ARCH_PERFMON_EVENTSEL_ENABLE |
+		   intel_pmu_arch_events[idx];
 
-		wrmsr(MSR_P6_EVNTSEL0 + i, 0);
-		if (guest_has_perf_global_ctrl)
-			wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, BIT_ULL(i));
+	wrmsr(MSR_P6_EVNTSEL0 + i, 0);
+	if (guest_has_perf_global_ctrl)
+		wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, BIT_ULL(i));
 
-		__guest_test_arch_event(idx, i, base_pmc_msr + i,
-					MSR_P6_EVNTSEL0 + i, eventsel);
-	}
+	__guest_test_arch_event(idx, i, base_pmc_msr + i, MSR_P6_EVNTSEL0 + i, eventsel);
 
 	if (!guest_has_perf_global_ctrl)
 		return;
@@ -328,30 +339,72 @@ static void guest_test_arch_events(void)
 	GUEST_DONE();
 }
 
-static void test_arch_events(u8 pmu_version, u64 perf_capabilities,
-			     u8 length, u32 unavailable_mask)
+static void __test_arch_events(struct kvm_vcpu *vcpu, u64 perf_capabilities,
+			       u8 length, u32 unavailable_mask)
 {
-	struct kvm_vcpu *vcpu;
-	struct kvm_vm *vm;
-
-	/* Testing arch events requires a vPMU (there are no negative tests). */
-	if (!pmu_version)
-		return;
-
 	unavailable_mask &= GENMASK(X86_PROPERTY_PMU_EVENTS_MASK.hi_bit,
 				    X86_PROPERTY_PMU_EVENTS_MASK.lo_bit);
 
-	vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_arch_events,
-					 pmu_version, perf_capabilities);
-
 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH,
 				length);
 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_EVENTS_MASK,
 				unavailable_mask);
 
 	run_vcpu(vcpu);
+}
 
-	kvm_vm_free(vm);
+static void test_arch_events(u8 pmu_version, u64 perf_capabilities)
+{
+	struct kvm_vcpu **vcpus;
+	struct kvm_vm *vm;
+	int i = 0;
+	u32 k;
+	u8 j;
+
+	/*
+	 * To keep the total runtime reasonable, test only a handful of select,
+	 * semi-arbitrary values for the mask of unavailable PMU events.  Test
+	 * 0 (all events available) and all ones (no events available) as well
+	 * as alternating bit sequencues, e.g. to detect if KVM is checking the
+	 * wrong bit(s).
+	 */
+	const u32 unavailable_masks[] = {
+		0x0,
+		0xffffffffu,
+		0xaaaaaaaau,
+		0x55555555u,
+		0xf0f0f0f0u,
+		0x0f0f0f0fu,
+		0xa0a0a0a0u,
+		0x0a0a0a0au,
+		0x50505050u,
+		0x05050505u,
+	};
+
+	pr_info("Testing arch events, PMU version %u, perf_caps = %lx\n",
+		pmu_version, perf_capabilities);
+
+	/* Testing arch events requires a vPMU (there are no negative tests). */
+	if (!pmu_version)
+		return;
+
+	vm = pmu_vm_create_with_vcpus((NR_INTEL_ARCH_EVENTS + 2) * ARRAY_SIZE(unavailable_masks),
+				      guest_test_arch_events, pmu_version,
+				      perf_capabilities, &vcpus);
+
+	/*
+	 * Test single bits for all PMU version and lengths up the number of
+	 * events +1 (to verify KVM doesn't do weird things if the guest length
+	 * is greater than the host length).  Explicitly test a mask of '0' and
+	 * all ones i.e. all events being available and unavailable.
+	 */
+	for (j = 0; j <= NR_INTEL_ARCH_EVENTS + 1; j++) {
+		for (k = 1; k < ARRAY_SIZE(unavailable_masks); k++)
+			__test_arch_events(vcpus[i++], perf_capabilities, j,
+					   unavailable_masks[k]);
+	}
+
+	pmu_vm_free(vm, vcpus);
 }
 
 /*
@@ -495,21 +548,27 @@ static void guest_test_gp_counters(void)
 	GUEST_DONE();
 }
 
-static void test_gp_counters(u8 pmu_version, u64 perf_capabilities,
-			     u8 nr_gp_counters)
+static void test_gp_counters(u8 pmu_version, u64 perf_capabilities)
 {
-	struct kvm_vcpu *vcpu;
+	u8 nr_gp_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
+	struct kvm_vcpu **vcpus;
 	struct kvm_vm *vm;
+	u8 j;
 
-	vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_gp_counters,
-					 pmu_version, perf_capabilities);
+	pr_info("Testing %u GP counters, PMU version %u, perf_caps = %lx\n",
+		nr_gp_counters, pmu_version, perf_capabilities);
 
-	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_NR_GP_COUNTERS,
-				nr_gp_counters);
+	vm = pmu_vm_create_with_vcpus(nr_gp_counters + 1, guest_test_gp_counters,
+				      pmu_version, perf_capabilities, &vcpus);
 
-	run_vcpu(vcpu);
+	for (j = 0; j <= nr_gp_counters; j++) {
+		vcpu_set_cpuid_property(vcpus[j], X86_PROPERTY_PMU_NR_GP_COUNTERS,
+					nr_gp_counters);
 
-	kvm_vm_free(vm);
+		run_vcpu(vcpus[j]);
+	}
+
+	pmu_vm_free(vm, vcpus);
 }
 
 static void guest_test_fixed_counters(void)
@@ -561,59 +620,53 @@ static void guest_test_fixed_counters(void)
 	GUEST_DONE();
 }
 
-static void test_fixed_counters(u8 pmu_version, u64 perf_capabilities,
-				u8 nr_fixed_counters, u32 supported_bitmask)
+static void __test_fixed_counters(struct kvm_vcpu *vcpu, u8 nr_fixed_counters,
+				  u32 supported_bitmask)
 {
-	struct kvm_vcpu *vcpu;
-	struct kvm_vm *vm;
-
-	vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_fixed_counters,
-					 pmu_version, perf_capabilities);
-
 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_FIXED_COUNTERS_BITMASK,
 				supported_bitmask);
 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_NR_FIXED_COUNTERS,
 				nr_fixed_counters);
 
 	run_vcpu(vcpu);
+}
 
-	kvm_vm_free(vm);
+static void test_fixed_counters(u8 pmu_version, u64 perf_capabilities)
+{
+	u8 nr_fixed_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNTERS);
+	struct kvm_vcpu **vcpus;
+	struct kvm_vm *vm;
+	int i = 0;
+	u32 k;
+	u8 j;
+
+	pr_info("Testing %u fixed counters, PMU version %u, perf_caps = %lx\n",
+		nr_fixed_counters, pmu_version, perf_capabilities);
+
+
+	vm = pmu_vm_create_with_vcpus((nr_fixed_counters + 1) * BIT(nr_fixed_counters),
+				      guest_test_fixed_counters,
+				      pmu_version, perf_capabilities, &vcpus);
+
+	for (j = 0; j <= nr_fixed_counters; j++) {
+		for (k = 0; k <= (BIT(nr_fixed_counters) - 1); k++)
+			__test_fixed_counters(vcpus[i++], j, k);
+	}
+
+	pmu_vm_free(vm, vcpus);
 }
 
 static void test_intel_counters(void)
 {
-	u8 nr_fixed_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNTERS);
-	u8 nr_gp_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
 	u8 pmu_version = kvm_cpu_property(X86_PROPERTY_PMU_VERSION);
 	unsigned int i;
-	u8 v, j;
-	u32 k;
+	u8 v;
 
 	const u64 perf_caps[] = {
 		0,
 		PMU_CAP_FW_WRITES,
 	};
 
-	/*
-	 * To keep the total runtime reasonable, test only a handful of select,
-	 * semi-arbitrary values for the mask of unavailable PMU events.  Test
-	 * 0 (all events available) and all ones (no events available) as well
-	 * as alternating bit sequencues, e.g. to detect if KVM is checking the
-	 * wrong bit(s).
-	 */
-	const u32 unavailable_masks[] = {
-		0x0,
-		0xffffffffu,
-		0xaaaaaaaau,
-		0x55555555u,
-		0xf0f0f0f0u,
-		0x0f0f0f0fu,
-		0xa0a0a0a0u,
-		0x0a0a0a0au,
-		0x50505050u,
-		0x05050505u,
-	};
-
 	/*
 	 * Test up to PMU v5, which is the current maximum version defined by
 	 * Intel, i.e. is the last version that is guaranteed to be backwards
@@ -649,32 +702,9 @@ static void test_intel_counters(void)
 			if (!kvm_has_perf_caps && perf_caps[i])
 				continue;
 
-			pr_info("Testing arch events, PMU version %u, perf_caps = %lx\n",
-				v, perf_caps[i]);
-
-			/*
-			 * Test single bits for all PMU version and lengths up
-			 * the number of events +1 (to verify KVM doesn't do
-			 * weird things if the guest length is greater than the
-			 * host length).  Explicitly test a mask of '0' and all
-			 * ones i.e. all events being available and unavailable.
-			 */
-			for (j = 0; j <= NR_INTEL_ARCH_EVENTS + 1; j++) {
-				for (k = 1; k < ARRAY_SIZE(unavailable_masks); k++)
-					test_arch_events(v, perf_caps[i], j, unavailable_masks[k]);
-			}
-
-			pr_info("Testing GP counters, PMU version %u, perf_caps = %lx\n",
-				v, perf_caps[i]);
-			for (j = 0; j <= nr_gp_counters; j++)
-				test_gp_counters(v, perf_caps[i], j);
-
-			pr_info("Testing fixed counters, PMU version %u, perf_caps = %lx\n",
-				v, perf_caps[i]);
-			for (j = 0; j <= nr_fixed_counters; j++) {
-				for (k = 0; k <= (BIT(nr_fixed_counters) - 1); k++)
-					test_fixed_counters(v, perf_caps[i], j, k);
-			}
+			test_arch_events(v, perf_caps[i]);
+			test_gp_counters(v, perf_caps[i]);
+			test_fixed_counters(v, perf_caps[i]);
 		}
 	}
 }

3/2 2026/08/04 20:52 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 7339
							output: 72
							thoughts: 479
						

Thoughts:
**WorthFuzzing Decision: No**

Okay, so I've got this patch here that touches a few files: `test_util.h`, `test_util.c`, and `pmu_counters_test.c`, all nestled within the KVM selftests directory. My initial thought is to make sure this doesn't accidentally leak into kernel space. A quick check of the diff confirms that it's all staying within `tools/testing/selftests/kvm/`. That's good.

Now, let's think about the fuzzing implications. The prompt provides some guidance. It specifically calls out modifications to Documentation, Kconfig, comments, decorative changes, unreachable code in virtualized environments, PCI switch code, and driver `.remove` functions as reasons for not fuzzing. While it doesn't explicitly mention selftests, I'm interpreting that selftests, being *user-space programs* designed to validate kernel behavior, aren't kernel *code* and therefore aren't what we're aiming to fuzz. We want to fuzz the *kernel* itself, the core execution logic. This patch, confined to selftests, won't affect that.

I'm doing a double check, just to be thorough and I can confirm that there's no kernel code in this diff.

So, I'm going to set the result to `WorthFuzzing=false`. My reasoning will be concise: "The patch only modifies KVM selftests in `tools/testing/selftests/kvm/`, which are user-space test programs and do not change any kernel logic to be fuzzed."

I'll quickly review the diff one more time to make sure I haven't missed anything...Nope, just the selftests.

All right, setting the result now.



4/2 2026/08/04 20:52 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies KVM selftests in tools/testing/selftests/kvm/, which are user-space test programs and do not change any kernel logic to be fuzzed.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies KVM selftests in tools/testing/selftests/kvm/, which are user-space test programs and do not change any kernel logic to be fuzzed.",
  "WorthFuzzing": false
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)