| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/06/25 22:38 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": [
"KVM_AMD_SEV",
"KVM_AMD",
"KVM",
"KVM_SW_PROTECTED_VM"
],
"FocusSymbols": [
"__sev_snp_reload_vmsa",
"sev_snp_reload_vmsa",
"sev_gmem_invalidate_range",
"sev_gmem_free_folio",
"kvm_arch_gmem_invalidate_range",
"kvm_arch_gmem_free_folio",
"sev_snp_init_protected_guest_state"
],
"Reasoning": "The patch modifies KVM's handling of AMD SEV-SNP VMSA (Virtual Machine Save Area) and guest_memfd invalidation. It introduces new functions to reload VMSA pages when the backing guest_memfd is invalidated (e.g., via fallocate punch hole) and changes the architecture-specific guest_memfd invalidation callbacks. This is functional core KVM code that is reachable from userspace via KVM ioctls and guest_memfd operations.",
"WorthFuzzing": true
} |
| 1/1 | 2026/06/25 22:38 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 36b0406645f2f8b6b2789912fff6bbea3d58fb36\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Thu Jun 25 22:38:14 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h\nindex 83dc5086138b39..fd08454c755364 100644\n--- a/arch/x86/include/asm/kvm-x86-ops.h\n+++ b/arch/x86/include/asm/kvm-x86-ops.h\n@@ -134,6 +134,7 @@ KVM_X86_OP_OPTIONAL(mem_enc_unregister_region)\n KVM_X86_OP_OPTIONAL(vm_copy_enc_context_from)\n KVM_X86_OP_OPTIONAL(vm_move_enc_context_from)\n KVM_X86_OP_OPTIONAL(guest_memory_reclaimed)\n+KVM_X86_OP_OPTIONAL(reload_vmsa)\n KVM_X86_OP(get_feature_msr)\n KVM_X86_OP(check_emulate_instruction)\n KVM_X86_OP(apic_init_signal_blocked)\n@@ -145,9 +146,14 @@ KVM_X86_OP(vcpu_deliver_sipi_vector)\n KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons);\n KVM_X86_OP_OPTIONAL(get_untagged_addr)\n KVM_X86_OP_OPTIONAL(alloc_apic_backing_page)\n+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE\n KVM_X86_OP_OPTIONAL_RET0(gmem_prepare)\n+#endif\n+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n+KVM_X86_OP_OPTIONAL(gmem_invalidate_range)\n+KVM_X86_OP_OPTIONAL(gmem_free_folio)\n+#endif\n KVM_X86_OP_OPTIONAL_RET0(gmem_max_mapping_level)\n-KVM_X86_OP_OPTIONAL(gmem_invalidate)\n #endif\n \n #undef KVM_X86_OP\ndiff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h\nindex b517257a631532..ee47a0d1feb990 100644\n--- a/arch/x86/include/asm/kvm_host.h\n+++ b/arch/x86/include/asm/kvm_host.h\n@@ -122,6 +122,8 @@\n \tKVM_ARCH_REQ_FLAGS(31, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)\n #define KVM_REQ_HV_TLB_FLUSH \\\n \tKVM_ARCH_REQ_FLAGS(32, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)\n+#define KVM_REQ_VMSA_PAGE_RELOAD \\\n+\tKVM_ARCH_REQ_FLAGS(33, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)\n #define KVM_REQ_UPDATE_PROTECTED_GUEST_STATE \\\n \tKVM_ARCH_REQ_FLAGS(34, KVM_REQUEST_WAIT)\n \n@@ -1878,6 +1880,7 @@ struct kvm_x86_ops {\n \tint (*vm_copy_enc_context_from)(struct kvm *kvm, unsigned int source_fd);\n \tint (*vm_move_enc_context_from)(struct kvm *kvm, unsigned int source_fd);\n \tvoid (*guest_memory_reclaimed)(struct kvm *kvm);\n+\tvoid (*reload_vmsa)(struct kvm_vcpu *vcpu);\n \n \tint (*get_feature_msr)(u32 msr, u64 *data);\n \n@@ -1900,8 +1903,13 @@ struct kvm_x86_ops {\n \n \tgva_t (*get_untagged_addr)(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags);\n \tvoid *(*alloc_apic_backing_page)(struct kvm_vcpu *vcpu);\n+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE\n \tint (*gmem_prepare)(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);\n-\tvoid (*gmem_invalidate)(kvm_pfn_t start, kvm_pfn_t end);\n+#endif\n+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n+\tvoid (*gmem_invalidate_range)(struct kvm *kvm, struct kvm_gfn_range *range);\n+\tvoid (*gmem_free_folio)(struct folio *folio);\n+#endif\n \tint (*gmem_max_mapping_level)(struct kvm *kvm, kvm_pfn_t pfn, bool is_private);\n };\n \ndiff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c\nindex 74fb15551e83fa..7e06ed16f47461 100644\n--- a/arch/x86/kvm/svm/sev.c\n+++ b/arch/x86/kvm/svm/sev.c\n@@ -3979,30 +3979,21 @@ static int snp_begin_psc(struct vcpu_svm *svm)\n \treturn snp_do_psc(svm);\n }\n \n-/*\n- * Invoked as part of svm_vcpu_reset() processing of an init event.\n- */\n-static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)\n+static void __sev_snp_reload_vmsa(struct kvm_vcpu *vcpu, gpa_t gpa)\n {\n \tstruct vcpu_svm *svm = to_svm(vcpu);\n \tstruct kvm_memory_slot *slot;\n+\tstruct kvm *kvm = vcpu-\u003ekvm;\n+\tgfn_t gfn = gpa_to_gfn(gpa);\n+\tunsigned long mmu_seq;\n \tstruct page *page;\n \tkvm_pfn_t pfn;\n-\tgfn_t gfn;\n-\n-\tguard(mutex)(\u0026svm-\u003esev_es.snp_vmsa_mutex);\n-\n-\tif (!svm-\u003esev_es.snp_ap_waiting_for_reset)\n-\t\treturn;\n-\n-\tsvm-\u003esev_es.snp_ap_waiting_for_reset = false;\n \n-\t/* Mark the vCPU as offline and not runnable */\n-\tvcpu-\u003earch.pv.pv_unhalted = false;\n-\tkvm_set_mp_state(vcpu, KVM_MP_STATE_HALTED);\n+\tlockdep_assert_held(\u0026svm-\u003esev_es.snp_vmsa_mutex);\n \n-\t/* Clear use of the VMSA */\n+\t/* Clear use of the VMSA. */\n \tsvm-\u003evmcb-\u003econtrol.vmsa_pa = INVALID_PAGE;\n+\tsvm-\u003esev_es.snp_guest_vmsa_gpa = INVALID_PAGE;\n \n \t/*\n \t * When replacing the VMSA during SEV-SNP AP creation,\n@@ -4010,16 +4001,27 @@ static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)\n \t */\n \tvmcb_mark_all_dirty(svm-\u003evmcb);\n \n-\tif (!VALID_PAGE(svm-\u003esev_es.snp_vmsa_gpa))\n-\t\treturn;\n+\t/*\n+\t * From this point forward, the VMSA will always be a guest-mapped page\n+\t * rather than the initial one allocated by KVM in svm-\u003esev_es.vmsa. In\n+\t * theory, svm-\u003esev_es.vmsa could be free'd and cleaned up here, but\n+\t * that involves cleanups like flushing caches, which would ideally be\n+\t * handled during teardown rather than guest boot. Deferring that also\n+\t * allows the existing logic for SEV-ES VMSAs to be re-used with\n+\t * minimal SNP-specific changes.\n+\t */\n+\tsvm-\u003esev_es.snp_has_guest_vmsa = true;\n \n-\tgfn = gpa_to_gfn(svm-\u003esev_es.snp_vmsa_gpa);\n-\tsvm-\u003esev_es.snp_vmsa_gpa = INVALID_PAGE;\n+\tif (!VALID_PAGE(gpa))\n+\t\treturn;\n \n \tslot = gfn_to_memslot(vcpu-\u003ekvm, gfn);\n \tif (!slot)\n \t\treturn;\n \n+\tmmu_seq = kvm-\u003emmu_invalidate_seq;\n+\tsmp_rmb();\n+\n \t/*\n \t * The new VMSA will be private memory guest memory, so retrieve the\n \t * PFN from the gmem backend.\n@@ -4027,29 +4029,64 @@ static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)\n \tif (kvm_gmem_get_pfn(vcpu-\u003ekvm, slot, gfn, \u0026pfn, \u0026page, NULL))\n \t\treturn;\n \n+\tread_lock(\u0026kvm-\u003emmu_lock);\n \t/*\n-\t * From this point forward, the VMSA will always be a guest-mapped page\n-\t * rather than the initial one allocated by KVM in svm-\u003esev_es.vmsa. In\n-\t * theory, svm-\u003esev_es.vmsa could be free'd and cleaned up here, but\n-\t * that involves cleanups like flushing caches, which would ideally be\n-\t * handled during teardown rather than guest boot. Deferring that also\n-\t * allows the existing logic for SEV-ES VMSAs to be re-used with\n-\t * minimal SNP-specific changes.\n+\t * Save the guest-provided GPA. If retry is needed, then KVM will try\n+\t * again with the same GPA. If the VMSA is usable, then KVM needs to\n+\t * track the GPA so that the VMSA can be reloaded if the backing page\n+\t * for the GPA is invalidated.\n \t */\n-\tsvm-\u003esev_es.snp_has_guest_vmsa = true;\n+\tsvm-\u003esev_es.snp_guest_vmsa_gpa = gpa;\n+\tif (mmu_invalidate_retry_gfn(kvm, mmu_seq, gfn))\n+\t\tkvm_make_request(KVM_REQ_VMSA_PAGE_RELOAD, vcpu);\n+\telse\n+\t\tsvm-\u003evmcb-\u003econtrol.vmsa_pa = pfn_to_hpa(pfn);\n+\tread_unlock(\u0026kvm-\u003emmu_lock);\n+\n+\tkvm_release_page_clean(page);\n+}\n+\n+/*\n+ * Invoked as part of svm_vcpu_reset() processing of an init event.\n+ */\n+static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)\n+{\n+\tstruct vcpu_svm *svm = to_svm(vcpu);\n+\tgpa_t gpa;\n+\n+\tguard(mutex)(\u0026svm-\u003esev_es.snp_vmsa_mutex);\n+\n+\tif (!svm-\u003esev_es.snp_ap_waiting_for_reset)\n+\t\treturn;\n+\n+\tsvm-\u003esev_es.snp_ap_waiting_for_reset = false;\n+\n+\t/* Mark the vCPU as offline and not runnable */\n+\tvcpu-\u003earch.pv.pv_unhalted = false;\n+\tkvm_set_mp_state(vcpu, KVM_MP_STATE_HALTED);\n \n-\t/* Use the new VMSA */\n-\tsvm-\u003evmcb-\u003econtrol.vmsa_pa = pfn_to_hpa(pfn);\n+\tgpa = svm-\u003esev_es.snp_pending_vmsa_gpa;\n+\tsvm-\u003esev_es.snp_pending_vmsa_gpa = INVALID_PAGE;\n \n-\t/* Mark the vCPU as runnable */\n-\tkvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE);\n+\t__sev_snp_reload_vmsa(vcpu, gpa);\n \n \t/*\n-\t * gmem pages aren't currently migratable, but if this ever changes\n-\t * then care should be taken to ensure svm-\u003esev_es.vmsa is pinned\n-\t * through some other means.\n+\t * Mark the vCPU as runnable for CREATE requests, indicated by a valid\n+\t * VMSA GPA, even if installing the VMSA failed, so that KVM_RUN will\n+\t * fail instead of blocking indefinitely and hanging the vCPU, e.g. if\n+\t * the backing guest_memfd page is unavailable.\n \t */\n-\tkvm_release_page_clean(page);\n+\tif (VALID_PAGE(gpa))\n+\t\tkvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE);\n+}\n+\n+void sev_snp_reload_vmsa(struct kvm_vcpu *vcpu)\n+{\n+\tstruct vcpu_sev_es_state *sev_es = \u0026to_svm(vcpu)-\u003esev_es;\n+\n+\tguard(mutex)(\u0026sev_es-\u003esnp_vmsa_mutex);\n+\n+\t__sev_snp_reload_vmsa(vcpu, sev_es-\u003esnp_guest_vmsa_gpa);\n }\n \n static int sev_snp_ap_creation(struct vcpu_svm *svm)\n@@ -4105,10 +4142,10 @@ static int sev_snp_ap_creation(struct vcpu_svm *svm)\n \t\t\treturn -EINVAL;\n \t\t}\n \n-\t\ttarget_svm-\u003esev_es.snp_vmsa_gpa = svm-\u003evmcb-\u003econtrol.exit_info_2;\n+\t\ttarget_svm-\u003esev_es.snp_pending_vmsa_gpa = svm-\u003evmcb-\u003econtrol.exit_info_2;\n \t\tbreak;\n \tcase SVM_VMGEXIT_AP_DESTROY:\n-\t\ttarget_svm-\u003esev_es.snp_vmsa_gpa = INVALID_PAGE;\n+\t\ttarget_svm-\u003esev_es.snp_pending_vmsa_gpa = INVALID_PAGE;\n \t\tbreak;\n \tdefault:\n \t\tvcpu_unimpl(vcpu, \"vmgexit: invalid AP creation request [%#x] from guest\\n\",\n@@ -4791,6 +4828,8 @@ int sev_vcpu_create(struct kvm_vcpu *vcpu)\n \t\treturn -ENOMEM;\n \n \tsvm-\u003esev_es.vmsa = page_address(vmsa_page);\n+\tsvm-\u003esev_es.snp_pending_vmsa_gpa = INVALID_PAGE;\n+\tsvm-\u003esev_es.snp_guest_vmsa_gpa = INVALID_PAGE;\n \n \tvcpu-\u003earch.guest_tsc_protected = snp_is_secure_tsc_enabled(vcpu-\u003ekvm);\n \n@@ -5115,9 +5154,36 @@ int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order)\n \n \treturn 0;\n }\n+void sev_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range)\n+{\n+\tstruct kvm_vcpu *vcpu;\n+\tunsigned long i;\n+\n+\tlockdep_assert_held_write(\u0026kvm-\u003emmu_lock);\n+\n+\t/*\n+\t * An unstable result for \"is SNP\" is a-ok here, thanks to mmu_lock.\n+\t * The vCPU's VMSA GPA is invalidated before the vCPU is made visible\n+\t * to other tasks, and can only become valid while holding mmu_lock,\n+\t * after the VM is fully committed to being an SNP VM.\n+\t */\n+\tif (!____sev_snp_guest(kvm))\n+\t\treturn;\n+\n+\tkvm_for_each_vcpu(i, vcpu, kvm) {\n+\t\tgpa_t gpa = to_svm(vcpu)-\u003esev_es.snp_guest_vmsa_gpa;\n+\n+\t\tif (VALID_PAGE(gpa) \u0026\u0026\n+\t\t gpa_to_gfn(gpa) \u003e= range-\u003estart \u0026\u0026\n+\t\t gpa_to_gfn(gpa) \u003c range-\u003eend)\n+\t\t\tkvm_make_request_and_kick(KVM_REQ_VMSA_PAGE_RELOAD, vcpu);\n+\t}\n+}\n \n-void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)\n+void sev_gmem_free_folio(struct folio *folio)\n {\n+\tkvm_pfn_t start = page_to_pfn(folio_page(folio, 0));\n+\tkvm_pfn_t end = start + (1ul \u003c\u003c folio_order(folio));\n \tkvm_pfn_t pfn;\n \n \tif (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))\ndiff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c\nindex ef69a51ab27f98..7d3dd371907045 100644\n--- a/arch/x86/kvm/svm/svm.c\n+++ b/arch/x86/kvm/svm/svm.c\n@@ -5445,6 +5445,7 @@ struct kvm_x86_ops svm_x86_ops __initdata = {\n \t.mem_enc_register_region = sev_mem_enc_register_region,\n \t.mem_enc_unregister_region = sev_mem_enc_unregister_region,\n \t.guest_memory_reclaimed = sev_guest_memory_reclaimed,\n+\t.reload_vmsa = sev_snp_reload_vmsa,\n \n \t.vm_copy_enc_context_from = sev_vm_copy_enc_context_from,\n \t.vm_move_enc_context_from = sev_vm_move_enc_context_from,\n@@ -5460,9 +5461,12 @@ struct kvm_x86_ops svm_x86_ops __initdata = {\n \t.vcpu_get_apicv_inhibit_reasons = avic_vcpu_get_apicv_inhibit_reasons,\n \t.alloc_apic_backing_page = svm_alloc_apic_backing_page,\n \n+#ifdef CONFIG_KVM_AMD_SEV\n \t.gmem_prepare = sev_gmem_prepare,\n-\t.gmem_invalidate = sev_gmem_invalidate,\n+\t.gmem_invalidate_range = sev_gmem_invalidate_range,\n+\t.gmem_free_folio = sev_gmem_free_folio,\n \t.gmem_max_mapping_level = sev_gmem_max_mapping_level,\n+#endif\n };\n \n /*\ndiff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h\nindex 716be21fba3354..c7ecc5fca689b0 100644\n--- a/arch/x86/kvm/svm/svm.h\n+++ b/arch/x86/kvm/svm/svm.h\n@@ -271,7 +271,8 @@ struct vcpu_sev_es_state {\n \tu64 ghcb_registered_gpa;\n \n \tstruct mutex snp_vmsa_mutex; /* Used to handle concurrent updates of VMSA. */\n-\tgpa_t snp_vmsa_gpa;\n+\tgpa_t snp_pending_vmsa_gpa;\n+\tgpa_t snp_guest_vmsa_gpa;\n \tbool snp_ap_waiting_for_reset;\n \tbool snp_has_guest_vmsa;\n };\n@@ -995,6 +996,7 @@ static inline struct page *snp_safe_alloc_page(void)\n {\n \treturn snp_safe_alloc_page_node(numa_node_id(), GFP_KERNEL_ACCOUNT);\n }\n+void sev_snp_reload_vmsa(struct kvm_vcpu *vcpu);\n \n int sev_vcpu_create(struct kvm_vcpu *vcpu);\n void sev_free_vcpu(struct kvm_vcpu *vcpu);\n@@ -1008,7 +1010,8 @@ int sev_dev_get_attr(u32 group, u64 attr, u64 *val);\n extern unsigned int max_sev_asid;\n void sev_handle_rmp_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code);\n int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);\n-void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);\n+void sev_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range);\n+void sev_gmem_free_folio(struct folio *folio);\n int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, bool is_private);\n struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu);\n void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa);\n@@ -1038,7 +1041,6 @@ static inline int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, in\n {\n \treturn 0;\n }\n-static inline void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end) {}\n static inline int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, bool is_private)\n {\n \treturn 0;\ndiff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c\nindex 0626e835e9eb77..9df6acf9a982e6 100644\n--- a/arch/x86/kvm/x86.c\n+++ b/arch/x86/kvm/x86.c\n@@ -8167,6 +8167,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)\n \t\t\t\tgoto out;\n \t\t\t}\n \t\t}\n+\t\tif (kvm_check_request(KVM_REQ_VMSA_PAGE_RELOAD, vcpu))\n+\t\t\tkvm_x86_call(reload_vmsa)(vcpu);\n \t}\n \n \tif (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win ||\n@@ -10592,9 +10594,13 @@ int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_ord\n #endif\n \n #ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n-void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)\n+void kvm_arch_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range)\n {\n-\tkvm_x86_call(gmem_invalidate)(start, end);\n+\tkvm_x86_call(gmem_invalidate_range)(kvm, range);\n+}\n+void kvm_arch_gmem_free_folio(struct folio *folio)\n+{\n+\tkvm_x86_call(gmem_free_folio)(folio);\n }\n #endif\n #endif\ndiff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h\nindex ab8cfaec82d31e..6b7f8801505d5c 100644\n--- a/include/linux/kvm_host.h\n+++ b/include/linux/kvm_host.h\n@@ -2607,7 +2607,8 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src,\n #endif\n \n #ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n-void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);\n+void kvm_arch_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range);\n+void kvm_arch_gmem_free_folio(struct folio *folio);\n #endif\n \n #ifdef CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY\ndiff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c\nindex 86690683b2fe3e..8ec5041934dbcf 100644\n--- a/virt/kvm/guest_memfd.c\n+++ b/virt/kvm/guest_memfd.c\n@@ -185,6 +185,10 @@ static void __kvm_gmem_invalidate_start(struct gmem_file *f, pgoff_t start,\n \t\t}\n \n \t\tflush |= kvm_mmu_unmap_gfn_range(kvm, \u0026gfn_range);\n+\n+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n+\t\tkvm_arch_gmem_invalidate_range(kvm, \u0026gfn_range);\n+#endif\n \t}\n \n \tif (flush)\n@@ -523,23 +527,12 @@ static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *fol\n \treturn MF_DELAYED;\n }\n \n-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n-static void kvm_gmem_free_folio(struct folio *folio)\n-{\n-\tstruct page *page = folio_page(folio, 0);\n-\tkvm_pfn_t pfn = page_to_pfn(page);\n-\tint order = folio_order(folio);\n-\n-\tkvm_arch_gmem_invalidate(pfn, pfn + (1ul \u003c\u003c order));\n-}\n-#endif\n-\n static const struct address_space_operations kvm_gmem_aops = {\n \t.dirty_folio = noop_dirty_folio,\n \t.migrate_folio\t= kvm_gmem_migrate_folio,\n \t.error_remove_folio = kvm_gmem_error_folio,\n #ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n-\t.free_folio = kvm_gmem_free_folio,\n+\t.free_folio = kvm_arch_gmem_free_folio,\n #endif\n };\n \n"
} |
| 2/1 | 2026/06/25 22:38 | agent | patch-evaluator |
1mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"KVM_AMD_SEV",
"KVM_AMD",
"KVM",
"KVM_SW_PROTECTED_VM"
],
"FocusSymbols": [
"__sev_snp_reload_vmsa",
"sev_snp_reload_vmsa",
"sev_gmem_invalidate_range",
"sev_gmem_free_folio",
"kvm_arch_gmem_invalidate_range",
"kvm_arch_gmem_free_folio",
"sev_snp_init_protected_guest_state"
],
"Reasoning": "The patch modifies KVM's handling of AMD SEV-SNP VMSA (Virtual Machine Save Area) and guest_memfd invalidation. It introduces new functions to reload VMSA pages when the backing guest_memfd is invalidated (e.g., via fallocate punch hole) and changes the architecture-specific guest_memfd invalidation callbacks. This is functional core KVM code that is reachable from userspace via KVM ioctls and guest_memfd operations.",
"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 36b0406645f2f8b6b2789912fff6bbea3d58fb36
Author: syz-cluster <triage@syzkaller.com>
Date: Thu Jun 25 22:38:14 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h
index 83dc5086138b39..fd08454c755364 100644
--- a/arch/x86/include/asm/kvm-x86-ops.h
+++ b/arch/x86/include/asm/kvm-x86-ops.h
@@ -134,6 +134,7 @@ KVM_X86_OP_OPTIONAL(mem_enc_unregister_region)
KVM_X86_OP_OPTIONAL(vm_copy_enc_context_from)
KVM_X86_OP_OPTIONAL(vm_move_enc_context_from)
KVM_X86_OP_OPTIONAL(guest_memory_reclaimed)
+KVM_X86_OP_OPTIONAL(reload_vmsa)
KVM_X86_OP(get_feature_msr)
KVM_X86_OP(check_emulate_instruction)
KVM_X86_OP(apic_init_signal_blocked)
@@ -145,9 +146,14 @@ KVM_X86_OP(vcpu_deliver_sipi_vector)
KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons);
KVM_X86_OP_OPTIONAL(get_untagged_addr)
KVM_X86_OP_OPTIONAL(alloc_apic_backing_page)
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE
KVM_X86_OP_OPTIONAL_RET0(gmem_prepare)
+#endif
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
+KVM_X86_OP_OPTIONAL(gmem_invalidate_range)
+KVM_X86_OP_OPTIONAL(gmem_free_folio)
+#endif
KVM_X86_OP_OPTIONAL_RET0(gmem_max_mapping_level)
-KVM_X86_OP_OPTIONAL(gmem_invalidate)
#endif
#undef KVM_X86_OP
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index b517257a631532..ee47a0d1feb990 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -122,6 +122,8 @@
KVM_ARCH_REQ_FLAGS(31, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
#define KVM_REQ_HV_TLB_FLUSH \
KVM_ARCH_REQ_FLAGS(32, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
+#define KVM_REQ_VMSA_PAGE_RELOAD \
+ KVM_ARCH_REQ_FLAGS(33, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
#define KVM_REQ_UPDATE_PROTECTED_GUEST_STATE \
KVM_ARCH_REQ_FLAGS(34, KVM_REQUEST_WAIT)
@@ -1878,6 +1880,7 @@ struct kvm_x86_ops {
int (*vm_copy_enc_context_from)(struct kvm *kvm, unsigned int source_fd);
int (*vm_move_enc_context_from)(struct kvm *kvm, unsigned int source_fd);
void (*guest_memory_reclaimed)(struct kvm *kvm);
+ void (*reload_vmsa)(struct kvm_vcpu *vcpu);
int (*get_feature_msr)(u32 msr, u64 *data);
@@ -1900,8 +1903,13 @@ struct kvm_x86_ops {
gva_t (*get_untagged_addr)(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags);
void *(*alloc_apic_backing_page)(struct kvm_vcpu *vcpu);
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE
int (*gmem_prepare)(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);
- void (*gmem_invalidate)(kvm_pfn_t start, kvm_pfn_t end);
+#endif
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
+ void (*gmem_invalidate_range)(struct kvm *kvm, struct kvm_gfn_range *range);
+ void (*gmem_free_folio)(struct folio *folio);
+#endif
int (*gmem_max_mapping_level)(struct kvm *kvm, kvm_pfn_t pfn, bool is_private);
};
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 74fb15551e83fa..7e06ed16f47461 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -3979,30 +3979,21 @@ static int snp_begin_psc(struct vcpu_svm *svm)
return snp_do_psc(svm);
}
-/*
- * Invoked as part of svm_vcpu_reset() processing of an init event.
- */
-static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)
+static void __sev_snp_reload_vmsa(struct kvm_vcpu *vcpu, gpa_t gpa)
{
struct vcpu_svm *svm = to_svm(vcpu);
struct kvm_memory_slot *slot;
+ struct kvm *kvm = vcpu->kvm;
+ gfn_t gfn = gpa_to_gfn(gpa);
+ unsigned long mmu_seq;
struct page *page;
kvm_pfn_t pfn;
- gfn_t gfn;
-
- guard(mutex)(&svm->sev_es.snp_vmsa_mutex);
-
- if (!svm->sev_es.snp_ap_waiting_for_reset)
- return;
-
- svm->sev_es.snp_ap_waiting_for_reset = false;
- /* Mark the vCPU as offline and not runnable */
- vcpu->arch.pv.pv_unhalted = false;
- kvm_set_mp_state(vcpu, KVM_MP_STATE_HALTED);
+ lockdep_assert_held(&svm->sev_es.snp_vmsa_mutex);
- /* Clear use of the VMSA */
+ /* Clear use of the VMSA. */
svm->vmcb->control.vmsa_pa = INVALID_PAGE;
+ svm->sev_es.snp_guest_vmsa_gpa = INVALID_PAGE;
/*
* When replacing the VMSA during SEV-SNP AP creation,
@@ -4010,16 +4001,27 @@ static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)
*/
vmcb_mark_all_dirty(svm->vmcb);
- if (!VALID_PAGE(svm->sev_es.snp_vmsa_gpa))
- return;
+ /*
+ * From this point forward, the VMSA will always be a guest-mapped page
+ * rather than the initial one allocated by KVM in svm->sev_es.vmsa. In
+ * theory, svm->sev_es.vmsa could be free'd and cleaned up here, but
+ * that involves cleanups like flushing caches, which would ideally be
+ * handled during teardown rather than guest boot. Deferring that also
+ * allows the existing logic for SEV-ES VMSAs to be re-used with
+ * minimal SNP-specific changes.
+ */
+ svm->sev_es.snp_has_guest_vmsa = true;
- gfn = gpa_to_gfn(svm->sev_es.snp_vmsa_gpa);
- svm->sev_es.snp_vmsa_gpa = INVALID_PAGE;
+ if (!VALID_PAGE(gpa))
+ return;
slot = gfn_to_memslot(vcpu->kvm, gfn);
if (!slot)
return;
+ mmu_seq = kvm->mmu_invalidate_seq;
+ smp_rmb();
+
/*
* The new VMSA will be private memory guest memory, so retrieve the
* PFN from the gmem backend.
@@ -4027,29 +4029,64 @@ static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)
if (kvm_gmem_get_pfn(vcpu->kvm, slot, gfn, &pfn, &page, NULL))
return;
+ read_lock(&kvm->mmu_lock);
/*
- * From this point forward, the VMSA will always be a guest-mapped page
- * rather than the initial one allocated by KVM in svm->sev_es.vmsa. In
- * theory, svm->sev_es.vmsa could be free'd and cleaned up here, but
- * that involves cleanups like flushing caches, which would ideally be
- * handled during teardown rather than guest boot. Deferring that also
- * allows the existing logic for SEV-ES VMSAs to be re-used with
- * minimal SNP-specific changes.
+ * Save the guest-provided GPA. If retry is needed, then KVM will try
+ * again with the same GPA. If the VMSA is usable, then KVM needs to
+ * track the GPA so that the VMSA can be reloaded if the backing page
+ * for the GPA is invalidated.
*/
- svm->sev_es.snp_has_guest_vmsa = true;
+ svm->sev_es.snp_guest_vmsa_gpa = gpa;
+ if (mmu_invalidate_retry_gfn(kvm, mmu_seq, gfn))
+ kvm_make_request(KVM_REQ_VMSA_PAGE_RELOAD, vcpu);
+ else
+ svm->vmcb->control.vmsa_pa = pfn_to_hpa(pfn);
+ read_unlock(&kvm->mmu_lock);
+
+ kvm_release_page_clean(page);
+}
+
+/*
+ * Invoked as part of svm_vcpu_reset() processing of an init event.
+ */
+static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+ gpa_t gpa;
+
+ guard(mutex)(&svm->sev_es.snp_vmsa_mutex);
+
+ if (!svm->sev_es.snp_ap_waiting_for_reset)
+ return;
+
+ svm->sev_es.snp_ap_waiting_for_reset = false;
+
+ /* Mark the vCPU as offline and not runnable */
+ vcpu->arch.pv.pv_unhalted = false;
+ kvm_set_mp_state(vcpu, KVM_MP_STATE_HALTED);
- /* Use the new VMSA */
- svm->vmcb->control.vmsa_pa = pfn_to_hpa(pfn);
+ gpa = svm->sev_es.snp_pending_vmsa_gpa;
+ svm->sev_es.snp_pending_vmsa_gpa = INVALID_PAGE;
- /* Mark the vCPU as runnable */
- kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE);
+ __sev_snp_reload_vmsa(vcpu, gpa);
/*
- * gmem pages aren't currently migratable, but if this ever changes
- * then care should be taken to ensure svm->sev_es.vmsa is pinned
- * through some other means.
+ * Mark the vCPU as runnable for CREATE requests, indicated by a valid
+ * VMSA GPA, even if installing the VMSA failed, so that KVM_RUN will
+ * fail instead of blocking indefinitely and hanging the vCPU, e.g. if
+ * the backing guest_memfd page is unavailable.
*/
- kvm_release_page_clean(page);
+ if (VALID_PAGE(gpa))
+ kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE);
+}
+
+void sev_snp_reload_vmsa(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_sev_es_state *sev_es = &to_svm(vcpu)->sev_es;
+
+ guard(mutex)(&sev_es->snp_vmsa_mutex);
+
+ __sev_snp_reload_vmsa(vcpu, sev_es->snp_guest_vmsa_gpa);
}
static int sev_snp_ap_creation(struct vcpu_svm *svm)
@@ -4105,10 +4142,10 @@ static int sev_snp_ap_creation(struct vcpu_svm *svm)
return -EINVAL;
}
- target_svm->sev_es.snp_vmsa_gpa = svm->vmcb->control.exit_info_2;
+ target_svm->sev_es.snp_pending_vmsa_gpa = svm->vmcb->control.exit_info_2;
break;
case SVM_VMGEXIT_AP_DESTROY:
- target_svm->sev_es.snp_vmsa_gpa = INVALID_PAGE;
+ target_svm->sev_es.snp_pending_vmsa_gpa = INVALID_PAGE;
break;
default:
vcpu_unimpl(vcpu, "vmgexit: invalid AP creation request [%#x] from guest\n",
@@ -4791,6 +4828,8 @@ int sev_vcpu_create(struct kvm_vcpu *vcpu)
return -ENOMEM;
svm->sev_es.vmsa = page_address(vmsa_page);
+ svm->sev_es.snp_pending_vmsa_gpa = INVALID_PAGE;
+ svm->sev_es.snp_guest_vmsa_gpa = INVALID_PAGE;
vcpu->arch.guest_tsc_protected = snp_is_secure_tsc_enabled(vcpu->kvm);
@@ -5115,9 +5154,36 @@ int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order)
return 0;
}
+void sev_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+ struct kvm_vcpu *vcpu;
+ unsigned long i;
+
+ lockdep_assert_held_write(&kvm->mmu_lock);
+
+ /*
+ * An unstable result for "is SNP" is a-ok here, thanks to mmu_lock.
+ * The vCPU's VMSA GPA is invalidated before the vCPU is made visible
+ * to other tasks, and can only become valid while holding mmu_lock,
+ * after the VM is fully committed to being an SNP VM.
+ */
+ if (!____sev_snp_guest(kvm))
+ return;
+
+ kvm_for_each_vcpu(i, vcpu, kvm) {
+ gpa_t gpa = to_svm(vcpu)->sev_es.snp_guest_vmsa_gpa;
+
+ if (VALID_PAGE(gpa) &&
+ gpa_to_gfn(gpa) >= range->start &&
+ gpa_to_gfn(gpa) < range->end)
+ kvm_make_request_and_kick(KVM_REQ_VMSA_PAGE_RELOAD, vcpu);
+ }
+}
-void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)
+void sev_gmem_free_folio(struct folio *folio)
{
+ kvm_pfn_t start = page_to_pfn(folio_page(folio, 0));
+ kvm_pfn_t end = start + (1ul << folio_order(folio));
kvm_pfn_t pfn;
if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index ef69a51ab27f98..7d3dd371907045 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5445,6 +5445,7 @@ struct kvm_x86_ops svm_x86_ops __initdata = {
.mem_enc_register_region = sev_mem_enc_register_region,
.mem_enc_unregister_region = sev_mem_enc_unregister_region,
.guest_memory_reclaimed = sev_guest_memory_reclaimed,
+ .reload_vmsa = sev_snp_reload_vmsa,
.vm_copy_enc_context_from = sev_vm_copy_enc_context_from,
.vm_move_enc_context_from = sev_vm_move_enc_context_from,
@@ -5460,9 +5461,12 @@ struct kvm_x86_ops svm_x86_ops __initdata = {
.vcpu_get_apicv_inhibit_reasons = avic_vcpu_get_apicv_inhibit_reasons,
.alloc_apic_backing_page = svm_alloc_apic_backing_page,
+#ifdef CONFIG_KVM_AMD_SEV
.gmem_prepare = sev_gmem_prepare,
- .gmem_invalidate = sev_gmem_invalidate,
+ .gmem_invalidate_range = sev_gmem_invalidate_range,
+ .gmem_free_folio = sev_gmem_free_folio,
.gmem_max_mapping_level = sev_gmem_max_mapping_level,
+#endif
};
/*
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 716be21fba3354..c7ecc5fca689b0 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -271,7 +271,8 @@ struct vcpu_sev_es_state {
u64 ghcb_registered_gpa;
struct mutex snp_vmsa_mutex; /* Used to handle concurrent updates of VMSA. */
- gpa_t snp_vmsa_gpa;
+ gpa_t snp_pending_vmsa_gpa;
+ gpa_t snp_guest_vmsa_gpa;
bool snp_ap_waiting_for_reset;
bool snp_has_guest_vmsa;
};
@@ -995,6 +996,7 @@ static inline struct page *snp_safe_alloc_page(void)
{
return snp_safe_alloc_page_node(numa_node_id(), GFP_KERNEL_ACCOUNT);
}
+void sev_snp_reload_vmsa(struct kvm_vcpu *vcpu);
int sev_vcpu_create(struct kvm_vcpu *vcpu);
void sev_free_vcpu(struct kvm_vcpu *vcpu);
@@ -1008,7 +1010,8 @@ int sev_dev_get_attr(u32 group, u64 attr, u64 *val);
extern unsigned int max_sev_asid;
void sev_handle_rmp_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code);
int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);
-void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);
+void sev_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range);
+void sev_gmem_free_folio(struct folio *folio);
int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, bool is_private);
struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu);
void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa);
@@ -1038,7 +1041,6 @@ static inline int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, in
{
return 0;
}
-static inline void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end) {}
static inline int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, bool is_private)
{
return 0;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0626e835e9eb77..9df6acf9a982e6 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -8167,6 +8167,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
goto out;
}
}
+ if (kvm_check_request(KVM_REQ_VMSA_PAGE_RELOAD, vcpu))
+ kvm_x86_call(reload_vmsa)(vcpu);
}
if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win ||
@@ -10592,9 +10594,13 @@ int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_ord
#endif
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
-void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)
+void kvm_arch_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range)
{
- kvm_x86_call(gmem_invalidate)(start, end);
+ kvm_x86_call(gmem_invalidate_range)(kvm, range);
+}
+void kvm_arch_gmem_free_folio(struct folio *folio)
+{
+ kvm_x86_call(gmem_free_folio)(folio);
}
#endif
#endif
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ab8cfaec82d31e..6b7f8801505d5c 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -2607,7 +2607,8 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src,
#endif
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
-void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);
+void kvm_arch_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range);
+void kvm_arch_gmem_free_folio(struct folio *folio);
#endif
#ifdef CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 86690683b2fe3e..8ec5041934dbcf 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -185,6 +185,10 @@ static void __kvm_gmem_invalidate_start(struct gmem_file *f, pgoff_t start,
}
flush |= kvm_mmu_unmap_gfn_range(kvm, &gfn_range);
+
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
+ kvm_arch_gmem_invalidate_range(kvm, &gfn_range);
+#endif
}
if (flush)
@@ -523,23 +527,12 @@ static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *fol
return MF_DELAYED;
}
-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
-static void kvm_gmem_free_folio(struct folio *folio)
-{
- struct page *page = folio_page(folio, 0);
- kvm_pfn_t pfn = page_to_pfn(page);
- int order = folio_order(folio);
-
- kvm_arch_gmem_invalidate(pfn, pfn + (1ul << order));
-}
-#endif
-
static const struct address_space_operations kvm_gmem_aops = {
.dirty_folio = noop_dirty_folio,
.migrate_folio = kvm_gmem_migrate_folio,
.error_remove_folio = kvm_gmem_error_folio,
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
- .free_folio = kvm_gmem_free_folio,
+ .free_folio = kvm_arch_gmem_free_folio,
#endif
};
|
| 3/2 | 2026/06/25 22:38 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8696 output: 22 thoughts: 370 Thoughts: **Analyzing the Patch Series for Fuzzing Potential** Okay, so I've got this patch series in front of me, and my immediate concern is whether these changes introduce new kernel functionality that warrants fuzzing. It's touching KVM, specifically AMD SEV-SNP support, and digging into the details, it seems to be dealing with `guest_memfd` and VMSA handling. New KVM request, `KVM_REQ_VMSA_PAGE_RELOAD`, is added. There are changes to `gmem_invalidate`, `gmem_invalidate_range`, `gmem_free_folio`. There are also modifications to `sev_snp_init_protected_guest_state` and a new function, `sev_snp_reload_vmsa`. The code is also changing `kvm_arch_gmem_invalidate` to `kvm_arch_gmem_invalidate_range` and `kvm_arch_gmem_free_folio`. My first thought is, can this code even be reached in a typical virtualized environment? I need to consider whether it's runnable in something like GCE or QEMU. SEV-SNP's a bit tricky, since it requires specific AMD hardware (EPYC with SEV-SNP support). But even if the VMs can't be run in a given test setup, often KVM code is still fuzzable if the relevant ioctls are reachable, or if we can successfully mock the setup. SEV-SNP is a bit different because hardware is required to actually run the VMs, but some ioctls *might* be reachable. Wait a second. I know Syzkaller heavily fuzzes KVM. I need to make sure this isn't already handled. Let me check for `CONFIG_KVM_AMD_SEV` in the patch. Yep, it is. Time to verify by looking in the kernel's `arch/x86/kvm/Kconfig` file. And let's use `grepper` to be sure to find all instances. |
| 4/2 | 2026/06/25 22:38 | tool | grepper |
0mArgs:{
"Expression": "config KVM_AMD_SEV"
}Results: {
"Output": "arch/x86/kvm/Kconfig=146=config KVM_AMD\n--\narch/x86/kvm/Kconfig-155-\narch/x86/kvm/Kconfig:156:config KVM_AMD_SEV\narch/x86/kvm/Kconfig-157-\tbool \"AMD Secure Encrypted Virtualization (SEV) support\"\n"
} |
| 5/2 | 2026/06/25 22:38 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9636 output: 27 thoughts: 274 Thoughts: **Analyzing Recent KVM/SEV-SNP Changes** Okay, let's take a look at these function changes and see what they tell us. I see a series of functions that have been added or modified: `sev_snp_init_protected_guest_state`, `__sev_snp_reload_vmsa`, `sev_snp_reload_vmsa`, `sev_gmem_invalidate_range`, `sev_gmem_free_folio`, `kvm_arch_gmem_invalidate_range`, and `kvm_arch_gmem_free_folio`. My initial thought is to figure out their reachability and context. Right, so `sev_snp_init_protected_guest_state` is invoked within the `svm_vcpu_reset` process, specifically during an initialization event. That's a good starting point. Then, `sev_gmem_invalidate_range` seems to be coming from `__kvm_gmem_invalidate_start` in `virt/kvm/guest_memfd.c`. Ah, and `__kvm_gmem_invalidate_start` itself is triggered when a guest memfd gets invalidated, likely through something like `fallocate --punch-hole`. And finally, `sev_gmem_free_folio` is called from `kvm_gmem_free_folio`, also in the `virt/kvm/guest_memfd.c` file. Now, a quick check to see if `CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE` is defined would be worthwhile. This will influence whether the architecture-specific KVM functions are even being used. Need to keep this in mind as I proceed with any further analysis. |
| 6/2 | 2026/06/25 22:38 | tool | grepper |
0mArgs:{
"Expression": "config HAVE_KVM_ARCH_GMEM_INVALIDATE"
}Results: {
"Output": "virt/kvm/Kconfig=110=config HAVE_KVM_ARCH_GMEM_PREPARE\n--\nvirt/kvm/Kconfig-113-\nvirt/kvm/Kconfig:114:config HAVE_KVM_ARCH_GMEM_INVALIDATE\nvirt/kvm/Kconfig-115- bool\n"
} |
| 7/2 | 2026/06/25 22:38 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10407 output: 27 thoughts: 23 Thoughts: Okay, here's my summary, tailored as if I'm the one thinking it: **Digging into the `HAVE_KVM_ARCH_GMEM_INVALIDATE` Configuration** Alright, time to get my hands dirty. I need to figure out exactly where the `HAVE_KVM_ARCH_GMEM_INVALIDATE` configuration option is being pulled into the build. That's the starting point. Understanding its dependencies and context is crucial before I can even begin to think about its implications or any potential changes. I'll start by checking the Kconfig files, tracing back through the dependencies to see what triggers its selection. I need the big picture before I can zero in on the details. |
| 8/2 | 2026/06/25 22:38 | tool | grepper |
0mArgs:{
"Expression": "select HAVE_KVM_ARCH_GMEM_INVALIDATE"
}Results: {
"Output": "arch/x86/kvm/Kconfig=156=config KVM_AMD_SEV\n--\narch/x86/kvm/Kconfig-163-\tselect HAVE_KVM_ARCH_GMEM_PREPARE\narch/x86/kvm/Kconfig:164:\tselect HAVE_KVM_ARCH_GMEM_INVALIDATE\narch/x86/kvm/Kconfig-165-\tselect HAVE_KVM_ARCH_GMEM_POPULATE\n"
} |
| 9/2 | 2026/06/25 22:38 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10742 output: 19 thoughts: 918 Thoughts: **Fuzzing KVM SEV-SNP Guest Memory Invalidation** Okay, so this patch is touching `KVM_AMD_SEV`, specifically related to how KVM handles guest memory with SEV-SNP and `guest_memfd`. The fact that `KVM_AMD_SEV` is selected implies `HAVE_KVM_ARCH_GMEM_INVALIDATE` is also in play here. My initial thought is, absolutely, this is worth fuzzing because it's functional KVM code. Given the scope, the necessary configurations will be `KVM_AMD_SEV`, `KVM_AMD`, and of course just plain `KVM`. Now, the important symbols to focus on are: `__sev_snp_reload_vmsa`, `sev_snp_reload_vmsa`, `sev_gmem_invalidate_range`, `sev_gmem_free_folio`, `kvm_arch_gmem_invalidate_range`, `kvm_arch_gmem_free_folio`, and `sev_snp_init_protected_guest_state`. I need to confirm if `sev_snp_reload_vmsa` is reachable. Digging in, I see it's called from `vcpu_enter_guest` in `arch/x86/kvm/x86.c`, specifically when the `KVM_REQ_VMSA_PAGE_RELOAD` request is present. This request is set by both `__sev_snp_reload_vmsa` and `sev_gmem_invalidate_range`. `sev_gmem_invalidate_range` in turn is called from `kvm_arch_gmem_invalidate_range`, which leads us to `__kvm_gmem_invalidate_start` in `virt/kvm/guest_memfd.c`. Aha! `__kvm_gmem_invalidate_start` is triggered when a hole is punched in the `guest_memfd`. That's *definitely* reachable from userspace, specifically through `fallocate` on a `guest_memfd`. So, fuzzing `fallocate` on a `guest_memfd` while a VM is running could potentially trigger `sev_gmem_invalidate_range` and subsequently the `KVM_REQ_VMSA_PAGE_RELOAD`. Seems like a good vector. However, the catch is `KVM_AMD_SEV` requires SEV hardware. Can Syzkaller realistically fuzz this? Syzkaller can fuzz KVM ioctls, and even if SEV hardware isn't present, some code paths may still be reachable (or fail early), which is useful. KVM code is generally worth fuzzing. But wait, the prompt specifies that I should return `WorthFuzzing=false` if the code paths are impossible to reach in virtualized environments like GCE or QEMU, even with software emulation. So the key question becomes, is SEV-SNP reachable in environments like GCE or QEMU? If the host doesn't support SEV-SNP, checks like `cc_platform_has(CC_ATTR_HOST_SEV_SNP)` will fail, and KVM won't allow SEV-SNP VM creation. This is a potential stumbling block. SEV-SNP is usually tough to fuzz in standard GCE VMs because it depends on specific hardware features. Nested virtualization with emulation could *potentially* allow it, but that's not the norm. Syzkaller *does* fuzz KVM, and sometimes we run Syzkaller on bare metal or nested VMs that support these specific hardware features. But can QEMU emulate SEV-SNP in a way that’s useful for KVM? QEMU can emulate a lot, but KVM SEV-SNP relies on a hardware PSP (Platform Security Processor) on AMD hardware. It's not pure software emulation; KVM delegates to the hardware. So, KVM alone cannot create SEV-SNP VMs without host hardware. Looking at `sev_snp_init_protected_guest_state` or `sev_vm_init` should give more clarity. Given this, the code path being discussed might be unreachable in standard virtualized environments like GCE or QEMU. |
| 10/2 | 2026/06/25 22:38 | tool | grepper |
0mArgs:{
"Expression": "sev_vm_init"
}Results: {
"Output": "arch/x86/kvm/svm/sev.c=2897=static int snp_decommission_context(struct kvm *kvm)\n--\narch/x86/kvm/svm/sev.c-2921-\narch/x86/kvm/svm/sev.c:2922:void sev_vm_init(struct kvm *kvm)\narch/x86/kvm/svm/sev.c-2923-{\n--\narch/x86/kvm/svm/svm.c=5298=static int svm_vm_init(struct kvm *kvm)\narch/x86/kvm/svm/svm.c-5299-{\narch/x86/kvm/svm/svm.c:5300:\tsev_vm_init(kvm);\narch/x86/kvm/svm/svm.c-5301-\n--\narch/x86/kvm/svm/svm.h=1002=void sev_free_vcpu(struct kvm_vcpu *vcpu);\narch/x86/kvm/svm/svm.h:1003:void sev_vm_init(struct kvm *kvm);\narch/x86/kvm/svm/svm.h-1004-void sev_vm_destroy(struct kvm *kvm);\n--\narch/x86/kvm/svm/svm.h=1030=static inline void sev_free_vcpu(struct kvm_vcpu *vcpu) {}\narch/x86/kvm/svm/svm.h:1031:static inline void sev_vm_init(struct kvm *kvm) {}\narch/x86/kvm/svm/svm.h-1032-static inline void sev_vm_destroy(struct kvm *kvm) {}\n--\ntools/testing/selftests/kvm/include/x86/sev.h=67=static inline u64 snp_default_policy(void)\n--\ntools/testing/selftests/kvm/include/x86/sev.h-102-\ntools/testing/selftests/kvm/include/x86/sev.h:103:void sev_vm_init(struct kvm_vm *vm);\ntools/testing/selftests/kvm/include/x86/sev.h-104-void sev_es_vm_init(struct kvm_vm *vm);\n--\ntools/testing/selftests/kvm/lib/x86/sev.c=17=static void encrypt_region(struct kvm_vm *vm, struct userspace_mem_region *region,\n--\ntools/testing/selftests/kvm/lib/x86/sev.c-47-\ntools/testing/selftests/kvm/lib/x86/sev.c:48:void sev_vm_init(struct kvm_vm *vm)\ntools/testing/selftests/kvm/lib/x86/sev.c-49-{\n--\ntools/testing/selftests/kvm/x86/sev_migrate_tests.c=23=static struct kvm_vm *sev_vm_create(bool es)\n--\ntools/testing/selftests/kvm/x86/sev_migrate_tests.c-29-\tif (!es)\ntools/testing/selftests/kvm/x86/sev_migrate_tests.c:30:\t\tsev_vm_init(vm);\ntools/testing/selftests/kvm/x86/sev_migrate_tests.c-31-\telse\n"
} |
| 11/2 | 2026/06/25 22:38 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13513 output: 43 thoughts: 28 Thoughts: Here's my summary, as though I'm thinking through this process: **Diving into KVM-SVM Initialization for SEV** Okay, time to get my hands dirty with this `sev_vm_init` function. I'm going to start by taking a look at `arch/x86/kvm/svm/sev.c`. This is the core of the Secure Encrypted Virtualization (SEV) support within the KVM-SVM module, so `sev_vm_init` should be where the guest VM environment gets properly configured and initialized for SEV. I expect to find the crucial steps for setting up memory encryption, handling the guest's secrets, and configuring the SVM-specific security features. Understanding this function is key to grasping how SEV works at the lowest level within the KVM architecture. Let's see what's happening in there. |
| 12/2 | 2026/06/25 22:38 | tool | read-file |
0mArgs:{
"File": "arch/x86/kvm/svm/sev.c",
"FirstLine": 2922,
"LineCount": 20
}Results: {
"Contents": "2922:\tvoid sev_vm_init(struct kvm *kvm)\n2923:\t{\n2924:\t\tswitch (kvm-\u003earch.vm_type) {\n2925:\t\tcase KVM_X86_DEFAULT_VM:\n2926:\t\tcase KVM_X86_SW_PROTECTED_VM:\n2927:\t\t\tbreak;\n2928:\t\tcase KVM_X86_SNP_VM:\n2929:\t\t\tkvm-\u003earch.has_private_mem = true;\n2930:\t\t\tfallthrough;\n2931:\t\tcase KVM_X86_SEV_ES_VM:\n2932:\t\t\tkvm-\u003earch.has_protected_state = true;\n2933:\t\t\tfallthrough;\n2934:\t\tcase KVM_X86_SEV_VM:\n2935:\t\t\tkvm-\u003earch.pre_fault_allowed = !kvm-\u003earch.has_private_mem;\n2936:\t\t\tto_kvm_sev_info(kvm)-\u003eneed_init = true;\n2937:\t\t\tbreak;\n2938:\t\tdefault:\n2939:\t\t\tWARN_ONCE(1, \"Unsupported VM type %u\", kvm-\u003earch.vm_type);\n2940:\t\t\tbreak;\n2941:\t\t}\n"
} |
| 13/2 | 2026/06/25 22:38 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14123 output: 24 thoughts: 57 Thoughts: Okay, let's see... **Investigating KVM_X86_SNP_VM and Virtual Machine Creation** Hmm, `KVM_X86_SNP_VM`... that's a VM type, isn't it? My intuition is screaming that this is something related to Secure Nested Paging, or AMD's Secure Nested Paging, but I need to confirm. I'm wondering: can a user actually *create* a VM of this specific type without the appropriate underlying hardware support? That seems like a potential security hole or, at the very least, a configuration error that should be prevented. Alright, time to dive into the code. The logical place to start digging is probably around the initialization of a VM. I need to track down the function or code block where the `vm_type` is validated. So I should probably look for `kvm_arch_init_vm` or wherever `vm_type` gets checked during the VM creation process. That's where I expect to find the guardrails preventing an attempt to create a secure VM on incompatible hardware. I'll focus on these areas to figure out if there's sufficient protection, or if there's a potential vulnerability there. |
| 14/2 | 2026/06/25 22:39 | tool | grepper |
0mArgs:{
"Expression": "KVM_X86_SNP_VM"
}Results: {
"Output": "Documentation/virt/kvm/api.rst=9405=means the VM type with value @n is supported. Possible values of @n are::\n--\nDocumentation/virt/kvm/api.rst-9410- #define KVM_X86_SEV_ES_VM\t3\nDocumentation/virt/kvm/api.rst:9411: #define KVM_X86_SNP_VM\t4\nDocumentation/virt/kvm/api.rst-9412- #define KVM_X86_TDX_VM\t5\n--\narch/x86/include/uapi/asm/kvm.h=927=struct kvm_hyperv_eventfd {\n--\narch/x86/include/uapi/asm/kvm.h-973-#define KVM_X86_SEV_ES_VM\t3\narch/x86/include/uapi/asm/kvm.h:974:#define KVM_X86_SNP_VM\t\t4\narch/x86/include/uapi/asm/kvm.h-975-#define KVM_X86_TDX_VM\t\t5\n--\narch/x86/kvm/svm/sev.c=262=static int sev_asid_new(struct kvm_sev_info *sev, unsigned long vm_type)\n--\narch/x86/kvm/svm/sev.c-270-\narch/x86/kvm/svm/sev.c:271:\tif (vm_type == KVM_X86_SNP_VM) {\narch/x86/kvm/svm/sev.c-272-\t\tmin_asid = min_snp_asid;\n--\narch/x86/kvm/svm/sev.c=488=static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,\n--\narch/x86/kvm/svm/sev.c-494-\tbool es_active = vm_type != KVM_X86_SEV_VM;\narch/x86/kvm/svm/sev.c:495:\tbool snp_active = vm_type == KVM_X86_SNP_VM;\narch/x86/kvm/svm/sev.c-496-\tu64 valid_vmsa_features = es_active ? sev_supported_vmsa_features : 0;\n--\narch/x86/kvm/svm/sev.c=601=static int sev_guest_init2(struct kvm *kvm, struct kvm_sev_cmd *argp)\n--\narch/x86/kvm/svm/sev.c-609-\t kvm-\u003earch.vm_type != KVM_X86_SEV_ES_VM \u0026\u0026\narch/x86/kvm/svm/sev.c:610:\t kvm-\u003earch.vm_type != KVM_X86_SNP_VM)\narch/x86/kvm/svm/sev.c-611-\t\treturn -EINVAL;\n--\narch/x86/kvm/svm/sev.c=2922=void sev_vm_init(struct kvm *kvm)\n--\narch/x86/kvm/svm/sev.c-2927-\t\tbreak;\narch/x86/kvm/svm/sev.c:2928:\tcase KVM_X86_SNP_VM:\narch/x86/kvm/svm/sev.c-2929-\t\tkvm-\u003earch.has_private_mem = true;\n--\narch/x86/kvm/svm/sev.c=3045=void __init sev_hardware_setup(void)\n--\narch/x86/kvm/svm/sev.c-3190-\tif (sev_snp_supported)\narch/x86/kvm/svm/sev.c:3191:\t\tvm_types |= BIT(KVM_X86_SNP_VM);\narch/x86/kvm/svm/sev.c-3192-\tvm_types \u0026= sev_firmware_supported_vm_types();\n--\narch/x86/kvm/svm/sev.c-3205-\t\tpr_info(\"SEV-SNP %s (ASIDs %u - %u)\\n\",\narch/x86/kvm/svm/sev.c:3206:\t\t\tsev_str_feature_state(sev_snp_supported, vm_types \u0026 BIT(KVM_X86_SNP_VM)),\narch/x86/kvm/svm/sev.c-3207-\t\t\tmin_snp_asid, max_snp_asid);\n--\ndrivers/crypto/ccp/sev-dev.c=3003=int sev_firmware_supported_vm_types(void)\n--\ndrivers/crypto/ccp/sev-dev.c-3017-\ndrivers/crypto/ccp/sev-dev.c:3018:\tsupported_vm_types |= BIT(KVM_X86_SNP_VM);\ndrivers/crypto/ccp/sev-dev.c-3019-\n--\ntools/arch/x86/include/uapi/asm/kvm.h=925=struct kvm_hyperv_eventfd {\n--\ntools/arch/x86/include/uapi/asm/kvm.h-971-#define KVM_X86_SEV_ES_VM\t3\ntools/arch/x86/include/uapi/asm/kvm.h:972:#define KVM_X86_SNP_VM\t\t4\ntools/arch/x86/include/uapi/asm/kvm.h-973-#define KVM_X86_TDX_VM\t\t5\n--\ntools/testing/selftests/kvm/include/x86/sev.h=34=static inline bool is_sev_snp_vm(struct kvm_vm *vm)\ntools/testing/selftests/kvm/include/x86/sev.h-35-{\ntools/testing/selftests/kvm/include/x86/sev.h:36:\treturn vm-\u003etype == KVM_X86_SNP_VM;\ntools/testing/selftests/kvm/include/x86/sev.h-37-}\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=470=static bool is_guest_memfd_required(struct vm_shape shape)\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-472-#ifdef __x86_64__\ntools/testing/selftests/kvm/lib/kvm_util.c:473:\treturn shape.type == KVM_X86_SNP_VM;\ntools/testing/selftests/kvm/lib/kvm_util.c-474-#else\n--\ntools/testing/selftests/kvm/lib/x86/sev.c=74=void snp_vm_init(struct kvm_vm *vm)\n--\ntools/testing/selftests/kvm/lib/x86/sev.c-77-\ntools/testing/selftests/kvm/lib/x86/sev.c:78:\tTEST_ASSERT_EQ(vm-\u003etype, KVM_X86_SNP_VM);\ntools/testing/selftests/kvm/lib/x86/sev.c-79-\tvm_sev_ioctl(vm, KVM_SEV_INIT2, \u0026init);\n--\ntools/testing/selftests/kvm/x86/sev_init2_tests.c=76=void test_vm_types(void)\n--\ntools/testing/selftests/kvm/x86/sev_init2_tests.c-87-\tif (have_snp)\ntools/testing/selftests/kvm/x86/sev_init2_tests.c:88:\t\ttest_init2(KVM_X86_SNP_VM, \u0026(struct kvm_sev_init){});\ntools/testing/selftests/kvm/x86/sev_init2_tests.c-89-\n--\ntools/testing/selftests/kvm/x86/sev_init2_tests.c=122=int main(int argc, char *argv[])\n--\ntools/testing/selftests/kvm/x86/sev_init2_tests.c-143-\ntools/testing/selftests/kvm/x86/sev_init2_tests.c:144:\thave_snp = kvm_check_cap(KVM_CAP_VM_TYPES) \u0026 BIT(KVM_X86_SNP_VM);\ntools/testing/selftests/kvm/x86/sev_init2_tests.c-145-\tTEST_ASSERT(!have_snp || kvm_cpu_has(X86_FEATURE_SEV_SNP),\n--\ntools/testing/selftests/kvm/x86/sev_init2_tests.c-153-\tif (have_snp)\ntools/testing/selftests/kvm/x86/sev_init2_tests.c:154:\t\ttest_flags(KVM_X86_SNP_VM);\ntools/testing/selftests/kvm/x86/sev_init2_tests.c-155-\n--\ntools/testing/selftests/kvm/x86/sev_init2_tests.c-159-\tif (have_snp)\ntools/testing/selftests/kvm/x86/sev_init2_tests.c:160:\t\ttest_features(KVM_X86_SNP_VM, supported_vmsa_features);\ntools/testing/selftests/kvm/x86/sev_init2_tests.c-161-\n--\ntools/testing/selftests/kvm/x86/sev_smoke_test.c=221=static void test_sev_smoke(void *guest, u32 type, u64 policy)\n--\ntools/testing/selftests/kvm/x86/sev_smoke_test.c-224-\ntools/testing/selftests/kvm/x86/sev_smoke_test.c:225:\tif (type == KVM_X86_SNP_VM)\ntools/testing/selftests/kvm/x86/sev_smoke_test.c-226-\t\ttest_sev(guest, type, policy | SNP_POLICY_DBG);\n--\ntools/testing/selftests/kvm/x86/sev_smoke_test.c-238-\t\ttest_sync_vmsa(type, policy);\ntools/testing/selftests/kvm/x86/sev_smoke_test.c:239:\t\tif (type == KVM_X86_SNP_VM)\ntools/testing/selftests/kvm/x86/sev_smoke_test.c-240-\t\t\ttest_sync_vmsa(type, policy | SNP_POLICY_DBG);\n--\ntools/testing/selftests/kvm/x86/sev_smoke_test.c=246=int main(int argc, char *argv[])\n--\ntools/testing/selftests/kvm/x86/sev_smoke_test.c-254-\ntools/testing/selftests/kvm/x86/sev_smoke_test.c:255:\tif (kvm_check_cap(KVM_CAP_VM_TYPES) \u0026 BIT(KVM_X86_SNP_VM))\ntools/testing/selftests/kvm/x86/sev_smoke_test.c:256:\t\ttest_sev_smoke(guest_snp_code, KVM_X86_SNP_VM, snp_default_policy());\ntools/testing/selftests/kvm/x86/sev_smoke_test.c-257-\n"
} |
| 15/2 | 2026/06/25 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 17484 output: 21 thoughts: 443 Thoughts: **KVM_X86_SNP_VM Worthiness Assessment** Okay, so `KVM_X86_SNP_VM` is tied directly to `sev_snp_supported`, which is determined by the hardware's SEV-SNP capabilities during the `sev_hardware_setup`. If the hardware doesn't have it, `KVM_X86_SNP_VM` is a no-go, and `kvm_create_vm` will error out with `-EINVAL`. My initial instinct was, "if it's impossible to trigger this in a typical virtualized environment like GCE or QEMU without that specific hardware, then it's `WorthFuzzing=false`". That's the core of the instructions in the prompt. But wait a minute, the prompt says "impossible to reach in *virtualized environments* like GCE or QEMU". Does syzkaller even run on hardware that could support SEV-SNP? Ah, syzkaller can run bare metal or nested VMs, that's right. So, it's not simply "impossible", I need to think this through. Now, is SEV-SNP impossible to reach in GCE? Aha, that's the key question. GCE actually supports AMD SEV and SEV-SNP instances, specifically Confidential VMs. That changes everything! It IS possible to trigger this code path on GCE if the instance type is configured correctly. And, while QEMU might require host hardware support, GCE *provides* the necessary hardware. Therefore, the code path *is* reachable. Conclusion: this patch is fuzzable, so I should return `WorthFuzzing=true`. Just to be safe, I should double-check the relevant kernel configs to be sure I'm not missing anything. Let's look at `CONFIG_KVM_AMD_SEV`, `CONFIG_KVM_AMD`, and `CONFIG_KVM`. Also, I'll take a quick look to see if `guest_memfd` requires any special configs. Specifically, does it need `CONFIG_KVM_PRIVATE_MEM` or something similar? Gotta be thorough. |
| 16/2 | 2026/06/25 22:39 | tool | grepper |
0mError:no matches Args: {
"Expression": "config KVM_PRIVATE_MEM"
}Results: {
"error": "no matches"
} |
| 17/2 | 2026/06/25 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 18426 output: 18 thoughts: 20 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Checking the KVM Configuration for Guest Memory Sharing** Right, let's dive into the kernel configuration. I need to refresh my memory on the specifics of memory sharing within KVM guests, particularly related to `memfd`. My immediate thought is to check the `virt/kvm/Kconfig` file. That's the logical place to start. I'm looking for the configuration option associated with `guest_memfd`. It’ll be the key to understanding how memory file descriptors are being used or can be enabled for these guests. I need to see the dependencies, help text, and default settings. Hopefully, this Kconfig entry gives me a clear picture of its integration and potential implications for my work. This should be a quick and efficient way to pinpoint how the system handles it, and if it's relevant to this current focus. |
| 18/2 | 2026/06/25 22:39 | tool | grepper |
0mArgs:{
"Expression": "guest_memfd"
}Results: {
"Output": "\nFull output is too long, showing 500 out of 577 lines.\nUse more precise expression if possible.\n\nDocumentation/virt/kvm/api.rst=6334=KVM_SET_USER_MEMORY_REGION2 is an extension to KVM_SET_USER_MEMORY_REGION that\nDocumentation/virt/kvm/api.rst:6335:allows mapping guest_memfd memory into a guest. All fields shared with\nDocumentation/virt/kvm/api.rst-6336-KVM_SET_USER_MEMORY_REGION identically. Userspace can set KVM_MEM_GUEST_MEMFD\nDocumentation/virt/kvm/api.rst:6337:in flags to have KVM bind the memory region to a given guest_memfd range of\nDocumentation/virt/kvm/api.rst:6338:[guest_memfd_offset, guest_memfd_offset + memory_size]. The target guest_memfd\nDocumentation/virt/kvm/api.rst-6339-must point at a file created via KVM_CREATE_GUEST_MEMFD on the current VM, and\n--\nDocumentation/virt/kvm/api.rst=6341=bounds checks apply (use common sense).\n--\nDocumentation/virt/kvm/api.rst-6350-\t__u64 userspace_addr; /* start of the userspace allocated memory */\nDocumentation/virt/kvm/api.rst:6351:\t__u64 guest_memfd_offset;\nDocumentation/virt/kvm/api.rst:6352:\t__u32 guest_memfd;\nDocumentation/virt/kvm/api.rst-6353-\t__u32 pad1;\n--\nDocumentation/virt/kvm/api.rst-6356-\nDocumentation/virt/kvm/api.rst:6357:A KVM_MEM_GUEST_MEMFD region _must_ have a valid guest_memfd (private memory) and\nDocumentation/virt/kvm/api.rst-6358-userspace_addr (shared memory). However, \"valid\" for userspace_addr simply\n--\nDocumentation/virt/kvm/api.rst=6364=When mapping a gfn into the guest, KVM selects shared vs. private, i.e consumes\nDocumentation/virt/kvm/api.rst:6365:userspace_addr vs. guest_memfd, based on the gfn's KVM_MEMORY_ATTRIBUTE_PRIVATE\nDocumentation/virt/kvm/api.rst-6366-state. At VM creation time, all memory is shared, i.e. the PRIVATE attribute\n--\nDocumentation/virt/kvm/api.rst=6410=The \"flags\" field is reserved for future extensions and must be '0'.\n--\nDocumentation/virt/kvm/api.rst-6417-:Type: vm ioctl\nDocumentation/virt/kvm/api.rst:6418::Parameters: struct kvm_create_guest_memfd(in)\nDocumentation/virt/kvm/api.rst-6419-:Returns: A file descriptor on success, \u003c0 on error\n--\nDocumentation/virt/kvm/api.rst=6421=KVM_CREATE_GUEST_MEMFD creates an anonymous file and returns a file descriptor\nDocumentation/virt/kvm/api.rst:6422:that refers to it. guest_memfd files are roughly analogous to files created\nDocumentation/virt/kvm/api.rst:6423:via memfd_create(), e.g. guest_memfd files live in RAM, have volatile storage,\nDocumentation/virt/kvm/api.rst-6424-and are automatically released when the last reference is dropped. Unlike\nDocumentation/virt/kvm/api.rst:6425:\"regular\" memfd_create() files, guest_memfd files are bound to their owning\nDocumentation/virt/kvm/api.rst-6426-virtual machine (see below), cannot be mapped, read, or written by userspace,\nDocumentation/virt/kvm/api.rst:6427:and cannot be resized (guest_memfd files do however support PUNCH_HOLE).\nDocumentation/virt/kvm/api.rst-6428-\n--\nDocumentation/virt/kvm/api.rst-6430-\nDocumentation/virt/kvm/api.rst:6431: struct kvm_create_guest_memfd {\nDocumentation/virt/kvm/api.rst-6432-\t__u64 size;\n--\nDocumentation/virt/kvm/api.rst-6436-\nDocumentation/virt/kvm/api.rst:6437:Conceptually, the inode backing a guest_memfd file represents physical memory,\nDocumentation/virt/kvm/api.rst-6438-i.e. is coupled to the virtual machine as a thing, not to a \"struct kvm\". The\n--\nDocumentation/virt/kvm/api.rst=6443=migration of a virtual machine.\nDocumentation/virt/kvm/api.rst-6444-\nDocumentation/virt/kvm/api.rst:6445:KVM currently only supports mapping guest_memfd via KVM_SET_USER_MEMORY_REGION2,\nDocumentation/virt/kvm/api.rst:6446:and more specifically via the guest_memfd and guest_memfd_offset fields in\nDocumentation/virt/kvm/api.rst:6447:\"struct kvm_userspace_memory_region2\", where guest_memfd_offset is the offset\nDocumentation/virt/kvm/api.rst:6448:into the guest_memfd instance. For a given guest_memfd file, there can be at\nDocumentation/virt/kvm/api.rst-6449-most one mapping per page, i.e. binding multiple memory regions to a single\nDocumentation/virt/kvm/api.rst:6450:guest_memfd range is not allowed (any number of memory regions can be bound to\nDocumentation/virt/kvm/api.rst:6451:a single guest_memfd file, but the bound ranges must not overlap).\nDocumentation/virt/kvm/api.rst-6452-\n--\nDocumentation/virt/kvm/api.rst=6454=specified via KVM_CREATE_GUEST_MEMFD. Currently defined flags:\n--\nDocumentation/virt/kvm/api.rst-6456- ============================ ================================================\nDocumentation/virt/kvm/api.rst:6457: GUEST_MEMFD_FLAG_MMAP Enable using mmap() on the guest_memfd file\nDocumentation/virt/kvm/api.rst-6458- descriptor.\n--\nDocumentation/virt/kvm/api.rst=6466=When the KVM MMU performs a PFN lookup to service a guest fault and the backing\nDocumentation/virt/kvm/api.rst:6467:guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be\nDocumentation/virt/kvm/api.rst:6468:consumed from guest_memfd, regardless of whether it is a shared or a private\nDocumentation/virt/kvm/api.rst-6469-fault.\n--\narch/arm64/kvm/mmu.c=2611=int kvm_arch_prepare_memory_region(struct kvm *kvm,\n--\narch/arm64/kvm/mmu.c-2643-\t/*\narch/arm64/kvm/mmu.c:2644:\t * Only support guest_memfd backed memslots with mappable memory, since\narch/arm64/kvm/mmu.c-2645-\t * there aren't any CoCo VMs that support only private memory on arm64.\n--\narch/arm64/kvm/nested.c=1474=int kvm_handle_vncr_abort(struct kvm_vcpu *vcpu)\n--\narch/arm64/kvm/nested.c-1503-\t\t\t/*\narch/arm64/kvm/nested.c:1504:\t\t\t * For guest_memfd, this indicates that it failed to\narch/arm64/kvm/nested.c-1505-\t\t\t * create a folio to back the memory. Inform userspace.\n--\narch/x86/kvm/mmu/mmu.c=3346=static u8 kvm_gmem_max_mapping_level(struct kvm *kvm, struct kvm_page_fault *fault,\n--\narch/x86/kvm/mmu/mmu.c-3357-\t} else {\narch/x86/kvm/mmu/mmu.c:3358:\t\t/* TODO: Call into guest_memfd once hugepages are supported. */\narch/x86/kvm/mmu/mmu.c:3359:\t\tWARN_ONCE(1, \"Get pfn+order from guest_memfd\");\narch/x86/kvm/mmu/mmu.c-3360-\t\tpfn = KVM_PFN_ERR_FAULT;\n--\narch/x86/kvm/mmu/mmu.c=5147=int kvm_tdp_mmu_map_private_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, kvm_pfn_t pfn)\n--\narch/x86/kvm/mmu/mmu.c-5172-\t * Mapping a pre-determined private pfn is intended only for use when\narch/x86/kvm/mmu/mmu.c:5173:\t * populating a guest_memfd instance. Assert that the slot is backed\narch/x86/kvm/mmu/mmu.c:5174:\t * by guest_memfd and that the gmem instance's invalidate_lock is held.\narch/x86/kvm/mmu/mmu.c-5175-\t */\n--\narch/x86/kvm/svm/sev.c=2398=static int snp_launch_update(struct kvm *kvm, struct kvm_sev_cmd *argp)\n--\narch/x86/kvm/svm/sev.c-2437-\t * beforehand.\narch/x86/kvm/svm/sev.c:2438:\t * 3) The PFN of the guest_memfd has not already been set to private\narch/x86/kvm/svm/sev.c-2439-\t * in the RMP table.\n--\narch/x86/kvm/svm/sev.c=4052=static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/svm/sev.c-4076-\t * fail instead of blocking indefinitely and hanging the vCPU, e.g. if\narch/x86/kvm/svm/sev.c:4077:\t * the backing guest_memfd page is unavailable.\narch/x86/kvm/svm/sev.c-4078-\t */\n--\narch/x86/kvm/svm/sev.c=5183=void sev_gmem_free_folio(struct folio *folio)\n--\narch/x86/kvm/svm/sev.c-5235-\t\t * userspace may also free gmem pages during run-time via\narch/x86/kvm/svm/sev.c:5236:\t\t * hole-punching operations on the guest_memfd, so flush the\narch/x86/kvm/svm/sev.c-5237-\t\t * cache entries for these pages before free'ing them back to\n--\narch/x86/kvm/vmx/tdx.c=2952=static int tdx_td_vcpu_init(struct kvm_vcpu *vcpu, u64 vcpu_rcx)\n--\narch/x86/kvm/vmx/tdx.c-3015-\t * the TDX-Module, and to ensure the no-fail MMU paths succeed, e.g. if\narch/x86/kvm/vmx/tdx.c:3016:\t * a concurrent PUNCH_HOLE on guest_memfd triggers removal of SPTEs.\narch/x86/kvm/vmx/tdx.c-3017-\t */\n--\narch/x86/kvm/vmx/tdx.c=3189=static int tdx_gmem_post_populate(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\n--\narch/x86/kvm/vmx/tdx.c-3213-\t * between mapping the pfn and now, but slots_lock prevents memslot\narch/x86/kvm/vmx/tdx.c:3214:\t * updates, filemap_invalidate_lock() prevents guest_memfd updates,\narch/x86/kvm/vmx/tdx.c-3215-\t * mmu_notifier events can't reach S-EPT entries, and KVM's internal\n--\narch/x86/kvm/x86.c=10573=bool kvm_arch_no_poll(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/x86.c-10579-/*\narch/x86/kvm/x86.c:10580: * KVM doesn't yet support initializing guest_memfd memory as shared for VMs\narch/x86/kvm/x86.c-10581- * with private memory (the private vs. shared tracking needs to be moved into\narch/x86/kvm/x86.c:10582: * guest_memfd).\narch/x86/kvm/x86.c-10583- */\n--\ninclude/uapi/linux/kvm.h=39=struct kvm_userspace_memory_region2 {\n--\ninclude/uapi/linux/kvm.h-44-\t__u64 userspace_addr;\ninclude/uapi/linux/kvm.h:45:\t__u64 guest_memfd_offset;\ninclude/uapi/linux/kvm.h:46:\t__u32 guest_memfd;\ninclude/uapi/linux/kvm.h-47-\t__u32 pad1;\n--\ninclude/uapi/linux/kvm.h=1645=struct kvm_memory_attributes {\n--\ninclude/uapi/linux/kvm.h-1653-\ninclude/uapi/linux/kvm.h:1654:#define KVM_CREATE_GUEST_MEMFD\t_IOWR(KVMIO, 0xd4, struct kvm_create_guest_memfd)\ninclude/uapi/linux/kvm.h-1655-#define GUEST_MEMFD_FLAG_MMAP\t\t(1ULL \u003c\u003c 0)\n--\ninclude/uapi/linux/kvm.h-1657-\ninclude/uapi/linux/kvm.h:1658:struct kvm_create_guest_memfd {\ninclude/uapi/linux/kvm.h-1659-\t__u64 size;\n--\ntools/include/uapi/linux/kvm.h=38=struct kvm_userspace_memory_region2 {\n--\ntools/include/uapi/linux/kvm.h-43-\t__u64 userspace_addr;\ntools/include/uapi/linux/kvm.h:44:\t__u64 guest_memfd_offset;\ntools/include/uapi/linux/kvm.h:45:\t__u32 guest_memfd;\ntools/include/uapi/linux/kvm.h-46-\t__u32 pad1;\n--\ntools/include/uapi/linux/kvm.h=1635=struct kvm_memory_attributes {\n--\ntools/include/uapi/linux/kvm.h-1643-\ntools/include/uapi/linux/kvm.h:1644:#define KVM_CREATE_GUEST_MEMFD\t_IOWR(KVMIO, 0xd4, struct kvm_create_guest_memfd)\ntools/include/uapi/linux/kvm.h-1645-#define GUEST_MEMFD_FLAG_MMAP\t\t(1ULL \u003c\u003c 0)\n--\ntools/include/uapi/linux/kvm.h-1647-\ntools/include/uapi/linux/kvm.h:1648:struct kvm_create_guest_memfd {\ntools/include/uapi/linux/kvm.h-1649-\t__u64 size;\n--\ntools/testing/selftests/kvm/Makefile.kvm=157=TEST_GEN_PROGS_x86 += dirty_log_perf_test\ntools/testing/selftests/kvm/Makefile.kvm:158:TEST_GEN_PROGS_x86 += guest_memfd_test\ntools/testing/selftests/kvm/Makefile.kvm-159-TEST_GEN_PROGS_x86 += hardware_disable_test\n--\ntools/testing/selftests/kvm/Makefile.kvm=196=TEST_GEN_PROGS_arm64 += get-reg-list\ntools/testing/selftests/kvm/Makefile.kvm:197:TEST_GEN_PROGS_arm64 += guest_memfd_test\ntools/testing/selftests/kvm/Makefile.kvm-198-TEST_GEN_PROGS_arm64 += mmu_stress_test\n--\ntools/testing/selftests/kvm/guest_memfd_test.c=42=static void test_mmap_cow(int fd, size_t size)\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-46-\tmem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);\ntools/testing/selftests/kvm/guest_memfd_test.c:47:\tTEST_ASSERT(mem == MAP_FAILED, \"Copy-on-write not allowed by guest_memfd.\");\ntools/testing/selftests/kvm/guest_memfd_test.c-48-}\n--\ntools/testing/selftests/kvm/guest_memfd_test.c=174=static void test_collapse(int fd, u64 flags)\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-182-\t/*\ntools/testing/selftests/kvm/guest_memfd_test.c:183:\t * To even reach the point where the guest_memfd folios will\ntools/testing/selftests/kvm/guest_memfd_test.c-184-\t * get collapsed, both the userspace address and the offset\ntools/testing/selftests/kvm/guest_memfd_test.c:185:\t * within the guest_memfd have to be aligned to pmd_size.\ntools/testing/selftests/kvm/guest_memfd_test.c-186-\t *\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-208-\t/*\ntools/testing/selftests/kvm/guest_memfd_test.c:209:\t * Advising the use of huge pages in guest_memfd should be\ntools/testing/selftests/kvm/guest_memfd_test.c-210-\t * fine...\n--\ntools/testing/selftests/kvm/guest_memfd_test.c=348=static void test_invalid_binding(struct kvm_vm *vm, int fd, size_t size)\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-357-\ntools/testing/selftests/kvm/guest_memfd_test.c:358:static void test_create_guest_memfd_invalid_sizes(struct kvm_vm *vm,\ntools/testing/selftests/kvm/guest_memfd_test.c:359:\t\t\t\t\t\t u64 guest_memfd_flags)\ntools/testing/selftests/kvm/guest_memfd_test.c-360-{\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-364-\tfor (size = 1; size \u003c page_size; size++) {\ntools/testing/selftests/kvm/guest_memfd_test.c:365:\t\tfd = __vm_create_guest_memfd(vm, size, guest_memfd_flags);\ntools/testing/selftests/kvm/guest_memfd_test.c-366-\t\tTEST_ASSERT(fd \u003c 0 \u0026\u0026 errno == EINVAL,\ntools/testing/selftests/kvm/guest_memfd_test.c:367:\t\t\t \"guest_memfd() with non-page-aligned page size '0x%lx' should fail with EINVAL\",\ntools/testing/selftests/kvm/guest_memfd_test.c-368-\t\t\t size);\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-371-\ntools/testing/selftests/kvm/guest_memfd_test.c:372:static void test_create_guest_memfd_multiple(struct kvm_vm *vm)\ntools/testing/selftests/kvm/guest_memfd_test.c-373-{\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-376-\ntools/testing/selftests/kvm/guest_memfd_test.c:377:\tfd1 = __vm_create_guest_memfd(vm, page_size, 0);\ntools/testing/selftests/kvm/guest_memfd_test.c-378-\tTEST_ASSERT(fd1 != -1, \"memfd creation should succeed\");\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-383-\ntools/testing/selftests/kvm/guest_memfd_test.c:384:\tfd2 = __vm_create_guest_memfd(vm, page_size * 2, 0);\ntools/testing/selftests/kvm/guest_memfd_test.c-385-\tTEST_ASSERT(fd2 != -1, \"memfd creation should succeed\");\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-399-\ntools/testing/selftests/kvm/guest_memfd_test.c:400:static void test_guest_memfd_flags(struct kvm_vm *vm)\ntools/testing/selftests/kvm/guest_memfd_test.c-401-{\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-406-\tfor (flag = BIT(0); flag; flag \u003c\u003c= 1) {\ntools/testing/selftests/kvm/guest_memfd_test.c:407:\t\tfd = __vm_create_guest_memfd(vm, page_size, flag);\ntools/testing/selftests/kvm/guest_memfd_test.c-408-\t\tif (flag \u0026 valid_flags) {\ntools/testing/selftests/kvm/guest_memfd_test.c-409-\t\t\tTEST_ASSERT(fd \u003e= 0,\ntools/testing/selftests/kvm/guest_memfd_test.c:410:\t\t\t\t \"guest_memfd() with flag '0x%lx' should succeed\",\ntools/testing/selftests/kvm/guest_memfd_test.c-411-\t\t\t\t flag);\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-414-\t\t\tTEST_ASSERT(fd \u003c 0 \u0026\u0026 errno == EINVAL,\ntools/testing/selftests/kvm/guest_memfd_test.c:415:\t\t\t\t \"guest_memfd() with flag '0x%lx' should fail with EINVAL\",\ntools/testing/selftests/kvm/guest_memfd_test.c-416-\t\t\t\t flag);\n--\ntools/testing/selftests/kvm/guest_memfd_test.c=422=do {\t\t\t\t\t\t\t\t\t\\\ntools/testing/selftests/kvm/guest_memfd_test.c:423:\tint fd = vm_create_guest_memfd(__vm, __gmem_size, __flags);\t\\\ntools/testing/selftests/kvm/guest_memfd_test.c-424-\t\t\t\t\t\t\t\t\t\\\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-440-\ntools/testing/selftests/kvm/guest_memfd_test.c:441:static void __test_guest_memfd(struct kvm_vm *vm, u64 flags)\ntools/testing/selftests/kvm/guest_memfd_test.c-442-{\ntools/testing/selftests/kvm/guest_memfd_test.c:443:\ttest_create_guest_memfd_multiple(vm);\ntools/testing/selftests/kvm/guest_memfd_test.c:444:\ttest_create_guest_memfd_invalid_sizes(vm, flags);\ntools/testing/selftests/kvm/guest_memfd_test.c-445-\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-471-\ntools/testing/selftests/kvm/guest_memfd_test.c:472:static void test_guest_memfd(unsigned long vm_type)\ntools/testing/selftests/kvm/guest_memfd_test.c-473-{\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-476-\ntools/testing/selftests/kvm/guest_memfd_test.c:477:\ttest_guest_memfd_flags(vm);\ntools/testing/selftests/kvm/guest_memfd_test.c-478-\ntools/testing/selftests/kvm/guest_memfd_test.c:479:\t__test_guest_memfd(vm, 0);\ntools/testing/selftests/kvm/guest_memfd_test.c-480-\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-482-\tif (flags \u0026 GUEST_MEMFD_FLAG_MMAP)\ntools/testing/selftests/kvm/guest_memfd_test.c:483:\t\t__test_guest_memfd(vm, GUEST_MEMFD_FLAG_MMAP);\ntools/testing/selftests/kvm/guest_memfd_test.c-484-\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-486-\tif (flags \u0026 GUEST_MEMFD_FLAG_INIT_SHARED)\ntools/testing/selftests/kvm/guest_memfd_test.c:487:\t\t__test_guest_memfd(vm, GUEST_MEMFD_FLAG_MMAP |\ntools/testing/selftests/kvm/guest_memfd_test.c-488-\t\t\t\t GUEST_MEMFD_FLAG_INIT_SHARED);\n--\ntools/testing/selftests/kvm/guest_memfd_test.c=493=static void guest_code(u8 *mem, u64 size)\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-504-\ntools/testing/selftests/kvm/guest_memfd_test.c:505:static void test_guest_memfd_guest(void)\ntools/testing/selftests/kvm/guest_memfd_test.c-506-{\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-534-\t * Use the max of the host or guest page size for all operations, as\ntools/testing/selftests/kvm/guest_memfd_test.c:535:\t * KVM requires guest_memfd files and memslots to be sized to multiples\ntools/testing/selftests/kvm/guest_memfd_test.c-536-\t * of the host page size.\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-538-\tsize = max_t(size_t, vm-\u003epage_size, page_size);\ntools/testing/selftests/kvm/guest_memfd_test.c:539:\tfd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP |\ntools/testing/selftests/kvm/guest_memfd_test.c-540-\t\t\t\t\t GUEST_MEMFD_FLAG_INIT_SHARED);\n--\ntools/testing/selftests/kvm/guest_memfd_test.c=561=int main(int argc, char *argv[])\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-570-\t * Not all architectures support KVM_CAP_VM_TYPES. However, those that\ntools/testing/selftests/kvm/guest_memfd_test.c:571:\t * support guest_memfd have that support for the default VM type.\ntools/testing/selftests/kvm/guest_memfd_test.c-572-\t */\n--\ntools/testing/selftests/kvm/guest_memfd_test.c-577-\tfor_each_set_bit(vm_type, \u0026vm_types, BITS_PER_TYPE(vm_types))\ntools/testing/selftests/kvm/guest_memfd_test.c:578:\t\ttest_guest_memfd(vm_type);\ntools/testing/selftests/kvm/guest_memfd_test.c-579-\ntools/testing/selftests/kvm/guest_memfd_test.c:580:\ttest_guest_memfd_guest();\ntools/testing/selftests/kvm/guest_memfd_test.c-581-}\n--\ntools/testing/selftests/kvm/include/kvm_util.h=665=void vm_create_irqchip(struct kvm_vm *vm);\ntools/testing/selftests/kvm/include/kvm_util.h-666-\ntools/testing/selftests/kvm/include/kvm_util.h:667:static inline int __vm_create_guest_memfd(struct kvm_vm *vm, u64 size,\ntools/testing/selftests/kvm/include/kvm_util.h-668-\t\t\t\t\t u64 flags)\ntools/testing/selftests/kvm/include/kvm_util.h-669-{\ntools/testing/selftests/kvm/include/kvm_util.h:670:\tstruct kvm_create_guest_memfd guest_memfd = {\ntools/testing/selftests/kvm/include/kvm_util.h-671-\t\t.size = size,\n--\ntools/testing/selftests/kvm/include/kvm_util.h-674-\ntools/testing/selftests/kvm/include/kvm_util.h:675:\treturn __vm_ioctl(vm, KVM_CREATE_GUEST_MEMFD, \u0026guest_memfd);\ntools/testing/selftests/kvm/include/kvm_util.h-676-}\ntools/testing/selftests/kvm/include/kvm_util.h-677-\ntools/testing/selftests/kvm/include/kvm_util.h:678:static inline int vm_create_guest_memfd(struct kvm_vm *vm, u64 size,\ntools/testing/selftests/kvm/include/kvm_util.h-679-\t\t\t\t\tu64 flags)\ntools/testing/selftests/kvm/include/kvm_util.h-680-{\ntools/testing/selftests/kvm/include/kvm_util.h:681:\tint fd = __vm_create_guest_memfd(vm, size, flags);\ntools/testing/selftests/kvm/include/kvm_util.h-682-\n--\ntools/testing/selftests/kvm/include/kvm_util.h=691=void vm_set_user_memory_region2(struct kvm_vm *vm, u32 slot, u32 flags,\ntools/testing/selftests/kvm/include/kvm_util.h-692-\t\t\t\tgpa_t gpa, u64 size, void *hva,\ntools/testing/selftests/kvm/include/kvm_util.h:693:\t\t\t\tu32 guest_memfd, u64 guest_memfd_offset);\ntools/testing/selftests/kvm/include/kvm_util.h-694-int __vm_set_user_memory_region2(struct kvm_vm *vm, u32 slot, u32 flags,\ntools/testing/selftests/kvm/include/kvm_util.h-695-\t\t\t\t gpa_t gpa, u64 size, void *hva,\ntools/testing/selftests/kvm/include/kvm_util.h:696:\t\t\t\t u32 guest_memfd, u64 guest_memfd_offset);\ntools/testing/selftests/kvm/include/kvm_util.h-697-\n--\ntools/testing/selftests/kvm/include/kvm_util.h=701=void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type,\ntools/testing/selftests/kvm/include/kvm_util.h-702-\t\tgpa_t gpa, u32 slot, u64 npages, u32 flags,\ntools/testing/selftests/kvm/include/kvm_util.h:703:\t\tint guest_memfd_fd, u64 guest_memfd_offset);\ntools/testing/selftests/kvm/include/kvm_util.h-704-\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=438=void kvm_set_files_rlimit(u32 nr_vcpus)\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-469-\ntools/testing/selftests/kvm/lib/kvm_util.c:470:static bool is_guest_memfd_required(struct vm_shape shape)\ntools/testing/selftests/kvm/lib/kvm_util.c-471-{\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=479=struct kvm_vm *__vm_create(struct vm_shape shape, u32 nr_runnable_vcpus,\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-499-\tflags = 0;\ntools/testing/selftests/kvm/lib/kvm_util.c:500:\tif (is_guest_memfd_required(shape))\ntools/testing/selftests/kvm/lib/kvm_util.c-501-\t\tflags |= KVM_MEM_GUEST_MEMFD;\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=804=static void __vm_mem_region_delete(struct kvm_vm *vm,\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-818-\t}\ntools/testing/selftests/kvm/lib/kvm_util.c:819:\tif ((int)region-\u003eregion.guest_memfd \u003e= 0)\ntools/testing/selftests/kvm/lib/kvm_util.c:820:\t\tkvm_free_fd(region-\u003eregion.guest_memfd);\ntools/testing/selftests/kvm/lib/kvm_util.c-821-\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=947=int __vm_set_user_memory_region2(struct kvm_vm *vm, u32 slot, u32 flags,\ntools/testing/selftests/kvm/lib/kvm_util.c-948-\t\t\t\t gpa_t gpa, u64 size, void *hva,\ntools/testing/selftests/kvm/lib/kvm_util.c:949:\t\t\t\t u32 guest_memfd, u64 guest_memfd_offset)\ntools/testing/selftests/kvm/lib/kvm_util.c-950-{\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-956-\t\t.userspace_addr = (uintptr_t)hva,\ntools/testing/selftests/kvm/lib/kvm_util.c:957:\t\t.guest_memfd = guest_memfd,\ntools/testing/selftests/kvm/lib/kvm_util.c:958:\t\t.guest_memfd_offset = guest_memfd_offset,\ntools/testing/selftests/kvm/lib/kvm_util.c-959-\t};\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=966=void vm_set_user_memory_region2(struct kvm_vm *vm, u32 slot, u32 flags,\ntools/testing/selftests/kvm/lib/kvm_util.c-967-\t\t\t\tgpa_t gpa, u64 size, void *hva,\ntools/testing/selftests/kvm/lib/kvm_util.c:968:\t\t\t\tu32 guest_memfd, u64 guest_memfd_offset)\ntools/testing/selftests/kvm/lib/kvm_util.c-969-{\ntools/testing/selftests/kvm/lib/kvm_util.c-970-\tint ret = __vm_set_user_memory_region2(vm, slot, flags, gpa, size, hva,\ntools/testing/selftests/kvm/lib/kvm_util.c:971:\t\t\t\t\t guest_memfd, guest_memfd_offset);\ntools/testing/selftests/kvm/lib/kvm_util.c-972-\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=979=void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type,\ntools/testing/selftests/kvm/lib/kvm_util.c-980-\t\tgpa_t gpa, u32 slot, u64 npages, u32 flags,\ntools/testing/selftests/kvm/lib/kvm_util.c:981:\t\tint guest_memfd, u64 guest_memfd_offset)\ntools/testing/selftests/kvm/lib/kvm_util.c-982-{\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-1085-\tif (flags \u0026 KVM_MEM_GUEST_MEMFD) {\ntools/testing/selftests/kvm/lib/kvm_util.c:1086:\t\tif (guest_memfd \u003c 0) {\ntools/testing/selftests/kvm/lib/kvm_util.c:1087:\t\t\tu32 guest_memfd_flags = 0;\ntools/testing/selftests/kvm/lib/kvm_util.c:1088:\t\t\tTEST_ASSERT(!guest_memfd_offset,\ntools/testing/selftests/kvm/lib/kvm_util.c:1089:\t\t\t\t \"Offset must be zero when creating new guest_memfd\");\ntools/testing/selftests/kvm/lib/kvm_util.c:1090:\t\t\tguest_memfd = vm_create_guest_memfd(vm, mem_size, guest_memfd_flags);\ntools/testing/selftests/kvm/lib/kvm_util.c-1091-\t\t} else {\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-1097-\t\t\t */\ntools/testing/selftests/kvm/lib/kvm_util.c:1098:\t\t\tguest_memfd = kvm_dup(guest_memfd);\ntools/testing/selftests/kvm/lib/kvm_util.c-1099-\t\t}\ntools/testing/selftests/kvm/lib/kvm_util.c-1100-\ntools/testing/selftests/kvm/lib/kvm_util.c:1101:\t\tregion-\u003eregion.guest_memfd = guest_memfd;\ntools/testing/selftests/kvm/lib/kvm_util.c:1102:\t\tregion-\u003eregion.guest_memfd_offset = guest_memfd_offset;\ntools/testing/selftests/kvm/lib/kvm_util.c-1103-\t} else {\ntools/testing/selftests/kvm/lib/kvm_util.c:1104:\t\tregion-\u003eregion.guest_memfd = -1;\ntools/testing/selftests/kvm/lib/kvm_util.c-1105-\t}\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-1119-\t\t\" slot: %u flags: 0x%x\\n\"\ntools/testing/selftests/kvm/lib/kvm_util.c:1120:\t\t\" guest_phys_addr: 0x%lx size: 0x%llx guest_memfd: %d\",\ntools/testing/selftests/kvm/lib/kvm_util.c-1121-\t\tret, errno, slot, flags, gpa, region-\u003eregion.memory_size,\ntools/testing/selftests/kvm/lib/kvm_util.c:1122:\t\tregion-\u003eregion.guest_memfd);\ntools/testing/selftests/kvm/lib/kvm_util.c-1123-\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=1274=void vm_guest_mem_fallocate(struct kvm_vm *vm, u64 base, u64 size,\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-1291-\t\toffset = gpa - region-\u003eregion.guest_phys_addr;\ntools/testing/selftests/kvm/lib/kvm_util.c:1292:\t\tfd_offset = region-\u003eregion.guest_memfd_offset + offset;\ntools/testing/selftests/kvm/lib/kvm_util.c-1293-\t\tlen = min_t(u64, end - gpa, region-\u003eregion.memory_size - offset);\ntools/testing/selftests/kvm/lib/kvm_util.c-1294-\ntools/testing/selftests/kvm/lib/kvm_util.c:1295:\t\tret = fallocate(region-\u003eregion.guest_memfd, mode, fd_offset, len);\ntools/testing/selftests/kvm/lib/kvm_util.c-1296-\t\tTEST_ASSERT(!ret, \"fallocate() failed to %s at %lx (len = %lu), fd = %d, mode = %x, offset = %lx\",\ntools/testing/selftests/kvm/lib/kvm_util.c-1297-\t\t\t punch_hole ? \"punch hole\" : \"allocate\", gpa, len,\ntools/testing/selftests/kvm/lib/kvm_util.c:1298:\t\t\t region-\u003eregion.guest_memfd, mode, fd_offset);\ntools/testing/selftests/kvm/lib/kvm_util.c-1299-\t}\n--\ntools/testing/selftests/kvm/set_memory_region_test.c=346=static void test_invalid_memory_region_flags(void)\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-386-\tif (supported_flags \u0026 KVM_MEM_GUEST_MEMFD) {\ntools/testing/selftests/kvm/set_memory_region_test.c:387:\t\tint guest_memfd = vm_create_guest_memfd(vm, MEM_REGION_SIZE, 0);\ntools/testing/selftests/kvm/set_memory_region_test.c-388-\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-390-\t\t\t\t\t\t KVM_MEM_LOG_DIRTY_PAGES | KVM_MEM_GUEST_MEMFD,\ntools/testing/selftests/kvm/set_memory_region_test.c:391:\t\t\t\t\t\t 0, MEM_REGION_SIZE, NULL, guest_memfd, 0);\ntools/testing/selftests/kvm/set_memory_region_test.c-392-\t\tTEST_ASSERT(r \u0026\u0026 errno == EINVAL,\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-396-\t\t\t\t\t\t KVM_MEM_READONLY | KVM_MEM_GUEST_MEMFD,\ntools/testing/selftests/kvm/set_memory_region_test.c:397:\t\t\t\t\t\t 0, MEM_REGION_SIZE, NULL, guest_memfd, 0);\ntools/testing/selftests/kvm/set_memory_region_test.c-398-\t\tTEST_ASSERT(r \u0026\u0026 errno == EINVAL,\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-400-\ntools/testing/selftests/kvm/set_memory_region_test.c:401:\t\tclose(guest_memfd);\ntools/testing/selftests/kvm/set_memory_region_test.c-402-\t}\n--\ntools/testing/selftests/kvm/set_memory_region_test.c=409=static void test_add_max_memory_regions(void)\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-457-#ifdef __x86_64__\ntools/testing/selftests/kvm/set_memory_region_test.c:458:static void test_invalid_guest_memfd(struct kvm_vm *vm, int memfd,\ntools/testing/selftests/kvm/set_memory_region_test.c-459-\t\t\t\t size_t offset, const char *msg)\n--\ntools/testing/selftests/kvm/set_memory_region_test.c=467=static void test_add_private_memory_region(void)\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-475-\ntools/testing/selftests/kvm/set_memory_region_test.c:476:\ttest_invalid_guest_memfd(vm, vm-\u003ekvm_fd, 0, \"KVM fd should fail\");\ntools/testing/selftests/kvm/set_memory_region_test.c:477:\ttest_invalid_guest_memfd(vm, vm-\u003efd, 0, \"VM's fd should fail\");\ntools/testing/selftests/kvm/set_memory_region_test.c-478-\ntools/testing/selftests/kvm/set_memory_region_test.c-479-\tmemfd = kvm_memfd_alloc(MEM_REGION_SIZE, false);\ntools/testing/selftests/kvm/set_memory_region_test.c:480:\ttest_invalid_guest_memfd(vm, memfd, 0, \"Regular memfd() should fail\");\ntools/testing/selftests/kvm/set_memory_region_test.c-481-\tclose(memfd);\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-483-\tvm2 = vm_create_barebones_type(KVM_X86_SW_PROTECTED_VM);\ntools/testing/selftests/kvm/set_memory_region_test.c:484:\tmemfd = vm_create_guest_memfd(vm2, MEM_REGION_SIZE, 0);\ntools/testing/selftests/kvm/set_memory_region_test.c:485:\ttest_invalid_guest_memfd(vm, memfd, 0, \"Other VM's guest_memfd() should fail\");\ntools/testing/selftests/kvm/set_memory_region_test.c-486-\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-491-\ntools/testing/selftests/kvm/set_memory_region_test.c:492:\tmemfd = vm_create_guest_memfd(vm, MEM_REGION_SIZE, 0);\ntools/testing/selftests/kvm/set_memory_region_test.c-493-\tfor (i = 1; i \u003c PAGE_SIZE; i++)\ntools/testing/selftests/kvm/set_memory_region_test.c:494:\t\ttest_invalid_guest_memfd(vm, memfd, i, \"Unaligned offset should fail\");\ntools/testing/selftests/kvm/set_memory_region_test.c-495-\n--\ntools/testing/selftests/kvm/set_memory_region_test.c=503=static void test_add_overlapping_private_memory_regions(void)\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-512-\ntools/testing/selftests/kvm/set_memory_region_test.c:513:\tmemfd = vm_create_guest_memfd(vm, MEM_REGION_SIZE * 5, 0);\ntools/testing/selftests/kvm/set_memory_region_test.c-514-\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-523-\t * Delete the first memslot, and then attempt to recreate it except\ntools/testing/selftests/kvm/set_memory_region_test.c:524:\t * with a \"bad\" offset that results in overlap in the guest_memfd().\ntools/testing/selftests/kvm/set_memory_region_test.c-525-\t */\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-529-\t/*\ntools/testing/selftests/kvm/set_memory_region_test.c:530:\t * Verify that overlap in the guest_memfd bindings (i.e. in guest_memfd\ntools/testing/selftests/kvm/set_memory_region_test.c-531-\t * file offsets), but _not_ in the GPA space, fails with -EEXIST.\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-537-\tTEST_ASSERT(r == -1 \u0026\u0026 errno == EEXIST,\ntools/testing/selftests/kvm/set_memory_region_test.c:538:\t\t \"Overlapping guest_memfd() bindings should fail with EEXIST\");\ntools/testing/selftests/kvm/set_memory_region_test.c-539-\ntools/testing/selftests/kvm/set_memory_region_test.c:540:\t/* And now the back half of the other slot's guest_memfd binding. */\ntools/testing/selftests/kvm/set_memory_region_test.c-541-\tr = __vm_set_user_memory_region2(vm, MEM_REGION_SLOT, KVM_MEM_GUEST_MEMFD,\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-545-\tTEST_ASSERT(r == -1 \u0026\u0026 errno == EEXIST,\ntools/testing/selftests/kvm/set_memory_region_test.c:546:\t\t \"Overlapping guest_memfd() bindings should fail with EEXIST\");\ntools/testing/selftests/kvm/set_memory_region_test.c-547-\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-557-\tTEST_ASSERT(r == -1 \u0026\u0026 errno == EEXIST,\ntools/testing/selftests/kvm/set_memory_region_test.c:558:\t\t \"Overlapping guest_memfd() bindings should fail with EEXIST\");\ntools/testing/selftests/kvm/set_memory_region_test.c-559-\n--\ntools/testing/selftests/kvm/set_memory_region_test.c-565-\tTEST_ASSERT(r == -1 \u0026\u0026 errno == EEXIST,\ntools/testing/selftests/kvm/set_memory_region_test.c:566:\t\t \"Overlapping guest_memfd() bindings should fail with EEXIST\");\ntools/testing/selftests/kvm/set_memory_region_test.c-567-\n--\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c=230=static void guest_test_punch_hole(u64 base_gpa, bool precise)\n--\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c-236-\t * Convert the entire range to private, this testcase is all about\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c:237:\t * punching holes in guest_memfd, i.e. shared mappings aren't needed.\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c-238-\t */\n--\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c=271=static void guest_code(u64 base_gpa)\n--\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c-274-\t * Run the conversion test twice, with and without doing fallocate() on\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c:275:\t * the guest_memfd backing when converting between shared and private.\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c-276-\t */\n--\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c-280-\t/*\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c:281:\t * Run the PUNCH_HOLE test twice too, once with the entire guest_memfd\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c-282-\t * faulted in, once with only the target range faulted in.\n--\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c=369=static void test_mem_conversions(enum vm_mem_backing_src_type src_type, u32 nr_vcpus,\n--\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c-396-\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c:397:\tmemfd = vm_create_guest_memfd(vm, memfd_size, 0);\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c-398-\n--\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c-425-\t/*\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c:426:\t * Allocate and free memory from the guest_memfd after closing the VM\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c:427:\t * fd. The guest_memfd is gifted a reference to its owning VM, i.e.\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c-428-\t * should prevent the VM from being fully destroyed until the last\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c:429:\t * reference to the guest_memfd is also put.\ntools/testing/selftests/kvm/x86/private_mem_conversions_test.c-430-\t */\n\n"
} |
| 19/2 | 2026/06/25 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 33149 output: 24 thoughts: 115 Thoughts: **Analyzing Guest Memfd Support** Okay, so it looks like `guest_memfd` support relies on either `KVM_X86_SW_PROTECTED_VM` or `KVM_X86_SNP_VM`. That makes sense; those VM types have security-related considerations that probably necessitate some form of protected memory management. Wait a minute… `KVM_X86_SW_PROTECTED_VM` is a *software*-protected VM? That's interesting. I hadn't thought about that. This suggests we might be able to test and validate `guest_memfd` functionality even without requiring specific hardware support, by leveraging the software-based protection features. That's a significant advantage for development and testing. Let's dig into `KVM_X86_SW_PROTECTED_VM` a bit more, specifically within `arch/x86/kvm/Kconfig` to understand the relevant configuration options and dependencies. I should be able to get a better handle on the implications by examining the Kconfig settings. |
| 20/2 | 2026/06/25 22:39 | tool | grepper |
0mArgs:{
"Expression": "config KVM_SW_PROTECTED_VM"
}Results: {
"Output": "arch/x86/kvm/Kconfig=69=config KVM_WERROR\n--\narch/x86/kvm/Kconfig-82-\narch/x86/kvm/Kconfig:83:config KVM_SW_PROTECTED_VM\narch/x86/kvm/Kconfig-84-\tbool \"Enable support for KVM software-protected VMs\"\n"
} |
| 21/2 | 2026/06/25 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 33621 output: 43 thoughts: 94 Thoughts: **Analyzing the Impact of `CONFIG_KVM_SW_PROTECTED_VM` on SEV-SNP VMs** Okay, so I see this `CONFIG_KVM_SW_PROTECTED_VM` flag, and it's enabling `guest_memfd` even without the underlying hardware support. That's interesting, I need to understand the implications of this. My immediate thought is, how does this interact with the more established SEV-SNP functionality? Hold on... I'm looking at the patch, and it's modifying `sev_gmem_invalidate_range` and `sev_gmem_free_folio`. Now, those functions are *specifically* called when `KVM_AMD_SEV` is enabled, and the virtual machine is, of course, an SEV-SNP VM. That's a red flag. This has potential implications for memory protection on a platform I care about, so I need to understand this connection. Right, time to dig deeper into `sev_gmem_invalidate_range`. Let's see exactly what's being altered. I need to understand the control flow. |
| 22/2 | 2026/06/25 22:39 | tool | read-file |
0mArgs:{
"File": "arch/x86/kvm/svm/sev.c",
"FirstLine": 5157,
"LineCount": 25
}Results: {
"Contents": "5157:\tvoid sev_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range)\n5158:\t{\n5159:\t\tstruct kvm_vcpu *vcpu;\n5160:\t\tunsigned long i;\n5161:\t\n5162:\t\tlockdep_assert_held_write(\u0026kvm-\u003emmu_lock);\n5163:\t\n5164:\t\t/*\n5165:\t\t * An unstable result for \"is SNP\" is a-ok here, thanks to mmu_lock.\n5166:\t\t * The vCPU's VMSA GPA is invalidated before the vCPU is made visible\n5167:\t\t * to other tasks, and can only become valid while holding mmu_lock,\n5168:\t\t * after the VM is fully committed to being an SNP VM.\n5169:\t\t */\n5170:\t\tif (!____sev_snp_guest(kvm))\n5171:\t\t\treturn;\n5172:\t\n5173:\t\tkvm_for_each_vcpu(i, vcpu, kvm) {\n5174:\t\t\tgpa_t gpa = to_svm(vcpu)-\u003esev_es.snp_guest_vmsa_gpa;\n5175:\t\n5176:\t\t\tif (VALID_PAGE(gpa) \u0026\u0026\n5177:\t\t\t gpa_to_gfn(gpa) \u003e= range-\u003estart \u0026\u0026\n5178:\t\t\t gpa_to_gfn(gpa) \u003c range-\u003eend)\n5179:\t\t\t\tkvm_make_request_and_kick(KVM_REQ_VMSA_PAGE_RELOAD, vcpu);\n5180:\t\t}\n5181:\t}\n"
} |
| 23/2 | 2026/06/25 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 34454 output: 21 thoughts: 277 Thoughts: **Analyzing the Patch's Worthiness for Fuzzing** Okay, so the code snippet starts by checking `____sev_snp_guest(kvm)`. Right, that means this path is only relevant if we're dealing with an SEV-SNP guest. My first thought is: can someone even *create* an SNP guest without the underlying hardware support? The answer's a solid *no*. `sev_snp_supported` is checked in `sev_hardware_setup`, which reads the hardware capabilities, so we're relying on the chip here. But then I recall that Syzkaller *does* run on GCE instances that support SEV-SNP, a.k.a. Confidential VMs. This throws a wrench in the works. The prompt I'm working with says to return `WorthFuzzing=false` if a patch only contains code paths unreachable in virtualized environments like GCE or QEMU, even with software emulation. Since GCE *does* offer SEV-SNP instances, this condition is, in fact, *possible*. Therefore, I'm leaning toward setting `WorthFuzzing=true`. The patch is, in principle, reachable. I'll need to confirm that. Next, I need to identify the relevant configs. I'm thinking: `KVM_AMD_SEV`, `KVM_AMD`, and `KVM` are the obvious ones. `KVM_SW_PROTECTED_VM` *might* come into play, especially when dealing with `guest_memfd`. Though, `KVM_AMD_SEV` is actually the one that enables `HAVE_KVM_ARCH_GMEM_INVALIDATE`, which implies guest_memfd is enabled. So I need to confirm the configurations needed for `guest_memfd`. |
| 24/2 | 2026/06/25 22:39 | tool | grepper |
0mError:no matches Args: {
"Expression": "config KVM_PRIVATE_MEM"
}Results: {
"error": "no matches"
} |
| 25/2 | 2026/06/25 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 35153 output: 24 thoughts: 20 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Checking the KVM Configuration for Guest Memory Sharing** Right, let's dive into the kernel configuration. I need to refresh my memory on the specifics of memory sharing within KVM guests, particularly related to `memfd`. My immediate thought is to check the `virt/kvm/Kconfig` file. That's the logical place to start. I'm looking for the configuration option associated with `guest_memfd`. It’ll be the key to understanding how memory file descriptors are being used or can be enabled for these guests. I need to see the dependencies, help text, and default settings. Hopefully, this Kconfig entry gives me a clear picture of its integration and potential implications for my work. This should be a quick and efficient way to pinpoint how the system handles it, and if it's relevant to this current focus. |
| 26/2 | 2026/06/25 22:39 | tool | grepper |
0mError:no matches Args: {
"Expression": "config KVM_GENERIC_PRIVATE_MEM"
}Results: {
"error": "no matches"
} |
| 27/2 | 2026/06/25 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 35408 output: 20 thoughts: 20 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Checking the KVM Configuration for Guest Memory Sharing** Right, let's dive into the kernel configuration. I need to refresh my memory on the specifics of memory sharing within KVM guests, particularly related to `memfd`. My immediate thought is to check the `virt/kvm/Kconfig` file. That's the logical place to start. I'm looking for the configuration option associated with `guest_memfd`. It’ll be the key to understanding how memory file descriptors are being used or can be enabled for these guests. I need to see the dependencies, help text, and default settings. Hopefully, this Kconfig entry gives me a clear picture of its integration and potential implications for my work. This should be a quick and efficient way to pinpoint how the system handles it, and if it's relevant to this current focus. |
| 28/2 | 2026/06/25 22:39 | tool | grepper |
0mArgs:{
"Expression": "guest_memfd.o"
}Results: {
"Output": "Documentation/virt/kvm/api.rst=6337=in flags to have KVM bind the memory region to a given guest_memfd range of\nDocumentation/virt/kvm/api.rst:6338:[guest_memfd_offset, guest_memfd_offset + memory_size]. The target guest_memfd\nDocumentation/virt/kvm/api.rst-6339-must point at a file created via KVM_CREATE_GUEST_MEMFD on the current VM, and\n--\nDocumentation/virt/kvm/api.rst=6341=bounds checks apply (use common sense).\n--\nDocumentation/virt/kvm/api.rst-6350-\t__u64 userspace_addr; /* start of the userspace allocated memory */\nDocumentation/virt/kvm/api.rst:6351:\t__u64 guest_memfd_offset;\nDocumentation/virt/kvm/api.rst-6352-\t__u32 guest_memfd;\n--\nDocumentation/virt/kvm/api.rst=6445=KVM currently only supports mapping guest_memfd via KVM_SET_USER_MEMORY_REGION2,\nDocumentation/virt/kvm/api.rst:6446:and more specifically via the guest_memfd and guest_memfd_offset fields in\nDocumentation/virt/kvm/api.rst:6447:\"struct kvm_userspace_memory_region2\", where guest_memfd_offset is the offset\nDocumentation/virt/kvm/api.rst-6448-into the guest_memfd instance. For a given guest_memfd file, there can be at\n--\narch/x86/kvm/mmu/mmu.c=3346=static u8 kvm_gmem_max_mapping_level(struct kvm *kvm, struct kvm_page_fault *fault,\n--\narch/x86/kvm/mmu/mmu.c-3357-\t} else {\narch/x86/kvm/mmu/mmu.c:3358:\t\t/* TODO: Call into guest_memfd once hugepages are supported. */\narch/x86/kvm/mmu/mmu.c-3359-\t\tWARN_ONCE(1, \"Get pfn+order from guest_memfd\");\n--\ninclude/uapi/linux/kvm.h=39=struct kvm_userspace_memory_region2 {\n--\ninclude/uapi/linux/kvm.h-44-\t__u64 userspace_addr;\ninclude/uapi/linux/kvm.h:45:\t__u64 guest_memfd_offset;\ninclude/uapi/linux/kvm.h-46-\t__u32 guest_memfd;\n--\ntools/include/uapi/linux/kvm.h=38=struct kvm_userspace_memory_region2 {\n--\ntools/include/uapi/linux/kvm.h-43-\t__u64 userspace_addr;\ntools/include/uapi/linux/kvm.h:44:\t__u64 guest_memfd_offset;\ntools/include/uapi/linux/kvm.h-45-\t__u32 guest_memfd;\n--\ntools/testing/selftests/kvm/include/kvm_util.h=691=void vm_set_user_memory_region2(struct kvm_vm *vm, u32 slot, u32 flags,\ntools/testing/selftests/kvm/include/kvm_util.h-692-\t\t\t\tgpa_t gpa, u64 size, void *hva,\ntools/testing/selftests/kvm/include/kvm_util.h:693:\t\t\t\tu32 guest_memfd, u64 guest_memfd_offset);\ntools/testing/selftests/kvm/include/kvm_util.h-694-int __vm_set_user_memory_region2(struct kvm_vm *vm, u32 slot, u32 flags,\ntools/testing/selftests/kvm/include/kvm_util.h-695-\t\t\t\t gpa_t gpa, u64 size, void *hva,\ntools/testing/selftests/kvm/include/kvm_util.h:696:\t\t\t\t u32 guest_memfd, u64 guest_memfd_offset);\ntools/testing/selftests/kvm/include/kvm_util.h-697-\n--\ntools/testing/selftests/kvm/include/kvm_util.h=701=void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type,\ntools/testing/selftests/kvm/include/kvm_util.h-702-\t\tgpa_t gpa, u32 slot, u64 npages, u32 flags,\ntools/testing/selftests/kvm/include/kvm_util.h:703:\t\tint guest_memfd_fd, u64 guest_memfd_offset);\ntools/testing/selftests/kvm/include/kvm_util.h-704-\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=947=int __vm_set_user_memory_region2(struct kvm_vm *vm, u32 slot, u32 flags,\ntools/testing/selftests/kvm/lib/kvm_util.c-948-\t\t\t\t gpa_t gpa, u64 size, void *hva,\ntools/testing/selftests/kvm/lib/kvm_util.c:949:\t\t\t\t u32 guest_memfd, u64 guest_memfd_offset)\ntools/testing/selftests/kvm/lib/kvm_util.c-950-{\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-957-\t\t.guest_memfd = guest_memfd,\ntools/testing/selftests/kvm/lib/kvm_util.c:958:\t\t.guest_memfd_offset = guest_memfd_offset,\ntools/testing/selftests/kvm/lib/kvm_util.c-959-\t};\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=966=void vm_set_user_memory_region2(struct kvm_vm *vm, u32 slot, u32 flags,\ntools/testing/selftests/kvm/lib/kvm_util.c-967-\t\t\t\tgpa_t gpa, u64 size, void *hva,\ntools/testing/selftests/kvm/lib/kvm_util.c:968:\t\t\t\tu32 guest_memfd, u64 guest_memfd_offset)\ntools/testing/selftests/kvm/lib/kvm_util.c-969-{\ntools/testing/selftests/kvm/lib/kvm_util.c-970-\tint ret = __vm_set_user_memory_region2(vm, slot, flags, gpa, size, hva,\ntools/testing/selftests/kvm/lib/kvm_util.c:971:\t\t\t\t\t guest_memfd, guest_memfd_offset);\ntools/testing/selftests/kvm/lib/kvm_util.c-972-\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=979=void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type,\ntools/testing/selftests/kvm/lib/kvm_util.c-980-\t\tgpa_t gpa, u32 slot, u64 npages, u32 flags,\ntools/testing/selftests/kvm/lib/kvm_util.c:981:\t\tint guest_memfd, u64 guest_memfd_offset)\ntools/testing/selftests/kvm/lib/kvm_util.c-982-{\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-1087-\t\t\tu32 guest_memfd_flags = 0;\ntools/testing/selftests/kvm/lib/kvm_util.c:1088:\t\t\tTEST_ASSERT(!guest_memfd_offset,\ntools/testing/selftests/kvm/lib/kvm_util.c-1089-\t\t\t\t \"Offset must be zero when creating new guest_memfd\");\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-1101-\t\tregion-\u003eregion.guest_memfd = guest_memfd;\ntools/testing/selftests/kvm/lib/kvm_util.c:1102:\t\tregion-\u003eregion.guest_memfd_offset = guest_memfd_offset;\ntools/testing/selftests/kvm/lib/kvm_util.c-1103-\t} else {\n--\ntools/testing/selftests/kvm/lib/kvm_util.c=1274=void vm_guest_mem_fallocate(struct kvm_vm *vm, u64 base, u64 size,\n--\ntools/testing/selftests/kvm/lib/kvm_util.c-1291-\t\toffset = gpa - region-\u003eregion.guest_phys_addr;\ntools/testing/selftests/kvm/lib/kvm_util.c:1292:\t\tfd_offset = region-\u003eregion.guest_memfd_offset + offset;\ntools/testing/selftests/kvm/lib/kvm_util.c-1293-\t\tlen = min_t(u64, end - gpa, region-\u003eregion.memory_size - offset);\n--\nvirt/kvm/Makefile.kvm=14=kvm-$(CONFIG_HAVE_KVM_PFNCACHE) += $(KVM)/pfncache.o\nvirt/kvm/Makefile.kvm:15:kvm-$(CONFIG_KVM_GUEST_MEMFD) += $(KVM)/guest_memfd.o\n--\nvirt/kvm/kvm_main.c=1994=static int kvm_set_memory_region(struct kvm *kvm,\n--\nvirt/kvm/kvm_main.c-2026-\tif (mem-\u003eflags \u0026 KVM_MEM_GUEST_MEMFD \u0026\u0026\nvirt/kvm/kvm_main.c:2027:\t (mem-\u003eguest_memfd_offset \u0026 (PAGE_SIZE - 1) ||\nvirt/kvm/kvm_main.c:2028:\t mem-\u003eguest_memfd_offset + mem-\u003ememory_size \u003c mem-\u003eguest_memfd_offset))\nvirt/kvm/kvm_main.c-2029-\t\treturn -EINVAL;\n--\nvirt/kvm/kvm_main.c-2107-\tif (mem-\u003eflags \u0026 KVM_MEM_GUEST_MEMFD) {\nvirt/kvm/kvm_main.c:2108:\t\tr = kvm_gmem_bind(kvm, new, mem-\u003eguest_memfd, mem-\u003eguest_memfd_offset);\nvirt/kvm/kvm_main.c-2109-\t\tif (r)\n"
} |
| 29/2 | 2026/06/25 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 38486 output: 23 thoughts: 33 Thoughts: Okay, here's my take on those thoughts, framed for an expert audience: **Investigating `CONFIG_KVM_GUEST_MEMFD`** Right, `CONFIG_KVM_GUEST_MEMFD`... that's the key enabling the `guest_memfd` functionality, isn't it? Okay, so that's where to start to see how `memfd` is implemented in the KVM guest. Let's trace back from the config option's definition. Need to understand the dependencies and implications of having that set. Where exactly is this option defined, and what surrounding context does that give me? From there, I can get a better feel for the whole picture. |
| 30/2 | 2026/06/25 22:39 | tool | grepper |
0mArgs:{
"Expression": "config KVM_GUEST_MEMFD"
}Results: {
"Output": "virt/kvm/Kconfig=103=config KVM_GENERIC_MEMORY_ATTRIBUTES\n--\nvirt/kvm/Kconfig-105-\nvirt/kvm/Kconfig:106:config KVM_GUEST_MEMFD\nvirt/kvm/Kconfig-107- select XARRAY_MULTI\n"
} |
| 31/2 | 2026/06/25 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 38784 output: 23 thoughts: 16 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience, presented in the first person: **Investigating the KVM_GUEST_MEMFD Selection** Alright, so the first thing on my mind is to understand the context of `KVM_GUEST_MEMFD`. I need to figure out *exactly* where this flag is being used. What code paths are dependent on it, and what are the implications of its presence or absence? Given the name, I'm already assuming it relates to memory management for KVM guests, specifically memory file descriptors. My immediate mental process is to quickly determine which systems or components are checking for this value. The goal is to understand what's *selecting* it – which drivers, subsystems, or potentially even user-space applications are querying and making decisions based on `KVM_GUEST_MEMFD`? Are we talking compile-time options, runtime features, or both? I need the big picture to determine why it is relevant. |
| 32/2 | 2026/06/25 22:39 | tool | grepper |
0mArgs:{
"Expression": "select KVM_GUEST_MEMFD"
}Results: {
"Output": "arch/arm64/kvm/Kconfig=20=menuconfig KVM\n--\narch/arm64/kvm/Kconfig-38-\tselect GUEST_PERF_EVENTS if PERF_EVENTS\narch/arm64/kvm/Kconfig:39:\tselect KVM_GUEST_MEMFD\narch/arm64/kvm/Kconfig-40-\thelp\n--\narch/x86/kvm/Kconfig=20=config KVM_X86\n--\narch/x86/kvm/Kconfig-49-\tselect KVM_WERROR if WERROR\narch/x86/kvm/Kconfig:50:\tselect KVM_GUEST_MEMFD if X86_64\narch/x86/kvm/Kconfig-51-\n"
} |
| 33/2 | 2026/06/25 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 39243 output: 44 thoughts: 262 Thoughts: **My KVM/x86 Configuration Review** Okay, so if I understand this correctly, `KVM_GUEST_MEMFD` gets auto-selected by `KVM_X86` when the architecture is `X86_64`. That means it's essentially always enabled on x86-64 systems, which makes sense. I need to make sure I have these configs enabled: `KVM_AMD_SEV`, `KVM_AMD`, `KVM`, and just to be sure, I'll throw in `KVM_SW_PROTECTED_VM` too. It might make testing `guest_memfd` a bit smoother, you never know. Now, let me shift gears and review the key symbols I need to keep an eye on: `__sev_snp_reload_vmsa`, `sev_snp_reload_vmsa`, `sev_gmem_invalidate_range`, `sev_gmem_free_folio`, `kvm_arch_gmem_invalidate_range`, and `kvm_arch_gmem_free_folio`, and `sev_snp_init_protected_guest_state`. Hold on a second... `kvm_arch_gmem_invalidate_range` and `kvm_arch_gmem_free_folio` look awfully generic. Shouldn't those be defined in the general x86 KVM code? Let me quickly double-check if they are defined in `arch/x86/kvm/x86.c`. It's always the generic stuff that gets you! |
| 34/2 | 2026/06/25 22:39 | tool | read-file |
0mArgs:{
"File": "arch/x86/kvm/x86.c",
"FirstLine": 10590,
"LineCount": 20
}Results: {
"Contents": "10590:\tint kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_order)\n10591:\t{\n10592:\t\treturn kvm_x86_call(gmem_prepare)(kvm, pfn, gfn, max_order);\n10593:\t}\n10594:\t#endif\n10595:\t\n10596:\t#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n10597:\tvoid kvm_arch_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range)\n10598:\t{\n10599:\t\tkvm_x86_call(gmem_invalidate_range)(kvm, range);\n10600:\t}\n10601:\tvoid kvm_arch_gmem_free_folio(struct folio *folio)\n10602:\t{\n10603:\t\tkvm_x86_call(gmem_free_folio)(folio);\n10604:\t}\n10605:\t#endif\n10606:\t#endif\n10607:\t\n10608:\tvoid kvm_fixup_and_inject_pf_error(struct kvm_vcpu *vcpu, gva_t gva, u16 error_code)\n10609:\t{\n"
} |
| 35/2 | 2026/06/25 22:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 40292 output: 39 thoughts: 36 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Checking `guest_memfd.c` for Invalidation** Yes, that's the likely area. We're definitely dealing with some memory management issue, so my immediate thought is to target the `virt/kvm/guest_memfd.c` file. Specifically, I need to check the implementation around `__kvm_gmem_invalidate_start`. That function name itself is a strong indicator; invalidation is usually involved in these kinds of problems, especially when KVM guests are misbehaving with memory and memfds. I want to see how that function is implemented, what its dependencies are, how it's called, and what potential race conditions or synchronization issues exist. It's a good starting point, and I expect it to shed some light on the problem. Let's dig in. |
| 36/2 | 2026/06/25 22:40 | tool | read-file |
0mArgs:{
"File": "virt/kvm/guest_memfd.c",
"FirstLine": 180,
"LineCount": 20
}Results: {
"Contents": " 180:\t\t\tif (!found_memslot) {\n 181:\t\t\t\tfound_memslot = true;\n 182:\t\n 183:\t\t\t\tKVM_MMU_LOCK(kvm);\n 184:\t\t\t\tkvm_mmu_invalidate_start(kvm);\n 185:\t\t\t}\n 186:\t\n 187:\t\t\tflush |= kvm_mmu_unmap_gfn_range(kvm, \u0026gfn_range);\n 188:\t\n 189:\t#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n 190:\t\t\tkvm_arch_gmem_invalidate_range(kvm, \u0026gfn_range);\n 191:\t#endif\n 192:\t\t}\n 193:\t\n 194:\t\tif (flush)\n 195:\t\t\tkvm_flush_remote_tlbs(kvm);\n 196:\t\n 197:\t\tif (found_memslot)\n 198:\t\t\tKVM_MMU_UNLOCK(kvm);\n 199:\t}\n"
} |
| 37/2 | 2026/06/25 22:40 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 40858 output: 251 thoughts: 404 Thoughts: **My Assessment of the KVM SEV-SNP Patch's Fuzzing Potential** Okay, so `kvm_arch_gmem_invalidate_range` is definitely a key function here, called directly from `__kvm_gmem_invalidate_start`. This makes it reachable and, critically, testable. Good. Let's break down the implications of this patch and summarize what we've got. The `WorthFuzzing` flag is set to `true`, which is what I suspected. The `FocusSymbols` are: - `__sev_snp_reload_vmsa` - `sev_snp_reload_vmsa` - `sev_gmem_invalidate_range` - `sev_gmem_free_folio` - `kvm_arch_gmem_invalidate_range` - `kvm_arch_gmem_free_folio` - `sev_snp_init_protected_guest_state` And the `EnableConfigs`: - `KVM_AMD_SEV` - `KVM_AMD` - `KVM` - `KVM_SW_PROTECTED_VM` The reasoning behind this is solid. The patch directly modifies KVM's AMD SEV-SNP VMSA handling and guest\_memfd invalidation. It's touching core KVM functionality, introducing new functions to reload VMSA pages when the guest\_memfd is invalidated. This invalidation can happen through operations like `fallocate punch hole`, and these changes affect the architecture-specific callbacks. This is *reachable* from userspace via KVM ioctls and guest\_memfd operations. Therefore, fuzzing is an ideal way to exercise this code. A slight concern—do I include `KVM_SW_PROTECTED_VM`? I think it might be worth it. It could potentially help syzkaller fuzz `guest_memfd` without necessarily needing SEV-SNP hardware present. Yes, the specific SEV-SNP callbacks won't trigger in that scenario, but the patch also modifies generic KVM code like `kvm_arch_gmem_invalidate_range` and `kvm_arch_gmem_free_folio`. So, it's a good coverage enhancement. Alright, with that assessment complete, time to call the set-results tool and move on. |
| 38/2 | 2026/06/25 22:40 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"KVM_AMD_SEV",
"KVM_AMD",
"KVM",
"KVM_SW_PROTECTED_VM"
],
"FocusSymbols": [
"__sev_snp_reload_vmsa",
"sev_snp_reload_vmsa",
"sev_gmem_invalidate_range",
"sev_gmem_free_folio",
"kvm_arch_gmem_invalidate_range",
"kvm_arch_gmem_free_folio",
"sev_snp_init_protected_guest_state"
],
"Reasoning": "The patch modifies KVM's handling of AMD SEV-SNP VMSA (Virtual Machine Save Area) and guest_memfd invalidation. It introduces new functions to reload VMSA pages when the backing guest_memfd is invalidated (e.g., via fallocate punch hole) and changes the architecture-specific guest_memfd invalidation callbacks. This is functional core KVM code that is reachable from userspace via KVM ioctls and guest_memfd operations.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"KVM_AMD_SEV",
"KVM_AMD",
"KVM",
"KVM_SW_PROTECTED_VM"
],
"FocusSymbols": [
"__sev_snp_reload_vmsa",
"sev_snp_reload_vmsa",
"sev_gmem_invalidate_range",
"sev_gmem_free_folio",
"kvm_arch_gmem_invalidate_range",
"kvm_arch_gmem_free_folio",
"sev_snp_init_protected_guest_state"
],
"Reasoning": "The patch modifies KVM's handling of AMD SEV-SNP VMSA (Virtual Machine Save Area) and guest_memfd invalidation. It introduces new functions to reload VMSA pages when the backing guest_memfd is invalidated (e.g., via fallocate punch hole) and changes the architecture-specific guest_memfd invalidation callbacks. This is functional core KVM code that is reachable from userspace via KVM ioctls and guest_memfd operations.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|