AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/08/01 06:42 flow patch-triage
2m Args:
null

Results:
{
  "EnableConfigs": [
    "KVM"
  ],
  "FocusSymbols": [
    "kvm_arch_vm_ioctl",
    "kvm_arch_vcpu_create",
    "kvm_arch_vcpu_postcreate",
    "kvm_arch_commit_memory_region",
    "kvm_arch_prepare_memory_region",
    "kvm_s390_pv_create_cpu",
    "kvm_s390_pv_destroy_cpu",
    "dat_reset_reference_bit",
    "kvm_s390_faultin_gfn"
  ],
  "Reasoning": "The patch makes functional changes to the s390 KVM subsystem, including fixes for memory leaks, locking, initialization races, and signal handling during page faults. It modifies core KVM ioctls, memory region management, and Protected Virtualization (PV) CPU lifecycle functions. These changes are reachable from userspace via KVM ioctls and memory accesses, making them suitable for fuzzing.",
  "WorthFuzzing": true
}

1/1 2026/08/01 06:42 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 667b22eb9c3398191ed1f90d35965dcc68eaf913\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Sat Aug 1 06:42:53 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 eaa34c5bd3c11..edf75b6ad20ce 100644\n--- a/arch/s390/include/asm/kvm_host.h\n+++ b/arch/s390/include/asm/kvm_host.h\n@@ -440,6 +440,7 @@ struct kvm_vcpu_arch {\n \tbool skey_enabled;\n \t/* Indicator if the access registers have been loaded from guest */\n \tbool acrs_loaded;\n+\tbool initialized;\n \tstruct kvm_s390_pv_vcpu pv;\n \tunion diag318_info diag318_info;\n \tstruct kvm_s390_mmu_cache *mc;\ndiff --git a/arch/s390/kvm/dat.c b/arch/s390/kvm/dat.c\nindex ed4259d176295..3f2d6e8902d76 100644\n--- a/arch/s390/kvm/dat.c\n+++ b/arch/s390/kvm/dat.c\n@@ -755,13 +755,15 @@ int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gf\n \treturn rc;\n }\n \n-int dat_reset_reference_bit(union asce asce, gfn_t gfn)\n+int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey)\n {\n \tunion pgste pgste, old;\n \tunion crste *crstep;\n \tunion pte *ptep;\n \tint rc;\n \n+\tskey-\u003eskey = 0;\n+\n \trc = dat_entry_walk(NULL, gfn, asce, DAT_WALK_ANY, TABLE_TYPE_PAGE_TABLE, \u0026crstep, \u0026ptep);\n \tif (rc)\n \t\treturn rc;\n@@ -771,21 +773,23 @@ int dat_reset_reference_bit(union asce asce, gfn_t gfn)\n \n \t\tif (!crste.h.fc || !crste.s.fc1.pr)\n \t\t\treturn 0;\n-\t\treturn page_reset_referenced(large_crste_to_phys(*crstep, gfn));\n+\t\tskey-\u003eskey = page_reset_referenced(large_crste_to_phys(*crstep, gfn)) \u003c\u003c 1;\n+\t\treturn 0;\n \t}\n \told = pgste_get_lock(ptep);\n \tpgste = old;\n \n \tif (!ptep-\u003eh.i) {\n-\t\trc = page_reset_referenced(pte_origin(*ptep));\n-\t\tpgste.hr = rc \u003e\u003e 1;\n+\t\tskey-\u003eskey = page_reset_referenced(pte_origin(*ptep)) \u003c\u003c 1;\n+\t\tpgste.hr = skey-\u003er;\n \t}\n-\trc |= (pgste.gr \u003c\u003c 1) | pgste.gc;\n+\tskey-\u003er |= pgste.gr;\n+\tskey-\u003ec |= pgste.gc;\n \tpgste.gr = 0;\n \n \tdat_update_ptep_sd(old, pgste, ptep);\n \tpgste_set_unlock(ptep, pgste);\n-\treturn rc;\n+\treturn 0;\n }\n \n static long dat_reset_skeys_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n@@ -846,6 +850,7 @@ static long _dat_slot_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_wal\n \tstruct slot_priv *p = walk-\u003epriv;\n \tunion crste dummy = { .val = p-\u003etoken };\n \tunion pte new_pte, pte = READ_ONCE(*ptep);\n+\tunion pgste pgste;\n \n \tnew_pte = _PTE_TOK(dummy.tok.type, dummy.tok.par);\n \n@@ -853,7 +858,11 @@ static long _dat_slot_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_wal\n \tif (pte.val == new_pte.val)\n \t\treturn 0;\n \n-\tdat_ptep_xchg(ptep, new_pte, gfn, walk-\u003easce, false);\n+\tpgste = pgste_get_lock(ptep);\n+\tpgste = __dat_ptep_xchg(ptep, pgste, new_pte, gfn, walk-\u003easce, false);\n+\tpgste.cmma_d = 0;\n+\tpgste_set_unlock(ptep, pgste);\n+\n \treturn 0;\n }\n \ndiff --git a/arch/s390/kvm/dat.h b/arch/s390/kvm/dat.h\nindex fad605305e05c..141ee7b9f0191 100644\n--- a/arch/s390/kvm/dat.h\n+++ b/arch/s390/kvm/dat.h\n@@ -537,7 +537,7 @@ int dat_set_storage_key(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t gf\n \t\t\tunion skey skey, bool nq);\n int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gfn_t gfn,\n \t\t\t     union skey skey, union skey *oldkey, bool nq, bool mr, bool mc);\n-int dat_reset_reference_bit(union asce asce, gfn_t gfn);\n+int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey);\n long dat_reset_skeys(union asce asce, gfn_t start);\n \n unsigned long dat_get_ptval(struct page_table *table, struct ptval_param param);\ndiff --git a/arch/s390/kvm/faultin.c b/arch/s390/kvm/faultin.c\nindex fee80047bd94f..3cc45f7f5b2d7 100644\n--- a/arch/s390/kvm/faultin.c\n+++ b/arch/s390/kvm/faultin.c\n@@ -91,9 +91,9 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa\n \t\t/* Access outside memory, addressing exception. */\n \t\tif (is_noslot_pfn(f-\u003epfn))\n \t\t\treturn PGM_ADDRESSING;\n-\t\t/* Signal pending: try again. */\n-\t\tif (f-\u003epfn == KVM_PFN_ERR_SIGPENDING)\n-\t\t\treturn -EAGAIN;\n+\t\t/* Fatal signal pending: bail out. */\n+\t\tif (is_sigpending_pfn(f-\u003epfn))\n+\t\t\treturn -EINTR;\n \t\t/* Check if it's read-only memory; don't try to actually handle that case. */\n \t\tif (f-\u003epfn == KVM_PFN_ERR_RO_FAULT)\n \t\t\treturn -EOPNOTSUPP;\ndiff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c\nindex 9e3e6b0d72ad6..6013f28e3461f 100644\n--- a/arch/s390/kvm/interrupt.c\n+++ b/arch/s390/kvm/interrupt.c\n@@ -45,13 +45,16 @@ static struct kvm_s390_gib *gib;\n static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)\n {\n \tstruct esca_block *sca = vcpu-\u003ekvm-\u003earch.sca;\n-\tunion esca_sigp_ctrl sigp_ctrl = sca-\u003ecpu[vcpu-\u003evcpu_id].sigp_ctrl;\n+\tunion esca_sigp_ctrl sigp_ctrl;\n \n \tif (!kvm_s390_test_cpuflags(vcpu, CPUSTAT_ECALL_PEND))\n \t\treturn 0;\n \n+\tif (KVM_BUG_ON(kvm_is_ucontrol(vcpu-\u003ekvm), vcpu-\u003ekvm))\n+\t\treturn -EINVAL;\n \tBUG_ON(!kvm_s390_use_sca_entries());\n \n+\tsigp_ctrl = sca-\u003ecpu[vcpu-\u003evcpu_id].sigp_ctrl;\n \tif (src_id)\n \t\t*src_id = sigp_ctrl.scn;\n \n@@ -60,13 +63,16 @@ static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)\n \n static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)\n {\n-\tstruct esca_block *sca = vcpu-\u003ekvm-\u003earch.sca;\n-\tunion esca_sigp_ctrl *sigp_ctrl = \u0026sca-\u003ecpu[vcpu-\u003evcpu_id].sigp_ctrl;\n \tunion esca_sigp_ctrl old_val, new_val = {.scn = src_id, .c = 1};\n+\tstruct esca_block *sca = vcpu-\u003ekvm-\u003earch.sca;\n+\tunion esca_sigp_ctrl *sigp_ctrl;\n \tint expect, rc;\n \n \tBUG_ON(!kvm_s390_use_sca_entries());\n+\tif (KVM_BUG_ON(kvm_is_ucontrol(vcpu-\u003ekvm), vcpu-\u003ekvm))\n+\t\treturn -EINVAL;\n \n+\tsigp_ctrl = \u0026sca-\u003ecpu[vcpu-\u003evcpu_id].sigp_ctrl;\n \told_val = READ_ONCE(*sigp_ctrl);\n \told_val.c = 0;\n \n@@ -84,10 +90,13 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)\n static void sca_clear_ext_call(struct kvm_vcpu *vcpu)\n {\n \tstruct esca_block *sca = vcpu-\u003ekvm-\u003earch.sca;\n-\tunion esca_sigp_ctrl *sigp_ctrl = \u0026sca-\u003ecpu[vcpu-\u003evcpu_id].sigp_ctrl;\n+\tunion esca_sigp_ctrl *sigp_ctrl;\n \n-\tif (!kvm_s390_use_sca_entries())\n+\tif (!kvm_s390_use_sca_entries() || !vcpu-\u003earch.initialized || kvm_is_ucontrol(vcpu-\u003ekvm))\n \t\treturn;\n+\n+\t/* Initialize after the above check, to prevent going out of bounds */\n+\tsigp_ctrl = \u0026sca-\u003ecpu[vcpu-\u003evcpu_id].sigp_ctrl;\n \tkvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);\n \n \tWRITE_ONCE(sigp_ctrl-\u003evalue, 0);\ndiff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c\nindex 150b5dd2170e2..668272dffa18b 100644\n--- a/arch/s390/kvm/kvm-s390.c\n+++ b/arch/s390/kvm/kvm-s390.c\n@@ -571,7 +571,7 @@ static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op\n \tswitch (op) {\n \tcase KVM_S390_KEYOP_SSKE:\n \t\tr = dat_cond_set_storage_key(mc, asce, gfn, skey, \u0026skey, 0, 0, 0);\n-\t\tif (r \u003e= 0)\n+\t\tif (r == 0 || r == 1)\n \t\t\treturn skey.skey;\n \t\tbreak;\n \tcase KVM_S390_KEYOP_ISKE:\n@@ -580,14 +580,14 @@ static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op\n \t\t\treturn skey.skey;\n \t\tbreak;\n \tcase KVM_S390_KEYOP_RRBE:\n-\t\tr = dat_reset_reference_bit(asce, gfn);\n-\t\tif (r \u003e 0)\n-\t\t\treturn r \u003c\u003c 1;\n+\t\tr = dat_reset_reference_bit(asce, gfn, \u0026skey);\n+\t\tif (!r)\n+\t\t\treturn skey.skey;\n \t\tbreak;\n \tdefault:\n \t\treturn -EINVAL;\n \t}\n-\treturn r;\n+\treturn r \u003e 0 ? -EFAULT : r;\n }\n \n /* Section: device related */\n@@ -1219,8 +1219,8 @@ static void kvm_s390_sync_request_broadcast(struct kvm *kvm, int req)\n \n /*\n  * Must be called with kvm-\u003esrcu held to avoid races on memslots, and with\n- * kvm-\u003eslots_lock to avoid races with ourselves, kvm_s390_vm_stop_migration(),\n- * and kvm_s390_get_cmma_bits().\n+ * kvm-\u003eslots_arch_lock to avoid races with ourselves,\n+ * kvm_s390_vm_stop_migration(), and kvm_s390_get_cmma_bits().\n  */\n static int kvm_s390_vm_start_migration(struct kvm *kvm)\n {\n@@ -1265,7 +1265,7 @@ static int kvm_s390_vm_start_migration(struct kvm *kvm)\n }\n \n /*\n- * Must be called with kvm-\u003eslots_lock to avoid races with ourselves,\n+ * Must be called with kvm-\u003eslots_arch_lock to avoid races with ourselves,\n  * kvm_s390_vm_start_migration() and kvm_s390_get_cmma_bits().\n  */\n static int kvm_s390_vm_stop_migration(struct kvm *kvm)\n@@ -1300,7 +1300,9 @@ static int kvm_s390_vm_set_migration(struct kvm *kvm,\n {\n \tint res = -ENXIO;\n \n-\tmutex_lock(\u0026kvm-\u003eslots_lock);\n+\tguard(srcu)(\u0026kvm-\u003esrcu);\n+\tguard(mutex)(\u0026kvm-\u003eslots_arch_lock);\n+\n \tswitch (attr-\u003eattr) {\n \tcase KVM_S390_VM_MIGRATION_START:\n \t\tres = kvm_s390_vm_start_migration(kvm);\n@@ -1311,7 +1313,6 @@ static int kvm_s390_vm_set_migration(struct kvm *kvm,\n \tdefault:\n \t\tbreak;\n \t}\n-\tmutex_unlock(\u0026kvm-\u003eslots_lock);\n \n \treturn res;\n }\n@@ -2214,7 +2215,7 @@ static int kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)\n \t}\n \n \tkvfree(keys);\n-\treturn r;\n+\treturn r \u003c= 0 ? r : -EFAULT;\n }\n \n static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)\n@@ -2276,7 +2277,7 @@ static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)\n \tkvm_s390_free_mmu_cache(mc);\n out:\n \tkvfree(keys);\n-\treturn r;\n+\treturn r \u003c= 0 ? r : -EFAULT;\n }\n \n /*\n@@ -2386,7 +2387,7 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,\n \n \tset_bit(GMAP_FLAG_USES_CMM, \u0026kvm-\u003earch.gmap-\u003eflags);\n \n-\treturn r;\n+\treturn r \u003c= 0 ? r : -EFAULT;\n }\n \n /**\n@@ -2934,6 +2935,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)\n \tcase KVM_S390_INTERRUPT: {\n \t\tstruct kvm_s390_interrupt s390int;\n \n+\t\tr = -EINVAL;\n+\t\tif (kvm_is_ucontrol(kvm))\n+\t\t\tbreak;\n \t\tr = -EFAULT;\n \t\tif (copy_from_user(\u0026s390int, argp, sizeof(s390int)))\n \t\t\tbreak;\n@@ -2998,9 +3002,8 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)\n \t\tr = -EFAULT;\n \t\tif (copy_from_user(\u0026args, argp, sizeof(args)))\n \t\t\tbreak;\n-\t\tmutex_lock(\u0026kvm-\u003eslots_lock);\n-\t\tr = kvm_s390_get_cmma_bits(kvm, \u0026args);\n-\t\tmutex_unlock(\u0026kvm-\u003eslots_lock);\n+\t\tscoped_guard(mutex, \u0026kvm-\u003eslots_arch_lock)\n+\t\t\tr = kvm_s390_get_cmma_bits(kvm, \u0026args);\n \t\tif (!r) {\n \t\t\tr = copy_to_user(argp, \u0026args, sizeof(args));\n \t\t\tif (r)\n@@ -3014,9 +3017,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)\n \t\tr = -EFAULT;\n \t\tif (copy_from_user(\u0026args, argp, sizeof(args)))\n \t\t\tbreak;\n-\t\tmutex_lock(\u0026kvm-\u003eslots_lock);\n+\t\tmutex_lock(\u0026kvm-\u003eslots_arch_lock);\n \t\tr = kvm_s390_set_cmma_bits(kvm, \u0026args);\n-\t\tmutex_unlock(\u0026kvm-\u003eslots_lock);\n+\t\tmutex_unlock(\u0026kvm-\u003eslots_arch_lock);\n \t\tbreak;\n \t}\n \tcase KVM_S390_PV_COMMAND: {\n@@ -3461,7 +3464,7 @@ static void sca_del_vcpu(struct kvm_vcpu *vcpu)\n {\n \tstruct esca_block *sca = vcpu-\u003ekvm-\u003earch.sca;\n \n-\tif (!kvm_s390_use_sca_entries())\n+\tif (!kvm_s390_use_sca_entries() || !vcpu-\u003earch.initialized)\n \t\treturn;\n \n \tclear_bit_inv(vcpu-\u003evcpu_id, (unsigned long *)sca-\u003emcn);\n@@ -3481,8 +3484,8 @@ static void sca_add_vcpu(struct kvm_vcpu *vcpu)\n \tif (!kvm_s390_use_sca_entries())\n \t\treturn;\n \n+\tWRITE_ONCE(sca-\u003ecpu[vcpu-\u003evcpu_id].sda, virt_to_phys(vcpu-\u003earch.sie_block));\n \tset_bit_inv(vcpu-\u003evcpu_id, (unsigned long *)sca-\u003emcn);\n-\tsca-\u003ecpu[vcpu-\u003evcpu_id].sda = virt_to_phys(vcpu-\u003earch.sie_block);\n }\n \n static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)\n@@ -3613,6 +3616,9 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)\n \tif (test_kvm_facility(vcpu-\u003ekvm, 74) || vcpu-\u003ekvm-\u003earch.user_instr0 ||\n \t    vcpu-\u003ekvm-\u003earch.user_operexec)\n \t\tvcpu-\u003earch.sie_block-\u003eictl |= ICTL_OPEREXC;\n+\n+\t/* Pairs with smp_load_acquire() in kvm_arch_vcpu_ioctl_run() and kvm_arch_vcpu_ioctl() */\n+\tsmp_store_release(\u0026vcpu-\u003earch.initialized, true);\n }\n \n static bool kvm_has_pckmo_subfunc(struct kvm *kvm, unsigned long nr)\n@@ -3674,7 +3680,8 @@ static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)\n \n void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu)\n {\n-\tfree_page((unsigned long)phys_to_virt(vcpu-\u003earch.sie_block-\u003ecbrlo));\n+\tif (vcpu-\u003earch.sie_block-\u003ecbrlo)\n+\t\tfree_page((unsigned long)phys_to_virt(vcpu-\u003earch.sie_block-\u003ecbrlo));\n \tvcpu-\u003earch.sie_block-\u003ecbrlo = 0;\n }\n \n@@ -3792,21 +3799,21 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)\n \treturn 0;\n }\n \n+DEFINE_FREE(sie_page, struct sie_page *, if (_T) free_page((unsigned long)(_T)))\n+\n int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)\n {\n-\tstruct sie_page *sie_page;\n+\tstruct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;\n+\tstruct sie_page *sie_page __free(sie_page) = NULL;\n \tint rc;\n \n \tBUILD_BUG_ON(sizeof(struct sie_page) != 4096);\n-\tvcpu-\u003earch.mc = kvm_s390_new_mmu_cache();\n-\tif (!vcpu-\u003earch.mc)\n+\tmc = kvm_s390_new_mmu_cache();\n+\tif (!mc)\n \t\treturn -ENOMEM;\n \tsie_page = (struct sie_page *) get_zeroed_page(GFP_KERNEL_ACCOUNT);\n-\tif (!sie_page) {\n-\t\tkvm_s390_free_mmu_cache(vcpu-\u003earch.mc);\n-\t\tvcpu-\u003earch.mc = NULL;\n+\tif (!sie_page)\n \t\treturn -ENOMEM;\n-\t}\n \n \tvcpu-\u003earch.sie_block = \u0026sie_page-\u003esie_block;\n \tvcpu-\u003earch.sie_block-\u003eitdba = virt_to_phys(\u0026sie_page-\u003eitdb);\n@@ -3848,10 +3855,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)\n \t\tvcpu-\u003erun-\u003ekvm_valid_regs |= KVM_SYNC_FPRS;\n \n \tif (kvm_is_ucontrol(vcpu-\u003ekvm)) {\n-\t\trc = -ENOMEM;\n \t\tvcpu-\u003earch.gmap = gmap_new_child(vcpu-\u003ekvm-\u003earch.gmap, -1UL);\n \t\tif (!vcpu-\u003earch.gmap)\n-\t\t\tgoto out_free_sie_block;\n+\t\t\treturn -ENOMEM;\n \t}\n \n \tVM_EVENT(vcpu-\u003ekvm, 3, \"create cpu %d at 0x%p, sie block at 0x%p\",\n@@ -3859,20 +3865,19 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)\n \ttrace_kvm_s390_create_vcpu(vcpu-\u003evcpu_id, vcpu, vcpu-\u003earch.sie_block);\n \n \trc = kvm_s390_vcpu_setup(vcpu);\n-\tif (rc)\n-\t\tgoto out_ucontrol_uninit;\n+\tif (rc) {\n+\t\tif (kvm_is_ucontrol(vcpu-\u003ekvm)) {\n+\t\t\tscoped_guard(spinlock, \u0026vcpu-\u003ekvm-\u003earch.gmap-\u003echildren_lock)\n+\t\t\t\tgmap_remove_child(vcpu-\u003earch.gmap);\n+\t\t\tvcpu-\u003earch.gmap = gmap_put(vcpu-\u003earch.gmap);\n+\t\t}\n+\t\treturn rc;\n+\t}\n \n+\tvcpu-\u003earch.mc = no_free_ptr(mc);\n+\tsie_page = NULL;\n \tkvm_s390_update_topology_change_report(vcpu-\u003ekvm, 1);\n \treturn 0;\n-\n-out_ucontrol_uninit:\n-\tif (kvm_is_ucontrol(vcpu-\u003ekvm)) {\n-\t\tgmap_remove_child(vcpu-\u003earch.gmap);\n-\t\tvcpu-\u003earch.gmap = gmap_put(vcpu-\u003earch.gmap);\n-\t}\n-out_free_sie_block:\n-\tfree_page((unsigned long)(vcpu-\u003earch.sie_block));\n-\treturn rc;\n }\n \n int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)\n@@ -5039,6 +5044,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)\n \t    kvm_run-\u003ekvm_dirty_regs \u0026 ~KVM_SYNC_S390_VALID_FIELDS)\n \t\treturn -EINVAL;\n \n+\t/* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */\n+\tif (!smp_load_acquire(\u0026vcpu-\u003earch.initialized))\n+\t\treturn -EINVAL;\n+\n \tvcpu_load(vcpu);\n \n \tif (guestdbg_exit_pending(vcpu)) {\n@@ -5523,6 +5532,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,\n \tlong r;\n \tu16 rc, rrc;\n \n+\t/* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */\n+\tif (!smp_load_acquire(\u0026vcpu-\u003earch.initialized))\n+\t\treturn -EINVAL;\n+\n \tvcpu_load(vcpu);\n \n \tswitch (ioctl) {\n@@ -5748,11 +5761,30 @@ bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)\n }\n \n /* Section: memory related */\n+static long cmma_d_count_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n+{\n+\tunion pgste pgste;\n+\n+\tpgste = pgste_get_lock(ptep);\n+\tif (pgste.cmma_d) {\n+\t\tpgste.cmma_d = 0;\n+\t\tatomic64_dec(walk-\u003epriv);\n+\t}\n+\tpgste_set_unlock(ptep, pgste);\n+\treturn 0;\n+}\n+\n int kvm_arch_prepare_memory_region(struct kvm *kvm,\n \t\t\t\t   const struct kvm_memory_slot *old,\n \t\t\t\t   struct kvm_memory_slot *new,\n \t\t\t\t   enum kvm_mr_change change)\n {\n+\tconst struct dat_walk_ops ops = { .pte_entry = cmma_d_count_pte, };\n+\tstruct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;\n+\tint rc = -ENOMEM;\n+\n+\tlockdep_assert_held(\u0026kvm-\u003eslots_arch_lock);\n+\n \tif (kvm_is_ucontrol(kvm) \u0026\u0026 new \u0026\u0026 new-\u003eid \u003c KVM_USER_MEM_SLOTS)\n \t\treturn -EINVAL;\n \n@@ -5775,43 +5807,35 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,\n \t\t\treturn -EINVAL;\n \t}\n \n-\tif (!kvm-\u003earch.migration_mode)\n-\t\treturn 0;\n-\n-\t/*\n-\t * Turn off migration mode when:\n-\t * - userspace creates a new memslot with dirty logging off,\n-\t * - userspace modifies an existing memslot (MOVE or FLAGS_ONLY) and\n-\t *   dirty logging is turned off.\n-\t * Migration mode expects dirty page logging being enabled to store\n-\t * its dirty bitmap.\n-\t */\n-\tif (change != KVM_MR_DELETE \u0026\u0026\n-\t    !(new-\u003eflags \u0026 KVM_MEM_LOG_DIRTY_PAGES))\n-\t\tWARN(kvm_s390_vm_stop_migration(kvm),\n-\t\t     \"Failed to stop migration mode\");\n-\n-\treturn 0;\n-}\n-\n-void kvm_arch_commit_memory_region(struct kvm *kvm,\n-\t\t\t\tstruct kvm_memory_slot *old,\n-\t\t\t\tconst struct kvm_memory_slot *new,\n-\t\t\t\tenum kvm_mr_change change)\n-{\n-\tstruct kvm_s390_mmu_cache *mc = NULL;\n-\tint rc = 0;\n+\tif (kvm-\u003earch.migration_mode) {\n+\t\t/*\n+\t\t * Turn off migration mode when:\n+\t\t * - userspace creates a new memslot with dirty logging off,\n+\t\t * - userspace modifies an existing memslot (MOVE or FLAGS_ONLY)\n+\t\t *   and dirty logging is turned off.\n+\t\t * Migration mode expects dirty page logging being enabled to\n+\t\t * store its dirty bitmap.\n+\t\t */\n+\t\tif (change != KVM_MR_DELETE \u0026\u0026\n+\t\t    !(new-\u003eflags \u0026 KVM_MEM_LOG_DIRTY_PAGES))\n+\t\t\tWARN(kvm_s390_vm_stop_migration(kvm),\n+\t\t\t     \"Failed to stop migration mode\");\n+\t}\n \n \tif (change == KVM_MR_FLAGS_ONLY)\n-\t\treturn;\n+\t\treturn 0;\n \n \tmc = kvm_s390_new_mmu_cache();\n-\tif (!mc) {\n-\t\trc = -ENOMEM;\n-\t\tgoto out;\n-\t}\n-\n+\tif (!mc)\n+\t\treturn -ENOMEM;\n+retry:\n \tscoped_guard(write_lock, \u0026kvm-\u003emmu_lock) {\n+\t\tif (kvm-\u003earch.migration_mode \u0026\u0026 kvm-\u003earch.use_cmma \u0026\u0026 old) {\n+\t\t\t_dat_walk_gfn_range(old-\u003ebase_gfn, old-\u003ebase_gfn + old-\u003enpages,\n+\t\t\t\t\t    kvm-\u003earch.gmap-\u003easce, \u0026ops, DAT_WALK_IGN_HOLES,\n+\t\t\t\t\t    \u0026kvm-\u003earch.cmma_dirty_pages);\n+\t\t}\n+\n \t\tswitch (change) {\n \t\tcase KVM_MR_DELETE:\n \t\t\trc = dat_delete_slot(mc, kvm-\u003earch.gmap-\u003easce, old-\u003ebase_gfn, old-\u003enpages);\n@@ -5827,14 +5851,21 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,\n \t\tcase KVM_MR_FLAGS_ONLY:\n \t\t\tbreak;\n \t\tdefault:\n+\t\t\trc = 0;\n \t\t\tWARN(1, \"Unknown KVM MR CHANGE: %d\\n\", change);\n \t\t}\n \t}\n-out:\n-\tif (rc)\n-\t\tpr_warn(\"failed to commit memory region\\n\");\n-\tkvm_s390_free_mmu_cache(mc);\n-\treturn;\n+\tif (rc == -ENOMEM) {\n+\t\trc = kvm_s390_mmu_cache_topup(mc);\n+\t\tif (!rc)\n+\t\t\tgoto retry;\n+\t}\n+\treturn rc;\n+}\n+\n+void kvm_arch_commit_memory_region(struct kvm *kvm, struct kvm_memory_slot *old,\n+\t\t\t\t   const struct kvm_memory_slot *new, enum kvm_mr_change change)\n+{\n }\n \n /**\ndiff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c\nindex ad0ddc433a73c..b1ba24c346efa 100644\n--- a/arch/s390/kvm/priv.c\n+++ b/arch/s390/kvm/priv.c\n@@ -289,6 +289,7 @@ static int handle_iske(struct kvm_vcpu *vcpu)\n static int handle_rrbe(struct kvm_vcpu *vcpu)\n {\n \tunsigned long gaddr;\n+\tunion skey skey;\n \tint reg1, reg2;\n \tint rc;\n \n@@ -307,12 +308,12 @@ static int handle_rrbe(struct kvm_vcpu *vcpu)\n \tgaddr = kvm_s390_logical_to_effective(vcpu, gaddr);\n \tgaddr = kvm_s390_real_to_abs(vcpu, gaddr);\n \tscoped_guard(read_lock, \u0026vcpu-\u003ekvm-\u003emmu_lock)\n-\t\trc = dat_reset_reference_bit(vcpu-\u003earch.gmap-\u003easce, gpa_to_gfn(gaddr));\n+\t\trc = dat_reset_reference_bit(vcpu-\u003earch.gmap-\u003easce, gpa_to_gfn(gaddr), \u0026skey);\n \tif (rc \u003e 0)\n \t\treturn kvm_s390_inject_program_int(vcpu, rc);\n \tif (rc \u003c 0)\n \t\treturn rc;\n-\tkvm_s390_set_psw_cc(vcpu, rc);\n+\tkvm_s390_set_psw_cc(vcpu, (skey.skey \u003e\u003e 1) \u0026 3);\n \treturn 0;\n }\n \n@@ -1260,8 +1261,9 @@ static int handle_essa(struct kvm_vcpu *vcpu)\n \t\t/* Retry the ESSA instruction */\n \t\tkvm_s390_retry_instr(vcpu);\n \t} else {\n-\t\tscoped_guard(read_lock, \u0026vcpu-\u003ekvm-\u003emmu_lock)\n-\t\t\ti = __do_essa(vcpu, orc);\n+\t\tscoped_guard(mutex, \u0026vcpu-\u003ekvm-\u003eslots_arch_lock)\n+\t\t\tscoped_guard(read_lock, \u0026vcpu-\u003ekvm-\u003emmu_lock)\n+\t\t\t\ti = __do_essa(vcpu, orc);\n \t\tif (i \u003c 0)\n \t\t\treturn i;\n \t\t/* Account for the possible extra cbrl entry */\ndiff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c\nindex 1beacc841ca85..b02e0159d3cd2 100644\n--- a/arch/s390/kvm/pv.c\n+++ b/arch/s390/kvm/pv.c\n@@ -244,6 +244,24 @@ static void kvm_s390_clear_pv_state(struct kvm *kvm)\n \tkvm-\u003earch.pv.stor_var = NULL;\n }\n \n+static void kvm_s390_pv_dispose_cpu(struct kvm_vcpu *vcpu, bool free_stor_base)\n+{\n+\tif (free_stor_base)\n+\t\tfree_pages(vcpu-\u003earch.pv.stor_base, get_order(uv_info.guest_cpu_stor_len));\n+\tfree_page((unsigned long)sida_addr(vcpu-\u003earch.sie_block));\n+\tvcpu-\u003earch.sie_block-\u003epv_handle_cpu = 0;\n+\tvcpu-\u003earch.sie_block-\u003epv_handle_config = 0;\n+\tmemset(\u0026vcpu-\u003earch.pv, 0, sizeof(vcpu-\u003earch.pv));\n+\tvcpu-\u003earch.sie_block-\u003esdf = 0;\n+\t/*\n+\t * The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).\n+\t * Use the reset value of gbea to avoid leaking the kernel pointer of\n+\t * the just freed sida.\n+\t */\n+\tvcpu-\u003earch.sie_block-\u003egbea = 1;\n+\tkvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);\n+}\n+\n int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)\n {\n \tint cc;\n@@ -258,24 +276,9 @@ int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)\n \tWARN_ONCE(cc, \"protvirt destroy cpu failed rc %x rrc %x\", *rc, *rrc);\n \n \t/* Intended memory leak for something that should never happen. */\n-\tif (!cc)\n-\t\tfree_pages(vcpu-\u003earch.pv.stor_base,\n-\t\t\t   get_order(uv_info.guest_cpu_stor_len));\n-\n-\tfree_page((unsigned long)sida_addr(vcpu-\u003earch.sie_block));\n-\tvcpu-\u003earch.sie_block-\u003epv_handle_cpu = 0;\n-\tvcpu-\u003earch.sie_block-\u003epv_handle_config = 0;\n-\tmemset(\u0026vcpu-\u003earch.pv, 0, sizeof(vcpu-\u003earch.pv));\n-\tvcpu-\u003earch.sie_block-\u003esdf = 0;\n-\t/*\n-\t * The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).\n-\t * Use the reset value of gbea to avoid leaking the kernel pointer of\n-\t * the just freed sida.\n-\t */\n-\tvcpu-\u003earch.sie_block-\u003egbea = 1;\n-\tkvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);\n+\tkvm_s390_pv_dispose_cpu(vcpu, !cc);\n \n-\treturn cc ? EIO : 0;\n+\treturn cc ? -EIO : 0;\n }\n \n int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)\n@@ -319,9 +322,7 @@ int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)\n \t\t     uvcb.header.rrc);\n \n \tif (cc) {\n-\t\tu16 dummy;\n-\n-\t\tkvm_s390_pv_destroy_cpu(vcpu, \u0026dummy, \u0026dummy);\n+\t\tkvm_s390_pv_dispose_cpu(vcpu, true);\n \t\treturn -EIO;\n \t}\n \n@@ -809,7 +810,7 @@ static int unpack_one(struct kvm *kvm, unsigned long addr, u64 tweak,\n \t\t\treturn -EAGAIN;\n \t}\n \n-\tif (ret \u0026\u0026 ret != -EAGAIN)\n+\tif (ret \u0026\u0026 ret != -EAGAIN \u0026\u0026 ret != -EINTR)\n \t\tKVM_UV_EVENT(kvm, 3, \"PROTVIRT VM UNPACK: failed addr %llx with rc %x rrc %x\",\n \t\t\t     uvcb.gaddr, *rc, *rrc);\n \treturn ret;\n"
}

