| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/01 02:56 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"KVM",
"KVM_INTEL",
"KVM_AMD",
"KVM_HYPERV"
],
"FocusSymbols": [
"kvm_arch_vcpu_ioctl",
"kvm_vm_ioctl_check_extension",
"kvm_get_hv_cpuid",
"kvm_hv_hypercall_complete",
"kvm_vcpu_ioctl_enable_cap"
],
"Reasoning": "The patch refactors KVM nested virtualization operations to use static calls instead of indirect function pointers. This changes the execution flow mechanism and introduces new initialization and checking logic (kvm_nested_ops.enabled). Bugs in this refactoring could lead to crashes or incorrect behavior in nested virtualization scenarios.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/01 02:56 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 626b53825aac2f39e31737df7a56ca71bb230db0\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Jul 1 02:56:36 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/x86/include/asm/kvm-x86-nested-ops.h b/arch/x86/include/asm/kvm-x86-nested-ops.h\nnew file mode 100644\nindex 00000000000000..4b1be5bcecaa48\n--- /dev/null\n+++ b/arch/x86/include/asm/kvm-x86-nested-ops.h\n@@ -0,0 +1,36 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+#if !defined(KVM_X86_NESTED_OP) || \\\n+ !defined(KVM_X86_NESTED_OP_OPTIONAL) || \\\n+ !defined(KVM_X86_NESTED_OP_OPTIONAL_RET0)\n+#error Missing one or more KVM_X86_NESTED_OP #defines\n+#else\n+/*\n+ * KVM_X86_NESTED_OP() and KVM_X86_NESTED_OP_OPTIONAL() are used to help\n+ * generate both DECLARE/DEFINE_STATIC_CALL() invocations and\n+ * \"static_call_update()\" calls.\n+ *\n+ * KVM_X86_NESTED_OP_OPTIONAL() can be used for those functions that can have\n+ * a NULL definition. KVM_X86_NESTED_OP_OPTIONAL_RET0() can be used likewise\n+ * to make a definition optional, but in this case the default will\n+ * be __static_call_return0.\n+ */\n+KVM_X86_NESTED_OP(leave_nested)\n+KVM_X86_NESTED_OP(is_exception_vmexit)\n+KVM_X86_NESTED_OP(check_events)\n+KVM_X86_NESTED_OP_OPTIONAL_RET0(has_events)\n+KVM_X86_NESTED_OP(triple_fault)\n+KVM_X86_NESTED_OP(get_state)\n+KVM_X86_NESTED_OP(set_state)\n+KVM_X86_NESTED_OP(get_nested_state_pages)\n+KVM_X86_NESTED_OP_OPTIONAL_RET0(write_log_dirty)\n+KVM_X86_NESTED_OP(translate_nested_gpa)\n+#ifdef CONFIG_KVM_HYPERV\n+KVM_X86_NESTED_OP_OPTIONAL(enable_evmcs)\n+KVM_X86_NESTED_OP_OPTIONAL_RET0(get_evmcs_version)\n+KVM_X86_NESTED_OP(hv_inject_synthetic_vmexit_post_tlb_flush)\n+#endif\n+#endif\n+\n+#undef KVM_X86_NESTED_OP\n+#undef KVM_X86_NESTED_OP_OPTIONAL\n+#undef KVM_X86_NESTED_OP_OPTIONAL_RET0\ndiff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h\nindex b517257a631532..7e07a9c259d092 100644\n--- a/arch/x86/include/asm/kvm_host.h\n+++ b/arch/x86/include/asm/kvm_host.h\n@@ -1842,8 +1842,6 @@ struct kvm_x86_ops {\n \n \tvoid (*update_cpu_dirty_logging)(struct kvm_vcpu *vcpu);\n \n-\tconst struct kvm_x86_nested_ops *nested_ops;\n-\n \tvoid (*vcpu_blocking)(struct kvm_vcpu *vcpu);\n \tvoid (*vcpu_unblocking)(struct kvm_vcpu *vcpu);\n \n@@ -1906,6 +1904,8 @@ struct kvm_x86_ops {\n };\n \n struct kvm_x86_nested_ops {\n+\tbool enabled;\n+\n \tvoid (*leave_nested)(struct kvm_vcpu *vcpu);\n \tbool (*is_exception_vmexit)(struct kvm_vcpu *vcpu, u8 vector,\n \t\t\t\t u32 error_code);\n@@ -1937,6 +1937,7 @@ struct kvm_x86_init_ops {\n \n \tstruct kvm_x86_ops *runtime_ops;\n \tstruct kvm_pmu_ops *pmu_ops;\n+\tstruct kvm_x86_nested_ops *nested_ops;\n };\n \n struct kvm_arch_async_pf {\n@@ -1952,6 +1953,7 @@ extern bool __read_mostly enable_apicv;\n extern bool __read_mostly enable_ipiv;\n extern bool __read_mostly enable_device_posted_irqs;\n extern struct kvm_x86_ops kvm_x86_ops;\n+extern struct kvm_x86_nested_ops kvm_nested_ops __read_mostly;\n \n #define kvm_x86_call(func) static_call(kvm_x86_##func)\n \n@@ -1961,6 +1963,14 @@ extern struct kvm_x86_ops kvm_x86_ops;\n #define KVM_X86_OP_OPTIONAL_RET0 KVM_X86_OP\n #include \u003casm/kvm-x86-ops.h\u003e\n \n+#define kvm_nested_call(func) static_call(kvm_x86_nested_##func)\n+\n+#define KVM_X86_NESTED_OP(func) \\\n+\tDECLARE_STATIC_CALL(kvm_x86_nested_##func, *(((struct kvm_x86_nested_ops *)0)-\u003efunc));\n+#define KVM_X86_NESTED_OP_OPTIONAL KVM_X86_NESTED_OP\n+#define KVM_X86_NESTED_OP_OPTIONAL_RET0 KVM_X86_NESTED_OP\n+#include \u003casm/kvm-x86-nested-ops.h\u003e\n+\n #define __KVM_HAVE_ARCH_VM_ALLOC\n static inline struct kvm *kvm_arch_alloc_vm(void)\n {\ndiff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c\nindex 1ee0d23f894974..b010dca37b9d1c 100644\n--- a/arch/x86/kvm/hyperv.c\n+++ b/arch/x86/kvm/hyperv.c\n@@ -2406,7 +2406,7 @@ static int kvm_hv_hypercall_complete(struct kvm_vcpu *vcpu, u64 result)\n \tret = kvm_skip_emulated_instruction(vcpu);\n \n \tif (tlb_lock_count)\n-\t\tkvm_x86_ops.nested_ops-\u003ehv_inject_synthetic_vmexit_post_tlb_flush(vcpu);\n+\t\tkvm_nested_call(hv_inject_synthetic_vmexit_post_tlb_flush)(vcpu);\n \n \treturn ret;\n }\n@@ -2787,8 +2787,8 @@ int kvm_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,\n \t};\n \tint i, nent = ARRAY_SIZE(cpuid_entries);\n \n-\tif (kvm_x86_ops.nested_ops-\u003eget_evmcs_version)\n-\t\tevmcs_ver = kvm_x86_ops.nested_ops-\u003eget_evmcs_version(vcpu);\n+\tif (kvm_nested_ops.enabled)\n+\t\tevmcs_ver = kvm_nested_call(get_evmcs_version)(vcpu);\n \n \tif (cpuid-\u003enent \u003c nent)\n \t\treturn -E2BIG;\ndiff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h\nindex c9f628b97daeb9..fa05ca2c8549e5 100644\n--- a/arch/x86/kvm/mmu.h\n+++ b/arch/x86/kvm/mmu.h\n@@ -385,9 +385,8 @@ static inline gpa_t kvm_translate_gpa(struct kvm_vcpu *vcpu,\n {\n \tif (!mmu_is_nested(vcpu) || w == \u0026vcpu-\u003earch.ngpa_walk)\n \t\treturn gpa;\n-\treturn kvm_x86_ops.nested_ops-\u003etranslate_nested_gpa(vcpu, gpa, access,\n-\t\t\t\t\t\t\t exception,\n-\t\t\t\t\t\t\t pte_access);\n+\treturn kvm_nested_call(translate_nested_gpa)(vcpu, gpa, access,\n+\t\t\t\t\t\t exception, pte_access);\n }\n \n static inline bool kvm_has_mirrored_tdp(const struct kvm *kvm)\ndiff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h\nindex e73fc09ec4db2e..4ee7b03e762d0f 100644\n--- a/arch/x86/kvm/mmu/paging_tmpl.h\n+++ b/arch/x86/kvm/mmu/paging_tmpl.h\n@@ -235,7 +235,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,\n \t\t\t\t!(pte \u0026 PT_GUEST_DIRTY_MASK)) {\n \t\t\ttrace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));\n #if PTTYPE == PTTYPE_EPT\n-\t\t\tif (kvm_x86_ops.nested_ops-\u003ewrite_log_dirty(vcpu, addr))\n+\t\t\tif (kvm_nested_call(write_log_dirty)(vcpu, addr))\n \t\t\t\treturn -EINVAL;\n #endif\n \t\t\tpte |= PT_GUEST_DIRTY_MASK;\ndiff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c\nindex ba985a02208a3e..5f6d9971a3f224 100644\n--- a/arch/x86/kvm/svm/nested.c\n+++ b/arch/x86/kvm/svm/nested.c\n@@ -2162,7 +2162,7 @@ static gpa_t svm_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,\n \treturn w-\u003egva_to_gpa(vcpu, w, gpa, access, exception);\n }\n \n-struct kvm_x86_nested_ops svm_nested_ops = {\n+struct kvm_x86_nested_ops svm_nested_ops __initdata = {\n \t.leave_nested = svm_leave_nested,\n \t.translate_nested_gpa = svm_translate_nested_gpa,\n \t.is_exception_vmexit = nested_svm_is_exception_vmexit,\ndiff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c\nindex ef69a51ab27f98..d3807f4abb499f 100644\n--- a/arch/x86/kvm/svm/svm.c\n+++ b/arch/x86/kvm/svm/svm.c\n@@ -5426,8 +5426,6 @@ struct kvm_x86_ops svm_x86_ops __initdata = {\n \t.check_intercept = svm_check_intercept,\n \t.handle_exit_irqoff = svm_handle_exit_irqoff,\n \n-\t.nested_ops = \u0026svm_nested_ops,\n-\n \t.deliver_interrupt = svm_deliver_interrupt,\n \t.pi_update_irte = avic_pi_update_irte,\n \t.setup_mce = svm_setup_mce,\n@@ -5646,6 +5644,7 @@ static __init int svm_hardware_setup(void)\n \t\tif (r)\n \t\t\treturn r;\n \t}\n+\tsvm_nested_ops.enabled = nested;\n \n \t/*\n \t * KVM's MMU doesn't support using 2-level paging for itself, and thus\n@@ -5772,6 +5771,7 @@ static struct kvm_x86_init_ops svm_init_ops __initdata = {\n \n \t.runtime_ops = \u0026svm_x86_ops,\n \t.pmu_ops = \u0026amd_pmu_ops,\n+\t.nested_ops = \u0026svm_nested_ops,\n };\n \n static void __svm_exit(void)\ndiff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c\nindex 83d9921277eac2..04f986e3d439af 100644\n--- a/arch/x86/kvm/vmx/main.c\n+++ b/arch/x86/kvm/vmx/main.c\n@@ -995,8 +995,6 @@ struct kvm_x86_ops vt_x86_ops __initdata = {\n \n \t.update_cpu_dirty_logging = vt_op(update_cpu_dirty_logging),\n \n-\t.nested_ops = \u0026vmx_nested_ops,\n-\n \t.pi_update_irte = vmx_pi_update_irte,\n \t.pi_start_bypass = vmx_pi_start_bypass,\n \n@@ -1038,6 +1036,7 @@ struct kvm_x86_init_ops vt_init_ops __initdata = {\n \n \t.runtime_ops = \u0026vt_x86_ops,\n \t.pmu_ops = \u0026intel_pmu_ops,\n+\t.nested_ops = \u0026vmx_nested_ops,\n };\n \n static void __exit vt_exit(void)\ndiff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c\nindex 0635e92471c89e..cbb209d8a8f0d1 100644\n--- a/arch/x86/kvm/vmx/nested.c\n+++ b/arch/x86/kvm/vmx/nested.c\n@@ -7484,7 +7484,7 @@ static gpa_t vmx_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,\n \treturn w-\u003egva_to_gpa(vcpu, w, gpa, access, exception);\n }\n \n-struct kvm_x86_nested_ops vmx_nested_ops = {\n+struct kvm_x86_nested_ops vmx_nested_ops __initdata = {\n \t.leave_nested = vmx_leave_nested,\n \t.translate_nested_gpa = vmx_translate_nested_gpa,\n \t.is_exception_vmexit = nested_vmx_is_exception_vmexit,\ndiff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c\nindex 3681d565f17789..ef9e1bc39edbbf 100644\n--- a/arch/x86/kvm/vmx/vmx.c\n+++ b/arch/x86/kvm/vmx/vmx.c\n@@ -8786,6 +8786,7 @@ __init int vmx_hardware_setup(void)\n \t\tif (r)\n \t\t\treturn r;\n \t}\n+\tvmx_nested_ops.enabled = nested;\n \n \tkvm_set_posted_intr_wakeup_handler(pi_wakeup_handler);\n \ndiff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c\nindex 0626e835e9eb77..5ba4aac376406c 100644\n--- a/arch/x86/kvm/x86.c\n+++ b/arch/x86/kvm/x86.c\n@@ -154,6 +154,7 @@ static int sync_regs(struct kvm_vcpu *vcpu);\n static DEFINE_MUTEX(vendor_module_lock);\n \n struct kvm_x86_ops kvm_x86_ops __read_mostly;\n+struct kvm_x86_nested_ops kvm_nested_ops __read_mostly;\n \n #define KVM_X86_OP(func)\t\t\t\t\t \\\n \tDEFINE_STATIC_CALL_NULL(kvm_x86_##func,\t\t\t \\\n@@ -165,6 +166,13 @@ EXPORT_STATIC_CALL_GPL(kvm_x86_get_cs_db_l_bits);\n EXPORT_STATIC_CALL_GPL(kvm_x86_cache_reg);\n EXPORT_STATIC_CALL_GPL(kvm_x86_get_cpl);\n \n+#define KVM_X86_NESTED_OP(func)\t\t\t\t\t\t\t\\\n+\tDEFINE_STATIC_CALL_NULL(kvm_x86_nested_##func,\t\t\t\t\\\n+\t\t\t\t*(((struct kvm_x86_nested_ops *)0)-\u003efunc));\n+#define KVM_X86_NESTED_OP_OPTIONAL KVM_X86_NESTED_OP\n+#define KVM_X86_NESTED_OP_OPTIONAL_RET0 KVM_X86_NESTED_OP\n+#include \u003casm/kvm-x86-nested-ops.h\u003e\n+\n unsigned int min_timer_period_us = 200;\n module_param(min_timer_period_us, uint, 0644);\n \n@@ -454,7 +462,7 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcpu, unsigned int nr,\n \t * wants to intercept the exception.\n \t */\n \tif (is_guest_mode(vcpu) \u0026\u0026\n-\t kvm_x86_ops.nested_ops-\u003eis_exception_vmexit(vcpu, nr, error_code)) {\n+\t kvm_nested_call(is_exception_vmexit)(vcpu, nr, error_code)) {\n \t\tkvm_queue_exception_vmexit(vcpu, nr, has_error, error_code,\n \t\t\t\t\t has_payload, payload);\n \t\treturn;\n@@ -2346,15 +2354,14 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)\n \t\t\tr \u0026= ~KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST;\n \t\tbreak;\n \tcase KVM_CAP_NESTED_STATE:\n-\t\tr = kvm_x86_ops.nested_ops-\u003eget_state ?\n-\t\t\tkvm_x86_ops.nested_ops-\u003eget_state(NULL, NULL, 0) : 0;\n+\t\tr = kvm_nested_ops.enabled ? kvm_nested_call(get_state)(NULL, NULL, 0) : 0;\n \t\tbreak;\n #ifdef CONFIG_KVM_HYPERV\n \tcase KVM_CAP_HYPERV_DIRECT_TLBFLUSH:\n \t\tr = kvm_x86_ops.enable_l2_tlb_flush != NULL;\n \t\tbreak;\n \tcase KVM_CAP_HYPERV_ENLIGHTENED_VMCS:\n-\t\tr = kvm_x86_ops.nested_ops-\u003eenable_evmcs != NULL;\n+\t\tr = kvm_nested_ops.enabled \u0026\u0026 kvm_nested_ops.enable_evmcs != NULL;\n \t\tbreak;\n #endif\n \tcase KVM_CAP_SMALLER_MAXPHYADDR:\n@@ -3366,9 +3373,10 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,\n \t\t\tuint16_t vmcs_version;\n \t\t\tvoid __user *user_ptr;\n \n-\t\t\tif (!kvm_x86_ops.nested_ops-\u003eenable_evmcs)\n+\t\t\tif (!kvm_nested_ops.enabled ||\n+\t\t\t !kvm_nested_ops.enable_evmcs)\n \t\t\t\treturn -ENOTTY;\n-\t\t\tr = kvm_x86_ops.nested_ops-\u003eenable_evmcs(vcpu, \u0026vmcs_version);\n+\t\t\tr = kvm_nested_call(enable_evmcs)(vcpu, \u0026vmcs_version);\n \t\t\tif (!r) {\n \t\t\t\tuser_ptr = (void __user *)(uintptr_t)cap-\u003eargs[0];\n \t\t\t\tif (copy_to_user(user_ptr, \u0026vmcs_version,\n@@ -3732,7 +3740,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,\n \t\tu32 user_data_size;\n \n \t\tr = -EINVAL;\n-\t\tif (!kvm_x86_ops.nested_ops-\u003eget_state)\n+\t\tif (!kvm_nested_ops.enabled)\n \t\t\tbreak;\n \n \t\tBUILD_BUG_ON(sizeof(user_data_size) != sizeof(user_kvm_nested_state-\u003esize));\n@@ -3740,8 +3748,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,\n \t\tif (get_user(user_data_size, \u0026user_kvm_nested_state-\u003esize))\n \t\t\tbreak;\n \n-\t\tr = kvm_x86_ops.nested_ops-\u003eget_state(vcpu, user_kvm_nested_state,\n-\t\t\t\t\t\t user_data_size);\n+\t\tr = kvm_nested_call(get_state)(vcpu, user_kvm_nested_state, user_data_size);\n \t\tif (r \u003c 0)\n \t\t\tbreak;\n \n@@ -3762,7 +3769,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,\n \t\tint idx;\n \n \t\tr = -EINVAL;\n-\t\tif (!kvm_x86_ops.nested_ops-\u003eset_state)\n+\t\tif (!kvm_nested_ops.enabled)\n \t\t\tbreak;\n \n \t\tr = -EFAULT;\n@@ -3785,7 +3792,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,\n \t\t\tbreak;\n \n \t\tidx = srcu_read_lock(\u0026vcpu-\u003ekvm-\u003esrcu);\n-\t\tr = kvm_x86_ops.nested_ops-\u003eset_state(vcpu, user_kvm_nested_state, \u0026kvm_state);\n+\t\tr = kvm_nested_call(set_state)(vcpu, user_kvm_nested_state, \u0026kvm_state);\n \t\tsrcu_read_unlock(\u0026vcpu-\u003ekvm-\u003esrcu, idx);\n \t\tbreak;\n \t}\n@@ -6903,6 +6910,22 @@ static void kvm_setup_efer_caps(void)\n \t\tkvm_enable_efer_bits(EFER_AUTOIBRS);\n }\n \n+static void kvm_nested_ops_update(const struct kvm_x86_nested_ops *nested_ops)\n+{\n+\tmemcpy(\u0026kvm_nested_ops, nested_ops, sizeof(kvm_nested_ops));\n+\n+#define __KVM_X86_NESTED_OP(func) \\\n+\tstatic_call_update(kvm_x86_nested_##func, kvm_nested_ops.func);\n+#define KVM_X86_NESTED_OP(func) \\\n+\tWARN_ON(!kvm_nested_ops.func); __KVM_X86_NESTED_OP(func)\n+#define KVM_X86_NESTED_OP_OPTIONAL __KVM_X86_NESTED_OP\n+#define KVM_X86_NESTED_OP_OPTIONAL_RET0(func) \\\n+\tstatic_call_update(kvm_x86_nested_##func, (void *)kvm_nested_ops.func ? : \\\n+\t\t\t\t\t\t (void *)__static_call_return0);\n+#include \u003casm/kvm-x86-nested-ops.h\u003e\n+#undef __KVM_X86_NESTED_OP\n+}\n+\n static inline void kvm_ops_update(struct kvm_x86_init_ops *ops)\n {\n \tmemcpy(\u0026kvm_x86_ops, ops-\u003eruntime_ops, sizeof(kvm_x86_ops));\n@@ -6918,6 +6941,8 @@ static inline void kvm_ops_update(struct kvm_x86_init_ops *ops)\n #include \u003casm/kvm-x86-ops.h\u003e\n #undef __KVM_X86_OP\n \n+\tkvm_nested_ops_update(ops-\u003enested_ops);\n+\n \tkvm_pmu_ops_update(ops-\u003epmu_ops);\n }\n \n@@ -7454,11 +7479,11 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)\n int kvm_check_nested_events(struct kvm_vcpu *vcpu)\n {\n \tif (kvm_test_request(KVM_REQ_TRIPLE_FAULT, vcpu)) {\n-\t\tkvm_x86_ops.nested_ops-\u003etriple_fault(vcpu);\n+\t\tkvm_nested_call(triple_fault)(vcpu);\n \t\treturn 1;\n \t}\n \n-\treturn kvm_x86_ops.nested_ops-\u003echeck_events(vcpu);\n+\treturn kvm_nested_call(check_events)(vcpu);\n }\n \n static void kvm_inject_exception(struct kvm_vcpu *vcpu)\n@@ -7696,9 +7721,7 @@ static int kvm_check_and_inject_events(struct kvm_vcpu *vcpu,\n \t\t\tkvm_x86_call(enable_irq_window)(vcpu);\n \t}\n \n-\tif (is_guest_mode(vcpu) \u0026\u0026\n-\t kvm_x86_ops.nested_ops-\u003ehas_events \u0026\u0026\n-\t kvm_x86_ops.nested_ops-\u003ehas_events(vcpu, true))\n+\tif (is_guest_mode(vcpu) \u0026\u0026 kvm_nested_call(has_events)(vcpu, true))\n \t\t*req_immediate_exit = true;\n \n \t/*\n@@ -8021,7 +8044,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)\n \t\t}\n \n \t\tif (kvm_check_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu)) {\n-\t\t\tif (unlikely(!kvm_x86_ops.nested_ops-\u003eget_nested_state_pages(vcpu))) {\n+\t\t\tif (unlikely(!kvm_nested_call(get_nested_state_pages)(vcpu))) {\n \t\t\t\tr = 0;\n \t\t\t\tgoto out;\n \t\t\t}\n@@ -8073,7 +8096,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)\n \t\t}\n \t\tif (kvm_test_request(KVM_REQ_TRIPLE_FAULT, vcpu)) {\n \t\t\tif (is_guest_mode(vcpu))\n-\t\t\t\tkvm_x86_ops.nested_ops-\u003etriple_fault(vcpu);\n+\t\t\t\tkvm_nested_call(triple_fault)(vcpu);\n \n \t\t\tif (kvm_check_request(KVM_REQ_TRIPLE_FAULT, vcpu)) {\n \t\t\t\tvcpu-\u003erun-\u003eexit_reason = KVM_EXIT_SHUTDOWN;\n@@ -8491,9 +8514,7 @@ bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)\n \tif (kvm_hv_has_stimer_pending(vcpu))\n \t\treturn true;\n \n-\tif (is_guest_mode(vcpu) \u0026\u0026\n-\t kvm_x86_ops.nested_ops-\u003ehas_events \u0026\u0026\n-\t kvm_x86_ops.nested_ops-\u003ehas_events(vcpu, false))\n+\tif (is_guest_mode(vcpu) \u0026\u0026 kvm_nested_call(has_events)(vcpu, false))\n \t\treturn true;\n \n \tif (kvm_xen_has_pending_events(vcpu))\n@@ -8896,8 +8917,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)\n \t * a pending VM-Exit if L1 wants to intercept the exception.\n \t */\n \tif (vcpu-\u003earch.exception_from_userspace \u0026\u0026 is_guest_mode(vcpu) \u0026\u0026\n-\t kvm_x86_ops.nested_ops-\u003eis_exception_vmexit(vcpu, ex-\u003evector,\n-\t\t\t\t\t\t\tex-\u003eerror_code)) {\n+\t kvm_nested_call(is_exception_vmexit)(vcpu, ex-\u003evector, ex-\u003eerror_code)) {\n \t\tkvm_queue_exception_vmexit(vcpu, ex-\u003evector,\n \t\t\t\t\t ex-\u003ehas_error_code, ex-\u003eerror_code,\n \t\t\t\t\t ex-\u003ehas_payload, ex-\u003epayload);\ndiff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h\nindex 8ece468087a8ee..b510b631f0c522 100644\n--- a/arch/x86/kvm/x86.h\n+++ b/arch/x86/kvm/x86.h\n@@ -93,7 +93,7 @@ int kvm_check_nested_events(struct kvm_vcpu *vcpu);\n /* Forcibly leave the nested mode in cases like a vCPU reset */\n static inline void kvm_leave_nested(struct kvm_vcpu *vcpu)\n {\n-\tkvm_x86_ops.nested_ops-\u003eleave_nested(vcpu);\n+\tkvm_nested_call(leave_nested)(vcpu);\n }\n \n /*\n"
} |
| 2/1 | 2026/07/01 02:56 | agent | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"KVM",
"KVM_INTEL",
"KVM_AMD",
"KVM_HYPERV"
],
"FocusSymbols": [
"kvm_arch_vcpu_ioctl",
"kvm_vm_ioctl_check_extension",
"kvm_get_hv_cpuid",
"kvm_hv_hypercall_complete",
"kvm_vcpu_ioctl_enable_cap"
],
"Reasoning": "The patch refactors KVM nested virtualization operations to use static calls instead of indirect function pointers. This changes the execution flow mechanism and introduces new initialization and checking logic (kvm_nested_ops.enabled). Bugs in this refactoring could lead to crashes or incorrect behavior in nested virtualization scenarios.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 626b53825aac2f39e31737df7a56ca71bb230db0
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Jul 1 02:56:36 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/x86/include/asm/kvm-x86-nested-ops.h b/arch/x86/include/asm/kvm-x86-nested-ops.h
new file mode 100644
index 00000000000000..4b1be5bcecaa48
--- /dev/null
+++ b/arch/x86/include/asm/kvm-x86-nested-ops.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#if !defined(KVM_X86_NESTED_OP) || \
+ !defined(KVM_X86_NESTED_OP_OPTIONAL) || \
+ !defined(KVM_X86_NESTED_OP_OPTIONAL_RET0)
+#error Missing one or more KVM_X86_NESTED_OP #defines
+#else
+/*
+ * KVM_X86_NESTED_OP() and KVM_X86_NESTED_OP_OPTIONAL() are used to help
+ * generate both DECLARE/DEFINE_STATIC_CALL() invocations and
+ * "static_call_update()" calls.
+ *
+ * KVM_X86_NESTED_OP_OPTIONAL() can be used for those functions that can have
+ * a NULL definition. KVM_X86_NESTED_OP_OPTIONAL_RET0() can be used likewise
+ * to make a definition optional, but in this case the default will
+ * be __static_call_return0.
+ */
+KVM_X86_NESTED_OP(leave_nested)
+KVM_X86_NESTED_OP(is_exception_vmexit)
+KVM_X86_NESTED_OP(check_events)
+KVM_X86_NESTED_OP_OPTIONAL_RET0(has_events)
+KVM_X86_NESTED_OP(triple_fault)
+KVM_X86_NESTED_OP(get_state)
+KVM_X86_NESTED_OP(set_state)
+KVM_X86_NESTED_OP(get_nested_state_pages)
+KVM_X86_NESTED_OP_OPTIONAL_RET0(write_log_dirty)
+KVM_X86_NESTED_OP(translate_nested_gpa)
+#ifdef CONFIG_KVM_HYPERV
+KVM_X86_NESTED_OP_OPTIONAL(enable_evmcs)
+KVM_X86_NESTED_OP_OPTIONAL_RET0(get_evmcs_version)
+KVM_X86_NESTED_OP(hv_inject_synthetic_vmexit_post_tlb_flush)
+#endif
+#endif
+
+#undef KVM_X86_NESTED_OP
+#undef KVM_X86_NESTED_OP_OPTIONAL
+#undef KVM_X86_NESTED_OP_OPTIONAL_RET0
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index b517257a631532..7e07a9c259d092 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1842,8 +1842,6 @@ struct kvm_x86_ops {
void (*update_cpu_dirty_logging)(struct kvm_vcpu *vcpu);
- const struct kvm_x86_nested_ops *nested_ops;
-
void (*vcpu_blocking)(struct kvm_vcpu *vcpu);
void (*vcpu_unblocking)(struct kvm_vcpu *vcpu);
@@ -1906,6 +1904,8 @@ struct kvm_x86_ops {
};
struct kvm_x86_nested_ops {
+ bool enabled;
+
void (*leave_nested)(struct kvm_vcpu *vcpu);
bool (*is_exception_vmexit)(struct kvm_vcpu *vcpu, u8 vector,
u32 error_code);
@@ -1937,6 +1937,7 @@ struct kvm_x86_init_ops {
struct kvm_x86_ops *runtime_ops;
struct kvm_pmu_ops *pmu_ops;
+ struct kvm_x86_nested_ops *nested_ops;
};
struct kvm_arch_async_pf {
@@ -1952,6 +1953,7 @@ extern bool __read_mostly enable_apicv;
extern bool __read_mostly enable_ipiv;
extern bool __read_mostly enable_device_posted_irqs;
extern struct kvm_x86_ops kvm_x86_ops;
+extern struct kvm_x86_nested_ops kvm_nested_ops __read_mostly;
#define kvm_x86_call(func) static_call(kvm_x86_##func)
@@ -1961,6 +1963,14 @@ extern struct kvm_x86_ops kvm_x86_ops;
#define KVM_X86_OP_OPTIONAL_RET0 KVM_X86_OP
#include <asm/kvm-x86-ops.h>
+#define kvm_nested_call(func) static_call(kvm_x86_nested_##func)
+
+#define KVM_X86_NESTED_OP(func) \
+ DECLARE_STATIC_CALL(kvm_x86_nested_##func, *(((struct kvm_x86_nested_ops *)0)->func));
+#define KVM_X86_NESTED_OP_OPTIONAL KVM_X86_NESTED_OP
+#define KVM_X86_NESTED_OP_OPTIONAL_RET0 KVM_X86_NESTED_OP
+#include <asm/kvm-x86-nested-ops.h>
+
#define __KVM_HAVE_ARCH_VM_ALLOC
static inline struct kvm *kvm_arch_alloc_vm(void)
{
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 1ee0d23f894974..b010dca37b9d1c 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -2406,7 +2406,7 @@ static int kvm_hv_hypercall_complete(struct kvm_vcpu *vcpu, u64 result)
ret = kvm_skip_emulated_instruction(vcpu);
if (tlb_lock_count)
- kvm_x86_ops.nested_ops->hv_inject_synthetic_vmexit_post_tlb_flush(vcpu);
+ kvm_nested_call(hv_inject_synthetic_vmexit_post_tlb_flush)(vcpu);
return ret;
}
@@ -2787,8 +2787,8 @@ int kvm_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
};
int i, nent = ARRAY_SIZE(cpuid_entries);
- if (kvm_x86_ops.nested_ops->get_evmcs_version)
- evmcs_ver = kvm_x86_ops.nested_ops->get_evmcs_version(vcpu);
+ if (kvm_nested_ops.enabled)
+ evmcs_ver = kvm_nested_call(get_evmcs_version)(vcpu);
if (cpuid->nent < nent)
return -E2BIG;
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index c9f628b97daeb9..fa05ca2c8549e5 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -385,9 +385,8 @@ static inline gpa_t kvm_translate_gpa(struct kvm_vcpu *vcpu,
{
if (!mmu_is_nested(vcpu) || w == &vcpu->arch.ngpa_walk)
return gpa;
- return kvm_x86_ops.nested_ops->translate_nested_gpa(vcpu, gpa, access,
- exception,
- pte_access);
+ return kvm_nested_call(translate_nested_gpa)(vcpu, gpa, access,
+ exception, pte_access);
}
static inline bool kvm_has_mirrored_tdp(const struct kvm *kvm)
diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
index e73fc09ec4db2e..4ee7b03e762d0f 100644
--- a/arch/x86/kvm/mmu/paging_tmpl.h
+++ b/arch/x86/kvm/mmu/paging_tmpl.h
@@ -235,7 +235,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
!(pte & PT_GUEST_DIRTY_MASK)) {
trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
#if PTTYPE == PTTYPE_EPT
- if (kvm_x86_ops.nested_ops->write_log_dirty(vcpu, addr))
+ if (kvm_nested_call(write_log_dirty)(vcpu, addr))
return -EINVAL;
#endif
pte |= PT_GUEST_DIRTY_MASK;
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index ba985a02208a3e..5f6d9971a3f224 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -2162,7 +2162,7 @@ static gpa_t svm_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,
return w->gva_to_gpa(vcpu, w, gpa, access, exception);
}
-struct kvm_x86_nested_ops svm_nested_ops = {
+struct kvm_x86_nested_ops svm_nested_ops __initdata = {
.leave_nested = svm_leave_nested,
.translate_nested_gpa = svm_translate_nested_gpa,
.is_exception_vmexit = nested_svm_is_exception_vmexit,
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index ef69a51ab27f98..d3807f4abb499f 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5426,8 +5426,6 @@ struct kvm_x86_ops svm_x86_ops __initdata = {
.check_intercept = svm_check_intercept,
.handle_exit_irqoff = svm_handle_exit_irqoff,
- .nested_ops = &svm_nested_ops,
-
.deliver_interrupt = svm_deliver_interrupt,
.pi_update_irte = avic_pi_update_irte,
.setup_mce = svm_setup_mce,
@@ -5646,6 +5644,7 @@ static __init int svm_hardware_setup(void)
if (r)
return r;
}
+ svm_nested_ops.enabled = nested;
/*
* KVM's MMU doesn't support using 2-level paging for itself, and thus
@@ -5772,6 +5771,7 @@ static struct kvm_x86_init_ops svm_init_ops __initdata = {
.runtime_ops = &svm_x86_ops,
.pmu_ops = &amd_pmu_ops,
+ .nested_ops = &svm_nested_ops,
};
static void __svm_exit(void)
diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c
index 83d9921277eac2..04f986e3d439af 100644
--- a/arch/x86/kvm/vmx/main.c
+++ b/arch/x86/kvm/vmx/main.c
@@ -995,8 +995,6 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
.update_cpu_dirty_logging = vt_op(update_cpu_dirty_logging),
- .nested_ops = &vmx_nested_ops,
-
.pi_update_irte = vmx_pi_update_irte,
.pi_start_bypass = vmx_pi_start_bypass,
@@ -1038,6 +1036,7 @@ struct kvm_x86_init_ops vt_init_ops __initdata = {
.runtime_ops = &vt_x86_ops,
.pmu_ops = &intel_pmu_ops,
+ .nested_ops = &vmx_nested_ops,
};
static void __exit vt_exit(void)
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 0635e92471c89e..cbb209d8a8f0d1 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -7484,7 +7484,7 @@ static gpa_t vmx_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,
return w->gva_to_gpa(vcpu, w, gpa, access, exception);
}
-struct kvm_x86_nested_ops vmx_nested_ops = {
+struct kvm_x86_nested_ops vmx_nested_ops __initdata = {
.leave_nested = vmx_leave_nested,
.translate_nested_gpa = vmx_translate_nested_gpa,
.is_exception_vmexit = nested_vmx_is_exception_vmexit,
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 3681d565f17789..ef9e1bc39edbbf 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -8786,6 +8786,7 @@ __init int vmx_hardware_setup(void)
if (r)
return r;
}
+ vmx_nested_ops.enabled = nested;
kvm_set_posted_intr_wakeup_handler(pi_wakeup_handler);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0626e835e9eb77..5ba4aac376406c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -154,6 +154,7 @@ static int sync_regs(struct kvm_vcpu *vcpu);
static DEFINE_MUTEX(vendor_module_lock);
struct kvm_x86_ops kvm_x86_ops __read_mostly;
+struct kvm_x86_nested_ops kvm_nested_ops __read_mostly;
#define KVM_X86_OP(func) \
DEFINE_STATIC_CALL_NULL(kvm_x86_##func, \
@@ -165,6 +166,13 @@ EXPORT_STATIC_CALL_GPL(kvm_x86_get_cs_db_l_bits);
EXPORT_STATIC_CALL_GPL(kvm_x86_cache_reg);
EXPORT_STATIC_CALL_GPL(kvm_x86_get_cpl);
+#define KVM_X86_NESTED_OP(func) \
+ DEFINE_STATIC_CALL_NULL(kvm_x86_nested_##func, \
+ *(((struct kvm_x86_nested_ops *)0)->func));
+#define KVM_X86_NESTED_OP_OPTIONAL KVM_X86_NESTED_OP
+#define KVM_X86_NESTED_OP_OPTIONAL_RET0 KVM_X86_NESTED_OP
+#include <asm/kvm-x86-nested-ops.h>
+
unsigned int min_timer_period_us = 200;
module_param(min_timer_period_us, uint, 0644);
@@ -454,7 +462,7 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcpu, unsigned int nr,
* wants to intercept the exception.
*/
if (is_guest_mode(vcpu) &&
- kvm_x86_ops.nested_ops->is_exception_vmexit(vcpu, nr, error_code)) {
+ kvm_nested_call(is_exception_vmexit)(vcpu, nr, error_code)) {
kvm_queue_exception_vmexit(vcpu, nr, has_error, error_code,
has_payload, payload);
return;
@@ -2346,15 +2354,14 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
r &= ~KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST;
break;
case KVM_CAP_NESTED_STATE:
- r = kvm_x86_ops.nested_ops->get_state ?
- kvm_x86_ops.nested_ops->get_state(NULL, NULL, 0) : 0;
+ r = kvm_nested_ops.enabled ? kvm_nested_call(get_state)(NULL, NULL, 0) : 0;
break;
#ifdef CONFIG_KVM_HYPERV
case KVM_CAP_HYPERV_DIRECT_TLBFLUSH:
r = kvm_x86_ops.enable_l2_tlb_flush != NULL;
break;
case KVM_CAP_HYPERV_ENLIGHTENED_VMCS:
- r = kvm_x86_ops.nested_ops->enable_evmcs != NULL;
+ r = kvm_nested_ops.enabled && kvm_nested_ops.enable_evmcs != NULL;
break;
#endif
case KVM_CAP_SMALLER_MAXPHYADDR:
@@ -3366,9 +3373,10 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
uint16_t vmcs_version;
void __user *user_ptr;
- if (!kvm_x86_ops.nested_ops->enable_evmcs)
+ if (!kvm_nested_ops.enabled ||
+ !kvm_nested_ops.enable_evmcs)
return -ENOTTY;
- r = kvm_x86_ops.nested_ops->enable_evmcs(vcpu, &vmcs_version);
+ r = kvm_nested_call(enable_evmcs)(vcpu, &vmcs_version);
if (!r) {
user_ptr = (void __user *)(uintptr_t)cap->args[0];
if (copy_to_user(user_ptr, &vmcs_version,
@@ -3732,7 +3740,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
u32 user_data_size;
r = -EINVAL;
- if (!kvm_x86_ops.nested_ops->get_state)
+ if (!kvm_nested_ops.enabled)
break;
BUILD_BUG_ON(sizeof(user_data_size) != sizeof(user_kvm_nested_state->size));
@@ -3740,8 +3748,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
if (get_user(user_data_size, &user_kvm_nested_state->size))
break;
- r = kvm_x86_ops.nested_ops->get_state(vcpu, user_kvm_nested_state,
- user_data_size);
+ r = kvm_nested_call(get_state)(vcpu, user_kvm_nested_state, user_data_size);
if (r < 0)
break;
@@ -3762,7 +3769,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
int idx;
r = -EINVAL;
- if (!kvm_x86_ops.nested_ops->set_state)
+ if (!kvm_nested_ops.enabled)
break;
r = -EFAULT;
@@ -3785,7 +3792,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
break;
idx = srcu_read_lock(&vcpu->kvm->srcu);
- r = kvm_x86_ops.nested_ops->set_state(vcpu, user_kvm_nested_state, &kvm_state);
+ r = kvm_nested_call(set_state)(vcpu, user_kvm_nested_state, &kvm_state);
srcu_read_unlock(&vcpu->kvm->srcu, idx);
break;
}
@@ -6903,6 +6910,22 @@ static void kvm_setup_efer_caps(void)
kvm_enable_efer_bits(EFER_AUTOIBRS);
}
+static void kvm_nested_ops_update(const struct kvm_x86_nested_ops *nested_ops)
+{
+ memcpy(&kvm_nested_ops, nested_ops, sizeof(kvm_nested_ops));
+
+#define __KVM_X86_NESTED_OP(func) \
+ static_call_update(kvm_x86_nested_##func, kvm_nested_ops.func);
+#define KVM_X86_NESTED_OP(func) \
+ WARN_ON(!kvm_nested_ops.func); __KVM_X86_NESTED_OP(func)
+#define KVM_X86_NESTED_OP_OPTIONAL __KVM_X86_NESTED_OP
+#define KVM_X86_NESTED_OP_OPTIONAL_RET0(func) \
+ static_call_update(kvm_x86_nested_##func, (void *)kvm_nested_ops.func ? : \
+ (void *)__static_call_return0);
+#include <asm/kvm-x86-nested-ops.h>
+#undef __KVM_X86_NESTED_OP
+}
+
static inline void kvm_ops_update(struct kvm_x86_init_ops *ops)
{
memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
@@ -6918,6 +6941,8 @@ static inline void kvm_ops_update(struct kvm_x86_init_ops *ops)
#include <asm/kvm-x86-ops.h>
#undef __KVM_X86_OP
+ kvm_nested_ops_update(ops->nested_ops);
+
kvm_pmu_ops_update(ops->pmu_ops);
}
@@ -7454,11 +7479,11 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
int kvm_check_nested_events(struct kvm_vcpu *vcpu)
{
if (kvm_test_request(KVM_REQ_TRIPLE_FAULT, vcpu)) {
- kvm_x86_ops.nested_ops->triple_fault(vcpu);
+ kvm_nested_call(triple_fault)(vcpu);
return 1;
}
- return kvm_x86_ops.nested_ops->check_events(vcpu);
+ return kvm_nested_call(check_events)(vcpu);
}
static void kvm_inject_exception(struct kvm_vcpu *vcpu)
@@ -7696,9 +7721,7 @@ static int kvm_check_and_inject_events(struct kvm_vcpu *vcpu,
kvm_x86_call(enable_irq_window)(vcpu);
}
- if (is_guest_mode(vcpu) &&
- kvm_x86_ops.nested_ops->has_events &&
- kvm_x86_ops.nested_ops->has_events(vcpu, true))
+ if (is_guest_mode(vcpu) && kvm_nested_call(has_events)(vcpu, true))
*req_immediate_exit = true;
/*
@@ -8021,7 +8044,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
}
if (kvm_check_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu)) {
- if (unlikely(!kvm_x86_ops.nested_ops->get_nested_state_pages(vcpu))) {
+ if (unlikely(!kvm_nested_call(get_nested_state_pages)(vcpu))) {
r = 0;
goto out;
}
@@ -8073,7 +8096,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
}
if (kvm_test_request(KVM_REQ_TRIPLE_FAULT, vcpu)) {
if (is_guest_mode(vcpu))
- kvm_x86_ops.nested_ops->triple_fault(vcpu);
+ kvm_nested_call(triple_fault)(vcpu);
if (kvm_check_request(KVM_REQ_TRIPLE_FAULT, vcpu)) {
vcpu->run->exit_reason = KVM_EXIT_SHUTDOWN;
@@ -8491,9 +8514,7 @@ bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
if (kvm_hv_has_stimer_pending(vcpu))
return true;
- if (is_guest_mode(vcpu) &&
- kvm_x86_ops.nested_ops->has_events &&
- kvm_x86_ops.nested_ops->has_events(vcpu, false))
+ if (is_guest_mode(vcpu) && kvm_nested_call(has_events)(vcpu, false))
return true;
if (kvm_xen_has_pending_events(vcpu))
@@ -8896,8 +8917,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
* a pending VM-Exit if L1 wants to intercept the exception.
*/
if (vcpu->arch.exception_from_userspace && is_guest_mode(vcpu) &&
- kvm_x86_ops.nested_ops->is_exception_vmexit(vcpu, ex->vector,
- ex->error_code)) {
+ kvm_nested_call(is_exception_vmexit)(vcpu, ex->vector, ex->error_code)) {
kvm_queue_exception_vmexit(vcpu, ex->vector,
ex->has_error_code, ex->error_code,
ex->has_payload, ex->payload);
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 8ece468087a8ee..b510b631f0c522 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -93,7 +93,7 @@ int kvm_check_nested_events(struct kvm_vcpu *vcpu);
/* Forcibly leave the nested mode in cases like a vCPU reset */
static inline void kvm_leave_nested(struct kvm_vcpu *vcpu)
{
- kvm_x86_ops.nested_ops->leave_nested(vcpu);
+ kvm_nested_call(leave_nested)(vcpu);
}
/*
|
| 3/2 | 2026/07/01 02:56 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9517 output: 20 thoughts: 1501 Thoughts: **Refactoring KVM Nested Virtualization Operations** Okay, so I'm looking at this patch. It's refactoring the KVM nested virtualization operations, essentially swapping out indirect function calls for static ones. The goal is performance improvement by avoiding those retpoline-inducing indirect branches. They're introducing `kvm_nested_call` and `KVM_X86_NESTED_OP` macros, along with a `kvm_nested_ops` structure and an `enabled` flag within it. This seems pretty clean, mimicking the existing `kvm_x86_ops` refactor. It touches a bunch of core x86 KVM files, so we need to be careful. Functionally, I need to verify there are no regressions. It looks like it's primarily replacing checks like `kvm_x86_ops.nested_ops->...` with `kvm_nested_ops.enabled` and then calling the function through `kvm_nested_call`. I see that optional functions are handled by returning 0 if they're not defined, which *seems* functionally equivalent to the old NULL checks. The change to the `get_state` check looks safe. It's essentially the same logic, but with a different check. I did spot some subtle differences, for instance: * Some checks now require the `kvm_nested_ops.enabled` check, with a direct check for the nested operation. The core of this patch seems to be an improvement in the calling mechanism, which, while changing the control flow slightly, maintains the same functional output. It's about how the functions are called, rather than the core logic. Now, should we fuzz this? The prompt says "Return WorthFuzzing=false if the patch only contains...Purely decorative changes...Changes to numeric constants or macros that do not functionally alter execution flow". It looks like this one falls under that category, because the underlying logic remains unchanged. However, introducing a new structure and new call macros does create more points of failure, which suggests it warrants further scrutiny. So, let's see. My focus points should include: `kvm_arch_vcpu_ioctl`, `kvm_vm_ioctl_check_extension`, `kvm_check_nested_events`, `kvm_check_and_inject_events`, `vcpu_enter_guest`, `kvm_vcpu_has_events`, `kvm_arch_vcpu_ioctl_run`, also `kvm_get_hv_cpuid`, `kvm_hv_hypercall_complete`. The hot paths like `vcpu_enter_guest` and `kvm_arch_vcpu_ioctl_run` are interesting, but I'd rather avoid them as initial fuzzing entry points. I'd lean towards ones such as `kvm_vm_ioctl_check_extension`, `kvm_arch_vcpu_ioctl`, `kvm_get_hv_cpuid`, and `kvm_hv_hypercall_complete`. I'll do a quick grep to make sure the `kvm_nested_ops` isn't used in some bizarre corner case. |
| 4/2 | 2026/07/01 02:56 | tool | grepper |
0mArgs:{
"Expression": "kvm_nested_ops"
}Results: {
"Output": "arch/x86/include/asm/kvm_host.h=1955=extern struct kvm_x86_ops kvm_x86_ops;\narch/x86/include/asm/kvm_host.h:1956:extern struct kvm_x86_nested_ops kvm_nested_ops __read_mostly;\narch/x86/include/asm/kvm_host.h-1957-\n--\narch/x86/kvm/hyperv.c=2772=int kvm_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,\n--\narch/x86/kvm/hyperv.c-2789-\narch/x86/kvm/hyperv.c:2790:\tif (kvm_nested_ops.enabled)\narch/x86/kvm/hyperv.c-2791-\t\tevmcs_ver = kvm_nested_call(get_evmcs_version)(vcpu);\n--\narch/x86/kvm/x86.c=156=struct kvm_x86_ops kvm_x86_ops __read_mostly;\narch/x86/kvm/x86.c:157:struct kvm_x86_nested_ops kvm_nested_ops __read_mostly;\narch/x86/kvm/x86.c-158-\n--\narch/x86/kvm/x86.c=2194=int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)\n--\narch/x86/kvm/x86.c-2356-\tcase KVM_CAP_NESTED_STATE:\narch/x86/kvm/x86.c:2357:\t\tr = kvm_nested_ops.enabled ? kvm_nested_call(get_state)(NULL, NULL, 0) : 0;\narch/x86/kvm/x86.c-2358-\t\tbreak;\n--\narch/x86/kvm/x86.c-2363-\tcase KVM_CAP_HYPERV_ENLIGHTENED_VMCS:\narch/x86/kvm/x86.c:2364:\t\tr = kvm_nested_ops.enabled \u0026\u0026 kvm_nested_ops.enable_evmcs != NULL;\narch/x86/kvm/x86.c-2365-\t\tbreak;\n--\narch/x86/kvm/x86.c=3352=static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,\n--\narch/x86/kvm/x86.c-3375-\narch/x86/kvm/x86.c:3376:\t\t\tif (!kvm_nested_ops.enabled ||\narch/x86/kvm/x86.c:3377:\t\t\t !kvm_nested_ops.enable_evmcs)\narch/x86/kvm/x86.c-3378-\t\t\t\treturn -ENOTTY;\n--\narch/x86/kvm/x86.c=3406=long kvm_arch_vcpu_ioctl(struct file *filp,\n--\narch/x86/kvm/x86.c-3742-\t\tr = -EINVAL;\narch/x86/kvm/x86.c:3743:\t\tif (!kvm_nested_ops.enabled)\narch/x86/kvm/x86.c-3744-\t\t\tbreak;\n--\narch/x86/kvm/x86.c-3771-\t\tr = -EINVAL;\narch/x86/kvm/x86.c:3772:\t\tif (!kvm_nested_ops.enabled)\narch/x86/kvm/x86.c-3773-\t\t\tbreak;\n--\narch/x86/kvm/x86.c=6901=static void kvm_setup_efer_caps(void)\n--\narch/x86/kvm/x86.c-6912-\narch/x86/kvm/x86.c:6913:static void kvm_nested_ops_update(const struct kvm_x86_nested_ops *nested_ops)\narch/x86/kvm/x86.c-6914-{\narch/x86/kvm/x86.c:6915:\tmemcpy(\u0026kvm_nested_ops, nested_ops, sizeof(kvm_nested_ops));\narch/x86/kvm/x86.c-6916-\narch/x86/kvm/x86.c-6917-#define __KVM_X86_NESTED_OP(func) \\\narch/x86/kvm/x86.c:6918:\tstatic_call_update(kvm_x86_nested_##func, kvm_nested_ops.func);\narch/x86/kvm/x86.c-6919-#define KVM_X86_NESTED_OP(func) \\\narch/x86/kvm/x86.c:6920:\tWARN_ON(!kvm_nested_ops.func); __KVM_X86_NESTED_OP(func)\narch/x86/kvm/x86.c-6921-#define KVM_X86_NESTED_OP_OPTIONAL __KVM_X86_NESTED_OP\narch/x86/kvm/x86.c-6922-#define KVM_X86_NESTED_OP_OPTIONAL_RET0(func) \\\narch/x86/kvm/x86.c:6923:\tstatic_call_update(kvm_x86_nested_##func, (void *)kvm_nested_ops.func ? : \\\narch/x86/kvm/x86.c-6924-\t\t\t\t\t\t (void *)__static_call_return0);\n--\narch/x86/kvm/x86.c=6929=static inline void kvm_ops_update(struct kvm_x86_init_ops *ops)\n--\narch/x86/kvm/x86.c-6943-\narch/x86/kvm/x86.c:6944:\tkvm_nested_ops_update(ops-\u003enested_ops);\narch/x86/kvm/x86.c-6945-\n"
} |
| 5/2 | 2026/07/01 02:57 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13430 output: 21 thoughts: 279 Thoughts: **Analyzing the KVM Nested Virtualization Patch** Okay, so this patch is making some fundamental changes to how nested virtualization operations are handled in KVM. Replacing those indirect calls with static calls, using `kvm_nested_ops` and `kvm_nested_call`, that's definitely a functional change. That means it's not just cosmetic; it's altering the *method* of invocation. I need to pay close attention to the initialization and validation now, particularly that `kvm_nested_ops.enabled` flag. A bug there, in the setup of the static calls themselves, or in how that `enabled` flag is handled, could be catastrophic. Crashes or subtle misbehavior in nested virtualization are not something I want to deal with, and those are potentially very difficult to debug. Now, let me make sure I understand the relevant configuration options. `KVM`, obviously, is the core. Then we have `KVM_INTEL` and `KVM_AMD`, which are essential because they provide the architecture-specific implementations. The diff also brings up `KVM_HYPERV`. Now, is that a separate option? Or is it a sub-option, or perhaps enabled by default if `KVM` is? I should check the Kconfig files. And I need to make sure to review those focused symbols: `kvm_arch_vcpu_ioctl`, `kvm_vm_ioctl_check_extension`, `kvm_get_hv_cpuid`, `kvm_hv_hypercall_complete`, and `kvm_vcpu_ioctl_enable_cap`. They are likely at the core of the functionality that's changing, and I'll need to understand how they are called and changed to ensure nothing is broken. |
| 6/2 | 2026/07/01 02:57 | tool | grepper |
0mArgs:{
"Expression": "config KVM_HYPERV"
}Results: {
"Output": "arch/x86/kvm/Kconfig=182=config KVM_SMM\n--\narch/x86/kvm/Kconfig-192-\narch/x86/kvm/Kconfig:193:config KVM_HYPERV\narch/x86/kvm/Kconfig-194-\tbool \"Support for Microsoft Hyper-V emulation\"\n"
} |
| 7/2 | 2026/07/01 02:57 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14212 output: 180 thoughts: 424 Thoughts: **My Assessment of the KVM Nested Virtualization Patch** Okay, so I've looked this patch over, and my immediate thought is that we definitely need to include `KVM_HYPERV` in the configurations. It's crucial for the specific functionality this refactoring touches. Let's break down the implications and confirm the choices. From the analysis, this is **worth fuzzing**, and the reasoning is sound. The patch is refactoring how KVM handles nested virtualization, specifically moving from indirect function pointers to static calls. This is a significant architectural shift that introduces new initialization steps, particularly the `kvm_nested_ops.enabled` check. Given this change in control flow, any bugs here could be nasty, potentially resulting in crashes or incorrect behaviors when nesting VMs, which can be difficult to diagnose. The initial selection of **focus symbols** is a good starting point. I reviewed the list again to be absolutely sure: `kvm_arch_vcpu_ioctl`, `kvm_vm_ioctl_check_extension`, `kvm_get_hv_cpuid`, `kvm_hv_hypercall_complete`, and `kvm_vcpu_ioctl_enable_cap`. Double-checking, `kvm_vcpu_ioctl_enable_cap` handles `KVM_CAP_HYPERV_ENLIGHTENED_VMCS` which, as expected, ultimately uses `kvm_nested_ops.enable_evmcs`. Perfect. That makes it a solid focus symbol. Then, `kvm_vm_ioctl_check_extension` deals with `KVM_CAP_NESTED_STATE` and `KVM_CAP_HYPERV_ENLIGHTENED_VMCS`, and that aligns with the changes and new logic. It's a valid choice. `kvm_arch_vcpu_ioctl` handling of `KVM_GET_NESTED_STATE` and `KVM_SET_NESTED_STATE` makes it a solid choice. `kvm_get_hv_cpuid` uses `get_evmcs_version`, so it also warrants scrutiny. And finally, `kvm_hv_hypercall_complete` is calling `hv_inject_synthetic_vmexit_post_tlb_flush`, so it fits the focus too. Yes, this is all good. I can proceed to call `set-results` now. |
| 8/2 | 2026/07/01 02:57 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"KVM",
"KVM_INTEL",
"KVM_AMD",
"KVM_HYPERV"
],
"FocusSymbols": [
"kvm_arch_vcpu_ioctl",
"kvm_vm_ioctl_check_extension",
"kvm_get_hv_cpuid",
"kvm_hv_hypercall_complete",
"kvm_vcpu_ioctl_enable_cap"
],
"Reasoning": "The patch refactors KVM nested virtualization operations to use static calls instead of indirect function pointers. This changes the execution flow mechanism and introduces new initialization and checking logic (kvm_nested_ops.enabled). Bugs in this refactoring could lead to crashes or incorrect behavior in nested virtualization scenarios.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"KVM",
"KVM_INTEL",
"KVM_AMD",
"KVM_HYPERV"
],
"FocusSymbols": [
"kvm_arch_vcpu_ioctl",
"kvm_vm_ioctl_check_extension",
"kvm_get_hv_cpuid",
"kvm_hv_hypercall_complete",
"kvm_vcpu_ioctl_enable_cap"
],
"Reasoning": "The patch refactors KVM nested virtualization operations to use static calls instead of indirect function pointers. This changes the execution flow mechanism and introduces new initialization and checking logic (kvm_nested_ops.enabled). Bugs in this refactoring could lead to crashes or incorrect behavior in nested virtualization scenarios.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|