| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/15 07:55 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"KVM_AMD_SEV"
],
"FocusSymbols": [
"kvm_gmem_make_private",
"kvm_gmem_free_folio",
"sev_gmem_convert",
"sev_gmem_make_private",
"sev_gmem_make_shared",
"kvm_arch_gmem_convert",
"kvm_arch_gmem_reclaim"
],
"Reasoning": "The patch modifies the KVM guest_memfd and AMD SEV code to support converting memory between private and shared states, and reclaiming private memory. It introduces new architecture hooks `gmem_convert` and `gmem_reclaim` and updates the SEV implementation to use them. These are functional changes to core KVM and SEV logic that should be fuzzed to ensure memory isolation and correctness.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/15 07:55 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 02d2eac97fd14fc698d52c79ecc902e4c3d0f10d\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Jul 15 07:55:57 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 736129db272abc..1764bad03b17b5 100644\n--- a/arch/x86/include/asm/kvm-x86-ops.h\n+++ b/arch/x86/include/asm/kvm-x86-ops.h\n@@ -146,10 +146,9 @@ 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+#if defined(CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT) || defined(CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM)\n+KVM_X86_OP_OPTIONAL_RET0(gmem_convert)\n #endif\n-KVM_X86_OP_OPTIONAL(gmem_invalidate)\n #ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n KVM_X86_OP_OPTIONAL(gmem_invalidate_range)\n #endif\ndiff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h\nindex 58f156ae31e750..08c4af487fa110 100644\n--- a/arch/x86/include/asm/kvm_host.h\n+++ b/arch/x86/include/asm/kvm_host.h\n@@ -1724,10 +1724,10 @@ 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+#if defined(CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT) || defined(CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM)\n+\tint (*gmem_convert)(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\n+\t\t\t kvm_pfn_t nr_pages, int max_order, bool to_private);\n #endif\n-\tvoid (*gmem_invalidate)(kvm_pfn_t start, kvm_pfn_t end);\n #ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n \tvoid (*gmem_invalidate_range)(struct kvm *kvm, struct kvm_gfn_range *range);\n #endif\ndiff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig\nindex 801bf9e520db33..538ed1e8033268 100644\n--- a/arch/x86/kvm/Kconfig\n+++ b/arch/x86/kvm/Kconfig\n@@ -160,7 +160,8 @@ config KVM_AMD_SEV\n \tdepends on CRYPTO_DEV_SP_PSP \u0026\u0026 !(KVM_AMD=y \u0026\u0026 CRYPTO_DEV_CCP_DD=m)\n \tselect ARCH_HAS_CC_PLATFORM\n \tselect KVM_GENERIC_MEMORY_ATTRIBUTES\n-\tselect HAVE_KVM_ARCH_GMEM_PREPARE\n+\tselect HAVE_KVM_ARCH_GMEM_CONVERT\n+\tselect HAVE_KVM_ARCH_GMEM_RECLAIM\n \tselect HAVE_KVM_ARCH_GMEM_INVALIDATE\n \tselect HAVE_KVM_ARCH_GMEM_POPULATE\n \thelp\ndiff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c\nindex 82b983484af208..b00623b2f26ac1 100644\n--- a/arch/x86/kvm/svm/sev.c\n+++ b/arch/x86/kvm/svm/sev.c\n@@ -5114,7 +5114,8 @@ static bool is_large_rmp_possible(struct kvm *kvm, kvm_pfn_t pfn, int order)\n \treturn false;\n }\n \n-int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order)\n+static int sev_gmem_make_private(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\n+\t\t\t\t kvm_pfn_t nr_pages, int max_order)\n {\n \tstruct kvm_sev_info *sev = to_kvm_sev_info(kvm);\n \tkvm_pfn_t pfn_aligned;\n@@ -5125,6 +5126,9 @@ int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order)\n \tif (!sev_snp_guest(kvm))\n \t\treturn 0;\n \n+\tif (WARN_ON_ONCE(nr_pages != 1))\n+\t\treturn -EIO;\n+\n \trc = snp_lookup_rmpentry(pfn, \u0026assigned, \u0026level);\n \tif (rc) {\n \t\tpr_err_ratelimited(\"SEV: Failed to look up RMP entry: GFN %llx PFN %llx error %d\\n\",\n@@ -5161,8 +5165,9 @@ int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order)\n \treturn 0;\n }\n \n-void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)\n+static void sev_gmem_make_shared(kvm_pfn_t start, kvm_pfn_t nr_pages)\n {\n+\tkvm_pfn_t end = start + nr_pages;\n \tkvm_pfn_t pfn;\n \n \tif (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))\n@@ -5224,6 +5229,20 @@ void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)\n \t}\n }\n \n+int sev_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\n+\t\t kvm_pfn_t nr_pages, int order, bool to_private)\n+{\n+\tif (to_private) {\n+\t\tif (WARN_ON_ONCE(!kvm || gfn \u003e\u003e (kvm_host.maxphyaddr - PAGE_SHIFT)))\n+\t\t\treturn -EIO;\n+\n+\t\treturn sev_gmem_make_private(kvm, gfn, pfn, nr_pages, order);\n+\t}\n+\n+\tsev_gmem_make_shared(pfn, nr_pages);\n+\treturn 0;\n+}\n+\n void sev_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range)\n {\n \tstruct kvm_vcpu *vcpu;\ndiff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c\nindex 91286d46d13adb..8c5018c65dc5e0 100644\n--- a/arch/x86/kvm/svm/svm.c\n+++ b/arch/x86/kvm/svm/svm.c\n@@ -5438,8 +5438,7 @@ struct kvm_x86_ops svm_x86_ops __initdata = {\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 \n-\t.gmem_prepare = sev_gmem_prepare,\n-\t.gmem_invalidate = sev_gmem_invalidate,\n+\t.gmem_convert = sev_gmem_convert,\n \t.gmem_invalidate_range = sev_gmem_invalidate_range,\n \t.gmem_max_mapping_level = sev_gmem_max_mapping_level,\n #endif\ndiff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h\nindex af25e4b5621270..57f692b5d7090c 100644\n--- a/arch/x86/kvm/svm/svm.h\n+++ b/arch/x86/kvm/svm/svm.h\n@@ -1009,8 +1009,8 @@ int sev_cpu_init(struct svm_cpu_data *sd);\n 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+int sev_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\n+\t\t kvm_pfn_t nr_pages, int max_order, bool to_private);\n void sev_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range);\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);\ndiff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c\nindex 1f5dc685f0490d..11017f49b94a0c 100644\n--- a/arch/x86/kvm/x86.c\n+++ b/arch/x86/kvm/x86.c\n@@ -10619,18 +10619,22 @@ bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm)\n \treturn !kvm_arch_has_private_mem(kvm);\n }\n \n-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE\n-int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_order)\n+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT\n+int kvm_arch_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\n+\t\t\t kvm_pfn_t nr_pages, int max_order, bool to_private)\n {\n-\treturn kvm_x86_call(gmem_prepare)(kvm, pfn, gfn, max_order);\n+\treturn kvm_x86_call(gmem_convert)(kvm, gfn, pfn, nr_pages, max_order, to_private);\n }\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+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM\n+void kvm_arch_gmem_reclaim(kvm_pfn_t pfn, kvm_pfn_t nr_pages, int max_order)\n {\n-\tkvm_x86_call(gmem_invalidate)(start, end);\n+\tWARN_ON_ONCE(kvm_x86_call(gmem_convert)(NULL, -1ull, pfn, nr_pages, max_order, false));\n }\n+#endif\n+\n+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE\n void kvm_arch_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range)\n {\n \tkvm_x86_call(gmem_invalidate_range)(kvm, range);\ndiff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h\nindex 9db6eb4023c48f..fdbd697d033751 100644\n--- a/include/linux/kvm_host.h\n+++ b/include/linux/kvm_host.h\n@@ -2579,8 +2579,9 @@ static inline int kvm_gmem_get_pfn(struct kvm *kvm,\n }\n #endif /* CONFIG_KVM_GUEST_MEMFD */\n \n-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE\n-int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_order);\n+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT\n+int kvm_arch_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\n+\t\t\t kvm_pfn_t nr_pages, int max_order, bool to_private);\n #endif\n \n #ifdef CONFIG_HAVE_KVM_ARCH_GMEM_POPULATE\n@@ -2613,8 +2614,11 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src,\n \t\t kvm_gmem_populate_cb post_populate, void *opaque);\n #endif\n \n+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM\n+void kvm_arch_gmem_reclaim(kvm_pfn_t pfn, kvm_pfn_t nr_pages, int order);\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 #endif\n \ndiff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig\nindex 794976b88c6f97..c3c0ee253fc77c 100644\n--- a/virt/kvm/Kconfig\n+++ b/virt/kvm/Kconfig\n@@ -107,7 +107,11 @@ config KVM_GUEST_MEMFD\n select XARRAY_MULTI\n bool\n \n-config HAVE_KVM_ARCH_GMEM_PREPARE\n+config HAVE_KVM_ARCH_GMEM_CONVERT\n+ bool\n+ depends on KVM_GUEST_MEMFD\n+\n+config HAVE_KVM_ARCH_GMEM_RECLAIM\n bool\n depends on KVM_GUEST_MEMFD\n \ndiff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c\nindex 171a9da1b6855d..173a7ed008d179 100644\n--- a/virt/kvm/guest_memfd.c\n+++ b/virt/kvm/guest_memfd.c\n@@ -60,32 +60,17 @@ static pgoff_t kvm_gmem_get_index(struct kvm_memory_slot *slot, gfn_t gfn)\n \treturn gfn - slot-\u003ebase_gfn + slot-\u003egmem.pgoff;\n }\n \n-static int __kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slot,\n-\t\t\t\t pgoff_t index, struct folio *folio)\n-{\n-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE\n-\tkvm_pfn_t pfn = folio_file_pfn(folio, index);\n-\tgfn_t gfn = slot-\u003ebase_gfn + index - slot-\u003egmem.pgoff;\n-\tint rc = kvm_arch_gmem_prepare(kvm, gfn, pfn, folio_order(folio));\n-\tif (rc) {\n-\t\tpr_warn_ratelimited(\"gmem: Failed to prepare folio for index %lx GFN %llx PFN %llx error %d.\\n\",\n-\t\t\t\t index, gfn, pfn, rc);\n-\t\treturn rc;\n-\t}\n-#endif\n-\n-\treturn 0;\n-}\n-\n /*\n * Process @folio, which contains @gfn, so that the guest can use it.\n * The folio must be locked and the gfn must be contained in @slot.\n * On successful return the guest sees a zero page so as to avoid\n * leaking host data and the up-to-date flag is set.\n */\n-static int kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slot,\n-\t\t\t\t gfn_t gfn, struct folio *folio)\n+static int kvm_gmem_make_private(struct kvm *kvm, struct kvm_memory_slot *slot,\n+\t\t\t\t gfn_t gfn, struct folio *folio)\n {\n+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT\n+\tunsigned long nr_pages = folio_nr_pages(folio);\n \tpgoff_t index;\n \n \t/*\n@@ -101,11 +86,15 @@ static int kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slot,\n \t * The order will be passed when creating the guest_memfd, and\n \t * checked when creating memslots.\n \t */\n-\tWARN_ON(!IS_ALIGNED(slot-\u003egmem.pgoff, folio_nr_pages(folio)));\n+\tWARN_ON_ONCE(!IS_ALIGNED(slot-\u003egmem.pgoff, nr_pages));\n+\tgfn = ALIGN_DOWN(gfn, nr_pages);\n \tindex = kvm_gmem_get_index(slot, gfn);\n-\tindex = ALIGN_DOWN(index, folio_nr_pages(folio));\n \n-\treturn __kvm_gmem_prepare_folio(kvm, slot, index, folio);\n+\treturn kvm_arch_gmem_convert(kvm, gfn, folio_file_pfn(folio, index),\n+\t\t\t\t nr_pages, folio_order(folio), true);\n+#else\n+\treturn 0;\n+#endif\n }\n \n /*\n@@ -527,14 +516,11 @@ 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+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM\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+\tkvm_arch_gmem_reclaim(folio_file_pfn(folio, 0), folio_nr_pages(folio),\n+\t\t\t folio_order(folio));\n }\n #endif\n \n@@ -542,7 +528,7 @@ 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+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM\n \t.free_folio = kvm_gmem_free_folio,\n #endif\n };\n@@ -812,7 +798,7 @@ int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,\n \t\tfolio_mark_uptodate(folio);\n \t}\n \n-\tr = kvm_gmem_prepare_folio(kvm, slot, gfn, folio);\n+\tr = kvm_gmem_make_private(kvm, slot, gfn, folio);\n \n \tfolio_unlock(folio);\n \n"
} |
| 2/1 | 2026/07/15 07:55 | agent | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"KVM_AMD_SEV"
],
"FocusSymbols": [
"kvm_gmem_make_private",
"kvm_gmem_free_folio",
"sev_gmem_convert",
"sev_gmem_make_private",
"sev_gmem_make_shared",
"kvm_arch_gmem_convert",
"kvm_arch_gmem_reclaim"
],
"Reasoning": "The patch modifies the KVM guest_memfd and AMD SEV code to support converting memory between private and shared states, and reclaiming private memory. It introduces new architecture hooks `gmem_convert` and `gmem_reclaim` and updates the SEV implementation to use them. These are functional changes to core KVM and SEV logic that should be fuzzed to ensure memory isolation and correctness.",
"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 02d2eac97fd14fc698d52c79ecc902e4c3d0f10d
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Jul 15 07:55:57 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 736129db272abc..1764bad03b17b5 100644
--- a/arch/x86/include/asm/kvm-x86-ops.h
+++ b/arch/x86/include/asm/kvm-x86-ops.h
@@ -146,10 +146,9 @@ 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)
+#if defined(CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT) || defined(CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM)
+KVM_X86_OP_OPTIONAL_RET0(gmem_convert)
#endif
-KVM_X86_OP_OPTIONAL(gmem_invalidate)
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
KVM_X86_OP_OPTIONAL(gmem_invalidate_range)
#endif
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 58f156ae31e750..08c4af487fa110 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1724,10 +1724,10 @@ 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);
+#if defined(CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT) || defined(CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM)
+ int (*gmem_convert)(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
+ kvm_pfn_t nr_pages, int max_order, bool to_private);
#endif
- void (*gmem_invalidate)(kvm_pfn_t start, kvm_pfn_t end);
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
void (*gmem_invalidate_range)(struct kvm *kvm, struct kvm_gfn_range *range);
#endif
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 801bf9e520db33..538ed1e8033268 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -160,7 +160,8 @@ config KVM_AMD_SEV
depends on CRYPTO_DEV_SP_PSP && !(KVM_AMD=y && CRYPTO_DEV_CCP_DD=m)
select ARCH_HAS_CC_PLATFORM
select KVM_GENERIC_MEMORY_ATTRIBUTES
- select HAVE_KVM_ARCH_GMEM_PREPARE
+ select HAVE_KVM_ARCH_GMEM_CONVERT
+ select HAVE_KVM_ARCH_GMEM_RECLAIM
select HAVE_KVM_ARCH_GMEM_INVALIDATE
select HAVE_KVM_ARCH_GMEM_POPULATE
help
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 82b983484af208..b00623b2f26ac1 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -5114,7 +5114,8 @@ static bool is_large_rmp_possible(struct kvm *kvm, kvm_pfn_t pfn, int order)
return false;
}
-int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order)
+static int sev_gmem_make_private(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
+ kvm_pfn_t nr_pages, int max_order)
{
struct kvm_sev_info *sev = to_kvm_sev_info(kvm);
kvm_pfn_t pfn_aligned;
@@ -5125,6 +5126,9 @@ int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order)
if (!sev_snp_guest(kvm))
return 0;
+ if (WARN_ON_ONCE(nr_pages != 1))
+ return -EIO;
+
rc = snp_lookup_rmpentry(pfn, &assigned, &level);
if (rc) {
pr_err_ratelimited("SEV: Failed to look up RMP entry: GFN %llx PFN %llx error %d\n",
@@ -5161,8 +5165,9 @@ int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order)
return 0;
}
-void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)
+static void sev_gmem_make_shared(kvm_pfn_t start, kvm_pfn_t nr_pages)
{
+ kvm_pfn_t end = start + nr_pages;
kvm_pfn_t pfn;
if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP))
@@ -5224,6 +5229,20 @@ void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)
}
}
+int sev_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
+ kvm_pfn_t nr_pages, int order, bool to_private)
+{
+ if (to_private) {
+ if (WARN_ON_ONCE(!kvm || gfn >> (kvm_host.maxphyaddr - PAGE_SHIFT)))
+ return -EIO;
+
+ return sev_gmem_make_private(kvm, gfn, pfn, nr_pages, order);
+ }
+
+ sev_gmem_make_shared(pfn, nr_pages);
+ return 0;
+}
+
void sev_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range)
{
struct kvm_vcpu *vcpu;
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 91286d46d13adb..8c5018c65dc5e0 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5438,8 +5438,7 @@ struct kvm_x86_ops svm_x86_ops __initdata = {
.vm_copy_enc_context_from = sev_vm_copy_enc_context_from,
.vm_move_enc_context_from = sev_vm_move_enc_context_from,
- .gmem_prepare = sev_gmem_prepare,
- .gmem_invalidate = sev_gmem_invalidate,
+ .gmem_convert = sev_gmem_convert,
.gmem_invalidate_range = sev_gmem_invalidate_range,
.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 af25e4b5621270..57f692b5d7090c 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -1009,8 +1009,8 @@ int sev_cpu_init(struct svm_cpu_data *sd);
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);
+int sev_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
+ kvm_pfn_t nr_pages, int max_order, bool to_private);
void sev_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range);
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);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 1f5dc685f0490d..11017f49b94a0c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10619,18 +10619,22 @@ bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm)
return !kvm_arch_has_private_mem(kvm);
}
-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE
-int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_order)
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
+int kvm_arch_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
+ kvm_pfn_t nr_pages, int max_order, bool to_private)
{
- return kvm_x86_call(gmem_prepare)(kvm, pfn, gfn, max_order);
+ return kvm_x86_call(gmem_convert)(kvm, gfn, pfn, nr_pages, max_order, to_private);
}
#endif
-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
-void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
+void kvm_arch_gmem_reclaim(kvm_pfn_t pfn, kvm_pfn_t nr_pages, int max_order)
{
- kvm_x86_call(gmem_invalidate)(start, end);
+ WARN_ON_ONCE(kvm_x86_call(gmem_convert)(NULL, -1ull, pfn, nr_pages, max_order, false));
}
+#endif
+
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
void kvm_arch_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range)
{
kvm_x86_call(gmem_invalidate_range)(kvm, range);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 9db6eb4023c48f..fdbd697d033751 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -2579,8 +2579,9 @@ static inline int kvm_gmem_get_pfn(struct kvm *kvm,
}
#endif /* CONFIG_KVM_GUEST_MEMFD */
-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE
-int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_order);
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
+int kvm_arch_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
+ kvm_pfn_t nr_pages, int max_order, bool to_private);
#endif
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_POPULATE
@@ -2613,8 +2614,11 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src,
kvm_gmem_populate_cb post_populate, void *opaque);
#endif
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
+void kvm_arch_gmem_reclaim(kvm_pfn_t pfn, kvm_pfn_t nr_pages, int order);
+#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);
#endif
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index 794976b88c6f97..c3c0ee253fc77c 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -107,7 +107,11 @@ config KVM_GUEST_MEMFD
select XARRAY_MULTI
bool
-config HAVE_KVM_ARCH_GMEM_PREPARE
+config HAVE_KVM_ARCH_GMEM_CONVERT
+ bool
+ depends on KVM_GUEST_MEMFD
+
+config HAVE_KVM_ARCH_GMEM_RECLAIM
bool
depends on KVM_GUEST_MEMFD
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 171a9da1b6855d..173a7ed008d179 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -60,32 +60,17 @@ static pgoff_t kvm_gmem_get_index(struct kvm_memory_slot *slot, gfn_t gfn)
return gfn - slot->base_gfn + slot->gmem.pgoff;
}
-static int __kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slot,
- pgoff_t index, struct folio *folio)
-{
-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE
- kvm_pfn_t pfn = folio_file_pfn(folio, index);
- gfn_t gfn = slot->base_gfn + index - slot->gmem.pgoff;
- int rc = kvm_arch_gmem_prepare(kvm, gfn, pfn, folio_order(folio));
- if (rc) {
- pr_warn_ratelimited("gmem: Failed to prepare folio for index %lx GFN %llx PFN %llx error %d.\n",
- index, gfn, pfn, rc);
- return rc;
- }
-#endif
-
- return 0;
-}
-
/*
* Process @folio, which contains @gfn, so that the guest can use it.
* The folio must be locked and the gfn must be contained in @slot.
* On successful return the guest sees a zero page so as to avoid
* leaking host data and the up-to-date flag is set.
*/
-static int kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slot,
- gfn_t gfn, struct folio *folio)
+static int kvm_gmem_make_private(struct kvm *kvm, struct kvm_memory_slot *slot,
+ gfn_t gfn, struct folio *folio)
{
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
+ unsigned long nr_pages = folio_nr_pages(folio);
pgoff_t index;
/*
@@ -101,11 +86,15 @@ static int kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slot,
* The order will be passed when creating the guest_memfd, and
* checked when creating memslots.
*/
- WARN_ON(!IS_ALIGNED(slot->gmem.pgoff, folio_nr_pages(folio)));
+ WARN_ON_ONCE(!IS_ALIGNED(slot->gmem.pgoff, nr_pages));
+ gfn = ALIGN_DOWN(gfn, nr_pages);
index = kvm_gmem_get_index(slot, gfn);
- index = ALIGN_DOWN(index, folio_nr_pages(folio));
- return __kvm_gmem_prepare_folio(kvm, slot, index, folio);
+ return kvm_arch_gmem_convert(kvm, gfn, folio_file_pfn(folio, index),
+ nr_pages, folio_order(folio), true);
+#else
+ return 0;
+#endif
}
/*
@@ -527,14 +516,11 @@ static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *fol
return MF_DELAYED;
}
-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
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));
+ kvm_arch_gmem_reclaim(folio_file_pfn(folio, 0), folio_nr_pages(folio),
+ folio_order(folio));
}
#endif
@@ -542,7 +528,7 @@ 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
+#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
.free_folio = kvm_gmem_free_folio,
#endif
};
@@ -812,7 +798,7 @@ int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
folio_mark_uptodate(folio);
}
- r = kvm_gmem_prepare_folio(kvm, slot, gfn, folio);
+ r = kvm_gmem_make_private(kvm, slot, gfn, folio);
folio_unlock(folio);
|
| 3/2 | 2026/07/15 07:55 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7215 output: 22 thoughts: 435 Thoughts: **Analyzing a KVM Patch for Guest Memory Management and SEV** Okay, so I'm looking at this patch and immediately, the refactoring catches my eye. We're renaming `gmem_prepare` to `gmem_convert` and `gmem_invalidate` to `gmem_reclaim` within the architecture-specific KVM hooks, which is a sensible move for clarity. This is also changing `kvm_gmem_prepare_folio` to `kvm_gmem_make_private` and making `kvm_gmem_free_folio` use `kvm_arch_gmem_reclaim`, which are potentially more descriptive names. The introduction of `HAVE_KVM_ARCH_GMEM_CONVERT` and `HAVE_KVM_ARCH_GMEM_RECLAIM` are standard flags that suggest the architecture-specific code has been enabled properly. Now, the important question: is this code path actually touched, and does it work? I see it modifies `virt/kvm/guest_memfd.c`, which is the implementation for `KVM_GUEST_MEMFD`, and it also changes `arch/x86/kvm/svm/sev.c`, which, of course, handles the AMD SEV implementation. Given that it touches both `guest_memfd` and SEV, this is definitely something we need to be careful with. Is it worth fuzzing? Absolutely, because we're talking core logic regarding guest memory and the secure virtualization components. I need to nail down the key functions. Let's focus on these specific ones: `kvm_gmem_make_private`, `kvm_gmem_free_folio`, `sev_gmem_convert`, `sev_gmem_make_private`, `sev_gmem_make_shared`, `kvm_arch_gmem_convert`, and `kvm_arch_gmem_reclaim`. Those are the entry points and the crucial operations, it seems. Next, I have to check the configurations, so that's where `KVM_GUEST_MEMFD` is. It looks like `KVM_AMD_SEV` or `KVM_SW_PROTECTED_VM` select it. Now, to make sure those are properly configured, I need to check `arch/x86/kvm/Kconfig` to see the details for those. |
| 4/2 | 2026/07/15 07:56 | 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/07/15 07:56 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8303 output: 24 thoughts: 15 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience, presented in the first person: **Investigating `KVM_SW_PROTECTED_VM`** Alright, let's dive into this `KVM_SW_PROTECTED_VM` concept. My first instinct is to immediately refresh my understanding of how this software-based protection mechanism interacts with the hardware virtualization extensions. What exactly is the goal here? Is it intended to provide an alternative or augmentation to hardware-based security features, or a fallback for when those are unavailable or compromised? I need to understand the nuances of the implementation. Is this implemented purely in the guest kernel, the host kernel, or a hybrid approach? What are the performance implications? I'm already mentally running through potential bottlenecks: trap and emulation overhead, memory access patterns, and the associated context switching penalties. Furthermore, I'm considering the security model. What attack surface does this introduce? Does it protect against specific classes of vulnerabilities, such as side-channel attacks, or is it more of a general defense-in-depth measure? I'm thinking about potential issues with the trusted computing base. If this relies on software, how is it verified? How is it protected against malicious modification? My next step would be to look at the source code – I need to see the precise mechanics. I'll focus on the data structures, the control flow, and any cryptographic primitives involved. That's the only way to gain a true grasp of its effectiveness and potential weaknesses. I need to know how it actually _works_ to evaluate its utility. |
| 6/2 | 2026/07/15 07:56 | 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"
} |
| 7/2 | 2026/07/15 07:56 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8783 output: 23 thoughts: 79 Thoughts: Okay, here's my understanding, thinking through this code change. **Analyzing the Patch's Scope** Alright, so the patch is clearly touching a couple of specific files: `arch/x86/kvm/svm/sev.c` and `virt/kvm/guest_memfd.c`. The first one, `sev.c`, is immediately interesting because it lives under the `arch/x86/kvm/svm` directory. That strongly suggests it's dealing with AMD's Secure Encrypted Virtualization (SEV) features within KVM on x86 architectures. And indeed, the code there depends on `KVM_AMD_SEV`. So, I'm already anticipating some potential interactions with SEV-specific encryption or memory handling. The second file, `guest_memfd.c`, is in the `virt/kvm` directory and is dependent on `KVM_GUEST_MEMFD`. `memfd` is an interesting system call, and its use in the guest context is something I need to keep an eye on. I should probably quickly check what configurations select `KVM_GUEST_MEMFD`. That'll help me understand the broader context of what this patch is likely aimed at improving or enabling. |
| 8/2 | 2026/07/15 07:56 | 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"
} |
| 9/2 | 2026/07/15 07:56 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9365 output: 81 thoughts: 267 Thoughts: **Analyzing KVM and AMD SEV Configuration** Okay, so it looks like `KVM_GUEST_MEMFD` gets auto-selected via `KVM_X86` if we're on `X86_64`, which makes sense. So, it should be enabled by default on 64-bit x86 systems. But this patch is touching `KVM_AMD_SEV` which, as I recall, handles AMD Secure Encrypted Virtualization support. Right. So, the logical next step is to ensure that `KVM_AMD_SEV` is enabled. Hang on... I should confirm if `KVM_AMD` is a prerequisite. Yep, `KVM_AMD_SEV` explicitly depends on `KVM_AMD`. Good, good. I need to make a mental note to confirm both `KVM_AMD` and `KVM_AMD_SEV` are configured correctly. And... wait, let me add `KVM_SW_PROTECTED_VM` to the list of configs to check. Alright, now that I have the configurations sorted, I need to focus on the key functions involved in this area. Specifically, I'm interested in: * `kvm_gmem_make_private` * `kvm_gmem_free_folio` * `sev_gmem_convert` * `sev_gmem_make_private` * `sev_gmem_make_shared` * `kvm_arch_gmem_convert` * `kvm_arch_gmem_reclaim` These seem to be the core functions for memory management within the SEV context. I need to verify their existence in the code base. Now, to the code! |
| 10/2 | 2026/07/15 07:56 | tool | grepper |
0mArgs:{
"Expression": "(kvm_gmem_make_private|kvm_gmem_free_folio|sev_gmem_convert|sev_gmem_make_private|sev_gmem_make_shared|kvm_arch_gmem_convert|kvm_arch_gmem_reclaim)"
}Results: {
"Output": "arch/x86/kvm/svm/sev.c=5101=static bool is_large_rmp_possible(struct kvm *kvm, kvm_pfn_t pfn, int order)\n--\narch/x86/kvm/svm/sev.c-5116-\narch/x86/kvm/svm/sev.c:5117:static int sev_gmem_make_private(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\narch/x86/kvm/svm/sev.c-5118-\t\t\t\t kvm_pfn_t nr_pages, int max_order)\n--\narch/x86/kvm/svm/sev.c-5167-\narch/x86/kvm/svm/sev.c:5168:static void sev_gmem_make_shared(kvm_pfn_t start, kvm_pfn_t nr_pages)\narch/x86/kvm/svm/sev.c-5169-{\n--\narch/x86/kvm/svm/sev.c-5231-\narch/x86/kvm/svm/sev.c:5232:int sev_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\narch/x86/kvm/svm/sev.c-5233-\t\t kvm_pfn_t nr_pages, int order, bool to_private)\n--\narch/x86/kvm/svm/sev.c-5238-\narch/x86/kvm/svm/sev.c:5239:\t\treturn sev_gmem_make_private(kvm, gfn, pfn, nr_pages, order);\narch/x86/kvm/svm/sev.c-5240-\t}\narch/x86/kvm/svm/sev.c-5241-\narch/x86/kvm/svm/sev.c:5242:\tsev_gmem_make_shared(pfn, nr_pages);\narch/x86/kvm/svm/sev.c-5243-\treturn 0;\n--\narch/x86/kvm/svm/svm.c=5314=struct kvm_x86_ops svm_x86_ops __initdata = {\n--\narch/x86/kvm/svm/svm.c-5440-\narch/x86/kvm/svm/svm.c:5441:\t.gmem_convert = sev_gmem_convert,\narch/x86/kvm/svm/svm.c-5442-\t.gmem_invalidate_range = sev_gmem_invalidate_range,\n--\narch/x86/kvm/svm/svm.h=1011=void sev_handle_rmp_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code);\narch/x86/kvm/svm/svm.h:1012:int sev_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\narch/x86/kvm/svm/svm.h-1013-\t\t kvm_pfn_t nr_pages, int max_order, bool to_private);\n--\narch/x86/kvm/x86.c=10617=bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm)\n--\narch/x86/kvm/x86.c-10622-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT\narch/x86/kvm/x86.c:10623:int kvm_arch_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\narch/x86/kvm/x86.c-10624-\t\t\t kvm_pfn_t nr_pages, int max_order, bool to_private)\n--\narch/x86/kvm/x86.c-10630-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM\narch/x86/kvm/x86.c:10631:void kvm_arch_gmem_reclaim(kvm_pfn_t pfn, kvm_pfn_t nr_pages, int max_order)\narch/x86/kvm/x86.c-10632-{\n--\ninclude/linux/kvm_host.h=2572=static inline int kvm_gmem_get_pfn(struct kvm *kvm,\n--\ninclude/linux/kvm_host.h-2582-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT\ninclude/linux/kvm_host.h:2583:int kvm_arch_gmem_convert(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,\ninclude/linux/kvm_host.h-2584-\t\t\t kvm_pfn_t nr_pages, int max_order, bool to_private);\n--\ninclude/linux/kvm_host.h=2612=long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src,\n--\ninclude/linux/kvm_host.h-2617-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM\ninclude/linux/kvm_host.h:2618:void kvm_arch_gmem_reclaim(kvm_pfn_t pfn, kvm_pfn_t nr_pages, int order);\ninclude/linux/kvm_host.h-2619-#endif\n--\nvirt/kvm/guest_memfd.c=58=static pgoff_t kvm_gmem_get_index(struct kvm_memory_slot *slot, gfn_t gfn)\n--\nvirt/kvm/guest_memfd.c-68- */\nvirt/kvm/guest_memfd.c:69:static int kvm_gmem_make_private(struct kvm *kvm, struct kvm_memory_slot *slot,\nvirt/kvm/guest_memfd.c-70-\t\t\t\t gfn_t gfn, struct folio *folio)\n--\nvirt/kvm/guest_memfd.c-92-\nvirt/kvm/guest_memfd.c:93:\treturn kvm_arch_gmem_convert(kvm, gfn, folio_file_pfn(folio, index),\nvirt/kvm/guest_memfd.c-94-\t\t\t\t nr_pages, folio_order(folio), true);\n--\nvirt/kvm/guest_memfd.c=492=static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *folio)\n--\nvirt/kvm/guest_memfd.c-519-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM\nvirt/kvm/guest_memfd.c:520:static void kvm_gmem_free_folio(struct folio *folio)\nvirt/kvm/guest_memfd.c-521-{\nvirt/kvm/guest_memfd.c:522:\tkvm_arch_gmem_reclaim(folio_file_pfn(folio, 0), folio_nr_pages(folio),\nvirt/kvm/guest_memfd.c-523-\t\t\t folio_order(folio));\n--\nvirt/kvm/guest_memfd.c=527=static const struct address_space_operations kvm_gmem_aops = {\n--\nvirt/kvm/guest_memfd.c-531-#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM\nvirt/kvm/guest_memfd.c:532:\t.free_folio = kvm_gmem_free_folio,\nvirt/kvm/guest_memfd.c-533-#endif\n--\nvirt/kvm/guest_memfd.c=780=int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,\n--\nvirt/kvm/guest_memfd.c-800-\nvirt/kvm/guest_memfd.c:801:\tr = kvm_gmem_make_private(kvm, slot, gfn, folio);\nvirt/kvm/guest_memfd.c-802-\n"
} |
| 11/2 | 2026/07/15 07:56 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12289 output: 203 thoughts: 820 Thoughts: **Analysis of KVM Guest Memory Management for Fuzzing** Okay, so I've looked over this and my initial thought is that the functions listed are definitely reachable and appear to be functional. Let's get right down to it. We need to focus on these symbols: `kvm_gmem_make_private`, `kvm_gmem_free_folio`, `sev_gmem_convert`, `sev_gmem_make_private`, `sev_gmem_make_shared`, `kvm_arch_gmem_convert`, and `kvm_arch_gmem_reclaim`. Now, regarding configurations, it looks like `KVM_AMD_SEV` is the key. While `KVM_GUEST_MEMFD` is also relevant, it's enabled by `KVM_X86` if `X86_64`, but primarily through `KVM_AMD_SEV`. So, let's stick with `KVM_AMD_SEV` as the core configuration to enable the SEV-specific code. Checking dependencies, `KVM_AMD_SEV` depends on `CRYPTO_DEV_SP_PSP` and `!(KVM_AMD=y && CRYPTO_DEV_CCP_DD=m)`. No need to list all of those dependencies here. `KVM_AMD_SEV` does the trick. I've also confirmed that `HAVE_KVM_ARCH_GMEM_CONVERT` and `HAVE_KVM_ARCH_GMEM_RECLAIM` are selected by `KVM_AMD_SEV`, which reinforces that it's the right config. Now, let's revisit those focus symbols and assess their hot-path status. `kvm_gmem_make_private` gets called when getting a pfn for a `guest_memfd`. That's page faults or memory population, so not a super hot path like the VMEXIT handler, but it's per page, so still relevant. `kvm_gmem_free_folio` is called when a folio is freed during memory reclaim or destruction. Then, `sev_gmem_convert` is called from `kvm_gmem_make_private` and `kvm_gmem_free_folio`, so it’s linked. Considering their roles in memory allocation, conversion and reclamation, these are good targets for fuzzing. My reasoning is this: the patch modifies KVM's `guest_memfd` and AMD SEV code to allow memory to be converted between private and shared states, and to reclaim private memory. It implements new architecture hooks, `gmem_convert` and `gmem_reclaim`, and updates the SEV implementation to use them. These are functional changes to crucial KVM and SEV logic, and they need fuzzing to make sure memory isolation and correctness are maintained. Therefore, this is WorthFuzzing. My final report is: WorthFuzzing: true FocusSymbols: - kvm_gmem_make_private - kvm_gmem_free_folio - sev_gmem_convert - sev_gmem_make_private - sev_gmem_make_shared - kvm_arch_gmem_convert - kvm_arch_gmem_reclaim EnableConfigs: - KVM_AMD_SEV Now let’s set the results and move on. |
| 12/2 | 2026/07/15 07:56 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"KVM_AMD_SEV"
],
"FocusSymbols": [
"kvm_gmem_make_private",
"kvm_gmem_free_folio",
"sev_gmem_convert",
"sev_gmem_make_private",
"sev_gmem_make_shared",
"kvm_arch_gmem_convert",
"kvm_arch_gmem_reclaim"
],
"Reasoning": "The patch modifies the KVM guest_memfd and AMD SEV code to support converting memory between private and shared states, and reclaiming private memory. It introduces new architecture hooks `gmem_convert` and `gmem_reclaim` and updates the SEV implementation to use them. These are functional changes to core KVM and SEV logic that should be fuzzed to ensure memory isolation and correctness.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"KVM_AMD_SEV"
],
"FocusSymbols": [
"kvm_gmem_make_private",
"kvm_gmem_free_folio",
"sev_gmem_convert",
"sev_gmem_make_private",
"sev_gmem_make_shared",
"kvm_arch_gmem_convert",
"kvm_arch_gmem_reclaim"
],
"Reasoning": "The patch modifies the KVM guest_memfd and AMD SEV code to support converting memory between private and shared states, and reclaiming private memory. It introduces new architecture hooks `gmem_convert` and `gmem_reclaim` and updates the SEV implementation to use them. These are functional changes to core KVM and SEV logic that should be fuzzed to ensure memory isolation and correctness.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|