2/1 2026/08/01 06:42 agent patch-evaluator
2m Model:
best-expensive

Args:
null

Results:
{
  "EnableConfigs": [
    "KVM"
  ],
  "FocusSymbols": [
    "kvm_arch_vm_ioctl",
    "kvm_arch_vcpu_create",
    "kvm_arch_vcpu_postcreate",
    "kvm_arch_commit_memory_region",
    "kvm_arch_prepare_memory_region",
    "kvm_s390_pv_create_cpu",
    "kvm_s390_pv_destroy_cpu",
    "dat_reset_reference_bit",
    "kvm_s390_faultin_gfn"
  ],
  "Reasoning": "The patch makes functional changes to the s390 KVM subsystem, including fixes for memory leaks, locking, initialization races, and signal handling during page faults. It modifies core KVM ioctls, memory region management, and Protected Virtualization (PV) CPU lifecycle functions. These changes are reachable from userspace via KVM ioctls and memory accesses, making them suitable for 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).
- 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 667b22eb9c3398191ed1f90d35965dcc68eaf913
Author: syz-cluster <triage@syzkaller.com>
Date:   Sat Aug 1 06:42:53 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 eaa34c5bd3c11..edf75b6ad20ce 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -440,6 +440,7 @@ struct kvm_vcpu_arch {
 	bool skey_enabled;
 	/* Indicator if the access registers have been loaded from guest */
 	bool acrs_loaded;
+	bool initialized;
 	struct kvm_s390_pv_vcpu pv;
 	union diag318_info diag318_info;
 	struct kvm_s390_mmu_cache *mc;
diff --git a/arch/s390/kvm/dat.c b/arch/s390/kvm/dat.c
index ed4259d176295..3f2d6e8902d76 100644
--- a/arch/s390/kvm/dat.c
+++ b/arch/s390/kvm/dat.c
@@ -755,13 +755,15 @@ int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gf
 	return rc;
 }
 
-int dat_reset_reference_bit(union asce asce, gfn_t gfn)
+int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey)
 {
 	union pgste pgste, old;
 	union crste *crstep;
 	union pte *ptep;
 	int rc;
 
+	skey->skey = 0;
+
 	rc = dat_entry_walk(NULL, gfn, asce, DAT_WALK_ANY, TABLE_TYPE_PAGE_TABLE, &crstep, &ptep);
 	if (rc)
 		return rc;
@@ -771,21 +773,23 @@ int dat_reset_reference_bit(union asce asce, gfn_t gfn)
 
 		if (!crste.h.fc || !crste.s.fc1.pr)
 			return 0;
-		return page_reset_referenced(large_crste_to_phys(*crstep, gfn));
+		skey->skey = page_reset_referenced(large_crste_to_phys(*crstep, gfn)) << 1;
+		return 0;
 	}
 	old = pgste_get_lock(ptep);
 	pgste = old;
 
 	if (!ptep->h.i) {
-		rc = page_reset_referenced(pte_origin(*ptep));
-		pgste.hr = rc >> 1;
+		skey->skey = page_reset_referenced(pte_origin(*ptep)) << 1;
+		pgste.hr = skey->r;
 	}
-	rc |= (pgste.gr << 1) | pgste.gc;
+	skey->r |= pgste.gr;
+	skey->c |= pgste.gc;
 	pgste.gr = 0;
 
 	dat_update_ptep_sd(old, pgste, ptep);
 	pgste_set_unlock(ptep, pgste);
-	return rc;
+	return 0;
 }
 
 static long dat_reset_skeys_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
