AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/07/16 18:47 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": [
    "KVM"
  ],
  "FocusSymbols": [
    "uv_alloc_stor_var",
    "uv_free_stor_var",
    "uv_alloc_range_cb",
    "uv_free_range_cb",
    "ex_handler_zeropad",
    "do_secure_storage_access",
    "kvm_s390_pv_alloc_vm",
    "kvm_s390_pv_dealloc_vm"
  ],
  "Reasoning": "The patch introduces functional changes to s390 architecture code, specifically handling of unaligned word loads with zero padding (`load_unaligned_zeropad`, `ex_handler_zeropad`), and memory allocation for KVM Protected Virtualization (`uv_alloc_stor_var`, `uv_free_stor_var`). These changes modify reachable core kernel logic and exception handling, which should be fuzzed to ensure memory safety and correctness.",
  "WorthFuzzing": true
}

1/1 2026/07/16 18:47 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 5b6458fb9362abd47c63d168905c5012c8587586\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Thu Jul 16 18:47:17 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/arch/s390/Kconfig b/arch/s390/Kconfig\nindex 84404e6778d504..fe81c539ef2ffc 100644\n--- a/arch/s390/Kconfig\n+++ b/arch/s390/Kconfig\n@@ -163,6 +163,7 @@ config S390\n \tselect ARCH_WANTS_THP_SWAP\n \tselect BUILDTIME_TABLE_SORT\n \tselect CLONE_BACKWARDS2\n+\tselect DCACHE_WORD_ACCESS if !KMSAN\n \tselect DYNAMIC_FTRACE if FUNCTION_TRACER\n \tselect FUNCTION_ALIGNMENT_8B if CC_IS_GCC\n \tselect FUNCTION_ALIGNMENT_16B if !CC_IS_GCC\ndiff --git a/arch/s390/include/asm/asm-extable.h b/arch/s390/include/asm/asm-extable.h\nindex 99748c20e76713..d23ea0c94e4ea6 100644\n--- a/arch/s390/include/asm/asm-extable.h\n+++ b/arch/s390/include/asm/asm-extable.h\n@@ -12,6 +12,7 @@\n #define EX_TYPE_UA_FAULT\t3\n #define EX_TYPE_UA_LOAD_REG\t5\n #define EX_TYPE_UA_LOAD_REGPAIR\t6\n+#define EX_TYPE_ZEROPAD\t\t7\n #define EX_TYPE_FPC\t\t8\n #define EX_TYPE_UA_MVCOS_TO\t9\n #define EX_TYPE_UA_MVCOS_FROM\t10\n@@ -79,6 +80,9 @@\n #define EX_TABLE_UA_LOAD_REGPAIR(_fault, _target, _regerr, _regzero)\t\\\n \t__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REGPAIR, _regerr, _regzero, 0)\n \n+#define EX_TABLE_ZEROPAD(_fault, _target, _regdata, _regaddr)\t\t\\\n+\t__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_ZEROPAD, _regdata, _regaddr, 0)\n+\n #define EX_TABLE_FPC(_fault, _target)\t\t\t\t\t\\\n \t__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FPC, __stringify(%%r0), __stringify(%%r0), 0)\n \ndiff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h\nindex d919e69662f584..153fed63adda3c 100644\n--- a/arch/s390/include/asm/uv.h\n+++ b/arch/s390/include/asm/uv.h\n@@ -635,6 +635,8 @@ int s390_wiggle_split_folio(struct mm_struct *mm, struct folio *folio);\n int __make_folio_secure(struct folio *folio, struct uv_cb_header *uvcb);\n int uv_convert_from_secure(unsigned long paddr);\n int uv_convert_from_secure_folio(struct folio *folio);\n+void *uv_alloc_stor_var(unsigned long size);\n+void uv_free_stor_var(void *stor_var);\n \n void setup_uv(void);\n \ndiff --git a/arch/s390/include/asm/word-at-a-time.h b/arch/s390/include/asm/word-at-a-time.h\nindex e9287036392d08..eaa19dee769941 100644\n--- a/arch/s390/include/asm/word-at-a-time.h\n+++ b/arch/s390/include/asm/word-at-a-time.h\n@@ -4,6 +4,7 @@\n \n #include \u003clinux/bitops.h\u003e\n #include \u003clinux/wordpart.h\u003e\n+#include \u003casm/asm-extable.h\u003e\n #include \u003casm/bitsperlong.h\u003e\n \n struct word_at_a_time {\n@@ -40,4 +41,25 @@ static inline unsigned long zero_bytemask(unsigned long data)\n \treturn ~1UL \u003c\u003c data;\n }\n \n+/*\n+ * Load an unaligned word from kernel space.\n+ *\n+ * In the (very unlikely) case of the word being a page-crosser\n+ * and the next page not being mapped, take the exception and\n+ * return zeroes in the non-existing part.\n+ */\n+static inline unsigned long load_unaligned_zeropad(const void *addr)\n+{\n+\tunsigned long data;\n+\n+\tasm_inline volatile(\n+\t\t\"0:\tlg\t%[data],0(%[addr])\\n\"\n+\t\t\"1:\tnopr\t%%r7\\n\"\n+\t\tEX_TABLE_ZEROPAD(0b, 1b, %[data], %[addr])\n+\t\tEX_TABLE_ZEROPAD(1b, 1b, %[data], %[addr])\n+\t\t: [data] \"=d\" (data)\n+\t\t: [addr] \"a\" (addr), \"m\" (*(unsigned long *)addr));\n+\treturn data;\n+}\n+\n #endif /* _ASM_WORD_AT_A_TIME_H */\ndiff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c\nindex a284f98d971680..98a7f988fc691d 100644\n--- a/arch/s390/kernel/uv.c\n+++ b/arch/s390/kernel/uv.c\n@@ -16,6 +16,7 @@\n #include \u003clinux/swap.h\u003e\n #include \u003clinux/pagewalk.h\u003e\n #include \u003clinux/backing-dev.h\u003e\n+#include \u003clinux/vmalloc.h\u003e\n #include \u003casm/facility.h\u003e\n #include \u003casm/sections.h\u003e\n #include \u003casm/uv.h\u003e\n@@ -209,6 +210,64 @@ int uv_convert_from_secure_pte(pte_t pte)\n \treturn uv_convert_from_secure_folio(pfn_folio(pte_pfn(pte)));\n }\n \n+static int uv_free_range_cb(pte_t *ptep, unsigned long addr, void *data)\n+{\n+\tpte_t pte = ptep_get(ptep);\n+\n+\tif (!pte_present(pte))\n+\t\treturn 0;\n+\t__free_page(pte_page(pte));\n+\treturn 0;\n+}\n+\n+void uv_free_stor_var(void *stor_var)\n+{\n+\tunsigned long addr, size;\n+\tstruct vm_struct *area;\n+\n+\tif (!stor_var)\n+\t\treturn;\n+\tarea = find_vm_area(stor_var);\n+\tif (WARN_ON_ONCE(!area || !(area-\u003eflags \u0026 VM_SPARSE)))\n+\t\treturn;\n+\tsize = get_vm_area_size(area);\n+\taddr = (unsigned long)area-\u003eaddr;\n+\tapply_to_existing_page_range(\u0026init_mm, addr, size, uv_free_range_cb, NULL);\n+\tfree_vm_area(area);\n+}\n+EXPORT_SYMBOL_FOR_MODULES(uv_free_stor_var, \"kvm\");\n+\n+static int uv_alloc_range_cb(pte_t *ptep, unsigned long addr, void *data)\n+{\n+\tstruct page *page;\n+\tpte_t pte;\n+\n+\tpage = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);\n+\tif (!page)\n+\t\treturn -ENOMEM;\n+\tpte = __pte(page_to_phys(page) | pgprot_val(PAGE_KERNEL));\n+\tset_pte(ptep, pte);\n+\treturn 0;\n+}\n+\n+void *uv_alloc_stor_var(unsigned long size)\n+{\n+\tstruct vm_struct *area;\n+\tunsigned long addr;\n+\n+\tarea = get_vm_area(size, VM_SPARSE);\n+\tif (!area)\n+\t\treturn NULL;\n+\taddr = (unsigned long)area-\u003eaddr;\n+\tif (apply_to_page_range(\u0026init_mm, addr, size, uv_alloc_range_cb, NULL))\n+\t\tgoto out;\n+\treturn area-\u003eaddr;\n+out:\n+\tuv_free_stor_var(area-\u003eaddr);\n+\treturn NULL;\n+}\n+EXPORT_SYMBOL_FOR_MODULES(uv_alloc_stor_var, \"kvm\");\n+\n /*\n  * Calculate the expected ref_count for a folio that would otherwise have no\n  * further pins. This was cribbed from similar functions in other places in\ndiff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c\nindex 1beacc841ca850..dc5ac29b4c3118 100644\n--- a/arch/s390/kvm/pv.c\n+++ b/arch/s390/kvm/pv.c\n@@ -337,7 +337,7 @@ int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)\n /* only free resources when the destroy was successful */\n static void kvm_s390_pv_dealloc_vm(struct kvm *kvm)\n {\n-\tvfree(kvm-\u003earch.pv.stor_var);\n+\tuv_free_stor_var(kvm-\u003earch.pv.stor_var);\n \tfree_pages(kvm-\u003earch.pv.stor_base,\n \t\t   get_order(uv_info.guest_base_stor_len));\n \tkvm_s390_clear_pv_state(kvm);\n@@ -369,7 +369,7 @@ static int kvm_s390_pv_alloc_vm(struct kvm *kvm)\n \t/* Allocate variable storage */\n \tvlen = ALIGN(virt * ((npages * PAGE_SIZE) / HPAGE_SIZE), PAGE_SIZE);\n \tvlen += uv_info.guest_virt_base_stor_len;\n-\tkvm-\u003earch.pv.stor_var = vzalloc(vlen);\n+\tkvm-\u003earch.pv.stor_var = uv_alloc_stor_var(vlen);\n \tif (!kvm-\u003earch.pv.stor_var)\n \t\tgoto out_err;\n \treturn 0;\n@@ -414,7 +414,7 @@ static int kvm_s390_pv_dispose_one_leftover(struct kvm *kvm,\n \t */\n \tfree_pages(leftover-\u003estor_base, get_order(uv_info.guest_base_stor_len));\n \tfree_pages(leftover-\u003eold_gmap_table, CRST_ALLOC_ORDER);\n-\tvfree(leftover-\u003estor_var);\n+\tuv_free_stor_var(leftover-\u003estor_var);\n done_fast:\n \tatomic_dec(\u0026kvm-\u003emm-\u003econtext.protected_count);\n \treturn 0;\ndiff --git a/arch/s390/mm/extable.c b/arch/s390/mm/extable.c\nindex 063b4346742d96..7498e858c40195 100644\n--- a/arch/s390/mm/extable.c\n+++ b/arch/s390/mm/extable.c\n@@ -50,6 +50,22 @@ static bool ex_handler_ua_load_reg(const struct exception_table_entry *ex,\n \treturn true;\n }\n \n+static bool ex_handler_zeropad(const struct exception_table_entry *ex, struct pt_regs *regs)\n+{\n+\tunsigned int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex-\u003edata);\n+\tunsigned int reg_data = FIELD_GET(EX_DATA_REG_ERR, ex-\u003edata);\n+\tunsigned long data, addr, offset;\n+\n+\taddr = regs-\u003egprs[reg_addr];\n+\toffset = addr \u0026 (sizeof(unsigned long) - 1);\n+\taddr \u0026= ~(sizeof(unsigned long) - 1);\n+\tdata = *(unsigned long *)addr;\n+\tdata \u003c\u003c= BITS_PER_BYTE * offset;\n+\tregs-\u003egprs[reg_data] = data;\n+\tregs-\u003epsw.addr = extable_fixup(ex);\n+\treturn true;\n+}\n+\n static bool ex_handler_fpc(const struct exception_table_entry *ex, struct pt_regs *regs)\n {\n \tfpu_sfpc(0);\n@@ -118,6 +134,8 @@ bool fixup_exception(struct pt_regs *regs)\n \t\treturn ex_handler_ua_load_reg(ex, false, regs);\n \tcase EX_TYPE_UA_LOAD_REGPAIR:\n \t\treturn ex_handler_ua_load_reg(ex, true, regs);\n+\tcase EX_TYPE_ZEROPAD:\n+\t\treturn ex_handler_zeropad(ex, regs);\n \tcase EX_TYPE_FPC:\n \t\treturn ex_handler_fpc(ex, regs);\n \tcase EX_TYPE_UA_MVCOS_TO:\ndiff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c\nindex 028aeb9c48d6ff..db77c8c0023ee6 100644\n--- a/arch/s390/mm/fault.c\n+++ b/arch/s390/mm/fault.c\n@@ -438,13 +438,9 @@ void do_secure_storage_access(struct pt_regs *regs)\n \t\tpanic(\"Unexpected PGM 0x3d with TEID bit 61=0\");\n \t}\n \tif (is_kernel_fault(regs)) {\n-\t\tfolio = virt_to_folio((void *)addr);\n-\t\tif (unlikely(!folio_try_get(folio)))\n-\t\t\treturn;\n-\t\trc = uv_convert_from_secure(folio_to_phys(folio));\n-\t\tif (!rc)\n-\t\t\tclear_bit(PG_arch_1, \u0026folio-\u003eflags.f);\n-\t\tfolio_put(folio);\n+\t\tif (is_vmalloc_addr((void *)addr))\n+\t\t\treturn handle_fault_error_nolock(regs, 0);\n+\t\trc = uv_convert_from_secure(__pa(addr));\n \t\t/*\n \t\t * There are some valid fixup types for kernel\n \t\t * accesses to donated secure memory. zeropad is one\n"
}

