| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/19 20:01 | flow | patch-triage |
11mArgs:null Results: {
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"distribute_float_irqs",
"kvm_s390_pv_sclp_kick",
"kvm_s390_inject_vm"
],
"KMSANReasoning": "The patch modifies the handling of floating interrupts in KVM for s390, introducing a new statistic `inject_redist` and changing how vCPUs are kicked when interrupts are pending. The only potential uninitialized memory is the local variable `parm` in `__inject_vm()`, which is left uninitialized for certain interrupt types (e.g., `KVM_S390_MCHK`). However, this uninitialized value is passed to `__floating_irq_kick()` and subsequently to `inti_to_irq_pend_mask()`, where it is completely ignored for those specific interrupt types. KMSAN tracks uninitialized memory at the shadow level and only reports an error if the uninitialized value is used in a branch, as a memory address, or copied to userspace. Since `parm` is never evaluated in these ways when uninitialized, it will not trigger a KMSAN report. Other changes involve basic control flow, vCPU wakeups, and a new field in `struct kvm_vm_stat` (which is zero-allocated). There are no new structures copied to userspace, no complex data parsing, and no uninitialized memory risks introduced. Standard KASAN and other bug detectors are sufficient.",
"NeedsKMSAN": false,
"Reasoning": "The patch modifies the handling and distribution of floating interrupts in KVM on s390x. It introduces new logic to distribute floating IRQs across VCPUs and to kick VCPUs when specific interrupts are injected. These changes affect core KVM interrupt injection paths, which are reachable from userspace via KVM ioctls (e.g., KVM_S390_INTERRUPT) and during VCPU execution.",
"WorthFuzzing": true
} |
| 1/1 | 2026/08/19 20:01 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 90883cfa06e77be61b79a608549167bd1ebd2d59\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Aug 19 20:01:52 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h\nindex b4182ca4435fb..1d62bdd7aca5e 100644\n--- a/arch/s390/include/asm/kvm_host.h\n+++ b/arch/s390/include/asm/kvm_host.h\n@@ -467,6 +467,7 @@ struct kvm_vm_stat {\n \tu64 gmap_shadow_r3_entry;\n \tu64 gmap_shadow_sg_entry;\n \tu64 gmap_shadow_pg_entry;\n+\tu64 inject_redist;\n };\n \n struct kvm_arch_memory_slot {\ndiff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c\nindex 1980df61ef304..e1de3f471ffd0 100644\n--- a/arch/s390/kvm/intercept.c\n+++ b/arch/s390/kvm/intercept.c\n@@ -536,6 +536,15 @@ static int handle_pv_sclp(struct kvm_vcpu *vcpu)\n \tset_bit(IRQ_PEND_EXT_SERVICE, \u0026fi-\u003epending_irqs);\n \tclear_bit(IRQ_PEND_EXT_SERVICE, \u0026fi-\u003emasked_irqs);\n \tspin_unlock_irqrestore(\u0026fi-\u003elock, flags);\n+\n+\t/*\n+\t * We missed the floating IRQ kick since we can only inject\n+\t * when we end up here and not when the irq was injected via\n+\t * the FLIC.\n+\t *\n+\t * Now that we have cleared the masking we can kick cpus.\n+\t */\n+\tkvm_s390_pv_sclp_kick(vcpu);\n \treturn 0;\n }\n \ndiff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c\nindex 8f24bcd1a6d36..1ee9ab2505042 100644\n--- a/arch/s390/kvm/interrupt.c\n+++ b/arch/s390/kvm/interrupt.c\n@@ -367,6 +367,37 @@ static unsigned long deliverable_irqs(struct kvm_vcpu *vcpu)\n \treturn active_mask;\n }\n \n+void distribute_float_irqs(struct kvm *kvm)\n+{\n+\tstruct kvm_vcpu *dst_vcpu;\n+\tint sigcpu, online_vcpus;\n+\n+\tif (!READ_ONCE(kvm-\u003earch.float_int.pending_irqs))\n+\t\treturn;\n+\n+\tonline_vcpus = atomic_read(\u0026kvm-\u003eonline_vcpus);\n+\n+\t/*\n+\t * Not too worried about synchronization for idle_mask. We\n+\t * might burn too many cycles but apart from that waking a\n+\t * vcpu is not harmful.\n+\t */\n+\tsigcpu = find_first_bit(kvm-\u003earch.idle_mask, online_vcpus);\n+\t/* Well nobody's sleeping so someone will likely take the IRQ soon */\n+\tif (sigcpu == online_vcpus)\n+\t\treturn;\n+\n+\tdo {\n+\t\tdst_vcpu = kvm_get_vcpu(kvm, sigcpu);\n+\t\tif (deliverable_irqs(dst_vcpu)) {\n+\t\t\tkvm-\u003estat.inject_redist++;\n+\t\t\tkvm_s390_vcpu_wakeup(dst_vcpu);\n+\t\t\tbreak;\n+\t\t}\n+\t\tsigcpu = find_next_bit(kvm-\u003earch.idle_mask, online_vcpus, ++sigcpu);\n+\t} while (sigcpu \u003c online_vcpus);\n+}\n+\n static void __set_cpu_idle(struct kvm_vcpu *vcpu)\n {\n \tkvm_s390_set_cpuflags(vcpu, CPUSTAT_WAIT);\n@@ -1915,49 +1946,129 @@ static int __inject_io(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)\n \treturn 0;\n }\n \n+static u64 inti_to_irq_pend_mask(u64 type, int isc)\n+{\n+\tswitch (type) {\n+\tcase KVM_S390_MCHK:\n+\t\t/* Only repressible machine checks are floating */\n+\t\treturn BIT(IRQ_PEND_MCHK_REP);\n+\tcase KVM_S390_INT_VIRTIO:\n+\t\treturn BIT(IRQ_PEND_VIRTIO);\n+\tcase KVM_S390_INT_SERVICE:\n+\t\treturn BIT(IRQ_PEND_EXT_SERVICE) |\n+\t\t BIT(IRQ_PEND_EXT_SERVICE_EV);\n+\tcase KVM_S390_INT_PFAULT_DONE:\n+\t\treturn BIT(IRQ_PEND_PFAULT_DONE);\n+\tcase KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:\n+\t\treturn isc_to_irq_type(isc);\n+\tdefault:\n+\t\treturn 0;\n+\t}\n+}\n+\n /*\n- * Find a destination VCPU for a floating irq and kick it.\n+ * Setup intervention masks to catch running vcpus that hopefully open\n+ * their masks soonish and kick sleeping vcpus to motivate them to\n+ * take IRQs.\n */\n-static void __floating_irq_kick(struct kvm *kvm, u64 type)\n+static void vcpu_intervention_kick(struct kvm_vcpu *vcpu, u64 type)\n+{\n+\t/* make the VCPU drop out of the SIE, or wake it up if sleeping */\n+\tswitch (type) {\n+\tcase KVM_S390_MCHK:\n+\t\tkvm_s390_set_cpuflags(vcpu, CPUSTAT_STOP_INT);\n+\t\tbreak;\n+\tcase KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:\n+\t\tif (!(type \u0026 KVM_S390_INT_IO_AI_MASK \u0026\u0026\n+\t\t vcpu-\u003ekvm-\u003earch.gisa_int.origin) ||\n+\t\t kvm_s390_pv_cpu_get_handle(vcpu))\n+\t\t\tkvm_s390_set_cpuflags(vcpu, CPUSTAT_IO_INT);\n+\t\tbreak;\n+\tdefault:\n+\t\tkvm_s390_set_cpuflags(vcpu, CPUSTAT_EXT_INT);\n+\t\tbreak;\n+\t}\n+\tkvm_s390_vcpu_wakeup(vcpu);\n+}\n+\n+static void kick_cpu_irq(struct kvm *kvm, u64 type, u64 parm)\n {\n \tstruct kvm_vcpu *dst_vcpu;\n \tint sigcpu, online_vcpus, nr_tries = 0;\n+\tu64 irq_pend_mask;\n+\tunsigned long i;\n \n \tonline_vcpus = atomic_read(\u0026kvm-\u003eonline_vcpus);\n \tif (!online_vcpus)\n \t\treturn;\n \n+\tirq_pend_mask = inti_to_irq_pend_mask(type, parm);\n \tfor (sigcpu = kvm-\u003earch.float_int.last_sleep_cpu; ; sigcpu++) {\n \t\tsigcpu %= online_vcpus;\n \t\tdst_vcpu = kvm_get_vcpu(kvm, sigcpu);\n-\t\tif (!is_vcpu_stopped(dst_vcpu))\n+\t\tif (!is_vcpu_stopped(dst_vcpu) \u0026\u0026\n+\t\t deliverable_irqs(dst_vcpu) \u0026 irq_pend_mask)\n \t\t\tbreak;\n \t\t/* avoid endless loops if all vcpus are stopped */\n-\t\tif (nr_tries++ \u003e= online_vcpus)\n-\t\t\treturn;\n+\t\tif (nr_tries++ \u003e= online_vcpus * 2) {\n+\t\t\tdst_vcpu = NULL;\n+\t\t\tbreak;\n+\t\t}\n \t}\n \n-\t/* make the VCPU drop out of the SIE, or wake it up if sleeping */\n-\tswitch (type) {\n-\tcase KVM_S390_MCHK:\n-\t\tkvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_STOP_INT);\n-\t\tbreak;\n-\tcase KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:\n-\t\tif (!(type \u0026 KVM_S390_INT_IO_AI_MASK \u0026\u0026\n-\t\t kvm-\u003earch.gisa_int.origin) ||\n-\t\t kvm_s390_pv_cpu_get_handle(dst_vcpu))\n-\t\t\tkvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_IO_INT);\n-\t\tbreak;\n-\tdefault:\n-\t\tkvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_EXT_INT);\n-\t\tbreak;\n+\t/* Nobody was enabled, time to wake all of them */\n+\tif (!dst_vcpu) {\n+\t\tkvm_for_each_vcpu(i, dst_vcpu, kvm)\n+\t\t\tvcpu_intervention_kick(dst_vcpu, type);\n+\t\treturn;\n \t}\n-\tkvm_s390_vcpu_wakeup(dst_vcpu);\n+\n+\tvcpu_intervention_kick(dst_vcpu, type);\n+}\n+\n+void kvm_s390_pv_sclp_kick(struct kvm_vcpu *vcpu)\n+{\n+\t/*\n+\t * The cpu that called sclp likely will also take the IRQ, no\n+\t * need to kick anyone.\n+\t */\n+\tif (likely(deliverable_irqs(vcpu) \u0026 IRQ_PEND_EXT_SERVICE))\n+\t\treturn;\n+\n+\t/*\n+\t * For the other cases we might have sleeping cpus with open\n+\t * masks. Time to find and kick them.\n+\t */\n+\tkick_cpu_irq(vcpu-\u003ekvm, KVM_S390_INT_SERVICE, -1);\n+}\n+\n+/*\n+ * Find a destination VCPU for a floating irq and kick it.\n+ */\n+static void __floating_irq_kick(struct kvm *kvm, u64 type, u64 parm)\n+{\n+\tint prot;\n+\n+\tmutex_lock(\u0026kvm-\u003elock);\n+\tprot = kvm_s390_pv_is_protected(kvm);\n+\tmutex_unlock(\u0026kvm-\u003elock);\n+\t/*\n+\t * No need to kick on non-ev service IRQs for PV VMs, we're\n+\t * not allowed to inject anyway. We need to wait for the sclp\n+\t * instruction notification AFTER re-entry of the vcpu that\n+\t * handled the instruction intercept.\n+\t */\n+\tif (prot \u0026\u0026 type == KVM_S390_INT_SERVICE \u0026\u0026\n+\t !(parm \u0026 SCCB_EVENT_PENDING))\n+\t\treturn;\n+\n+\tkick_cpu_irq(kvm, type, parm);\n }\n \n static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)\n {\n \tu64 type = READ_ONCE(inti-\u003etype);\n+\tu64 parm;\n \tint rc;\n \n \tswitch (type) {\n@@ -1968,12 +2079,15 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)\n \t\trc = __inject_virtio(kvm, inti);\n \t\tbreak;\n \tcase KVM_S390_INT_SERVICE:\n+\t\tparm = inti-\u003eext.ext_params \u0026 SCCB_EVENT_PENDING;\n \t\trc = __inject_service(kvm, inti);\n \t\tbreak;\n \tcase KVM_S390_INT_PFAULT_DONE:\n \t\trc = __inject_pfault_done(kvm, inti);\n \t\tbreak;\n \tcase KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:\n+\t\t/* Grab isc here since __inject_io() might free inti */\n+\t\tparm = isc_to_irq_type(int_word_to_isc(inti-\u003eio.io_int_word));\n \t\trc = __inject_io(kvm, inti);\n \t\tbreak;\n \tdefault:\n@@ -1982,7 +2096,7 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)\n \tif (rc)\n \t\treturn rc;\n \n-\t__floating_irq_kick(kvm, type);\n+\t__floating_irq_kick(kvm, type, parm);\n \treturn 0;\n }\n \ndiff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c\nindex 518a69c55e85c..d6d46688d9808 100644\n--- a/arch/s390/kvm/kvm-s390.c\n+++ b/arch/s390/kvm/kvm-s390.c\n@@ -86,6 +86,7 @@ const struct kvm_stats_desc kvm_vm_stats_desc[] = {\n \tSTATS_DESC_COUNTER(VM, gmap_shadow_r3_entry),\n \tSTATS_DESC_COUNTER(VM, gmap_shadow_sg_entry),\n \tSTATS_DESC_COUNTER(VM, gmap_shadow_pg_entry),\n+\tSTATS_DESC_COUNTER(VM, inject_redist),\n };\n \n const struct kvm_stats_header kvm_vm_stats_header = {\n@@ -4572,6 +4573,8 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)\n \t\trc = kvm_s390_deliver_pending_interrupts(vcpu);\n \t\tif (rc || guestdbg_exit_pending(vcpu))\n \t\t\treturn rc;\n+\n+\t\tdistribute_float_irqs(vcpu-\u003ekvm);\n \t}\n \n \trc = kvm_s390_handle_requests(vcpu);\ndiff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h\nindex 6d2842fb71a33..7115a8f5b1882 100644\n--- a/arch/s390/kvm/kvm-s390.h\n+++ b/arch/s390/kvm/kvm-s390.h\n@@ -375,6 +375,8 @@ enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);\n int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu);\n void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu);\n void kvm_s390_clear_float_irqs(struct kvm *kvm);\n+void kvm_s390_pv_sclp_kick(struct kvm_vcpu *vcpu);\n+void distribute_float_irqs(struct kvm *kvm);\n int __must_check kvm_s390_inject_vm(struct kvm *kvm,\n \t\t\t\t struct kvm_s390_interrupt *s390int,\n \t\t\t\t struct kvm_s390_interrupt_info *inti);\n"
} |
| 2/1 | 2026/08/19 20:01 | agent | patch-evaluator |
10mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"distribute_float_irqs",
"kvm_s390_pv_sclp_kick",
"kvm_s390_inject_vm"
],
"Reasoning": "The patch modifies the handling and distribution of floating interrupts in KVM on s390x. It introduces new logic to distribute floating IRQs across VCPUs and to kick VCPUs when specific interrupts are injected. These changes affect core KVM interrupt injection paths, which are reachable from userspace via KVM ioctls (e.g., KVM_S390_INTERRUPT) and during VCPU execution.",
"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 90883cfa06e77be61b79a608549167bd1ebd2d59
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Aug 19 20:01:52 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index b4182ca4435fb..1d62bdd7aca5e 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -467,6 +467,7 @@ struct kvm_vm_stat {
u64 gmap_shadow_r3_entry;
u64 gmap_shadow_sg_entry;
u64 gmap_shadow_pg_entry;
+ u64 inject_redist;
};
struct kvm_arch_memory_slot {
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 1980df61ef304..e1de3f471ffd0 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -536,6 +536,15 @@ static int handle_pv_sclp(struct kvm_vcpu *vcpu)
set_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs);
clear_bit(IRQ_PEND_EXT_SERVICE, &fi->masked_irqs);
spin_unlock_irqrestore(&fi->lock, flags);
+
+ /*
+ * We missed the floating IRQ kick since we can only inject
+ * when we end up here and not when the irq was injected via
+ * the FLIC.
+ *
+ * Now that we have cleared the masking we can kick cpus.
+ */
+ kvm_s390_pv_sclp_kick(vcpu);
return 0;
}
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 8f24bcd1a6d36..1ee9ab2505042 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -367,6 +367,37 @@ static unsigned long deliverable_irqs(struct kvm_vcpu *vcpu)
return active_mask;
}
+void distribute_float_irqs(struct kvm *kvm)
+{
+ struct kvm_vcpu *dst_vcpu;
+ int sigcpu, online_vcpus;
+
+ if (!READ_ONCE(kvm->arch.float_int.pending_irqs))
+ return;
+
+ online_vcpus = atomic_read(&kvm->online_vcpus);
+
+ /*
+ * Not too worried about synchronization for idle_mask. We
+ * might burn too many cycles but apart from that waking a
+ * vcpu is not harmful.
+ */
+ sigcpu = find_first_bit(kvm->arch.idle_mask, online_vcpus);
+ /* Well nobody's sleeping so someone will likely take the IRQ soon */
+ if (sigcpu == online_vcpus)
+ return;
+
+ do {
+ dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
+ if (deliverable_irqs(dst_vcpu)) {
+ kvm->stat.inject_redist++;
+ kvm_s390_vcpu_wakeup(dst_vcpu);
+ break;
+ }
+ sigcpu = find_next_bit(kvm->arch.idle_mask, online_vcpus, ++sigcpu);
+ } while (sigcpu < online_vcpus);
+}
+
static void __set_cpu_idle(struct kvm_vcpu *vcpu)
{
kvm_s390_set_cpuflags(vcpu, CPUSTAT_WAIT);
@@ -1915,49 +1946,129 @@ static int __inject_io(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
return 0;
}
+static u64 inti_to_irq_pend_mask(u64 type, int isc)
+{
+ switch (type) {
+ case KVM_S390_MCHK:
+ /* Only repressible machine checks are floating */
+ return BIT(IRQ_PEND_MCHK_REP);
+ case KVM_S390_INT_VIRTIO:
+ return BIT(IRQ_PEND_VIRTIO);
+ case KVM_S390_INT_SERVICE:
+ return BIT(IRQ_PEND_EXT_SERVICE) |
+ BIT(IRQ_PEND_EXT_SERVICE_EV);
+ case KVM_S390_INT_PFAULT_DONE:
+ return BIT(IRQ_PEND_PFAULT_DONE);
+ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
+ return isc_to_irq_type(isc);
+ default:
+ return 0;
+ }
+}
+
/*
- * Find a destination VCPU for a floating irq and kick it.
+ * Setup intervention masks to catch running vcpus that hopefully open
+ * their masks soonish and kick sleeping vcpus to motivate them to
+ * take IRQs.
*/
-static void __floating_irq_kick(struct kvm *kvm, u64 type)
+static void vcpu_intervention_kick(struct kvm_vcpu *vcpu, u64 type)
+{
+ /* make the VCPU drop out of the SIE, or wake it up if sleeping */
+ switch (type) {
+ case KVM_S390_MCHK:
+ kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOP_INT);
+ break;
+ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
+ if (!(type & KVM_S390_INT_IO_AI_MASK &&
+ vcpu->kvm->arch.gisa_int.origin) ||
+ kvm_s390_pv_cpu_get_handle(vcpu))
+ kvm_s390_set_cpuflags(vcpu, CPUSTAT_IO_INT);
+ break;
+ default:
+ kvm_s390_set_cpuflags(vcpu, CPUSTAT_EXT_INT);
+ break;
+ }
+ kvm_s390_vcpu_wakeup(vcpu);
+}
+
+static void kick_cpu_irq(struct kvm *kvm, u64 type, u64 parm)
{
struct kvm_vcpu *dst_vcpu;
int sigcpu, online_vcpus, nr_tries = 0;
+ u64 irq_pend_mask;
+ unsigned long i;
online_vcpus = atomic_read(&kvm->online_vcpus);
if (!online_vcpus)
return;
+ irq_pend_mask = inti_to_irq_pend_mask(type, parm);
for (sigcpu = kvm->arch.float_int.last_sleep_cpu; ; sigcpu++) {
sigcpu %= online_vcpus;
dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
- if (!is_vcpu_stopped(dst_vcpu))
+ if (!is_vcpu_stopped(dst_vcpu) &&
+ deliverable_irqs(dst_vcpu) & irq_pend_mask)
break;
/* avoid endless loops if all vcpus are stopped */
- if (nr_tries++ >= online_vcpus)
- return;
+ if (nr_tries++ >= online_vcpus * 2) {
+ dst_vcpu = NULL;
+ break;
+ }
}
- /* make the VCPU drop out of the SIE, or wake it up if sleeping */
- switch (type) {
- case KVM_S390_MCHK:
- kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_STOP_INT);
- break;
- case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
- if (!(type & KVM_S390_INT_IO_AI_MASK &&
- kvm->arch.gisa_int.origin) ||
- kvm_s390_pv_cpu_get_handle(dst_vcpu))
- kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_IO_INT);
- break;
- default:
- kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_EXT_INT);
- break;
+ /* Nobody was enabled, time to wake all of them */
+ if (!dst_vcpu) {
+ kvm_for_each_vcpu(i, dst_vcpu, kvm)
+ vcpu_intervention_kick(dst_vcpu, type);
+ return;
}
- kvm_s390_vcpu_wakeup(dst_vcpu);
+
+ vcpu_intervention_kick(dst_vcpu, type);
+}
+
+void kvm_s390_pv_sclp_kick(struct kvm_vcpu *vcpu)
+{
+ /*
+ * The cpu that called sclp likely will also take the IRQ, no
+ * need to kick anyone.
+ */
+ if (likely(deliverable_irqs(vcpu) & IRQ_PEND_EXT_SERVICE))
+ return;
+
+ /*
+ * For the other cases we might have sleeping cpus with open
+ * masks. Time to find and kick them.
+ */
+ kick_cpu_irq(vcpu->kvm, KVM_S390_INT_SERVICE, -1);
+}
+
+/*
+ * Find a destination VCPU for a floating irq and kick it.
+ */
+static void __floating_irq_kick(struct kvm *kvm, u64 type, u64 parm)
+{
+ int prot;
+
+ mutex_lock(&kvm->lock);
+ prot = kvm_s390_pv_is_protected(kvm);
+ mutex_unlock(&kvm->lock);
+ /*
+ * No need to kick on non-ev service IRQs for PV VMs, we're
+ * not allowed to inject anyway. We need to wait for the sclp
+ * instruction notification AFTER re-entry of the vcpu that
+ * handled the instruction intercept.
+ */
+ if (prot && type == KVM_S390_INT_SERVICE &&
+ !(parm & SCCB_EVENT_PENDING))
+ return;
+
+ kick_cpu_irq(kvm, type, parm);
}
static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
{
u64 type = READ_ONCE(inti->type);
+ u64 parm;
int rc;
switch (type) {
@@ -1968,12 +2079,15 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
rc = __inject_virtio(kvm, inti);
break;
case KVM_S390_INT_SERVICE:
+ parm = inti->ext.ext_params & SCCB_EVENT_PENDING;
rc = __inject_service(kvm, inti);
break;
case KVM_S390_INT_PFAULT_DONE:
rc = __inject_pfault_done(kvm, inti);
break;
case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
+ /* Grab isc here since __inject_io() might free inti */
+ parm = isc_to_irq_type(int_word_to_isc(inti->io.io_int_word));
rc = __inject_io(kvm, inti);
break;
default:
@@ -1982,7 +2096,7 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
if (rc)
return rc;
- __floating_irq_kick(kvm, type);
+ __floating_irq_kick(kvm, type, parm);
return 0;
}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 518a69c55e85c..d6d46688d9808 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -86,6 +86,7 @@ const struct kvm_stats_desc kvm_vm_stats_desc[] = {
STATS_DESC_COUNTER(VM, gmap_shadow_r3_entry),
STATS_DESC_COUNTER(VM, gmap_shadow_sg_entry),
STATS_DESC_COUNTER(VM, gmap_shadow_pg_entry),
+ STATS_DESC_COUNTER(VM, inject_redist),
};
const struct kvm_stats_header kvm_vm_stats_header = {
@@ -4572,6 +4573,8 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
rc = kvm_s390_deliver_pending_interrupts(vcpu);
if (rc || guestdbg_exit_pending(vcpu))
return rc;
+
+ distribute_float_irqs(vcpu->kvm);
}
rc = kvm_s390_handle_requests(vcpu);
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 6d2842fb71a33..7115a8f5b1882 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -375,6 +375,8 @@ enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu);
void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu);
void kvm_s390_clear_float_irqs(struct kvm *kvm);
+void kvm_s390_pv_sclp_kick(struct kvm_vcpu *vcpu);
+void distribute_float_irqs(struct kvm *kvm);
int __must_check kvm_s390_inject_vm(struct kvm *kvm,
struct kvm_s390_interrupt *s390int,
struct kvm_s390_interrupt_info *inti);
|
| 3/2 | 2026/08/19 20:01 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5889 output: 35 thoughts: 289 Thoughts: **KVM s390 Patch Assessment** Okay, so I've got this patch – seems like a pretty significant one. It's touching some critical KVM code specifically for the s390 architecture, specifically modifying `intercept.c`, `interrupt.c`, `kvm-s390.c`, `kvm-s390.h`, and `kvm_host.h` within the `arch/s390/kvm` directory. That points to some serious changes under the hood. Specifically, it's adding these new functions, `distribute_float_irqs` and `kvm_s390_pv_sclp_kick`, so the core logic of how we handle floating IRQs in KVM for s390 is changing, which means I need to pay *very* close attention to this. The crucial question now is, can I test this effectively? Is this reachable by existing testing infrastructure? Ah, yes, if we have s390x QEMU, KVM on s390 is testable. Good, good. And syzkaller... does syzkaller do s390x? Yes, it does, so syzkaller *can* fuzz KVM on s390x. Perfect. That's a huge win in terms of testability and finding any potential regressions or subtle issues. Now, let's just make sure there aren't any weird config dependencies that syzkaller needs to enable KVM on s390x. I'll need to double-check that the standard KVM config is sufficient, `CONFIG_KVM` should be good enough. Time to check `arch/s390/kvm/Kconfig` to be sure. |
| 4/2 | 2026/08/19 20:02 | tool | grepper |
0mArgs:{
"Expression": "config KVM",
"PathPrefix": "arch/s390/kvm/Kconfig"
}Results: {
"Output": "arch/s390/kvm/Kconfig=17=if VIRTUALIZATION\narch/s390/kvm/Kconfig-18-\narch/s390/kvm/Kconfig:19:config KVM\narch/s390/kvm/Kconfig-20-\tdef_tristate y\n--\narch/s390/kvm/Kconfig-46-\narch/s390/kvm/Kconfig:47:config KVM_S390_UCONTROL\narch/s390/kvm/Kconfig-48-\tbool \"Userspace controlled virtual machines\"\n"
} |
| 5/2 | 2026/08/19 20:02 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 6763 output: 37 thoughts: 38 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Investigating KVM Dependencies for s390 Architecture Interrupt Handling** Right, let's see, the system is indicating that `CONFIG_KVM` is a hard requirement for something, which isn't entirely surprising given the context. My initial instinct is to go digging through the architecture-specific KVM code to figure out what functionality is leaning on it, specifically interrupt management. The s390 architecture often has some unique approaches here. I'll start with `arch/s390/kvm/interrupt.c`. That file is a likely candidate; interrupt handling and distribution are often tightly coupled with virtualization. The presence of `distribute_float_irqs` is a particular point of interest because of its implication for floating point. Let's see how that function and others are utilizing KVM functionality, and where that dependency is declared or implied. I need to understand the connection between `CONFIG_KVM` and how we're distributing those interrupts. The goal is to identify if there's any area that's not needed, or could be replaced by a different approach. |
| 6/2 | 2026/08/19 20:02 | tool | grepper |
0mArgs:{
"Expression": "distribute_float_irqs",
"PathPrefix": "arch/s390/kvm/"
}Results: {
"Output": "arch/s390/kvm/interrupt.c=318=static unsigned long deliverable_irqs(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/interrupt.c-369-\narch/s390/kvm/interrupt.c:370:void distribute_float_irqs(struct kvm *kvm)\narch/s390/kvm/interrupt.c-371-{\n--\narch/s390/kvm/kvm-s390.c=4558=static int vcpu_pre_run(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/kvm-s390.c-4576-\narch/s390/kvm/kvm-s390.c:4577:\t\tdistribute_float_irqs(vcpu-\u003ekvm);\narch/s390/kvm/kvm-s390.c-4578-\t}\n--\narch/s390/kvm/kvm-s390.h=378=void kvm_s390_pv_sclp_kick(struct kvm_vcpu *vcpu);\narch/s390/kvm/kvm-s390.h:379:void distribute_float_irqs(struct kvm *kvm);\narch/s390/kvm/kvm-s390.h-380-int __must_check kvm_s390_inject_vm(struct kvm *kvm,\n"
} |
| 7/2 | 2026/08/19 20:02 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7501 output: 41 thoughts: 407 Thoughts: **My Assessment of the Patch** Okay, let's break this down. This patch introduces `distribute_float_irqs`, which is interesting because it's called within `vcpu_pre_run` in `arch/s390/kvm/kvm-s390.c`. Simultaneously, we have `kvm_s390_pv_sclp_kick` being introduced, triggered from `handle_pv_sclp` in `arch/s390/kvm/intercept.c`. I need to remember that `handle_pv_sclp` is specifically related to Protected Virtualization (PV). My immediate thought is to check QEMU's s390x PV support. Ah, yes, it does support s390x Secure Execution, which includes PV. But even if PV isn't in play, `distribute_float_irqs` still gets invoked via `vcpu_pre_run`. I also see changes around `__floating_irq_kick`, so there's definitely functional modification here in the KVM s390x implementation. It means I'm comfortable saying this is WorthFuzzing=true. Now, let's get into the key symbols. `distribute_float_irqs`, `kvm_s390_pv_sclp_kick` are obvious ones. Then there's this path: `vcpu_intervention_kick` -> `kick_cpu_irq` -> `__floating_irq_kick` -> `__inject_vm` -> `kvm_s390_inject_vm`. Wait, `kvm_s390_inject_vm` is the one I want to really look into. Both `distribute_float_irqs` and `kvm_s390_pv_sclp_kick` are exported, which gives us some good entry points. Next steps, I need to verify `kvm_s390_inject_vm` and `handle_pv_sclp` and how they're used. |
| 8/2 | 2026/08/19 20:02 | tool | grepper |
0mArgs:{
"Expression": "kvm_s390_inject_vm",
"PathPrefix": "arch/s390/kvm/"
}Results: {
"Output": "arch/s390/kvm/interrupt.c=2068=static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)\n--\narch/s390/kvm/interrupt.c-2102-\narch/s390/kvm/interrupt.c:2103:int kvm_s390_inject_vm(struct kvm *kvm,\narch/s390/kvm/interrupt.c-2104-\t\t struct kvm_s390_interrupt *s390int, struct kvm_s390_interrupt_info *inti)\n--\narch/s390/kvm/interrupt.c-2137-\t}\narch/s390/kvm/interrupt.c:2138:\ttrace_kvm_s390_inject_vm(s390int-\u003etype, s390int-\u003eparm, s390int-\u003eparm64,\narch/s390/kvm/interrupt.c-2139-\t\t\t\t 2);\n--\narch/s390/kvm/interrupt.c=2877=static int kvm_s390_inject_airq(struct kvm *kvm,\n--\narch/s390/kvm/interrupt.c-2895-\tif (!test_kvm_facility(kvm, 72) || !adapter-\u003esuppressible) {\narch/s390/kvm/interrupt.c:2896:\t\tret = kvm_s390_inject_vm(kvm, \u0026s390int, inti);\narch/s390/kvm/interrupt.c-2897-\t\tif (ret)\n--\narch/s390/kvm/interrupt.c-2909-\narch/s390/kvm/interrupt.c:2910:\tret = kvm_s390_inject_vm(kvm, \u0026s390int, inti);\narch/s390/kvm/interrupt.c-2911-\n--\narch/s390/kvm/interrupt.c=3865=int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,\n--\narch/s390/kvm/interrupt.c-3907-\tif (!test_kvm_facility(kvm, 72) || !adapter-\u003esuppressible) {\narch/s390/kvm/interrupt.c:3908:\t\tret = kvm_s390_inject_vm(kvm, \u0026s390int, inti);\narch/s390/kvm/interrupt.c-3909-\t\tif (ret == 0) {\n--\narch/s390/kvm/interrupt.c-3927-\narch/s390/kvm/interrupt.c:3928:\tret = kvm_s390_inject_vm(kvm, \u0026s390int, inti);\narch/s390/kvm/interrupt.c-3929-\tif (!ret \u0026\u0026 (fi-\u003esimm \u0026 AIS_MODE_MASK(adapter-\u003eisc))) {\n--\narch/s390/kvm/kvm-s390.c=2927=int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)\n--\narch/s390/kvm/kvm-s390.c-2947-\t\t\treturn -ENOMEM;\narch/s390/kvm/kvm-s390.c:2948:\t\tr = kvm_s390_inject_vm(kvm, \u0026s390int, inti);\narch/s390/kvm/kvm-s390.c-2949-\t\tif (r)\n--\narch/s390/kvm/kvm-s390.c=4475=static void __kvm_inject_pfault_token(struct kvm_vcpu *vcpu, bool start_token,\n--\narch/s390/kvm/kvm-s390.c-4493-\t\tinti.parm64 = token;\narch/s390/kvm/kvm-s390.c:4494:\t\tret = kvm_s390_inject_vm(vcpu-\u003ekvm, \u0026inti, inti_mem);\narch/s390/kvm/kvm-s390.c-4495-\t\tif (ret)\n--\narch/s390/kvm/kvm-s390.h=379=void distribute_float_irqs(struct kvm *kvm);\narch/s390/kvm/kvm-s390.h:380:int __must_check kvm_s390_inject_vm(struct kvm *kvm,\narch/s390/kvm/kvm-s390.h-381-\t\t\t\t struct kvm_s390_interrupt *s390int,\n--\narch/s390/kvm/trace-s390.h=81=TRACE_EVENT(kvm_s390_vcpu_start_stop,\n--\narch/s390/kvm/trace-s390.h-124-\narch/s390/kvm/trace-s390.h:125:TRACE_EVENT(kvm_s390_inject_vm,\narch/s390/kvm/trace-s390.h-126-\t TP_PROTO(__u64 type, __u32 parm, __u64 parm64, int who),\n"
} |
| 9/2 | 2026/08/19 20:02 | llm | patch-evaluator |
2mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9888 output: 37 thoughts: 33 Thoughts: Okay, here's my interpretation of those thoughts, presented as a first-person expert summary: **Considering Injection Points in the s390 KVM Kernel Module** Right, let's see. `kvm_s390_inject_vm`... that seems like a solid entry point to focus on, a good symbol to dive into. It's often where we see critical events being injected into the virtual machine. Now, I'm trying to think about other potentially important areas, and the name that pops into my head is `handle_pv_sclp`. I'm starting to think about whether there's some useful overlap. Let's dig deeper and see if any interactions are of note. |
| 10/2 | 2026/08/19 20:05 | tool | grepper |
0mArgs:{
"Expression": "handle_pv_sclp",
"PathPrefix": "arch/s390/kvm/"
}Results: {
"Output": "arch/s390/kvm/intercept.c=508=static int handle_pv_spx(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/intercept.c-516-\narch/s390/kvm/intercept.c:517:static int handle_pv_sclp(struct kvm_vcpu *vcpu)\narch/s390/kvm/intercept.c-518-{\n--\narch/s390/kvm/intercept.c=582=static int handle_pv_notification(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/intercept.c-588-\tif (vcpu-\u003earch.sie_block-\u003eipa == 0xb220)\narch/s390/kvm/intercept.c:589:\t\treturn handle_pv_sclp(vcpu);\narch/s390/kvm/intercept.c-590-\tif (vcpu-\u003earch.sie_block-\u003eipa == 0xb9a4)\n"
} |
| 11/2 | 2026/08/19 20:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10394 output: 35 thoughts: 36 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Investigating Potential Static Method Usage** Alright, so `handle_pv_sclp` is static, that's already established. But wait a minute... I need to check something related to `handle_pv_notification`. It seems odd that one handler is static while the other isn't, especially when they likely handle similar parallel processing scenarios, so I need to understand that better. A quick look at `handle_pv_notification` is in order; I want to grasp its context and determine whether that's the expected usage, or if there's an opportunity for improvement or refactoring. Let's see what's happening there... |
| 12/2 | 2026/08/19 20:05 | tool | grepper |
0mArgs:{
"Expression": "handle_pv_notification",
"PathPrefix": "arch/s390/kvm/"
}Results: {
"Output": "arch/s390/kvm/intercept.c=551=static int handle_pv_uvc(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/intercept.c-581-\narch/s390/kvm/intercept.c:582:static int handle_pv_notification(struct kvm_vcpu *vcpu)\narch/s390/kvm/intercept.c-583-{\n--\narch/s390/kvm/intercept.c=622=int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/intercept.c-670-\tcase ICPT_PV_NOTIFY:\narch/s390/kvm/intercept.c:671:\t\trc = handle_pv_notification(vcpu);\narch/s390/kvm/intercept.c-672-\t\tbreak;\n"
} |
| 13/2 | 2026/08/19 20:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10875 output: 35 thoughts: 189 Thoughts: **Focusing on Key KVM Symbols for Investigation** Okay, so I'm thinking about where to start digging into this KVM code. I know `kvm_handle_sie_intercept` is exported, meaning it's visible outside its own file, so theoretically, it's a candidate. But, knowing how KVM works, that function is likely a *very* hot path. I'd rather look somewhere less heavily trafficked to start. Right, let's see. `kvm_s390_pv_sclp_kick` is also exported. That sounds promising. Then there's `distribute_float_irqs` and `kvm_s390_inject_vm` – they're non-static and exported, so they're all solid starting points. These seem to be good focus symbols to begin with. They're accessible and potentially offer a clearer view of the larger architecture than something like `kvm_handle_sie_intercept`. Now, before I get too deep, I should double-check the configuration requirements. `CONFIG_KVM` is, of course, the big one. I should probably revisit `arch/s390/kvm/Kconfig` to be sure there aren’t any PV-specific configurations I'm missing. |
| 14/2 | 2026/08/19 20:05 | tool | grepper |
0mArgs:{
"Expression": "config KVM",
"PathPrefix": "arch/s390/kvm/Kconfig"
}Results: {
"Output": "arch/s390/kvm/Kconfig=17=if VIRTUALIZATION\narch/s390/kvm/Kconfig-18-\narch/s390/kvm/Kconfig:19:config KVM\narch/s390/kvm/Kconfig-20-\tdef_tristate y\n--\narch/s390/kvm/Kconfig-46-\narch/s390/kvm/Kconfig:47:config KVM_S390_UCONTROL\narch/s390/kvm/Kconfig-48-\tbool \"Userspace controlled virtual machines\"\n"
} |
| 15/2 | 2026/08/19 20:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11549 output: 39 thoughts: 20 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Examining the s390 KVM Configuration** Okay, time to dive into the `arch/s390/kvm/Kconfig` file. I need a comprehensive overview of the configuration options available for KVM on the System z architecture. I'm looking for the dependencies, default settings, and potential implications of each option. Specifically, I'm thinking about: * **Understanding the Scope**: What KVM features are controlled here? Is this just the core KVM support, or are there more specific extensions or optimizations defined? * **Dependency Analysis**: What other Kconfig options does this file rely on? I need to quickly identify the prerequisites for enabling certain KVM functionality. Are there any potential conflicts with other kernel components? * **Default Settings**: What are the default values for the KVM features? Are the defaults reasonable and safe, or do they represent a performance vs. security trade-off that requires careful consideration in a specific deployment? * **Potential Areas for Optimization**: Are there any obvious areas within the configuration that could lead to performance gains or reduced resource consumption if tuned correctly? I'm particularly interested in any s390-specific settings. * **Possible Interactions**: How does the Kconfig file interact with the rest of the s390 architecture code? Are there any potential limitations that are not immediately obvious from just looking at this file? This scan will hopefully allow me to develop a good mental model of KVM configuration on System z. Let's see what we can find. |
| 16/2 | 2026/08/19 20:05 | tool | read-file |
0mArgs:{
"File": "arch/s390/kvm/Kconfig",
"FirstLine": 1,
"LineCount": 100
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0\n 2:\t#\n 3:\t# KVM configuration\n 4:\t#\n 5:\tsource \"virt/kvm/Kconfig\"\n 6:\t\n 7:\tmenuconfig VIRTUALIZATION\n 8:\t\tdef_bool y\n 9:\t\tprompt \"KVM\"\n 10:\t\thelp\n 11:\t\t Say Y here to get to see options for using your Linux host to run other\n 12:\t\t operating systems inside virtual machines (guests).\n 13:\t\t This option alone does not add any kernel code.\n 14:\t\n 15:\t\t If you say N, all options in this submenu will be skipped and disabled.\n 16:\t\n 17:\tif VIRTUALIZATION\n 18:\t\n 19:\tconfig KVM\n 20:\t\tdef_tristate y\n 21:\t\tprompt \"Kernel-based Virtual Machine (KVM) support\"\n 22:\t\tselect HAVE_KVM_CPU_RELAX_INTERCEPT\n 23:\t\tselect KVM_ASYNC_PF\n 24:\t\tselect KVM_ASYNC_PF_SYNC\n 25:\t\tselect KVM_COMMON\n 26:\t\tselect HAVE_KVM_IRQCHIP\n 27:\t\tselect HAVE_KVM_IRQ_ROUTING\n 28:\t\tselect HAVE_KVM_INVALID_WAKEUPS\n 29:\t\tselect HAVE_KVM_NO_POLL\n 30:\t\tselect KVM_VFIO\n 31:\t\tselect VIRT_XFER_TO_GUEST_WORK\n 32:\t\tselect KVM_MMU_LOCKLESS_AGING\n 33:\t\tselect KVM_GENERIC_PRE_FAULT_MEMORY\n 34:\t\thelp\n 35:\t\t Support hosting paravirtualized guest machines using the SIE\n 36:\t\t virtualization capability on the mainframe. This should work\n 37:\t\t on any 64bit machine.\n 38:\t\n 39:\t\t This module provides access to the hardware capabilities through\n 40:\t\t a character device node named /dev/kvm.\n 41:\t\n 42:\t\t To compile this as a module, choose M here: the module\n 43:\t\t will be called kvm.\n 44:\t\n 45:\t\t If unsure, say N.\n 46:\t\n 47:\tconfig KVM_S390_UCONTROL\n 48:\t\tbool \"Userspace controlled virtual machines\"\n 49:\t\tdepends on KVM\n 50:\t\thelp\n 51:\t\t Allow CAP_SYS_ADMIN users to create KVM virtual machines that are\n 52:\t\t controlled by userspace.\n 53:\t\n 54:\t\t If unsure, say N.\n 55:\t\n 56:\tendif # VIRTUALIZATION\n"
} |
| 17/2 | 2026/08/19 20:05 | llm | patch-evaluator |
3mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12678 output: 30 thoughts: 45 Thoughts: Okay, here's my take on those thoughts, framed as my own reasoning, and tailored for a fellow expert: **KVM Configuration Deep Dive** Alright, KVM is the central point here, the core configuration. That's the foundation we're working with. Now, the real question is, are there any other supporting configurations we need to account for, particularly for Paravirtualization (PV)? I'm thinking, is there a specific, dedicated option in the kernel config related to Paravirtualization on S390, like a `CONFIG_KVM_S390_PV` flag? We need to make absolutely sure we haven't missed any dependencies or relevant features that might be critical to our desired PV setup. The devil is often in the details, so let's dig a little deeper. |
| 18/2 | 2026/08/19 20:08 | tool | grepper |
0mError:no matches Args: {
"Expression": "config .*PV",
"PathPrefix": "arch/s390/"
}Results: {
"error": "no matches"
} |
| 19/2 | 2026/08/19 20:08 | llm | patch-evaluator |
3mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12942 output: 31 thoughts: 18 Thoughts: Here's a summary of my thought process, as requested: **Checking for Paravirtualization Configuration** Okay, so I need to figure out the paravirtualization (PV) configuration settings within the s390 architecture. My immediate instinct is to check the `arch/s390/Kconfig` file. That's the typical place where architecture-specific configuration options are defined. It's the central place to discover what kernel features are exposed to the user for this architecture. By examining this Kconfig file, I expect to find the relevant configuration options that determine whether PV support is enabled, what kinds of PV interfaces are supported (e.g., virtio, paravirt-ops), and any dependencies or default values. It's the starting point for understanding how the kernel handles virtualization on s390. I'll need to look for keywords like "paravirtualization," "pv," "virtio," or specific Kconfig symbols related to those concepts. This will give me a clear picture of how PV is integrated into the s390 kernel build. |
| 20/2 | 2026/08/19 20:12 | tool | grepper |
0mError:no matches Args: {
"Expression": "config .*SECURE",
"PathPrefix": "arch/s390/"
}Results: {
"error": "no matches"
} |
| 21/2 | 2026/08/19 20:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13234 output: 31 thoughts: 13 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Initial Search Strategy** Okay, so I'm looking for specific indicators here. My immediate thought is to zero in on key terms related to whatever this "PROTECTED" or "PV" refers to. It's a quick, efficient way to identify the core concept and its potential variations within the context. This initial approach focuses on direct matches to avoid missing any direct references. This helps establish an initial range of relevant data. |
| 22/2 | 2026/08/19 20:12 | tool | grepper |
0mError:no matches Args: {
"Expression": "config .*PROTECTED",
"PathPrefix": "arch/s390/"
}Results: {
"error": "no matches"
} |
| 23/2 | 2026/08/19 20:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13399 output: 31 thoughts: 25 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Investigating Virtualization Configuration in the S390 Architecture** Alright, let's dive into this. My initial instinct is to zero in on the configuration options related to virtualization within the S390 architecture's kernel configuration. Specifically, I need to start by looking within the `arch/s390/Kconfig` file. I'm going to leverage a search, something like `config .*`, which should catch all configuration options, and I'll focus that search to be relevant to virtualization, since this is my primary interest in the subject. This should be a quick way to identify the relevant settings. My gut feeling is that there could be some options related to KVM, s390x-specific paravirtualization, or potentially even some more generalized virtualization support that's lurking in there. Gotta map out what's available before I can make a judgement. |
| 24/2 | 2026/08/19 20:12 | tool | grepper |
0mArgs:{
"Expression": "config .*",
"PathPrefix": "arch/s390/Kconfig"
}Results: {
"Output": "arch/s390/Kconfig-1-# SPDX-License-Identifier: GPL-2.0\narch/s390/Kconfig:2:config MMU\narch/s390/Kconfig-3-\tdef_bool y\narch/s390/Kconfig-4-\narch/s390/Kconfig:5:config CPU_BIG_ENDIAN\narch/s390/Kconfig-6-\tdef_bool y\narch/s390/Kconfig-7-\narch/s390/Kconfig:8:config LOCKDEP_SUPPORT\narch/s390/Kconfig-9-\tdef_bool y\narch/s390/Kconfig-10-\narch/s390/Kconfig:11:config STACKTRACE_SUPPORT\narch/s390/Kconfig-12-\tdef_bool y\narch/s390/Kconfig-13-\narch/s390/Kconfig:14:config ARCH_HAS_ILOG2_U32\narch/s390/Kconfig-15-\tdef_bool n\narch/s390/Kconfig-16-\narch/s390/Kconfig:17:config ARCH_HAS_ILOG2_U64\narch/s390/Kconfig-18-\tdef_bool n\narch/s390/Kconfig-19-\narch/s390/Kconfig:20:config ARCH_PROC_KCORE_TEXT\narch/s390/Kconfig-21-\tdef_bool y\narch/s390/Kconfig-22-\narch/s390/Kconfig:23:config GENERIC_HWEIGHT\narch/s390/Kconfig-24-\tdef_bool !HAVE_MARCH_Z196_FEATURES\narch/s390/Kconfig-25-\narch/s390/Kconfig:26:config GENERIC_BUG\narch/s390/Kconfig-27-\tdef_bool y if BUG\narch/s390/Kconfig-28-\narch/s390/Kconfig:29:config GENERIC_BUG_RELATIVE_POINTERS\narch/s390/Kconfig-30-\tdef_bool y\narch/s390/Kconfig-31-\narch/s390/Kconfig:32:config AUDIT_ARCH\narch/s390/Kconfig-33-\tdef_bool y\narch/s390/Kconfig-34-\narch/s390/Kconfig:35:config NO_IOPORT_MAP\narch/s390/Kconfig-36-\tdef_bool y\narch/s390/Kconfig-37-\narch/s390/Kconfig:38:config ARCH_SUPPORTS_UPROBES\narch/s390/Kconfig-39-\tdef_bool y\narch/s390/Kconfig-40-\narch/s390/Kconfig:41:config KASAN_SHADOW_OFFSET\narch/s390/Kconfig-42-\thex\n--\narch/s390/Kconfig-45-\narch/s390/Kconfig:46:config CC_HAS_BUILTIN_FFS\narch/s390/Kconfig-47-\tdef_bool !(CC_IS_GCC \u0026\u0026 GCC_VERSION \u003c 160000)\n--\narch/s390/Kconfig-52-\narch/s390/Kconfig:53:config CC_ASM_FLAG_OUTPUT_BROKEN\narch/s390/Kconfig-54-\tdef_bool CC_IS_GCC \u0026\u0026 GCC_VERSION \u003c 140200\n--\narch/s390/Kconfig-59-\narch/s390/Kconfig:60:config CC_HAS_ASM_AOR_FORMAT_FLAGS\narch/s390/Kconfig-61-\tdef_bool !(CC_IS_CLANG \u0026\u0026 CLANG_VERSION \u003c 190100)\n--\narch/s390/Kconfig-65-\narch/s390/Kconfig:66:config CC_HAS_ASM_IMMEDIATE_STRINGS\narch/s390/Kconfig-67-\tdef_bool !(CC_IS_GCC \u0026\u0026 GCC_VERSION \u003c 90000)\n--\narch/s390/Kconfig-71-\narch/s390/Kconfig:72:config CC_HAS_STACKPROTECTOR_GLOBAL\narch/s390/Kconfig-73-\tdef_bool $(cc-option, -mstack-protector-guard=global -mstack-protector-guard-record)\narch/s390/Kconfig-74-\narch/s390/Kconfig:75:config S390\narch/s390/Kconfig-76-\tdef_bool y\n--\narch/s390/Kconfig-289-\narch/s390/Kconfig:290:config SCHED_OMIT_FRAME_POINTER\narch/s390/Kconfig-291-\tdef_bool y\narch/s390/Kconfig-292-\narch/s390/Kconfig:293:config PGTABLE_LEVELS\narch/s390/Kconfig-294-\tint\n--\narch/s390/Kconfig=297=source \"kernel/livepatch/Kconfig\"\narch/s390/Kconfig-298-\narch/s390/Kconfig:299:config ARCH_CC_CAN_LINK\narch/s390/Kconfig-300-\tbool\n--\narch/s390/Kconfig-302-\narch/s390/Kconfig:303:config ARCH_USERFLAGS\narch/s390/Kconfig-304-\tstring\n--\narch/s390/Kconfig-306-\narch/s390/Kconfig:307:config ARCH_SUPPORTS_KEXEC\narch/s390/Kconfig-308-\tdef_bool y\narch/s390/Kconfig-309-\narch/s390/Kconfig:310:config ARCH_SUPPORTS_KEXEC_FILE\narch/s390/Kconfig-311-\tdef_bool y\narch/s390/Kconfig-312-\narch/s390/Kconfig:313:config ARCH_SUPPORTS_KEXEC_SIG\narch/s390/Kconfig-314-\tdef_bool y\narch/s390/Kconfig-315-\narch/s390/Kconfig:316:config ARCH_SUPPORTS_KEXEC_PURGATORY\narch/s390/Kconfig-317-\tdef_bool y\narch/s390/Kconfig-318-\narch/s390/Kconfig:319:config ARCH_SUPPORTS_CRASH_DUMP\narch/s390/Kconfig-320-\tdef_bool y\n--\narch/s390/Kconfig-325-\narch/s390/Kconfig:326:config ARCH_DEFAULT_CRASH_DUMP\narch/s390/Kconfig-327-\tdef_bool y\n--\narch/s390/Kconfig=329=menu \"Processor type and features\"\narch/s390/Kconfig-330-\narch/s390/Kconfig:331:config HAVE_MARCH_Z10_FEATURES\narch/s390/Kconfig-332-\tdef_bool n\narch/s390/Kconfig-333-\narch/s390/Kconfig:334:config HAVE_MARCH_Z196_FEATURES\narch/s390/Kconfig-335-\tdef_bool n\n--\narch/s390/Kconfig-337-\narch/s390/Kconfig:338:config HAVE_MARCH_ZEC12_FEATURES\narch/s390/Kconfig-339-\tdef_bool n\n--\narch/s390/Kconfig-341-\narch/s390/Kconfig:342:config HAVE_MARCH_Z13_FEATURES\narch/s390/Kconfig-343-\tdef_bool n\n--\narch/s390/Kconfig-345-\narch/s390/Kconfig:346:config HAVE_MARCH_Z14_FEATURES\narch/s390/Kconfig-347-\tdef_bool n\n--\narch/s390/Kconfig-349-\narch/s390/Kconfig:350:config HAVE_MARCH_Z15_FEATURES\narch/s390/Kconfig-351-\tdef_bool n\n--\narch/s390/Kconfig-353-\narch/s390/Kconfig:354:config HAVE_MARCH_Z16_FEATURES\narch/s390/Kconfig-355-\tdef_bool n\n--\narch/s390/Kconfig-357-\narch/s390/Kconfig:358:config HAVE_MARCH_Z17_FEATURES\narch/s390/Kconfig-359-\tdef_bool n\n--\narch/s390/Kconfig=362=choice\n--\narch/s390/Kconfig-365-\narch/s390/Kconfig:366:config MARCH_Z10\narch/s390/Kconfig-367-\tbool \"IBM System z10\"\n--\narch/s390/Kconfig-373-\narch/s390/Kconfig:374:config MARCH_Z196\narch/s390/Kconfig-375-\tbool \"IBM zEnterprise 114 and 196\"\n--\narch/s390/Kconfig-382-\narch/s390/Kconfig:383:config MARCH_ZEC12\narch/s390/Kconfig-384-\tbool \"IBM zBC12 and zEC12\"\n--\narch/s390/Kconfig-391-\narch/s390/Kconfig:392:config MARCH_Z13\narch/s390/Kconfig-393-\tbool \"IBM z13s and z13\"\n--\narch/s390/Kconfig-400-\narch/s390/Kconfig:401:config MARCH_Z14\narch/s390/Kconfig-402-\tbool \"IBM z14 ZR1 and z14\"\n--\narch/s390/Kconfig-409-\narch/s390/Kconfig:410:config MARCH_Z15\narch/s390/Kconfig-411-\tbool \"IBM z15\"\n--\narch/s390/Kconfig-418-\narch/s390/Kconfig:419:config MARCH_Z16\narch/s390/Kconfig-420-\tbool \"IBM z16\"\n--\narch/s390/Kconfig-426-\narch/s390/Kconfig:427:config MARCH_Z17\narch/s390/Kconfig-428-\tbool \"IBM z17\"\n--\narch/s390/Kconfig=435=endchoice\narch/s390/Kconfig-436-\narch/s390/Kconfig:437:config MARCH_Z10_TUNE\narch/s390/Kconfig-438-\tdef_bool TUNE_Z10 || MARCH_Z10 \u0026\u0026 TUNE_DEFAULT\narch/s390/Kconfig-439-\narch/s390/Kconfig:440:config MARCH_Z196_TUNE\narch/s390/Kconfig-441-\tdef_bool TUNE_Z196 || MARCH_Z196 \u0026\u0026 TUNE_DEFAULT\narch/s390/Kconfig-442-\narch/s390/Kconfig:443:config MARCH_ZEC12_TUNE\narch/s390/Kconfig-444-\tdef_bool TUNE_ZEC12 || MARCH_ZEC12 \u0026\u0026 TUNE_DEFAULT\narch/s390/Kconfig-445-\narch/s390/Kconfig:446:config MARCH_Z13_TUNE\narch/s390/Kconfig-447-\tdef_bool TUNE_Z13 || MARCH_Z13 \u0026\u0026 TUNE_DEFAULT\narch/s390/Kconfig-448-\narch/s390/Kconfig:449:config MARCH_Z14_TUNE\narch/s390/Kconfig-450-\tdef_bool TUNE_Z14 || MARCH_Z14 \u0026\u0026 TUNE_DEFAULT\narch/s390/Kconfig-451-\narch/s390/Kconfig:452:config MARCH_Z15_TUNE\narch/s390/Kconfig-453-\tdef_bool TUNE_Z15 || MARCH_Z15 \u0026\u0026 TUNE_DEFAULT\narch/s390/Kconfig-454-\narch/s390/Kconfig:455:config MARCH_Z16_TUNE\narch/s390/Kconfig-456-\tdef_bool TUNE_Z16 || MARCH_Z16 \u0026\u0026 TUNE_DEFAULT\narch/s390/Kconfig-457-\narch/s390/Kconfig:458:config MARCH_Z17_TUNE\narch/s390/Kconfig-459-\tdef_bool TUNE_Z17 || MARCH_Z17 \u0026\u0026 TUNE_DEFAULT\n--\narch/s390/Kconfig=461=choice\n--\narch/s390/Kconfig-471-\narch/s390/Kconfig:472:config TUNE_DEFAULT\narch/s390/Kconfig-473-\tbool \"Default\"\n--\narch/s390/Kconfig-477-\narch/s390/Kconfig:478:config TUNE_Z10\narch/s390/Kconfig-479-\tbool \"IBM System z10\"\narch/s390/Kconfig-480-\narch/s390/Kconfig:481:config TUNE_Z196\narch/s390/Kconfig-482-\tbool \"IBM zEnterprise 114 and 196\"\n--\narch/s390/Kconfig-484-\narch/s390/Kconfig:485:config TUNE_ZEC12\narch/s390/Kconfig-486-\tbool \"IBM zBC12 and zEC12\"\n--\narch/s390/Kconfig-488-\narch/s390/Kconfig:489:config TUNE_Z13\narch/s390/Kconfig-490-\tbool \"IBM z13s and z13\"\n--\narch/s390/Kconfig-492-\narch/s390/Kconfig:493:config TUNE_Z14\narch/s390/Kconfig-494-\tbool \"IBM z14 ZR1 and z14\"\n--\narch/s390/Kconfig-496-\narch/s390/Kconfig:497:config TUNE_Z15\narch/s390/Kconfig-498-\tbool \"IBM z15\"\n--\narch/s390/Kconfig-500-\narch/s390/Kconfig:501:config TUNE_Z16\narch/s390/Kconfig-502-\tbool \"IBM z16\"\n--\narch/s390/Kconfig-504-\narch/s390/Kconfig:505:config TUNE_Z17\narch/s390/Kconfig-506-\tbool \"IBM z17\"\n--\narch/s390/Kconfig=509=endchoice\narch/s390/Kconfig-510-\narch/s390/Kconfig:511:config 64BIT\narch/s390/Kconfig-512-\tdef_bool y\narch/s390/Kconfig-513-\narch/s390/Kconfig:514:config COMMAND_LINE_SIZE\narch/s390/Kconfig-515-\tint \"Maximum size of kernel command line\"\n--\narch/s390/Kconfig-521-\narch/s390/Kconfig:522:config SMP\narch/s390/Kconfig-523-\tdef_bool y\narch/s390/Kconfig-524-\narch/s390/Kconfig:525:config NR_CPUS\narch/s390/Kconfig-526-\tint \"Maximum number of CPUs (2-512)\"\n--\narch/s390/Kconfig-536-\narch/s390/Kconfig:537:config HOTPLUG_CPU\narch/s390/Kconfig-538-\tdef_bool y\narch/s390/Kconfig-539-\narch/s390/Kconfig:540:config NUMA\narch/s390/Kconfig-541-\tbool \"NUMA support\"\n--\narch/s390/Kconfig-548-\narch/s390/Kconfig:549:config NODES_SHIFT\narch/s390/Kconfig-550-\tint\n--\narch/s390/Kconfig-553-\narch/s390/Kconfig:554:config SCHED_TOPOLOGY\narch/s390/Kconfig-555-\tdef_bool y\n--\narch/s390/Kconfig-565-\narch/s390/Kconfig:566:config SCHED_TOPOLOGY_VERTICAL\narch/s390/Kconfig-567-\tdef_bool y\n--\narch/s390/Kconfig-573-\narch/s390/Kconfig:574:config HIPERDISPATCH_ON\narch/s390/Kconfig-575-\tdef_bool y\n--\narch/s390/Kconfig=586=source \"kernel/Kconfig.hz\"\narch/s390/Kconfig-587-\narch/s390/Kconfig:588:config CERT_STORE\narch/s390/Kconfig-589-\tbool \"Get user certificates via DIAG320\"\n--\narch/s390/Kconfig-598-\narch/s390/Kconfig:599:config KERNEL_NOBP\narch/s390/Kconfig-600-\tdef_bool n\n--\narch/s390/Kconfig-615-\narch/s390/Kconfig:616:config EXPOLINE\narch/s390/Kconfig-617-\tdef_bool n\n--\narch/s390/Kconfig-628-\narch/s390/Kconfig:629:config EXPOLINE_EXTERN\narch/s390/Kconfig-630-\tdef_bool EXPOLINE \u0026\u0026 CC_IS_GCC \u0026\u0026 GCC_VERSION \u003e= 110200 \u0026\u0026 \\\n--\narch/s390/Kconfig=638=choice\n--\narch/s390/Kconfig-642-\narch/s390/Kconfig:643:config EXPOLINE_OFF\narch/s390/Kconfig-644-\tbool \"spectre_v2=off\"\narch/s390/Kconfig-645-\narch/s390/Kconfig:646:config EXPOLINE_AUTO\narch/s390/Kconfig-647-\tbool \"spectre_v2=auto\"\narch/s390/Kconfig-648-\narch/s390/Kconfig:649:config EXPOLINE_FULL\narch/s390/Kconfig-650-\tbool \"spectre_v2=on\"\n--\narch/s390/Kconfig=652=endchoice\narch/s390/Kconfig-653-\narch/s390/Kconfig:654:config RELOCATABLE\narch/s390/Kconfig-655-\tdef_bool y\n--\narch/s390/Kconfig-664-\narch/s390/Kconfig:665:config RANDOMIZE_BASE\narch/s390/Kconfig-666-\tbool \"Randomize the address of the kernel image (KASLR)\"\n--\narch/s390/Kconfig-673-\narch/s390/Kconfig:674:config RANDOMIZE_IDENTITY_BASE\narch/s390/Kconfig-675-\tbool \"Randomize the address of the identity mapping base\"\n--\narch/s390/Kconfig-686-\narch/s390/Kconfig:687:config KERNEL_IMAGE_BASE\narch/s390/Kconfig-688-\thex \"Kernel image base address\"\n--\narch/s390/Kconfig=708=menu \"Memory setup\"\narch/s390/Kconfig-709-\narch/s390/Kconfig:710:config ARCH_SPARSEMEM_ENABLE\narch/s390/Kconfig-711-\tdef_bool y\n--\narch/s390/Kconfig-713-\narch/s390/Kconfig:714:config ARCH_SPARSEMEM_DEFAULT\narch/s390/Kconfig-715-\tdef_bool y\narch/s390/Kconfig-716-\narch/s390/Kconfig:717:config ILLEGAL_POINTER_VALUE\narch/s390/Kconfig-718-\thex\n--\narch/s390/Kconfig-720-\narch/s390/Kconfig:721:config MAX_PHYSMEM_BITS\narch/s390/Kconfig-722-\tint \"Maximum size of supported physical memory in bits (42-53)\"\n--\narch/s390/Kconfig=733=menu \"I/O subsystem\"\narch/s390/Kconfig-734-\narch/s390/Kconfig:735:config QDIO\narch/s390/Kconfig-736-\tdef_tristate y\n--\narch/s390/Kconfig=747=if PCI\narch/s390/Kconfig-748-\narch/s390/Kconfig:749:config PCI_NR_FUNCTIONS\narch/s390/Kconfig-750-\tint \"Maximum number of PCI functions (1-4096)\"\n--\narch/s390/Kconfig=757=endif # PCI\narch/s390/Kconfig-758-\narch/s390/Kconfig:759:config HAS_IOMEM\narch/s390/Kconfig-760-\tdef_bool PCI\narch/s390/Kconfig-761-\narch/s390/Kconfig:762:config CHSC_SCH\narch/s390/Kconfig-763-\tdef_tristate m\n--\narch/s390/Kconfig-778-\narch/s390/Kconfig:779:config SCM_BUS\narch/s390/Kconfig-780-\tdef_bool y\n--\narch/s390/Kconfig-784-\narch/s390/Kconfig:785:config EADM_SCH\narch/s390/Kconfig-786-\tdef_tristate m\n--\narch/s390/Kconfig-795-\narch/s390/Kconfig:796:config AP\narch/s390/Kconfig-797-\tdef_tristate y\n--\narch/s390/Kconfig-808-\narch/s390/Kconfig:809:config AP_DEBUG\narch/s390/Kconfig-810-\tdef_bool n\n--\narch/s390/Kconfig-822-\narch/s390/Kconfig:823:config VFIO_CCW\narch/s390/Kconfig-824-\tdef_tristate n\n--\narch/s390/Kconfig-833-\narch/s390/Kconfig:834:config VFIO_AP\narch/s390/Kconfig-835-\tdef_tristate n\n--\narch/s390/Kconfig=848=endmenu\narch/s390/Kconfig-849-\narch/s390/Kconfig:850:config CCW\narch/s390/Kconfig-851-\tdef_bool y\narch/s390/Kconfig-852-\narch/s390/Kconfig:853:config HAVE_PNETID\narch/s390/Kconfig-854-\ttristate\n--\narch/s390/Kconfig=857=menu \"Virtualization\"\narch/s390/Kconfig-858-\narch/s390/Kconfig:859:config PFAULT\narch/s390/Kconfig-860-\tdef_bool y\n--\narch/s390/Kconfig-871-\narch/s390/Kconfig:872:config CMM\narch/s390/Kconfig-873-\tdef_tristate n\n--\narch/s390/Kconfig-884-\narch/s390/Kconfig:885:config CMM_IUCV\narch/s390/Kconfig-886-\tdef_bool y\n--\narch/s390/Kconfig-892-\narch/s390/Kconfig:893:config APPLDATA_BASE\narch/s390/Kconfig-894-\tdef_bool n\n--\narch/s390/Kconfig-908-\narch/s390/Kconfig:909:config APPLDATA_MEM\narch/s390/Kconfig-910-\tdef_tristate m\n--\narch/s390/Kconfig-925-\narch/s390/Kconfig:926:config APPLDATA_OS\narch/s390/Kconfig-927-\tdef_tristate m\n--\narch/s390/Kconfig-940-\narch/s390/Kconfig:941:config APPLDATA_NET_SUM\narch/s390/Kconfig-942-\tdef_tristate m\n--\narch/s390/Kconfig-956-\narch/s390/Kconfig:957:config S390_HYPFS\narch/s390/Kconfig-958-\tdef_bool y\n--\narch/s390/Kconfig-963-\narch/s390/Kconfig:964:config S390_HYPFS_FS\narch/s390/Kconfig-965-\tdef_bool n\n--\narch/s390/Kconfig=976=source \"arch/s390/kvm/Kconfig\"\narch/s390/Kconfig-977-\narch/s390/Kconfig:978:config S390_GUEST\narch/s390/Kconfig-979-\tdef_bool y\n--\narch/s390/Kconfig=991=endmenu\narch/s390/Kconfig-992-\narch/s390/Kconfig:993:config S390_MODULES_SANITY_TEST_HELPERS\narch/s390/Kconfig-994-\tdef_bool n\n--\narch/s390/Kconfig=996=menu \"Selftests\"\narch/s390/Kconfig-997-\narch/s390/Kconfig:998:config S390_UNWIND_SELFTEST\narch/s390/Kconfig-999-\tdef_tristate KUNIT_ALL_TESTS\n--\narch/s390/Kconfig-1008-\narch/s390/Kconfig:1009:config S390_KPROBES_SANITY_TEST\narch/s390/Kconfig-1010-\tdef_tristate KUNIT_ALL_TESTS\n--\narch/s390/Kconfig-1020-\narch/s390/Kconfig:1021:config S390_MODULES_SANITY_TEST\narch/s390/Kconfig-1022-\tdef_tristate KUNIT_ALL_TESTS\n"
} |
| 25/2 | 2026/08/19 20:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 21182 output: 49 thoughts: 122 Thoughts: **My KVM Configuration Analysis** Okay, so there isn't a dedicated, specific configuration option for PV (para-virtualization) on S390 KVM. It looks like it's just implicitly part of KVM itself. Therefore, logically, `KVM` is the only configuration option I need to worry about. Hang on a second… `KVM` is a tristate, isn't it? So, it could be built as a module (`m`). But considering how syzkaller generally handles things, it's likely going to be built as either 'y' or 'm'. I will just list `KVM`. Now, let me just quickly double-check that `kvm_s390_pv_sclp_kick` function. Ah, yes, found it in `arch/s390/kvm/interrupt.c`. Now the critical question: is it exported? That's what I need to know. |
| 26/2 | 2026/08/19 20:12 | tool | grepper |
0mError:no matches Args: {
"Expression": "EXPORT_SYMBOL.*kvm_s390_pv_sclp_kick",
"PathPrefix": "arch/s390/kvm/"
}Results: {
"error": "no matches"
} |
| 27/2 | 2026/08/19 20:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 21576 output: 41 thoughts: 153 Thoughts: **Reaching That Function in KVM** Okay, so I'm looking at this `kvm_s390_pv_sclp_kick` function. The code says it's *not* exported with `EXPORT_SYMBOL`, but it *is* non-static and declared in `kvm-s390.h`. No problem, syzkaller can definitely fuzz non-static functions, so that's not a blocker. I need to figure out the call chain. Wait a second...I see it now. `kvm_s390_pv_sclp_kick` is invoked by `handle_pv_sclp`. And that, in turn, is called from `handle_pv_notification`, which *itself* is called from `kvm_handle_sie_intercept`. And finally, *that* function, `kvm_handle_sie_intercept`, is called from `vcpu_post_run`. Bingo. So, essentially, it's reachable from the core KVM run loop, it is part of the execution flow in the main KVM execution path. Now, let's turn my attention to `distribute_float_irqs`. |
| 28/2 | 2026/08/19 20:12 | tool | grepper |
0mError:no matches Args: {
"Expression": "EXPORT_SYMBOL.*distribute_float_irqs",
"PathPrefix": "arch/s390/kvm/"
}Results: {
"error": "no matches"
} |
| 29/2 | 2026/08/19 20:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 22046 output: 45 thoughts: 26 Thoughts: Okay, here's my attempt at summarizing those thoughts from a first-person, expert perspective, aiming for a fulsome rendering: **My Immediate Assessment** Alright, so the context is dynamic – not a fixed snapshot. My brain immediately jumps to checking the function `kvm_s390_inject_vm`. That's where I need to start. My immediate thought is, what's non-static and how does it play into this function. I need to understand how the non-static element effects how the `kvm_s390_inject_vm` function functions, and its effect on the larger architecture. I need to think about what variables may be effecting that function. |
| 30/2 | 2026/08/19 20:12 | tool | grepper |
0mError:no matches Args: {
"Expression": "EXPORT_SYMBOL.*kvm_s390_inject_vm",
"PathPrefix": "arch/s390/kvm/"
}Results: {
"error": "no matches"
} |
| 31/2 | 2026/08/19 20:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 22279 output: 45 thoughts: 356 Thoughts: **Analyzing KVM/s390 Interrupt Handling** Okay, so I'm digging into this KVM/s390 interrupt handling code, specifically looking at symbol visibility within the module. I see a few key functions that aren't static but are globally accessible within the module. Aha, `kvm_s390_inject_vm` is exported, meaning it's intended to be used by other files in the `kvm` module. Right, that makes sense. We don't need `EXPORT_SYMBOL` for inter-file module usage. It's only needed if other modules consume these symbols. Therefore, the critical symbols I need to focus on are: `distribute_float_irqs`, `kvm_s390_pv_sclp_kick`, and `kvm_s390_inject_vm`. Now, I should quickly check if any other functions have been modified related to these symbols. Alright, `inti_to_irq_pend_mask`, `vcpu_intervention_kick`, `kick_cpu_irq`, `__floating_irq_kick`, and `__inject_vm` are all static. That's good. So, the non-static functions again are: `distribute_float_irqs`, `kvm_s390_pv_sclp_kick`, and `kvm_s390_inject_vm`. (Although `kvm_s390_inject_vm` isn't *directly* modified, `__inject_vm` which it wraps is.) Wait, let me just confirm that thought. `kvm_s390_inject_vm` *calls* `__inject_vm`. So, a change to `__inject_vm` affects the behavior of `kvm_s390_inject_vm`, even though the latter isn't directly modified. Let's make sure that that is correct and not some obfuscation. I should go check `arch/s390/kvm/interrupt.c` to be sure. |
| 32/2 | 2026/08/19 20:12 | tool | grepper |
0mArgs:{
"Expression": "int kvm_s390_inject_vm",
"PathPrefix": "arch/s390/kvm/interrupt.c"
}Results: {
"Output": "arch/s390/kvm/interrupt.c=2068=static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)\n--\narch/s390/kvm/interrupt.c-2102-\narch/s390/kvm/interrupt.c:2103:int kvm_s390_inject_vm(struct kvm *kvm,\narch/s390/kvm/interrupt.c-2104-\t\t struct kvm_s390_interrupt *s390int, struct kvm_s390_interrupt_info *inti)\n"
} |
| 33/2 | 2026/08/19 20:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 23312 output: 50 thoughts: 123 Thoughts: **Fuzzing Target Identified** Okay, `kvm_s390_inject_vm` looks like a solid entry point. But hold on... I remember now, that's called from `kvm_arch_vm_ioctl` when the `KVM_S390_INTERRUPT` ioctl is used. Bingo! That means it's directly accessible from userspace. Perfect! This is a prime target for fuzzing. I can bypass a lot of the usual complexities by going straight through the ioctl interface. Now, let's dive into `kvm_arch_vm_ioctl` in `arch/s390/kvm/kvm-s390.c` to understand the setup. I need to see what arguments it expects and how that injection mechanism is handled. |
| 34/2 | 2026/08/19 20:12 | tool | grepper |
0mArgs:{
"Expression": "KVM_S390_INTERRUPT",
"PathPrefix": "arch/s390/kvm/kvm-s390.c"
}Results: {
"Output": "arch/s390/kvm/kvm-s390.c=2927=int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)\n--\narch/s390/kvm/kvm-s390.c-2935-\tswitch (ioctl) {\narch/s390/kvm/kvm-s390.c:2936:\tcase KVM_S390_INTERRUPT: {\narch/s390/kvm/kvm-s390.c-2937-\t\tstruct kvm_s390_interrupt s390int;\n--\narch/s390/kvm/kvm-s390.c=5443=long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,\n--\narch/s390/kvm/kvm-s390.c-5458-\t}\narch/s390/kvm/kvm-s390.c:5459:\tcase KVM_S390_INTERRUPT: {\narch/s390/kvm/kvm-s390.c-5460-\t\tstruct kvm_s390_interrupt s390int;\n"
} |
| 35/2 | 2026/08/19 20:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 24009 output: 166 thoughts: 218 Thoughts: **My Analysis of the KVM/s390x Interrupt Handling Patch**
Okay, so I've been digging into this patch. I can confirm that the `KVM_S390_INTERRUPT` ioctl, as I suspected, *does* indeed call `kvm_s390_inject_vm`. That immediately flags `kvm_s390_inject_vm` as a particularly interesting function for fuzzing efforts. It’s a core entry point.
Let me break down what I've got so far:
* **Fuzzing Priority:** High priority - `WorthFuzzing` is set to `true`, which is what I would expect given the changes.
* **Key Focus Symbols:** The patch really highlights these:
* `distribute_float_irqs`: This is clearly involved in the *new* logic, which means any subtle changes in interrupt distribution handling need to be checked.
* `kvm_s390_pv_sclp_kick`: This function is tied to kicking VCPUs. I bet this is related to how the interrupts force execution to move.
* `kvm_s390_inject_vm`: This function is the direct injection point. It's the central hub for our fuzzing strategy. We need to hammer this.
* **Enabled Configuration:** The `KVM` config is required. Not a surprise, but important to note.
* **Reasoning Summary:** This patch modifies how floating interrupts are handled and distributed within KVM on s390x. The changes introduce new logic for interrupt distribution across VCPUs. The patch is tied to interrupt injection, which means this could be triggered from userspace via KVM ioctls like `KVM_S390_INTERRUPT`. Moreover, these changes impact interrupt injection paths and VCPU execution. This is a critical area for further investigation. It seems that interrupt handling paths are being updated or modified.
|
| 36/2 | 2026/08/19 20:12 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"distribute_float_irqs",
"kvm_s390_pv_sclp_kick",
"kvm_s390_inject_vm"
],
"Reasoning": "The patch modifies the handling and distribution of floating interrupts in KVM on s390x. It introduces new logic to distribute floating IRQs across VCPUs and to kick VCPUs when specific interrupts are injected. These changes affect core KVM interrupt injection paths, which are reachable from userspace via KVM ioctls (e.g., KVM_S390_INTERRUPT) and during VCPU execution.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"KVM"
],
"FocusSymbols": [
"distribute_float_irqs",
"kvm_s390_pv_sclp_kick",
"kvm_s390_inject_vm"
],
"Reasoning": "The patch modifies the handling and distribution of floating interrupts in KVM on s390x. It introduces new logic to distribute floating IRQs across VCPUs and to kick VCPUs when specific interrupts are injected. These changes affect core KVM interrupt injection paths, which are reachable from userspace via KVM ioctls (e.g., KVM_S390_INTERRUPT) and during VCPU execution.",
"WorthFuzzing": true
} |
| 37/1 | 2026/08/19 20:12 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 38/2 | 2026/08/19 20:12 | agent | kmsan-evaluator |
0mModel:best-expensive Args: null Results: {
"KMSANReasoning": "The patch modifies the handling of floating interrupts in KVM for s390, introducing a new statistic `inject_redist` and changing how vCPUs are kicked when interrupts are pending. The only potential uninitialized memory is the local variable `parm` in `__inject_vm()`, which is left uninitialized for certain interrupt types (e.g., `KVM_S390_MCHK`). However, this uninitialized value is passed to `__floating_irq_kick()` and subsequently to `inti_to_irq_pend_mask()`, where it is completely ignored for those specific interrupt types. KMSAN tracks uninitialized memory at the shadow level and only reports an error if the uninitialized value is used in a branch, as a memory address, or copied to userspace. Since `parm` is never evaluated in these ways when uninitialized, it will not trigger a KMSAN report. Other changes involve basic control flow, vCPU wakeups, and a new field in `struct kvm_vm_stat` (which is zero-allocated). There are no new structures copied to userspace, no complex data parsing, and no uninitialized memory risks introduced. Standard KASAN and other bug detectors are sufficient.",
"NeedsKMSAN": false
}Instruction: You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.
CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
a comprehensive suite of debugging tools and sanitizers, including KASAN
(out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
(locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
or page allocations) and kernel-to-user memory info-leaks.
Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.
Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.
Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
attributes, ioctl output arguments, socket options, or BPF buffers) where fields
or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
uninitialized bytes of existing buffers.
Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
dereferences, locking deadlocks, or use-after-free bugs (these are already caught
by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.
Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
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 90883cfa06e77be61b79a608549167bd1ebd2d59
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Aug 19 20:01:52 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index b4182ca4435fb..1d62bdd7aca5e 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -467,6 +467,7 @@ struct kvm_vm_stat {
u64 gmap_shadow_r3_entry;
u64 gmap_shadow_sg_entry;
u64 gmap_shadow_pg_entry;
+ u64 inject_redist;
};
struct kvm_arch_memory_slot {
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 1980df61ef304..e1de3f471ffd0 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -536,6 +536,15 @@ static int handle_pv_sclp(struct kvm_vcpu *vcpu)
set_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs);
clear_bit(IRQ_PEND_EXT_SERVICE, &fi->masked_irqs);
spin_unlock_irqrestore(&fi->lock, flags);
+
+ /*
+ * We missed the floating IRQ kick since we can only inject
+ * when we end up here and not when the irq was injected via
+ * the FLIC.
+ *
+ * Now that we have cleared the masking we can kick cpus.
+ */
+ kvm_s390_pv_sclp_kick(vcpu);
return 0;
}
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 8f24bcd1a6d36..1ee9ab2505042 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -367,6 +367,37 @@ static unsigned long deliverable_irqs(struct kvm_vcpu *vcpu)
return active_mask;
}
+void distribute_float_irqs(struct kvm *kvm)
+{
+ struct kvm_vcpu *dst_vcpu;
+ int sigcpu, online_vcpus;
+
+ if (!READ_ONCE(kvm->arch.float_int.pending_irqs))
+ return;
+
+ online_vcpus = atomic_read(&kvm->online_vcpus);
+
+ /*
+ * Not too worried about synchronization for idle_mask. We
+ * might burn too many cycles but apart from that waking a
+ * vcpu is not harmful.
+ */
+ sigcpu = find_first_bit(kvm->arch.idle_mask, online_vcpus);
+ /* Well nobody's sleeping so someone will likely take the IRQ soon */
+ if (sigcpu == online_vcpus)
+ return;
+
+ do {
+ dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
+ if (deliverable_irqs(dst_vcpu)) {
+ kvm->stat.inject_redist++;
+ kvm_s390_vcpu_wakeup(dst_vcpu);
+ break;
+ }
+ sigcpu = find_next_bit(kvm->arch.idle_mask, online_vcpus, ++sigcpu);
+ } while (sigcpu < online_vcpus);
+}
+
static void __set_cpu_idle(struct kvm_vcpu *vcpu)
{
kvm_s390_set_cpuflags(vcpu, CPUSTAT_WAIT);
@@ -1915,49 +1946,129 @@ static int __inject_io(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
return 0;
}
+static u64 inti_to_irq_pend_mask(u64 type, int isc)
+{
+ switch (type) {
+ case KVM_S390_MCHK:
+ /* Only repressible machine checks are floating */
+ return BIT(IRQ_PEND_MCHK_REP);
+ case KVM_S390_INT_VIRTIO:
+ return BIT(IRQ_PEND_VIRTIO);
+ case KVM_S390_INT_SERVICE:
+ return BIT(IRQ_PEND_EXT_SERVICE) |
+ BIT(IRQ_PEND_EXT_SERVICE_EV);
+ case KVM_S390_INT_PFAULT_DONE:
+ return BIT(IRQ_PEND_PFAULT_DONE);
+ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
+ return isc_to_irq_type(isc);
+ default:
+ return 0;
+ }
+}
+
/*
- * Find a destination VCPU for a floating irq and kick it.
+ * Setup intervention masks to catch running vcpus that hopefully open
+ * their masks soonish and kick sleeping vcpus to motivate them to
+ * take IRQs.
*/
-static void __floating_irq_kick(struct kvm *kvm, u64 type)
+static void vcpu_intervention_kick(struct kvm_vcpu *vcpu, u64 type)
+{
+ /* make the VCPU drop out of the SIE, or wake it up if sleeping */
+ switch (type) {
+ case KVM_S390_MCHK:
+ kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOP_INT);
+ break;
+ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
+ if (!(type & KVM_S390_INT_IO_AI_MASK &&
+ vcpu->kvm->arch.gisa_int.origin) ||
+ kvm_s390_pv_cpu_get_handle(vcpu))
+ kvm_s390_set_cpuflags(vcpu, CPUSTAT_IO_INT);
+ break;
+ default:
+ kvm_s390_set_cpuflags(vcpu, CPUSTAT_EXT_INT);
+ break;
+ }
+ kvm_s390_vcpu_wakeup(vcpu);
+}
+
+static void kick_cpu_irq(struct kvm *kvm, u64 type, u64 parm)
{
struct kvm_vcpu *dst_vcpu;
int sigcpu, online_vcpus, nr_tries = 0;
+ u64 irq_pend_mask;
+ unsigned long i;
online_vcpus = atomic_read(&kvm->online_vcpus);
if (!online_vcpus)
return;
+ irq_pend_mask = inti_to_irq_pend_mask(type, parm);
for (sigcpu = kvm->arch.float_int.last_sleep_cpu; ; sigcpu++) {
sigcpu %= online_vcpus;
dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
- if (!is_vcpu_stopped(dst_vcpu))
+ if (!is_vcpu_stopped(dst_vcpu) &&
+ deliverable_irqs(dst_vcpu) & irq_pend_mask)
break;
/* avoid endless loops if all vcpus are stopped */
- if (nr_tries++ >= online_vcpus)
- return;
+ if (nr_tries++ >= online_vcpus * 2) {
+ dst_vcpu = NULL;
+ break;
+ }
}
- /* make the VCPU drop out of the SIE, or wake it up if sleeping */
- switch (type) {
- case KVM_S390_MCHK:
- kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_STOP_INT);
- break;
- case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
- if (!(type & KVM_S390_INT_IO_AI_MASK &&
- kvm->arch.gisa_int.origin) ||
- kvm_s390_pv_cpu_get_handle(dst_vcpu))
- kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_IO_INT);
- break;
- default:
- kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_EXT_INT);
- break;
+ /* Nobody was enabled, time to wake all of them */
+ if (!dst_vcpu) {
+ kvm_for_each_vcpu(i, dst_vcpu, kvm)
+ vcpu_intervention_kick(dst_vcpu, type);
+ return;
}
- kvm_s390_vcpu_wakeup(dst_vcpu);
+
+ vcpu_intervention_kick(dst_vcpu, type);
+}
+
+void kvm_s390_pv_sclp_kick(struct kvm_vcpu *vcpu)
+{
+ /*
+ * The cpu that called sclp likely will also take the IRQ, no
+ * need to kick anyone.
+ */
+ if (likely(deliverable_irqs(vcpu) & IRQ_PEND_EXT_SERVICE))
+ return;
+
+ /*
+ * For the other cases we might have sleeping cpus with open
+ * masks. Time to find and kick them.
+ */
+ kick_cpu_irq(vcpu->kvm, KVM_S390_INT_SERVICE, -1);
+}
+
+/*
+ * Find a destination VCPU for a floating irq and kick it.
+ */
+static void __floating_irq_kick(struct kvm *kvm, u64 type, u64 parm)
+{
+ int prot;
+
+ mutex_lock(&kvm->lock);
+ prot = kvm_s390_pv_is_protected(kvm);
+ mutex_unlock(&kvm->lock);
+ /*
+ * No need to kick on non-ev service IRQs for PV VMs, we're
+ * not allowed to inject anyway. We need to wait for the sclp
+ * instruction notification AFTER re-entry of the vcpu that
+ * handled the instruction intercept.
+ */
+ if (prot && type == KVM_S390_INT_SERVICE &&
+ !(parm & SCCB_EVENT_PENDING))
+ return;
+
+ kick_cpu_irq(kvm, type, parm);
}
static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
{
u64 type = READ_ONCE(inti->type);
+ u64 parm;
int rc;
switch (type) {
@@ -1968,12 +2079,15 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
rc = __inject_virtio(kvm, inti);
break;
case KVM_S390_INT_SERVICE:
+ parm = inti->ext.ext_params & SCCB_EVENT_PENDING;
rc = __inject_service(kvm, inti);
break;
case KVM_S390_INT_PFAULT_DONE:
rc = __inject_pfault_done(kvm, inti);
break;
case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
+ /* Grab isc here since __inject_io() might free inti */
+ parm = isc_to_irq_type(int_word_to_isc(inti->io.io_int_word));
rc = __inject_io(kvm, inti);
break;
default:
@@ -1982,7 +2096,7 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
if (rc)
return rc;
- __floating_irq_kick(kvm, type);
+ __floating_irq_kick(kvm, type, parm);
return 0;
}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 518a69c55e85c..d6d46688d9808 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -86,6 +86,7 @@ const struct kvm_stats_desc kvm_vm_stats_desc[] = {
STATS_DESC_COUNTER(VM, gmap_shadow_r3_entry),
STATS_DESC_COUNTER(VM, gmap_shadow_sg_entry),
STATS_DESC_COUNTER(VM, gmap_shadow_pg_entry),
+ STATS_DESC_COUNTER(VM, inject_redist),
};
const struct kvm_stats_header kvm_vm_stats_header = {
@@ -4572,6 +4573,8 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
rc = kvm_s390_deliver_pending_interrupts(vcpu);
if (rc || guestdbg_exit_pending(vcpu))
return rc;
+
+ distribute_float_irqs(vcpu->kvm);
}
rc = kvm_s390_handle_requests(vcpu);
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 6d2842fb71a33..7115a8f5b1882 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -375,6 +375,8 @@ enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu);
void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu);
void kvm_s390_clear_float_irqs(struct kvm *kvm);
+void kvm_s390_pv_sclp_kick(struct kvm_vcpu *vcpu);
+void distribute_float_irqs(struct kvm *kvm);
int __must_check kvm_s390_inject_vm(struct kvm *kvm,
struct kvm_s390_interrupt *s390int,
struct kvm_s390_interrupt_info *inti);
|
| 39/3 | 2026/08/19 20:12 | llm | kmsan-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5886 output: 287 thoughts: 4892 Thoughts: **KMSAN Assessment of s390 KVM Interrupt Redistribution Patch** Okay, so I've gone through this patch, which focuses on modifying KVM for the s390 architecture, particularly regarding floating interrupt handling. It introduces a new statistic, `inject_redist`, within the `kvm_vm_stat` structure, which is typical for KVM statistics and is initialized to zero on allocation, so that's fine. The patch's core logic revolves around distributing floating interrupts to idle vCPUs and waking them up as needed. There are modifications to functions like `handle_pv_sclp`, `distribute_float_irqs`, `__floating_irq_kick`, `kick_cpu_irq`, `inti_to_irq_pend_mask`, `vcpu_intervention_kick`, `__inject_vm`, and `vcpu_pre_run` to implement this new behavior. My immediate concern is always uninitialized memory, which I scrutinized here. The main area of interest is the `__inject_vm` function, where the variable `parm` *can* be uninitialized in certain scenarios, specifically when the interrupt type is `KVM_S390_MCHK`, `KVM_S390_INT_VIRTIO`, or `KVM_S390_INT_PFAULT_DONE`. This `parm` value is then passed to `__floating_irq_kick` and subsequently to `kick_cpu_irq` and `inti_to_irq_pend_mask`. However, critically, the value of `parm` is completely ignored in the latter function when `type` is one of the cases where `parm` is uninitialized. Now, the question is whether this constitutes a KMSAN (Kernel Memory Sanitizer) issue. KMSAN tracks memory at the shadow level and is designed to detect the use of uninitialized values. However, KMSAN only reports when the uninitialized value is used in a branch, as a memory address, or copied to userspace. In this scenario, while `parm` *is* passed as an argument with an undefined value when `type` is certain values, that uninitialized value is NOT used in any conditional branch or memory access. It's effectively discarded. The checks in `__floating_irq_kick` specifically skip the branching when `type` is `KVM_S390_MCHK`, etc. In `inti_to_irq_pend_mask`, the value of `parm` (passed as `isc`) is completely ignored when the interrupt type is one of those that leave `parm` uninitialized. Thus, KMSAN won't complain here, as the undefined value isn't used in a way that affects program behavior. The rest of the patch involves mostly control flow, setting and checking masks, and waking vCPUs, which are all pretty standard KVM operations. The new `inject_redist` statistic is exposed through the standard KVM infrastructure, so the structure is already zero-initialized. I didn't see any other uninitialized variables, new structures being copied to userspace, or complex data parsing that would increase the risk of an uninitialized memory issue. So, I'm confident that this is *not* a KMSAN issue. Regular static analysis tools should be sufficient. |
| 40/3 | 2026/08/19 20:13 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch modifies the handling of floating interrupts in KVM for s390, introducing a new statistic `inject_redist` and changing how vCPUs are kicked when interrupts are pending. The only potential uninitialized memory is the local variable `parm` in `__inject_vm()`, which is left uninitialized for certain interrupt types (e.g., `KVM_S390_MCHK`). However, this uninitialized value is passed to `__floating_irq_kick()` and subsequently to `inti_to_irq_pend_mask()`, where it is completely ignored for those specific interrupt types. KMSAN tracks uninitialized memory at the shadow level and only reports an error if the uninitialized value is used in a branch, as a memory address, or copied to userspace. Since `parm` is never evaluated in these ways when uninitialized, it will not trigger a KMSAN report. Other changes involve basic control flow, vCPU wakeups, and a new field in `struct kvm_vm_stat` (which is zero-allocated). There are no new structures copied to userspace, no complex data parsing, and no uninitialized memory risks introduced. Standard KASAN and other bug detectors are sufficient.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch modifies the handling of floating interrupts in KVM for s390, introducing a new statistic `inject_redist` and changing how vCPUs are kicked when interrupts are pending. The only potential uninitialized memory is the local variable `parm` in `__inject_vm()`, which is left uninitialized for certain interrupt types (e.g., `KVM_S390_MCHK`). However, this uninitialized value is passed to `__floating_irq_kick()` and subsequently to `inti_to_irq_pend_mask()`, where it is completely ignored for those specific interrupt types. KMSAN tracks uninitialized memory at the shadow level and only reports an error if the uninitialized value is used in a branch, as a memory address, or copied to userspace. Since `parm` is never evaluated in these ways when uninitialized, it will not trigger a KMSAN report. Other changes involve basic control flow, vCPU wakeups, and a new field in `struct kvm_vm_stat` (which is zero-allocated). There are no new structures copied to userspace, no complex data parsing, and no uninitialized memory risks introduced. Standard KASAN and other bug detectors are sufficient.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|