@@ -846,6 +850,7 @@ static long _dat_slot_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_wal
 	struct slot_priv *p = walk->priv;
 	union crste dummy = { .val = p->token };
 	union pte new_pte, pte = READ_ONCE(*ptep);
+	union pgste pgste;
 
 	new_pte = _PTE_TOK(dummy.tok.type, dummy.tok.par);
 
@@ -853,7 +858,11 @@ static long _dat_slot_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_wal
 	if (pte.val == new_pte.val)
 		return 0;
 
-	dat_ptep_xchg(ptep, new_pte, gfn, walk->asce, false);
+	pgste = pgste_get_lock(ptep);
+	pgste = __dat_ptep_xchg(ptep, pgste, new_pte, gfn, walk->asce, false);
+	pgste.cmma_d = 0;
+	pgste_set_unlock(ptep, pgste);
+
 	return 0;
 }
 
diff --git a/arch/s390/kvm/dat.h b/arch/s390/kvm/dat.h
index fad605305e05c..141ee7b9f0191 100644
--- a/arch/s390/kvm/dat.h
+++ b/arch/s390/kvm/dat.h
@@ -537,7 +537,7 @@ int dat_set_storage_key(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t gf
 			union skey skey, bool nq);
 int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gfn_t gfn,
 			     union skey skey, union skey *oldkey, bool nq, bool mr, bool mc);
-int dat_reset_reference_bit(union asce asce, gfn_t gfn);
+int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey);
 long dat_reset_skeys(union asce asce, gfn_t start);
 
 unsigned long dat_get_ptval(struct page_table *table, struct ptval_param param);
diff --git a/arch/s390/kvm/faultin.c b/arch/s390/kvm/faultin.c
index fee80047bd94f..3cc45f7f5b2d7 100644
--- a/arch/s390/kvm/faultin.c
+++ b/arch/s390/kvm/faultin.c
@@ -91,9 +91,9 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
 		/* Access outside memory, addressing exception. */
 		if (is_noslot_pfn(f->pfn))
 			return PGM_ADDRESSING;
-		/* Signal pending: try again. */
-		if (f->pfn == KVM_PFN_ERR_SIGPENDING)
-			return -EAGAIN;
+		/* Fatal signal pending: bail out. */
+		if (is_sigpending_pfn(f->pfn))
+			return -EINTR;
 		/* Check if it's read-only memory; don't try to actually handle that case. */
 		if (f->pfn == KVM_PFN_ERR_RO_FAULT)
 			return -EOPNOTSUPP;
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 9e3e6b0d72ad6..6013f28e3461f 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -45,13 +45,16 @@ static struct kvm_s390_gib *gib;
 static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
 {
 	struct esca_block *sca = vcpu->kvm->arch.sca;
-	union esca_sigp_ctrl sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
+	union esca_sigp_ctrl sigp_ctrl;
 
 	if (!kvm_s390_test_cpuflags(vcpu, CPUSTAT_ECALL_PEND))
 		return 0;
 
+	if (KVM_BUG_ON(kvm_is_ucontrol(vcpu->kvm), vcpu->kvm))
+		return -EINVAL;
 	BUG_ON(!kvm_s390_use_sca_entries());
 
+	sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
 	if (src_id)
 		*src_id = sigp_ctrl.scn;
 
@@ -60,13 +63,16 @@ static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
 
 static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
 {
-	struct esca_block *sca = vcpu->kvm->arch.sca;
-	union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
 	union esca_sigp_ctrl old_val, new_val = {.scn = src_id, .c = 1};
+	struct esca_block *sca = vcpu->kvm->arch.sca;
+	union esca_sigp_ctrl *sigp_ctrl;
 	int expect, rc;
 
 	BUG_ON(!kvm_s390_use_sca_entries());
+	if (KVM_BUG_ON(kvm_is_ucontrol(vcpu->kvm), vcpu->kvm))
+		return -EINVAL;
 
+	sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
 	old_val = READ_ONCE(*sigp_ctrl);
 	old_val.c = 0;
 
@@ -84,10 +90,13 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
 static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
 {
 	struct esca_block *sca = vcpu->kvm->arch.sca;
-	union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
+	union esca_sigp_ctrl *sigp_ctrl;
 
-	if (!kvm_s390_use_sca_entries())
+	if (!kvm_s390_use_sca_entries() || !vcpu->arch.initialized || kvm_is_ucontrol(vcpu->kvm))
 		return;
+
+	/* Initialize after the above check, to prevent going out of bounds */
+	sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
 	kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
 
 	WRITE_ONCE(sigp_ctrl->value, 0);
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 150b5dd2170e2..668272dffa18b 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -571,7 +571,7 @@ static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op
 	switch (op) {
 	case KVM_S390_KEYOP_SSKE:
 		r = dat_cond_set_storage_key(mc, asce, gfn, skey, &skey, 0, 0, 0);
-		if (r >= 0)
+		if (r == 0 || r == 1)
 			return skey.skey;
 		break;
 	case KVM_S390_KEYOP_ISKE:
@@ -580,14 +580,14 @@ static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op
 			return skey.skey;
 		break;
 	case KVM_S390_KEYOP_RRBE:
-		r = dat_reset_reference_bit(asce, gfn);
-		if (r > 0)
-			return r << 1;
+		r = dat_reset_reference_bit(asce, gfn, &skey);
+		if (!r)
+			return skey.skey;
 		break;
 	default:
 		return -EINVAL;
 	}
-	return r;
+	return r > 0 ? -EFAULT : r;
 }
 
 /* Section: device related */
@@ -1219,8 +1219,8 @@ static void kvm_s390_sync_request_broadcast(struct kvm *kvm, int req)
 
 /*
  * Must be called with kvm->srcu held to avoid races on memslots, and with
- * kvm->slots_lock to avoid races with ourselves, kvm_s390_vm_stop_migration(),
- * and kvm_s390_get_cmma_bits().
+ * kvm->slots_arch_lock to avoid races with ourselves,
+ * kvm_s390_vm_stop_migration(), and kvm_s390_get_cmma_bits().
  */
 static int kvm_s390_vm_start_migration(struct kvm *kvm)
 {
@@ -1265,7 +1265,7 @@ static int kvm_s390_vm_start_migration(struct kvm *kvm)
 }
 
 /*
- * Must be called with kvm->slots_lock to avoid races with ourselves,
+ * Must be called with kvm->slots_arch_lock to avoid races with ourselves,
  * kvm_s390_vm_start_migration() and kvm_s390_get_cmma_bits().
  */
 static int kvm_s390_vm_stop_migration(struct kvm *kvm)
@@ -1300,7 +1300,9 @@ static int kvm_s390_vm_set_migration(struct kvm *kvm,
 {
 	int res = -ENXIO;
 
-	mutex_lock(&kvm->slots_lock);
+	guard(srcu)(&kvm->srcu);
+	guard(mutex)(&kvm->slots_arch_lock);
+
 	switch (attr->attr) {
 	case KVM_S390_VM_MIGRATION_START:
 		res = kvm_s390_vm_start_migration(kvm);
@@ -1311,7 +1313,6 @@ static int kvm_s390_vm_set_migration(struct kvm *kvm,
 	default:
 		break;
 	}
-	mutex_unlock(&kvm->slots_lock);
 
 	return res;
 }
@@ -2214,7 +2215,7 @@ static int kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
 	}
 
 	kvfree(keys);
-	return r;
+	return r <= 0 ? r : -EFAULT;
 }
 
 static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
@@ -2276,7 +2277,7 @@ static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
 	kvm_s390_free_mmu_cache(mc);
 out:
 	kvfree(keys);
-	return r;
+	return r <= 0 ? r : -EFAULT;
 }
 
 /*
@@ -2386,7 +2387,7 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,
 
 	set_bit(GMAP_FLAG_USES_CMM, &kvm->arch.gmap->flags);
 
-	return r;
+	return r <= 0 ? r : -EFAULT;
 }
 
 /**
@@ -2934,6 +2935,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
 	case KVM_S390_INTERRUPT: {
 		struct kvm_s390_interrupt s390int;
 
+		r = -EINVAL;
+		if (kvm_is_ucontrol(kvm))
+			break;
 		r = -EFAULT;
 		if (copy_from_user(&s390int, argp, sizeof(s390int)))
 			break;
@@ -2998,9 +3002,8 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
 		r = -EFAULT;
 		if (copy_from_user(&args, argp, sizeof(args)))
 			break;
-		mutex_lock(&kvm->slots_lock);
-		r = kvm_s390_get_cmma_bits(kvm, &args);
-		mutex_unlock(&kvm->slots_lock);
+		scoped_guard(mutex, &kvm->slots_arch_lock)
+			r = kvm_s390_get_cmma_bits(kvm, &args);
 		if (!r) {
 			r = copy_to_user(argp, &args, sizeof(args));
 			if (r)
@@ -3014,9 +3017,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
 		r = -EFAULT;
 		if (copy_from_user(&args, argp, sizeof(args)))
 			break;
-		mutex_lock(&kvm->slots_lock);
+		mutex_lock(&kvm->slots_arch_lock);
 		r = kvm_s390_set_cmma_bits(kvm, &args);
-		mutex_unlock(&kvm->slots_lock);
+		mutex_unlock(&kvm->slots_arch_lock);
 		break;
 	}
 	case KVM_S390_PV_COMMAND: {
@@ -3461,7 +3464,7 @@ static void sca_del_vcpu(struct kvm_vcpu *vcpu)
 {
 	struct esca_block *sca = vcpu->kvm->arch.sca;
 
-	if (!kvm_s390_use_sca_entries())
+	if (!kvm_s390_use_sca_entries() || !vcpu->arch.initialized)
 		return;
 
 	clear_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
@@ -3481,8 +3484,8 @@ static void sca_add_vcpu(struct kvm_vcpu *vcpu)
 	if (!kvm_s390_use_sca_entries())
 		return;
 
+	WRITE_ONCE(sca->cpu[vcpu->vcpu_id].sda, virt_to_phys(vcpu->arch.sie_block));
 	set_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
-	sca->cpu[vcpu->vcpu_id].sda = virt_to_phys(vcpu->arch.sie_block);
 }
 
 static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)
@@ -3613,6 +3616,9 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
 	if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0 ||
 	    vcpu->kvm->arch.user_operexec)
 		vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
+
+	/* Pairs with smp_load_acquire() in kvm_arch_vcpu_ioctl_run() and kvm_arch_vcpu_ioctl() */
+	smp_store_release(&vcpu->arch.initialized, true);
 }
 
 static bool kvm_has_pckmo_subfunc(struct kvm *kvm, unsigned long nr)
@@ -3674,7 +3680,8 @@ static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
 
 void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu)
 {
-	free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
+	if (vcpu->arch.sie_block->cbrlo)
+		free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
 	vcpu->arch.sie_block->cbrlo = 0;
 }
 
@@ -3792,21 +3799,21 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
 	return 0;
 }
 
+DEFINE_FREE(sie_page, struct sie_page *, if (_T) free_page((unsigned long)(_T)))
+
 int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
 {
-	struct sie_page *sie_page;
+	struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
+	struct sie_page *sie_page __free(sie_page) = NULL;
 	int rc;
 
 	BUILD_BUG_ON(sizeof(struct sie_page) != 4096);
-	vcpu->arch.mc = kvm_s390_new_mmu_cache();
-	if (!vcpu->arch.mc)
+	mc = kvm_s390_new_mmu_cache();
+	if (!mc)
 		return -ENOMEM;
 	sie_page = (struct sie_page *) get_zeroed_page(GFP_KERNEL_ACCOUNT);
-	if (!sie_page) {
-		kvm_s390_free_mmu_cache(vcpu->arch.mc);
-		vcpu->arch.mc = NULL;
+	if (!sie_page)
 		return -ENOMEM;
-	}
 
 	vcpu->arch.sie_block = &sie_page->sie_block;
 	vcpu->arch.sie_block->itdba = virt_to_phys(&sie_page->itdb);
@@ -3848,10 +3855,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
 		vcpu->run->kvm_valid_regs |= KVM_SYNC_FPRS;
 
 	if (kvm_is_ucontrol(vcpu->kvm)) {
-		rc = -ENOMEM;
 		vcpu->arch.gmap = gmap_new_child(vcpu->kvm->arch.gmap, -1UL);
 		if (!vcpu->arch.gmap)
-			goto out_free_sie_block;
+			return -ENOMEM;
 	}
 
 	VM_EVENT(vcpu->kvm, 3, "create cpu %d at 0x%p, sie block at 0x%p",
@@ -3859,20 +3865,19 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
 	trace_kvm_s390_create_vcpu(vcpu->vcpu_id, vcpu, vcpu->arch.sie_block);
 
 	rc = kvm_s390_vcpu_setup(vcpu);
-	if (rc)
-		goto out_ucontrol_uninit;
+	if (rc) {
+		if (kvm_is_ucontrol(vcpu->kvm)) {
+			scoped_guard(spinlock, &vcpu->kvm->arch.gmap->children_lock)
+				gmap_remove_child(vcpu->arch.gmap);
+			vcpu->arch.gmap = gmap_put(vcpu->arch.gmap);
+		}
+		return rc;
+	}
 
+	vcpu->arch.mc = no_free_ptr(mc);
+	sie_page = NULL;
 	kvm_s390_update_topology_change_report(vcpu->kvm, 1);
 	return 0;
-
-out_ucontrol_uninit:
-	if (kvm_is_ucontrol(vcpu->kvm)) {
-		gmap_remove_child(vcpu->arch.gmap);
-		vcpu->arch.gmap = gmap_put(vcpu->arch.gmap);
-	}
-out_free_sie_block:
-	free_page((unsigned long)(vcpu->arch.sie_block));
-	return rc;
 }
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
@@ -5039,6 +5044,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
 	    kvm_run->kvm_dirty_regs & ~KVM_SYNC_S390_VALID_FIELDS)
 		return -EINVAL;
 
+	/* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */
+	if (!smp_load_acquire(&vcpu->arch.initialized))
+		return -EINVAL;
+
 	vcpu_load(vcpu);
 
 	if (guestdbg_exit_pending(vcpu)) {
@@ -5523,6 +5532,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 	long r;
 	u16 rc, rrc;
 
+	/* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */
+	if (!smp_load_acquire(&vcpu->arch.initialized))
+		return -EINVAL;
+
 	vcpu_load(vcpu);
 
 	switch (ioctl) {
@@ -5748,11 +5761,30 @@ bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)
 }
 
 /* Section: memory related */
+static long cmma_d_count_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
+{
+	union pgste pgste;
+
+	pgste = pgste_get_lock(ptep);
+	if (pgste.cmma_d) {
+		pgste.cmma_d = 0;
+		atomic64_dec(walk->priv);
+	}
+	pgste_set_unlock(ptep, pgste);
+	return 0;
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				   const struct kvm_memory_slot *old,
 				   struct kvm_memory_slot *new,
 				   enum kvm_mr_change change)
 {
+	const struct dat_walk_ops ops = { .pte_entry = cmma_d_count_pte, };
+	struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
+	int rc = -ENOMEM;
+
+	lockdep_assert_held(&kvm->slots_arch_lock);
+
 	if (kvm_is_ucontrol(kvm) && new && new->id < KVM_USER_MEM_SLOTS)
 		return -EINVAL;
 
@@ -5775,43 +5807,35 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 			return -EINVAL;
 	}
 
-	if (!kvm->arch.migration_mode)
-		return 0;
-
-	/*
-	 * Turn off migration mode when:
-	 * - userspace creates a new memslot with dirty logging off,
-	 * - userspace modifies an existing memslot (MOVE or FLAGS_ONLY) and
-	 *   dirty logging is turned off.
-	 * Migration mode expects dirty page logging being enabled to store
-	 * its dirty bitmap.
-	 */
-	if (change != KVM_MR_DELETE &&
-	    !(new->flags & KVM_MEM_LOG_DIRTY_PAGES))
-		WARN(kvm_s390_vm_stop_migration(kvm),
-		     "Failed to stop migration mode");
-
-	return 0;
-}
-
-void kvm_arch_commit_memory_region(struct kvm *kvm,
-				struct kvm_memory_slot *old,
-				const struct kvm_memory_slot *new,
-				enum kvm_mr_change change)
-{
-	struct kvm_s390_mmu_cache *mc = NULL;
-	int rc = 0;
+	if (kvm->arch.migration_mode) {
+		/*
+		 * Turn off migration mode when:
+		 * - userspace creates a new memslot with dirty logging off,
+		 * - userspace modifies an existing memslot (MOVE or FLAGS_ONLY)
+		 *   and dirty logging is turned off.
+		 * Migration mode expects dirty page logging being enabled to
+		 * store its dirty bitmap.
+		 */
+		if (change != KVM_MR_DELETE &&
+		    !(new->flags & KVM_MEM_LOG_DIRTY_PAGES))
+			WARN(kvm_s390_vm_stop_migration(kvm),
+			     "Failed to stop migration mode");
+	}
 
 	if (change == KVM_MR_FLAGS_ONLY)
-		return;
+		return 0;
 
 	mc = kvm_s390_new_mmu_cache();
-	if (!mc) {
-		rc = -ENOMEM;
-		goto out;
-	}
-
+	if (!mc)
+		return -ENOMEM;
+retry:
 	scoped_guard(write_lock, &kvm->mmu_lock) {
+		if (kvm->arch.migration_mode && kvm->arch.use_cmma && old) {
+			_dat_walk_gfn_range(old->base_gfn, old->base_gfn + old->npages,
+					    kvm->arch.gmap->asce, &ops, DAT_WALK_IGN_HOLES,
+					    &kvm->arch.cmma_dirty_pages);
+		}
+
 		switch (change) {
 		case KVM_MR_DELETE:
 			rc = dat_delete_slot(mc, kvm->arch.gmap->asce, old->base_gfn, old->npages);
@@ -5827,14 +5851,21 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 		case KVM_MR_FLAGS_ONLY:
 			break;
 		default:
+			rc = 0;
 			WARN(1, "Unknown KVM MR CHANGE: %d\n", change);
 		}
 	}
-out:
-	if (rc)
-		pr_warn("failed to commit memory region\n");
-	kvm_s390_free_mmu_cache(mc);
-	return;
+	if (rc == -ENOMEM) {
+		rc = kvm_s390_mmu_cache_topup(mc);
+		if (!rc)
+			goto retry;
+	}
+	return rc;
+}
+
+void kvm_arch_commit_memory_region(struct kvm *kvm, struct kvm_memory_slot *old,
+				   const struct kvm_memory_slot *new, enum kvm_mr_change change)
+{
 }
 
 /**
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index ad0ddc433a73c..b1ba24c346efa 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -289,6 +289,7 @@ static int handle_iske(struct kvm_vcpu *vcpu)
 static int handle_rrbe(struct kvm_vcpu *vcpu)
 {
 	unsigned long gaddr;
+	union skey skey;
 	int reg1, reg2;
 	int rc;
 
@@ -307,12 +308,12 @@ static int handle_rrbe(struct kvm_vcpu *vcpu)
 	gaddr = kvm_s390_logical_to_effective(vcpu, gaddr);
 	gaddr = kvm_s390_real_to_abs(vcpu, gaddr);
 	scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
-		rc = dat_reset_reference_bit(vcpu->arch.gmap->asce, gpa_to_gfn(gaddr));
+		rc = dat_reset_reference_bit(vcpu->arch.gmap->asce, gpa_to_gfn(gaddr), &skey);
 	if (rc > 0)
 		return kvm_s390_inject_program_int(vcpu, rc);
 	if (rc < 0)
 		return rc;
-	kvm_s390_set_psw_cc(vcpu, rc);
+	kvm_s390_set_psw_cc(vcpu, (skey.skey >> 1) & 3);
 	return 0;
 }
 
@@ -1260,8 +1261,9 @@ static int handle_essa(struct kvm_vcpu *vcpu)
 		/* Retry the ESSA instruction */
 		kvm_s390_retry_instr(vcpu);
 	} else {
-		scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
-			i = __do_essa(vcpu, orc);
+		scoped_guard(mutex, &vcpu->kvm->slots_arch_lock)
+			scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
+				i = __do_essa(vcpu, orc);
 		if (i < 0)
 			return i;
 		/* Account for the possible extra cbrl entry */
diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c
index 1beacc841ca85..b02e0159d3cd2 100644
--- a/arch/s390/kvm/pv.c
+++ b/arch/s390/kvm/pv.c
@@ -244,6 +244,24 @@ static void kvm_s390_clear_pv_state(struct kvm *kvm)
 	kvm->arch.pv.stor_var = NULL;
 }
 
