| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/08 21:49 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": [
"KVM_AMD",
"AMD_IOMMU",
"IRQ_REMAP"
],
"FocusSymbols": [
"avic_update_iommu_vcpu_affinity",
"amd_iommu_update_ga",
"amd_iommu_activate_guest_mode",
"avic_pi_update_irte",
"__amd_iommu_update_ga",
"avic_add_vcpu_to_gappi_wakeup_list",
"avic_remove_vcpu_from_gappi_wakeup_list",
"avic_gappi_wakeup_handler",
"avic_destroy_vcpu",
"svm_ir_list_del"
],
"Reasoning": "The patch introduces Guest APIC Posted Interrupts (GAPPI) support for AMD IOMMU and KVM SVM AVIC. It modifies the interrupt remapping table entry updates and vCPU affinity logic, which are reachable in virtualized environments (e.g., QEMU with KVM SVM). The changes alter core AVIC and IOMMU logic even when GAPPI is not explicitly enabled via boot parameter, making it functional and worth fuzzing.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/08 21:49 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit eaea02c5c6a81a4a71795126a2885e00fbdaa164\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Jul 8 21:49:00 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h\nindex 37b94f484ef338..40a2206a33c08d 100644\n--- a/arch/x86/include/asm/irq_remapping.h\n+++ b/arch/x86/include/asm/irq_remapping.h\n@@ -35,8 +35,8 @@ struct amd_iommu_pi_data {\n \tu64 vapic_addr;\t\t/* Physical address of the vCPU's vAPIC. */\n \tu32 ga_tag;\n \tu32 vector;\t\t/* Guest vector of the interrupt */\n-\tint cpu;\n-\tbool ga_log_intr;\n+\tint apicid;\n+\tint flags;\n \tbool is_guest_mode;\n \tvoid *ir_data;\n };\ndiff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c\nindex cdd5a6dc646f11..8185841d9b8165 100644\n--- a/arch/x86/kvm/svm/avic.c\n+++ b/arch/x86/kvm/svm/avic.c\n@@ -63,6 +63,9 @@\n \tga_tag;\t\t\t\t\t\t\t\t\\\n })\n \n+static DEFINE_PER_CPU(struct list_head, gappi_vcpu_wakeup_list);\n+static DEFINE_PER_CPU(raw_spinlock_t, gappi_vcpu_wakeup_list_lock);\n+\n static_assert(__AVIC_GATAG(AVIC_VM_ID_MASK, AVIC_VCPU_IDX_MASK) == -1u);\n \n #define AVIC_AUTO_MODE -1\n@@ -874,6 +877,9 @@ int avic_init_vcpu(struct vcpu_svm *svm)\n \tINIT_LIST_HEAD(\u0026svm-\u003eir_list);\n \traw_spin_lock_init(\u0026svm-\u003eir_list_lock);\n \n+\tINIT_LIST_HEAD(\u0026svm-\u003egappi_vcpu_wakeup_list);\n+\tsvm-\u003egappi_cpu = -1;\n+\n \tif (!enable_apicv || !irqchip_in_kernel(vcpu-\u003ekvm))\n \t\treturn 0;\n \n@@ -886,6 +892,42 @@ int avic_init_vcpu(struct vcpu_svm *svm)\n \treturn ret;\n }\n \n+static void avic_add_vcpu_to_gappi_wakeup_list(struct vcpu_svm *svm, int cpu)\n+{\n+\tstruct list_head *wakeup_list;\n+\traw_spinlock_t *spinlock;\n+\n+\tif (WARN_ON(cpu \u003c 0))\n+\t\treturn;\n+\n+\twakeup_list = \u0026per_cpu(gappi_vcpu_wakeup_list, cpu);\n+\tspinlock = \u0026per_cpu(gappi_vcpu_wakeup_list_lock, cpu);\n+\tguard(raw_spinlock_irqsave)(spinlock);\n+\tif (list_empty(\u0026svm-\u003egappi_vcpu_wakeup_list))\n+\t\tlist_add_tail(\u0026svm-\u003egappi_vcpu_wakeup_list, wakeup_list);\n+}\n+\n+static void avic_remove_vcpu_from_gappi_wakeup_list(struct vcpu_svm *svm, int cpu)\n+{\n+\traw_spinlock_t *spinlock;\n+\n+\tif (WARN_ON(cpu \u003c 0))\n+\t\treturn;\n+\n+\tspinlock = \u0026per_cpu(gappi_vcpu_wakeup_list_lock, cpu);\n+\tguard(raw_spinlock_irqsave)(spinlock);\n+\tif (!list_empty(\u0026svm-\u003egappi_vcpu_wakeup_list))\n+\t\tlist_del_init(\u0026svm-\u003egappi_vcpu_wakeup_list);\n+}\n+\n+void avic_destroy_vcpu(struct vcpu_svm *svm)\n+{\n+\tif (svm-\u003egappi_cpu != -1 \u0026\u0026 amd_iommu_gappi) {\n+\t\tavic_remove_vcpu_from_gappi_wakeup_list(svm, svm-\u003egappi_cpu);\n+\t\tsvm-\u003egappi_cpu = -1;\n+\t}\n+}\n+\n void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu)\n {\n \tavic_handle_dfr_update(vcpu);\n@@ -896,13 +938,18 @@ static void svm_ir_list_del(struct kvm_kernel_irqfd *irqfd)\n {\n \tstruct kvm_vcpu *vcpu = irqfd-\u003eirq_bypass_vcpu;\n \tunsigned long flags;\n+\tstruct vcpu_svm *svm;\n \n \tif (!vcpu)\n \t\treturn;\n \n-\traw_spin_lock_irqsave(\u0026to_svm(vcpu)-\u003eir_list_lock, flags);\n+\tsvm = to_svm(vcpu);\n+\n+\traw_spin_lock_irqsave(\u0026svm-\u003eir_list_lock, flags);\n \tlist_del(\u0026irqfd-\u003evcpu_list);\n-\traw_spin_unlock_irqrestore(\u0026to_svm(vcpu)-\u003eir_list_lock, flags);\n+\tif (list_empty(\u0026svm-\u003eir_list))\n+\t\tavic_remove_vcpu_from_gappi_wakeup_list(svm, svm-\u003egappi_cpu);\n+\traw_spin_unlock_irqrestore(\u0026svm-\u003eir_list_lock, flags);\n }\n \n int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,\n@@ -932,6 +979,8 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,\n \t\tstruct vcpu_svm *svm = to_svm(vcpu);\n \t\tu64 entry;\n \t\tint ret;\n+\t\tint posted_intr;\n+\t\tbool is_vcpu_waiting = false;\n \n \t\t/*\n \t\t * Prevent the vCPU from being scheduled out or migrated until\n@@ -949,15 +998,23 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,\n \t\t */\n \t\tentry = svm-\u003eavic_physical_id_entry;\n \t\tif (entry \u0026 AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK) {\n-\t\t\tpi_data.cpu = entry \u0026 AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;\n+\t\t\tpi_data.apicid = entry \u0026 AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;\n+\t\t\tpi_data.flags = AMD_IOMMU_FLAG_VCPU_RUNNING;\n \t\t} else {\n-\t\t\tpi_data.cpu = -1;\n-\t\t\tpi_data.ga_log_intr = entry \u0026 AVIC_PHYSICAL_ID_ENTRY_GA_LOG_INTR;\n+\t\t\tposted_intr = !!(entry \u0026 AVIC_PHYSICAL_ID_ENTRY_GA_LOG_INTR);\n+\t\t\tpi_data.flags = posted_intr \u003c\u003c AMD_IOMMU_FLAG_POSTED_INTR_SHIFT;\n+\t\t\tif (amd_iommu_gappi) {\n+\t\t\t\tpi_data.apicid = kvm_cpu_get_apicid(svm-\u003egappi_cpu);\n+\t\t\t\tif (list_empty(\u0026svm-\u003eir_list)) {\n+\t\t\t\t\tavic_add_vcpu_to_gappi_wakeup_list(svm, svm-\u003egappi_cpu);\n+\t\t\t\t\tis_vcpu_waiting = true;\n+\t\t\t\t}\n+\t\t\t}\n \t\t}\n \n \t\tret = irq_set_vcpu_affinity(host_irq, \u0026pi_data);\n \t\tif (ret)\n-\t\t\treturn ret;\n+\t\t\tgoto gappi_err_out;\n \n \t\t/*\n \t\t * Revert to legacy mode if the IOMMU didn't provide metadata\n@@ -966,12 +1023,17 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,\n \t\t */\n \t\tif (WARN_ON_ONCE(!pi_data.ir_data)) {\n \t\t\tirq_set_vcpu_affinity(host_irq, NULL);\n-\t\t\treturn -EIO;\n+\t\t\tret = -EIO;\n+\t\t\tgoto gappi_err_out;\n \t\t}\n \n \t\tirqfd-\u003eirq_bypass_data = pi_data.ir_data;\n \t\tlist_add(\u0026irqfd-\u003evcpu_list, \u0026svm-\u003eir_list);\n \t\treturn 0;\n+gappi_err_out:\n+\t\tif (is_vcpu_waiting)\n+\t\t\tavic_remove_vcpu_from_gappi_wakeup_list(svm, svm-\u003egappi_cpu);\n+\t\treturn ret;\n \t}\n \treturn irq_set_vcpu_affinity(host_irq, NULL);\n }\n@@ -1004,10 +1066,14 @@ enum avic_vcpu_action {\n \tAVIC_START_BLOCKING\t= BIT(1),\n };\n \n-static void avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int cpu,\n-\t\t\t\t\t enum avic_vcpu_action action)\n+static void avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int apicid,\n+\t\t\t\t\t int cpu, enum avic_vcpu_action action)\n {\n-\tbool ga_log_intr = (action \u0026 AVIC_START_BLOCKING);\n+\tint posted_intr = !!(action \u0026 AVIC_START_BLOCKING) \u003c\u003c\n+\t\t\t AMD_IOMMU_FLAG_POSTED_INTR_SHIFT;\n+\tint is_vcpu_running = (apicid \u003e= 0) \u003c\u003c\n+\t\t\t AMD_IOMMU_FLAG_VCPU_RUNNING_SHIFT;\n+\tint flags = posted_intr | is_vcpu_running;\n \tstruct vcpu_svm *svm = to_svm(vcpu);\n \tstruct kvm_kernel_irqfd *irqfd;\n \n@@ -1017,16 +1083,30 @@ static void avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int cpu,\n \t * Here, we go through the per-vcpu ir_list to update all existing\n \t * interrupt remapping table entry targeting this vcpu.\n \t */\n-\tif (list_empty(\u0026svm-\u003eir_list))\n+\tif (list_empty(\u0026svm-\u003eir_list)) {\n+\t\tif (amd_iommu_gappi \u0026\u0026 cpu \u003e= 0)\n+\t\t\tsvm-\u003egappi_cpu = cpu;\n \t\treturn;\n+\t}\n+\n+\tif (is_vcpu_running \u0026\u0026 amd_iommu_gappi) {\n+\t\t/* IF condition handles the initial state */\n+\t\tif (svm-\u003egappi_cpu != -1)\n+\t\t\tavic_remove_vcpu_from_gappi_wakeup_list(svm, svm-\u003egappi_cpu);\n+\n+\t\tsvm-\u003egappi_cpu = cpu; /* Store cpu no as target for GAPPI */\n+\t} else if (amd_iommu_gappi) {\n+\t\tapicid = kvm_cpu_get_apicid(svm-\u003egappi_cpu);\n+\t\tavic_add_vcpu_to_gappi_wakeup_list(svm, svm-\u003egappi_cpu);\n+\t}\n \n \tlist_for_each_entry(irqfd, \u0026svm-\u003eir_list, vcpu_list) {\n \t\tvoid *data = irqfd-\u003eirq_bypass_data;\n \n \t\tif (!(action \u0026 AVIC_TOGGLE_ON_OFF))\n-\t\t\tWARN_ON_ONCE(amd_iommu_update_ga(data, cpu, ga_log_intr));\n-\t\telse if (cpu \u003e= 0)\n-\t\t\tWARN_ON_ONCE(amd_iommu_activate_guest_mode(data, cpu, ga_log_intr));\n+\t\t\tWARN_ON_ONCE(amd_iommu_update_ga(data, apicid, flags));\n+\t\telse if (is_vcpu_running)\n+\t\t\tWARN_ON_ONCE(amd_iommu_activate_guest_mode(data, apicid, flags));\n \t\telse\n \t\t\tWARN_ON_ONCE(amd_iommu_deactivate_guest_mode(data));\n \t}\n@@ -1080,7 +1160,7 @@ static void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu,\n \n \tWRITE_ONCE(kvm_svm-\u003eavic_physical_id_table[vcpu-\u003evcpu_id], entry);\n \n-\tavic_update_iommu_vcpu_affinity(vcpu, h_physical_id, action);\n+\tavic_update_iommu_vcpu_affinity(vcpu, h_physical_id, cpu, action);\n \n \traw_spin_unlock_irqrestore(\u0026svm-\u003eir_list_lock, flags);\n }\n@@ -1123,7 +1203,7 @@ static void __avic_vcpu_put(struct kvm_vcpu *vcpu, enum avic_vcpu_action action)\n \t */\n \traw_spin_lock_irqsave(\u0026svm-\u003eir_list_lock, flags);\n \n-\tavic_update_iommu_vcpu_affinity(vcpu, -1, action);\n+\tavic_update_iommu_vcpu_affinity(vcpu, -1, -1, action);\n \n \tWARN_ON_ONCE(entry \u0026 AVIC_PHYSICAL_ID_ENTRY_GA_LOG_INTR);\n \n@@ -1296,6 +1376,21 @@ static bool __init avic_want_avic_enabled(void)\n \treturn true;\n }\n \n+static void avic_gappi_wakeup_handler(void)\n+{\n+\tint cpu = smp_processor_id();\n+\tstruct list_head *vcpu_wakeup_list = \u0026per_cpu(gappi_vcpu_wakeup_list, cpu);\n+\traw_spinlock_t *spinlock = \u0026per_cpu(gappi_vcpu_wakeup_list_lock, cpu);\n+\tstruct vcpu_svm *svm;\n+\n+\traw_spin_lock(spinlock);\n+\tlist_for_each_entry(svm, vcpu_wakeup_list, gappi_vcpu_wakeup_list) {\n+\t\tif (kvm_lapic_find_highest_irr(\u0026svm-\u003evcpu) \u003e= 0)\n+\t\t\tkvm_vcpu_wake_up(\u0026svm-\u003evcpu);\n+\t}\n+\traw_spin_unlock(spinlock);\n+}\n+\n /*\n * Note:\n * - The module param avic enable both xAPIC and x2APIC mode.\n@@ -1304,12 +1399,18 @@ static bool __init avic_want_avic_enabled(void)\n */\n bool __init avic_hardware_setup(void)\n {\n+\tint cpu;\n \tavic = avic_want_avic_enabled();\n \tif (!avic)\n \t\treturn false;\n \n \tpr_info(\"AVIC enabled\\n\");\n \n+\tfor_each_possible_cpu(cpu) {\n+\t\tINIT_LIST_HEAD(\u0026per_cpu(gappi_vcpu_wakeup_list, cpu));\n+\t\traw_spin_lock_init(\u0026per_cpu(gappi_vcpu_wakeup_list_lock, cpu));\n+\t}\n+\n \t/* AVIC is a prerequisite for x2AVIC. */\n \tx2avic_enabled = boot_cpu_has(X86_FEATURE_X2AVIC);\n \tif (x2avic_enabled) {\n@@ -1333,12 +1434,16 @@ bool __init avic_hardware_setup(void)\n \t\tenable_ipiv = false;\n \n \tamd_iommu_register_ga_log_notifier(\u0026avic_ga_log_notifier);\n+\tkvm_set_posted_intr_wakeup_handler(\u0026avic_gappi_wakeup_handler);\n \n \treturn true;\n }\n \n void avic_hardware_unsetup(void)\n {\n-\tif (avic)\n-\t\tamd_iommu_register_ga_log_notifier(NULL);\n+\tif (!avic)\n+\t\treturn;\n+\n+\tamd_iommu_register_ga_log_notifier(NULL);\n+\tkvm_set_posted_intr_wakeup_handler(NULL);\n }\ndiff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c\nindex e02a38da5296e3..b687133f8528ba 100644\n--- a/arch/x86/kvm/svm/svm.c\n+++ b/arch/x86/kvm/svm/svm.c\n@@ -1356,6 +1356,8 @@ static void svm_vcpu_free(struct kvm_vcpu *vcpu)\n \n \tWARN_ON_ONCE(!list_empty(\u0026svm-\u003eir_list));\n \n+\tavic_destroy_vcpu(svm);\n+\n \tsvm_leave_nested(vcpu);\n \tsvm_free_nested(svm);\n \ndiff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h\nindex 5137416be593d7..47d5bb5d7103da 100644\n--- a/arch/x86/kvm/svm/svm.h\n+++ b/arch/x86/kvm/svm/svm.h\n@@ -362,6 +362,10 @@ struct vcpu_svm {\n \n \t/* Guest GIF value, used when vGIF is not enabled */\n \tbool guest_gif;\n+\n+\t/* GAPPI related fields */\n+\tstruct list_head gappi_vcpu_wakeup_list;\n+\tint gappi_cpu;\n };\n \n struct svm_cpu_data {\n@@ -909,6 +913,7 @@ void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb);\n int avic_incomplete_ipi_interception(struct kvm_vcpu *vcpu);\n int avic_unaccelerated_access_interception(struct kvm_vcpu *vcpu);\n int avic_init_vcpu(struct vcpu_svm *svm);\n+void avic_destroy_vcpu(struct vcpu_svm *svm);\n void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu);\n void avic_vcpu_put(struct kvm_vcpu *vcpu);\n void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu);\ndiff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h\nindex 834d8fabfba387..044179cab12e4b 100644\n--- a/drivers/iommu/amd/amd_iommu.h\n+++ b/drivers/iommu/amd/amd_iommu.h\n@@ -41,6 +41,7 @@ int amd_iommu_enable(void);\n void amd_iommu_disable(void);\n int amd_iommu_reenable(int mode);\n int amd_iommu_enable_faulting(unsigned int cpu);\n+extern bool amd_iommu_gappi;\n extern int amd_iommu_guest_ir;\n extern enum protection_domain_mode amd_iommu_pgtable;\n extern int amd_iommu_gpt_level;\ndiff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h\nindex f9f71808789303..de0b23306944b8 100644\n--- a/drivers/iommu/amd/amd_iommu_types.h\n+++ b/drivers/iommu/amd/amd_iommu_types.h\n@@ -94,6 +94,7 @@\n #define FEATURE_X2APIC\t\tBIT_ULL(2)\n #define FEATURE_NX\t\tBIT_ULL(3)\n #define FEATURE_GT\t\tBIT_ULL(4)\n+#define FEATURE_GAPPI\t\tBIT_ULL(5)\n #define FEATURE_IA\t\tBIT_ULL(6)\n #define FEATURE_GA\t\tBIT_ULL(7)\n #define FEATURE_HE\t\tBIT_ULL(8)\n@@ -113,6 +114,7 @@\n /* Extended Feature 2 Bits */\n #define FEATURE_SEVSNPIO_SUP\tBIT_ULL(1)\n #define FEATURE_GCR3TRPMODE\tBIT_ULL(3)\n+#define FEATURE_GAPPIDISSUP\tBIT_ULL(4)\n #define FEATURE_SNPAVICSUP\tGENMASK_ULL(7, 5)\n #define FEATURE_SNPAVICSUP_GAM(x) \\\n \t(FIELD_GET(FEATURE_SNPAVICSUP, x) == 0x1)\n@@ -190,6 +192,7 @@\n #define CONTROL_EPH_EN\t\t45\n #define CONTROL_XT_EN\t\t50\n #define CONTROL_INTCAPXT_EN\t51\n+#define CONTROL_GAPPI_EN\t55\n #define CONTROL_GCR3TRPMODE\t58\n #define CONTROL_IRTCACHEDIS\t59\n #define CONTROL_SNPAVIC_EN\t61\n@@ -1004,7 +1007,8 @@ union irte_ga_lo {\n \t\t no_fault\t: 1,\n \t\t /* ------ */\n \t\t ga_log_intr\t: 1,\n-\t\t rsvd1\t: 3,\n+\t\t rsvd1\t: 2,\n+\t\t gappi_dis\t: 1,\n \t\t is_run\t: 1,\n \t\t /* ------ */\n \t\t guest_mode\t: 1,\ndiff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c\nindex 3bdb380d23e9a9..27ffb2184bf296 100644\n--- a/drivers/iommu/amd/init.c\n+++ b/drivers/iommu/amd/init.c\n@@ -160,6 +160,9 @@ u8 amd_iommu_hpt_level;\n /* Guest page table level */\n int amd_iommu_gpt_level = PAGE_MODE_4_LEVEL;\n \n+bool amd_iommu_gappi;\n+EXPORT_SYMBOL(amd_iommu_gappi);\n+\n int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;\n static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;\n \n@@ -462,6 +465,9 @@ static void iommu_disable(struct amd_iommu *iommu)\n \tiommu_feature_disable(iommu, CONTROL_GALOG_EN);\n \tiommu_feature_disable(iommu, CONTROL_GAINT_EN);\n \n+\t/* Disable IOMMU GAPPI */\n+\tiommu_feature_disable(iommu, CONTROL_GAPPI_EN);\n+\n \t/* Disable IOMMU PPR logging */\n \tiommu_feature_disable(iommu, CONTROL_PPRLOG_EN);\n \tiommu_feature_disable(iommu, CONTROL_PPRINT_EN);\n@@ -2996,6 +3002,12 @@ static void enable_iommus_vapic(void)\n \tstruct amd_iommu *iommu;\n \n \tfor_each_iommu(iommu) {\n+\t\t/* Disable GAPPI, do not check amd_iommu_gappi as it may be\n+\t\t * false in new kexec kernel even though previous kernel has\n+\t\t * enabled it.\n+\t\t */\n+\t\tiommu_feature_disable(iommu, CONTROL_GAPPI_EN);\n+\n \t\t/*\n \t\t * Disable GALog if already running. It could have been enabled\n \t\t * in the previous boot before kdump.\n@@ -3035,10 +3047,19 @@ static void enable_iommus_vapic(void)\n \t\treturn;\n \t}\n \n+\tif (amd_iommu_gappi \u0026\u0026\n+\t !(check_feature(FEATURE_GAPPI) \u0026\u0026\n+\t AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))) {\n+\t\tpr_warn(\"GAPPI is not supported.\\n\");\n+\t\tamd_iommu_gappi = false;\n+\t}\n+\n \t/* Enabling GAM and SNPAVIC support */\n \tfor_each_iommu(iommu) {\n-\t\tif (iommu_init_ga_log(iommu) ||\n-\t\t iommu_ga_log_enable(iommu))\n+\t\tif (amd_iommu_gappi)\n+\t\t\tiommu_feature_enable(iommu, CONTROL_GAPPI_EN);\n+\t\telse if (iommu_init_ga_log(iommu) ||\n+\t\t\t iommu_ga_log_enable(iommu))\n \t\t\treturn;\n \n \t\tiommu_feature_enable(iommu, CONTROL_GAM_EN);\n@@ -3047,7 +3068,8 @@ static void enable_iommus_vapic(void)\n \t}\n \n \tamd_iommu_irq_ops.capability |= (1 \u003c\u003c IRQ_POSTING_CAP);\n-\tpr_info(\"Virtual APIC enabled\\n\");\n+\tpr_info(\"Virtual APIC enabled with %s\\n\",\n+\t\tamd_iommu_gappi ? \"GAPPI\" : \"GALOG\");\n #endif\n }\n \n@@ -3738,6 +3760,8 @@ static int __init parse_amd_iommu_options(char *str)\n \t\t} else if (strncmp(str, \"v2_pgsizes_only\", 15) == 0) {\n \t\t\tpr_info(\"Restricting V1 page-sizes to 4KiB/2MiB/1GiB\");\n \t\t\tamd_iommu_pgsize_bitmap = AMD_IOMMU_PGSIZES_V2;\n+\t\t} else if (strncmp(str, \"gappi\", 5) == 0) {\n+\t\t\tamd_iommu_gappi = true;\n \t\t} else {\n \t\t\tpr_notice(\"Unknown option - '%s'\\n\", str);\n \t\t}\ndiff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c\nindex 57dc8fabc7d9b9..b226d3941cb9b8 100644\n--- a/drivers/iommu/amd/iommu.c\n+++ b/drivers/iommu/amd/iommu.c\n@@ -3959,19 +3959,29 @@ static const struct irq_domain_ops amd_ir_domain_ops = {\n \t.deactivate = irq_remapping_deactivate,\n };\n \n-static void __amd_iommu_update_ga(struct irte_ga *entry, int cpu,\n-\t\t\t\t bool ga_log_intr)\n+static void __amd_iommu_update_ga(struct irte_ga *entry, int apicid, int flags)\n {\n-\tif (cpu \u003e= 0) {\n+\tif (flags \u0026 AMD_IOMMU_FLAG_VCPU_RUNNING) {\n \t\tentry-\u003elo.fields_vapic.destination =\n-\t\t\t\t\tAPICID_TO_IRTE_DEST_LO(cpu);\n+\t\t\t\t\tAPICID_TO_IRTE_DEST_LO(apicid);\n \t\tentry-\u003ehi.fields.destination =\n-\t\t\t\t\tAPICID_TO_IRTE_DEST_HI(cpu);\n+\t\t\t\t\tAPICID_TO_IRTE_DEST_HI(apicid);\n \t\tentry-\u003elo.fields_vapic.is_run = true;\n \t\tentry-\u003elo.fields_vapic.ga_log_intr = false;\n \t} else {\n-\t\tentry-\u003elo.fields_vapic.is_run = false;\n-\t\tentry-\u003elo.fields_vapic.ga_log_intr = ga_log_intr;\n+\t\tbool posted_intr = !!(flags \u0026 AMD_IOMMU_FLAG_POSTED_INTR);\n+\n+\t\tif (amd_iommu_gappi) {\n+\t\t\tentry-\u003elo.fields_vapic.gappi_dis = !posted_intr \u0026\u0026\n+\t\t\t\t\t\t\t check_feature2(FEATURE_GAPPIDISSUP);\n+\t\t\tentry-\u003elo.fields_vapic.is_run = false;\n+\t\t\tentry-\u003elo.fields_vapic.destination =\n+\t\t\t\t\t\tAPICID_TO_IRTE_DEST_LO(apicid);\n+\t\t\tentry-\u003ehi.fields.destination = APICID_TO_IRTE_DEST_HI(apicid);\n+\t\t} else {\n+\t\t\tentry-\u003elo.fields_vapic.is_run = false;\n+\t\t\tentry-\u003elo.fields_vapic.ga_log_intr = posted_intr;\n+\t\t}\n \t}\n }\n \n@@ -3992,7 +4002,7 @@ static void __amd_iommu_update_ga(struct irte_ga *entry, int cpu,\n * and thus don't require an invalidation to ensure the IOMMU consumes fresh\n * information.\n */\n-int amd_iommu_update_ga(void *data, int cpu, bool ga_log_intr)\n+int amd_iommu_update_ga(void *data, int apicid, int flags)\n {\n \tstruct amd_ir_data *ir_data = (struct amd_ir_data *)data;\n \tstruct irte_ga *entry = (struct irte_ga *) ir_data-\u003eentry;\n@@ -4006,14 +4016,14 @@ int amd_iommu_update_ga(void *data, int cpu, bool ga_log_intr)\n \tif (!ir_data-\u003eiommu)\n \t\treturn -ENODEV;\n \n-\t__amd_iommu_update_ga(entry, cpu, ga_log_intr);\n+\t__amd_iommu_update_ga(entry, apicid, flags);\n \n \treturn __modify_irte_ga(ir_data-\u003eiommu, ir_data-\u003eirq_2_irte.devid,\n \t\t\t\tir_data-\u003eirq_2_irte.index, entry);\n }\n EXPORT_SYMBOL(amd_iommu_update_ga);\n \n-int amd_iommu_activate_guest_mode(void *data, int cpu, bool ga_log_intr)\n+int amd_iommu_activate_guest_mode(void *data, int apicid, int flags)\n {\n \tstruct amd_ir_data *ir_data = (struct amd_ir_data *)data;\n \tstruct irte_ga *entry = (struct irte_ga *) ir_data-\u003eentry;\n@@ -4034,9 +4044,13 @@ int amd_iommu_activate_guest_mode(void *data, int cpu, bool ga_log_intr)\n \tentry-\u003elo.fields_vapic.guest_mode = 1;\n \tentry-\u003ehi.fields.ga_root_ptr = ir_data-\u003ega_root_ptr;\n \tentry-\u003ehi.fields.vector = ir_data-\u003ega_vector;\n-\tentry-\u003elo.fields_vapic.ga_tag = ir_data-\u003ega_tag;\n \n-\t__amd_iommu_update_ga(entry, cpu, ga_log_intr);\n+\tif (amd_iommu_gappi)\n+\t\tentry-\u003elo.fields_vapic.ga_tag = POSTED_INTR_WAKEUP_VECTOR;\n+\telse\n+\t\tentry-\u003elo.fields_vapic.ga_tag = ir_data-\u003ega_tag;\n+\n+\t__amd_iommu_update_ga(entry, apicid, flags);\n \n \treturn modify_irte_ga(ir_data-\u003eiommu, ir_data-\u003eirq_2_irte.devid,\n \t\t\t ir_data-\u003eirq_2_irte.index, entry);\n@@ -4107,8 +4121,8 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *info)\n \t\tir_data-\u003ega_vector = pi_data-\u003evector;\n \t\tir_data-\u003ega_tag = pi_data-\u003ega_tag;\n \t\tif (pi_data-\u003eis_guest_mode)\n-\t\t\tret = amd_iommu_activate_guest_mode(ir_data, pi_data-\u003ecpu,\n-\t\t\t\t\t\t\t pi_data-\u003ega_log_intr);\n+\t\t\tret = amd_iommu_activate_guest_mode(ir_data, pi_data-\u003eapicid,\n+\t\t\t\t\t\t\t pi_data-\u003eflags);\n \t\telse\n \t\t\tret = amd_iommu_deactivate_guest_mode(ir_data);\n \t} else {\ndiff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h\nindex edcee9f5335a6f..87e76f617ea185 100644\n--- a/include/linux/amd-iommu.h\n+++ b/include/linux/amd-iommu.h\n@@ -30,8 +30,8 @@ static inline void amd_iommu_detect(void) { }\n /* IOMMU AVIC Function */\n extern int amd_iommu_register_ga_log_notifier(int (*notifier)(u32));\n \n-extern int amd_iommu_update_ga(void *data, int cpu, bool ga_log_intr);\n-extern int amd_iommu_activate_guest_mode(void *data, int cpu, bool ga_log_intr);\n+extern int amd_iommu_update_ga(void *data, int apicid, int flags);\n+extern int amd_iommu_activate_guest_mode(void *data, int apicid, int flags);\n extern int amd_iommu_deactivate_guest_mode(void *data);\n \n #else /* defined(CONFIG_AMD_IOMMU) \u0026\u0026 defined(CONFIG_IRQ_REMAP) */\n@@ -42,12 +42,12 @@ amd_iommu_register_ga_log_notifier(int (*notifier)(u32))\n \treturn 0;\n }\n \n-static inline int amd_iommu_update_ga(void *data, int cpu, bool ga_log_intr)\n+static inline int amd_iommu_update_ga(void *data, int apicid, int flags)\n {\n \treturn 0;\n }\n \n-static inline int amd_iommu_activate_guest_mode(void *data, int cpu, bool ga_log_intr)\n+static inline int amd_iommu_activate_guest_mode(void *data, int apicid, int flags)\n {\n \treturn 0;\n }\n@@ -76,4 +76,11 @@ static inline int amd_iommu_snp_disable(void) { return 0; }\n static inline bool amd_iommu_sev_tio_supported(void) { return false; }\n #endif\n \n+#define AMD_IOMMU_FLAG_VCPU_RUNNING_SHIFT 0\n+#define AMD_IOMMU_FLAG_VCPU_RUNNING BIT(0)\n+\n+#define AMD_IOMMU_FLAG_POSTED_INTR_SHIFT 1\n+#define AMD_IOMMU_FLAG_POSTED_INTR BIT(1)\n+\n+extern bool amd_iommu_gappi;\n #endif /* _ASM_X86_AMD_IOMMU_H */\n"
} |
| 2/1 | 2026/07/08 21:49 | agent | patch-evaluator |
1mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"KVM_AMD",
"AMD_IOMMU",
"IRQ_REMAP"
],
"FocusSymbols": [
"avic_update_iommu_vcpu_affinity",
"amd_iommu_update_ga",
"amd_iommu_activate_guest_mode",
"avic_pi_update_irte",
"__amd_iommu_update_ga",
"avic_add_vcpu_to_gappi_wakeup_list",
"avic_remove_vcpu_from_gappi_wakeup_list",
"avic_gappi_wakeup_handler",
"avic_destroy_vcpu",
"svm_ir_list_del"
],
"Reasoning": "The patch introduces Guest APIC Posted Interrupts (GAPPI) support for AMD IOMMU and KVM SVM AVIC. It modifies the interrupt remapping table entry updates and vCPU affinity logic, which are reachable in virtualized environments (e.g., QEMU with KVM SVM). The changes alter core AVIC and IOMMU logic even when GAPPI is not explicitly enabled via boot parameter, making it functional and worth fuzzing.",
"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 eaea02c5c6a81a4a71795126a2885e00fbdaa164
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Jul 8 21:49:00 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h
index 37b94f484ef338..40a2206a33c08d 100644
--- a/arch/x86/include/asm/irq_remapping.h
+++ b/arch/x86/include/asm/irq_remapping.h
@@ -35,8 +35,8 @@ struct amd_iommu_pi_data {
u64 vapic_addr; /* Physical address of the vCPU's vAPIC. */
u32 ga_tag;
u32 vector; /* Guest vector of the interrupt */
- int cpu;
- bool ga_log_intr;
+ int apicid;
+ int flags;
bool is_guest_mode;
void *ir_data;
};
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index cdd5a6dc646f11..8185841d9b8165 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -63,6 +63,9 @@
ga_tag; \
})
+static DEFINE_PER_CPU(struct list_head, gappi_vcpu_wakeup_list);
+static DEFINE_PER_CPU(raw_spinlock_t, gappi_vcpu_wakeup_list_lock);
+
static_assert(__AVIC_GATAG(AVIC_VM_ID_MASK, AVIC_VCPU_IDX_MASK) == -1u);
#define AVIC_AUTO_MODE -1
@@ -874,6 +877,9 @@ int avic_init_vcpu(struct vcpu_svm *svm)
INIT_LIST_HEAD(&svm->ir_list);
raw_spin_lock_init(&svm->ir_list_lock);
+ INIT_LIST_HEAD(&svm->gappi_vcpu_wakeup_list);
+ svm->gappi_cpu = -1;
+
if (!enable_apicv || !irqchip_in_kernel(vcpu->kvm))
return 0;
@@ -886,6 +892,42 @@ int avic_init_vcpu(struct vcpu_svm *svm)
return ret;
}
+static void avic_add_vcpu_to_gappi_wakeup_list(struct vcpu_svm *svm, int cpu)
+{
+ struct list_head *wakeup_list;
+ raw_spinlock_t *spinlock;
+
+ if (WARN_ON(cpu < 0))
+ return;
+
+ wakeup_list = &per_cpu(gappi_vcpu_wakeup_list, cpu);
+ spinlock = &per_cpu(gappi_vcpu_wakeup_list_lock, cpu);
+ guard(raw_spinlock_irqsave)(spinlock);
+ if (list_empty(&svm->gappi_vcpu_wakeup_list))
+ list_add_tail(&svm->gappi_vcpu_wakeup_list, wakeup_list);
+}
+
+static void avic_remove_vcpu_from_gappi_wakeup_list(struct vcpu_svm *svm, int cpu)
+{
+ raw_spinlock_t *spinlock;
+
+ if (WARN_ON(cpu < 0))
+ return;
+
+ spinlock = &per_cpu(gappi_vcpu_wakeup_list_lock, cpu);
+ guard(raw_spinlock_irqsave)(spinlock);
+ if (!list_empty(&svm->gappi_vcpu_wakeup_list))
+ list_del_init(&svm->gappi_vcpu_wakeup_list);
+}
+
+void avic_destroy_vcpu(struct vcpu_svm *svm)
+{
+ if (svm->gappi_cpu != -1 && amd_iommu_gappi) {
+ avic_remove_vcpu_from_gappi_wakeup_list(svm, svm->gappi_cpu);
+ svm->gappi_cpu = -1;
+ }
+}
+
void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu)
{
avic_handle_dfr_update(vcpu);
@@ -896,13 +938,18 @@ static void svm_ir_list_del(struct kvm_kernel_irqfd *irqfd)
{
struct kvm_vcpu *vcpu = irqfd->irq_bypass_vcpu;
unsigned long flags;
+ struct vcpu_svm *svm;
if (!vcpu)
return;
- raw_spin_lock_irqsave(&to_svm(vcpu)->ir_list_lock, flags);
+ svm = to_svm(vcpu);
+
+ raw_spin_lock_irqsave(&svm->ir_list_lock, flags);
list_del(&irqfd->vcpu_list);
- raw_spin_unlock_irqrestore(&to_svm(vcpu)->ir_list_lock, flags);
+ if (list_empty(&svm->ir_list))
+ avic_remove_vcpu_from_gappi_wakeup_list(svm, svm->gappi_cpu);
+ raw_spin_unlock_irqrestore(&svm->ir_list_lock, flags);
}
int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
@@ -932,6 +979,8 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
struct vcpu_svm *svm = to_svm(vcpu);
u64 entry;
int ret;
+ int posted_intr;
+ bool is_vcpu_waiting = false;
/*
* Prevent the vCPU from being scheduled out or migrated until
@@ -949,15 +998,23 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
*/
entry = svm->avic_physical_id_entry;
if (entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK) {
- pi_data.cpu = entry & AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;
+ pi_data.apicid = entry & AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;
+ pi_data.flags = AMD_IOMMU_FLAG_VCPU_RUNNING;
} else {
- pi_data.cpu = -1;
- pi_data.ga_log_intr = entry & AVIC_PHYSICAL_ID_ENTRY_GA_LOG_INTR;
+ posted_intr = !!(entry & AVIC_PHYSICAL_ID_ENTRY_GA_LOG_INTR);
+ pi_data.flags = posted_intr << AMD_IOMMU_FLAG_POSTED_INTR_SHIFT;
+ if (amd_iommu_gappi) {
+ pi_data.apicid = kvm_cpu_get_apicid(svm->gappi_cpu);
+ if (list_empty(&svm->ir_list)) {
+ avic_add_vcpu_to_gappi_wakeup_list(svm, svm->gappi_cpu);
+ is_vcpu_waiting = true;
+ }
+ }
}
ret = irq_set_vcpu_affinity(host_irq, &pi_data);
if (ret)
- return ret;
+ goto gappi_err_out;
/*
* Revert to legacy mode if the IOMMU didn't provide metadata
@@ -966,12 +1023,17 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
*/
if (WARN_ON_ONCE(!pi_data.ir_data)) {
irq_set_vcpu_affinity(host_irq, NULL);
- return -EIO;
+ ret = -EIO;
+ goto gappi_err_out;
}
irqfd->irq_bypass_data = pi_data.ir_data;
list_add(&irqfd->vcpu_list, &svm->ir_list);
return 0;
+gappi_err_out:
+ if (is_vcpu_waiting)
+ avic_remove_vcpu_from_gappi_wakeup_list(svm, svm->gappi_cpu);
+ return ret;
}
return irq_set_vcpu_affinity(host_irq, NULL);
}
@@ -1004,10 +1066,14 @@ enum avic_vcpu_action {
AVIC_START_BLOCKING = BIT(1),
};
-static void avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int cpu,
- enum avic_vcpu_action action)
+static void avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int apicid,
+ int cpu, enum avic_vcpu_action action)
{
- bool ga_log_intr = (action & AVIC_START_BLOCKING);
+ int posted_intr = !!(action & AVIC_START_BLOCKING) <<
+ AMD_IOMMU_FLAG_POSTED_INTR_SHIFT;
+ int is_vcpu_running = (apicid >= 0) <<
+ AMD_IOMMU_FLAG_VCPU_RUNNING_SHIFT;
+ int flags = posted_intr | is_vcpu_running;
struct vcpu_svm *svm = to_svm(vcpu);
struct kvm_kernel_irqfd *irqfd;
@@ -1017,16 +1083,30 @@ static void avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int cpu,
* Here, we go through the per-vcpu ir_list to update all existing
* interrupt remapping table entry targeting this vcpu.
*/
- if (list_empty(&svm->ir_list))
+ if (list_empty(&svm->ir_list)) {
+ if (amd_iommu_gappi && cpu >= 0)
+ svm->gappi_cpu = cpu;
return;
+ }
+
+ if (is_vcpu_running && amd_iommu_gappi) {
+ /* IF condition handles the initial state */
+ if (svm->gappi_cpu != -1)
+ avic_remove_vcpu_from_gappi_wakeup_list(svm, svm->gappi_cpu);
+
+ svm->gappi_cpu = cpu; /* Store cpu no as target for GAPPI */
+ } else if (amd_iommu_gappi) {
+ apicid = kvm_cpu_get_apicid(svm->gappi_cpu);
+ avic_add_vcpu_to_gappi_wakeup_list(svm, svm->gappi_cpu);
+ }
list_for_each_entry(irqfd, &svm->ir_list, vcpu_list) {
void *data = irqfd->irq_bypass_data;
if (!(action & AVIC_TOGGLE_ON_OFF))
- WARN_ON_ONCE(amd_iommu_update_ga(data, cpu, ga_log_intr));
- else if (cpu >= 0)
- WARN_ON_ONCE(amd_iommu_activate_guest_mode(data, cpu, ga_log_intr));
+ WARN_ON_ONCE(amd_iommu_update_ga(data, apicid, flags));
+ else if (is_vcpu_running)
+ WARN_ON_ONCE(amd_iommu_activate_guest_mode(data, apicid, flags));
else
WARN_ON_ONCE(amd_iommu_deactivate_guest_mode(data));
}
@@ -1080,7 +1160,7 @@ static void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu,
WRITE_ONCE(kvm_svm->avic_physical_id_table[vcpu->vcpu_id], entry);
- avic_update_iommu_vcpu_affinity(vcpu, h_physical_id, action);
+ avic_update_iommu_vcpu_affinity(vcpu, h_physical_id, cpu, action);
raw_spin_unlock_irqrestore(&svm->ir_list_lock, flags);
}
@@ -1123,7 +1203,7 @@ static void __avic_vcpu_put(struct kvm_vcpu *vcpu, enum avic_vcpu_action action)
*/
raw_spin_lock_irqsave(&svm->ir_list_lock, flags);
- avic_update_iommu_vcpu_affinity(vcpu, -1, action);
+ avic_update_iommu_vcpu_affinity(vcpu, -1, -1, action);
WARN_ON_ONCE(entry & AVIC_PHYSICAL_ID_ENTRY_GA_LOG_INTR);
@@ -1296,6 +1376,21 @@ static bool __init avic_want_avic_enabled(void)
return true;
}
+static void avic_gappi_wakeup_handler(void)
+{
+ int cpu = smp_processor_id();
+ struct list_head *vcpu_wakeup_list = &per_cpu(gappi_vcpu_wakeup_list, cpu);
+ raw_spinlock_t *spinlock = &per_cpu(gappi_vcpu_wakeup_list_lock, cpu);
+ struct vcpu_svm *svm;
+
+ raw_spin_lock(spinlock);
+ list_for_each_entry(svm, vcpu_wakeup_list, gappi_vcpu_wakeup_list) {
+ if (kvm_lapic_find_highest_irr(&svm->vcpu) >= 0)
+ kvm_vcpu_wake_up(&svm->vcpu);
+ }
+ raw_spin_unlock(spinlock);
+}
+
/*
* Note:
* - The module param avic enable both xAPIC and x2APIC mode.
@@ -1304,12 +1399,18 @@ static bool __init avic_want_avic_enabled(void)
*/
bool __init avic_hardware_setup(void)
{
+ int cpu;
avic = avic_want_avic_enabled();
if (!avic)
return false;
pr_info("AVIC enabled\n");
+ for_each_possible_cpu(cpu) {
+ INIT_LIST_HEAD(&per_cpu(gappi_vcpu_wakeup_list, cpu));
+ raw_spin_lock_init(&per_cpu(gappi_vcpu_wakeup_list_lock, cpu));
+ }
+
/* AVIC is a prerequisite for x2AVIC. */
x2avic_enabled = boot_cpu_has(X86_FEATURE_X2AVIC);
if (x2avic_enabled) {
@@ -1333,12 +1434,16 @@ bool __init avic_hardware_setup(void)
enable_ipiv = false;
amd_iommu_register_ga_log_notifier(&avic_ga_log_notifier);
+ kvm_set_posted_intr_wakeup_handler(&avic_gappi_wakeup_handler);
return true;
}
void avic_hardware_unsetup(void)
{
- if (avic)
- amd_iommu_register_ga_log_notifier(NULL);
+ if (!avic)
+ return;
+
+ amd_iommu_register_ga_log_notifier(NULL);
+ kvm_set_posted_intr_wakeup_handler(NULL);
}
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index e02a38da5296e3..b687133f8528ba 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1356,6 +1356,8 @@ static void svm_vcpu_free(struct kvm_vcpu *vcpu)
WARN_ON_ONCE(!list_empty(&svm->ir_list));
+ avic_destroy_vcpu(svm);
+
svm_leave_nested(vcpu);
svm_free_nested(svm);
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 5137416be593d7..47d5bb5d7103da 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -362,6 +362,10 @@ struct vcpu_svm {
/* Guest GIF value, used when vGIF is not enabled */
bool guest_gif;
+
+ /* GAPPI related fields */
+ struct list_head gappi_vcpu_wakeup_list;
+ int gappi_cpu;
};
struct svm_cpu_data {
@@ -909,6 +913,7 @@ void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb);
int avic_incomplete_ipi_interception(struct kvm_vcpu *vcpu);
int avic_unaccelerated_access_interception(struct kvm_vcpu *vcpu);
int avic_init_vcpu(struct vcpu_svm *svm);
+void avic_destroy_vcpu(struct vcpu_svm *svm);
void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
void avic_vcpu_put(struct kvm_vcpu *vcpu);
void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu);
diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index 834d8fabfba387..044179cab12e4b 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -41,6 +41,7 @@ int amd_iommu_enable(void);
void amd_iommu_disable(void);
int amd_iommu_reenable(int mode);
int amd_iommu_enable_faulting(unsigned int cpu);
+extern bool amd_iommu_gappi;
extern int amd_iommu_guest_ir;
extern enum protection_domain_mode amd_iommu_pgtable;
extern int amd_iommu_gpt_level;
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index f9f71808789303..de0b23306944b8 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -94,6 +94,7 @@
#define FEATURE_X2APIC BIT_ULL(2)
#define FEATURE_NX BIT_ULL(3)
#define FEATURE_GT BIT_ULL(4)
+#define FEATURE_GAPPI BIT_ULL(5)
#define FEATURE_IA BIT_ULL(6)
#define FEATURE_GA BIT_ULL(7)
#define FEATURE_HE BIT_ULL(8)
@@ -113,6 +114,7 @@
/* Extended Feature 2 Bits */
#define FEATURE_SEVSNPIO_SUP BIT_ULL(1)
#define FEATURE_GCR3TRPMODE BIT_ULL(3)
+#define FEATURE_GAPPIDISSUP BIT_ULL(4)
#define FEATURE_SNPAVICSUP GENMASK_ULL(7, 5)
#define FEATURE_SNPAVICSUP_GAM(x) \
(FIELD_GET(FEATURE_SNPAVICSUP, x) == 0x1)
@@ -190,6 +192,7 @@
#define CONTROL_EPH_EN 45
#define CONTROL_XT_EN 50
#define CONTROL_INTCAPXT_EN 51
+#define CONTROL_GAPPI_EN 55
#define CONTROL_GCR3TRPMODE 58
#define CONTROL_IRTCACHEDIS 59
#define CONTROL_SNPAVIC_EN 61
@@ -1004,7 +1007,8 @@ union irte_ga_lo {
no_fault : 1,
/* ------ */
ga_log_intr : 1,
- rsvd1 : 3,
+ rsvd1 : 2,
+ gappi_dis : 1,
is_run : 1,
/* ------ */
guest_mode : 1,
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 3bdb380d23e9a9..27ffb2184bf296 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -160,6 +160,9 @@ u8 amd_iommu_hpt_level;
/* Guest page table level */
int amd_iommu_gpt_level = PAGE_MODE_4_LEVEL;
+bool amd_iommu_gappi;
+EXPORT_SYMBOL(amd_iommu_gappi);
+
int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;
static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
@@ -462,6 +465,9 @@ static void iommu_disable(struct amd_iommu *iommu)
iommu_feature_disable(iommu, CONTROL_GALOG_EN);
iommu_feature_disable(iommu, CONTROL_GAINT_EN);
+ /* Disable IOMMU GAPPI */
+ iommu_feature_disable(iommu, CONTROL_GAPPI_EN);
+
/* Disable IOMMU PPR logging */
iommu_feature_disable(iommu, CONTROL_PPRLOG_EN);
iommu_feature_disable(iommu, CONTROL_PPRINT_EN);
@@ -2996,6 +3002,12 @@ static void enable_iommus_vapic(void)
struct amd_iommu *iommu;
for_each_iommu(iommu) {
+ /* Disable GAPPI, do not check amd_iommu_gappi as it may be
+ * false in new kexec kernel even though previous kernel has
+ * enabled it.
+ */
+ iommu_feature_disable(iommu, CONTROL_GAPPI_EN);
+
/*
* Disable GALog if already running. It could have been enabled
* in the previous boot before kdump.
@@ -3035,10 +3047,19 @@ static void enable_iommus_vapic(void)
return;
}
+ if (amd_iommu_gappi &&
+ !(check_feature(FEATURE_GAPPI) &&
+ AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))) {
+ pr_warn("GAPPI is not supported.\n");
+ amd_iommu_gappi = false;
+ }
+
/* Enabling GAM and SNPAVIC support */
for_each_iommu(iommu) {
- if (iommu_init_ga_log(iommu) ||
- iommu_ga_log_enable(iommu))
+ if (amd_iommu_gappi)
+ iommu_feature_enable(iommu, CONTROL_GAPPI_EN);
+ else if (iommu_init_ga_log(iommu) ||
+ iommu_ga_log_enable(iommu))
return;
iommu_feature_enable(iommu, CONTROL_GAM_EN);
@@ -3047,7 +3068,8 @@ static void enable_iommus_vapic(void)
}
amd_iommu_irq_ops.capability |= (1 << IRQ_POSTING_CAP);
- pr_info("Virtual APIC enabled\n");
+ pr_info("Virtual APIC enabled with %s\n",
+ amd_iommu_gappi ? "GAPPI" : "GALOG");
#endif
}
@@ -3738,6 +3760,8 @@ static int __init parse_amd_iommu_options(char *str)
} else if (strncmp(str, "v2_pgsizes_only", 15) == 0) {
pr_info("Restricting V1 page-sizes to 4KiB/2MiB/1GiB");
amd_iommu_pgsize_bitmap = AMD_IOMMU_PGSIZES_V2;
+ } else if (strncmp(str, "gappi", 5) == 0) {
+ amd_iommu_gappi = true;
} else {
pr_notice("Unknown option - '%s'\n", str);
}
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 57dc8fabc7d9b9..b226d3941cb9b8 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -3959,19 +3959,29 @@ static const struct irq_domain_ops amd_ir_domain_ops = {
.deactivate = irq_remapping_deactivate,
};
-static void __amd_iommu_update_ga(struct irte_ga *entry, int cpu,
- bool ga_log_intr)
+static void __amd_iommu_update_ga(struct irte_ga *entry, int apicid, int flags)
{
- if (cpu >= 0) {
+ if (flags & AMD_IOMMU_FLAG_VCPU_RUNNING) {
entry->lo.fields_vapic.destination =
- APICID_TO_IRTE_DEST_LO(cpu);
+ APICID_TO_IRTE_DEST_LO(apicid);
entry->hi.fields.destination =
- APICID_TO_IRTE_DEST_HI(cpu);
+ APICID_TO_IRTE_DEST_HI(apicid);
entry->lo.fields_vapic.is_run = true;
entry->lo.fields_vapic.ga_log_intr = false;
} else {
- entry->lo.fields_vapic.is_run = false;
- entry->lo.fields_vapic.ga_log_intr = ga_log_intr;
+ bool posted_intr = !!(flags & AMD_IOMMU_FLAG_POSTED_INTR);
+
+ if (amd_iommu_gappi) {
+ entry->lo.fields_vapic.gappi_dis = !posted_intr &&
+ check_feature2(FEATURE_GAPPIDISSUP);
+ entry->lo.fields_vapic.is_run = false;
+ entry->lo.fields_vapic.destination =
+ APICID_TO_IRTE_DEST_LO(apicid);
+ entry->hi.fields.destination = APICID_TO_IRTE_DEST_HI(apicid);
+ } else {
+ entry->lo.fields_vapic.is_run = false;
+ entry->lo.fields_vapic.ga_log_intr = posted_intr;
+ }
}
}
@@ -3992,7 +4002,7 @@ static void __amd_iommu_update_ga(struct irte_ga *entry, int cpu,
* and thus don't require an invalidation to ensure the IOMMU consumes fresh
* information.
*/
-int amd_iommu_update_ga(void *data, int cpu, bool ga_log_intr)
+int amd_iommu_update_ga(void *data, int apicid, int flags)
{
struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
@@ -4006,14 +4016,14 @@ int amd_iommu_update_ga(void *data, int cpu, bool ga_log_intr)
if (!ir_data->iommu)
return -ENODEV;
- __amd_iommu_update_ga(entry, cpu, ga_log_intr);
+ __amd_iommu_update_ga(entry, apicid, flags);
return __modify_irte_ga(ir_data->iommu, ir_data->irq_2_irte.devid,
ir_data->irq_2_irte.index, entry);
}
EXPORT_SYMBOL(amd_iommu_update_ga);
-int amd_iommu_activate_guest_mode(void *data, int cpu, bool ga_log_intr)
+int amd_iommu_activate_guest_mode(void *data, int apicid, int flags)
{
struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
@@ -4034,9 +4044,13 @@ int amd_iommu_activate_guest_mode(void *data, int cpu, bool ga_log_intr)
entry->lo.fields_vapic.guest_mode = 1;
entry->hi.fields.ga_root_ptr = ir_data->ga_root_ptr;
entry->hi.fields.vector = ir_data->ga_vector;
- entry->lo.fields_vapic.ga_tag = ir_data->ga_tag;
- __amd_iommu_update_ga(entry, cpu, ga_log_intr);
+ if (amd_iommu_gappi)
+ entry->lo.fields_vapic.ga_tag = POSTED_INTR_WAKEUP_VECTOR;
+ else
+ entry->lo.fields_vapic.ga_tag = ir_data->ga_tag;
+
+ __amd_iommu_update_ga(entry, apicid, flags);
return modify_irte_ga(ir_data->iommu, ir_data->irq_2_irte.devid,
ir_data->irq_2_irte.index, entry);
@@ -4107,8 +4121,8 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *info)
ir_data->ga_vector = pi_data->vector;
ir_data->ga_tag = pi_data->ga_tag;
if (pi_data->is_guest_mode)
- ret = amd_iommu_activate_guest_mode(ir_data, pi_data->cpu,
- pi_data->ga_log_intr);
+ ret = amd_iommu_activate_guest_mode(ir_data, pi_data->apicid,
+ pi_data->flags);
else
ret = amd_iommu_deactivate_guest_mode(ir_data);
} else {
diff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h
index edcee9f5335a6f..87e76f617ea185 100644
--- a/include/linux/amd-iommu.h
+++ b/include/linux/amd-iommu.h
@@ -30,8 +30,8 @@ static inline void amd_iommu_detect(void) { }
/* IOMMU AVIC Function */
extern int amd_iommu_register_ga_log_notifier(int (*notifier)(u32));
-extern int amd_iommu_update_ga(void *data, int cpu, bool ga_log_intr);
-extern int amd_iommu_activate_guest_mode(void *data, int cpu, bool ga_log_intr);
+extern int amd_iommu_update_ga(void *data, int apicid, int flags);
+extern int amd_iommu_activate_guest_mode(void *data, int apicid, int flags);
extern int amd_iommu_deactivate_guest_mode(void *data);
#else /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */
@@ -42,12 +42,12 @@ amd_iommu_register_ga_log_notifier(int (*notifier)(u32))
return 0;
}
-static inline int amd_iommu_update_ga(void *data, int cpu, bool ga_log_intr)
+static inline int amd_iommu_update_ga(void *data, int apicid, int flags)
{
return 0;
}
-static inline int amd_iommu_activate_guest_mode(void *data, int cpu, bool ga_log_intr)
+static inline int amd_iommu_activate_guest_mode(void *data, int apicid, int flags)
{
return 0;
}
@@ -76,4 +76,11 @@ static inline int amd_iommu_snp_disable(void) { return 0; }
static inline bool amd_iommu_sev_tio_supported(void) { return false; }
#endif
+#define AMD_IOMMU_FLAG_VCPU_RUNNING_SHIFT 0
+#define AMD_IOMMU_FLAG_VCPU_RUNNING BIT(0)
+
+#define AMD_IOMMU_FLAG_POSTED_INTR_SHIFT 1
+#define AMD_IOMMU_FLAG_POSTED_INTR BIT(1)
+
+extern bool amd_iommu_gappi;
#endif /* _ASM_X86_AMD_IOMMU_H */
|
| 3/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10800 output: 32 thoughts: 360 Thoughts: **GAPPI Support Investigation** Okay, so we have this patch that's trying to bring in GAPPI support – Guest APIC Posted Interrupts – for AMD IOMMU and KVM SVM AVIC. My immediate thought is, "Is this actually functional, and is it worth the effort to fuzz it?" Looking at the file modifications – `avic.c`, `svm.c`, `init.c`, `iommu.c` – it's definitely touching some key areas. It seems the patch introduces a `amd_iommu=gappi` boot parameter, which is a good starting point for enabling this functionality. And it looks like the code modifies some key functions like `avic_pi_update_irte`, and adds some new ones too. The next question in my mind is, "Can we even *reach* this feature in our test environments? Can we reproduce this in a virtualized setting like GCE or QEMU?" Ah, right, nested virtualization with KVM SVM should work. That's good. However, what about syzkaller? Does it target AMD IOMMU or SVM? Fortunately, syzkaller does fuzz KVM, including SVM, so the potential is there. Given the functional changes to KVM SVM AVIC and AMD IOMMU, I need to make sure the relevant configuration options are enabled. Looks like `CONFIG_KVM`, `CONFIG_KVM_AMD`, and `CONFIG_AMD_IOMMU` are the key ones to investigate. I'll need to check the Kconfig files in `drivers/iommu/amd/` and `arch/x86/kvm/` to confirm. |
| 4/2 | 2026/07/08 21:49 | tool | grepper |
0mArgs:{
"Expression": "config AMD_IOMMU",
"PathPrefix": "drivers/iommu/"
}Results: {
"Output": "drivers/iommu/amd/Kconfig-2-# AMD IOMMU support\ndrivers/iommu/amd/Kconfig:3:config AMD_IOMMU\ndrivers/iommu/amd/Kconfig-4-\tbool \"AMD IOMMU support\"\n--\ndrivers/iommu/amd/Kconfig-32-\ndrivers/iommu/amd/Kconfig:33:config AMD_IOMMU_IOMMUFD\ndrivers/iommu/amd/Kconfig-34-\tbool \"Enable IOMMUFD features for AMD IOMMU (EXPERIMENTAL)\"\n--\ndrivers/iommu/amd/Kconfig-42-\ndrivers/iommu/amd/Kconfig:43:config AMD_IOMMU_DEBUGFS\ndrivers/iommu/amd/Kconfig-44-\tbool \"Enable AMD IOMMU internals in DebugFS\"\n"
} |
| 5/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11763 output: 34 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. |
| 6/2 | 2026/07/08 21:49 | tool | grepper |
0mArgs:{
"Expression": "config KVM_AMD",
"PathPrefix": "arch/x86/kvm/"
}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"
} |
| 7/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12167 output: 34 thoughts: 53 Thoughts: Okay, let's see, my mental gears are turning... **Kernel Configuration Dependencies** Alright, I'm focusing on these KVM and IOMMU configurations – `KVM_AMD` and `AMD_IOMMU` in particular. But, wait... what about `IRQ_REMAP`? That's a critical piece, isn't it? I need to clarify the relationship between `AMD_IOMMU` and `IRQ_REMAP`. Does `AMD_IOMMU` *depend* on `IRQ_REMAP`, meaning that it requires it to function? Or does `AMD_IOMMU` *select* it, making `IRQ_REMAP` a sort of implicit requirement that is taken care of automatically? I need to check the dependencies. Let's delve in and find out. |
| 8/2 | 2026/07/08 21:49 | tool | grepper |
0mError:no matches Args: {
"Expression": "select IRQ_REMAP",
"PathPrefix": "drivers/iommu/amd/"
}Results: {
"error": "no matches"
} |
| 9/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12443 output: 34 thoughts: 13 Thoughts: Okay, let's dive into this. Here's my thought process on this: **Checking `AMD_IOMMU` Dependencies** Alright, the first thing that pops into my head is a methodical check of the dependencies related to `AMD_IOMMU`. I need to ensure a comprehensive overview. I'm thinking, "what external elements interact with this feature? What components are relying on it, and what, in turn, does it depend on?" I need to consider things like the kernel modules involved, their version compatibility, any necessary firmware updates, and any potential conflicts with other hardware or software configurations on this system. My priority is to identify any potential sticking points *before* I even begin to implement or troubleshoot anything further. This involves a deep dive into the relevant documentation, kernel configurations, and known compatibility matrices. This check is crucial for a stable and properly functioning system. |
| 10/2 | 2026/07/08 21:49 | tool | grepper |
0mArgs:{
"Expression": "config AMD_IOMMU",
"PathPrefix": "drivers/iommu/amd/"
}Results: {
"Output": "drivers/iommu/amd/Kconfig-2-# AMD IOMMU support\ndrivers/iommu/amd/Kconfig:3:config AMD_IOMMU\ndrivers/iommu/amd/Kconfig-4-\tbool \"AMD IOMMU support\"\n--\ndrivers/iommu/amd/Kconfig-32-\ndrivers/iommu/amd/Kconfig:33:config AMD_IOMMU_IOMMUFD\ndrivers/iommu/amd/Kconfig-34-\tbool \"Enable IOMMUFD features for AMD IOMMU (EXPERIMENTAL)\"\n--\ndrivers/iommu/amd/Kconfig-42-\ndrivers/iommu/amd/Kconfig:43:config AMD_IOMMU_DEBUGFS\ndrivers/iommu/amd/Kconfig-44-\tbool \"Enable AMD IOMMU internals in DebugFS\"\n"
} |
| 11/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12891 output: 36 thoughts: 16 Thoughts: Okay, let's dive into this. Here's my take on those thoughts, as if they're my own: **Analyzing the Kconfig for the AMD IOMMU Driver** Alright, time to get to it. Let's see what's going on in the `drivers/iommu/amd/Kconfig` file. Given my expertise, I need to understand exactly how this AMD IOMMU driver is configured and what options are available. I'm immediately looking for the core settings – the ones that define the very foundation of how this driver is built and enabled. I'll be scrutinizing the dependencies, the default states, and any conditional logic that's in place. I want to see how these settings play with the broader IOMMU framework within the kernel and how they impact the overall system configuration. Specifically, I'll pay attention to any hardware dependencies, and how these configurations will play with any other related hardware. This file is the key to understanding the build-time control and configurability of this critical component. |
| 12/2 | 2026/07/08 21:49 | tool | read-file |
0mArgs:{
"File": "drivers/iommu/amd/Kconfig",
"FirstLine": 1,
"LineCount": 20
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0-only\n 2:\t# AMD IOMMU support\n 3:\tconfig AMD_IOMMU\n 4:\t\tbool \"AMD IOMMU support\"\n 5:\t\tselect SWIOTLB\n 6:\t\tselect PCI_MSI\n 7:\t\tselect PCI_ATS\n 8:\t\tselect PCI_PRI\n 9:\t\tselect PCI_PASID\n 10:\t\tselect IRQ_MSI_LIB\n 11:\t\tselect MMU_NOTIFIER\n 12:\t\tselect IOMMU_API\n 13:\t\tselect IOMMU_IOVA\n 14:\t\tselect IOMMU_SVA\n 15:\t\tselect IOMMU_IOPF\n 16:\t\tselect IOMMUFD_DRIVER if IOMMUFD\n 17:\t\tselect GENERIC_PT\n 18:\t\tselect IOMMU_PT\n 19:\t\tselect IOMMU_PT_AMDV1\n 20:\t\tselect IOMMU_PT_X86_64\n"
} |
| 13/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13430 output: 26 thoughts: 47 Thoughts: Okay, here's my take on those considerations: **Thinking Through IOMMU Configuration** Right, so I'm satisfied that `AMD_IOMMU` is the correct setting. It's the base functionality I need. But, I'm not stopping there; let's drill down a bit further. Now, what about `IRQ_REMAP`? That's the next key piece of the puzzle. The question is, where is that option defined? I'm going to quickly check in the kernel config files. Either `arch/x86/Kconfig` or `drivers/iommu/Kconfig` should have the details I'm after, and that should clarify everything. |
| 14/2 | 2026/07/08 21:49 | tool | grepper |
0mArgs:{
"Expression": "config IRQ_REMAP",
"PathPrefix": ""
}Results: {
"Output": "drivers/iommu/Kconfig=199=source \"drivers/iommu/riscv/Kconfig\"\ndrivers/iommu/Kconfig-200-\ndrivers/iommu/Kconfig:201:config IRQ_REMAP\ndrivers/iommu/Kconfig-202-\tbool \"Support for Interrupt Remapping\"\n"
} |
| 15/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13751 output: 36 thoughts: 21 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience: **Analyzing the IRQ_REMAP Configuration in the IOMMU Driver** Alright, let's dive into the `drivers/iommu/Kconfig` file. Specifically, I need to understand the configuration options related to `IRQ_REMAP`. I suspect I'll be looking for dependencies, default settings, and potential build-time constraints or conflicts. This is a critical area, as incorrect settings here can lead to significant performance degradation or even system instability when handling interrupt remapping. I'll be focused on how this configuration interacts with different IOMMU implementations and if there are specific architectural considerations at play. I'll pay close attention to the implications of enabling or disabling this feature. I'll need to note any platform-specific conditionals or limitations. The goal is a deep understanding of the ramifications of any changes I'm considering within this section, so I'm scanning for any subtle details that might be relevant. |
| 16/2 | 2026/07/08 21:49 | tool | read-file |
0mArgs:{
"File": "drivers/iommu/Kconfig",
"FirstLine": 201,
"LineCount": 10
}Results: {
"Contents": " 201:\tconfig IRQ_REMAP\n 202:\t\tbool \"Support for Interrupt Remapping\"\n 203:\t\tdepends on X86_64 \u0026\u0026 X86_IO_APIC \u0026\u0026 PCI_MSI \u0026\u0026 ACPI\n 204:\t\tselect IRQ_MSI_LIB\n 205:\t\thelp\n 206:\t\t Supports Interrupt remapping for IO-APIC and MSI devices.\n 207:\t\t To use x2apic mode in the CPU's which support x2APIC enhancements or\n 208:\t\t to support platforms with CPU's having \u003e 8 bit APIC ID, say Y.\n 209:\t\n 210:\t# OMAP IOMMU support\n"
} |
| 17/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14212 output: 40 thoughts: 514 Thoughts: **Analyzing Potential Fuzzing Targets in the IRQ_REMAP Patch** Okay, so this `IRQ_REMAP` configuration looks promising. The patch targets `arch/x86/kvm/svm/avic.c` and `drivers/iommu/amd/iommu.c`, which makes it immediately interesting. I need to zero in on the key functions modified here. Specifically, I need to understand: `avic_add_vcpu_to_gappi_wakeup_list`, `avic_remove_vcpu_from_gappi_wakeup_list`, `avic_gappi_wakeup_handler`, `avic_update_iommu_vcpu_affinity`, `amd_iommu_update_ga`, and `amd_iommu_activate_guest_mode`. Let me quickly check which of these are static. Good, `avic_add_vcpu_to_gappi_wakeup_list`, `avic_gappi_wakeup_handler`, and `avic_update_iommu_vcpu_affinity` are all static. `amd_iommu_update_ga` and `amd_iommu_activate_guest_mode` are exported, so that's helpful. `avic_pi_update_irte` is present but not static, so I should keep an eye on that as well, though it appears to be an existing function. Okay, let's make a clear list of the relevant symbols I need to investigate in more detail: `avic_add_vcpu_to_gappi_wakeup_list`, `avic_remove_vcpu_from_gappi_wakeup_list`, `avic_gappi_wakeup_handler`, `avic_update_iommu_vcpu_affinity`, `amd_iommu_update_ga`, and `amd_iommu_activate_guest_mode`. Now, the configurations are listed as `KVM_AMD`, `AMD_IOMMU`, and of course, `IRQ_REMAP`. That's standard and expected. Hold on, I see a potential gotcha... `amd_iommu_gappi` is a *boot parameter*. Syzkaller might not pass that by default! The problem is that I can't directly control boot parameters using the set-results mechanism. I can only control configs and focus symbols. The prompt states that I need to return `WorthFuzzing=false` if the code paths are unreachable in virtualized environments like GCE or QEMU, even with emulated hardware. So, is GAPPI reachable *without* that boot parameter? I need to check how GAPPI is used to determine if it's reachable. I'll check `parse_amd_iommu_options` to determine how that's handled. |
| 18/2 | 2026/07/08 21:49 | tool | read-file |
0mArgs:{
"File": "drivers/iommu/amd/init.c",
"FirstLine": 3755,
"LineCount": 20
}Results: {
"Contents": "3755:\t\t\t} else if (strncmp(str, \"irtcachedis\", 11) == 0) {\n3756:\t\t\t\tamd_iommu_irtcachedis = true;\n3757:\t\t\t} else if (strncmp(str, \"nohugepages\", 11) == 0) {\n3758:\t\t\t\tpr_info(\"Restricting V1 page-sizes to 4KiB\");\n3759:\t\t\t\tamd_iommu_pgsize_bitmap = AMD_IOMMU_PGSIZES_4K;\n3760:\t\t\t} else if (strncmp(str, \"v2_pgsizes_only\", 15) == 0) {\n3761:\t\t\t\tpr_info(\"Restricting V1 page-sizes to 4KiB/2MiB/1GiB\");\n3762:\t\t\t\tamd_iommu_pgsize_bitmap = AMD_IOMMU_PGSIZES_V2;\n3763:\t\t\t} else if (strncmp(str, \"gappi\", 5) == 0) {\n3764:\t\t\t\tamd_iommu_gappi = true;\n3765:\t\t\t} else {\n3766:\t\t\t\tpr_notice(\"Unknown option - '%s'\\n\", str);\n3767:\t\t\t}\n3768:\t\n3769:\t\t\tstr += strcspn(str, \",\");\n3770:\t\t\twhile (*str == ',')\n3771:\t\t\t\tstr++;\n3772:\t\t}\n3773:\t\n3774:\t\treturn 1;\n"
} |
| 19/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15771 output: 36 thoughts: 120 Thoughts: **Analyzing the `amd_iommu_gappi` Setting** Okay, so it looks like `amd_iommu_gappi` defaults to being disabled. That makes sense, but it also presents a potential issue. If the default is false, and syzkaller, which is the fuzzer we're using, doesn't explicitly pass `amd_iommu=gappi` as a boot parameter, then `amd_iommu_gappi` will stay disabled. Hmm, wait a second, I remember syzkaller *can* inject boot parameters, if we configure it correctly. However, as a reviewer in this situation, I can't directly specify those boot parameters for the fuzzer. This limits my ability to test this configuration. This brings up another question: is `amd_iommu_gappi` *only* controllable via the boot parameter? If there's another mechanism, a module parameter or something, that would change things. I need to make sure this isn't controlled by something other than the kernel boot parameter. Let me check the source code for any alternative configuration options for `amd_iommu_gappi` and make sure it's not being set anywhere else. |
| 20/2 | 2026/07/08 21:49 | tool | grepper |
0mArgs:{
"Expression": "amd_iommu_gappi",
"PathPrefix": "drivers/iommu/amd/"
}Results: {
"Output": "drivers/iommu/amd/amd_iommu.h=43=int amd_iommu_enable_faulting(unsigned int cpu);\ndrivers/iommu/amd/amd_iommu.h:44:extern bool amd_iommu_gappi;\ndrivers/iommu/amd/amd_iommu.h-45-extern int amd_iommu_guest_ir;\n--\ndrivers/iommu/amd/init.c=161=int amd_iommu_gpt_level = PAGE_MODE_4_LEVEL;\ndrivers/iommu/amd/init.c-162-\ndrivers/iommu/amd/init.c:163:bool amd_iommu_gappi;\ndrivers/iommu/amd/init.c:164:EXPORT_SYMBOL(amd_iommu_gappi);\ndrivers/iommu/amd/init.c-165-\n--\ndrivers/iommu/amd/init.c=2998=static void enable_iommus_vapic(void)\n--\ndrivers/iommu/amd/init.c-3004-\tfor_each_iommu(iommu) {\ndrivers/iommu/amd/init.c:3005:\t\t/* Disable GAPPI, do not check amd_iommu_gappi as it may be\ndrivers/iommu/amd/init.c-3006-\t\t * false in new kexec kernel even though previous kernel has\n--\ndrivers/iommu/amd/init.c-3049-\ndrivers/iommu/amd/init.c:3050:\tif (amd_iommu_gappi \u0026\u0026\ndrivers/iommu/amd/init.c-3051-\t !(check_feature(FEATURE_GAPPI) \u0026\u0026\n--\ndrivers/iommu/amd/init.c-3053-\t\tpr_warn(\"GAPPI is not supported.\\n\");\ndrivers/iommu/amd/init.c:3054:\t\tamd_iommu_gappi = false;\ndrivers/iommu/amd/init.c-3055-\t}\n--\ndrivers/iommu/amd/init.c-3058-\tfor_each_iommu(iommu) {\ndrivers/iommu/amd/init.c:3059:\t\tif (amd_iommu_gappi)\ndrivers/iommu/amd/init.c-3060-\t\t\tiommu_feature_enable(iommu, CONTROL_GAPPI_EN);\n--\ndrivers/iommu/amd/init.c-3071-\tpr_info(\"Virtual APIC enabled with %s\\n\",\ndrivers/iommu/amd/init.c:3072:\t\tamd_iommu_gappi ? \"GAPPI\" : \"GALOG\");\ndrivers/iommu/amd/init.c-3073-#endif\n--\ndrivers/iommu/amd/init.c=3736=static int __init parse_amd_iommu_options(char *str)\n--\ndrivers/iommu/amd/init.c-3763-\t\t} else if (strncmp(str, \"gappi\", 5) == 0) {\ndrivers/iommu/amd/init.c:3764:\t\t\tamd_iommu_gappi = true;\ndrivers/iommu/amd/init.c-3765-\t\t} else {\n--\ndrivers/iommu/amd/iommu.c=3962=static void __amd_iommu_update_ga(struct irte_ga *entry, int apicid, int flags)\n--\ndrivers/iommu/amd/iommu.c-3973-\ndrivers/iommu/amd/iommu.c:3974:\t\tif (amd_iommu_gappi) {\ndrivers/iommu/amd/iommu.c-3975-\t\t\tentry-\u003elo.fields_vapic.gappi_dis = !posted_intr \u0026\u0026\n--\ndrivers/iommu/amd/iommu.c=4026=int amd_iommu_activate_guest_mode(void *data, int apicid, int flags)\n--\ndrivers/iommu/amd/iommu.c-4047-\ndrivers/iommu/amd/iommu.c:4048:\tif (amd_iommu_gappi)\ndrivers/iommu/amd/iommu.c-4049-\t\tentry-\u003elo.fields_vapic.ga_tag = POSTED_INTR_WAKEUP_VECTOR;\n"
} |
| 21/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 17348 output: 43 thoughts: 227 Thoughts: **Analyzing the Scope of this Patch** Okay, so I see that this feature, whatever it is, is *only* enabled through a boot parameter. That seems straightforward enough on the surface. However, the more I dig into this patch, the implications are broader than that initial limitation suggests. I'm focusing on the modifications to `amd_iommu_update_ga` and `amd_iommu_activate_guest_mode` – these functions' signatures and core logic have been altered. The critical thing here is that they're called even when this boot parameter isn't explicitly set. For example, I'm looking at `arch/x86/kvm/svm/avic.c` right now. `avic_update_iommu_vcpu_affinity` calls both `amd_iommu_update_ga` and `amd_iommu_activate_guest_mode`. And guess what? `avic_update_iommu_vcpu_affinity` *doesn't* check `amd_iommu_gappi`. It calls these functions regardless of the boot parameter's setting. The logic within `avic_update_iommu_vcpu_affinity` seems to handle both scenarios, whether `amd_iommu_gappi` is true or false. Therefore, those modified functions are absolutely reachable, even without that specific boot parameter being set! That's a significant point. I need to understand exactly how `avic_update_iommu_vcpu_affinity` handles this duality. Let me take a look at the code in `arch/x86/kvm/svm/avic.c` and dig into `avic_update_iommu_vcpu_affinity`. I need to get a clear picture of how these changes interact, even when the intended feature is disabled. |
| 22/2 | 2026/07/08 21:49 | tool | read-file |
0mArgs:{
"File": "arch/x86/kvm/svm/avic.c",
"FirstLine": 1069,
"LineCount": 40
}Results: {
"Contents": "1069:\tstatic void avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int apicid,\n1070:\t\t\t\t\t\t int cpu, enum avic_vcpu_action action)\n1071:\t{\n1072:\t\tint posted_intr = !!(action \u0026 AVIC_START_BLOCKING) \u003c\u003c\n1073:\t\t\t\t AMD_IOMMU_FLAG_POSTED_INTR_SHIFT;\n1074:\t\tint is_vcpu_running = (apicid \u003e= 0) \u003c\u003c\n1075:\t\t\t\t AMD_IOMMU_FLAG_VCPU_RUNNING_SHIFT;\n1076:\t\tint flags = posted_intr | is_vcpu_running;\n1077:\t\tstruct vcpu_svm *svm = to_svm(vcpu);\n1078:\t\tstruct kvm_kernel_irqfd *irqfd;\n1079:\t\n1080:\t\tlockdep_assert_held(\u0026svm-\u003eir_list_lock);\n1081:\t\n1082:\t\t/*\n1083:\t\t * Here, we go through the per-vcpu ir_list to update all existing\n1084:\t\t * interrupt remapping table entry targeting this vcpu.\n1085:\t\t */\n1086:\t\tif (list_empty(\u0026svm-\u003eir_list)) {\n1087:\t\t\tif (amd_iommu_gappi \u0026\u0026 cpu \u003e= 0)\n1088:\t\t\t\tsvm-\u003egappi_cpu = cpu;\n1089:\t\t\treturn;\n1090:\t\t}\n1091:\t\n1092:\t\tif (is_vcpu_running \u0026\u0026 amd_iommu_gappi) {\n1093:\t\t\t/* IF condition handles the initial state */\n1094:\t\t\tif (svm-\u003egappi_cpu != -1)\n1095:\t\t\t\tavic_remove_vcpu_from_gappi_wakeup_list(svm, svm-\u003egappi_cpu);\n1096:\t\n1097:\t\t\tsvm-\u003egappi_cpu = cpu; /* Store cpu no as target for GAPPI */\n1098:\t\t} else if (amd_iommu_gappi) {\n1099:\t\t\tapicid = kvm_cpu_get_apicid(svm-\u003egappi_cpu);\n1100:\t\t\tavic_add_vcpu_to_gappi_wakeup_list(svm, svm-\u003egappi_cpu);\n1101:\t\t}\n1102:\t\n1103:\t\tlist_for_each_entry(irqfd, \u0026svm-\u003eir_list, vcpu_list) {\n1104:\t\t\tvoid *data = irqfd-\u003eirq_bypass_data;\n1105:\t\n1106:\t\t\tif (!(action \u0026 AVIC_TOGGLE_ON_OFF))\n1107:\t\t\t\tWARN_ON_ONCE(amd_iommu_update_ga(data, apicid, flags));\n1108:\t\t\telse if (is_vcpu_running)\n"
} |
| 23/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 18785 output: 43 thoughts: 346 Thoughts: **Analyzing the AMD IOMMU Code Changes** Okay, so I'm looking at this code and it seems like `amd_iommu_update_ga` and `amd_iommu_activate_guest_mode` are now getting called with `apicid` and `flags` instead of the old `cpu` and `ga_log_intr` parameters. This is definitely a functional change to the AVIC code, even if GAPPI isn't being used. The crucial thing is that `flags` is being constructed and passed to `amd_iommu_update_ga`. That sounds like a good place to focus our fuzzing efforts. Before I dive too deep into fuzzing, I should probably verify the relevant config options. Let's see... `KVM_AMD`, `AMD_IOMMU`, and `IRQ_REMAP`. Okay, `KVM_AMD` is tristate, `AMD_IOMMU` and `IRQ_REMAP` are booleans. I should double check if there are any other configs. It looks like `CONFIG_KVM` is implied by `CONFIG_KVM_AMD` and `CONFIG_IOMMU_API` is selected by `AMD_IOMMU`. Now, I need to list the key symbols and functions I should be keeping an eye on. Right, let's see: `avic_update_iommu_vcpu_affinity`, `amd_iommu_update_ga`, `amd_iommu_activate_guest_mode`, `avic_pi_update_irte`, and `__amd_iommu_update_ga`. Wait a minute, `__amd_iommu_update_ga` is static within `drivers/iommu/amd/iommu.c`. Right, I should be looking at `drivers/iommu/amd/iommu.c` for this function. Good to know. |
| 24/2 | 2026/07/08 21:49 | tool | grepper |
0mArgs:{
"Expression": "__amd_iommu_update_ga",
"PathPrefix": "drivers/iommu/amd/iommu.c"
}Results: {
"Output": "drivers/iommu/amd/iommu.c=3954=static const struct irq_domain_ops amd_ir_domain_ops = {\n--\ndrivers/iommu/amd/iommu.c-3961-\ndrivers/iommu/amd/iommu.c:3962:static void __amd_iommu_update_ga(struct irte_ga *entry, int apicid, int flags)\ndrivers/iommu/amd/iommu.c-3963-{\n--\ndrivers/iommu/amd/iommu.c=4005=int amd_iommu_update_ga(void *data, int apicid, int flags)\n--\ndrivers/iommu/amd/iommu.c-4018-\ndrivers/iommu/amd/iommu.c:4019:\t__amd_iommu_update_ga(entry, apicid, flags);\ndrivers/iommu/amd/iommu.c-4020-\n--\ndrivers/iommu/amd/iommu.c=4026=int amd_iommu_activate_guest_mode(void *data, int apicid, int flags)\n--\ndrivers/iommu/amd/iommu.c-4052-\ndrivers/iommu/amd/iommu.c:4053:\t__amd_iommu_update_ga(entry, apicid, flags);\ndrivers/iommu/amd/iommu.c-4054-\n"
} |
| 25/2 | 2026/07/08 21:49 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 19990 output: 40 thoughts: 192 Thoughts: **Analyzing IOMMU and AVIC Function Dependencies** Okay, so `__amd_iommu_update_ga` is definitely static. That narrows down the key functions I need to focus on. My initial list includes: `avic_update_iommu_vcpu_affinity`, `amd_iommu_update_ga`, `amd_iommu_activate_guest_mode`, `avic_pi_update_irte`, and, of course, `__amd_iommu_update_ga` itself. Then there's the AVIC-specific group: `avic_add_vcpu_to_gappi_wakeup_list`, `avic_remove_vcpu_from_gappi_wakeup_list`, and `avic_gappi_wakeup_handler`. Now, I'm just curious if I've missed anything, so I'll quickly consider `avic_destroy_vcpu`, `avic_init_vcpu`, and `svm_ir_list_del`. My intuition says these might be relevant, so I'll add them to the list to check later. My immediate next step is to examine `avic_destroy_vcpu` and `avic_init_vcpu`. |
| 26/2 | 2026/07/08 21:50 | tool | grepper |
0mArgs:{
"Expression": "avic_destroy_vcpu",
"PathPrefix": "arch/x86/kvm/svm/avic.c"
}Results: {
"Output": "arch/x86/kvm/svm/avic.c=910=static void avic_remove_vcpu_from_gappi_wakeup_list(struct vcpu_svm *svm, int cpu)\n--\narch/x86/kvm/svm/avic.c-922-\narch/x86/kvm/svm/avic.c:923:void avic_destroy_vcpu(struct vcpu_svm *svm)\narch/x86/kvm/svm/avic.c-924-{\n"
} |
| 27/2 | 2026/07/08 21:50 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 20626 output: 41 thoughts: 244 Thoughts: **My Assessment of the Recent Modifications** Okay, so I'm seeing a focused set of changes here, mostly centered around the Advanced Virtual Interrupt Controller (AVIC) and its interaction with the AMD IOMMU. It's clear that the addition of `avic_destroy_vcpu` is a key addition, likely a necessary cleanup function to complement existing VCPU initialization and lifecycle management. The modifications to `avic_init_vcpu`, `svm_ir_list_del`, `avic_hardware_setup`, `avic_hardware_unsetup`, `enable_iommus_vapic`, and `iommu_disable` all suggest deeper integration and refined control. Focusing on the core functions, these are the critical pieces I'm seeing: `avic_update_iommu_vcpu_affinity`, `amd_iommu_update_ga`, `amd_iommu_activate_guest_mode`, `avic_pi_update_irte`, `__amd_iommu_update_ga`, `avic_add_vcpu_to_gappi_wakeup_list`, `avic_remove_vcpu_from_gappi_wakeup_list`, `avic_gappi_wakeup_handler`, `avic_destroy_vcpu` and `svm_ir_list_del`. The presence of so many IOMMU and GA-related function indicates a careful consideration of guest addressing and interrupt routing. The GAppI wakeup list functions, in conjunction with the handler, look like they are central to the AVIC interrupt injection process. I need to confirm whether `svm_ir_list_del` is static. That would impact its visibility and scope. That has significant implications on the function's internal consistency. |
| 28/2 | 2026/07/08 21:50 | tool | grepper |
0mArgs:{
"Expression": "svm_ir_list_del",
"PathPrefix": "arch/x86/kvm/svm/avic.c"
}Results: {
"Output": "arch/x86/kvm/svm/avic.c=931=void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/svm/avic.c-936-\narch/x86/kvm/svm/avic.c:937:static void svm_ir_list_del(struct kvm_kernel_irqfd *irqfd)\narch/x86/kvm/svm/avic.c-938-{\n--\narch/x86/kvm/svm/avic.c=955=int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,\n--\narch/x86/kvm/svm/avic.c-962-\t */\narch/x86/kvm/svm/avic.c:963:\tsvm_ir_list_del(irqfd);\narch/x86/kvm/svm/avic.c-964-\n"
} |
| 29/2 | 2026/07/08 21:50 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 21554 output: 273 thoughts: 142 Thoughts: **My Assessment of the Configuration and Its Implications** Okay, it's clear: this is a static configuration. No dynamic elements to consider here. Alright, let's break down the relevant configurations: we're dealing with `KVM_AMD`, `AMD_IOMMU`, and `IRQ_REMAP`. These three are the key components. The patch itself is introducing Guest APIC Posted Interrupts, or GAPPI, specifically for AMD's IOMMU and KVM SVM AVIC. Now, the meat of this is that it's modifying the update process for interrupt remapping table entries and the vCPU affinity logic. The important thing is that these changes are absolutely relevant within virtualized environments, like when using QEMU with KVM SVM. What's really interesting is that these updates are impacting core AVIC and IOMMU logic, even if GAPPI isn't directly activated through a boot parameter. This means that functionality is present, even if not directly enabled. This makes it a great candidate for fuzzing to check for unexpected behavior. I'll proceed to set the results based on this understanding. |
| 30/2 | 2026/07/08 21:50 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"KVM_AMD",
"AMD_IOMMU",
"IRQ_REMAP"
],
"FocusSymbols": [
"avic_update_iommu_vcpu_affinity",
"amd_iommu_update_ga",
"amd_iommu_activate_guest_mode",
"avic_pi_update_irte",
"__amd_iommu_update_ga",
"avic_add_vcpu_to_gappi_wakeup_list",
"avic_remove_vcpu_from_gappi_wakeup_list",
"avic_gappi_wakeup_handler",
"avic_destroy_vcpu",
"svm_ir_list_del"
],
"Reasoning": "The patch introduces Guest APIC Posted Interrupts (GAPPI) support for AMD IOMMU and KVM SVM AVIC. It modifies the interrupt remapping table entry updates and vCPU affinity logic, which are reachable in virtualized environments (e.g., QEMU with KVM SVM). The changes alter core AVIC and IOMMU logic even when GAPPI is not explicitly enabled via boot parameter, making it functional and worth fuzzing.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"KVM_AMD",
"AMD_IOMMU",
"IRQ_REMAP"
],
"FocusSymbols": [
"avic_update_iommu_vcpu_affinity",
"amd_iommu_update_ga",
"amd_iommu_activate_guest_mode",
"avic_pi_update_irte",
"__amd_iommu_update_ga",
"avic_add_vcpu_to_gappi_wakeup_list",
"avic_remove_vcpu_from_gappi_wakeup_list",
"avic_gappi_wakeup_handler",
"avic_destroy_vcpu",
"svm_ir_list_del"
],
"Reasoning": "The patch introduces Guest APIC Posted Interrupts (GAPPI) support for AMD IOMMU and KVM SVM AVIC. It modifies the interrupt remapping table entry updates and vCPU affinity logic, which are reachable in virtualized environments (e.g., QEMU with KVM SVM). The changes alter core AVIC and IOMMU logic even when GAPPI is not explicitly enabled via boot parameter, making it functional and worth fuzzing.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|