2/1 2026/07/16 18:47 agent patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": [
    "KVM"
  ],
  "FocusSymbols": [
    "uv_alloc_stor_var",
    "uv_free_stor_var",
    "uv_alloc_range_cb",
    "uv_free_range_cb",
    "ex_handler_zeropad",
    "do_secure_storage_access",
    "kvm_s390_pv_alloc_vm",
    "kvm_s390_pv_dealloc_vm"
  ],
  "Reasoning": "The patch introduces functional changes to s390 architecture code, specifically handling of unaligned word loads with zero padding (`load_unaligned_zeropad`, `ex_handler_zeropad`), and memory allocation for KVM Protected Virtualization (`uv_alloc_stor_var`, `uv_free_stor_var`). These changes modify reachable core kernel logic and exception handling, which should be fuzzed to ensure memory safety and correctness.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Do not list too generic configs (we already have them enabled). Only list those that
   specifically cover the modified code. List them in the EnableConfigs output array,
   and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit 5b6458fb9362abd47c63d168905c5012c8587586
Author: syz-cluster <triage@syzkaller.com>
Date:   Thu Jul 16 18:47:17 2026 +0000

    syz-cluster: applied patch under review

diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 84404e6778d504..fe81c539ef2ffc 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -163,6 +163,7 @@ config S390
 	select ARCH_WANTS_THP_SWAP
 	select BUILDTIME_TABLE_SORT
 	select CLONE_BACKWARDS2