+static void kvm_s390_pv_dispose_cpu(struct kvm_vcpu *vcpu, bool free_stor_base)
+{
+	if (free_stor_base)
+		free_pages(vcpu->arch.pv.stor_base, get_order(uv_info.guest_cpu_stor_len));
+	free_page((unsigned long)sida_addr(vcpu->arch.sie_block));
+	vcpu->arch.sie_block->pv_handle_cpu = 0;
+	vcpu->arch.sie_block->pv_handle_config = 0;
+	memset(&vcpu->arch.pv, 0, sizeof(vcpu->arch.pv));
+	vcpu->arch.sie_block->sdf = 0;
+	/*
+	 * The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).
+	 * Use the reset value of gbea to avoid leaking the kernel pointer of
+	 * the just freed sida.
+	 */
+	vcpu->arch.sie_block->gbea = 1;
+	kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+}
+
 int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
 {
 	int cc;
@@ -258,24 +276,9 @@ int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
 	WARN_ONCE(cc, "protvirt destroy cpu failed rc %x rrc %x", *rc, *rrc);
 
 	/* Intended memory leak for something that should never happen. */
-	if (!cc)
-		free_pages(vcpu->arch.pv.stor_base,
-			   get_order(uv_info.guest_cpu_stor_len));
-
-	free_page((unsigned long)sida_addr(vcpu->arch.sie_block));
-	vcpu->arch.sie_block->pv_handle_cpu = 0;
-	vcpu->arch.sie_block->pv_handle_config = 0;
-	memset(&vcpu->arch.pv, 0, sizeof(vcpu->arch.pv));
-	vcpu->arch.sie_block->sdf = 0;
-	/*
-	 * The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).
-	 * Use the reset value of gbea to avoid leaking the kernel pointer of
-	 * the just freed sida.
-	 */
-	vcpu->arch.sie_block->gbea = 1;
-	kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+	kvm_s390_pv_dispose_cpu(vcpu, !cc);
 
-	return cc ? EIO : 0;
+	return cc ? -EIO : 0;
 }
 
 int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
@@ -319,9 +322,7 @@ int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
 		     uvcb.header.rrc);
 
 	if (cc) {
-		u16 dummy;
-
-		kvm_s390_pv_destroy_cpu(vcpu, &dummy, &dummy);
+		kvm_s390_pv_dispose_cpu(vcpu, true);
 		return -EIO;
 	}
 
@@ -809,7 +810,7 @@ static int unpack_one(struct kvm *kvm, unsigned long addr, u64 tweak,
 			return -EAGAIN;
 	}
 
-	if (ret && ret != -EAGAIN)
+	if (ret && ret != -EAGAIN && ret != -EINTR)
 		KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: failed addr %llx with rc %x rrc %x",
 			     uvcb.gaddr, *rc, *rrc);
 	return ret;

3/2 2026/08/01 06:42 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 12293
							output: 51
							thoughts: 1707
						

Thoughts:
**Analyzing the s390 KVM Patch**

Alright, let's dive into this patch targeting s390 KVM. My initial assessment suggests a set of refinements and fixes across several critical areas. First, I see a new boolean, `initialized`, being introduced within `struct kvm_vcpu_arch`. This likely addresses initialization races. Then I am going to see how `dat_reset_reference_bit` is now taking a `union skey *skey` parameter and returning the skey via pointer and also how `_dat_slot_pte` clears `pgste.cmma_d` during PTE exchanges. These indicate changes in Secure Key management and CMMAs.

The change in `kvm_s390_faultin_gfn` is immediately apparent. We're shifting from retrying on `KVM_PFN_ERR_SIGPENDING` to bailing out with `EINTR` when a fatal signal is pending. This is a sensible change in error handling.

The introduction of checks for `kvm_is_ucontrol(vcpu->kvm)` and `vcpu->arch.initialized` within the interrupt handling functions (`sca_ext_call_pending`, `sca_inject_ext_call`, and `sca_clear_ext_call`) immediately captures my attention. This suggests tighter control and potentially security-related refinements for User Control scenarios.

Looking at `kvm-s390.c`, I see that `kvm_s390_keyop` is updated to the new `dat_reset_reference_bit` signature. The locking strategy for `kvm_s390_vm_set_migration` appears to be refined, shifting to `srcu` and `mutex` guards, which could have implications on concurrency. The error return values have been homogenized to `-EFAULT` in several `kvm_s390_` functions. The use of `slots_arch_lock` consistently within the relevant ioctls and the sca functions for adding and deleting vCPUs seems to be a significant locking strategy change. Importantly, I note the use of `smp_store_release` when setting `vcpu->arch.initialized = true`, which is crucial for memory ordering. The cleanup in `kvm_arch_vcpu_create` leveraging `__free` macros and the different handling of `kvm_is_ucontrol` are also interesting. The checks of `smp_load_acquire` in the run and ioctl are important to ensure that the initialization order is correct. Finally, the refactoring of memory region preparation and commit looks significant, with `kvm_arch_commit_memory_region` now handling migration and CMMA modes in conjunction with `_dat_walk_gfn_range`.

The code within `priv.c` confirms the new `dat_reset_reference_bit` signature is in use and that `slots_arch_lock` is now being taken around the `__do_essa` in `handle_essa`.

And finally, `pv.c` shows function re-arrangement for CPU disposal and that `-EINTR` handling in `unpack_one`.

In summary, this seems to be a functional change to the s390 KVM subsystem, and it's certainly worth fuzzing to uncover any remaining issues. Since syzkaller supports s390x and KVM on s390x, that seems like a viable path.

Now, let's identify the key focus symbols for fuzzing. Ideally, these should be non-static, non-inlined API entrypoints. Given the patch, some promising candidates include:

*   `kvm_arch_vm_ioctl`: A general ioctl entrypoint.
*   `kvm_s390_pv_create_cpu`: Non-static and seems to be a good entry point.
*   `kvm_s390_pv_destroy_cpu`: Non-static and seems to be a good entry point.
*   `dat_reset_reference_bit`: Non-static and part of a significant data structure change.
*   `kvm_arch_commit_memory_region`: Also modified significantly.

I'll quickly double-check the Kconfig options to confirm that CONFIG\_KVM is set, and confirm these non-static functions exists.



4/2 2026/08/01 06:43 tool grepper
0m Args:
{
  "Expression": "^(int|void|long|bool) [a-zA-Z0-9_]+\\(",
  "PathPrefix": "arch/s390/kvm/"
}

