| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/16 06:00 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"kvm_arch_vcpu_run_pid_change",
"kvm_reset_stolen_time"
],
"KMSANReasoning": "The patch simply resets the KVM steal time accounting base (`last_steal`) to the current task's `run_delay` when a vCPU thread changes its host PID. This involves reading a fully initialized scalar value (`current-\u003esched_info.run_delay`) from the scheduler and assigning it to a field in the vCPU architecture structure. No new memory allocations are introduced, no structures are copied to user space, and no complex data structures are manipulated in a way that could expose uninitialized memory. Therefore, there is no risk of uninitialized memory use or info-leaks, and a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false,
"Reasoning": "The patch introduces a mechanism to reset steal-time accounting when a KVM vCPU is run from a different host PID. It modifies core KVM logic for both ARM64 and x86 architectures, adding `kvm_arch_vcpu_run_pid_change` and `kvm_reset_stolen_time`. This is a functional change to reachable KVM code that should be fuzzed to ensure it doesn't introduce regressions or unexpected behavior during vCPU thread migrations.",
"WorthFuzzing": true
} |
| 1/1 | 2026/08/16 06:00 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit af3fc23673193eefa3b2d6aca19c55f9b0c4828d\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sun Aug 16 06:00:11 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h\nindex bae2c4f92ef5c..4607f956e7879 100644\n--- a/arch/arm64/include/asm/kvm_host.h\n+++ b/arch/arm64/include/asm/kvm_host.h\n@@ -1339,6 +1339,7 @@ static inline bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu)\n long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu);\n gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu);\n void kvm_update_stolen_time(struct kvm_vcpu *vcpu);\n+void kvm_reset_stolen_time(struct kvm_vcpu *vcpu);\n \n bool kvm_arm_pvtime_supported(void);\n int kvm_arm_pvtime_set_attr(struct kvm_vcpu *vcpu,\ndiff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c\nindex 9a6c72a186727..0f6e63eace21f 100644\n--- a/arch/arm64/kvm/arm.c\n+++ b/arch/arm64/kvm/arm.c\n@@ -929,6 +929,8 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)\n \tif (!kvm_arm_vcpu_is_finalized(vcpu))\n \t\treturn -EPERM;\n \n+\tkvm_reset_stolen_time(vcpu);\n+\n \tif (likely(vcpu_has_run_once(vcpu)))\n \t\treturn 0;\n \ndiff --git a/arch/arm64/kvm/pvtime.c b/arch/arm64/kvm/pvtime.c\nindex 4ceabaa4c30bd..000bf49cc0fdf 100644\n--- a/arch/arm64/kvm/pvtime.c\n+++ b/arch/arm64/kvm/pvtime.c\n@@ -32,6 +32,11 @@ void kvm_update_stolen_time(struct kvm_vcpu *vcpu)\n \tsrcu_read_unlock(\u0026kvm-\u003esrcu, idx);\n }\n \n+void kvm_reset_stolen_time(struct kvm_vcpu *vcpu)\n+{\n+\tvcpu-\u003earch.steal.last_steal = current-\u003esched_info.run_delay;\n+}\n+\n long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)\n {\n \tu32 feature = smccc_get_arg1(vcpu);\ndiff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig\nindex 801bf9e520db3..b7cb2ceda6d9a 100644\n--- a/arch/x86/kvm/Kconfig\n+++ b/arch/x86/kvm/Kconfig\n@@ -40,6 +40,7 @@ config KVM_X86\n \tselect HAVE_KVM_MSI\n \tselect HAVE_KVM_CPU_RELAX_INTERCEPT\n \tselect HAVE_KVM_NO_POLL\n+\tselect HAVE_KVM_VCPU_RUN_PID_CHANGE\n \tselect VIRT_XFER_TO_GUEST_WORK\n \tselect KVM_GENERIC_DIRTYLOG_READ_PROTECT\n \tselect KVM_VFIO\ndiff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c\nindex 47cb9eba113b1..33be45eec32bc 100644\n--- a/arch/x86/kvm/x86.c\n+++ b/arch/x86/kvm/x86.c\n@@ -3717,6 +3717,13 @@ void kvm_service_local_tlb_flush_requests(struct kvm_vcpu *vcpu)\n }\n EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_service_local_tlb_flush_requests);\n \n+int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)\n+{\n+\tvcpu-\u003earch.st.last_steal = current-\u003esched_info.run_delay;\n+\n+\treturn 0;\n+}\n+\n static void record_steal_time(struct kvm_vcpu *vcpu)\n {\n \tstruct gfn_to_hva_cache *ghc = \u0026vcpu-\u003earch.st.cache;\ndiff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm\nindex 6fc34e9bf8e1b..b01a3403d602a 100644\n--- a/tools/testing/selftests/kvm/Makefile.kvm\n+++ b/tools/testing/selftests/kvm/Makefile.kvm\n@@ -159,6 +159,7 @@ TEST_GEN_PROGS_x86 += hardware_disable_test\n TEST_GEN_PROGS_x86 += mmu_stress_test\n TEST_GEN_PROGS_x86 += rseq_test\n TEST_GEN_PROGS_x86 += steal_time\n+TEST_GEN_PROGS_x86 += steal_time_change_pid\n TEST_GEN_PROGS_x86 += system_counter_offset_test\n TEST_GEN_PROGS_x86 += pre_fault_memory_test\n \n@@ -198,6 +199,7 @@ TEST_GEN_PROGS_arm64 += guest_memfd_test\n TEST_GEN_PROGS_arm64 += mmu_stress_test\n TEST_GEN_PROGS_arm64 += rseq_test\n TEST_GEN_PROGS_arm64 += steal_time\n+TEST_GEN_PROGS_arm64 += steal_time_change_pid\n \n TEST_GEN_PROGS_s390 = $(TEST_GEN_PROGS_COMMON)\n TEST_GEN_PROGS_s390 += s390/memop\ndiff --git a/tools/testing/selftests/kvm/steal_time_change_pid.c b/tools/testing/selftests/kvm/steal_time_change_pid.c\nnew file mode 100644\nindex 0000000000000..12d4927d1c017\n--- /dev/null\n+++ b/tools/testing/selftests/kvm/steal_time_change_pid.c\n@@ -0,0 +1,216 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Verify that KVM resets steal-time accounting when a vCPU fd is run from\n+ * a different host PID.\n+ */\n+\n+#include \u003cpthread.h\u003e\n+#include \u003casm/kvm_para.h\u003e\n+#include \"kvm_util.h\"\n+#include \"processor.h\"\n+\n+#define ST_GPA_BASE\t\t(1 \u003c\u003c 30)\n+#define ST_SANE_DELTA_NS\t(1ULL \u003c\u003c 63)\n+\n+static void *st_gva;\n+static u64 guest_stolen_time;\n+static u64 main_steal;\n+static u64 thread_steal;\n+\n+#if defined(__x86_64__)\n+\n+#define STEAL_TIME_SIZE\t((sizeof(struct kvm_steal_time) + 63) \u0026 ~63)\n+\n+static void guest_code(void)\n+{\n+\tstruct kvm_steal_time *st = st_gva;\n+\n+\tWRITE_ONCE(guest_stolen_time, READ_ONCE(st-\u003esteal));\n+\tGUEST_SYNC(0);\n+\n+\tWRITE_ONCE(guest_stolen_time, READ_ONCE(st-\u003esteal));\n+\tGUEST_SYNC(1);\n+\n+\tWRITE_ONCE(guest_stolen_time, READ_ONCE(st-\u003esteal));\n+\tGUEST_DONE();\n+}\n+\n+static bool steal_time_supported(struct kvm_vcpu *vcpu)\n+{\n+\treturn kvm_cpu_has(X86_FEATURE_KVM_STEAL_TIME);\n+}\n+\n+static void steal_time_enable(struct kvm_vcpu *vcpu)\n+{\n+\tvcpu_set_msr(vcpu, MSR_KVM_STEAL_TIME,\n+\t\t (ulong)st_gva | KVM_MSR_ENABLED);\n+}\n+\n+#elif defined(__aarch64__)\n+\n+#define STEAL_TIME_SIZE\t((sizeof(struct st_time) + 63) \u0026 ~63)\n+\n+#define PV_TIME_ST\t0xc5000021\n+\n+struct st_time {\n+\tu32 rev;\n+\tu32 attr;\n+\tu64 st_time;\n+};\n+\n+static void guest_code(void)\n+{\n+\tstruct arm_smccc_res res;\n+\tstruct st_time *st;\n+\n+\tdo_smccc(PV_TIME_ST, 0, 0, 0, 0, 0, 0, 0, \u0026res);\n+\tGUEST_ASSERT_NE(res.a0, -1);\n+\tGUEST_ASSERT_EQ(res.a0, (ulong)st_gva);\n+\n+\tst = (struct st_time *)res.a0;\n+\tWRITE_ONCE(guest_stolen_time, READ_ONCE(st-\u003est_time));\n+\tGUEST_SYNC(0);\n+\n+\tWRITE_ONCE(guest_stolen_time, READ_ONCE(st-\u003est_time));\n+\tGUEST_SYNC(1);\n+\n+\tWRITE_ONCE(guest_stolen_time, READ_ONCE(st-\u003est_time));\n+\tGUEST_DONE();\n+}\n+\n+static bool steal_time_supported(struct kvm_vcpu *vcpu)\n+{\n+\tstruct kvm_device_attr dev = {\n+\t\t.group = KVM_ARM_VCPU_PVTIME_CTRL,\n+\t\t.attr = KVM_ARM_VCPU_PVTIME_IPA,\n+\t};\n+\n+\treturn !__vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, \u0026dev);\n+}\n+\n+static void steal_time_enable(struct kvm_vcpu *vcpu)\n+{\n+\tu64 st_ipa = (ulong)st_gva;\n+\tstruct kvm_device_attr dev = {\n+\t\t.group = KVM_ARM_VCPU_PVTIME_CTRL,\n+\t\t.attr = KVM_ARM_VCPU_PVTIME_IPA,\n+\t\t.addr = (u64)\u0026st_ipa,\n+\t};\n+\n+\tvcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, \u0026dev);\n+}\n+\n+#else\n+#error \"steal_time_change_pid is not implemented on this architecture\"\n+#endif\n+\n+static void run_vcpu(struct kvm_vcpu *vcpu)\n+{\n+\tstruct ucall uc;\n+\n+\tvcpu_run(vcpu);\n+\n+\tswitch (get_ucall(vcpu, \u0026uc)) {\n+\tcase UCALL_SYNC:\n+\tcase UCALL_DONE:\n+\t\tbreak;\n+\tcase UCALL_ABORT:\n+\t\tREPORT_GUEST_ASSERT(uc);\n+\tdefault:\n+\t\tTEST_ASSERT(false, \"Unexpected exit: %s\",\n+\t\t\t exit_reason_str(vcpu-\u003erun-\u003eexit_reason));\n+\t}\n+}\n+\n+static void *do_steal_time(void *arg)\n+{\n+\tstruct timespec ts, stop;\n+\n+\tclock_gettime(CLOCK_MONOTONIC, \u0026ts);\n+\tstop = timespec_add_ns(ts, MIN_RUN_DELAY_NS);\n+\n+\twhile (timespec_to_ns(timespec_sub(ts, stop)) \u003c 0)\n+\t\tclock_gettime(CLOCK_MONOTONIC, \u0026ts);\n+\n+\treturn NULL;\n+}\n+\n+static void *vcpu_thread(void *arg)\n+{\n+\tstruct kvm_vcpu *vcpu = arg;\n+\n+\trun_vcpu(vcpu);\n+\tsync_global_from_guest(vcpu-\u003evm, guest_stolen_time);\n+\tthread_steal = guest_stolen_time;\n+\n+\treturn NULL;\n+}\n+\n+int main(void)\n+{\n+\tstruct kvm_vcpu *vcpu;\n+\tstruct kvm_vm *vm;\n+\tpthread_attr_t attr;\n+\tpthread_t thread;\n+\tcpu_set_t cpuset;\n+\tlong run_delay;\n+\tlong run_delay_delta;\n+\n+\tksft_print_header();\n+\tksft_set_plan(1);\n+\n+\tCPU_ZERO(\u0026cpuset);\n+\tCPU_SET(0, \u0026cpuset);\n+\tpthread_attr_init(\u0026attr);\n+\tpthread_attr_setaffinity_np(\u0026attr, sizeof(cpuset), \u0026cpuset);\n+\tpthread_setaffinity_np(pthread_self(), sizeof(cpuset), \u0026cpuset);\n+\n+\tvm = vm_create_with_one_vcpu(\u0026vcpu, guest_code);\n+\tvm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,\n+\t\t\t\t ST_GPA_BASE, 1, 1, 0);\n+\tvirt_map(vm, ST_GPA_BASE, ST_GPA_BASE, 1);\n+\n+\tst_gva = (void *)ST_GPA_BASE;\n+\tsync_global_to_guest(vm, st_gva);\n+\tmemset(addr_gva2hva(vm, ST_GPA_BASE), 0, STEAL_TIME_SIZE);\n+\n+\tTEST_REQUIRE(steal_time_supported(vcpu));\n+\n+\tsteal_time_enable(vcpu);\n+\trun_vcpu(vcpu);\n+\n+\trun_delay = get_run_delay();\n+\tpthread_create(\u0026thread, \u0026attr, do_steal_time, NULL);\n+\n+\twhile (get_run_delay() - run_delay \u003c MIN_RUN_DELAY_NS)\n+\t\tsched_yield();\n+\n+\tpthread_join(thread, NULL);\n+\trun_delay_delta = get_run_delay() - run_delay;\n+\tTEST_ASSERT(run_delay_delta \u003e= MIN_RUN_DELAY_NS,\n+\t\t \"Expected run_delay \u003e= %ld, got %ld\",\n+\t\t MIN_RUN_DELAY_NS, run_delay_delta);\n+\n+\trun_vcpu(vcpu);\n+\tsync_global_from_guest(vm, guest_stolen_time);\n+\tmain_steal = guest_stolen_time;\n+\n+\tTEST_ASSERT(main_steal \u003e= MIN_RUN_DELAY_NS,\n+\t\t \"Expected steal time \u003e= %ld, got %\"PRIu64,\n+\t\t MIN_RUN_DELAY_NS, main_steal);\n+\n+\tpthread_create(\u0026thread, NULL, vcpu_thread, vcpu);\n+\tpthread_join(thread, NULL);\n+\n+\tTEST_ASSERT(thread_steal \u003e= main_steal \u0026\u0026\n+\t\t thread_steal - main_steal \u003c ST_SANE_DELTA_NS,\n+\t\t \"Expected sane steal after vCPU pid change: \"\n+\t\t \"old=%\"PRIu64\", new=%\"PRIu64,\n+\t\t main_steal, thread_steal);\n+\n+\tksft_test_result_pass(\"steal time remains sane across vCPU pid change\\n\");\n+\n+\tpthread_attr_destroy(\u0026attr);\n+\tkvm_vm_free(vm);\n+\tksft_finished();\n+}\n"
} |
| 2/1 | 2026/08/16 06:00 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"kvm_arch_vcpu_run_pid_change",
"kvm_reset_stolen_time"
],
"Reasoning": "The patch introduces a mechanism to reset steal-time accounting when a KVM vCPU is run from a different host PID. It modifies core KVM logic for both ARM64 and x86 architectures, adding `kvm_arch_vcpu_run_pid_change` and `kvm_reset_stolen_time`. This is a functional change to reachable KVM code that should be fuzzed to ensure it doesn't introduce regressions or unexpected behavior during vCPU thread migrations.",
"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). - 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 af3fc23673193eefa3b2d6aca19c55f9b0c4828d
Author: syz-cluster <triage@syzkaller.com>
Date: Sun Aug 16 06:00:11 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index bae2c4f92ef5c..4607f956e7879 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -1339,6 +1339,7 @@ static inline bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu)
long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu);
gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu);
void kvm_update_stolen_time(struct kvm_vcpu *vcpu);
+void kvm_reset_stolen_time(struct kvm_vcpu *vcpu);
bool kvm_arm_pvtime_supported(void);
int kvm_arm_pvtime_set_attr(struct kvm_vcpu *vcpu,
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 9a6c72a186727..0f6e63eace21f 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -929,6 +929,8 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
if (!kvm_arm_vcpu_is_finalized(vcpu))
return -EPERM;
+ kvm_reset_stolen_time(vcpu);
+
if (likely(vcpu_has_run_once(vcpu)))
return 0;
diff --git a/arch/arm64/kvm/pvtime.c b/arch/arm64/kvm/pvtime.c
index 4ceabaa4c30bd..000bf49cc0fdf 100644
--- a/arch/arm64/kvm/pvtime.c
+++ b/arch/arm64/kvm/pvtime.c
@@ -32,6 +32,11 @@ void kvm_update_stolen_time(struct kvm_vcpu *vcpu)
srcu_read_unlock(&kvm->srcu, idx);
}
+void kvm_reset_stolen_time(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.steal.last_steal = current->sched_info.run_delay;
+}
+
long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
{
u32 feature = smccc_get_arg1(vcpu);
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 801bf9e520db3..b7cb2ceda6d9a 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -40,6 +40,7 @@ config KVM_X86
select HAVE_KVM_MSI
select HAVE_KVM_CPU_RELAX_INTERCEPT
select HAVE_KVM_NO_POLL
+ select HAVE_KVM_VCPU_RUN_PID_CHANGE
select VIRT_XFER_TO_GUEST_WORK
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_VFIO
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 47cb9eba113b1..33be45eec32bc 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3717,6 +3717,13 @@ void kvm_service_local_tlb_flush_requests(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_service_local_tlb_flush_requests);
+int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.st.last_steal = current->sched_info.run_delay;
+
+ return 0;
+}
+
static void record_steal_time(struct kvm_vcpu *vcpu)
{
struct gfn_to_hva_cache *ghc = &vcpu->arch.st.cache;
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 6fc34e9bf8e1b..b01a3403d602a 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -159,6 +159,7 @@ TEST_GEN_PROGS_x86 += hardware_disable_test
TEST_GEN_PROGS_x86 += mmu_stress_test
TEST_GEN_PROGS_x86 += rseq_test
TEST_GEN_PROGS_x86 += steal_time
+TEST_GEN_PROGS_x86 += steal_time_change_pid
TEST_GEN_PROGS_x86 += system_counter_offset_test
TEST_GEN_PROGS_x86 += pre_fault_memory_test
@@ -198,6 +199,7 @@ TEST_GEN_PROGS_arm64 += guest_memfd_test
TEST_GEN_PROGS_arm64 += mmu_stress_test
TEST_GEN_PROGS_arm64 += rseq_test
TEST_GEN_PROGS_arm64 += steal_time
+TEST_GEN_PROGS_arm64 += steal_time_change_pid
TEST_GEN_PROGS_s390 = $(TEST_GEN_PROGS_COMMON)
TEST_GEN_PROGS_s390 += s390/memop
diff --git a/tools/testing/selftests/kvm/steal_time_change_pid.c b/tools/testing/selftests/kvm/steal_time_change_pid.c
new file mode 100644
index 0000000000000..12d4927d1c017
--- /dev/null
+++ b/tools/testing/selftests/kvm/steal_time_change_pid.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Verify that KVM resets steal-time accounting when a vCPU fd is run from
+ * a different host PID.
+ */
+
+#include <pthread.h>
+#include <asm/kvm_para.h>
+#include "kvm_util.h"
+#include "processor.h"
+
+#define ST_GPA_BASE (1 << 30)
+#define ST_SANE_DELTA_NS (1ULL << 63)
+
+static void *st_gva;
+static u64 guest_stolen_time;
+static u64 main_steal;
+static u64 thread_steal;
+
+#if defined(__x86_64__)
+
+#define STEAL_TIME_SIZE ((sizeof(struct kvm_steal_time) + 63) & ~63)
+
+static void guest_code(void)
+{
+ struct kvm_steal_time *st = st_gva;
+
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->steal));
+ GUEST_SYNC(0);
+
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->steal));
+ GUEST_SYNC(1);
+
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->steal));
+ GUEST_DONE();
+}
+
+static bool steal_time_supported(struct kvm_vcpu *vcpu)
+{
+ return kvm_cpu_has(X86_FEATURE_KVM_STEAL_TIME);
+}
+
+static void steal_time_enable(struct kvm_vcpu *vcpu)
+{
+ vcpu_set_msr(vcpu, MSR_KVM_STEAL_TIME,
+ (ulong)st_gva | KVM_MSR_ENABLED);
+}
+
+#elif defined(__aarch64__)
+
+#define STEAL_TIME_SIZE ((sizeof(struct st_time) + 63) & ~63)
+
+#define PV_TIME_ST 0xc5000021
+
+struct st_time {
+ u32 rev;
+ u32 attr;
+ u64 st_time;
+};
+
+static void guest_code(void)
+{
+ struct arm_smccc_res res;
+ struct st_time *st;
+
+ do_smccc(PV_TIME_ST, 0, 0, 0, 0, 0, 0, 0, &res);
+ GUEST_ASSERT_NE(res.a0, -1);
+ GUEST_ASSERT_EQ(res.a0, (ulong)st_gva);
+
+ st = (struct st_time *)res.a0;
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->st_time));
+ GUEST_SYNC(0);
+
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->st_time));
+ GUEST_SYNC(1);
+
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->st_time));
+ GUEST_DONE();
+}
+
+static bool steal_time_supported(struct kvm_vcpu *vcpu)
+{
+ struct kvm_device_attr dev = {
+ .group = KVM_ARM_VCPU_PVTIME_CTRL,
+ .attr = KVM_ARM_VCPU_PVTIME_IPA,
+ };
+
+ return !__vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &dev);
+}
+
+static void steal_time_enable(struct kvm_vcpu *vcpu)
+{
+ u64 st_ipa = (ulong)st_gva;
+ struct kvm_device_attr dev = {
+ .group = KVM_ARM_VCPU_PVTIME_CTRL,
+ .attr = KVM_ARM_VCPU_PVTIME_IPA,
+ .addr = (u64)&st_ipa,
+ };
+
+ vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &dev);
+}
+
+#else
+#error "steal_time_change_pid is not implemented on this architecture"
+#endif
+
+static void run_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct ucall uc;
+
+ vcpu_run(vcpu);
+
+ switch (get_ucall(vcpu, &uc)) {
+ case UCALL_SYNC:
+ case UCALL_DONE:
+ break;
+ case UCALL_ABORT:
+ REPORT_GUEST_ASSERT(uc);
+ default:
+ TEST_ASSERT(false, "Unexpected exit: %s",
+ exit_reason_str(vcpu->run->exit_reason));
+ }
+}
+
+static void *do_steal_time(void *arg)
+{
+ struct timespec ts, stop;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ stop = timespec_add_ns(ts, MIN_RUN_DELAY_NS);
+
+ while (timespec_to_ns(timespec_sub(ts, stop)) < 0)
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ return NULL;
+}
+
+static void *vcpu_thread(void *arg)
+{
+ struct kvm_vcpu *vcpu = arg;
+
+ run_vcpu(vcpu);
+ sync_global_from_guest(vcpu->vm, guest_stolen_time);
+ thread_steal = guest_stolen_time;
+
+ return NULL;
+}
+
+int main(void)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+ pthread_attr_t attr;
+ pthread_t thread;
+ cpu_set_t cpuset;
+ long run_delay;
+ long run_delay_delta;
+
+ ksft_print_header();
+ ksft_set_plan(1);
+
+ CPU_ZERO(&cpuset);
+ CPU_SET(0, &cpuset);
+ pthread_attr_init(&attr);
+ pthread_attr_setaffinity_np(&attr, sizeof(cpuset), &cpuset);
+ pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
+
+ vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+ vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
+ ST_GPA_BASE, 1, 1, 0);
+ virt_map(vm, ST_GPA_BASE, ST_GPA_BASE, 1);
+
+ st_gva = (void *)ST_GPA_BASE;
+ sync_global_to_guest(vm, st_gva);
+ memset(addr_gva2hva(vm, ST_GPA_BASE), 0, STEAL_TIME_SIZE);
+
+ TEST_REQUIRE(steal_time_supported(vcpu));
+
+ steal_time_enable(vcpu);
+ run_vcpu(vcpu);
+
+ run_delay = get_run_delay();
+ pthread_create(&thread, &attr, do_steal_time, NULL);
+
+ while (get_run_delay() - run_delay < MIN_RUN_DELAY_NS)
+ sched_yield();
+
+ pthread_join(thread, NULL);
+ run_delay_delta = get_run_delay() - run_delay;
+ TEST_ASSERT(run_delay_delta >= MIN_RUN_DELAY_NS,
+ "Expected run_delay >= %ld, got %ld",
+ MIN_RUN_DELAY_NS, run_delay_delta);
+
+ run_vcpu(vcpu);
+ sync_global_from_guest(vm, guest_stolen_time);
+ main_steal = guest_stolen_time;
+
+ TEST_ASSERT(main_steal >= MIN_RUN_DELAY_NS,
+ "Expected steal time >= %ld, got %"PRIu64,
+ MIN_RUN_DELAY_NS, main_steal);
+
+ pthread_create(&thread, NULL, vcpu_thread, vcpu);
+ pthread_join(thread, NULL);
+
+ TEST_ASSERT(thread_steal >= main_steal &&
+ thread_steal - main_steal < ST_SANE_DELTA_NS,
+ "Expected sane steal after vCPU pid change: "
+ "old=%"PRIu64", new=%"PRIu64,
+ main_steal, thread_steal);
+
+ ksft_test_result_pass("steal time remains sane across vCPU pid change\n");
+
+ pthread_attr_destroy(&attr);
+ kvm_vm_free(vm);
+ ksft_finished();
+}
|
| 3/2 | 2026/08/16 06:00 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5875 output: 27 thoughts: 212 Thoughts: **Analyzing the KVM Patch for Stolen Time Reset** Okay, so I'm looking at this patch and it seems pretty straightforward on the surface, but I need to dive a little deeper. The core of it revolves around resetting stolen time within KVM, specifically during PID changes. This makes sense; when a vCPU is context-switching, especially to different PIDs, the steal time accumulated needs to be accurately reflected. The patch implements a new function, `kvm_reset_stolen_time`, and integrates it within `arch/arm64/kvm/pvtime.c` and calls it from `kvm_arch_vcpu_run_pid_change` in `arch/arm64/kvm/arm.c`. Good. It also addresses the x86 architecture, adding the function `kvm_arch_vcpu_run_pid_change` in `arch/x86/kvm/x86.c`. On x86, it resets `vcpu->arch.st.last_steal`. That's where things get interesting, ensuring the steal time counter is properly cleared on the x86 architecture. It's using the `HAVE_KVM_VCPU_RUN_PID_CHANGE` Kconfig option for KVM_X86. So that's the guard. I'll need to double-check the implications of that config option, but my initial thought is, if defined it means we support the new functionality. And, of course, the obligatory selftest, `steal_time_change_pid.c`, to validate that all of this is working as expected. That's good practice. I always stress the importance of thorough testing, especially when dealing with timing-sensitive issues like this. I'm going to quickly use `grepper` to see *where* `kvm_arch_vcpu_run_pid_change` is called, just to get a good contextual understanding of how the new function is being used. I need to make sure I understand the call graph and the surrounding logic to fully appreciate the impact of this. Gotta cover all my bases. |
| 4/2 | 2026/08/16 06:00 | tool | grepper |
0mArgs:{
"Expression": "kvm_arch_vcpu_run_pid_change"
}Results: {
"Output": "arch/arm64/kvm/arm.c=864=static void kvm_init_mpidr_data(struct kvm *kvm)\n--\narch/arm64/kvm/arm.c-920- */\narch/arm64/kvm/arm.c:921:int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)\narch/arm64/kvm/arm.c-922-{\n--\narch/x86/kvm/x86.c=3718=EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_service_local_tlb_flush_requests);\narch/x86/kvm/x86.c-3719-\narch/x86/kvm/x86.c:3720:int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)\narch/x86/kvm/x86.c-3721-{\n--\ninclude/linux/kvm_host.h=2460=void kvm_arch_guest_memory_reclaimed(struct kvm *kvm);\n--\ninclude/linux/kvm_host.h-2462-#ifdef CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE\ninclude/linux/kvm_host.h:2463:int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu);\ninclude/linux/kvm_host.h-2464-#else\ninclude/linux/kvm_host.h:2465:static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)\ninclude/linux/kvm_host.h-2466-{\n--\nvirt/kvm/kvm_main.c=4406=static long kvm_vcpu_ioctl(struct file *filp,\n--\nvirt/kvm/kvm_main.c-4457-\nvirt/kvm/kvm_main.c:4458:\t\t\tr = kvm_arch_vcpu_run_pid_change(vcpu);\nvirt/kvm/kvm_main.c-4459-\t\t\tif (r)\n"
} |
| 5/2 | 2026/08/16 06:00 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7153 output: 40 thoughts: 69 Thoughts: Here's my take on the thought process, considering I'm an expert: **Investigating a KVM VCPU PID Change** Okay, so `kvm_arch_vcpu_run_pid_change` is the function of interest. The trace shows it being called from `kvm_vcpu_ioctl`, specifically in `virt/kvm/kvm_main.c`. That's a good starting point. I need to understand the context of that call, so I'll jump directly into `virt/kvm/kvm_main.c`. Let's assume the function call is around line 4458. Time to get my bearings and see what triggers the `kvm_arch_vcpu_run_pid_change` function call. Need to understand the logic flow, what data is passed, and what this PID change actually signifies within the VCPU's lifecycle. I'll be looking for potential race conditions or synchronization issues related to process ID management within the KVM environment. |
| 6/2 | 2026/08/16 06:00 | tool | read-file |
0mArgs:{
"File": "virt/kvm/kvm_main.c",
"FirstLine": 4440,
"LineCount": 30
}Results: {
"Contents": "4440:\t\tswitch (ioctl) {\n4441:\t\tcase KVM_RUN: {\n4442:\t\t\tstruct pid *oldpid;\n4443:\t\t\tr = -EINVAL;\n4444:\t\t\tif (arg)\n4445:\t\t\t\tgoto out;\n4446:\t\n4447:\t\t\t/*\n4448:\t\t\t * Note, vcpu-\u003epid is primarily protected by vcpu-\u003emutex. The\n4449:\t\t\t * dedicated r/w lock allows other tasks, e.g. other vCPUs, to\n4450:\t\t\t * read vcpu-\u003epid while this vCPU is in KVM_RUN, e.g. to yield\n4451:\t\t\t * directly to this vCPU\n4452:\t\t\t */\n4453:\t\t\toldpid = vcpu-\u003epid;\n4454:\t\t\tif (unlikely(oldpid != task_pid(current))) {\n4455:\t\t\t\t/* The thread running this VCPU changed. */\n4456:\t\t\t\tstruct pid *newpid;\n4457:\t\n4458:\t\t\t\tr = kvm_arch_vcpu_run_pid_change(vcpu);\n4459:\t\t\t\tif (r)\n4460:\t\t\t\t\tbreak;\n4461:\t\n4462:\t\t\t\tnewpid = get_task_pid(current, PIDTYPE_PID);\n4463:\t\t\t\twrite_lock(\u0026vcpu-\u003epid_lock);\n4464:\t\t\t\tvcpu-\u003epid = newpid;\n4465:\t\t\t\twrite_unlock(\u0026vcpu-\u003epid_lock);\n4466:\t\n4467:\t\t\t\tput_pid(oldpid);\n4468:\t\t\t}\n4469:\t\t\tvcpu-\u003ewants_to_run = !READ_ONCE(vcpu-\u003erun-\u003eimmediate_exit__unsafe);\n"
} |
| 7/2 | 2026/08/16 06:00 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7947 output: 17 thoughts: 518 Thoughts: **KVM Functionality Assessment** Okay, so `kvm_arch_vcpu_run_pid_change` is triggered when a vCPU switches execution threads. That's a clearly defined point of interaction, and therefore, definitely fuzzable. My immediate thought is, this is a functional change warranting thorough investigation. The patch itself modifies this function in both `arch/x86/kvm/x86.c` and `arch/arm64/kvm/arm.c`. Looking at the x86 code, we have `vcpu->arch.st.last_steal = current->sched_info.run_delay;` which appears to be recording steal time, or the time the vCPU was ready to run but couldn't because the host was busy. The ARM64 code is a little more involved. It has an early return if the vCPU isn't finalized, then calls `kvm_reset_stolen_time`. And that `kvm_reset_stolen_time` function sets `vcpu->arch.steal.last_steal` to `current->sched_info.run_delay`. So, again, it's dealing with steal time. Since this change is about handling the context switch and potentially impacting how stolen time is accounted for, my fuzzing focus will be on the `kvm_arch_vcpu_run_pid_change` and the `kvm_reset_stolen_time` functions directly. Regarding the Kconfig options, I need to make sure the fuzzing environment is correctly configured. For x86, it's `KVM` and `KVM_X86`, the latter being implicitly set by `KVM`. For arm64, just `KVM` is sufficient. I should double-check the `arch/x86/kvm/Kconfig` and `arch/arm64/kvm/Kconfig` files to verify these configurations are in place, but I'm pretty confident in the initial assessment of the required dependencies. |
| 8/2 | 2026/08/16 06:00 | tool | grepper |
0mArgs:{
"Expression": "config KVM"
}Results: {
"Output": "arch/arm64/kvm/Kconfig=18=if VIRTUALIZATION\narch/arm64/kvm/Kconfig-19-\narch/arm64/kvm/Kconfig:20:menuconfig KVM\narch/arm64/kvm/Kconfig-21-\tbool \"Kernel-based Virtual Machine (KVM) support\"\n--\narch/loongarch/kvm/Kconfig=18=if VIRTUALIZATION\narch/loongarch/kvm/Kconfig-19-\narch/loongarch/kvm/Kconfig:20:config KVM\narch/loongarch/kvm/Kconfig-21-\ttristate \"Kernel-based Virtual Machine (KVM) support\"\n--\narch/mips/kvm/Kconfig=16=if VIRTUALIZATION\narch/mips/kvm/Kconfig-17-\narch/mips/kvm/Kconfig:18:config KVM\narch/mips/kvm/Kconfig-19-\ttristate \"Kernel-based Virtual Machine (KVM) support\"\n--\narch/mips/kvm/Kconfig-30-\narch/mips/kvm/Kconfig:31:config KVM_MIPS_DEBUG_COP0_COUNTERS\narch/mips/kvm/Kconfig-32-\tbool \"Maintain counters for COP0 accesses\"\n--\narch/powerpc/kvm/Kconfig=18=if VIRTUALIZATION\narch/powerpc/kvm/Kconfig-19-\narch/powerpc/kvm/Kconfig:20:config KVM\narch/powerpc/kvm/Kconfig-21-\tbool\n--\narch/powerpc/kvm/Kconfig-25-\narch/powerpc/kvm/Kconfig:26:config KVM_BOOK3S_HANDLER\narch/powerpc/kvm/Kconfig-27-\tbool\narch/powerpc/kvm/Kconfig-28-\narch/powerpc/kvm/Kconfig:29:config KVM_BOOK3S_32_HANDLER\narch/powerpc/kvm/Kconfig-30-\tbool\n--\narch/powerpc/kvm/Kconfig-33-\narch/powerpc/kvm/Kconfig:34:config KVM_BOOK3S_64_HANDLER\narch/powerpc/kvm/Kconfig-35-\tbool\n--\narch/powerpc/kvm/Kconfig-37-\narch/powerpc/kvm/Kconfig:38:config KVM_BOOK3S_PR_POSSIBLE\narch/powerpc/kvm/Kconfig-39-\tbool\n--\narch/powerpc/kvm/Kconfig-41-\narch/powerpc/kvm/Kconfig:42:config KVM_BOOK3S_HV_POSSIBLE\narch/powerpc/kvm/Kconfig-43-\tbool\narch/powerpc/kvm/Kconfig-44-\narch/powerpc/kvm/Kconfig:45:config KVM_BOOK3S_32\narch/powerpc/kvm/Kconfig-46-\ttristate \"KVM support for PowerPC book3s_32 processors\"\n--\narch/powerpc/kvm/Kconfig-61-\narch/powerpc/kvm/Kconfig:62:config KVM_BOOK3S_64\narch/powerpc/kvm/Kconfig-63-\ttristate \"KVM support for PowerPC book3s_64 processors\"\n--\narch/powerpc/kvm/Kconfig-78-\narch/powerpc/kvm/Kconfig:79:config KVM_BOOK3S_64_HV\narch/powerpc/kvm/Kconfig-80-\ttristate \"KVM for POWER7 and later using hypervisor mode in host\"\n--\narch/powerpc/kvm/Kconfig-99-\narch/powerpc/kvm/Kconfig:100:config KVM_BOOK3S_64_PR\narch/powerpc/kvm/Kconfig-101-\ttristate \"KVM support without using hypervisor mode in host\"\n--\narch/powerpc/kvm/Kconfig-125-\narch/powerpc/kvm/Kconfig:126:config KVM_BOOK3S_HV_EXIT_TIMING\narch/powerpc/kvm/Kconfig-127-\tbool\narch/powerpc/kvm/Kconfig-128-\narch/powerpc/kvm/Kconfig:129:config KVM_BOOK3S_HV_P9_TIMING\narch/powerpc/kvm/Kconfig-130-\tbool \"Detailed timing for the P9 entry point\"\n--\narch/powerpc/kvm/Kconfig-141-\narch/powerpc/kvm/Kconfig:142:config KVM_BOOK3S_HV_P8_TIMING\narch/powerpc/kvm/Kconfig-143-\tbool \"Detailed timing for hypervisor real-mode code (for POWER8)\"\n--\narch/powerpc/kvm/Kconfig-156-\narch/powerpc/kvm/Kconfig:157:config KVM_BOOK3S_HV_NESTED_PMU_WORKAROUND\narch/powerpc/kvm/Kconfig-158-\tbool \"Nested L0 host workaround for L1 KVM host PMU handling bug\" if EXPERT\n--\narch/powerpc/kvm/Kconfig-171-\narch/powerpc/kvm/Kconfig:172:config KVM_BOOK3S_HV_PMU\narch/powerpc/kvm/Kconfig-173-\ttristate \"Hypervisor Perf events for KVM Book3s-HV\"\n--\narch/powerpc/kvm/Kconfig-183-\narch/powerpc/kvm/Kconfig:184:config KVM_BOOKE_HV\narch/powerpc/kvm/Kconfig-185-\tbool\narch/powerpc/kvm/Kconfig-186-\narch/powerpc/kvm/Kconfig:187:config KVM_EXIT_TIMING\narch/powerpc/kvm/Kconfig-188-\tbool \"Detailed exit timing\"\n--\narch/powerpc/kvm/Kconfig-197-\narch/powerpc/kvm/Kconfig:198:config KVM_E500V2\narch/powerpc/kvm/Kconfig-199-\tbool \"KVM support for PowerPC E500v2 processors\"\n--\narch/powerpc/kvm/Kconfig-212-\narch/powerpc/kvm/Kconfig:213:config KVM_E500MC\narch/powerpc/kvm/Kconfig-214-\tbool \"KVM support for PowerPC E500MC/E5500/E6500 processors\"\n--\narch/powerpc/kvm/Kconfig-228-\narch/powerpc/kvm/Kconfig:229:config KVM_MPIC\narch/powerpc/kvm/Kconfig-230-\tbool \"KVM in-kernel MPIC emulation\"\n--\narch/powerpc/kvm/Kconfig-240-\narch/powerpc/kvm/Kconfig:241:config KVM_XICS\narch/powerpc/kvm/Kconfig-242-\tbool \"KVM in-kernel XICS emulation\"\n--\narch/powerpc/kvm/Kconfig-250-\narch/powerpc/kvm/Kconfig:251:config KVM_XIVE\narch/powerpc/kvm/Kconfig-252-\tbool\n--\narch/powerpc/platforms/Kconfig=22=source \"arch/powerpc/platforms/microwatt/Kconfig\"\narch/powerpc/platforms/Kconfig-23-\narch/powerpc/platforms/Kconfig:24:config KVM_GUEST\narch/powerpc/platforms/Kconfig-25-\tbool \"KVM Guest support\"\n--\narch/riscv/kvm/Kconfig=18=if VIRTUALIZATION\narch/riscv/kvm/Kconfig-19-\narch/riscv/kvm/Kconfig:20:config KVM\narch/riscv/kvm/Kconfig-21-\ttristate \"Kernel-based Virtual Machine (KVM) support\"\n--\narch/s390/kvm/Kconfig=17=if VIRTUALIZATION\narch/s390/kvm/Kconfig-18-\narch/s390/kvm/Kconfig:19:config KVM\narch/s390/kvm/Kconfig-20-\tdef_tristate y\n--\narch/s390/kvm/Kconfig-46-\narch/s390/kvm/Kconfig:47:config KVM_S390_UCONTROL\narch/s390/kvm/Kconfig-48-\tbool \"Userspace controlled virtual machines\"\n--\narch/x86/Kconfig=826=source \"arch/x86/xen/Kconfig\"\narch/x86/Kconfig-827-\narch/x86/Kconfig:828:config KVM_GUEST\narch/x86/Kconfig-829-\tbool \"KVM Guest support (including kvmclock)\"\n--\narch/x86/kvm/Kconfig=18=if VIRTUALIZATION\narch/x86/kvm/Kconfig-19-\narch/x86/kvm/Kconfig:20:config KVM_X86\narch/x86/kvm/Kconfig-21-\tdef_tristate KVM if (KVM_INTEL != n || KVM_AMD != n)\n--\narch/x86/kvm/Kconfig-52-\narch/x86/kvm/Kconfig:53:config KVM\narch/x86/kvm/Kconfig-54-\ttristate \"Kernel-based Virtual Machine (KVM) support\"\n--\narch/x86/kvm/Kconfig-69-\narch/x86/kvm/Kconfig:70:config KVM_WERROR\narch/x86/kvm/Kconfig-71-\tbool \"Compile KVM with -Werror\"\n--\narch/x86/kvm/Kconfig-83-\narch/x86/kvm/Kconfig:84:config KVM_SW_PROTECTED_VM\narch/x86/kvm/Kconfig-85-\tbool \"Enable support for KVM software-protected VMs\"\n--\narch/x86/kvm/Kconfig-96-\narch/x86/kvm/Kconfig:97:config KVM_INTEL\narch/x86/kvm/Kconfig-98-\ttristate \"KVM for Intel (and compatible) processors support\"\n--\narch/x86/kvm/Kconfig-107-\narch/x86/kvm/Kconfig:108:config KVM_INTEL_PROVE_VE\narch/x86/kvm/Kconfig-109- bool \"Check that guests do not receive #VE exceptions\"\n--\narch/x86/kvm/Kconfig=123=config X86_SGX_KVM\n--\narch/x86/kvm/Kconfig-134-\narch/x86/kvm/Kconfig:135:config KVM_INTEL_TDX\narch/x86/kvm/Kconfig-136-\tbool \"Intel Trust Domain Extensions (TDX) support\"\n--\narch/x86/kvm/Kconfig-146-\narch/x86/kvm/Kconfig:147:config KVM_AMD\narch/x86/kvm/Kconfig-148-\ttristate \"KVM for AMD processors support\"\n--\narch/x86/kvm/Kconfig-156-\narch/x86/kvm/Kconfig:157:config KVM_AMD_SEV\narch/x86/kvm/Kconfig-158-\tbool \"AMD Secure Encrypted Virtualization (SEV) support\"\n--\narch/x86/kvm/Kconfig-172-\narch/x86/kvm/Kconfig:173:config KVM_IOAPIC\narch/x86/kvm/Kconfig-174-\tbool \"I/O APIC, PIC, and PIT emulation\"\n--\narch/x86/kvm/Kconfig-182-\narch/x86/kvm/Kconfig:183:config KVM_SMM\narch/x86/kvm/Kconfig-184-\tbool \"System Management Mode emulation\"\n--\narch/x86/kvm/Kconfig-193-\narch/x86/kvm/Kconfig:194:config KVM_HYPERV\narch/x86/kvm/Kconfig-195-\tbool \"Support for Microsoft Hyper-V emulation\"\n--\narch/x86/kvm/Kconfig-207-\narch/x86/kvm/Kconfig:208:config KVM_XEN\narch/x86/kvm/Kconfig-209-\tbool \"Support for Xen hypercall interface\"\n--\narch/x86/kvm/Kconfig-216-\narch/x86/kvm/Kconfig:217:config KVM_PROVE_MMU\narch/x86/kvm/Kconfig-218-\tbool \"Prove KVM MMU correctness\"\n--\narch/x86/kvm/Kconfig-229-\narch/x86/kvm/Kconfig:230:config KVM_EXTERNAL_WRITE_TRACKING\narch/x86/kvm/Kconfig-231-\tbool\narch/x86/kvm/Kconfig-232-\narch/x86/kvm/Kconfig:233:config KVM_MAX_NR_VCPUS\narch/x86/kvm/Kconfig-234-\tint \"Maximum number of vCPUs per KVM guest\"\n--\nvirt/kvm/Kconfig-3-\nvirt/kvm/Kconfig:4:config KVM_COMMON\nvirt/kvm/Kconfig-5- bool\n--\nvirt/kvm/Kconfig=39=config NEED_KVM_DIRTY_RING_WITH_BITMAP\n--\nvirt/kvm/Kconfig-42-\nvirt/kvm/Kconfig:43:config KVM_MMIO\nvirt/kvm/Kconfig-44- bool\nvirt/kvm/Kconfig-45-\nvirt/kvm/Kconfig:46:config KVM_ASYNC_PF\nvirt/kvm/Kconfig-47- bool\n--\nvirt/kvm/Kconfig-49-# Toggle to switch between direct notification and batch job\nvirt/kvm/Kconfig:50:config KVM_ASYNC_PF_SYNC\nvirt/kvm/Kconfig-51- bool\n--\nvirt/kvm/Kconfig=59=config HAVE_KVM_CPU_RELAX_INTERCEPT\n--\nvirt/kvm/Kconfig-61-\nvirt/kvm/Kconfig:62:config KVM_VFIO\nvirt/kvm/Kconfig-63- bool\n--\nvirt/kvm/Kconfig=65=config HAVE_KVM_INVALID_WAKEUPS\n--\nvirt/kvm/Kconfig-67-\nvirt/kvm/Kconfig:68:config KVM_GENERIC_DIRTYLOG_READ_PROTECT\nvirt/kvm/Kconfig-69- bool\nvirt/kvm/Kconfig-70-\nvirt/kvm/Kconfig:71:config KVM_GENERIC_PRE_FAULT_MEMORY\nvirt/kvm/Kconfig-72- bool\nvirt/kvm/Kconfig-73-\nvirt/kvm/Kconfig:74:config KVM_COMPAT\nvirt/kvm/Kconfig-75- def_bool y\n--\nvirt/kvm/Kconfig=91=config HAVE_KVM_PM_NOTIFIER\n--\nvirt/kvm/Kconfig-93-\nvirt/kvm/Kconfig:94:config KVM_GENERIC_HARDWARE_ENABLING\nvirt/kvm/Kconfig-95- bool\nvirt/kvm/Kconfig-96-\nvirt/kvm/Kconfig:97:config KVM_ELIDE_TLB_FLUSH_IF_YOUNG\nvirt/kvm/Kconfig-98- bool\nvirt/kvm/Kconfig-99-\nvirt/kvm/Kconfig:100:config KVM_MMU_LOCKLESS_AGING\nvirt/kvm/Kconfig-101- bool\nvirt/kvm/Kconfig-102-\nvirt/kvm/Kconfig:103:config KVM_GENERIC_MEMORY_ATTRIBUTES\nvirt/kvm/Kconfig-104- bool\nvirt/kvm/Kconfig-105-\nvirt/kvm/Kconfig:106:config KVM_GUEST_MEMFD\nvirt/kvm/Kconfig-107- select XARRAY_MULTI\n"
} |
| 9/2 | 2026/08/16 06:00 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13209 output: 28 thoughts: 189 Thoughts: **My KVM Configuration Analysis** Okay, so I'm looking at these configurations. The focus is definitely `KVM`. For x86, it's pretty standard that `KVM` relies on either `KVM_INTEL` or `KVM_AMD`, but `KVM` itself is the core. Right, `KVM` is defined as a tristate option for "Kernel-based Virtual Machine (KVM) support." That makes sense; I'll definitely include `KVM` in the `EnableConfigs` list. Now, let's just quickly confirm that `HAVE_KVM_VCPU_RUN_PID_CHANGE` is something we need to consider. Ah, yes, it's selected by both `KVM_X86` and `KVM` on arm64 architectures. Now hold on a second... the diff doesn't seem to explicitly add `HAVE_KVM_VCPU_RUN_PID_CHANGE` to the `arch/arm64/kvm/Kconfig` file. I'd better double-check the `arch/arm64/kvm/Kconfig` to be absolutely sure what's going on there. Gotta be thorough. |
| 10/2 | 2026/08/16 06:00 | tool | grepper |
0mArgs:{
"Expression": "HAVE_KVM_VCPU_RUN_PID_CHANGE"
}Results: {
"Output": "arch/arm64/kvm/Kconfig=20=menuconfig KVM\n--\narch/arm64/kvm/Kconfig-35-\tselect HAVE_KVM_READONLY_MEM\narch/arm64/kvm/Kconfig:36:\tselect HAVE_KVM_VCPU_RUN_PID_CHANGE\narch/arm64/kvm/Kconfig-37-\tselect SCHED_INFO\n--\narch/x86/kvm/Kconfig=20=config KVM_X86\n--\narch/x86/kvm/Kconfig-42-\tselect HAVE_KVM_NO_POLL\narch/x86/kvm/Kconfig:43:\tselect HAVE_KVM_VCPU_RUN_PID_CHANGE\narch/x86/kvm/Kconfig-44-\tselect VIRT_XFER_TO_GUEST_WORK\n--\ninclude/linux/kvm_host.h=2460=void kvm_arch_guest_memory_reclaimed(struct kvm *kvm);\ninclude/linux/kvm_host.h-2461-\ninclude/linux/kvm_host.h:2462:#ifdef CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE\ninclude/linux/kvm_host.h-2463-int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu);\n--\ninclude/linux/kvm_host.h=2465=static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)\n--\ninclude/linux/kvm_host.h-2468-}\ninclude/linux/kvm_host.h:2469:#endif /* CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE */\ninclude/linux/kvm_host.h-2470-\n--\nvirt/kvm/Kconfig=78=config HAVE_KVM_IRQ_BYPASS\n--\nvirt/kvm/Kconfig-81-\nvirt/kvm/Kconfig:82:config HAVE_KVM_VCPU_RUN_PID_CHANGE\nvirt/kvm/Kconfig-83- bool\n"
} |
| 11/2 | 2026/08/16 06:00 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14246 output: 165 thoughts: 212 Thoughts: **My Assessment of the KVM Steal-Time Reset Patch** Okay, so I see this patch is triggered by `KVM` on arm64 and `KVM_X86` on x86, which confirms `KVM` is the primary configuration variable at play here. Let me quickly scan for any other potentially relevant configurations... nope, `KVM` seems to be the only thing we need to consider. The core of the change revolves around resetting steal-time accounting when a KVM vCPU transitions to a new host PID. This directly impacts core KVM logic across both ARM64 and x86 architectures, and the code introduces `kvm_arch_vcpu_run_pid_change` and `kvm_reset_stolen_time`. These are significant functional additions within the KVM code. Given their direct impact on vCPU migration behavior, this is an area that *absolutely* warrants targeted fuzzing. We need to ensure that this change doesn't introduce any performance regressions or, even worse, unanticipated behavioral shifts during vCPU thread migrations. Right, I'm confident in this evaluation, I'll go ahead and log the results now. |
| 12/2 | 2026/08/16 06:00 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"kvm_arch_vcpu_run_pid_change",
"kvm_reset_stolen_time"
],
"Reasoning": "The patch introduces a mechanism to reset steal-time accounting when a KVM vCPU is run from a different host PID. It modifies core KVM logic for both ARM64 and x86 architectures, adding `kvm_arch_vcpu_run_pid_change` and `kvm_reset_stolen_time`. This is a functional change to reachable KVM code that should be fuzzed to ensure it doesn't introduce regressions or unexpected behavior during vCPU thread migrations.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"kvm_arch_vcpu_run_pid_change",
"kvm_reset_stolen_time"
],
"Reasoning": "The patch introduces a mechanism to reset steal-time accounting when a KVM vCPU is run from a different host PID. It modifies core KVM logic for both ARM64 and x86 architectures, adding `kvm_arch_vcpu_run_pid_change` and `kvm_reset_stolen_time`. This is a functional change to reachable KVM code that should be fuzzed to ensure it doesn't introduce regressions or unexpected behavior during vCPU thread migrations.",
"WorthFuzzing": true
} |
| 13/1 | 2026/08/16 06:00 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 14/2 | 2026/08/16 06:00 | agent | kmsan-evaluator |
0mModel:best-expensive Args: null Results: {
"KMSANReasoning": "The patch simply resets the KVM steal time accounting base (`last_steal`) to the current task's `run_delay` when a vCPU thread changes its host PID. This involves reading a fully initialized scalar value (`current-\u003esched_info.run_delay`) from the scheduler and assigning it to a field in the vCPU architecture structure. No new memory allocations are introduced, no structures are copied to user space, and no complex data structures are manipulated in a way that could expose uninitialized memory. Therefore, there is no risk of uninitialized memory use or info-leaks, and a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false
}Instruction: You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.
CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
a comprehensive suite of debugging tools and sanitizers, including KASAN
(out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
(locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
or page allocations) and kernel-to-user memory info-leaks.
Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.
Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.
Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
attributes, ioctl output arguments, socket options, or BPF buffers) where fields
or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
uninitialized bytes of existing buffers.
Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
dereferences, locking deadlocks, or use-after-free bugs (these are already caught
by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.
Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
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 af3fc23673193eefa3b2d6aca19c55f9b0c4828d
Author: syz-cluster <triage@syzkaller.com>
Date: Sun Aug 16 06:00:11 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index bae2c4f92ef5c..4607f956e7879 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -1339,6 +1339,7 @@ static inline bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu)
long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu);
gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu);
void kvm_update_stolen_time(struct kvm_vcpu *vcpu);
+void kvm_reset_stolen_time(struct kvm_vcpu *vcpu);
bool kvm_arm_pvtime_supported(void);
int kvm_arm_pvtime_set_attr(struct kvm_vcpu *vcpu,
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 9a6c72a186727..0f6e63eace21f 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -929,6 +929,8 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
if (!kvm_arm_vcpu_is_finalized(vcpu))
return -EPERM;
+ kvm_reset_stolen_time(vcpu);
+
if (likely(vcpu_has_run_once(vcpu)))
return 0;
diff --git a/arch/arm64/kvm/pvtime.c b/arch/arm64/kvm/pvtime.c
index 4ceabaa4c30bd..000bf49cc0fdf 100644
--- a/arch/arm64/kvm/pvtime.c
+++ b/arch/arm64/kvm/pvtime.c
@@ -32,6 +32,11 @@ void kvm_update_stolen_time(struct kvm_vcpu *vcpu)
srcu_read_unlock(&kvm->srcu, idx);
}
+void kvm_reset_stolen_time(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.steal.last_steal = current->sched_info.run_delay;
+}
+
long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
{
u32 feature = smccc_get_arg1(vcpu);
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 801bf9e520db3..b7cb2ceda6d9a 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -40,6 +40,7 @@ config KVM_X86
select HAVE_KVM_MSI
select HAVE_KVM_CPU_RELAX_INTERCEPT
select HAVE_KVM_NO_POLL
+ select HAVE_KVM_VCPU_RUN_PID_CHANGE
select VIRT_XFER_TO_GUEST_WORK
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_VFIO
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 47cb9eba113b1..33be45eec32bc 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3717,6 +3717,13 @@ void kvm_service_local_tlb_flush_requests(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_service_local_tlb_flush_requests);
+int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.st.last_steal = current->sched_info.run_delay;
+
+ return 0;
+}
+
static void record_steal_time(struct kvm_vcpu *vcpu)
{
struct gfn_to_hva_cache *ghc = &vcpu->arch.st.cache;
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 6fc34e9bf8e1b..b01a3403d602a 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -159,6 +159,7 @@ TEST_GEN_PROGS_x86 += hardware_disable_test
TEST_GEN_PROGS_x86 += mmu_stress_test
TEST_GEN_PROGS_x86 += rseq_test
TEST_GEN_PROGS_x86 += steal_time
+TEST_GEN_PROGS_x86 += steal_time_change_pid
TEST_GEN_PROGS_x86 += system_counter_offset_test
TEST_GEN_PROGS_x86 += pre_fault_memory_test
@@ -198,6 +199,7 @@ TEST_GEN_PROGS_arm64 += guest_memfd_test
TEST_GEN_PROGS_arm64 += mmu_stress_test
TEST_GEN_PROGS_arm64 += rseq_test
TEST_GEN_PROGS_arm64 += steal_time
+TEST_GEN_PROGS_arm64 += steal_time_change_pid
TEST_GEN_PROGS_s390 = $(TEST_GEN_PROGS_COMMON)
TEST_GEN_PROGS_s390 += s390/memop
diff --git a/tools/testing/selftests/kvm/steal_time_change_pid.c b/tools/testing/selftests/kvm/steal_time_change_pid.c
new file mode 100644
index 0000000000000..12d4927d1c017
--- /dev/null
+++ b/tools/testing/selftests/kvm/steal_time_change_pid.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Verify that KVM resets steal-time accounting when a vCPU fd is run from
+ * a different host PID.
+ */
+
+#include <pthread.h>
+#include <asm/kvm_para.h>
+#include "kvm_util.h"
+#include "processor.h"
+
+#define ST_GPA_BASE (1 << 30)
+#define ST_SANE_DELTA_NS (1ULL << 63)
+
+static void *st_gva;
+static u64 guest_stolen_time;
+static u64 main_steal;
+static u64 thread_steal;
+
+#if defined(__x86_64__)
+
+#define STEAL_TIME_SIZE ((sizeof(struct kvm_steal_time) + 63) & ~63)
+
+static void guest_code(void)
+{
+ struct kvm_steal_time *st = st_gva;
+
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->steal));
+ GUEST_SYNC(0);
+
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->steal));
+ GUEST_SYNC(1);
+
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->steal));
+ GUEST_DONE();
+}
+
+static bool steal_time_supported(struct kvm_vcpu *vcpu)
+{
+ return kvm_cpu_has(X86_FEATURE_KVM_STEAL_TIME);
+}
+
+static void steal_time_enable(struct kvm_vcpu *vcpu)
+{
+ vcpu_set_msr(vcpu, MSR_KVM_STEAL_TIME,
+ (ulong)st_gva | KVM_MSR_ENABLED);
+}
+
+#elif defined(__aarch64__)
+
+#define STEAL_TIME_SIZE ((sizeof(struct st_time) + 63) & ~63)
+
+#define PV_TIME_ST 0xc5000021
+
+struct st_time {
+ u32 rev;
+ u32 attr;
+ u64 st_time;
+};
+
+static void guest_code(void)
+{
+ struct arm_smccc_res res;
+ struct st_time *st;
+
+ do_smccc(PV_TIME_ST, 0, 0, 0, 0, 0, 0, 0, &res);
+ GUEST_ASSERT_NE(res.a0, -1);
+ GUEST_ASSERT_EQ(res.a0, (ulong)st_gva);
+
+ st = (struct st_time *)res.a0;
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->st_time));
+ GUEST_SYNC(0);
+
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->st_time));
+ GUEST_SYNC(1);
+
+ WRITE_ONCE(guest_stolen_time, READ_ONCE(st->st_time));
+ GUEST_DONE();
+}
+
+static bool steal_time_supported(struct kvm_vcpu *vcpu)
+{
+ struct kvm_device_attr dev = {
+ .group = KVM_ARM_VCPU_PVTIME_CTRL,
+ .attr = KVM_ARM_VCPU_PVTIME_IPA,
+ };
+
+ return !__vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &dev);
+}
+
+static void steal_time_enable(struct kvm_vcpu *vcpu)
+{
+ u64 st_ipa = (ulong)st_gva;
+ struct kvm_device_attr dev = {
+ .group = KVM_ARM_VCPU_PVTIME_CTRL,
+ .attr = KVM_ARM_VCPU_PVTIME_IPA,
+ .addr = (u64)&st_ipa,
+ };
+
+ vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &dev);
+}
+
+#else
+#error "steal_time_change_pid is not implemented on this architecture"
+#endif
+
+static void run_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct ucall uc;
+
+ vcpu_run(vcpu);
+
+ switch (get_ucall(vcpu, &uc)) {
+ case UCALL_SYNC:
+ case UCALL_DONE:
+ break;
+ case UCALL_ABORT:
+ REPORT_GUEST_ASSERT(uc);
+ default:
+ TEST_ASSERT(false, "Unexpected exit: %s",
+ exit_reason_str(vcpu->run->exit_reason));
+ }
+}
+
+static void *do_steal_time(void *arg)
+{
+ struct timespec ts, stop;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ stop = timespec_add_ns(ts, MIN_RUN_DELAY_NS);
+
+ while (timespec_to_ns(timespec_sub(ts, stop)) < 0)
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ return NULL;
+}
+
+static void *vcpu_thread(void *arg)
+{
+ struct kvm_vcpu *vcpu = arg;
+
+ run_vcpu(vcpu);
+ sync_global_from_guest(vcpu->vm, guest_stolen_time);
+ thread_steal = guest_stolen_time;
+
+ return NULL;
+}
+
+int main(void)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+ pthread_attr_t attr;
+ pthread_t thread;
+ cpu_set_t cpuset;
+ long run_delay;
+ long run_delay_delta;
+
+ ksft_print_header();
+ ksft_set_plan(1);
+
+ CPU_ZERO(&cpuset);
+ CPU_SET(0, &cpuset);
+ pthread_attr_init(&attr);
+ pthread_attr_setaffinity_np(&attr, sizeof(cpuset), &cpuset);
+ pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
+
+ vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+ vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
+ ST_GPA_BASE, 1, 1, 0);
+ virt_map(vm, ST_GPA_BASE, ST_GPA_BASE, 1);
+
+ st_gva = (void *)ST_GPA_BASE;
+ sync_global_to_guest(vm, st_gva);
+ memset(addr_gva2hva(vm, ST_GPA_BASE), 0, STEAL_TIME_SIZE);
+
+ TEST_REQUIRE(steal_time_supported(vcpu));
+
+ steal_time_enable(vcpu);
+ run_vcpu(vcpu);
+
+ run_delay = get_run_delay();
+ pthread_create(&thread, &attr, do_steal_time, NULL);
+
+ while (get_run_delay() - run_delay < MIN_RUN_DELAY_NS)
+ sched_yield();
+
+ pthread_join(thread, NULL);
+ run_delay_delta = get_run_delay() - run_delay;
+ TEST_ASSERT(run_delay_delta >= MIN_RUN_DELAY_NS,
+ "Expected run_delay >= %ld, got %ld",
+ MIN_RUN_DELAY_NS, run_delay_delta);
+
+ run_vcpu(vcpu);
+ sync_global_from_guest(vm, guest_stolen_time);
+ main_steal = guest_stolen_time;
+
+ TEST_ASSERT(main_steal >= MIN_RUN_DELAY_NS,
+ "Expected steal time >= %ld, got %"PRIu64,
+ MIN_RUN_DELAY_NS, main_steal);
+
+ pthread_create(&thread, NULL, vcpu_thread, vcpu);
+ pthread_join(thread, NULL);
+
+ TEST_ASSERT(thread_steal >= main_steal &&
+ thread_steal - main_steal < ST_SANE_DELTA_NS,
+ "Expected sane steal after vCPU pid change: "
+ "old=%"PRIu64", new=%"PRIu64,
+ main_steal, thread_steal);
+
+ ksft_test_result_pass("steal time remains sane across vCPU pid change\n");
+
+ pthread_attr_destroy(&attr);
+ kvm_vm_free(vm);
+ ksft_finished();
+}
|
| 15/3 | 2026/08/16 06:00 | llm | kmsan-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5872 output: 159 thoughts: 537 Thoughts: **Patch Analysis: Resetting Steal Time Accounting on vCPU PID Change** Okay, let me break this down. This patch is aimed at correcting KVM's steal time accounting, specifically when a vCPU transitions to a new host PID, which happens on both ARM64 and x86 architectures. The core of the change involves resetting the base for the steal time calculation to prevent skew caused by the task-specific nature of `current->sched_info.run_delay`. On ARM64, the new `kvm_reset_stolen_time(vcpu)` function is introduced and called from `kvm_arch_vcpu_run_pid_change(vcpu)`. This function simply sets `vcpu->arch.steal.last_steal` to the value of `current->sched_info.run_delay`. The x86 version implements `kvm_arch_vcpu_run_pid_change(vcpu)` and does the same assignment of `current->sched_info.run_delay` to `vcpu->arch.st.last_steal`. Now, the crucial part: I need to ensure this doesn't create any memory safety issues. The variables involved – `vcpu->arch.steal.last_steal` and `vcpu->arch.st.last_steal` on ARM64 and x86 respectively – are being assigned the value of `current->sched_info.run_delay`. `current->sched_info.run_delay` is an initialized `unsigned long long` (or equivalent) representing the scheduler's run delay. It's a scalar value, not a complex structure or potentially uninitialized chunk of memory. Looking at the code, there are no new structures or any data that is passed to userspace. No uninitialized variables or struct fields are being introduced. There are no complicated data structures being allocated or involved. And there are no bounds checks or length modifications that could potentially reveal uninitialized data. This patch is essentially just resetting a base value when the vCPU thread switches PIDs, and it is a simple scalar assignment. The whole point is to ensure accurate accounting, avoiding a large jump in steal time due to the per-task nature of the `run_delay` statistic. I can confidently say that this patch doesn't introduce any risk of uninitialized memory usage or data leaks. KMSAN isn't particularly relevant here, and KASAN isn't likely either, given the nature of the change. `current->sched_info.run_delay` is a known, initialized scheduler-maintained value. Therefore, I'm setting `NeedsKMSAN=false` and adding this reasoning. |
| 16/3 | 2026/08/16 06:00 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch simply resets the KVM steal time accounting base (`last_steal`) to the current task's `run_delay` when a vCPU thread changes its host PID. This involves reading a fully initialized scalar value (`current-\u003esched_info.run_delay`) from the scheduler and assigning it to a field in the vCPU architecture structure. No new memory allocations are introduced, no structures are copied to user space, and no complex data structures are manipulated in a way that could expose uninitialized memory. Therefore, there is no risk of uninitialized memory use or info-leaks, and a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch simply resets the KVM steal time accounting base (`last_steal`) to the current task's `run_delay` when a vCPU thread changes its host PID. This involves reading a fully initialized scalar value (`current-\u003esched_info.run_delay`) from the scheduler and assigning it to a field in the vCPU architecture structure. No new memory allocations are introduced, no structures are copied to user space, and no complex data structures are manipulated in a way that could expose uninitialized memory. Therefore, there is no risk of uninitialized memory use or info-leaks, and a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|