+	select DCACHE_WORD_ACCESS if !KMSAN
 	select DYNAMIC_FTRACE if FUNCTION_TRACER
 	select FUNCTION_ALIGNMENT_8B if CC_IS_GCC
 	select FUNCTION_ALIGNMENT_16B if !CC_IS_GCC
diff --git a/arch/s390/include/asm/asm-extable.h b/arch/s390/include/asm/asm-extable.h
index 99748c20e76713..d23ea0c94e4ea6 100644
--- a/arch/s390/include/asm/asm-extable.h
+++ b/arch/s390/include/asm/asm-extable.h
@@ -12,6 +12,7 @@
 #define EX_TYPE_UA_FAULT	3
 #define EX_TYPE_UA_LOAD_REG	5
 #define EX_TYPE_UA_LOAD_REGPAIR	6
+#define EX_TYPE_ZEROPAD		7
 #define EX_TYPE_FPC		8
 #define EX_TYPE_UA_MVCOS_TO	9
 #define EX_TYPE_UA_MVCOS_FROM	10
@@ -79,6 +80,9 @@
 #define EX_TABLE_UA_LOAD_REGPAIR(_fault, _target, _regerr, _regzero)	\
 	__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REGPAIR, _regerr, _regzero, 0)
 
+#define EX_TABLE_ZEROPAD(_fault, _target, _regdata, _regaddr)		\
+	__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_ZEROPAD, _regdata, _regaddr, 0)
+
 #define EX_TABLE_FPC(_fault, _target)					\
 	__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FPC, __stringify(%%r0), __stringify(%%r0), 0)
 
diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
index d919e69662f584..153fed63adda3c 100644
--- a/arch/s390/include/asm/uv.h
+++ b/arch/s390/include/asm/uv.h
@@ -635,6 +635,8 @@ int s390_wiggle_split_folio(struct mm_struct *mm, struct folio *folio);
 int __make_folio_secure(struct folio *folio, struct uv_cb_header *uvcb);
 int uv_convert_from_secure(unsigned long paddr);
 int uv_convert_from_secure_folio(struct folio *folio);
+void *uv_alloc_stor_var(unsigned long size);
+void uv_free_stor_var(void *stor_var);
 
 void setup_uv(void);
 
diff --git a/arch/s390/include/asm/word-at-a-time.h b/arch/s390/include/asm/word-at-a-time.h
index e9287036392d08..eaa19dee769941 100644
--- a/arch/s390/include/asm/word-at-a-time.h
+++ b/arch/s390/include/asm/word-at-a-time.h
@@ -4,6 +4,7 @@
 
 #include <linux/bitops.h>
 #include <linux/wordpart.h>
+#include <asm/asm-extable.h>
 #include <asm/bitsperlong.h>
 
 struct word_at_a_time {
@@ -40,4 +41,25 @@ static inline unsigned long zero_bytemask(unsigned long data)
 	return ~1UL << data;
 }
 
+/*
+ * Load an unaligned word from kernel space.
+ *
+ * In the (very unlikely) case of the word being a page-crosser
+ * and the next page not being mapped, take the exception and
+ * return zeroes in the non-existing part.
+ */
+static inline unsigned long load_unaligned_zeropad(const void *addr)
+{
+	unsigned long data;
+
+	asm_inline volatile(
+		"0:	lg	%[data],0(%[addr])\n"
+		"1:	nopr	%%r7\n"
+		EX_TABLE_ZEROPAD(0b, 1b, %[data], %[addr])
+		EX_TABLE_ZEROPAD(1b, 1b, %[data], %[addr])
+		: [data] "=d" (data)
+		: [addr] "a" (addr), "m" (*(unsigned long *)addr));
+	return data;
+}
+
 #endif /* _ASM_WORD_AT_A_TIME_H */
diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c
index a284f98d971680..98a7f988fc691d 100644
--- a/arch/s390/kernel/uv.c
+++ b/arch/s390/kernel/uv.c
@@ -16,6 +16,7 @@
 #include <linux/swap.h>
 #include <linux/pagewalk.h>
 #include <linux/backing-dev.h>
+#include <linux/vmalloc.h>
 #include <asm/facility.h>
 #include <asm/sections.h>
 #include <asm/uv.h>
@@ -209,6 +210,64 @@ int uv_convert_from_secure_pte(pte_t pte)
 	return uv_convert_from_secure_folio(pfn_folio(pte_pfn(pte)));
 }
 