Results:
{
  "Output": "\nFull output is too long, showing 500 out of 1354 lines.\nUse more precise expression if possible.\n\narch/s390/kvm/dat.c-30-\narch/s390/kvm/dat.c:31:int kvm_s390_mmu_cache_topup(struct kvm_s390_mmu_cache *mc)\narch/s390/kvm/dat.c-32-{\n--\narch/s390/kvm/dat.c=76=struct crst_table *dat_alloc_crst_sleepable(unsigned long init)\n--\narch/s390/kvm/dat.c-89-\narch/s390/kvm/dat.c:90:void dat_free_level(struct crst_table *table, bool owns_ptes)\narch/s390/kvm/dat.c-91-{\n--\narch/s390/kvm/dat.c-104-\narch/s390/kvm/dat.c:105:int dat_set_asce_limit(struct kvm_s390_mmu_cache *mc, union asce *asce, int newtype)\narch/s390/kvm/dat.c-106-{\n--\narch/s390/kvm/dat.c=302=static int dat_split_crste(struct kvm_s390_mmu_cache *mc, union crste *crstep,\n--\narch/s390/kvm/dat.c-378- */\narch/s390/kvm/dat.c:379:int dat_entry_walk(struct kvm_s390_mmu_cache *mc, gfn_t gfn, union asce asce, int flags,\narch/s390/kvm/dat.c-380-\t\t   int walk_level, union crste **last, union pte **ptepp)\n--\narch/s390/kvm/dat.c=534=static long dat_crste_walk_range(gfn_t start, gfn_t end, struct crst_table *table,\n--\narch/s390/kvm/dat.c-594- */\narch/s390/kvm/dat.c:595:long _dat_walk_gfn_range(gfn_t start, gfn_t end, union asce asce,\narch/s390/kvm/dat.c-596-\t\t\t const struct dat_walk_ops *ops, int flags, void *priv)\n--\narch/s390/kvm/dat.c-615-\narch/s390/kvm/dat.c:616:int dat_get_storage_key(union asce asce, gfn_t gfn, union skey *skey)\narch/s390/kvm/dat.c-617-{\n--\narch/s390/kvm/dat.c=650=static void dat_update_ptep_sd(union pgste old, union pgste pgste, union pte *ptep)\n--\narch/s390/kvm/dat.c-655-\narch/s390/kvm/dat.c:656:int dat_set_storage_key(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t gfn,\narch/s390/kvm/dat.c-657-\t\t\tunion skey skey, bool nq)\n--\narch/s390/kvm/dat.c=700=static bool page_cond_set_storage_key(phys_addr_t paddr, union skey skey, union skey *oldkey,\n--\narch/s390/kvm/dat.c-710-\narch/s390/kvm/dat.c:711:int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gfn_t gfn,\narch/s390/kvm/dat.c-712-\t\t\t     union skey skey, union skey *oldkey, bool nq, bool mr, bool mc)\n--\narch/s390/kvm/dat.c-757-\narch/s390/kvm/dat.c:758:int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey)\narch/s390/kvm/dat.c-759-{\n--\narch/s390/kvm/dat.c=813=static long dat_reset_skeys_crste(union crste *crstep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n--\narch/s390/kvm/dat.c-831-\narch/s390/kvm/dat.c:832:long dat_reset_skeys(union asce asce, gfn_t start)\narch/s390/kvm/dat.c-833-{\n--\narch/s390/kvm/dat.c=902=static const struct dat_walk_ops dat_slot_ops = {\n--\narch/s390/kvm/dat.c-906-\narch/s390/kvm/dat.c:907:int dat_set_slot(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t start, gfn_t end,\narch/s390/kvm/dat.c-908-\t\t u16 type, u16 param)\n--\narch/s390/kvm/dat.c=944=unsigned long dat_get_ptval(struct page_table *table, struct ptval_param param)\n--\narch/s390/kvm/dat.c-961-\narch/s390/kvm/dat.c:962:void dat_set_ptval(struct page_table *table, struct ptval_param param, unsigned long val)\narch/s390/kvm/dat.c-963-{\n--\narch/s390/kvm/dat.c=991=static const struct dat_walk_ops test_age_ops = {\n--\narch/s390/kvm/dat.c-1006- */\narch/s390/kvm/dat.c:1007:bool dat_test_age_gfn(union asce asce, gfn_t start, gfn_t end)\narch/s390/kvm/dat.c-1008-{\n--\narch/s390/kvm/dat.c=1030=static long dat_set_pn_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n--\narch/s390/kvm/dat.c-1043-\narch/s390/kvm/dat.c:1044:int dat_set_prefix_notif_bit(union asce asce, gfn_t gfn)\narch/s390/kvm/dat.c-1045-{\n--\narch/s390/kvm/dat.c-1074- */\narch/s390/kvm/dat.c:1075:int dat_perform_essa(union asce asce, gfn_t gfn, int orc, union essa_state *state, bool *dirty)\narch/s390/kvm/dat.c-1076-{\n--\narch/s390/kvm/dat.c=1156=static long dat_reset_cmma_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n--\narch/s390/kvm/dat.c-1169-\narch/s390/kvm/dat.c:1170:long dat_reset_cmma(union asce asce, gfn_t start)\narch/s390/kvm/dat.c-1171-{\n--\narch/s390/kvm/dat.c=1201=static long __dat_peek_cmma_crste(union crste *crstep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n--\narch/s390/kvm/dat.c-1209-\narch/s390/kvm/dat.c:1210:int dat_peek_cmma(gfn_t start, union asce asce, unsigned int *count, u8 *values)\narch/s390/kvm/dat.c-1211-{\n--\narch/s390/kvm/dat.c=1228=static long __dat_get_cmma_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n--\narch/s390/kvm/dat.c-1255-\narch/s390/kvm/dat.c:1256:int dat_get_cmma(union asce asce, gfn_t *start, unsigned int *count, u8 *values, atomic64_t *rem)\narch/s390/kvm/dat.c-1257-{\n--\narch/s390/kvm/dat.c=1286=static long __dat_set_cmma_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n--\narch/s390/kvm/dat.c-1318- */\narch/s390/kvm/dat.c:1319:int dat_set_cmma_bits(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t gfn,\narch/s390/kvm/dat.c-1320-\t\t      unsigned long count, unsigned long mask, const uint8_t *bits)\n--\narch/s390/kvm/dat.h=521=union pgste __must_check __dat_ptep_xchg(union pte *ptep, union pgste pgste, union pte new,\narch/s390/kvm/dat.h-522-\t\t\t\t\t gfn_t gfn, union asce asce, bool uses_skeys);\narch/s390/kvm/dat.h:523:bool dat_crstep_xchg_atomic(union crste *crstep, union crste old, union crste new, gfn_t gfn,\narch/s390/kvm/dat.h-524-\t\t\t    union asce asce);\narch/s390/kvm/dat.h:525:void dat_crstep_xchg(union crste *crstep, union crste new, gfn_t gfn, union asce asce);\narch/s390/kvm/dat.h-526-\narch/s390/kvm/dat.h:527:long _dat_walk_gfn_range(gfn_t start, gfn_t end, union asce asce,\narch/s390/kvm/dat.h-528-\t\t\t const struct dat_walk_ops *ops, int flags, void *priv);\narch/s390/kvm/dat.h-529-\narch/s390/kvm/dat.h:530:int dat_entry_walk(struct kvm_s390_mmu_cache *mc, gfn_t gfn, union asce asce, int flags,\narch/s390/kvm/dat.h-531-\t\t   int walk_level, union crste **last, union pte **ptepp);\narch/s390/kvm/dat.h:532:void dat_free_level(struct crst_table *table, bool owns_ptes);\narch/s390/kvm/dat.h-533-struct crst_table *dat_alloc_crst_sleepable(unsigned long init);\narch/s390/kvm/dat.h:534:int dat_set_asce_limit(struct kvm_s390_mmu_cache *mc, union asce *asce, int newtype);\narch/s390/kvm/dat.h:535:int dat_get_storage_key(union asce asce, gfn_t gfn, union skey *skey);\narch/s390/kvm/dat.h:536:int dat_set_storage_key(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t gfn,\narch/s390/kvm/dat.h-537-\t\t\tunion skey skey, bool nq);\narch/s390/kvm/dat.h:538:int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gfn_t gfn,\narch/s390/kvm/dat.h-539-\t\t\t     union skey skey, union skey *oldkey, bool nq, bool mr, bool mc);\narch/s390/kvm/dat.h:540:int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey);\narch/s390/kvm/dat.h:541:long dat_reset_skeys(union asce asce, gfn_t start);\narch/s390/kvm/dat.h-542-\narch/s390/kvm/dat.h=543=unsigned long dat_get_ptval(struct page_table *table, struct ptval_param param);\narch/s390/kvm/dat.h:544:void dat_set_ptval(struct page_table *table, struct ptval_param param, unsigned long val);\narch/s390/kvm/dat.h-545-\narch/s390/kvm/dat.h:546:int dat_set_slot(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t start, gfn_t end,\narch/s390/kvm/dat.h-547-\t\t u16 type, u16 param);\narch/s390/kvm/dat.h:548:int dat_set_prefix_notif_bit(union asce asce, gfn_t gfn);\narch/s390/kvm/dat.h:549:bool dat_test_age_gfn(union asce asce, gfn_t start, gfn_t end);\narch/s390/kvm/dat.h-550-\narch/s390/kvm/dat.h:551:int dat_perform_essa(union asce asce, gfn_t gfn, int orc, union essa_state *state, bool *dirty);\narch/s390/kvm/dat.h:552:long dat_reset_cmma(union asce asce, gfn_t start_gfn);\narch/s390/kvm/dat.h:553:int dat_peek_cmma(gfn_t start, union asce asce, unsigned int *count, u8 *values);\narch/s390/kvm/dat.h:554:int dat_get_cmma(union asce asce, gfn_t *start, unsigned int *count, u8 *values, atomic64_t *rem);\narch/s390/kvm/dat.h:555:int dat_set_cmma_bits(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t gfn,\narch/s390/kvm/dat.h-556-\t\t      unsigned long count, unsigned long mask, const uint8_t *bits);\narch/s390/kvm/dat.h-557-\narch/s390/kvm/dat.h:558:int kvm_s390_mmu_cache_topup(struct kvm_s390_mmu_cache *mc);\narch/s390/kvm/dat.h-559-\n--\narch/s390/kvm/diag.c=266=static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/diag.c-301-\narch/s390/kvm/diag.c:302:int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)\narch/s390/kvm/diag.c-303-{\n--\narch/s390/kvm/faultin.c-14-\narch/s390/kvm/faultin.c:15:bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu);\narch/s390/kvm/faultin.c-16-\n--\narch/s390/kvm/faultin.c-32- */\narch/s390/kvm/faultin.c:33:int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fault *f)\narch/s390/kvm/faultin.c-34-{\n--\narch/s390/kvm/faultin.c-128-\narch/s390/kvm/faultin.c:129:int kvm_s390_get_guest_page(struct kvm *kvm, struct guest_fault *f, gfn_t gfn, bool w)\narch/s390/kvm/faultin.c-130-{\n--\narch/s390/kvm/faultin.h-15-\narch/s390/kvm/faultin.h:16:int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fault *f);\narch/s390/kvm/faultin.h:17:int kvm_s390_get_guest_page(struct kvm *kvm, struct guest_fault *f, gfn_t gfn, bool w);\narch/s390/kvm/faultin.h-18-\n--\narch/s390/kvm/gaccess.c=112=union oac {\n--\narch/s390/kvm/gaccess.c-133-\narch/s390/kvm/gaccess.c:134:int ipte_lock_held(struct kvm *kvm)\narch/s390/kvm/gaccess.c-135-{\n--\narch/s390/kvm/gaccess.c=202=static void ipte_unlock_siif(struct kvm *kvm)\n--\narch/s390/kvm/gaccess.c-217-\narch/s390/kvm/gaccess.c:218:void ipte_lock(struct kvm *kvm)\narch/s390/kvm/gaccess.c-219-{\n--\narch/s390/kvm/gaccess.c-225-\narch/s390/kvm/gaccess.c:226:void ipte_unlock(struct kvm *kvm)\narch/s390/kvm/gaccess.c-227-{\n--\narch/s390/kvm/gaccess.c=882=static int access_guest_page_with_key_gpa(struct kvm *kvm, enum gacc_mode mode, gpa_t gpa,\n--\narch/s390/kvm/gaccess.c-908-\narch/s390/kvm/gaccess.c:909:int access_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, void *data,\narch/s390/kvm/gaccess.c-910-\t\t\t      unsigned long len, enum gacc_mode mode, u8 access_key)\n--\narch/s390/kvm/gaccess.c-928-\narch/s390/kvm/gaccess.c:929:int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,\narch/s390/kvm/gaccess.c-930-\t\t\t  void *data, unsigned long len, enum gacc_mode mode,\n--\narch/s390/kvm/gaccess.c-1008-\narch/s390/kvm/gaccess.c:1009:int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,\narch/s390/kvm/gaccess.c-1010-\t\t      void *data, unsigned long len, enum gacc_mode mode)\n--\narch/s390/kvm/gaccess.c=1104=static void _cmpxchg_guest_abs_with_key(struct guest_fault *f)\n--\narch/s390/kvm/gaccess.c-1136- */\narch/s390/kvm/gaccess.c:1137:int cmpxchg_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, int len, union kvm_s390_quad *old,\narch/s390/kvm/gaccess.c-1138-\t\t\t       union kvm_s390_quad new, u8 acc, bool *success)\n--\narch/s390/kvm/gaccess.c-1183- */\narch/s390/kvm/gaccess.c:1184:int guest_translate_address_with_key(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,\narch/s390/kvm/gaccess.c-1185-\t\t\t\t     unsigned long *gpa, enum gacc_mode mode,\n--\narch/s390/kvm/gaccess.c-1207- */\narch/s390/kvm/gaccess.c:1208:int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,\narch/s390/kvm/gaccess.c-1209-\t\t    unsigned long length, enum gacc_mode mode, u8 access_key)\n--\narch/s390/kvm/gaccess.c-1232- */\narch/s390/kvm/gaccess.c:1233:int check_gpa_range(struct kvm *kvm, unsigned long gpa, unsigned long length,\narch/s390/kvm/gaccess.c-1234-\t\t    enum gacc_mode mode, u8 access_key)\n--\narch/s390/kvm/gaccess.c-1257- */\narch/s390/kvm/gaccess.c:1258:int kvm_s390_check_low_addr_prot_real(struct kvm_vcpu *vcpu, unsigned long gra)\narch/s390/kvm/gaccess.c-1259-{\n--\narch/s390/kvm/gaccess.c=1646=static int __gaccess_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg, gpa_t saddr,\n--\narch/s390/kvm/gaccess.c-1670-\narch/s390/kvm/gaccess.c:1671:int gaccess_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg, gpa_t saddr,\narch/s390/kvm/gaccess.c-1672-\t\t\t union mvpg_pei *datptr, bool wr)\n--\narch/s390/kvm/gaccess.h=148=static inline __must_check\narch/s390/kvm/gaccess.h:149:int write_guest_lc(struct kvm_vcpu *vcpu, unsigned long gra, void *data,\narch/s390/kvm/gaccess.h-150-\t\t   unsigned long len)\n--\narch/s390/kvm/gaccess.h=174=static inline __must_check\narch/s390/kvm/gaccess.h:175:int read_guest_lc(struct kvm_vcpu *vcpu, unsigned long gra, void *data,\narch/s390/kvm/gaccess.h-176-\t\t  unsigned long len)\n--\narch/s390/kvm/gaccess.h=183=enum gacc_mode {\n--\narch/s390/kvm/gaccess.h-188-\narch/s390/kvm/gaccess.h:189:int guest_translate_address_with_key(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,\narch/s390/kvm/gaccess.h-190-\t\t\t\t     unsigned long *gpa, enum gacc_mode mode,\n--\narch/s390/kvm/gaccess.h-192-\narch/s390/kvm/gaccess.h:193:int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,\narch/s390/kvm/gaccess.h-194-\t\t    unsigned long length, enum gacc_mode mode, u8 access_key);\narch/s390/kvm/gaccess.h-195-\narch/s390/kvm/gaccess.h:196:int check_gpa_range(struct kvm *kvm, unsigned long gpa, unsigned long length,\narch/s390/kvm/gaccess.h-197-\t\t    enum gacc_mode mode, u8 access_key);\narch/s390/kvm/gaccess.h-198-\narch/s390/kvm/gaccess.h:199:int access_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, void *data,\narch/s390/kvm/gaccess.h-200-\t\t\t      unsigned long len, enum gacc_mode mode, u8 access_key);\narch/s390/kvm/gaccess.h-201-\narch/s390/kvm/gaccess.h:202:int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,\narch/s390/kvm/gaccess.h-203-\t\t\t  void *data, unsigned long len, enum gacc_mode mode,\n--\narch/s390/kvm/gaccess.h-205-\narch/s390/kvm/gaccess.h:206:int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,\narch/s390/kvm/gaccess.h-207-\t\t      void *data, unsigned long len, enum gacc_mode mode);\narch/s390/kvm/gaccess.h-208-\narch/s390/kvm/gaccess.h:209:int cmpxchg_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, int len, union kvm_s390_quad *old,\narch/s390/kvm/gaccess.h-210-\t\t\t       union kvm_s390_quad new, u8 access_key, bool *success);\n--\narch/s390/kvm/gaccess.h=258=static inline __must_check\narch/s390/kvm/gaccess.h:259:int write_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,\narch/s390/kvm/gaccess.h-260-\t\t\t void *data, unsigned long len, u8 access_key)\n--\narch/s390/kvm/gaccess.h=277=static inline __must_check\narch/s390/kvm/gaccess.h:278:int write_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data,\narch/s390/kvm/gaccess.h-279-\t\tunsigned long len)\n--\narch/s390/kvm/gaccess.h=300=static inline __must_check\narch/s390/kvm/gaccess.h:301:int read_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,\narch/s390/kvm/gaccess.h-302-\t\t\tvoid *data, unsigned long len, u8 access_key)\n--\narch/s390/kvm/gaccess.h=321=static inline __must_check\narch/s390/kvm/gaccess.h:322:int read_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data,\narch/s390/kvm/gaccess.h-323-\t       unsigned long len)\n--\narch/s390/kvm/gaccess.h=344=static inline __must_check\narch/s390/kvm/gaccess.h:345:int read_guest_instr(struct kvm_vcpu *vcpu, unsigned long ga, void *data,\narch/s390/kvm/gaccess.h-346-\t\t     unsigned long len)\n--\narch/s390/kvm/gaccess.h=370=static inline __must_check\narch/s390/kvm/gaccess.h:371:int write_guest_abs(struct kvm_vcpu *vcpu, unsigned long gpa, void *data,\narch/s390/kvm/gaccess.h-372-\t\t    unsigned long len)\n--\narch/s390/kvm/gaccess.h=393=static inline __must_check\narch/s390/kvm/gaccess.h:394:int read_guest_abs(struct kvm_vcpu *vcpu, unsigned long gpa, void *data,\narch/s390/kvm/gaccess.h-395-\t\t   unsigned long len)\n--\narch/s390/kvm/gaccess.h=417=static inline __must_check\narch/s390/kvm/gaccess.h:418:int write_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, void *data,\narch/s390/kvm/gaccess.h-419-\t\t     unsigned long len)\n--\narch/s390/kvm/gaccess.h=441=static inline __must_check\narch/s390/kvm/gaccess.h:442:int read_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, void *data,\narch/s390/kvm/gaccess.h-443-\t\t    unsigned long len)\n--\narch/s390/kvm/gaccess.h-447-\narch/s390/kvm/gaccess.h:448:void ipte_lock(struct kvm *kvm);\narch/s390/kvm/gaccess.h:449:void ipte_unlock(struct kvm *kvm);\narch/s390/kvm/gaccess.h:450:int ipte_lock_held(struct kvm *kvm);\narch/s390/kvm/gaccess.h:451:int kvm_s390_check_low_addr_prot_real(struct kvm_vcpu *vcpu, unsigned long gra);\narch/s390/kvm/gaccess.h-452-\narch/s390/kvm/gaccess.h=453=union mvpg_pei {\n--\narch/s390/kvm/gaccess.h-462-\narch/s390/kvm/gaccess.h:463:int gaccess_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg, gpa_t saddr,\narch/s390/kvm/gaccess.h-464-\t\t\t union mvpg_pei *datptr, bool wr);\n--\narch/s390/kvm/gmap.c=118=struct gmap *gmap_new_child(struct gmap *parent, gfn_t limit)\n--\narch/s390/kvm/gmap.c-130-\narch/s390/kvm/gmap.c:131:int gmap_set_limit(struct gmap *gmap, gfn_t limit)\narch/s390/kvm/gmap.c-132-{\n--\narch/s390/kvm/gmap.c=153=static void gmap_rmap_radix_tree_free(struct radix_tree_root *root)\n--\narch/s390/kvm/gmap.c-179-\narch/s390/kvm/gmap.c:180:void gmap_remove_child(struct gmap *child)\narch/s390/kvm/gmap.c-181-{\n--\narch/s390/kvm/gmap.c-194- */\narch/s390/kvm/gmap.c:195:void gmap_dispose(struct gmap *gmap)\narch/s390/kvm/gmap.c-196-{\n--\narch/s390/kvm/gmap.c-236- */\narch/s390/kvm/gmap.c:237:int s390_replace_asce(struct gmap *gmap)\narch/s390/kvm/gmap.c-238-{\n--\narch/s390/kvm/gmap.c-258-\narch/s390/kvm/gmap.c:259:bool _gmap_unmap_prefix(struct gmap *gmap, gfn_t gfn, gfn_t end, bool hint)\narch/s390/kvm/gmap.c-260-{\n--\narch/s390/kvm/gmap.c=316=static long gmap_clear_young_crste(union crste *crstep, gfn_t gfn, gfn_t end, struct dat_walk *walk)\n--\narch/s390/kvm/gmap.c-353- */\narch/s390/kvm/gmap.c:354:bool gmap_age_gfn(struct gmap *gmap, gfn_t start, gfn_t end)\narch/s390/kvm/gmap.c-355-{\n--\narch/s390/kvm/gmap.c=398=static long _gmap_unmap_crste(union crste *crstep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n--\narch/s390/kvm/gmap.c-440- */\narch/s390/kvm/gmap.c:441:bool gmap_unmap_gfn_range(struct gmap *gmap, struct kvm_memory_slot *slot, gfn_t start, gfn_t end)\narch/s390/kvm/gmap.c-442-{\n--\narch/s390/kvm/gmap.c=494=static long _crste_test_and_clear_softdirty(union crste *table, gfn_t gfn, gfn_t end,\n--\narch/s390/kvm/gmap.c-526-\narch/s390/kvm/gmap.c:527:void gmap_sync_dirty_log(struct gmap *gmap, gfn_t start, gfn_t end)\narch/s390/kvm/gmap.c-528-{\n--\narch/s390/kvm/gmap.c=573=static int _gmap_handle_minor_pte_fault(struct gmap *gmap, union pgste *pgste,\n--\narch/s390/kvm/gmap.c-611- */\narch/s390/kvm/gmap.c:612:int gmap_try_fixup_minor(struct gmap *gmap, struct guest_fault *fault)\narch/s390/kvm/gmap.c-613-{\n--\narch/s390/kvm/gmap.c=685=static int _gmap_link(struct kvm_s390_mmu_cache *mc, struct gmap *gmap, int level,\n--\narch/s390/kvm/gmap.c-736-\narch/s390/kvm/gmap.c:737:int gmap_link(struct kvm_s390_mmu_cache *mc, struct gmap *gmap, struct guest_fault *f,\narch/s390/kvm/gmap.c-738-\t      struct kvm_memory_slot *slot)\n--\narch/s390/kvm/gmap.c=794=static int gmap_ucas_translate_simple(struct gmap *gmap, gpa_t *gaddr, union crste **crstepp)\n--\narch/s390/kvm/gmap.c-822- */\narch/s390/kvm/gmap.c:823:int gmap_ucas_translate(struct kvm_s390_mmu_cache *mc, struct gmap *gmap, gpa_t *gaddr)\narch/s390/kvm/gmap.c-824-{\n--\narch/s390/kvm/gmap.c-858-\narch/s390/kvm/gmap.c:859:int gmap_ucas_map(struct gmap *gmap, gfn_t p_gfn, gfn_t c_gfn, unsigned long count)\narch/s390/kvm/gmap.c-860-{\n--\narch/s390/kvm/gmap.c=887=static void gmap_ucas_unmap_one(struct gmap *gmap, gfn_t c_gfn)\n--\narch/s390/kvm/gmap.c-899-\narch/s390/kvm/gmap.c:900:void gmap_ucas_unmap(struct gmap *gmap, gfn_t c_gfn, unsigned long count)\narch/s390/kvm/gmap.c-901-{\n--\narch/s390/kvm/gmap.c=908=static long _gmap_split_crste(union crste *crstep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n--\narch/s390/kvm/gmap.c-931-\narch/s390/kvm/gmap.c:932:void gmap_split_huge_pages(struct gmap *gmap)\narch/s390/kvm/gmap.c-933-{\n--\narch/s390/kvm/gmap.c=948=static int _gmap_enable_skeys(struct gmap *gmap)\n--\narch/s390/kvm/gmap.c-970-\narch/s390/kvm/gmap.c:971:int gmap_enable_skeys(struct gmap *gmap)\narch/s390/kvm/gmap.c-972-{\n--\narch/s390/kvm/gmap.c=991=static long _destroy_pages_crste(union crste *crstep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n--\narch/s390/kvm/gmap.c-1007-\narch/s390/kvm/gmap.c:1008:int gmap_pv_destroy_range(struct gmap *gmap, gfn_t start, gfn_t end, bool interruptible)\narch/s390/kvm/gmap.c-1009-{\n--\narch/s390/kvm/gmap.c-1026-\narch/s390/kvm/gmap.c:1027:int gmap_insert_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn,\narch/s390/kvm/gmap.c-1028-\t\t     gfn_t r_gfn, int level)\n--\narch/s390/kvm/gmap.c-1062-\narch/s390/kvm/gmap.c:1063:int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn,\narch/s390/kvm/gmap.c-1064-\t\t      kvm_pfn_t pfn, int level, bool wr)\n--\narch/s390/kvm/gmap.c=1114=static long __set_cmma_dirty_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n--\narch/s390/kvm/gmap.c-1128-\narch/s390/kvm/gmap.c:1129:void _gmap_set_cmma_all(struct gmap *gmap, bool dirty)\narch/s390/kvm/gmap.c-1130-{\n--\narch/s390/kvm/gmap.c=1174=static void gmap_unshadow(struct gmap *sg)\n--\narch/s390/kvm/gmap.c-1193-\narch/s390/kvm/gmap.c:1194:void _gmap_handle_vsie_unshadow_event(struct gmap *parent, gfn_t gfn)\narch/s390/kvm/gmap.c-1195-{\n--\narch/s390/kvm/gmap.h=77=struct gmap_cache {\n--\narch/s390/kvm/gmap.h-84-\narch/s390/kvm/gmap.h:85:int s390_replace_asce(struct gmap *gmap);\narch/s390/kvm/gmap.h:86:bool _gmap_unmap_prefix(struct gmap *gmap, gfn_t gfn, gfn_t end, bool hint);\narch/s390/kvm/gmap.h:87:bool gmap_age_gfn(struct gmap *gmap, gfn_t start, gfn_t end);\narch/s390/kvm/gmap.h:88:bool gmap_unmap_gfn_range(struct gmap *gmap, struct kvm_memory_slot *slot, gfn_t start, gfn_t end);\narch/s390/kvm/gmap.h:89:int gmap_try_fixup_minor(struct gmap *gmap, struct guest_fault *fault);\narch/s390/kvm/gmap.h-90-struct gmap *gmap_new(struct kvm *kvm, gfn_t limit);\narch/s390/kvm/gmap.h=91=struct gmap *gmap_new_child(struct gmap *parent, gfn_t limit);\narch/s390/kvm/gmap.h:92:void gmap_remove_child(struct gmap *child);\narch/s390/kvm/gmap.h:93:void gmap_dispose(struct gmap *gmap);\narch/s390/kvm/gmap.h:94:int gmap_link(struct kvm_s390_mmu_cache *mc, struct gmap *gmap, struct guest_fault *fault,\narch/s390/kvm/gmap.h-95-\t      struct kvm_memory_slot *slot);\narch/s390/kvm/gmap.h:96:void gmap_sync_dirty_log(struct gmap *gmap, gfn_t start, gfn_t end);\narch/s390/kvm/gmap.h:97:int gmap_set_limit(struct gmap *gmap, gfn_t limit);\narch/s390/kvm/gmap.h:98:int gmap_ucas_translate(struct kvm_s390_mmu_cache *mc, struct gmap *gmap, gpa_t *gaddr);\narch/s390/kvm/gmap.h:99:int gmap_ucas_map(struct gmap *gmap, gfn_t p_gfn, gfn_t c_gfn, unsigned long count);\narch/s390/kvm/gmap.h:100:void gmap_ucas_unmap(struct gmap *gmap, gfn_t c_gfn, unsigned long count);\narch/s390/kvm/gmap.h:101:int gmap_enable_skeys(struct gmap *gmap);\narch/s390/kvm/gmap.h:102:int gmap_pv_destroy_range(struct gmap *gmap, gfn_t start, gfn_t end, bool interruptible);\narch/s390/kvm/gmap.h:103:int gmap_insert_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn,\narch/s390/kvm/gmap.h-104-\t\t     gfn_t r_gfn, int level);\narch/s390/kvm/gmap.h:105:int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn,\narch/s390/kvm/gmap.h-106-\t\t      kvm_pfn_t pfn, int level, bool wr);\narch/s390/kvm/gmap.h:107:void _gmap_set_cmma_all(struct gmap *gmap, bool dirty);\narch/s390/kvm/gmap.h:108:void _gmap_handle_vsie_unshadow_event(struct gmap *parent, gfn_t gfn);\narch/s390/kvm/gmap.h-109-struct gmap *gmap_create_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *gmap,\narch/s390/kvm/gmap.h-110-\t\t\t\tunion asce asce, int edat_level);\narch/s390/kvm/gmap.h:111:void gmap_split_huge_pages(struct gmap *gmap);\narch/s390/kvm/gmap.h-112-\n--\narch/s390/kvm/guestdbg.c=99=static void enable_all_hw_wp(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/guestdbg.c-129-\narch/s390/kvm/guestdbg.c:130:void kvm_s390_backup_guest_per_regs(struct kvm_vcpu *vcpu)\narch/s390/kvm/guestdbg.c-131-{\n--\narch/s390/kvm/guestdbg.c-137-\narch/s390/kvm/guestdbg.c:138:void kvm_s390_restore_guest_per_regs(struct kvm_vcpu *vcpu)\narch/s390/kvm/guestdbg.c-139-{\n--\narch/s390/kvm/guestdbg.c-145-\narch/s390/kvm/guestdbg.c:146:void kvm_s390_patch_guest_per_regs(struct kvm_vcpu *vcpu)\narch/s390/kvm/guestdbg.c-147-{\n--\narch/s390/kvm/guestdbg.c=174=static int __import_wp_info(struct kvm_vcpu *vcpu,\n--\narch/s390/kvm/guestdbg.c-202-\narch/s390/kvm/guestdbg.c:203:int kvm_s390_import_bp_data(struct kvm_vcpu *vcpu,\narch/s390/kvm/guestdbg.c-204-\t\t\t    struct kvm_guest_debug *dbg)\n--\narch/s390/kvm/guestdbg.c-277-\narch/s390/kvm/guestdbg.c:278:void kvm_s390_clear_bp_data(struct kvm_vcpu *vcpu)\narch/s390/kvm/guestdbg.c-279-{\n--\narch/s390/kvm/guestdbg.c=334=static struct kvm_hw_wp_info_arch *any_wp_changed(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/guestdbg.c-366-\narch/s390/kvm/guestdbg.c:367:void kvm_s390_prepare_debug_exit(struct kvm_vcpu *vcpu)\narch/s390/kvm/guestdbg.c-368-{\n--\narch/s390/kvm/guestdbg.c=432=static int per_fetched_addr(struct kvm_vcpu *vcpu, unsigned long *addr)\n--\narch/s390/kvm/guestdbg.c-492-\narch/s390/kvm/guestdbg.c:493:int kvm_s390_handle_per_ifetch_icpt(struct kvm_vcpu *vcpu)\narch/s390/kvm/guestdbg.c-494-{\n--\narch/s390/kvm/guestdbg.c=533=static int filter_guest_per_event(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/guestdbg.c-581-\narch/s390/kvm/guestdbg.c:582:int kvm_s390_handle_per_event(struct kvm_vcpu *vcpu)\narch/s390/kvm/guestdbg.c-583-{\n--\narch/s390/kvm/intercept.c=395=static int handle_partial_execution(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/intercept.c-411- */\narch/s390/kvm/intercept.c:412:int handle_sthyi(struct kvm_vcpu *vcpu)\narch/s390/kvm/intercept.c-413-{\n--\narch/s390/kvm/intercept.c=600=static bool should_handle_per_ifetch(const struct kvm_vcpu *vcpu, int rc)\n--\narch/s390/kvm/intercept.c-612-\narch/s390/kvm/intercept.c:613:int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)\narch/s390/kvm/intercept.c-614-{\n\n"
}

