| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/26 07:40 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": [
"KVM",
"KVM_AMD",
"PERF_EVENTS",
"CPU_SUP_AMD"
],
"FocusSymbols": [
"svm_update_lbrv",
"svm_enable_lbrv",
"svm_vcpu_after_set_cpuid",
"perf_get_x86_pmu_capability"
],
"Reasoning": "The patch adds support for AMD LBR V2 (Last Branch Record Version 2) in KVM. It modifies SVM to handle new MSRs (MSR_AMD_DBG_EXTN_CFG, MSR_AMD64_LBR_SELECT, MSR_AMD_SAMP_BR_FROM) and CPUID features (AMD_LBR_V2, AMD_LBR_PMC_FREEZE). This is a functional change in the core KVM AMD virtualization logic and should be fuzzed.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/26 07:40 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 4030b3da982b3788e50868b31ab3b2ed2022c69c\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sun Jul 26 07:40:18 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/x86/events/core.c b/arch/x86/events/core.c\nindex 4b9e105309c6a9..4acbca1a88a180 100644\n--- a/arch/x86/events/core.c\n+++ b/arch/x86/events/core.c\n@@ -3138,6 +3138,7 @@ void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)\n \tcap-\u003ebit_width_fixed\t= cap-\u003enum_counters_fixed ? x86_pmu.cntval_bits : 0;\n \tcap-\u003eevents_mask\t= (unsigned int)x86_pmu.events_maskl;\n \tcap-\u003eevents_mask_len\t= x86_pmu.events_mask_len;\n+\tcap-\u003enum_branches_lbr\t= x86_pmu.lbr_nr;\n \tcap-\u003epebs_ept\t\t= x86_pmu.pebs_ept;\n \tcap-\u003emediated\t\t= !!(pmu.capabilities \u0026 PERF_PMU_CAP_MEDIATED_VPMU);\n }\ndiff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h\nindex 1eb13673e889f9..f18cf0986e12d3 100644\n--- a/arch/x86/include/asm/perf_event.h\n+++ b/arch/x86/include/asm/perf_event.h\n@@ -306,6 +306,7 @@ struct x86_pmu_capability {\n \tint\t\tbit_width_fixed;\n \tunsigned int\tevents_mask;\n \tint\t\tevents_mask_len;\n+\tint\t\tnum_branches_lbr;\n \tunsigned int\tpebs_ept\t:1;\n \tunsigned int\tmediated\t:1;\n };\ndiff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h\nindex aa63431ba92c31..f3bc97bc6acab3 100644\n--- a/arch/x86/include/asm/svm.h\n+++ b/arch/x86/include/asm/svm.h\n@@ -253,6 +253,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area {\n #define SVM_TSC_RATIO_MAX\t0x000000ffffffffffULL\n #define SVM_TSC_RATIO_DEFAULT\t0x0100000000ULL\n \n+#define SVM_LBR_V2_STACK_SIZE 16\n+\n \n /* AVIC */\n #define AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK\t(0xFFULL)\n@@ -368,8 +370,15 @@ struct vmcb_save_area {\n \tu64 br_to;\n \tu64 last_excp_from;\n \tu64 last_excp_to;\n-\tu8 reserved_0x298[72];\n+\tu64 dbg_extn_cfg;\n+\tu8 reserved_0x2a0[64];\n \tu64 spec_ctrl;\t\t/* Guest version of SPEC_CTRL at 0x2E0 */\n+\tu8 reserved_0x2e8[904];\n+\tstruct {\n+\t\tu64 lbr_stack_from;\n+\t\tu64 lbr_stack_to;\n+\t} __packed lbr[16];\n+\tu64 lbr_select;\n } __packed;\n \n /* Save area definition for SEV-ES and SEV-SNP guests */\n@@ -552,7 +561,7 @@ struct vmcb {\n \t};\n } __packed;\n \n-#define EXPECTED_VMCB_SAVE_AREA_SIZE\t\t744\n+#define EXPECTED_VMCB_SAVE_AREA_SIZE\t\t1912\n #define EXPECTED_GHCB_SAVE_AREA_SIZE\t\t1032\n #define EXPECTED_SEV_ES_SAVE_AREA_SIZE\t\t1648\n #define EXPECTED_VMCB_CONTROL_AREA_SIZE\t\t1024\n@@ -577,7 +586,8 @@ static inline void __unused_size_checks(void)\n \tBUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0xd8);\n \tBUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0x180);\n \tBUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0x248);\n-\tBUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0x298);\n+\tBUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0x2a0);\n+\tBUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0x2e8);\n \n \tBUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0xc8);\n \tBUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0xcc);\ndiff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c\nindex 2698fa42cd9711..51b691f91442ba 100644\n--- a/arch/x86/kvm/cpuid.c\n+++ b/arch/x86/kvm/cpuid.c\n@@ -1266,7 +1266,9 @@ void kvm_initialize_cpu_caps(void)\n \t);\n \n \tkvm_cpu_cap_init(CPUID_8000_0022_EAX,\n-\t\tF(PERFMON_V2),\n+\t\tSCATTERED_F(PERFMON_V2),\n+\t\tSCATTERED_F(AMD_LBR_V2),\n+\t\tSCATTERED_F(AMD_LBR_PMC_FREEZE),\n \t);\n \n \tif (!static_cpu_has_bug(X86_BUG_NULL_SEG))\n@@ -1883,6 +1885,11 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)\n \t\tcpuid_entry_override(entry, CPUID_8000_0022_EAX);\n \n \t\tebx.split.num_core_pmc = kvm_pmu_cap.num_counters_gp;\n+\n+\t\tif (kvm_cpu_cap_has(X86_FEATURE_AMD_LBR_V2))\n+\t\t\tebx.split.lbr_v2_stack_sz =\n+\t\t\t\tmin(kvm_pmu_cap.num_branches_lbr, SVM_LBR_V2_STACK_SIZE);\n+\n \t\tentry-\u003eebx = ebx.full;\n \t\tbreak;\n \t}\ndiff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h\nindex 657f5f743ed975..9a58f91eb173d0 100644\n--- a/arch/x86/kvm/reverse_cpuid.h\n+++ b/arch/x86/kvm/reverse_cpuid.h\n@@ -70,7 +70,9 @@\n #define KVM_X86_FEATURE_CONSTANT_TSC\tKVM_X86_FEATURE(CPUID_8000_0007_EDX, 8)\n \n /* CPUID level 0x80000022 (EAX) */\n-#define KVM_X86_FEATURE_PERFMON_V2\tKVM_X86_FEATURE(CPUID_8000_0022_EAX, 0)\n+#define KVM_X86_FEATURE_PERFMON_V2\t\tKVM_X86_FEATURE(CPUID_8000_0022_EAX, 0)\n+#define KVM_X86_FEATURE_AMD_LBR_V2\t\tKVM_X86_FEATURE(CPUID_8000_0022_EAX, 1)\n+#define KVM_X86_FEATURE_AMD_LBR_PMC_FREEZE\tKVM_X86_FEATURE(CPUID_8000_0022_EAX, 2)\n \n /* CPUID level 0x80000021 (ECX) */\n #define KVM_X86_FEATURE_TSA_SQ_NO\tKVM_X86_FEATURE(CPUID_8000_0021_ECX, 1)\n@@ -146,6 +148,8 @@ static __always_inline u32 __feature_translate(int x86_feature)\n \tKVM_X86_TRANSLATE_FEATURE(SGX_EDECCSSA);\n \tKVM_X86_TRANSLATE_FEATURE(CONSTANT_TSC);\n \tKVM_X86_TRANSLATE_FEATURE(PERFMON_V2);\n+\tKVM_X86_TRANSLATE_FEATURE(AMD_LBR_V2);\n+\tKVM_X86_TRANSLATE_FEATURE(AMD_LBR_PMC_FREEZE);\n \tKVM_X86_TRANSLATE_FEATURE(RRSBA_CTRL);\n \tKVM_X86_TRANSLATE_FEATURE(BHI_CTRL);\n \tKVM_X86_TRANSLATE_FEATURE(TSA_SQ_NO);\ndiff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c\nindex ef69a51ab27f98..3ec91c1c58dcc5 100644\n--- a/arch/x86/kvm/svm/svm.c\n+++ b/arch/x86/kvm/svm/svm.c\n@@ -744,6 +744,47 @@ static void svm_recalc_lbr_msr_intercepts(struct kvm_vcpu *vcpu)\n \tsvm-\u003elbr_msrs_intercepted = intercept;\n }\n \n+static bool svm_lbrv2_supported(struct kvm_vcpu *vcpu)\n+{\n+\treturn guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_V2) \u0026\u0026\n+\t kvm_vcpu_has_mediated_pmu(vcpu);\n+}\n+\n+static bool svm_lbrv2_active(struct kvm_vcpu *vcpu)\n+{\n+\tstruct vcpu_svm *svm = to_svm(vcpu);\n+\treturn svm_lbrv2_supported(vcpu) \u0026\u0026\n+\t (svm-\u003evmcb-\u003esave.dbg_extn_cfg \u0026 DBG_EXTN_CFG_LBRV2EN);\n+}\n+\n+static void svm_recalc_lbrv2_msr_intercepts(struct kvm_vcpu *vcpu)\n+{\n+\tstruct vcpu_svm *svm = to_svm(vcpu);\n+\tbool intercept = !svm_lbrv2_active(vcpu);\n+\tint i;\n+\n+\tif (intercept == svm-\u003elbrv2_msrs_intercepted)\n+\t\treturn;\n+\n+\tfor (i = 0; i \u003c 32; i++)\n+\t\tsvm_set_intercept_for_msr(vcpu, MSR_AMD_SAMP_BR_FROM + i, MSR_TYPE_RW, intercept);\n+\n+\tsvm_set_intercept_for_msr(vcpu, MSR_AMD64_LBR_SELECT, MSR_TYPE_RW, intercept);\n+\n+\t/*\n+\t * DBG_EXTN_CFG stays permanently intercepted for non-SEV-ES guests so\n+\t * KVM can observe LBRV2EN and lazily toggle V_LBR. SEV-ES+ guests must\n+\t * delegate LBR virtualization to the processor (per the APM), where\n+\t * intercepting LBR MSRs can be fatal, so toggle it with the rest. See\n+\t * commit b7e4be0a224f (\"KVM: SEV-ES: Delegate LBR virtualization to the\n+\t * processor\").\n+\t */\n+\tif (is_sev_es_guest(vcpu))\n+\t\tsvm_set_intercept_for_msr(vcpu, MSR_AMD_DBG_EXTN_CFG, MSR_TYPE_RW, intercept);\n+\n+\tsvm-\u003elbrv2_msrs_intercepted = intercept;\n+}\n+\n void svm_vcpu_free_msrpm(void *msrpm)\n {\n \t__free_pages(virt_to_page(msrpm), get_order(MSRPM_SIZE));\n@@ -799,8 +840,10 @@ static void svm_recalc_msr_intercepts(struct kvm_vcpu *vcpu)\n \tsvm_disable_intercept_for_msr(vcpu, MSR_SYSCALL_MASK, MSR_TYPE_RW);\n #endif\n \n-\tif (lbrv)\n+\tif (lbrv) {\n \t\tsvm_recalc_lbr_msr_intercepts(vcpu);\n+\t\tsvm_recalc_lbrv2_msr_intercepts(vcpu);\n+\t}\n \n \tif (cpu_feature_enabled(X86_FEATURE_IBPB))\n \t\tsvm_set_intercept_for_msr(vcpu, MSR_IA32_PRED_CMD, MSR_TYPE_W,\n@@ -868,6 +911,7 @@ void svm_enable_lbrv(struct kvm_vcpu *vcpu)\n {\n \t__svm_enable_lbrv(vcpu);\n \tsvm_recalc_lbr_msr_intercepts(vcpu);\n+\tsvm_recalc_lbrv2_msr_intercepts(vcpu);\n }\n \n static void __svm_disable_lbrv(struct kvm_vcpu *vcpu)\n@@ -880,9 +924,11 @@ void svm_update_lbrv(struct kvm_vcpu *vcpu)\n {\n \tstruct vcpu_svm *svm = to_svm(vcpu);\n \tbool current_enable_lbrv = svm-\u003evmcb-\u003econtrol.misc_ctl2 \u0026 SVM_MISC2_ENABLE_V_LBR;\n+\n \tbool enable_lbrv = (svm-\u003evmcb-\u003esave.dbgctl \u0026 DEBUGCTLMSR_LBR) ||\n \t\t\t (is_guest_mode(vcpu) \u0026\u0026 guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) \u0026\u0026\n-\t\t\t (svm-\u003enested.ctl.misc_ctl2 \u0026 SVM_MISC2_ENABLE_V_LBR));\n+\t\t\t (svm-\u003enested.ctl.misc_ctl2 \u0026 SVM_MISC2_ENABLE_V_LBR)) ||\n+\t\t\t svm_lbrv2_active(vcpu);\n \n \tif (enable_lbrv \u0026\u0026 !current_enable_lbrv)\n \t\t__svm_enable_lbrv(vcpu);\n@@ -896,6 +942,7 @@ void svm_update_lbrv(struct kvm_vcpu *vcpu)\n \t * do, so always recalculate the intercepts here.\n \t */\n \tsvm_recalc_lbr_msr_intercepts(vcpu);\n+\tsvm_recalc_lbrv2_msr_intercepts(vcpu);\n }\n \n void disable_nmi_singlestep(struct vcpu_svm *svm)\n@@ -1341,6 +1388,7 @@ static int svm_vcpu_create(struct kvm_vcpu *vcpu)\n \n \tsvm-\u003ex2avic_msrs_intercepted = true;\n \tsvm-\u003elbr_msrs_intercepted = true;\n+\tsvm-\u003elbrv2_msrs_intercepted = true;\n \n \tsvm-\u003evmcb01.ptr = page_address(vmcb01_page);\n \tsvm-\u003evmcb01.pa = __sme_set(page_to_pfn(vmcb01_page) \u003c\u003c PAGE_SHIFT);\n@@ -2787,6 +2835,19 @@ static u64 *svm_vmcb_lbr(struct vcpu_svm *svm, u32 msr)\n \treturn \u0026svm-\u003evmcb-\u003esave.br_from;\n }\n \n+static u64 *svm_vmcb_lbrv2(struct vcpu_svm *svm, u32 msr)\n+{\n+\tu32 offset = msr - MSR_AMD_SAMP_BR_FROM;\n+\tu32 idx = offset \u003e\u003e 1;\n+\n+\tif (WARN_ON_ONCE(idx \u003e= SVM_LBR_V2_STACK_SIZE))\n+\t\treturn \u0026svm-\u003evmcb-\u003esave.lbr[0].lbr_stack_from;\n+\n+\tif (offset \u0026 1)\n+\t\treturn \u0026svm-\u003evmcb-\u003esave.lbr[idx].lbr_stack_to;\n+\treturn \u0026svm-\u003evmcb-\u003esave.lbr[idx].lbr_stack_from;\n+}\n+\n static bool sev_es_prevent_msr_access(struct kvm_vcpu *vcpu,\n \t\t\t\t struct msr_data *msr_info)\n {\n@@ -2882,6 +2943,21 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)\n \tcase MSR_IA32_LASTINTTOIP:\n \t\tmsr_info-\u003edata = lbrv ? *svm_vmcb_lbr(svm, msr_info-\u003eindex) : 0;\n \t\tbreak;\n+\tcase MSR_AMD_DBG_EXTN_CFG:\n+\t\tif (!svm_lbrv2_supported(vcpu))\n+\t\t\treturn KVM_MSR_RET_UNSUPPORTED;\n+\t\tmsr_info-\u003edata = svm-\u003evmcb-\u003esave.dbg_extn_cfg;\n+\t\tbreak;\n+\tcase MSR_AMD64_LBR_SELECT:\n+\t\tif (!svm_lbrv2_supported(vcpu))\n+\t\t\treturn KVM_MSR_RET_UNSUPPORTED;\n+\t\tmsr_info-\u003edata = svm-\u003evmcb-\u003esave.lbr_select;\n+\t\tbreak;\n+\tcase MSR_AMD_SAMP_BR_FROM ... MSR_AMD_SAMP_BR_FROM + 31:\n+\t\tif (!svm_lbrv2_supported(vcpu))\n+\t\t\treturn KVM_MSR_RET_UNSUPPORTED;\n+\t\tmsr_info-\u003edata = *svm_vmcb_lbrv2(svm, msr_info-\u003eindex);\n+\t\tbreak;\n \tcase MSR_VM_HSAVE_PA:\n \t\tmsr_info-\u003edata = svm-\u003enested.hsave_msr;\n \t\tbreak;\n@@ -3160,6 +3236,10 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)\n \t\t\tdata \u0026= ~DEBUGCTLMSR_BTF;\n \t\t}\n \n+\t\tif ((data \u0026 DEBUGCTL_LBR_PMC_FREEZE_BITS) \u0026\u0026\n+\t\t !guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_PMC_FREEZE))\n+\t\t\treturn 1;\n+\n \t\tif (data \u0026 DEBUGCTL_RESERVED_BITS)\n \t\t\treturn 1;\n \n@@ -3181,6 +3261,40 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)\n \t\t*svm_vmcb_lbr(svm, ecx) = data;\n \t\tvmcb_mark_dirty(svm-\u003evmcb, VMCB_LBR);\n \t\tbreak;\n+\tcase MSR_AMD_DBG_EXTN_CFG:\n+\t\tif (!svm_lbrv2_supported(vcpu))\n+\t\t\treturn KVM_MSR_RET_UNSUPPORTED;\n+\n+\t\tif (data \u0026 DBG_EXTN_CFG_RESERVED_BITS)\n+\t\t\treturn 1;\n+\n+\t\tif (svm-\u003evmcb-\u003esave.dbg_extn_cfg == data)\n+\t\t\tbreak;\n+\n+\t\tsvm-\u003evmcb-\u003esave.dbg_extn_cfg = data;\n+\t\tvmcb_mark_dirty(svm-\u003evmcb, VMCB_LBR);\n+\t\tsvm_update_lbrv(vcpu);\n+\t\tbreak;\n+\tcase MSR_AMD64_LBR_SELECT:\n+\t\tif (!svm_lbrv2_supported(vcpu))\n+\t\t\treturn KVM_MSR_RET_UNSUPPORTED;\n+\n+\t\tif (data \u0026 LBR_SELECT_RESERVED_BITS)\n+\t\t\treturn 1;\n+\n+\t\tif (svm-\u003evmcb-\u003esave.lbr_select == data)\n+\t\t\tbreak;\n+\n+\t\tsvm-\u003evmcb-\u003esave.lbr_select = data;\n+\t\tvmcb_mark_dirty(svm-\u003evmcb, VMCB_LBR);\n+\t\tbreak;\n+\tcase MSR_AMD_SAMP_BR_FROM ... MSR_AMD_SAMP_BR_FROM + 31:\n+\t\tif (!svm_lbrv2_supported(vcpu))\n+\t\t\treturn KVM_MSR_RET_UNSUPPORTED;\n+\n+\t\t*svm_vmcb_lbrv2(svm, ecx) = data;\n+\t\tvmcb_mark_dirty(svm-\u003evmcb, VMCB_LBR);\n+\t\tbreak;\n \tcase MSR_VM_HSAVE_PA:\n \t\t/*\n \t\t * Old kernels did not validate the value written to\n@@ -4710,6 +4824,20 @@ static bool svm_has_emulated_msr(struct kvm *kvm, u32 index)\n \treturn true;\n }\n \n+static int cpuid_query_lbrv2_stack_size(struct kvm_vcpu *vcpu)\n+{\n+\tstruct kvm_cpuid_entry2 *entry;\n+\n+\tentry = kvm_find_cpuid_entry(vcpu, 0x80000000);\n+\tif (!entry || entry-\u003eeax \u003c 0x80000022)\n+\t\tgoto not_found;\n+\tentry = kvm_find_cpuid_entry(vcpu, 0x80000022);\n+\tif (entry)\n+\t\treturn (entry-\u003eebx \u003e\u003e 4) \u0026 0x3f;\n+not_found:\n+\treturn 0;\n+}\n+\n static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)\n {\n \tstruct vcpu_svm *svm = to_svm(vcpu);\n@@ -4736,6 +4864,10 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)\n \tif (guest_cpuid_is_intel_compatible(vcpu))\n \t\tguest_cpu_cap_clear(vcpu, X86_FEATURE_V_VMSAVE_VMLOAD);\n \n+\tif (guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_V2) \u0026\u0026\n+\t cpuid_query_lbrv2_stack_size(vcpu) != SVM_LBR_V2_STACK_SIZE)\n+\t\tguest_cpu_cap_clear(vcpu, X86_FEATURE_AMD_LBR_V2);\n+\n \tif (is_sev_guest(vcpu))\n \t\tsev_vcpu_after_set_cpuid(svm);\n }\n@@ -5582,6 +5714,10 @@ static __init void svm_set_cpu_caps(void)\n \t\tif (kvm_pmu_cap.version != 2 ||\n \t\t !kvm_cpu_cap_has(X86_FEATURE_PERFCTR_CORE))\n \t\t\tkvm_cpu_cap_clear(X86_FEATURE_PERFMON_V2);\n+\n+\t\tif (!lbrv || !enable_mediated_pmu ||\n+\t\t !kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2))\n+\t\t\tkvm_cpu_cap_clear(X86_FEATURE_AMD_LBR_V2);\n \t}\n \n \t/* CPUID 0x8000001F (SME/SEV features) */\ndiff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h\nindex 716be21fba3354..105a71d69d68a8 100644\n--- a/arch/x86/kvm/svm/svm.h\n+++ b/arch/x86/kvm/svm/svm.h\n@@ -363,6 +363,7 @@ struct vcpu_svm {\n \tbool avic_irq_window;\n \tbool x2avic_msrs_intercepted;\n \tbool lbr_msrs_intercepted;\n+\tbool lbrv2_msrs_intercepted;\n \n \t/* Guest GIF value, used when vGIF is not enabled */\n \tbool guest_gif;\n@@ -783,7 +784,11 @@ BUILD_SVM_MSR_BITMAP_HELPERS(bool, test, test)\n BUILD_SVM_MSR_BITMAP_HELPERS(void, clear, __clear)\n BUILD_SVM_MSR_BITMAP_HELPERS(void, set, __set)\n \n-#define DEBUGCTL_RESERVED_BITS (~DEBUGCTLMSR_LBR)\n+#define DEBUGCTL_LBR_PMC_FREEZE_BITS\t(DEBUGCTLMSR_FREEZE_LBRS_ON_PMI |\t\\\n+\t\t\t\t\t DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI)\n+#define DEBUGCTL_RESERVED_BITS\t(~(DEBUGCTLMSR_LBR | DEBUGCTL_LBR_PMC_FREEZE_BITS))\n+#define DBG_EXTN_CFG_RESERVED_BITS (~DBG_EXTN_CFG_LBRV2EN)\n+#define LBR_SELECT_RESERVED_BITS (~GENMASK_ULL(8, 0))\n \n /* svm.c */\n extern bool dump_invalid_vmcb;\n"
} |
| 2/1 | 2026/07/26 07:40 | agent | patch-evaluator |
1mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"KVM",
"KVM_AMD",
"PERF_EVENTS",
"CPU_SUP_AMD"
],
"FocusSymbols": [
"svm_update_lbrv",
"svm_enable_lbrv",
"svm_vcpu_after_set_cpuid",
"perf_get_x86_pmu_capability"
],
"Reasoning": "The patch adds support for AMD LBR V2 (Last Branch Record Version 2) in KVM. It modifies SVM to handle new MSRs (MSR_AMD_DBG_EXTN_CFG, MSR_AMD64_LBR_SELECT, MSR_AMD_SAMP_BR_FROM) and CPUID features (AMD_LBR_V2, AMD_LBR_PMC_FREEZE). This is a functional change in the core KVM AMD virtualization logic and should be fuzzed.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 4030b3da982b3788e50868b31ab3b2ed2022c69c
Author: syz-cluster <triage@syzkaller.com>
Date: Sun Jul 26 07:40:18 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 4b9e105309c6a9..4acbca1a88a180 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -3138,6 +3138,7 @@ void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
cap->bit_width_fixed = cap->num_counters_fixed ? x86_pmu.cntval_bits : 0;
cap->events_mask = (unsigned int)x86_pmu.events_maskl;
cap->events_mask_len = x86_pmu.events_mask_len;
+ cap->num_branches_lbr = x86_pmu.lbr_nr;
cap->pebs_ept = x86_pmu.pebs_ept;
cap->mediated = !!(pmu.capabilities & PERF_PMU_CAP_MEDIATED_VPMU);
}
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 1eb13673e889f9..f18cf0986e12d3 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -306,6 +306,7 @@ struct x86_pmu_capability {
int bit_width_fixed;
unsigned int events_mask;
int events_mask_len;
+ int num_branches_lbr;
unsigned int pebs_ept :1;
unsigned int mediated :1;
};
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index aa63431ba92c31..f3bc97bc6acab3 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -253,6 +253,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
#define SVM_TSC_RATIO_MAX 0x000000ffffffffffULL
#define SVM_TSC_RATIO_DEFAULT 0x0100000000ULL
+#define SVM_LBR_V2_STACK_SIZE 16
+
/* AVIC */
#define AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK (0xFFULL)
@@ -368,8 +370,15 @@ struct vmcb_save_area {
u64 br_to;
u64 last_excp_from;
u64 last_excp_to;
- u8 reserved_0x298[72];
+ u64 dbg_extn_cfg;
+ u8 reserved_0x2a0[64];
u64 spec_ctrl; /* Guest version of SPEC_CTRL at 0x2E0 */
+ u8 reserved_0x2e8[904];
+ struct {
+ u64 lbr_stack_from;
+ u64 lbr_stack_to;
+ } __packed lbr[16];
+ u64 lbr_select;
} __packed;
/* Save area definition for SEV-ES and SEV-SNP guests */
@@ -552,7 +561,7 @@ struct vmcb {
};
} __packed;
-#define EXPECTED_VMCB_SAVE_AREA_SIZE 744
+#define EXPECTED_VMCB_SAVE_AREA_SIZE 1912
#define EXPECTED_GHCB_SAVE_AREA_SIZE 1032
#define EXPECTED_SEV_ES_SAVE_AREA_SIZE 1648
#define EXPECTED_VMCB_CONTROL_AREA_SIZE 1024
@@ -577,7 +586,8 @@ static inline void __unused_size_checks(void)
BUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0xd8);
BUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0x180);
BUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0x248);
- BUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0x298);
+ BUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0x2a0);
+ BUILD_BUG_RESERVED_OFFSET(vmcb_save_area, 0x2e8);
BUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0xc8);
BUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0xcc);
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 2698fa42cd9711..51b691f91442ba 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -1266,7 +1266,9 @@ void kvm_initialize_cpu_caps(void)
);
kvm_cpu_cap_init(CPUID_8000_0022_EAX,
- F(PERFMON_V2),
+ SCATTERED_F(PERFMON_V2),
+ SCATTERED_F(AMD_LBR_V2),
+ SCATTERED_F(AMD_LBR_PMC_FREEZE),
);
if (!static_cpu_has_bug(X86_BUG_NULL_SEG))
@@ -1883,6 +1885,11 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
cpuid_entry_override(entry, CPUID_8000_0022_EAX);
ebx.split.num_core_pmc = kvm_pmu_cap.num_counters_gp;
+
+ if (kvm_cpu_cap_has(X86_FEATURE_AMD_LBR_V2))
+ ebx.split.lbr_v2_stack_sz =
+ min(kvm_pmu_cap.num_branches_lbr, SVM_LBR_V2_STACK_SIZE);
+
entry->ebx = ebx.full;
break;
}
diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h
index 657f5f743ed975..9a58f91eb173d0 100644
--- a/arch/x86/kvm/reverse_cpuid.h
+++ b/arch/x86/kvm/reverse_cpuid.h
@@ -70,7 +70,9 @@
#define KVM_X86_FEATURE_CONSTANT_TSC KVM_X86_FEATURE(CPUID_8000_0007_EDX, 8)
/* CPUID level 0x80000022 (EAX) */
-#define KVM_X86_FEATURE_PERFMON_V2 KVM_X86_FEATURE(CPUID_8000_0022_EAX, 0)
+#define KVM_X86_FEATURE_PERFMON_V2 KVM_X86_FEATURE(CPUID_8000_0022_EAX, 0)
+#define KVM_X86_FEATURE_AMD_LBR_V2 KVM_X86_FEATURE(CPUID_8000_0022_EAX, 1)
+#define KVM_X86_FEATURE_AMD_LBR_PMC_FREEZE KVM_X86_FEATURE(CPUID_8000_0022_EAX, 2)
/* CPUID level 0x80000021 (ECX) */
#define KVM_X86_FEATURE_TSA_SQ_NO KVM_X86_FEATURE(CPUID_8000_0021_ECX, 1)
@@ -146,6 +148,8 @@ static __always_inline u32 __feature_translate(int x86_feature)
KVM_X86_TRANSLATE_FEATURE(SGX_EDECCSSA);
KVM_X86_TRANSLATE_FEATURE(CONSTANT_TSC);
KVM_X86_TRANSLATE_FEATURE(PERFMON_V2);
+ KVM_X86_TRANSLATE_FEATURE(AMD_LBR_V2);
+ KVM_X86_TRANSLATE_FEATURE(AMD_LBR_PMC_FREEZE);
KVM_X86_TRANSLATE_FEATURE(RRSBA_CTRL);
KVM_X86_TRANSLATE_FEATURE(BHI_CTRL);
KVM_X86_TRANSLATE_FEATURE(TSA_SQ_NO);
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index ef69a51ab27f98..3ec91c1c58dcc5 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -744,6 +744,47 @@ static void svm_recalc_lbr_msr_intercepts(struct kvm_vcpu *vcpu)
svm->lbr_msrs_intercepted = intercept;
}
+static bool svm_lbrv2_supported(struct kvm_vcpu *vcpu)
+{
+ return guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_V2) &&
+ kvm_vcpu_has_mediated_pmu(vcpu);
+}
+
+static bool svm_lbrv2_active(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+ return svm_lbrv2_supported(vcpu) &&
+ (svm->vmcb->save.dbg_extn_cfg & DBG_EXTN_CFG_LBRV2EN);
+}
+
+static void svm_recalc_lbrv2_msr_intercepts(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+ bool intercept = !svm_lbrv2_active(vcpu);
+ int i;
+
+ if (intercept == svm->lbrv2_msrs_intercepted)
+ return;
+
+ for (i = 0; i < 32; i++)
+ svm_set_intercept_for_msr(vcpu, MSR_AMD_SAMP_BR_FROM + i, MSR_TYPE_RW, intercept);
+
+ svm_set_intercept_for_msr(vcpu, MSR_AMD64_LBR_SELECT, MSR_TYPE_RW, intercept);
+
+ /*
+ * DBG_EXTN_CFG stays permanently intercepted for non-SEV-ES guests so
+ * KVM can observe LBRV2EN and lazily toggle V_LBR. SEV-ES+ guests must
+ * delegate LBR virtualization to the processor (per the APM), where
+ * intercepting LBR MSRs can be fatal, so toggle it with the rest. See
+ * commit b7e4be0a224f ("KVM: SEV-ES: Delegate LBR virtualization to the
+ * processor").
+ */
+ if (is_sev_es_guest(vcpu))
+ svm_set_intercept_for_msr(vcpu, MSR_AMD_DBG_EXTN_CFG, MSR_TYPE_RW, intercept);
+
+ svm->lbrv2_msrs_intercepted = intercept;
+}
+
void svm_vcpu_free_msrpm(void *msrpm)
{
__free_pages(virt_to_page(msrpm), get_order(MSRPM_SIZE));
@@ -799,8 +840,10 @@ static void svm_recalc_msr_intercepts(struct kvm_vcpu *vcpu)
svm_disable_intercept_for_msr(vcpu, MSR_SYSCALL_MASK, MSR_TYPE_RW);
#endif
- if (lbrv)
+ if (lbrv) {
svm_recalc_lbr_msr_intercepts(vcpu);
+ svm_recalc_lbrv2_msr_intercepts(vcpu);
+ }
if (cpu_feature_enabled(X86_FEATURE_IBPB))
svm_set_intercept_for_msr(vcpu, MSR_IA32_PRED_CMD, MSR_TYPE_W,
@@ -868,6 +911,7 @@ void svm_enable_lbrv(struct kvm_vcpu *vcpu)
{
__svm_enable_lbrv(vcpu);
svm_recalc_lbr_msr_intercepts(vcpu);
+ svm_recalc_lbrv2_msr_intercepts(vcpu);
}
static void __svm_disable_lbrv(struct kvm_vcpu *vcpu)
@@ -880,9 +924,11 @@ void svm_update_lbrv(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
bool current_enable_lbrv = svm->vmcb->control.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR;
+
bool enable_lbrv = (svm->vmcb->save.dbgctl & DEBUGCTLMSR_LBR) ||
(is_guest_mode(vcpu) && guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) &&
- (svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR));
+ (svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR)) ||
+ svm_lbrv2_active(vcpu);
if (enable_lbrv && !current_enable_lbrv)
__svm_enable_lbrv(vcpu);
@@ -896,6 +942,7 @@ void svm_update_lbrv(struct kvm_vcpu *vcpu)
* do, so always recalculate the intercepts here.
*/
svm_recalc_lbr_msr_intercepts(vcpu);
+ svm_recalc_lbrv2_msr_intercepts(vcpu);
}
void disable_nmi_singlestep(struct vcpu_svm *svm)
@@ -1341,6 +1388,7 @@ static int svm_vcpu_create(struct kvm_vcpu *vcpu)
svm->x2avic_msrs_intercepted = true;
svm->lbr_msrs_intercepted = true;
+ svm->lbrv2_msrs_intercepted = true;
svm->vmcb01.ptr = page_address(vmcb01_page);
svm->vmcb01.pa = __sme_set(page_to_pfn(vmcb01_page) << PAGE_SHIFT);
@@ -2787,6 +2835,19 @@ static u64 *svm_vmcb_lbr(struct vcpu_svm *svm, u32 msr)
return &svm->vmcb->save.br_from;
}
+static u64 *svm_vmcb_lbrv2(struct vcpu_svm *svm, u32 msr)
+{
+ u32 offset = msr - MSR_AMD_SAMP_BR_FROM;
+ u32 idx = offset >> 1;
+
+ if (WARN_ON_ONCE(idx >= SVM_LBR_V2_STACK_SIZE))
+ return &svm->vmcb->save.lbr[0].lbr_stack_from;
+
+ if (offset & 1)
+ return &svm->vmcb->save.lbr[idx].lbr_stack_to;
+ return &svm->vmcb->save.lbr[idx].lbr_stack_from;
+}
+
static bool sev_es_prevent_msr_access(struct kvm_vcpu *vcpu,
struct msr_data *msr_info)
{
@@ -2882,6 +2943,21 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_IA32_LASTINTTOIP:
msr_info->data = lbrv ? *svm_vmcb_lbr(svm, msr_info->index) : 0;
break;
+ case MSR_AMD_DBG_EXTN_CFG:
+ if (!svm_lbrv2_supported(vcpu))
+ return KVM_MSR_RET_UNSUPPORTED;
+ msr_info->data = svm->vmcb->save.dbg_extn_cfg;
+ break;
+ case MSR_AMD64_LBR_SELECT:
+ if (!svm_lbrv2_supported(vcpu))
+ return KVM_MSR_RET_UNSUPPORTED;
+ msr_info->data = svm->vmcb->save.lbr_select;
+ break;
+ case MSR_AMD_SAMP_BR_FROM ... MSR_AMD_SAMP_BR_FROM + 31:
+ if (!svm_lbrv2_supported(vcpu))
+ return KVM_MSR_RET_UNSUPPORTED;
+ msr_info->data = *svm_vmcb_lbrv2(svm, msr_info->index);
+ break;
case MSR_VM_HSAVE_PA:
msr_info->data = svm->nested.hsave_msr;
break;
@@ -3160,6 +3236,10 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
data &= ~DEBUGCTLMSR_BTF;
}
+ if ((data & DEBUGCTL_LBR_PMC_FREEZE_BITS) &&
+ !guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_PMC_FREEZE))
+ return 1;
+
if (data & DEBUGCTL_RESERVED_BITS)
return 1;
@@ -3181,6 +3261,40 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
*svm_vmcb_lbr(svm, ecx) = data;
vmcb_mark_dirty(svm->vmcb, VMCB_LBR);
break;
+ case MSR_AMD_DBG_EXTN_CFG:
+ if (!svm_lbrv2_supported(vcpu))
+ return KVM_MSR_RET_UNSUPPORTED;
+
+ if (data & DBG_EXTN_CFG_RESERVED_BITS)
+ return 1;
+
+ if (svm->vmcb->save.dbg_extn_cfg == data)
+ break;
+
+ svm->vmcb->save.dbg_extn_cfg = data;
+ vmcb_mark_dirty(svm->vmcb, VMCB_LBR);
+ svm_update_lbrv(vcpu);
+ break;
+ case MSR_AMD64_LBR_SELECT:
+ if (!svm_lbrv2_supported(vcpu))
+ return KVM_MSR_RET_UNSUPPORTED;
+
+ if (data & LBR_SELECT_RESERVED_BITS)
+ return 1;
+
+ if (svm->vmcb->save.lbr_select == data)
+ break;
+
+ svm->vmcb->save.lbr_select = data;
+ vmcb_mark_dirty(svm->vmcb, VMCB_LBR);
+ break;
+ case MSR_AMD_SAMP_BR_FROM ... MSR_AMD_SAMP_BR_FROM + 31:
+ if (!svm_lbrv2_supported(vcpu))
+ return KVM_MSR_RET_UNSUPPORTED;
+
+ *svm_vmcb_lbrv2(svm, ecx) = data;
+ vmcb_mark_dirty(svm->vmcb, VMCB_LBR);
+ break;
case MSR_VM_HSAVE_PA:
/*
* Old kernels did not validate the value written to
@@ -4710,6 +4824,20 @@ static bool svm_has_emulated_msr(struct kvm *kvm, u32 index)
return true;
}
+static int cpuid_query_lbrv2_stack_size(struct kvm_vcpu *vcpu)
+{
+ struct kvm_cpuid_entry2 *entry;
+
+ entry = kvm_find_cpuid_entry(vcpu, 0x80000000);
+ if (!entry || entry->eax < 0x80000022)
+ goto not_found;
+ entry = kvm_find_cpuid_entry(vcpu, 0x80000022);
+ if (entry)
+ return (entry->ebx >> 4) & 0x3f;
+not_found:
+ return 0;
+}
+
static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -4736,6 +4864,10 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
if (guest_cpuid_is_intel_compatible(vcpu))
guest_cpu_cap_clear(vcpu, X86_FEATURE_V_VMSAVE_VMLOAD);
+ if (guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_V2) &&
+ cpuid_query_lbrv2_stack_size(vcpu) != SVM_LBR_V2_STACK_SIZE)
+ guest_cpu_cap_clear(vcpu, X86_FEATURE_AMD_LBR_V2);
+
if (is_sev_guest(vcpu))
sev_vcpu_after_set_cpuid(svm);
}
@@ -5582,6 +5714,10 @@ static __init void svm_set_cpu_caps(void)
if (kvm_pmu_cap.version != 2 ||
!kvm_cpu_cap_has(X86_FEATURE_PERFCTR_CORE))
kvm_cpu_cap_clear(X86_FEATURE_PERFMON_V2);
+
+ if (!lbrv || !enable_mediated_pmu ||
+ !kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2))
+ kvm_cpu_cap_clear(X86_FEATURE_AMD_LBR_V2);
}
/* CPUID 0x8000001F (SME/SEV features) */
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 716be21fba3354..105a71d69d68a8 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -363,6 +363,7 @@ struct vcpu_svm {
bool avic_irq_window;
bool x2avic_msrs_intercepted;
bool lbr_msrs_intercepted;
+ bool lbrv2_msrs_intercepted;
/* Guest GIF value, used when vGIF is not enabled */
bool guest_gif;
@@ -783,7 +784,11 @@ BUILD_SVM_MSR_BITMAP_HELPERS(bool, test, test)
BUILD_SVM_MSR_BITMAP_HELPERS(void, clear, __clear)
BUILD_SVM_MSR_BITMAP_HELPERS(void, set, __set)
-#define DEBUGCTL_RESERVED_BITS (~DEBUGCTLMSR_LBR)
+#define DEBUGCTL_LBR_PMC_FREEZE_BITS (DEBUGCTLMSR_FREEZE_LBRS_ON_PMI | \
+ DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI)
+#define DEBUGCTL_RESERVED_BITS (~(DEBUGCTLMSR_LBR | DEBUGCTL_LBR_PMC_FREEZE_BITS))
+#define DBG_EXTN_CFG_RESERVED_BITS (~DBG_EXTN_CFG_LBRV2EN)
+#define LBR_SELECT_RESERVED_BITS (~GENMASK_ULL(8, 0))
/* svm.c */
extern bool dump_invalid_vmcb;
|
| 3/2 | 2026/07/26 07:40 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8583 output: 21 thoughts: 462 Thoughts: **My Assessment of the AMD LBR V2 KVM Patch** Okay, so I'm looking at a patch that introduces AMD LBR V2 support within KVM, specifically for SVM. This is a pretty significant change, touching core areas of the hypervisor and performance monitoring. Immediately, I see it's spread across several key files: `core.c`, headers (`perf_event.h`, `svm.h`, `reverse_cpuid.h`), and crucial KVM SVM components (`cpuid.c`, `svm.c`). This tells me the change involves both fundamental CPUID feature advertisement and the interception/emulation of specific Model-Specific Registers (MSRs). Specifically, it deals with MSRs such as `MSR_AMD_DBG_EXTN_CFG`, `MSR_AMD64_LBR_SELECT`, and `MSR_AMD_SAMP_BR_FROM`, all of which are a good indication that branch tracing is the focus here. The addition of CPUID features `AMD_LBR_V2` and `AMD_LBR_PMC_FREEZE` is the standard approach to indicating this new functionality to the guest. Digging into `arch/x86/kvm/svm/svm.c` is important to me, so I’m going to focus my analysis there. I can see functions dealing with enabling/disabling the feature, and MSR read/write operations for these new registers. The functions are: `svm_recalc_lbrv2_msr_intercepts`, `svm_lbrv2_supported`, `svm_lbrv2_active`, `svm_update_lbrv`, `svm_get_msr`, `svm_set_msr`, `cpuid_query_lbrv2_stack_size`, `svm_vcpu_after_set_cpuid`, and `svm_set_cpu_caps`. This indicates that the functionality is fully supported. Now, I need to understand the dependencies. Clearly, `CONFIG_KVM` and `CONFIG_KVM_AMD` are mandatory. Perf events would be relevant here, so I'll assume `CONFIG_PERF_EVENTS` is also needed, but let’s check. I’m going to run a `grepper` search for "AMD_LBR_V2" or similar terms within the Kconfig files to be certain, and verify whether a specific Kconfig option has been added for this feature. That will be my next step. |
| 4/2 | 2026/07/26 07:40 | tool | grepper |
0mArgs:{
"Expression": "AMD_LBR_V2"
}Results: {
"Output": "arch/x86/events/amd/lbr.c=422=__init int amd_pmu_lbr_init(void)\n--\narch/x86/events/amd/lbr.c-425-\narch/x86/events/amd/lbr.c:426:\tif (x86_pmu.version \u003c 2 || !boot_cpu_has(X86_FEATURE_AMD_LBR_V2))\narch/x86/events/amd/lbr.c-427-\t\treturn -EOPNOTSUPP;\n--\narch/x86/include/asm/cpufeatures.h-88-#define X86_FEATURE_REP_GOOD\t\t( 3*32+16) /* \"rep_good\" REP microcode works well */\narch/x86/include/asm/cpufeatures.h:89:#define X86_FEATURE_AMD_LBR_V2\t\t( 3*32+17) /* \"amd_lbr_v2\" AMD Last Branch Record Extension Version 2 */\narch/x86/include/asm/cpufeatures.h-90-#define X86_FEATURE_CLEAR_CPU_BUF\t( 3*32+18) /* Clear CPU buffers using VERW */\n--\narch/x86/kernel/cpu/scattered.c=26=static const struct cpuid_bit cpuid_bits[] = {\n--\narch/x86/kernel/cpu/scattered.c-66-\t{ X86_FEATURE_PERFMON_V2,\t\tCPUID_EAX, 0, 0x80000022, 0 },\narch/x86/kernel/cpu/scattered.c:67:\t{ X86_FEATURE_AMD_LBR_V2,\t\tCPUID_EAX, 1, 0x80000022, 0 },\narch/x86/kernel/cpu/scattered.c-68-\t{ X86_FEATURE_AMD_LBR_PMC_FREEZE,\tCPUID_EAX, 2, 0x80000022, 0 },\n--\narch/x86/kvm/cpuid.c=836=void kvm_initialize_cpu_caps(void)\n--\narch/x86/kvm/cpuid.c-1269-\t\tSCATTERED_F(PERFMON_V2),\narch/x86/kvm/cpuid.c:1270:\t\tSCATTERED_F(AMD_LBR_V2),\narch/x86/kvm/cpuid.c-1271-\t\tSCATTERED_F(AMD_LBR_PMC_FREEZE),\n--\narch/x86/kvm/cpuid.c=1420=static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)\n--\narch/x86/kvm/cpuid.c-1888-\narch/x86/kvm/cpuid.c:1889:\t\tif (kvm_cpu_cap_has(X86_FEATURE_AMD_LBR_V2))\narch/x86/kvm/cpuid.c-1890-\t\t\tebx.split.lbr_v2_stack_sz =\n--\narch/x86/kvm/reverse_cpuid.h-73-#define KVM_X86_FEATURE_PERFMON_V2\t\tKVM_X86_FEATURE(CPUID_8000_0022_EAX, 0)\narch/x86/kvm/reverse_cpuid.h:74:#define KVM_X86_FEATURE_AMD_LBR_V2\t\tKVM_X86_FEATURE(CPUID_8000_0022_EAX, 1)\narch/x86/kvm/reverse_cpuid.h-75-#define KVM_X86_FEATURE_AMD_LBR_PMC_FREEZE\tKVM_X86_FEATURE(CPUID_8000_0022_EAX, 2)\n--\narch/x86/kvm/reverse_cpuid.h=140=static __always_inline u32 __feature_translate(int x86_feature)\n--\narch/x86/kvm/reverse_cpuid.h-150-\tKVM_X86_TRANSLATE_FEATURE(PERFMON_V2);\narch/x86/kvm/reverse_cpuid.h:151:\tKVM_X86_TRANSLATE_FEATURE(AMD_LBR_V2);\narch/x86/kvm/reverse_cpuid.h-152-\tKVM_X86_TRANSLATE_FEATURE(AMD_LBR_PMC_FREEZE);\n--\narch/x86/kvm/svm/svm.c=747=static bool svm_lbrv2_supported(struct kvm_vcpu *vcpu)\narch/x86/kvm/svm/svm.c-748-{\narch/x86/kvm/svm/svm.c:749:\treturn guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_V2) \u0026\u0026\narch/x86/kvm/svm/svm.c-750-\t kvm_vcpu_has_mediated_pmu(vcpu);\n--\narch/x86/kvm/svm/svm.c=4841=static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/svm/svm.c-4866-\narch/x86/kvm/svm/svm.c:4867:\tif (guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_V2) \u0026\u0026\narch/x86/kvm/svm/svm.c-4868-\t cpuid_query_lbrv2_stack_size(vcpu) != SVM_LBR_V2_STACK_SIZE)\narch/x86/kvm/svm/svm.c:4869:\t\tguest_cpu_cap_clear(vcpu, X86_FEATURE_AMD_LBR_V2);\narch/x86/kvm/svm/svm.c-4870-\n--\narch/x86/kvm/svm/svm.c=5641=static __init void svm_set_cpu_caps(void)\n--\narch/x86/kvm/svm/svm.c-5719-\t\t !kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2))\narch/x86/kvm/svm/svm.c:5720:\t\t\tkvm_cpu_cap_clear(X86_FEATURE_AMD_LBR_V2);\narch/x86/kvm/svm/svm.c-5721-\t}\n--\ntools/arch/x86/include/asm/cpufeatures.h-88-#define X86_FEATURE_REP_GOOD\t\t( 3*32+16) /* \"rep_good\" REP microcode works well */\ntools/arch/x86/include/asm/cpufeatures.h:89:#define X86_FEATURE_AMD_LBR_V2\t\t( 3*32+17) /* \"amd_lbr_v2\" AMD Last Branch Record Extension Version 2 */\ntools/arch/x86/include/asm/cpufeatures.h-90-#define X86_FEATURE_CLEAR_CPU_BUF\t( 3*32+18) /* Clear CPU buffers using VERW */\n"
} |
| 5/2 | 2026/07/26 07:40 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11533 output: 20 thoughts: 501 Thoughts: **Analyzing the KVM Patch for AMD LBR V2 Support** Okay, so I'm looking at this patch implementing LBR V2 support for AMD processors within KVM. My first thought is to zero in on the core modifications, which, as expected, are happening within `arch/x86/kvm/svm/svm.c`. It's all about adding the MSR interception and handling logic for the new MSRs: `MSR_AMD_DBG_EXTN_CFG`, `MSR_AMD64_LBR_SELECT`, and `MSR_AMD_SAMP_BR_FROM`. That's where the interesting stuff will be. I'm initially focusing on the key functions involved: `svm_recalc_lbrv2_msr_intercepts`, `svm_lbrv2_supported`, `svm_lbrv2_active`, `svm_update_lbrv`, `svm_get_msr`, `svm_set_msr`, `cpuid_query_lbrv2_stack_size`, `svm_vcpu_after_set_cpuid`, and `svm_set_cpu_caps`. My immediate instinct is to check `svm_get_msr` and `svm_set_msr` as potential fuzzing targets. They're pretty generic KVM hot-path functions but they are the entrypoints to handle the new MSRs. It’s pretty obvious they're going to be important. Wait, I'm second-guessing myself a bit now. Those are really broad functions and fuzzing them directly could be a challenge. Maybe there are other, more targeted functions I can leverage? Okay, let me see. `svm_recalc_lbrv2_msr_intercepts` is static, which might make it harder to target directly, unless it's inlined. I need to see if there are any non-static functions added or modified. Alright, I see `svm_vcpu_free_msrpm` is modified. And I also see some static functions: `svm_recalc_msr_intercepts`, `svm_vcpu_create`, `svm_vmcb_lbr`, `svm_vmcb_lbrv2`, and `sev_es_prevent_msr_access`. Okay, so `svm_enable_lbrv`, `svm_update_lbrv`, and `disable_nmi_singlestep` are non-static. Something doesn't feel right. `svm_get_msr` is listed as static? That's unusual. I need to double-check that; I'll definitely want to ensure that it's actually static. I'll need to confirm that. |
| 6/2 | 2026/07/26 07:40 | tool | grepper |
0mArgs:{
"Expression": "svm_get_msr"
}Results: {
"Output": "arch/x86/kvm/svm/svm.c=2859=static bool svm_pat_accesses_gpat(struct kvm_vcpu *vcpu, bool from_host)\n--\narch/x86/kvm/svm/svm.c-2872-\narch/x86/kvm/svm/svm.c:2873:static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)\narch/x86/kvm/svm/svm.c-2874-{\n--\narch/x86/kvm/svm/svm.c=5457=struct kvm_x86_ops svm_x86_ops __initdata = {\n--\narch/x86/kvm/svm/svm.c-5484-\t.get_feature_msr = svm_get_feature_msr,\narch/x86/kvm/svm/svm.c:5485:\t.get_msr = svm_get_msr,\narch/x86/kvm/svm/svm.c-5486-\t.set_msr = svm_set_msr,\n"
} |
| 7/2 | 2026/07/26 07:40 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12961 output: 21 thoughts: 166 Thoughts: **Analyzing MSR Access in the AMD-V Implementation** Okay, so `svm_get_msr` and `svm_set_msr` are static functions, I see that. But the fact that they're registered in `svm_x86_ops` makes them entry points for MSR accesses, essentially the public interface, doesn't it? Hmm, the instructions mention preferring non-static, non-inlined API entrypoints over internal static helper functions. The logic is clear, inlined functions lack distinct symbols. But hold on a second. Because `svm_get_msr` and `svm_set_msr` are assigned to function pointers, that actually prevents them from being *fully* inlined, right? Taking their address gives them a symbol address, regardless. That changes the calculus somewhat. Still, they are very hot paths in the code so we need to be careful. Let me shift gears and consider `svm_update_lbrv` and `svm_enable_lbrv`. |
| 8/2 | 2026/07/26 07:40 | tool | grepper |
0mArgs:{
"Expression": "svm_update_lbrv"
}Results: {
"Output": "arch/x86/kvm/svm/nested.c=745=static void nested_vmcb02_prepare_save(struct vcpu_svm *svm)\n--\narch/x86/kvm/svm/nested.c-825-\tvmcb_mark_dirty(vmcb02, VMCB_LBR);\narch/x86/kvm/svm/nested.c:826:\tsvm_update_lbrv(\u0026svm-\u003evcpu);\narch/x86/kvm/svm/nested.c-827-}\n--\narch/x86/kvm/svm/nested.c=853=static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)\n--\narch/x86/kvm/svm/nested.c-987-\narch/x86/kvm/svm/nested.c:988:\t/* SVM_MISC2_ENABLE_V_LBR is controlled by svm_update_lbrv() */\narch/x86/kvm/svm/nested.c-989-\n--\narch/x86/kvm/svm/nested.c=1322=void nested_svm_vmexit(struct vcpu_svm *svm)\n--\narch/x86/kvm/svm/nested.c-1386-\narch/x86/kvm/svm/nested.c:1387:\tsvm_update_lbrv(vcpu);\narch/x86/kvm/svm/nested.c-1388-\n--\narch/x86/kvm/svm/svm.c=917=static void __svm_disable_lbrv(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/svm/svm.c-922-\narch/x86/kvm/svm/svm.c:923:void svm_update_lbrv(struct kvm_vcpu *vcpu)\narch/x86/kvm/svm/svm.c-924-{\n--\narch/x86/kvm/svm/svm.c=3051=static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)\n--\narch/x86/kvm/svm/svm.c-3250-\t\tvmcb_mark_dirty(svm-\u003evmcb, VMCB_LBR);\narch/x86/kvm/svm/svm.c:3251:\t\tsvm_update_lbrv(vcpu);\narch/x86/kvm/svm/svm.c-3252-\t\tbreak;\n--\narch/x86/kvm/svm/svm.c-3275-\t\tvmcb_mark_dirty(svm-\u003evmcb, VMCB_LBR);\narch/x86/kvm/svm/svm.c:3276:\t\tsvm_update_lbrv(vcpu);\narch/x86/kvm/svm/svm.c-3277-\t\tbreak;\n--\narch/x86/kvm/svm/svm.h=813=void svm_enable_lbrv(struct kvm_vcpu *vcpu);\narch/x86/kvm/svm/svm.h:814:void svm_update_lbrv(struct kvm_vcpu *vcpu);\narch/x86/kvm/svm/svm.h-815-\n"
} |
| 9/2 | 2026/07/26 07:40 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14238 output: 21 thoughts: 39 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience: **Considering Logical Branch Record Virtualization (LBRV) Updates** Right, so I'm thinking about the most relevant functions for this particular issue. My initial thought is to zero in on `svm_update_lbrv`. It's a strong contender given the name. But I need to consider all possibilities and not jump to conclusions. So, I'm also putting `svm_enable_lbrv` on the short list. I need to figure out which is more relevant and/or complementary. I'll take a closer look at `svm_enable_lbrv` first. I want to check its implementation and interaction with related structures. That should give me a good jumping off point. |
| 10/2 | 2026/07/26 07:40 | tool | grepper |
0mArgs:{
"Expression": "svm_enable_lbrv"
}Results: {
"Output": "arch/x86/kvm/svm/sev.c=1065=static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu,\n--\narch/x86/kvm/svm/sev.c-1111-\t */\narch/x86/kvm/svm/sev.c:1112:\tsvm_enable_lbrv(vcpu);\narch/x86/kvm/svm/sev.c-1113-\treturn 0;\n--\narch/x86/kvm/svm/sev.c=2480=static int snp_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp)\n--\narch/x86/kvm/svm/sev.c-2528-\t\t */\narch/x86/kvm/svm/sev.c:2529:\t\tsvm_enable_lbrv(vcpu);\narch/x86/kvm/svm/sev.c-2530-\t}\n--\narch/x86/kvm/svm/svm.c=827=static void svm_recalc_msr_intercepts(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/svm/svm.c-904-\narch/x86/kvm/svm/svm.c:905:static void __svm_enable_lbrv(struct kvm_vcpu *vcpu)\narch/x86/kvm/svm/svm.c-906-{\n--\narch/x86/kvm/svm/svm.c-909-\narch/x86/kvm/svm/svm.c:910:void svm_enable_lbrv(struct kvm_vcpu *vcpu)\narch/x86/kvm/svm/svm.c-911-{\narch/x86/kvm/svm/svm.c:912:\t__svm_enable_lbrv(vcpu);\narch/x86/kvm/svm/svm.c-913-\tsvm_recalc_lbr_msr_intercepts(vcpu);\n--\narch/x86/kvm/svm/svm.c=923=void svm_update_lbrv(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/svm/svm.c-933-\tif (enable_lbrv \u0026\u0026 !current_enable_lbrv)\narch/x86/kvm/svm/svm.c:934:\t\t__svm_enable_lbrv(vcpu);\narch/x86/kvm/svm/svm.c-935-\telse if (!enable_lbrv \u0026\u0026 current_enable_lbrv)\n--\narch/x86/kvm/svm/svm.h=812=void svm_vcpu_free_msrpm(void *msrpm);\narch/x86/kvm/svm/svm.h:813:void svm_enable_lbrv(struct kvm_vcpu *vcpu);\narch/x86/kvm/svm/svm.h-814-void svm_update_lbrv(struct kvm_vcpu *vcpu);\n"
} |
| 11/2 | 2026/07/26 07:40 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15295 output: 26 thoughts: 449 Thoughts: **My Analysis of the Code Changes** Okay, so I'm diving into this `svm_update_lbrv` function, triggered by writes to `MSR_AMD_DBG_EXTN_CFG` via `svm_set_msr`. That's a clear entry point to focus on, and a good starting point. My thinking is, let's look at the broader picture. What about `svm_set_msr` and `svm_get_msr`? They're the primary handlers for all MSR interactions. They've been adapted for these new `MSR_AMD_DBG_EXTN_CFG`, `MSR_AMD64_LBR_SELECT`, and `MSR_AMD_SAMP_BR_FROM` MSRs. I will add these to my list. I will also make sure to investigate `svm_get_msr` and `svm_set_msr` since they are the core functions handling the new MSRs. Even though they're likely performance-critical paths, they're the only routes to reach the new logic. Wait, hold on a second. `svm_get_msr` and `svm_set_msr` *are* extremely hot. Is there a more efficient way to trace this change? Hmm... Maybe `svm_recalc_lbrv2_msr_intercepts`? It's a static function, which often means it could be inlined. It's called from `svm_update_lbrv` and `svm_recalc_msr_intercepts`. I will check if it's been inlined by the compiler. I'll quickly check `svm_lbrv2_supported` and `svm_lbrv2_active`. They're static, short, and likely inlined, so they probably won't be significant to my research. Now, let's broaden the scope. I need to understand the architectural context. Let's look at `arch/x86/kvm/cpuid.c`. I see `kvm_initialize_cpu_caps` and `__do_cpuid_func` have been modified. These aren't explicitly tied to LBR V2, but they've been touched, so they need a look. Finally, I'll take a glance at `arch/x86/events/core.c`. I notice changes in `perf_get_x86_pmu_capability`. That's the scope of the changes I've seen so far. |
| 12/2 | 2026/07/26 07:40 | tool | grepper |
0mArgs:{
"Expression": "perf_get_x86_pmu_capability"
}Results: {
"Output": "arch/x86/events/core.c=3111=unsigned long perf_arch_misc_flags(struct pt_regs *regs)\n--\narch/x86/events/core.c-3119-\narch/x86/events/core.c:3120:void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)\narch/x86/events/core.c-3121-{\n--\narch/x86/events/core.c-3144-}\narch/x86/events/core.c:3145:EXPORT_SYMBOL_FOR_KVM(perf_get_x86_pmu_capability);\narch/x86/events/core.c-3146-\n--\narch/x86/include/asm/perf_event.h=759=struct x86_pmu_lbr {\n--\narch/x86/include/asm/perf_event.h-766-\narch/x86/include/asm/perf_event.h:767:extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap);\narch/x86/include/asm/perf_event.h-768-extern u64 perf_get_hw_event_config(int hw_event);\n--\narch/x86/include/asm/perf_event.h=771=extern int x86_perf_rdpmc_index(struct perf_event *event);\narch/x86/include/asm/perf_event.h-772-#else\narch/x86/include/asm/perf_event.h:773:static inline void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)\narch/x86/include/asm/perf_event.h-774-{\n--\narch/x86/kvm/pmu.c=133=void kvm_init_pmu_capability(struct kvm_pmu_ops *pmu_ops)\n--\narch/x86/kvm/pmu.c-147-\t} else {\narch/x86/kvm/pmu.c:148:\t\tperf_get_x86_pmu_capability(\u0026kvm_host_pmu);\narch/x86/kvm/pmu.c-149-\t}\n"
} |
| 13/2 | 2026/07/26 07:41 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 16950 output: 21 thoughts: 62 Thoughts: **Fuzzing the PMU Capability Check** Okay, so `perf_get_x86_pmu_capability` is exported for KVM – that's interesting. A potential target for fuzzing, definitely. However, if I recall correctly, it's only called during initialization, specifically within `kvm_init_pmu_capability`. Hmm, that limits its attack surface somewhat, doesn't it? Still, fuzzing initialization can be fruitful. But let's see, what else can we dig up? I wonder if `svm_set_cpu_caps` is worth a look. Might be some interesting interactions there that we can exploit. |
| 14/2 | 2026/07/26 07:41 | tool | grepper |
0mArgs:{
"Expression": "svm_set_cpu_caps"
}Results: {
"Output": "arch/x86/kvm/svm/svm.c=5606=static __init void svm_adjust_mmio_mask(void)\n--\narch/x86/kvm/svm/svm.c-5640-\narch/x86/kvm/svm/svm.c:5641:static __init void svm_set_cpu_caps(void)\narch/x86/kvm/svm/svm.c-5642-{\n--\narch/x86/kvm/svm/svm.c=5737=static __init int svm_hardware_setup(void)\n--\narch/x86/kvm/svm/svm.c-5887-\narch/x86/kvm/svm/svm.c:5888:\tsvm_set_cpu_caps();\narch/x86/kvm/svm/svm.c-5889-\n"
} |
| 15/2 | 2026/07/26 07:41 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 17410 output: 25 thoughts: 48 Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience: **Analyzing CPUID Hook Placement for Fuzzing** Hmm, so `svm_set_cpu_caps` is being called during the module's initialization phase. That's essentially tied to the module loading process, right? Which means it's not going to be triggered dynamically, and certainly not during a fuzzing campaign. That's a definite limitation. If I'm trying to fuzz CPUID-related vulnerabilities, I need something that's reachable under more varied execution conditions. Let me pivot. Let's shift our focus and see if `svm_vcpu_after_set_cpuid` provides a more viable hook. Perhaps this callback is invoked after a vCPU is initialized or on a per-VM basis, opening up more interesting fuzzing opportunities. |
| 16/2 | 2026/07/26 07:41 | tool | grepper |
0mArgs:{
"Expression": "svm_vcpu_after_set_cpuid"
}Results: {
"Output": "arch/x86/kvm/svm/svm.c=4827=static int cpuid_query_lbrv2_stack_size(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/svm/svm.c-4840-\narch/x86/kvm/svm/svm.c:4841:static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)\narch/x86/kvm/svm/svm.c-4842-{\n--\narch/x86/kvm/svm/svm.c=5457=struct kvm_x86_ops svm_x86_ops __initdata = {\n--\narch/x86/kvm/svm/svm.c-5545-\narch/x86/kvm/svm/svm.c:5546:\t.vcpu_after_set_cpuid = svm_vcpu_after_set_cpuid,\narch/x86/kvm/svm/svm.c-5547-\n"
} |
| 17/2 | 2026/07/26 07:41 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 17945 output: 19 thoughts: 157 Thoughts: **My Fuzzing Strategy for AMD KVM vCPUs** Okay, so I'm thinking about how to effectively fuzz the AMD KVM vCPU code, and `svm_vcpu_after_set_cpuid` really jumps out at me. The fact that it's triggered by userspace via `KVM_SET_CPUID2` makes it a prime candidate for fuzzing. User-controlled input directly influences its execution, so that's where I need to focus my initial efforts. Naturally, I need to look at the Microprocessor Specific Registers (MSRs). So, I'll definitely be including `svm_get_msr` and `svm_set_msr` in the fuzzing scope; they are the main entrypoints for interactions there. I also see that `svm_update_lbrv` needs to be considered. Then, of course, I must look at `svm_vcpu_after_set_cpuid` to round that out. Now, let's think about the build configurations that are relevant here. I'll need to verify the dependencies. Namely, `CONFIG_KVM`, `CONFIG_KVM_AMD`, and `CONFIG_PERF_EVENTS` are the obvious ones. But, I should also double-check and see if there are any other configs that might subtly influence the behavior of the code I'm targeting. I want to be thorough and minimize the risk of missing something critical. |
| 18/2 | 2026/07/26 07:41 | tool | grepper |
0mArgs:{
"Expression": "config KVM_AMD"
}Results: {
"Output": "arch/x86/kvm/Kconfig=134=config KVM_INTEL_TDX\n--\narch/x86/kvm/Kconfig-145-\narch/x86/kvm/Kconfig:146:config KVM_AMD\narch/x86/kvm/Kconfig-147-\ttristate \"KVM for AMD processors support\"\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"
} |
| 19/2 | 2026/07/26 07:41 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 18616 output: 39 thoughts: 24 Thoughts: Here's my thought process, summarized as if I were considering this myself: **Investigating KVM Configuration for AMD Architecture** Okay, so I need to figure out where the KVM configuration options for AMD processors are defined. My first instinct, and the standard practice for this kind of investigation, is to check the relevant Kconfig file. Since we're dealing with x86, the natural starting point is `arch/x86/kvm/Kconfig`. That's where I'd expect to find the conditional logic and definitions related to features specific to AMD processors within the KVM framework. I need to locate the `KVM_AMD` symbol, which likely controls various AMD-specific KVM functionalities. Let's see what's in there. |
| 20/2 | 2026/07/26 07:41 | tool | read-file |
0mArgs:{
"File": "arch/x86/kvm/Kconfig",
"FirstLine": 146,
"LineCount": 20
}Results: {
"Contents": " 146:\tconfig KVM_AMD\n 147:\t\ttristate \"KVM for AMD processors support\"\n 148:\t\tdepends on KVM \u0026\u0026 (CPU_SUP_AMD || CPU_SUP_HYGON)\n 149:\t\thelp\n 150:\t\t Provides support for KVM on AMD processors equipped with the AMD-V\n 151:\t\t (SVM) extensions.\n 152:\t\n 153:\t\t To compile this as a module, choose M here: the module\n 154:\t\t will be called kvm-amd.\n 155:\t\n 156:\tconfig KVM_AMD_SEV\n 157:\t\tbool \"AMD Secure Encrypted Virtualization (SEV) support\"\n 158:\t\tdefault y\n 159:\t\tdepends on KVM_AMD \u0026\u0026 X86_64\n 160:\t\tdepends on CRYPTO_DEV_SP_PSP \u0026\u0026 !(KVM_AMD=y \u0026\u0026 CRYPTO_DEV_CCP_DD=m)\n 161:\t\tselect ARCH_HAS_CC_PLATFORM\n 162:\t\tselect KVM_GENERIC_MEMORY_ATTRIBUTES\n 163:\t\tselect HAVE_KVM_ARCH_GMEM_PREPARE\n 164:\t\tselect HAVE_KVM_ARCH_GMEM_INVALIDATE\n 165:\t\tselect HAVE_KVM_ARCH_GMEM_POPULATE\n"
} |
| 21/2 | 2026/07/26 07:41 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 19202 output: 19 thoughts: 239 Thoughts: **Analyzing KVM Dependencies** Okay, let's break this down. From what I'm seeing, `KVM_AMD` is, as expected, reliant on both the core `KVM` module and `CPU_SUP_AMD`. That makes sense; AMD-specific virtualization features definitely need the base KVM infrastructure and the CPU support. Now, `KVM` itself is where things get more interesting and, as an expert, I know these dependencies inside and out. It's built upon a comprehensive foundation: `HIGH_RES_TIMERS`, `X86_LOCAL_APIC`, `PREEMPT_NOTIFIERS`, `MMU_NOTIFIER`, and all the `HAVE_KVM_*` features related to interrupt handling, event management, and routing. The inclusion of `KVM_ASYNC_PF`, its sync counterpart, and the generic dirty log feature indicate performance optimizations and memory management are critical components. Additionally, `KVM_VFIO` support shows that device pass-through is fully enabled, and the PM and user-return notifications ensure power management and user-space interactions are considered. Finally, `KVM_GENERIC_HARDWARE_ENABLING`, `HAVE_KVM_CPU_RELAX_INTERCEPT`, and `KVM_XFER_TO_GUEST_WORK` suggest that general hardware enablement and CPU interactions are also accounted for within the core modules. Generally, a base setup containing `KVM` and `KVM_AMD` should be sufficient for many typical virtualization needs. However, I need to also check the `PERF_EVENTS` setting to get a full and complete view. |
| 22/2 | 2026/07/26 07:41 | tool | grepper |
0mArgs:{
"Expression": "config PERF_EVENTS"
}Results: {
"Output": "arch/x86/events/Kconfig=2=menu \"Performance monitoring\"\narch/x86/events/Kconfig-3-\narch/x86/events/Kconfig:4:config PERF_EVENTS_INTEL_UNCORE\narch/x86/events/Kconfig-5-\ttristate \"Intel uncore performance events\"\n--\narch/x86/events/Kconfig-11-\narch/x86/events/Kconfig:12:config PERF_EVENTS_INTEL_RAPL\narch/x86/events/Kconfig-13-\ttristate \"Intel/AMD rapl performance events\"\n--\narch/x86/events/Kconfig-19-\narch/x86/events/Kconfig:20:config PERF_EVENTS_INTEL_CSTATE\narch/x86/events/Kconfig-21-\ttristate \"Intel cstate performance events\"\n--\narch/x86/events/Kconfig-27-\narch/x86/events/Kconfig:28:config PERF_EVENTS_AMD_POWER\narch/x86/events/Kconfig-29-\tdepends on PERF_EVENTS \u0026\u0026 CPU_SUP_AMD\n--\narch/x86/events/Kconfig-36-\narch/x86/events/Kconfig:37:config PERF_EVENTS_AMD_UNCORE\narch/x86/events/Kconfig-38-\ttristate \"AMD Uncore performance events\"\n--\narch/x86/events/Kconfig-47-\narch/x86/events/Kconfig:48:config PERF_EVENTS_AMD_BRS\narch/x86/events/Kconfig-49-\tdepends on PERF_EVENTS \u0026\u0026 CPU_SUP_AMD\n--\ninit/Kconfig=2121=menu \"Kernel Performance Events And Counters\"\ninit/Kconfig-2122-\ninit/Kconfig:2123:config PERF_EVENTS\ninit/Kconfig-2124-\tbool \"Kernel performance events and counters\"\n"
} |
| 23/2 | 2026/07/26 07:41 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 20322 output: 36 thoughts: 37 Thoughts: Here's my thought process, summarized as you requested: **Investigating Performance Event Configuration** Okay, so I'm looking at how performance events are configured within the kernel. My immediate thought is to check `init/Kconfig` – I know that's often the root level for these kinds of feature flags. I expect to find the top-level definition of `PERF_EVENTS` there. Next, since I'm trying to pinpoint AMD-specific configurations, I'll drill down. I'll need to look in `arch/x86/events/Kconfig`. I'm specifically hunting for any AMD-related or AMD-prefixed config options within that file. That would be the logical place to find any conditional or specialized settings. I expect I might find something that ties into the CPU model or specific features of AMD processors. Let's see what's in there. |
| 24/2 | 2026/07/26 07:41 | tool | read-file |
0mArgs:{
"File": "arch/x86/events/Kconfig",
"FirstLine": 1,
"LineCount": 50
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0\n 2:\tmenu \"Performance monitoring\"\n 3:\t\n 4:\tconfig PERF_EVENTS_INTEL_UNCORE\n 5:\t\ttristate \"Intel uncore performance events\"\n 6:\t\tdepends on PERF_EVENTS \u0026\u0026 CPU_SUP_INTEL \u0026\u0026 PCI\n 7:\t\tdefault y\n 8:\t\thelp\n 9:\t\t Include support for Intel uncore performance events. These are\n 10:\t\t available on NehalemEX and more modern processors.\n 11:\t\n 12:\tconfig PERF_EVENTS_INTEL_RAPL\n 13:\t\ttristate \"Intel/AMD rapl performance events\"\n 14:\t\tdepends on PERF_EVENTS \u0026\u0026 (CPU_SUP_INTEL || CPU_SUP_AMD) \u0026\u0026 PCI\n 15:\t\tdefault y\n 16:\t\thelp\n 17:\t\t Include support for Intel and AMD rapl performance events for power\n 18:\t\t monitoring on modern processors.\n 19:\t\n 20:\tconfig PERF_EVENTS_INTEL_CSTATE\n 21:\t\ttristate \"Intel cstate performance events\"\n 22:\t\tdepends on PERF_EVENTS \u0026\u0026 CPU_SUP_INTEL \u0026\u0026 PCI\n 23:\t\tdefault y\n 24:\t\thelp\n 25:\t\t Include support for Intel cstate performance events for power\n 26:\t\t monitoring on modern processors.\n 27:\t\n 28:\tconfig PERF_EVENTS_AMD_POWER\n 29:\t\tdepends on PERF_EVENTS \u0026\u0026 CPU_SUP_AMD\n 30:\t\ttristate \"AMD Processor Power Reporting Mechanism\"\n 31:\t\thelp\n 32:\t\t Provide power reporting mechanism support for AMD processors.\n 33:\t\t Currently, it leverages X86_FEATURE_ACC_POWER\n 34:\t\t (CPUID Fn8000_0007_EDX[12]) interface to calculate the\n 35:\t\t average power consumption on Family 15h processors.\n 36:\t\n 37:\tconfig PERF_EVENTS_AMD_UNCORE\n 38:\t\ttristate \"AMD Uncore performance events\"\n 39:\t\tdepends on PERF_EVENTS \u0026\u0026 CPU_SUP_AMD\n 40:\t\tdefault y\n 41:\t\thelp\n 42:\t\t Include support for AMD uncore performance events for use with\n 43:\t\t e.g., perf stat -e amd_l3/.../,amd_df/.../.\n 44:\t\n 45:\t\t To compile this driver as a module, choose M here: the\n 46:\t\t module will be called 'amd-uncore'.\n 47:\t\n 48:\tconfig PERF_EVENTS_AMD_BRS\n 49:\t\tdepends on PERF_EVENTS \u0026\u0026 CPU_SUP_AMD\n 50:\t\tbool \"AMD Zen3 Branch Sampling support\"\n"
} |
| 25/2 | 2026/07/26 07:41 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 21309 output: 217 thoughts: 1351 Thoughts: **KVM AMD LBR V2 Fuzzing Strategy** Okay, so I've been assessing the potential fuzzing targets for this KVM patch implementing AMD LBR V2 support. First, I've confirmed that the necessary Kconfig options are enabled: `KVM`, `KVM_AMD`, `PERF_EVENTS`, and `CPU_SUP_AMD`. That's the baseline. My initial thought was to include `svm_get_msr` and `svm_set_msr`, as they're central to any MSR handling in the SVM code. They're definitely hot paths. However, the guidance is to prioritize API entrypoints that aren't overly generic or static to avoid skewing the fuzzing distribution. While `svm_get_msr` and `svm_set_msr` are critical for hitting the new MSR-related code, they cover *all* MSRs, and that level of generality might not be ideal for focused fuzzing on this patch's specific functionality. After reviewing the patch and the surrounding code, I'm focusing on these key functions: * `svm_update_lbrv`: This one is interesting; it's a non-static function directly involved in updating LBR virtualization and is linked to `svm_recalc_lbrv2_msr_intercepts`. * `svm_enable_lbrv`: Also non-static. This seems important, as it enables LBR V2 functionality, and calls `svm_recalc_lbrv2_msr_intercepts` and `svm_recalc_lbr_msr_intercepts`. * `svm_vcpu_after_set_cpuid`: This is a callback function in `svm_x86_ops`, which is not inlined, and is specifically related to CPUID updates, and interacts with new feature bits. Since this patch adds support for new MSRs (`MSR_AMD_DBG_EXTN_CFG`, `MSR_AMD64_LBR_SELECT`, `MSR_AMD_SAMP_BR_FROM`) and new CPUID features (`AMD_LBR_V2`, `AMD_LBR_PMC_FREEZE`), these functions represent good entry points to exercise the new code paths. I've also decided to include `perf_get_x86_pmu_capability`. It's a non-static, exported function and is called during KVM PMU initialization. It is not on the hot path. I've checked some other functions like `cpuid_query_lbrv2_stack_size`, `svm_lbrv2_supported`, and `svm_lbrv2_active`. These are static and small, so they're probably inlined and not good candidates. So, the fuzzing strategy is defined. I will be sure to focus on these functions to target the new LBR V2 functionality. |
| 26/2 | 2026/07/26 07:41 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"KVM",
"KVM_AMD",
"PERF_EVENTS",
"CPU_SUP_AMD"
],
"FocusSymbols": [
"svm_update_lbrv",
"svm_enable_lbrv",
"svm_vcpu_after_set_cpuid",
"perf_get_x86_pmu_capability"
],
"Reasoning": "The patch adds support for AMD LBR V2 (Last Branch Record Version 2) in KVM. It modifies SVM to handle new MSRs (MSR_AMD_DBG_EXTN_CFG, MSR_AMD64_LBR_SELECT, MSR_AMD_SAMP_BR_FROM) and CPUID features (AMD_LBR_V2, AMD_LBR_PMC_FREEZE). This is a functional change in the core KVM AMD virtualization logic and should be fuzzed.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"KVM",
"KVM_AMD",
"PERF_EVENTS",
"CPU_SUP_AMD"
],
"FocusSymbols": [
"svm_update_lbrv",
"svm_enable_lbrv",
"svm_vcpu_after_set_cpuid",
"perf_get_x86_pmu_capability"
],
"Reasoning": "The patch adds support for AMD LBR V2 (Last Branch Record Version 2) in KVM. It modifies SVM to handle new MSRs (MSR_AMD_DBG_EXTN_CFG, MSR_AMD64_LBR_SELECT, MSR_AMD_SAMP_BR_FROM) and CPUID features (AMD_LBR_V2, AMD_LBR_PMC_FREEZE). This is a functional change in the core KVM AMD virtualization logic and should be fuzzed.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|