+static int uv_free_range_cb(pte_t *ptep, unsigned long addr, void *data)
+{
+	pte_t pte = ptep_get(ptep);
+
+	if (!pte_present(pte))
+		return 0;
+	__free_page(pte_page(pte));
+	return 0;
+}
+
+void uv_free_stor_var(void *stor_var)
+{
+	unsigned long addr, size;
+	struct vm_struct *area;
+
+	if (!stor_var)
+		return;
+	area = find_vm_area(stor_var);
+	if (WARN_ON_ONCE(!area || !(area->flags & VM_SPARSE)))
+		return;
+	size = get_vm_area_size(area);
+	addr = (unsigned long)area->addr;
+	apply_to_existing_page_range(&init_mm, addr, size, uv_free_range_cb, NULL);
+	free_vm_area(area);
+}
+EXPORT_SYMBOL_FOR_MODULES(uv_free_stor_var, "kvm");
+
+static int uv_alloc_range_cb(pte_t *ptep, unsigned long addr, void *data)
+{
+	struct page *page;
+	pte_t pte;
+
+	page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
+	if (!page)
+		return -ENOMEM;
+	pte = __pte(page_to_phys(page) | pgprot_val(PAGE_KERNEL));
+	set_pte(ptep, pte);
+	return 0;
+}
+
+void *uv_alloc_stor_var(unsigned long size)
+{
+	struct vm_struct *area;
+	unsigned long addr;
+
+	area = get_vm_area(size, VM_SPARSE);
+	if (!area)
+		return NULL;
+	addr = (unsigned long)area->addr;
+	if (apply_to_page_range(&init_mm, addr, size, uv_alloc_range_cb, NULL))
+		goto out;
+	return area->addr;
+out:
+	uv_free_stor_var(area->addr);
+	return NULL;
+}
+EXPORT_SYMBOL_FOR_MODULES(uv_alloc_stor_var, "kvm");
+
 /*
  * Calculate the expected ref_count for a folio that would otherwise have no
  * further pins. This was cribbed from similar functions in other places in
diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c
index 1beacc841ca850..dc5ac29b4c3118 100644
--- a/arch/s390/kvm/pv.c
+++ b/arch/s390/kvm/pv.c
@@ -337,7 +337,7 @@ int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
 /* only free resources when the destroy was successful */
 static void kvm_s390_pv_dealloc_vm(struct kvm *kvm)
 {
-	vfree(kvm->arch.pv.stor_var);
+	uv_free_stor_var(kvm->arch.pv.stor_var);
 	free_pages(kvm->arch.pv.stor_base,
 		   get_order(uv_info.guest_base_stor_len));
 	kvm_s390_clear_pv_state(kvm);
@@ -369,7 +369,7 @@ static int kvm_s390_pv_alloc_vm(struct kvm *kvm)
 	/* Allocate variable storage */
 	vlen = ALIGN(virt * ((npages * PAGE_SIZE) / HPAGE_SIZE), PAGE_SIZE);
 	vlen += uv_info.guest_virt_base_stor_len;
-	kvm->arch.pv.stor_var = vzalloc(vlen);
+	kvm->arch.pv.stor_var = uv_alloc_stor_var(vlen);
 	if (!kvm->arch.pv.stor_var)
 		goto out_err;
 	return 0;
@@ -414,7 +414,7 @@ static int kvm_s390_pv_dispose_one_leftover(struct kvm *kvm,
 	 */
 	free_pages(leftover->stor_base, get_order(uv_info.guest_base_stor_len));
 	free_pages(leftover->old_gmap_table, CRST_ALLOC_ORDER);
-	vfree(leftover->stor_var);
+	uv_free_stor_var(leftover->stor_var);
 done_fast:
 	atomic_dec(&kvm->mm->context.protected_count);
 	return 0;
diff --git a/arch/s390/mm/extable.c b/arch/s390/mm/extable.c
index 063b4346742d96..7498e858c40195 100644
--- a/arch/s390/mm/extable.c
+++ b/arch/s390/mm/extable.c
@@ -50,6 +50,22 @@ static bool ex_handler_ua_load_reg(const struct exception_table_entry *ex,
 	return true;
 }
 
+static bool ex_handler_zeropad(const struct exception_table_entry *ex, struct pt_regs *regs)
+{
+	unsigned int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
+	unsigned int reg_data = FIELD_GET(EX_DATA_REG_ERR, ex->data);
+	unsigned long data, addr, offset;
+
+	addr = regs->gprs[reg_addr];
+	offset = addr & (sizeof(unsigned long) - 1);
+	addr &= ~(sizeof(unsigned long) - 1);
+	data = *(unsigned long *)addr;
+	data <<= BITS_PER_BYTE * offset;
+	regs->gprs[reg_data] = data;
+	regs->psw.addr = extable_fixup(ex);
+	return true;
+}
+
 static bool ex_handler_fpc(const struct exception_table_entry *ex, struct pt_regs *regs)
 {
 	fpu_sfpc(0);
@@ -118,6 +134,8 @@ bool fixup_exception(struct pt_regs *regs)
 		return ex_handler_ua_load_reg(ex, false, regs);
 	case EX_TYPE_UA_LOAD_REGPAIR:
 		return ex_handler_ua_load_reg(ex, true, regs);
+	case EX_TYPE_ZEROPAD:
+		return ex_handler_zeropad(ex, regs);
 	case EX_TYPE_FPC:
 		return ex_handler_fpc(ex, regs);
 	case EX_TYPE_UA_MVCOS_TO:
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 028aeb9c48d6ff..db77c8c0023ee6 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -438,13 +438,9 @@ void do_secure_storage_access(struct pt_regs *regs)
 		panic("Unexpected PGM 0x3d with TEID bit 61=0");
 	}
 	if (is_kernel_fault(regs)) {
-		folio = virt_to_folio((void *)addr);
-		if (unlikely(!folio_try_get(folio)))
-			return;
-		rc = uv_convert_from_secure(folio_to_phys(folio));
-		if (!rc)
-			clear_bit(PG_arch_1, &folio->flags.f);
-		folio_put(folio);
+		if (is_vmalloc_addr((void *)addr))
+			return handle_fault_error_nolock(regs, 0);
+		rc = uv_convert_from_secure(__pa(addr));
 		/*
 		 * There are some valid fixup types for kernel
 		 * accesses to donated secure memory. zeropad is one

3/2 2026/07/16 18:47 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 5426
							output: 33
							thoughts: 694
						

Thoughts:
**Analyzing the s390 Kernel Patch**

Okay, so I've got this patch series targeting the s390 architecture. Looks like it touches a significant chunk of the s390 code base: `arch/s390/Kconfig`, several include files, and a few core kernel areas like `uv.c`, `kvm/pv.c`, `extable.c`, and `fault.c`. The changes are specifically around adding `DCACHE_WORD_ACCESS` (conditionally, if not KMSAN), introducing new exception types, implementing an inline `load_unaligned_zeropad` function, adding storage variable allocation/deallocation in `uv.c` and using them in KVM's PV code, and tweaking `do_secure_storage_access` in the memory management fault handler.

My immediate question is, is this thing *functional* and *reachable*? Since this is s390-specific, that's the crucial question. It seems to be related to Protected Virtualization in KVM and exception handling when dealing with unaligned memory access with zero-padding. Normally, I would think twice about fuzzing code paths that are difficult to reach in virtualized environments, but wait, syzkaller *does* support s390x QEMU, so that changes the calculus. This is definitely worth exploring because it's touching pretty core kernel logic.

I need to nail down exactly which functions are most relevant for fuzzing, so I'll be focusing on: `load_unaligned_zeropad` (that inline function is always a good target), `uv_alloc_stor_var`, `uv_free_stor_var`, the `kvm_s390_pv_*` functions, `ex_handler_zeropad`, and `do_secure_storage_access`.

Time to dig into the Kconfig to see what's enabling `DCACHE_WORD_ACCESS`. I'll see if `S390` is selecting it. And I'll double-check what config options are required to enable `uv.c` and `kvm/pv.c`, just to get a fuller picture of the context and the build configuration.



4/2 2026/07/16 18:47 tool grepper
0m Args:
{
  "Expression": "uv\\.o",
  "PathPrefix": "arch/s390/kernel/Makefile"
}

Results:
{
  "Output": "arch/s390/kernel/Makefile=45=obj-y\t+= nospec-branch.o ipl_vmparm.o machine_kexec_reloc.o unwind_bc.o\narch/s390/kernel/Makefile:46:obj-y\t+= smp.o text_amode31.o stacktrace.o abs_lowcore.o facility.o uv.o wti.o\narch/s390/kernel/Makefile-47-obj-y\t+= diag/\n"
}

5/2 2026/07/16 18:47 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 6762
							output: 34
							thoughts: 26
						

Thoughts:
Okay, here's my interpretation of those thoughts, tailored for an expert audience, and delivered as a first-person summary:

**Considering s390 Build Habits and KVM/PV.c**

Alright, I'm thinking about this build process... Specifically, I'm seeing that the `uv.o` object file *always* seems to be compiled and built specifically for the s390 architecture. It's a bit of a given at this point, but it triggers something in the back of my mind.

Then the question hits me: what about `kvm/pv.c`? Is that file also consistently built with s390 in mind, or are there conditional compilation elements at play? If it's *not* always an s390-specific build, I need to understand what's driving the difference. Are there platform-specific optimizations or architectural considerations inherent in `uv.o` that *aren't* as strongly present in the KVM paravirtualization code? Or perhaps there are very specific use cases for one or the other? This could be because KVM/PV is expected to be more portable, but UV might have very specific features for s390 which it needs to leverage.
Essentially, I'm trying to figure out why one seems to be an s390 given, and the other doesn't appear as such at first glance. It's time to dig deeper into the build configurations and the code itself to see if the assumptions hold, and the reasons why.



6/2 2026/07/16 18:47 tool grepper
0m Args:
{
  "Expression": "pv\\.o",
  "PathPrefix": "arch/s390/kvm/Makefile"
}

Results:
{
  "Output": "arch/s390/kvm/Makefile=10=kvm-y += kvm-s390.o intercept.o interrupt.o priv.o sigp.o\narch/s390/kvm/Makefile:11:kvm-y += diag.o gaccess.o guestdbg.o vsie.o pv.o\narch/s390/kvm/Makefile-12-kvm-y += dat.o gmap.o faultin.o\n"
}

7/2 2026/07/16 18:47 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 7273
							output: 39
							thoughts: 69
						

Thoughts:
Okay, let's break this down.

**KVM Configuration and Secure Storage Access**

Right, so `pv.o` is consistently built whenever KVM is active. That’s a clear indication that KVM is the deciding factor in its inclusion. In other words, `KVM` is the config option that triggers it. Wait a moment, I think I remember this: for s390, KVM is explicitly labeled as `CONFIG_KVM`. That confirms my initial assessment.

Now, let's pivot to investigating `do_secure_storage_access`. Specifically, I'll need to check the implementation of that function within `arch/s390/mm/fault.c`. That seems to be the right place to get a deeper look at the secure storage access implementation within the s390 architecture. This is where the magic happens.



8/2 2026/07/16 18:47 tool grepper
0m Args:
{
  "Expression": "do_secure_storage_access",
  "PathPrefix": "arch/s390/mm/fault.c"
}

Results:
{
  "Output": "arch/s390/mm/fault.c=404=NOKPROBE_SYMBOL(do_dat_exception);\n--\narch/s390/mm/fault.c-407-\narch/s390/mm/fault.c:408:void do_secure_storage_access(struct pt_regs *regs)\narch/s390/mm/fault.c-409-{\n--\narch/s390/mm/fault.c-473-}\narch/s390/mm/fault.c:474:NOKPROBE_SYMBOL(do_secure_storage_access);\narch/s390/mm/fault.c-475-\n"
}

9/2 2026/07/16 18:47 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 7751
							output: 40
							thoughts: 184
						

Thoughts:
**Analyzing the Storage Variable Allocation Code**

Okay, let's break this down. My focus right now is on these core functions: `uv_alloc_stor_var`, `uv_free_stor_var`, `ex_handler_zeropad`, and `do_secure_storage_access`. These are the key areas where I suspect modifications or potential interactions will be critical.

Now, for the configs. The instructions say to only list those configs that directly relate to the code, and not the generic stuff. `S390` is the base architecture, so that's implicit. But the presence of `kvm_s390_pv_alloc_vm` and related functions points directly to `KVM`. Therefore, `KVM` is the config I'm most interested in, given the presence of those specific functions.

A quick check confirms that `arch/s390/kvm/Makefile` is the relevant file, so `KVM` is indeed the correct configuration flag to consider here. That should be sufficient for now.



10/2 2026/07/16 18:47 tool grepper
0m Args:
{
  "Expression": "obj-\\$\\(CONFIG_KVM\\)",
  "PathPrefix": "arch/s390/kvm/Makefile"
}

Results:
{
  "Output": "arch/s390/kvm/Makefile=14=kvm-$(CONFIG_VFIO_PCI_ZDEV_KVM) += pci.o\narch/s390/kvm/Makefile:15:obj-$(CONFIG_KVM) += kvm.o\n"
}

11/2 2026/07/16 18:47 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 8280
							output: 40
							thoughts: 89
						

Thoughts:
Okay, here's my interpretation of this configuration process, expressed as my internal thought process:

**Configuration Analysis: KVM and Implicit Dependencies**

Alright, the system is configured with `CONFIG_KVM`. That's the baseline, the core of the hypervisor support. Now, the next step is to see if there are any *other* configurations tied in or affected by this.

Aha! It looks like `DCACHE_WORD_ACCESS` is automatically selected based on the architecture, which is `S390`, *unless* `KMSAN` is *not* enabled. So, in this scenario given that we know `CONFIG_KVM` is configured, `DCACHE_WORD_ACCESS` is implicitly enabled because we don't know the state of `KMSAN`.

Now, I'm going to shift gears slightly and check on `ex_handler_zeropad` within `arch/s390/mm/extable.c`.



12/2 2026/07/16 18:47 tool grepper
0m Args:
{
  "Expression": "ex_handler_zeropad",
  "PathPrefix": "arch/s390/mm/extable.c"
}

Results:
{
  "Output": "arch/s390/mm/extable.c=39=static bool ex_handler_ua_load_reg(const struct exception_table_entry *ex,\n--\narch/s390/mm/extable.c-52-\narch/s390/mm/extable.c:53:static bool ex_handler_zeropad(const struct exception_table_entry *ex, struct pt_regs *regs)\narch/s390/mm/extable.c-54-{\n--\narch/s390/mm/extable.c=119=bool fixup_exception(struct pt_regs *regs)\n--\narch/s390/mm/extable.c-137-\tcase EX_TYPE_ZEROPAD:\narch/s390/mm/extable.c:138:\t\treturn ex_handler_zeropad(ex, regs);\narch/s390/mm/extable.c-139-\tcase EX_TYPE_FPC:\n"
}

13/2 2026/07/16 18:47 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 8879
							output: 39
							thoughts: 111
						

Thoughts:
Okay, here's my breakdown of what I'm looking at, from my expert perspective:

**Prioritizing Code Analysis: Key Functions for Deep Dive**

Right, so I'm honing in on specific functions within this codebase. It's clear that these are the ones to scrutinize most closely. My primary focus is going to be on: `uv_alloc_stor_var` and `uv_free_stor_var` – these are crucial for understanding how storage variables are allocated and deallocated. That's a classic area for memory management bugs or security vulnerabilities. Next up, `ex_handler_zeropad` is interesting; zero-padding functions are often involved in sensitive data handling, and I'll need to confirm that this one is implemented correctly, including looking for potential padding oracle attack vectors. Moving on to secure storage access, `do_secure_storage_access` is obviously critical; any flaw here could compromise the entire system's security posture. I need to understand the access control mechanisms, encryption, and authentication involved. Finally, the KVM/s390 virtualization specific functions `kvm_s390_pv_alloc_vm` and `kvm_s390_pv_dealloc_vm` look like key pieces for managing virtual machine resources. I'll need to explore these in context to confirm whether there are issues here related to resource exhaustion, or any security concerns.

I've also noticed a couple of additional functions that warrant further investigation: `uv_free_range_cb` and `uv_alloc_range_cb`. These *could* be involved in similar memory or resource allocation/deallocation tasks as the initial functions.



14/2 2026/07/16 18:48 tool grepper
0m Args:
{
  "Expression": "uv_free_range_cb",
  "PathPrefix": "arch/s390/kernel/uv.c"
}

Results:
{
  "Output": "arch/s390/kernel/uv.c=207=int uv_convert_from_secure_pte(pte_t pte)\n--\narch/s390/kernel/uv.c-212-\narch/s390/kernel/uv.c:213:static int uv_free_range_cb(pte_t *ptep, unsigned long addr, void *data)\narch/s390/kernel/uv.c-214-{\n--\narch/s390/kernel/uv.c=223=void uv_free_stor_var(void *stor_var)\n--\narch/s390/kernel/uv.c-234-\taddr = (unsigned long)area-\u003eaddr;\narch/s390/kernel/uv.c:235:\tapply_to_existing_page_range(\u0026init_mm, addr, size, uv_free_range_cb, NULL);\narch/s390/kernel/uv.c-236-\tfree_vm_area(area);\n"
}

15/2 2026/07/16 18:48 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 9655
							output: 220
							thoughts: 247
						

Thoughts:
**My Assessment of the Patch's Fuzzing Potential**

Okay, here's the breakdown. I see this patch introduces changes that are definitely worth a closer look from a fuzzing perspective. The key functions to target are `uv_free_range_cb` and `uv_alloc_range_cb` - the memory allocation/deallocation callbacks are always critical areas to explore for potential vulnerabilities.

Let's summarize my analysis:

*   **WorthFuzzing:** Absolutely.
*   **Focus Symbols:** We need to prioritize these symbols when setting up the fuzzing campaign:
    *   `uv_alloc_stor_var`
    *   `uv_free_stor_var`
    *   `uv_alloc_range_cb`
    *   `uv_free_range_cb`
    *   `ex_handler_zeropad`
    *   `do_secure_storage_access`
    *   `kvm_s390_pv_alloc_vm`
    *   `kvm_s390_pv_dealloc_vm`

*   **Enable Configurations:** The `KVM` configuration needs to be enabled for this fuzzing campaign, as the changes are related to that subsystem.

*   **Reasoning:** This patch digs into s390 architecture specifics, which always pique my interest. I see functionality that specifically relates to unaligned word loads with zero padding, and Protected Virtualization memory management, which, from an attack surface point of view, is a high-value target. These modifications touch core kernel logic and exception handling, and those are prime candidates for uncovering memory safety bugs or correctness issues through fuzzing. The interplay of memory allocation and exception handling is a classic recipe for vulnerability. It's time to set up the fuzzers and get to work.



16/2 2026/07/16 18:48 tool set-results
0m Args:
{
  "EnableConfigs": [
    "KVM"
  ],
  "FocusSymbols": [
    "uv_alloc_stor_var",
    "uv_free_stor_var",
    "uv_alloc_range_cb",
    "uv_free_range_cb",
    "ex_handler_zeropad",
    "do_secure_storage_access",
    "kvm_s390_pv_alloc_vm",
    "kvm_s390_pv_dealloc_vm"
  ],
  "Reasoning": "The patch introduces functional changes to s390 architecture code, specifically handling of unaligned word loads with zero padding (`load_unaligned_zeropad`, `ex_handler_zeropad`), and memory allocation for KVM Protected Virtualization (`uv_alloc_stor_var`, `uv_free_stor_var`). These changes modify reachable core kernel logic and exception handling, which should be fuzzed to ensure memory safety and correctness.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "KVM"
  ],
  "FocusSymbols": [
    "uv_alloc_stor_var",
    "uv_free_stor_var",
    "uv_alloc_range_cb",
    "uv_free_range_cb",
    "ex_handler_zeropad",
    "do_secure_storage_access",
    "kvm_s390_pv_alloc_vm",
    "kvm_s390_pv_dealloc_vm"
  ],
  "Reasoning": "The patch introduces functional changes to s390 architecture code, specifically handling of unaligned word loads with zero padding (`load_unaligned_zeropad`, `ex_handler_zeropad`), and memory allocation for KVM Protected Virtualization (`uv_alloc_stor_var`, `uv_free_stor_var`). These changes modify reachable core kernel logic and exception handling, which should be fuzzed to ensure memory safety and correctness.",
  "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)