5/2 2026/08/01 06:43 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 28543
							output: 54
							thoughts: 93
						

Thoughts:
Okay, here's my interpretation of those thoughts, framed as my own:

**Investigating KVM/s390 CPU PV Creation and Destruction**

Alright, so the output appears truncated, but I can already see that the functions `kvm_s390_pv_create_cpu` and `kvm_s390_pv_destroy_cpu` are both located in `arch/s390/kvm/pv.c`. That's a good starting point. My next step is clear: I need to dive into that file, `arch/s390/kvm/pv.c`, to understand the implementation of those functions. I'll also want to take a look at `arch/s390/kvm/priv.c` to see if there's any related code there. Might as well broaden the search a little at this early stage. This will give me a better understanding of how the paravirtualization aspects interact with the CPU management within KVM on s390. I'm especially interested in how the PV setup and teardown are handled.



6/2 2026/08/01 06:43 tool grepper
0m Args:
{
  "Expression": "^(int|void|long|bool) [a-zA-Z0-9_]+\\(",
  "PathPrefix": "arch/s390/kvm/pv.c"
}

Results:
{
  "Output": "arch/s390/kvm/pv.c-26-\narch/s390/kvm/pv.c:27:bool kvm_s390_pv_is_protected(struct kvm *kvm)\narch/s390/kvm/pv.c-28-{\n--\narch/s390/kvm/pv.c=32=EXPORT_SYMBOL_GPL(kvm_s390_pv_is_protected);\narch/s390/kvm/pv.c-33-\narch/s390/kvm/pv.c:34:bool kvm_s390_pv_cpu_is_protected(struct kvm_vcpu *vcpu)\narch/s390/kvm/pv.c-35-{\n--\narch/s390/kvm/pv.c=104=static void _kvm_s390_pv_make_secure(struct guest_fault *f)\n--\narch/s390/kvm/pv.c-146- */\narch/s390/kvm/pv.c:147:int kvm_s390_pv_make_secure(struct kvm *kvm, unsigned long gaddr, void *uvcb)\narch/s390/kvm/pv.c-148-{\n--\narch/s390/kvm/pv.c-178-\narch/s390/kvm/pv.c:179:int kvm_s390_pv_convert_to_secure(struct kvm *kvm, unsigned long gaddr)\narch/s390/kvm/pv.c-180-{\n--\narch/s390/kvm/pv.c-201- */\narch/s390/kvm/pv.c:202:int kvm_s390_pv_destroy_page(struct kvm *kvm, unsigned long gaddr)\narch/s390/kvm/pv.c-203-{\n--\narch/s390/kvm/pv.c=247=static void kvm_s390_pv_dispose_cpu(struct kvm_vcpu *vcpu, bool free_stor_base)\n--\narch/s390/kvm/pv.c-264-\narch/s390/kvm/pv.c:265:int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)\narch/s390/kvm/pv.c-266-{\n--\narch/s390/kvm/pv.c-283-\narch/s390/kvm/pv.c:284:int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)\narch/s390/kvm/pv.c-285-{\n--\narch/s390/kvm/pv.c=449=static inline bool is_destroy_fast_available(void)\n--\narch/s390/kvm/pv.c-471- */\narch/s390/kvm/pv.c:472:int kvm_s390_pv_set_aside(struct kvm *kvm, u16 *rc, u16 *rrc)\narch/s390/kvm/pv.c-473-{\n--\narch/s390/kvm/pv.c-536- */\narch/s390/kvm/pv.c:537:int kvm_s390_pv_deinit_vm(struct kvm *kvm, u16 *rc, u16 *rrc)\narch/s390/kvm/pv.c-538-{\n--\narch/s390/kvm/pv.c-571- */\narch/s390/kvm/pv.c:572:int kvm_s390_pv_deinit_cleanup_all(struct kvm *kvm, u16 *rc, u16 *rrc)\narch/s390/kvm/pv.c-573-{\n--\narch/s390/kvm/pv.c-648- */\narch/s390/kvm/pv.c:649:int kvm_s390_pv_deinit_aside_vm(struct kvm *kvm, u16 *rc, u16 *rrc)\narch/s390/kvm/pv.c-650-{\n--\narch/s390/kvm/pv.c=705=static const struct mmu_notifier_ops kvm_s390_pv_mmu_notifier_ops = {\n--\narch/s390/kvm/pv.c-708-\narch/s390/kvm/pv.c:709:int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc)\narch/s390/kvm/pv.c-710-{\n--\narch/s390/kvm/pv.c-771-\narch/s390/kvm/pv.c:772:int kvm_s390_pv_set_sec_parms(struct kvm *kvm, void *hdr, u64 length, u16 *rc,\narch/s390/kvm/pv.c-773-\t\t\t      u16 *rrc)\n--\narch/s390/kvm/pv.c=791=static int unpack_one(struct kvm *kvm, unsigned long addr, u64 tweak,\n--\narch/s390/kvm/pv.c-818-\narch/s390/kvm/pv.c:819:int kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size,\narch/s390/kvm/pv.c-820-\t\t       unsigned long tweak, u16 *rc, u16 *rrc)\n--\narch/s390/kvm/pv.c-850-\narch/s390/kvm/pv.c:851:int kvm_s390_pv_set_cpu_state(struct kvm_vcpu *vcpu, u8 state)\narch/s390/kvm/pv.c-852-{\n--\narch/s390/kvm/pv.c-868-\narch/s390/kvm/pv.c:869:int kvm_s390_pv_dump_cpu(struct kvm_vcpu *vcpu, void *buff, u16 *rc, u16 *rrc)\narch/s390/kvm/pv.c-870-{\n--\narch/s390/kvm/pv.c-915- */\narch/s390/kvm/pv.c:916:int kvm_s390_pv_dump_stor_state(struct kvm *kvm, void __user *buff_user,\narch/s390/kvm/pv.c-917-\t\t\t\tu64 *gaddr, u64 buff_user_len, u16 *rc, u16 *rrc)\n--\narch/s390/kvm/pv.c-1023- */\narch/s390/kvm/pv.c:1024:int kvm_s390_pv_dump_complete(struct kvm *kvm, void __user *buff_user,\narch/s390/kvm/pv.c-1025-\t\t\t      u16 *rc, u16 *rrc)\n"
}

7/2 2026/08/01 06:43 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 30941
							output: 54
							thoughts: 32
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Diving into s390 KVM Interrupt Handling**

Right, let's zero in on `arch/s390/kvm/priv.c`. My immediate focus is on the interrupt handling routines within that file. Specifically, I need to refresh my memory on the implementation details for `handle_rrbe` and `handle_essa`. Given the context, I'm likely dealing with error events, and these probably relate to specific hardware exceptions or processor conditions within the s390 architecture running in a KVM environment. I'm assuming that these functions are where KVM intercepts and potentially emulates or handles these events for the guest. I need to understand the control flow, the data structures involved, and the implications of these handlers. Are they involved in the RRBE handling in the new hardware, or an older mechanism? What about ESA handling? Are these performance critical? I need to quickly recall the implications of these events at the hardware level and their corresponding representations within KVM and then review the KVM specific handling. The goal is to fully grasp how KVM is managing these specific exception and status events and whether there are any potential vulnerabilities or performance bottlenecks there.



8/2 2026/08/01 06:43 tool grepper
0m Args:
{
  "Expression": "^(int|void|long|bool) [a-zA-Z0-9_]+\\(",
  "PathPrefix": "arch/s390/kvm/priv.c"
}

Results:
{
  "Output": "arch/s390/kvm/priv.c=33=static int handle_ri(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/priv.c-45-\narch/s390/kvm/priv.c:46:int kvm_s390_handle_aa(struct kvm_vcpu *vcpu)\narch/s390/kvm/priv.c-47-{\n--\narch/s390/kvm/priv.c=54=static int handle_gs(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/priv.c-73-\narch/s390/kvm/priv.c:74:int kvm_s390_handle_e3(struct kvm_vcpu *vcpu)\narch/s390/kvm/priv.c-75-{\n--\narch/s390/kvm/priv.c=191=static int handle_store_cpu_address(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/priv.c-216-\narch/s390/kvm/priv.c:217:int kvm_s390_skey_check_enable(struct kvm_vcpu *vcpu)\narch/s390/kvm/priv.c-218-{\n--\narch/s390/kvm/priv.c=541=static int handle_io_inst(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/priv.c-570-#if IS_ENABLED(CONFIG_VFIO_AP)\narch/s390/kvm/priv.c:571:bool kvm_s390_is_gpa_in_memslot(struct kvm *kvm, gpa_t gpa)\narch/s390/kvm/priv.c-572-{\n--\narch/s390/kvm/priv.c=670=static int handle_stfl(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/priv.c-698-\narch/s390/kvm/priv.c:699:int is_valid_psw(psw_t *psw)\narch/s390/kvm/priv.c-700-{\n--\narch/s390/kvm/priv.c-715-\narch/s390/kvm/priv.c:716:int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu)\narch/s390/kvm/priv.c-717-{\n--\narch/s390/kvm/priv.c=867=static int handle_stsi(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/priv.c-958-\narch/s390/kvm/priv.c:959:int kvm_s390_handle_b2(struct kvm_vcpu *vcpu)\narch/s390/kvm/priv.c-960-{\n--\narch/s390/kvm/priv.c=1217=static int handle_essa(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/priv.c-1283-\narch/s390/kvm/priv.c:1284:int kvm_s390_handle_b9(struct kvm_vcpu *vcpu)\narch/s390/kvm/priv.c-1285-{\n--\narch/s390/kvm/priv.c-1301-\narch/s390/kvm/priv.c:1302:int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu)\narch/s390/kvm/priv.c-1303-{\n--\narch/s390/kvm/priv.c-1340-\narch/s390/kvm/priv.c:1341:int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu)\narch/s390/kvm/priv.c-1342-{\n--\narch/s390/kvm/priv.c=1413=static int handle_stctg(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/priv.c-1446-\narch/s390/kvm/priv.c:1447:int kvm_s390_handle_eb(struct kvm_vcpu *vcpu)\narch/s390/kvm/priv.c-1448-{\n--\narch/s390/kvm/priv.c=1465=static int handle_tprot(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/priv.c-1523-\narch/s390/kvm/priv.c:1524:int kvm_s390_handle_e5(struct kvm_vcpu *vcpu)\narch/s390/kvm/priv.c-1525-{\n--\narch/s390/kvm/priv.c=1553=static int handle_ptff(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/priv.c-1561-\narch/s390/kvm/priv.c:1562:int kvm_s390_handle_01(struct kvm_vcpu *vcpu)\narch/s390/kvm/priv.c-1563-{\n"
}

9/2 2026/08/01 06:43 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 32789
							output: 60
							thoughts: 157
						

Thoughts:
**Analyzing Static vs. Non-Static Functions**

Okay, so I'm looking at these functions: `handle_rrbe` and `handle_essa`. Hmm, they're static, which is interesting. It makes me think about scope and potential for inlining, depending on the compiler's optimization strategy. Now, hold on... `kvm_s390_pv_create_cpu` and `kvm_s390_pv_destroy_cpu`, those aren't static. Alright. And the `dat_reset_reference_bit` function, also non-static. Then there are `kvm_arch_commit_memory_region` and `kvm_arch_prepare_memory_region`, also non-static.

Given that these functions aren't static, I need to check where they're being called and how they're used. I should probably dig into the `arch/s390/kvm/kvm-s390.c` file and zero in on those last two functions, `kvm_arch_commit_memory_region` and `kvm_arch_prepare_memory_region`, to get a better understanding of their context.



10/2 2026/08/01 06:44 tool grepper
0m Args:
{
  "Expression": "^(int|void|long|bool) [a-zA-Z0-9_]+\\(",
  "PathPrefix": "arch/s390/kvm/kvm-s390.c"
}

Results:
{
  "Output": "arch/s390/kvm/kvm-s390.c=562=static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op,\n--\narch/s390/kvm/kvm-s390.c-593-/* Section: device related */\narch/s390/kvm/kvm-s390.c:594:long kvm_arch_dev_ioctl(struct file *filp,\narch/s390/kvm/kvm-s390.c-595-\t\t\tunsigned int ioctl, unsigned long arg)\n--\narch/s390/kvm/kvm-s390.c-601-\narch/s390/kvm/kvm-s390.c:602:int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)\narch/s390/kvm/kvm-s390.c-603-{\n--\narch/s390/kvm/kvm-s390.c-731-\narch/s390/kvm/kvm-s390.c:732:void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)\narch/s390/kvm/kvm-s390.c-733-{\n--\narch/s390/kvm/kvm-s390.c=741=static void sca_del_vcpu(struct kvm_vcpu *vcpu);\n--\narch/s390/kvm/kvm-s390.c-745- */\narch/s390/kvm/kvm-s390.c:746:int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,\narch/s390/kvm/kvm-s390.c-747-\t\t\t       struct kvm_dirty_log *log)\n--\narch/s390/kvm/kvm-s390.c=778=static void icpt_operexc_on_all_vcpus(struct kvm *kvm)\n--\narch/s390/kvm/kvm-s390.c-787-\narch/s390/kvm/kvm-s390.c:788:int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)\narch/s390/kvm/kvm-s390.c-789-{\n--\narch/s390/kvm/kvm-s390.c=1087=static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu);\narch/s390/kvm/kvm-s390.c-1088-\narch/s390/kvm/kvm-s390.c:1089:void kvm_s390_vcpu_crypto_reset_all(struct kvm *kvm)\narch/s390/kvm/kvm-s390.c-1090-{\n--\narch/s390/kvm/kvm-s390.c=1175=static void kvm_s390_vcpu_pci_setup(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/kvm-s390.c-1184-\narch/s390/kvm/kvm-s390.c:1185:void kvm_s390_vcpu_pci_enable_interp(struct kvm *kvm)\narch/s390/kvm/kvm-s390.c-1186-{\n--\narch/s390/kvm/kvm-s390.c=2348=static int kvm_s390_set_cmma_bits(struct kvm *kvm,\n--\narch/s390/kvm/kvm-s390.c-2405- */\narch/s390/kvm/kvm-s390.c:2406:int kvm_s390_cpus_from_pv(struct kvm *kvm, u16 *rc, u16 *rrc)\narch/s390/kvm/kvm-s390.c-2407-{\n--\narch/s390/kvm/kvm-s390.c=2901=static int kvm_s390_vm_mem_op(struct kvm *kvm, struct kvm_s390_mem_op *mop)\n--\narch/s390/kvm/kvm-s390.c-2925-\narch/s390/kvm/kvm-s390.c:2926:int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)\narch/s390/kvm/kvm-s390.c-2927-{\n--\narch/s390/kvm/kvm-s390.c=3126=static void kvm_s390_set_crycb_format(struct kvm *kvm)\n--\narch/s390/kvm/kvm-s390.c-3157- */\narch/s390/kvm/kvm-s390.c:3158:void kvm_arch_crypto_set_masks(struct kvm *kvm, unsigned long *apm,\narch/s390/kvm/kvm-s390.c-3159-\t\t\t       unsigned long *aqm, unsigned long *adm)\n--\narch/s390/kvm/kvm-s390.c=3194=EXPORT_SYMBOL_GPL(kvm_arch_crypto_set_masks);\n--\narch/s390/kvm/kvm-s390.c-3207- */\narch/s390/kvm/kvm-s390.c:3208:void kvm_arch_crypto_clear_masks(struct kvm *kvm)\narch/s390/kvm/kvm-s390.c-3209-{\n--\narch/s390/kvm/kvm-s390.c=3251=static void sca_dispose(struct kvm *kvm)\n--\narch/s390/kvm/kvm-s390.c-3256-\narch/s390/kvm/kvm-s390.c:3257:void kvm_arch_free_vm(struct kvm *kvm)\narch/s390/kvm/kvm-s390.c-3258-{\n--\narch/s390/kvm/kvm-s390.c-3264-\narch/s390/kvm/kvm-s390.c:3265:int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)\narch/s390/kvm/kvm-s390.c-3266-{\n--\narch/s390/kvm/kvm-s390.c-3403-\narch/s390/kvm/kvm-s390.c:3404:void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3405-{\n--\narch/s390/kvm/kvm-s390.c-3430-\narch/s390/kvm/kvm-s390.c:3431:void kvm_arch_destroy_vm(struct kvm *kvm)\narch/s390/kvm/kvm-s390.c-3432-{\n--\narch/s390/kvm/kvm-s390.c=3541=static void disable_cpu_timer_accounting(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/kvm-s390.c-3548-/* set the cpu timer - may only be called from the VCPU thread itself */\narch/s390/kvm/kvm-s390.c:3549:void kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm)\narch/s390/kvm/kvm-s390.c-3550-{\n--\narch/s390/kvm/kvm-s390.c=3561=__u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/kvm-s390.c-3585-\narch/s390/kvm/kvm-s390.c:3586:void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)\narch/s390/kvm/kvm-s390.c-3587-{\n--\narch/s390/kvm/kvm-s390.c-3594-\narch/s390/kvm/kvm-s390.c:3595:void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3596-{\n--\narch/s390/kvm/kvm-s390.c-3603-\narch/s390/kvm/kvm-s390.c:3604:void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3605-{\n--\narch/s390/kvm/kvm-s390.c=3650=static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/kvm-s390.c-3680-\narch/s390/kvm/kvm-s390.c:3681:void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3682-{\n--\narch/s390/kvm/kvm-s390.c-3687-\narch/s390/kvm/kvm-s390.c:3688:int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3689-{\n--\narch/s390/kvm/kvm-s390.c=3708=static int kvm_s390_vcpu_setup(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/kvm-s390.c-3794-\narch/s390/kvm/kvm-s390.c:3795:int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)\narch/s390/kvm/kvm-s390.c-3796-{\n--\narch/s390/kvm/kvm-s390.c=3802=DEFINE_FREE(sie_page, struct sie_page *, if (_T) free_page((unsigned long)(_T)))\narch/s390/kvm/kvm-s390.c-3803-\narch/s390/kvm/kvm-s390.c:3804:int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3805-{\n--\narch/s390/kvm/kvm-s390.c-3882-\narch/s390/kvm/kvm-s390.c:3883:int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3884-{\n--\narch/s390/kvm/kvm-s390.c-3888-\narch/s390/kvm/kvm-s390.c:3889:bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3890-{\n--\narch/s390/kvm/kvm-s390.c-3893-\narch/s390/kvm/kvm-s390.c:3894:void kvm_s390_vcpu_block(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3895-{\n--\narch/s390/kvm/kvm-s390.c-3899-\narch/s390/kvm/kvm-s390.c:3900:void kvm_s390_vcpu_unblock(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3901-{\n--\narch/s390/kvm/kvm-s390.c=3905=static void kvm_s390_vcpu_request(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/kvm-s390.c-3910-\narch/s390/kvm/kvm-s390.c:3911:bool kvm_s390_vcpu_sie_inhibited(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3912-{\n--\narch/s390/kvm/kvm-s390.c=3917=static void kvm_s390_vcpu_request_handled(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/kvm-s390.c-3925- * return immediately. */\narch/s390/kvm/kvm-s390.c:3926:void exit_sie(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3927-{\n--\narch/s390/kvm/kvm-s390.c-3934-/* Kick a guest cpu out of SIE to process a request synchronously */\narch/s390/kvm/kvm-s390.c:3935:void kvm_s390_sync_request(int req, struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3936-{\n--\narch/s390/kvm/kvm-s390.c-3940-\narch/s390/kvm/kvm-s390.c:3941:bool kvm_arch_no_poll(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3942-{\n--\narch/s390/kvm/kvm-s390.c-3951-\narch/s390/kvm/kvm-s390.c:3952:int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-3953-{\n--\narch/s390/kvm/kvm-s390.c=4117=static void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/kvm-s390.c-4132-\narch/s390/kvm/kvm-s390.c:4133:int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)\narch/s390/kvm/kvm-s390.c-4134-{\n--\narch/s390/kvm/kvm-s390.c-4140-\narch/s390/kvm/kvm-s390.c:4141:int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)\narch/s390/kvm/kvm-s390.c-4142-{\n--\narch/s390/kvm/kvm-s390.c-4148-\narch/s390/kvm/kvm-s390.c:4149:int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,\narch/s390/kvm/kvm-s390.c-4150-\t\t\t\t  struct kvm_sregs *sregs)\n--\narch/s390/kvm/kvm-s390.c-4160-\narch/s390/kvm/kvm-s390.c:4161:int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,\narch/s390/kvm/kvm-s390.c-4162-\t\t\t\t  struct kvm_sregs *sregs)\n--\narch/s390/kvm/kvm-s390.c-4172-\narch/s390/kvm/kvm-s390.c:4173:int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)\narch/s390/kvm/kvm-s390.c-4174-{\n--\narch/s390/kvm/kvm-s390.c-4187-\narch/s390/kvm/kvm-s390.c:4188:int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)\narch/s390/kvm/kvm-s390.c-4189-{\n--\narch/s390/kvm/kvm-s390.c=4203=static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)\n--\narch/s390/kvm/kvm-s390.c-4215-\narch/s390/kvm/kvm-s390.c:4216:int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,\narch/s390/kvm/kvm-s390.c-4217-\t\t\t\t  struct kvm_translation *tr)\n--\narch/s390/kvm/kvm-s390.c-4225-\narch/s390/kvm/kvm-s390.c:4226:int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,\narch/s390/kvm/kvm-s390.c-4227-\t\t\t\t\tstruct kvm_guest_debug *dbg)\n--\narch/s390/kvm/kvm-s390.c-4267-\narch/s390/kvm/kvm-s390.c:4268:int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,\narch/s390/kvm/kvm-s390.c-4269-\t\t\t\t    struct kvm_mp_state *mp_state)\n--\narch/s390/kvm/kvm-s390.c-4282-\narch/s390/kvm/kvm-s390.c:4283:int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,\narch/s390/kvm/kvm-s390.c-4284-\t\t\t\t    struct kvm_mp_state *mp_state)\n--\narch/s390/kvm/kvm-s390.c=4436=static void __kvm_s390_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod)\n--\narch/s390/kvm/kvm-s390.c-4463-\narch/s390/kvm/kvm-s390.c:4464:int kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod)\narch/s390/kvm/kvm-s390.c-4465-{\n--\narch/s390/kvm/kvm-s390.c=4473=static void __kvm_inject_pfault_token(struct kvm_vcpu *vcpu, bool start_token,\n--\narch/s390/kvm/kvm-s390.c-4498-\narch/s390/kvm/kvm-s390.c:4499:bool kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu,\narch/s390/kvm/kvm-s390.c-4500-\t\t\t\t     struct kvm_async_pf *work)\n--\narch/s390/kvm/kvm-s390.c-4507-\narch/s390/kvm/kvm-s390.c:4508:void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,\narch/s390/kvm/kvm-s390.c-4509-\t\t\t\t struct kvm_async_pf *work)\n--\narch/s390/kvm/kvm-s390.c-4514-\narch/s390/kvm/kvm-s390.c:4515:void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu,\narch/s390/kvm/kvm-s390.c-4516-\t\t\t       struct kvm_async_pf *work)\n--\narch/s390/kvm/kvm-s390.c-4520-\narch/s390/kvm/kvm-s390.c:4521:bool kvm_arch_can_dequeue_async_page_present(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-4522-{\n--\narch/s390/kvm/kvm-s390.c-4529-\narch/s390/kvm/kvm-s390.c:4530:bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-4531-{\n--\narch/s390/kvm/kvm-s390.c=5004=static void store_regs(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/kvm-s390.c-5024-\narch/s390/kvm/kvm-s390.c:5025:int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-5026-{\n--\narch/s390/kvm/kvm-s390.c-5114- */\narch/s390/kvm/kvm-s390.c:5115:int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)\narch/s390/kvm/kvm-s390.c-5116-{\n--\narch/s390/kvm/kvm-s390.c-5166-\narch/s390/kvm/kvm-s390.c:5167:int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)\narch/s390/kvm/kvm-s390.c-5168-{\n--\narch/s390/kvm/kvm-s390.c=5196=static void __enable_ibs_on_vcpu(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/kvm-s390.c-5203-\narch/s390/kvm/kvm-s390.c:5204:int kvm_s390_vcpu_start(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-5205-{\n--\narch/s390/kvm/kvm-s390.c-5258-\narch/s390/kvm/kvm-s390.c:5259:int kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu)\narch/s390/kvm/kvm-s390.c-5260-{\n--\narch/s390/kvm/kvm-s390.c=5414=static long kvm_s390_vcpu_memsida_op(struct kvm_vcpu *vcpu,\n--\narch/s390/kvm/kvm-s390.c-5438-\narch/s390/kvm/kvm-s390.c:5439:long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,\narch/s390/kvm/kvm-s390.c-5440-\t\t\t\t  unsigned long arg)\n--\narch/s390/kvm/kvm-s390.c=5484=static int kvm_s390_handle_pv_vcpu_dump(struct kvm_vcpu *vcpu,\n--\narch/s390/kvm/kvm-s390.c-5525-\narch/s390/kvm/kvm-s390.c:5526:long kvm_arch_vcpu_ioctl(struct file *filp,\narch/s390/kvm/kvm-s390.c-5527-\t\t\t unsigned int ioctl, unsigned long arg)\n--\narch/s390/kvm/kvm-s390.c=5745=vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)\n--\narch/s390/kvm/kvm-s390.c-5757-\narch/s390/kvm/kvm-s390.c:5758:bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)\narch/s390/kvm/kvm-s390.c-5759-{\n--\narch/s390/kvm/kvm-s390.c=5764=static long cmma_d_count_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)\n--\narch/s390/kvm/kvm-s390.c-5776-\narch/s390/kvm/kvm-s390.c:5777:int kvm_arch_prepare_memory_region(struct kvm *kvm,\narch/s390/kvm/kvm-s390.c-5778-\t\t\t\t   const struct kvm_memory_slot *old,\n--\narch/s390/kvm/kvm-s390.c-5865-\narch/s390/kvm/kvm-s390.c:5866:void kvm_arch_commit_memory_region(struct kvm *kvm, struct kvm_memory_slot *old,\narch/s390/kvm/kvm-s390.c-5867-\t\t\t\t   const struct kvm_memory_slot *new, enum kvm_mr_change change)\n--\narch/s390/kvm/kvm-s390.c-5890- */\narch/s390/kvm/kvm-s390.c:5891:long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu, struct kvm_pre_fault_memory *range)\narch/s390/kvm/kvm-s390.c-5892-{\n--\narch/s390/kvm/kvm-s390.c-5922- */\narch/s390/kvm/kvm-s390.c:5923:bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)\narch/s390/kvm/kvm-s390.c-5924-{\n--\narch/s390/kvm/kvm-s390.c-5936- */\narch/s390/kvm/kvm-s390.c:5937:bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)\narch/s390/kvm/kvm-s390.c-5938-{\n--\narch/s390/kvm/kvm-s390.c-5954- */\narch/s390/kvm/kvm-s390.c:5955:bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)\narch/s390/kvm/kvm-s390.c-5956-{\n"
}

11/2 2026/08/01 06:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 41523
							output: 54
							thoughts: 147
						

Thoughts:
Okay, here's my understanding, formatted as requested:

**Assessing KVM Architecture Non-Static Functions**

Right, let me see... I'm looking at these KVM-related functions. It seems I've identified several that are non-static: `kvm_arch_prepare_memory_region`, `kvm_arch_commit_memory_region`, `dat_reset_reference_bit`, `kvm_s390_pv_create_cpu`, `kvm_s390_pv_destroy_cpu`, and `kvm_arch_vm_ioctl`. My immediate thought is, "Okay, so these are accessible outside of their respective compilation units, which implies a potential for external modification or use." I need to understand the implications of this, particularly in a context as performance-critical as KVM.

Now, considering the architecture, specifically the s390 architecture, I'll shift gears. I remember those SCAs and external calls related to interrupts, so I need to check `arch/s390/kvm/interrupt.c`. I'm going to look for the definitions of `sca_ext_call_pending`, `sca_inject_ext_call`, and `sca_clear_ext_call` to understand how these might interact with those non-static functions and if they introduce anything unexpected. This is about making sure nothing untoward happens with external calls, particularly regarding interrupt management.



12/2 2026/08/01 06:44 tool grepper
0m Args:
{
  "Expression": "^(int|void|long|bool) [a-zA-Z0-9_]+\\(",
  "PathPrefix": "arch/s390/kvm/interrupt.c"
}

Results:
{
  "Output": "arch/s390/kvm/interrupt.c=90=static void sca_clear_ext_call(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/interrupt.c-104-\narch/s390/kvm/interrupt.c:105:int psw_extint_disabled(struct kvm_vcpu *vcpu)\narch/s390/kvm/interrupt.c-106-{\n--\narch/s390/kvm/interrupt.c=1123=static int __must_check __deliver_io(struct kvm_vcpu *vcpu,\n--\narch/s390/kvm/interrupt.c-1193-/* Check whether an external call is pending (deliverable or not) */\narch/s390/kvm/interrupt.c:1194:int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu)\narch/s390/kvm/interrupt.c-1195-{\n--\narch/s390/kvm/interrupt.c-1203-\narch/s390/kvm/interrupt.c:1204:int kvm_s390_vcpu_has_irq(struct kvm_vcpu *vcpu, int exclude_stop)\narch/s390/kvm/interrupt.c-1205-{\n--\narch/s390/kvm/interrupt.c-1222-\narch/s390/kvm/interrupt.c:1223:int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)\narch/s390/kvm/interrupt.c-1224-{\n--\narch/s390/kvm/interrupt.c=1228=static u64 __calculate_sltime(struct kvm_vcpu *vcpu)\n--\narch/s390/kvm/interrupt.c-1259-\narch/s390/kvm/interrupt.c:1260:int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)\narch/s390/kvm/interrupt.c-1261-{\n--\narch/s390/kvm/interrupt.c-1306-\narch/s390/kvm/interrupt.c:1307:void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)\narch/s390/kvm/interrupt.c-1308-{\n--\narch/s390/kvm/interrupt.c=1319=enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer)\n--\narch/s390/kvm/interrupt.c-1336-\narch/s390/kvm/interrupt.c:1337:void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu)\narch/s390/kvm/interrupt.c-1338-{\n--\narch/s390/kvm/interrupt.c=1958=static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)\n--\narch/s390/kvm/interrupt.c-1988-\narch/s390/kvm/interrupt.c:1989:int kvm_s390_inject_vm(struct kvm *kvm,\narch/s390/kvm/interrupt.c-1990-\t\t       struct kvm_s390_interrupt *s390int, struct kvm_s390_interrupt_info *inti)\n--\narch/s390/kvm/interrupt.c-2031-\narch/s390/kvm/interrupt.c:2032:int kvm_s390_reinject_io_int(struct kvm *kvm,\narch/s390/kvm/interrupt.c-2033-\t\t\t      struct kvm_s390_interrupt_info *inti)\n--\narch/s390/kvm/interrupt.c-2037-\narch/s390/kvm/interrupt.c:2038:int s390int_to_s390irq(struct kvm_s390_interrupt *s390int,\narch/s390/kvm/interrupt.c-2039-\t\t       struct kvm_s390_irq *irq)\n--\narch/s390/kvm/interrupt.c-2080-\narch/s390/kvm/interrupt.c:2081:int kvm_s390_is_stop_irq_pending(struct kvm_vcpu *vcpu)\narch/s390/kvm/interrupt.c-2082-{\n--\narch/s390/kvm/interrupt.c-2087-\narch/s390/kvm/interrupt.c:2088:int kvm_s390_is_restart_irq_pending(struct kvm_vcpu *vcpu)\narch/s390/kvm/interrupt.c-2089-{\n--\narch/s390/kvm/interrupt.c-2094-\narch/s390/kvm/interrupt.c:2095:void kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu)\narch/s390/kvm/interrupt.c-2096-{\n--\narch/s390/kvm/interrupt.c=2105=static int do_inject_vcpu(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)\n--\narch/s390/kvm/interrupt.c-2149-\narch/s390/kvm/interrupt.c:2150:int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)\narch/s390/kvm/interrupt.c-2151-{\n--\narch/s390/kvm/interrupt.c=2173=static void inti_to_irq(struct kvm_s390_interrupt_info *inti,\n--\narch/s390/kvm/interrupt.c-2188-\narch/s390/kvm/interrupt.c:2189:void kvm_s390_clear_float_irqs(struct kvm *kvm)\narch/s390/kvm/interrupt.c-2190-{\n--\narch/s390/kvm/interrupt.c=2426=static int register_io_adapter(struct kvm_device *dev,\n--\narch/s390/kvm/interrupt.c-2472-\narch/s390/kvm/interrupt.c:2473:int kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked)\narch/s390/kvm/interrupt.c-2474-{\n--\narch/s390/kvm/interrupt.c=2552=static int kvm_s390_adapter_unmap(struct kvm *kvm, unsigned int id, __u64 addr)\n--\narch/s390/kvm/interrupt.c-2589-\narch/s390/kvm/interrupt.c:2590:void kvm_s390_unmap_all_adapters(struct kvm *kvm)\narch/s390/kvm/interrupt.c-2591-{\n--\narch/s390/kvm/interrupt.c-2619-\narch/s390/kvm/interrupt.c:2620:void kvm_s390_destroy_adapters(struct kvm *kvm)\narch/s390/kvm/interrupt.c-2621-{\n--\narch/s390/kvm/interrupt.c=3053=static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e,\n--\narch/s390/kvm/interrupt.c-3079- */\narch/s390/kvm/interrupt.c:3080:void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,\narch/s390/kvm/interrupt.c-3081-\t\t\t\t     struct mcck_volatile_info *mcck_info)\n--\narch/s390/kvm/interrupt.c-3120-\narch/s390/kvm/interrupt.c:3121:int kvm_set_routing_entry(struct kvm *kvm,\narch/s390/kvm/interrupt.c-3122-\t\t\t  struct kvm_kernel_irq_routing_entry *e,\n--\narch/s390/kvm/interrupt.c-3162-\narch/s390/kvm/interrupt.c:3163:int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,\narch/s390/kvm/interrupt.c-3164-\t\tint irq_source_id, int level, bool line_status)\n--\narch/s390/kvm/interrupt.c-3168-\narch/s390/kvm/interrupt.c:3169:int kvm_s390_set_irq_state(struct kvm_vcpu *vcpu, void __user *irqstate, int len)\narch/s390/kvm/interrupt.c-3170-{\n--\narch/s390/kvm/interrupt.c=3209=static void store_local_irq(struct kvm_s390_local_interrupt *li,\n--\narch/s390/kvm/interrupt.c-3250-\narch/s390/kvm/interrupt.c:3251:int kvm_s390_get_irq_state(struct kvm_vcpu *vcpu, __u8 __user *buf, int len)\narch/s390/kvm/interrupt.c-3252-{\n--\narch/s390/kvm/interrupt.c=3351=static void process_gib_alert_list(void)\n--\narch/s390/kvm/interrupt.c-3395-\narch/s390/kvm/interrupt.c:3396:void kvm_s390_gisa_clear(struct kvm *kvm)\narch/s390/kvm/interrupt.c-3397-{\n--\narch/s390/kvm/interrupt.c-3405-\narch/s390/kvm/interrupt.c:3406:void kvm_s390_gisa_init(struct kvm *kvm)\narch/s390/kvm/interrupt.c-3407-{\n--\narch/s390/kvm/interrupt.c-3421-\narch/s390/kvm/interrupt.c:3422:void kvm_s390_gisa_enable(struct kvm *kvm)\narch/s390/kvm/interrupt.c-3423-{\n--\narch/s390/kvm/interrupt.c-3444-\narch/s390/kvm/interrupt.c:3445:void kvm_s390_gisa_destroy(struct kvm *kvm)\narch/s390/kvm/interrupt.c-3446-{\n--\narch/s390/kvm/interrupt.c-3462-\narch/s390/kvm/interrupt.c:3463:void kvm_s390_gisa_disable(struct kvm *kvm)\narch/s390/kvm/interrupt.c-3464-{\n--\narch/s390/kvm/interrupt.c-3497- */\narch/s390/kvm/interrupt.c:3498:int kvm_s390_gisc_register(struct kvm *kvm, u32 gisc)\narch/s390/kvm/interrupt.c-3499-{\n--\narch/s390/kvm/interrupt.c=3517=EXPORT_SYMBOL_GPL(kvm_s390_gisc_register);\n--\narch/s390/kvm/interrupt.c-3536- */\narch/s390/kvm/interrupt.c:3537:int kvm_s390_gisc_unregister(struct kvm *kvm, u32 gisc)\narch/s390/kvm/interrupt.c-3538-{\n--\narch/s390/kvm/interrupt.c=3646=static struct airq_struct gib_alert_irq = {\n--\narch/s390/kvm/interrupt.c-3649-\narch/s390/kvm/interrupt.c:3650:void kvm_s390_gib_destroy(void)\narch/s390/kvm/interrupt.c-3651-{\n--\narch/s390/kvm/interrupt.c=3665=int __init kvm_s390_gib_init(u8 nisc)\n--\narch/s390/kvm/interrupt.c-3722- */\narch/s390/kvm/interrupt.c:3723:int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,\narch/s390/kvm/interrupt.c-3724-\t\t\t      struct kvm *kvm, int irq_source_id, int level,\n"
}

13/2 2026/08/01 06:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 45656
							output: 55
							thoughts: 75
						

Thoughts:
Here's my take on the thought process:

**Focusing on External Call Management**

Okay, so I'm honing in on how these external calls are handled. I need to keep the code efficient and streamlined. I'm noting that `sca_ext_call_pending`, `sca_inject_ext_call`, and `sca_clear_ext_call` are static, which simplifies their inclusion in this specific context. Considering their static nature, I won't need to consider them. I'm going to skip them from any further analysis in this case, as they don't seem directly relevant to what I'm currently investigating. I'm trying to figure out how to work with the memory.

Right now, I am going to check `arch/s390/kvm/faultin.c` and specifically look at the `kvm_s390_faultin_gfn` function for some clues. I'm hoping it'll offer some insight into how faults are handled, which relates directly to the external call mechanisms I'm looking into.



14/2 2026/08/01 06:44 tool grepper
0m Args:
{
  "Expression": "^(int|void|long|bool) [a-zA-Z0-9_]+\\(",
  "PathPrefix": "arch/s390/kvm/faultin.c"
}

Results:
{
  "Output": "arch/s390/kvm/faultin.c-14-\narch/s390/kvm/faultin.c:15:bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu);\narch/s390/kvm/faultin.c-16-\n--\narch/s390/kvm/faultin.c-32- */\narch/s390/kvm/faultin.c:33:int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fault *f)\narch/s390/kvm/faultin.c-34-{\n--\narch/s390/kvm/faultin.c-128-\narch/s390/kvm/faultin.c:129:int kvm_s390_get_guest_page(struct kvm *kvm, struct guest_fault *f, gfn_t gfn, bool w)\narch/s390/kvm/faultin.c-130-{\n"
}

15/2 2026/08/01 06:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 46308
							output: 35
							thoughts: 403
						

Thoughts:
**Analyzing KVM/s390 Symbols**

Okay, so I'm looking at this code and making some decisions about potential areas for review or refactoring, specifically focusing on symbol visibility. I noted that `kvm_s390_faultin_gfn` is *not* declared static, which is a key observation.

To get a clearer picture, I'm going to summarize the relevant symbols: `kvm_arch_vm_ioctl`, `kvm_arch_commit_memory_region`, `kvm_arch_prepare_memory_region`, `kvm_s390_pv_create_cpu`, `kvm_s390_pv_destroy_cpu`, `dat_reset_reference_bit`, and of course `kvm_s390_faultin_gfn` – this is my primary interest.

I initially thought `kvm_arch_vm_ioctl` might be a generic hot-path function, but quickly realized it's actually the VM ioctl handler. It's a fundamental entry point, but not in the performance-critical path like `kvm_arch_vcpu_ioctl_run`. That's important to remember for future optimization considerations. I wanted to verify if `kvm_s390_vm_set_migration` is reachable via `kvm_arch_vm_ioctl` because I thought that might have been the better option. I can confirm, via the `KVM_SET_DEVICE_ATTR` ioctl for `KVM_S390_VM_MIGRATION`, that it is. But, I looked at it and it's static. So, it looks like `kvm_arch_vm_ioctl` is the correct symbol.

Now, let's circle back to the other symbols. `dat_reset_reference_bit` is also non-static. Then `kvm_s390_pv_create_cpu` and `kvm_s390_pv_destroy_cpu` are non-static as well. Also, `kvm_arch_commit_memory_region` is, too, non-static.

Before I move on, I should probably check the s390 Kconfig to see if anything there influences these choices. That might give me some clues about why these were designed this way.



16/2 2026/08/01 06:44 tool grepper
0m Args:
{
  "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"
}

17/2 2026/08/01 06:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 47422
							output: 35
							thoughts: 948
						

Thoughts:
**Analyzing KVM Configuration and Focus Symbols**

Okay, so I'm looking at this KVM patch, and the primary configuration seems to be `KVM`, naturally. However, `KVM_S390_UCONTROL` is also mentioned, specifically within `kvm_is_ucontrol(vcpu->kvm)`. I need to confirm whether `KVM_S390_UCONTROL` is essential here, so let's check.

The code snippets include checks like `if (kvm_is_ucontrol(vcpu->kvm))` which directly uses `KVM_S390_UCONTROL`, and based on that, it’s relevant to the operation. Therefore, I need to include it in the `EnableConfigs`.

Next, I'll scan for any other configuration dependencies. `CONFIG_KVM` is definitely a core requirement.

Now, let's circle back to the 'focus symbols' – the critical functions touched by this patch. I've already identified several: `kvm_arch_vm_ioctl`, `kvm_arch_commit_memory_region`, `kvm_arch_prepare_memory_region`, `kvm_s390_pv_create_cpu`, `kvm_s390_pv_destroy_cpu`, `dat_reset_reference_bit`, and `kvm_s390_faultin_gfn`. But are there any others?

I see `handle_rrbe` and `handle_essa` are static, but they are called from instruction intercept handlers. The entry point for that seems to be `kvm_handle_sie_intercept`, which is a hot path. And also, `kvm_s390_keyop` is static, called from `kvm_arch_dev_ioctl` or `kvm_arch_vm_ioctl`. Also, `kvm_s390_get_skeys`, `kvm_s390_set_skeys`, `kvm_s390_set_cmma_bits` are static, called from `kvm_arch_vm_ioctl`. Then there are `kvm_arch_vcpu_create` which includes changes related to `kvm_is_ucontrol` and `kvm_arch_vcpu_postcreate` which includes changes related to `vcpu->arch.initialized`.

Okay, I need to add `kvm_arch_vcpu_create` and `kvm_arch_vcpu_postcreate` to the focus symbols.

So, here's my updated list: `kvm_arch_vm_ioctl`, `kvm_arch_vcpu_create`, `kvm_arch_vcpu_postcreate`, `kvm_arch_commit_memory_region`, `kvm_arch_prepare_memory_region`, `kvm_s390_pv_create_cpu`, `kvm_s390_pv_destroy_cpu`, `dat_reset_reference_bit`, and `kvm_s390_faultin_gfn`.

Now, time to refine the list to avoid generic symbols. `kvm_arch_vm_ioctl` is fine; it's the entry point for VM ioctls. Same with `kvm_arch_vcpu_create`, and `kvm_arch_commit_memory_region`. However, `kvm_s390_pv_create_cpu` and `kvm_s390_pv_destroy_cpu` are specific to PV (Protected Virtualization). `dat_reset_reference_bit` is DAT-specific (Dynamic Address Translation), and `kvm_s390_faultin_gfn` is about page fault handling.

This looks like a solid, specific list of focus symbols.

Now, final check – are `KVM` and `KVM_S390_UCONTROL` the only configuration dependencies? I need to think if there are PV-related configs.



18/2 2026/08/01 06:44 tool grepper
0m Args:
{
  "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"
}

19/2 2026/08/01 06:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 49453
							output: 30
							thoughts: 39
						

Thoughts:
Okay, let's see what's going on with Persistent Virtual Machines. My immediate thought is, "Where's the configuration for this thing?" I know the architecture is s390, so the logical starting points are the Kconfig files specific to the architecture and KVM integration, namely `arch/s390/kvm/Kconfig` and `arch/s390/Kconfig`. I need to confirm whether any configuration options related to Persistent VMs exist in those locations. Let's dig in and check. That should be the starting point to investigate.



20/2 2026/08/01 06:44 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "config .*PV",
  "PathPrefix": "arch/s390/"
}

Results:
{
  "error": "no matches"
}

21/2 2026/08/01 06:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 49658
							output: 31
							thoughts: 23
						

Thoughts:
Here's my thought process, as requested:

**Investigating Potential Configuration Options**

Okay, so I need to understand how protected memory regions are configured for s390 architecture within the kernel. My first instinct is to dive into the Kconfig file for that architecture. It's almost always the central repository for build-time configuration options. I'll need to look for a symbol related to protection, maybe `PROTECTED` itself, or something similar – it could be `SECURE`, `GUARDED`, `RESTRICTED`, or anything of that nature. I'm expecting this file to contain the definitions and dependencies that govern whether this functionality gets built into the kernel. From there, I can trace back where this is used within the kernel.



22/2 2026/08/01 06:44 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "config .*PROTECTED",
  "PathPrefix": "arch/s390/"
}

Results:
{
  "error": "no matches"
}

23/2 2026/08/01 06:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 49883
							output: 34
							thoughts: 14
						

Thoughts:
Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person:

**Potential Misinterpretation of Memory Protection Flag**

Hmm, I was just reviewing the code, specifically the memory protection flags for that new mapping, and for a moment I thought I had the wrong flag. I was considering `PROT_READ | PROT_WRITE | PROT_EXEC`, but then I had this flicker of doubt. Did I perhaps misread the documentation, or maybe misremember the intended access permissions? Could it be that what I *really* need here is `PROT_VIRT`? It's the one I should double-check since I do not want to mistakenly grant unnecessary permissions for security or performance reasons. I should go back and confirm my assumption against the documentation.



24/2 2026/08/01 06:44 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "config .*PROT_VIRT",
  "PathPrefix": "arch/s390/"
}

Results:
{
  "error": "no matches"
}

25/2 2026/08/01 06:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 50116
							output: 35
							thoughts: 26
						

Thoughts:
Here's my take on those thoughts, tailored for an expert audience:

**Diving into `pv.c` on s390x KVM**

Alright, time to dig into the s390x KVM's paravirtualization code. My immediate thought is to zero in on potential platform-specific adaptations. Specifically, I need to scan `arch/s390/kvm/pv.c` with a laser focus on `#ifdef` directives. I'm looking for conditional compilation blocks. This will show me where the architecture might have diverged for specific feature sets, vendor quirks, or older kernels and I want to see how the PV code handles it. I'm expecting to see things like specific instruction set checks or maybe even handling of different KVM hypervisor versions. I need to understand how the code adapts to the underlying hardware and potentially varying KVM host capabilities. I'm anticipating that these preprocessor directives are going to guide me to those critical areas where I need to focus my debugging and analysis.



26/2 2026/08/01 06:44 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "#ifdef",
  "PathPrefix": "arch/s390/kvm/pv.c"
}

Results:
{
  "error": "no matches"
}

27/2 2026/08/01 06:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 50409
							output: 248
							thoughts: 388
						

Thoughts:
**My Analysis of the s390 KVM Subsystem Patch**

Okay, so it looks like Protected Virtualization (PV) is consistently compiled whenever Kernel-based Virtual Machine (KVM) is enabled on s390. This is important to note for understanding the scope of the changes.

Let's dive into the specifics. I'm going to quickly review the enabling configurations: `KVM` and `KVM_S390_UCONTROL`. Now, let's look at the symbols that drive the focus of our analysis. I see these: `kvm_arch_vm_ioctl`, `kvm_arch_vcpu_create`, `kvm_arch_vcpu_postcreate`, `kvm_arch_commit_memory_region`, `kvm_arch_prepare_memory_region`, `kvm_s390_pv_create_cpu`, `kvm_s390_pv_destroy_cpu`, `dat_reset_reference_bit`, and `kvm_s390_faultin_gfn`.

The reason these are important is because the patch itself seems to be making functional changes to the s390 KVM subsystem. These changes are addressing things like memory leaks, locking issues, initialization races, and signal handling during page faults. It's modifying core KVM ioctls, how memory regions are managed, and functions related to PV CPU lifecycle.

These modifications are all reachable from userspace, either through KVM ioctls or memory accesses, which means they're excellent targets for fuzzing.

Let's quickly check a couple of these symbols. `kvm_arch_vcpu_postcreate` seems fine as a symbol, as it's called once per vCPU creation. `kvm_s390_faultin_gfn` is triggered during page faults, which is also a good target. `dat_reset_reference_bit` is called during `KVM_S390_KEYOP_RRBE` and `handle_rrbe`. That's also good.

With this solid understanding, I'm going to call `set-results` and move forward.



28/2 2026/08/01 06:45 tool set-results
0m Error:
the following configs do not exist in the kernel tree: KVM_S390_UCONTROL

Args:
{
  "EnableConfigs": [
    "KVM",
    "KVM_S390_UCONTROL"
  ],
  "FocusSymbols": [
    "kvm_arch_vm_ioctl",
    "kvm_arch_vcpu_create",
    "kvm_arch_vcpu_postcreate",
    "kvm_arch_commit_memory_region",
    "kvm_arch_prepare_memory_region",
    "kvm_s390_pv_create_cpu",
    "kvm_s390_pv_destroy_cpu",
    "dat_reset_reference_bit",
    "kvm_s390_faultin_gfn"
  ],
  "Reasoning": "The patch makes functional changes to the s390 KVM subsystem, including fixes for memory leaks, locking, initialization races, and signal handling during page faults. It modifies core KVM ioctls, memory region management, and Protected Virtualization (PV) CPU lifecycle functions. These changes are reachable from userspace via KVM ioctls and memory accesses, making them suitable for fuzzing.",
  "WorthFuzzing": true
}

Results:
{
  "error": "the following configs do not exist in the kernel tree: KVM_S390_UCONTROL"
}

29/2 2026/08/01 06:45 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 51548
							output: 43
							thoughts: 38
						

Thoughts:
Okay, here's the summary, assuming I'm a Linux kernel developer/KVM specialist:

**Checking for KVM_S390_UCONTROL Configuration**

Right, *KVM_S390_UCONTROL*... I seem to recall that being a thing, specifically related to the s390 architecture. Let me confirm, it should be in the `arch/s390/kvm/Kconfig` file. I need to make sure I've got the exact name correct, as a misspelling here would be a real waste of time. I can't be off by even a character. Okay, let me quickly verify the exact designation...



30/2 2026/08/01 06:45 tool grepper
0m Args:
{
  "Expression": "config KVM_S390_UCONTROL",
  "PathPrefix": "arch/s390/kvm/Kconfig"
}

Results:
{
  "Output": "arch/s390/kvm/Kconfig=19=config KVM\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"
}

31/2 2026/08/01 06:45 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 51880
							output: 235
							thoughts: 139
						

Thoughts:
**Debugging a Kernel Configuration Error**

Okay, so the error message is screaming about `KVM_S390_UCONTROL` not being found. My initial thought is to, of course, check the `Kconfig` file. But hold on, the tool might be looking for this configuration under `x86`, which, as we know, isn't the only architecture. I need to make sure the search isn't erroneously filtering by architecture. Let me quickly double-check that `KVM_S390_UCONTROL` is *actually* the correct name for the config, just to make sure I haven't fat-fingered something. Yep, looks good there. If the tool is still being difficult and rejecting it, I'll just skip `KVM_S390_UCONTROL` and use the more general `KVM` config. It might be a workaround, but I have a high degree of confidence that the more general config will be functionally sufficient, at least as a starting point.



32/2 2026/08/01 06:45 tool set-results
0m Args:
{
  "EnableConfigs": [
    "KVM"
  ],
  "FocusSymbols": [
    "kvm_arch_vm_ioctl",
    "kvm_arch_vcpu_create",
    "kvm_arch_vcpu_postcreate",
    "kvm_arch_commit_memory_region",
    "kvm_arch_prepare_memory_region",
    "kvm_s390_pv_create_cpu",
    "kvm_s390_pv_destroy_cpu",
    "dat_reset_reference_bit",
    "kvm_s390_faultin_gfn"
  ],
  "Reasoning": "The patch makes functional changes to the s390 KVM subsystem, including fixes for memory leaks, locking, initialization races, and signal handling during page faults. It modifies core KVM ioctls, memory region management, and Protected Virtualization (PV) CPU lifecycle functions. These changes are reachable from userspace via KVM ioctls and memory accesses, making them suitable for fuzzing.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "KVM"
  ],
  "FocusSymbols": [
    "kvm_arch_vm_ioctl",
    "kvm_arch_vcpu_create",
    "kvm_arch_vcpu_postcreate",
    "kvm_arch_commit_memory_region",
    "kvm_arch_prepare_memory_region",
    "kvm_s390_pv_create_cpu",
    "kvm_s390_pv_destroy_cpu",
    "dat_reset_reference_bit",
    "kvm_s390_faultin_gfn"
  ],
  "Reasoning": "The patch makes functional changes to the s390 KVM subsystem, including fixes for memory leaks, locking, initialization races, and signal handling during page faults. It modifies core KVM ioctls, memory region management, and Protected Virtualization (PV) CPU lifecycle functions. These changes are reachable from userspace via KVM ioctls and memory accesses, making them suitable for fuzzing.",
  "WorthFuzzing": true
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)