Linux Documentation
 help / color / mirror / Atom feed
* [RFC v1 3/9] kho: split out vmalloc preservation into kho_vmalloc.c
From: Pasha Tatashin @ 2026-06-05  3:32 UTC (permalink / raw)
  To: linux-kselftest, rppt, shuah, akpm, linux-mm, skhan, linux-doc,
	jasonmiu, linux-kernel, corbet, ran.xiaokai, pasha.tatashin,
	kexec, pratyush, graf
In-Reply-To: <20260605033235.717351-1-pasha.tatashin@soleen.com>

Move the vmalloc serialization and preservation implementation out of the
core KHO code into its own dedicated file (kho_vmalloc.c).

This is a pure code movement patch; no logic or functional changes are
introduced.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 Documentation/core-api/kho/index.rst |   3 +
 kernel/liveupdate/Makefile           |   3 +-
 kernel/liveupdate/kexec_handover.c   | 258 +------------------------
 kernel/liveupdate/kho_vmalloc.c      | 274 +++++++++++++++++++++++++++
 lib/test_kho.c                       |   1 +
 mm/memfd_luo.c                       |   1 +
 6 files changed, 282 insertions(+), 258 deletions(-)
 create mode 100644 kernel/liveupdate/kho_vmalloc.c

diff --git a/Documentation/core-api/kho/index.rst b/Documentation/core-api/kho/index.rst
index f69367d217cf..a10b10700fb9 100644
--- a/Documentation/core-api/kho/index.rst
+++ b/Documentation/core-api/kho/index.rst
@@ -86,6 +86,9 @@ Public API
 .. kernel-doc:: kernel/liveupdate/kho_radix.c
   :export:
 
+.. kernel-doc:: kernel/liveupdate/kho_vmalloc.c
+  :export:
+
 KHO Serialization Blocks API
 ============================
 
diff --git a/kernel/liveupdate/Makefile b/kernel/liveupdate/Makefile
index a3ee8a5c27a2..b481e21a311a 100644
--- a/kernel/liveupdate/Makefile
+++ b/kernel/liveupdate/Makefile
@@ -9,7 +9,8 @@ luo-y :=								\
 
 kho-y :=								\
 		kexec_handover.o					\
-		kho_radix.o
+		kho_radix.o						\
+		kho_vmalloc.o
 
 obj-$(CONFIG_KEXEC_HANDOVER)		+= kho.o
 obj-$(CONFIG_KEXEC_HANDOVER_DEBUG)	+= kexec_handover_debug.o
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 4a3d6a54a17f..6672bc168e57 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -13,7 +13,6 @@
 #include <linux/cma.h>
 #include <linux/kmemleak.h>
 #include <linux/count_zeros.h>
-#include <linux/kasan.h>
 #include <linux/kexec.h>
 #include <linux/kexec_handover.h>
 #include <linux/kho/radix_tree.h>
@@ -23,11 +22,7 @@
 #include <linux/libfdt.h>
 #include <linux/list.h>
 #include <linux/memblock.h>
-#include <linux/page-isolation.h>
 #include <linux/unaligned.h>
-#include <linux/vmalloc.h>
-
-#include <asm/early_ioremap.h>
 
 /*
  * KHO is tightly coupled with mm init and needs access to some of mm
@@ -84,6 +79,7 @@ static struct kho_out kho_out = {
 };
 
 
+
 /* For physically contiguous 0-order pages. */
 static void kho_init_pages(struct page *page, unsigned long nr_pages)
 {
@@ -702,259 +698,7 @@ void kho_unpreserve_pages(struct page *page, unsigned long nr_pages)
 }
 EXPORT_SYMBOL_GPL(kho_unpreserve_pages);
 
-/* vmalloc flags KHO supports */
-#define KHO_VMALLOC_SUPPORTED_FLAGS	(VM_ALLOC | VM_ALLOW_HUGE_VMAP)
-
-/* KHO internal flags for vmalloc preservations */
-#define KHO_VMALLOC_ALLOC	0x0001
-#define KHO_VMALLOC_HUGE_VMAP	0x0002
-
-static unsigned short vmalloc_flags_to_kho(unsigned int vm_flags)
-{
-	unsigned short kho_flags = 0;
-
-	if (vm_flags & VM_ALLOC)
-		kho_flags |= KHO_VMALLOC_ALLOC;
-	if (vm_flags & VM_ALLOW_HUGE_VMAP)
-		kho_flags |= KHO_VMALLOC_HUGE_VMAP;
-
-	return kho_flags;
-}
-
-static unsigned int kho_flags_to_vmalloc(unsigned short kho_flags)
-{
-	unsigned int vm_flags = 0;
-
-	if (kho_flags & KHO_VMALLOC_ALLOC)
-		vm_flags |= VM_ALLOC;
-	if (kho_flags & KHO_VMALLOC_HUGE_VMAP)
-		vm_flags |= VM_ALLOW_HUGE_VMAP;
-
-	return vm_flags;
-}
-
-static struct kho_vmalloc_chunk *new_vmalloc_chunk(struct kho_vmalloc_chunk *cur)
-{
-	struct kho_vmalloc_chunk *chunk;
-	int err;
-
-	chunk = (struct kho_vmalloc_chunk *)get_zeroed_page(GFP_KERNEL);
-	if (!chunk)
-		return NULL;
-
-	err = kho_preserve_pages(virt_to_page(chunk), 1);
-	if (err)
-		goto err_free;
-	if (cur)
-		KHOSER_STORE_PTR(cur->hdr.next, chunk);
-	return chunk;
-
-err_free:
-	free_page((unsigned long)chunk);
-	return NULL;
-}
-
-static void kho_vmalloc_unpreserve_chunk(struct kho_vmalloc_chunk *chunk,
-					 unsigned short order)
-{
-	struct kho_radix_tree *tree = &kho_out.radix_tree;
-	unsigned long pfn = PHYS_PFN(virt_to_phys(chunk));
-
-	__kho_unpreserve(tree, pfn, pfn + 1);
-
-	for (int i = 0; i < ARRAY_SIZE(chunk->phys) && chunk->phys[i]; i++) {
-		pfn = PHYS_PFN(chunk->phys[i]);
-		__kho_unpreserve(tree, pfn, pfn + (1 << order));
-	}
-}
-
-/**
- * kho_preserve_vmalloc - preserve memory allocated with vmalloc() across kexec
- * @ptr: pointer to the area in vmalloc address space
- * @preservation: placeholder for preservation metadata
- *
- * Instructs KHO to preserve the area in vmalloc address space at @ptr. The
- * physical pages mapped at @ptr will be preserved and on successful return
- * @preservation will hold the physical address of a structure that describes
- * the preservation.
- *
- * NOTE: The memory allocated with vmalloc_node() variants cannot be reliably
- * restored on the same node
- *
- * Return: 0 on success, error code on failure
- */
-int kho_preserve_vmalloc(void *ptr, struct kho_vmalloc *preservation)
-{
-	struct kho_vmalloc_chunk *chunk;
-	struct vm_struct *vm = find_vm_area(ptr);
-	unsigned int order, flags, nr_contig_pages;
-	unsigned int idx = 0;
-	int err;
-
-	if (!vm)
-		return -EINVAL;
-
-	if (vm->flags & ~KHO_VMALLOC_SUPPORTED_FLAGS)
-		return -EOPNOTSUPP;
-
-	flags = vmalloc_flags_to_kho(vm->flags);
-	order = get_vm_area_page_order(vm);
-
-	chunk = new_vmalloc_chunk(NULL);
-	if (!chunk)
-		return -ENOMEM;
-	KHOSER_STORE_PTR(preservation->first, chunk);
-
-	nr_contig_pages = (1 << order);
-	for (int i = 0; i < vm->nr_pages; i += nr_contig_pages) {
-		phys_addr_t phys = page_to_phys(vm->pages[i]);
-
-		err = kho_preserve_pages(vm->pages[i], nr_contig_pages);
-		if (err)
-			goto err_free;
-
-		chunk->phys[idx++] = phys;
-		if (idx == ARRAY_SIZE(chunk->phys)) {
-			chunk = new_vmalloc_chunk(chunk);
-			if (!chunk) {
-				err = -ENOMEM;
-				goto err_free;
-			}
-			idx = 0;
-		}
-	}
-
-	preservation->total_pages = vm->nr_pages;
-	preservation->flags = flags;
-	preservation->order = order;
-
-	return 0;
-
-err_free:
-	kho_unpreserve_vmalloc(preservation);
-	return err;
-}
-EXPORT_SYMBOL_GPL(kho_preserve_vmalloc);
-
-/**
- * kho_unpreserve_vmalloc - unpreserve memory allocated with vmalloc()
- * @preservation: preservation metadata returned by kho_preserve_vmalloc()
- *
- * Instructs KHO to unpreserve the area in vmalloc address space that was
- * previously preserved with kho_preserve_vmalloc().
- */
-void kho_unpreserve_vmalloc(struct kho_vmalloc *preservation)
-{
-	struct kho_vmalloc_chunk *chunk = KHOSER_LOAD_PTR(preservation->first);
-
-	while (chunk) {
-		struct kho_vmalloc_chunk *tmp = chunk;
-
-		kho_vmalloc_unpreserve_chunk(chunk, preservation->order);
-
-		chunk = KHOSER_LOAD_PTR(chunk->hdr.next);
-		free_page((unsigned long)tmp);
-	}
-}
-EXPORT_SYMBOL_GPL(kho_unpreserve_vmalloc);
-
-/**
- * kho_restore_vmalloc - recreates and populates an area in vmalloc address
- * space from the preserved memory.
- * @preservation: preservation metadata.
- *
- * Recreates an area in vmalloc address space and populates it with memory that
- * was preserved using kho_preserve_vmalloc().
- *
- * Return: pointer to the area in the vmalloc address space, NULL on failure.
- */
-void *kho_restore_vmalloc(const struct kho_vmalloc *preservation)
-{
-	struct kho_vmalloc_chunk *chunk = KHOSER_LOAD_PTR(preservation->first);
-	kasan_vmalloc_flags_t kasan_flags = KASAN_VMALLOC_PROT_NORMAL;
-	unsigned int align, order, shift, vm_flags;
-	unsigned long total_pages, contig_pages;
-	unsigned long addr, size;
-	struct vm_struct *area;
-	struct page **pages;
-	unsigned int idx = 0;
-	int err;
-
-	vm_flags = kho_flags_to_vmalloc(preservation->flags);
-	if (vm_flags & ~KHO_VMALLOC_SUPPORTED_FLAGS)
-		return NULL;
-
-	total_pages = preservation->total_pages;
-	pages = kvmalloc_objs(*pages, total_pages);
-	if (!pages)
-		return NULL;
-	order = preservation->order;
-	contig_pages = (1 << order);
-	shift = PAGE_SHIFT + order;
-	align = 1 << shift;
-
-	while (chunk) {
-		struct page *page;
-
-		for (int i = 0; i < ARRAY_SIZE(chunk->phys) && chunk->phys[i]; i++) {
-			phys_addr_t phys = chunk->phys[i];
-
-			if (idx + contig_pages > total_pages)
-				goto err_free_pages_array;
-
-			page = kho_restore_pages(phys, contig_pages);
-			if (!page)
-				goto err_free_pages_array;
-
-			for (int j = 0; j < contig_pages; j++)
-				pages[idx++] = page + j;
-
-			phys += contig_pages * PAGE_SIZE;
-		}
-
-		page = kho_restore_pages(virt_to_phys(chunk), 1);
-		if (!page)
-			goto err_free_pages_array;
-		chunk = KHOSER_LOAD_PTR(chunk->hdr.next);
-		__free_page(page);
-	}
-
-	if (idx != total_pages)
-		goto err_free_pages_array;
-
-	area = __get_vm_area_node(total_pages * PAGE_SIZE, align, shift,
-				  vm_flags | VM_UNINITIALIZED,
-				  VMALLOC_START, VMALLOC_END,
-				  NUMA_NO_NODE, GFP_KERNEL,
-				  __builtin_return_address(0));
-	if (!area)
-		goto err_free_pages_array;
-
-	addr = (unsigned long)area->addr;
-	size = get_vm_area_size(area);
-	err = vmap_pages_range(addr, addr + size, PAGE_KERNEL, pages, shift);
-	if (err)
-		goto err_free_vm_area;
 
-	area->nr_pages = total_pages;
-	area->pages = pages;
-
-	if (vm_flags & VM_ALLOC)
-		kasan_flags |= KASAN_VMALLOC_VM_ALLOC;
-
-	area->addr = kasan_unpoison_vmalloc(area->addr, total_pages * PAGE_SIZE,
-					    kasan_flags);
-	clear_vm_uninitialized_flag(area);
-
-	return area->addr;
-
-err_free_vm_area:
-	free_vm_area(area);
-err_free_pages_array:
-	kvfree(pages);
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(kho_restore_vmalloc);
 
 /**
  * kho_alloc_preserve - Allocate, zero, and preserve memory.
diff --git a/kernel/liveupdate/kho_vmalloc.c b/kernel/liveupdate/kho_vmalloc.c
new file mode 100644
index 000000000000..84c17b7a81ae
--- /dev/null
+++ b/kernel/liveupdate/kho_vmalloc.c
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * kho_vmalloc.c - KHO vmalloc space serialization/preservation
+ * Copyright (C) 2025 Microsoft Corporation, Mike Rapoport <rppt@kernel.org>
+ * Copyright (C) 2025 Pasha Tatashin <pasha.tatashin@soleen.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <linux/io.h>
+#include <linux/kasan.h>
+#include <linux/kexec_handover.h>
+#include <linux/kho/abi/kexec_handover.h>
+#include <linux/kho/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+
+#include "../../mm/internal.h"
+#include "kexec_handover_internal.h"
+
+/* vmalloc flags KHO supports */
+#define KHO_VMALLOC_SUPPORTED_FLAGS	(VM_ALLOC | VM_ALLOW_HUGE_VMAP)
+
+/* KHO internal flags for vmalloc preservations */
+#define KHO_VMALLOC_ALLOC	0x0001
+#define KHO_VMALLOC_HUGE_VMAP	0x0002
+
+static unsigned short vmalloc_flags_to_kho(unsigned int vm_flags)
+{
+	unsigned short kho_flags = 0;
+
+	if (vm_flags & VM_ALLOC)
+		kho_flags |= KHO_VMALLOC_ALLOC;
+	if (vm_flags & VM_ALLOW_HUGE_VMAP)
+		kho_flags |= KHO_VMALLOC_HUGE_VMAP;
+
+	return kho_flags;
+}
+
+static unsigned int kho_flags_to_vmalloc(unsigned short kho_flags)
+{
+	unsigned int vm_flags = 0;
+
+	if (kho_flags & KHO_VMALLOC_ALLOC)
+		vm_flags |= VM_ALLOC;
+	if (kho_flags & KHO_VMALLOC_HUGE_VMAP)
+		vm_flags |= VM_ALLOW_HUGE_VMAP;
+
+	return vm_flags;
+}
+
+static struct kho_vmalloc_chunk *new_vmalloc_chunk(struct kho_vmalloc_chunk *cur)
+{
+	struct kho_vmalloc_chunk *chunk;
+	int err;
+
+	chunk = (struct kho_vmalloc_chunk *)get_zeroed_page(GFP_KERNEL);
+	if (!chunk)
+		return NULL;
+
+	err = kho_preserve_pages(virt_to_page(chunk), 1);
+	if (err)
+		goto err_free;
+	if (cur)
+		KHOSER_STORE_PTR(cur->hdr.next, chunk);
+	return chunk;
+
+err_free:
+	free_page((unsigned long)chunk);
+	return NULL;
+}
+
+static void kho_vmalloc_unpreserve_chunk(struct kho_vmalloc_chunk *chunk,
+					 unsigned short order)
+{
+	unsigned long pfn = PHYS_PFN(virt_to_phys(chunk));
+
+	kho_unpreserve_pages(pfn_to_page(pfn), 1);
+
+	for (int i = 0; i < ARRAY_SIZE(chunk->phys) && chunk->phys[i]; i++) {
+		pfn = PHYS_PFN(chunk->phys[i]);
+		kho_unpreserve_pages(pfn_to_page(pfn), 1 << order);
+	}
+}
+
+/**
+ * kho_preserve_vmalloc - preserve memory allocated with vmalloc() across kexec
+ * @ptr: pointer to the area in vmalloc address space
+ * @preservation: placeholder for preservation metadata
+ *
+ * Instructs KHO to preserve the area in vmalloc address space at @ptr. The
+ * physical pages mapped at @ptr will be preserved and on successful return
+ * @preservation will hold the physical address of a structure that describes
+ * the preservation.
+ *
+ * NOTE: The memory allocated with vmalloc_node() variants cannot be reliably
+ * restored on the same node
+ *
+ * Return: 0 on success, error code on failure
+ */
+int kho_preserve_vmalloc(void *ptr, struct kho_vmalloc *preservation)
+{
+	struct kho_vmalloc_chunk *chunk;
+	struct vm_struct *vm = find_vm_area(ptr);
+	unsigned int order, flags, nr_contig_pages;
+	unsigned int idx = 0;
+	int err;
+
+	if (!vm)
+		return -EINVAL;
+
+	if (vm->flags & ~KHO_VMALLOC_SUPPORTED_FLAGS)
+		return -EOPNOTSUPP;
+
+	flags = vmalloc_flags_to_kho(vm->flags);
+	order = get_vm_area_page_order(vm);
+
+	chunk = new_vmalloc_chunk(NULL);
+	if (!chunk)
+		return -ENOMEM;
+	KHOSER_STORE_PTR(preservation->first, chunk);
+
+	nr_contig_pages = (1 << order);
+	for (int i = 0; i < vm->nr_pages; i += nr_contig_pages) {
+		phys_addr_t phys = page_to_phys(vm->pages[i]);
+
+		err = kho_preserve_pages(vm->pages[i], nr_contig_pages);
+		if (err)
+			goto err_free;
+
+		chunk->phys[idx++] = phys;
+		if (idx == ARRAY_SIZE(chunk->phys)) {
+			chunk = new_vmalloc_chunk(chunk);
+			if (!chunk) {
+				err = -ENOMEM;
+				goto err_free;
+			}
+			idx = 0;
+		}
+	}
+
+	preservation->total_pages = vm->nr_pages;
+	preservation->flags = flags;
+	preservation->order = order;
+
+	return 0;
+
+err_free:
+	kho_unpreserve_vmalloc(preservation);
+	return err;
+}
+EXPORT_SYMBOL_GPL(kho_preserve_vmalloc);
+
+/**
+ * kho_unpreserve_vmalloc - unpreserve memory allocated with vmalloc()
+ * @preservation: preservation metadata returned by kho_preserve_vmalloc()
+ *
+ * Instructs KHO to unpreserve the area in vmalloc address space that was
+ * previously preserved with kho_preserve_vmalloc().
+ */
+void kho_unpreserve_vmalloc(struct kho_vmalloc *preservation)
+{
+	struct kho_vmalloc_chunk *chunk = KHOSER_LOAD_PTR(preservation->first);
+
+	while (chunk) {
+		struct kho_vmalloc_chunk *tmp = chunk;
+
+		kho_vmalloc_unpreserve_chunk(chunk, preservation->order);
+
+		chunk = KHOSER_LOAD_PTR(chunk->hdr.next);
+		free_page((unsigned long)tmp);
+	}
+}
+EXPORT_SYMBOL_GPL(kho_unpreserve_vmalloc);
+
+/**
+ * kho_restore_vmalloc - recreates and populates an area in vmalloc address
+ * space from the preserved memory.
+ * @preservation: preservation metadata.
+ *
+ * Recreates an area in vmalloc address space and populates it with memory that
+ * was preserved using kho_preserve_vmalloc().
+ *
+ * Return: pointer to the area in the vmalloc address space, NULL on failure.
+ */
+void *kho_restore_vmalloc(const struct kho_vmalloc *preservation)
+{
+	struct kho_vmalloc_chunk *chunk = KHOSER_LOAD_PTR(preservation->first);
+	kasan_vmalloc_flags_t kasan_flags = KASAN_VMALLOC_PROT_NORMAL;
+	unsigned int align, order, shift, vm_flags;
+	unsigned long total_pages, contig_pages;
+	unsigned long addr, size;
+	struct vm_struct *area;
+	struct page **pages;
+	unsigned int idx = 0;
+	int err;
+
+	vm_flags = kho_flags_to_vmalloc(preservation->flags);
+	if (vm_flags & ~KHO_VMALLOC_SUPPORTED_FLAGS)
+		return NULL;
+
+	total_pages = preservation->total_pages;
+	pages = kvmalloc_objs(*pages, total_pages);
+	if (!pages)
+		return NULL;
+	order = preservation->order;
+	contig_pages = (1 << order);
+	shift = PAGE_SHIFT + order;
+	align = 1 << shift;
+
+	while (chunk) {
+		struct page *page;
+
+		for (int i = 0; i < ARRAY_SIZE(chunk->phys) && chunk->phys[i]; i++) {
+			phys_addr_t phys = chunk->phys[i];
+
+			if (idx + contig_pages > total_pages)
+				goto err_free_pages_array;
+
+			page = kho_restore_pages(phys, contig_pages);
+			if (!page)
+				goto err_free_pages_array;
+
+			for (int j = 0; j < contig_pages; j++)
+				pages[idx++] = page + j;
+
+			phys += contig_pages * PAGE_SIZE;
+		}
+
+		page = kho_restore_pages(virt_to_phys(chunk), 1);
+		if (!page)
+			goto err_free_pages_array;
+		chunk = KHOSER_LOAD_PTR(chunk->hdr.next);
+		__free_page(page);
+	}
+
+	if (idx != total_pages)
+		goto err_free_pages_array;
+
+	area = __get_vm_area_node(total_pages * PAGE_SIZE, align, shift,
+				  vm_flags | VM_UNINITIALIZED,
+				  VMALLOC_START, VMALLOC_END,
+				  NUMA_NO_NODE, GFP_KERNEL,
+				  __builtin_return_address(0));
+	if (!area)
+		goto err_free_pages_array;
+
+	addr = (unsigned long)area->addr;
+	size = get_vm_area_size(area);
+	err = vmap_pages_range(addr, addr + size, PAGE_KERNEL, pages, shift);
+	if (err)
+		goto err_free_vm_area;
+
+	area->nr_pages = total_pages;
+	area->pages = pages;
+
+	if (vm_flags & VM_ALLOC)
+		kasan_flags |= KASAN_VMALLOC_VM_ALLOC;
+
+	area->addr = kasan_unpoison_vmalloc(area->addr, total_pages * PAGE_SIZE,
+					    kasan_flags);
+	clear_vm_uninitialized_flag(area);
+
+	return area->addr;
+
+err_free_vm_area:
+	free_vm_area(area);
+err_free_pages_array:
+	kvfree(pages);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(kho_restore_vmalloc);
diff --git a/lib/test_kho.c b/lib/test_kho.c
index aa6a0956bb8b..6907e09688dd 100644
--- a/lib/test_kho.c
+++ b/lib/test_kho.c
@@ -20,6 +20,7 @@
 #include <linux/vmalloc.h>
 #include <linux/kexec_handover.h>
 #include <linux/kho/abi/kexec_handover.h>
+#include <linux/kho/vmalloc.h>
 
 #include <net/checksum.h>
 
diff --git a/mm/memfd_luo.c b/mm/memfd_luo.c
index 59de210bee5f..ade2aa24c7b8 100644
--- a/mm/memfd_luo.c
+++ b/mm/memfd_luo.c
@@ -76,6 +76,7 @@
 #include <linux/io.h>
 #include <linux/kexec_handover.h>
 #include <linux/kho/abi/memfd.h>
+#include <linux/kho/vmalloc.h>
 #include <linux/liveupdate.h>
 #include <linux/shmem_fs.h>
 #include <linux/vmalloc.h>
-- 
2.53.0


^ permalink raw reply related

* [RFC v1 4/9] kho: split vmalloc headers out of kexec_handover.h
From: Pasha Tatashin @ 2026-06-05  3:32 UTC (permalink / raw)
  To: linux-kselftest, rppt, shuah, akpm, linux-mm, skhan, linux-doc,
	jasonmiu, linux-kernel, corbet, ran.xiaokai, pasha.tatashin,
	kexec, pratyush, graf
In-Reply-To: <20260605033235.717351-1-pasha.tatashin@soleen.com>

Split the vmalloc-related ABI definitions and header declarations out
of the monolithic kexec_handover.h header into a dedicated header
file (vmalloc.h).

This is a pure code movement patch; no logic or functional changes are
introduced.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 Documentation/core-api/kho/abi.rst     |  3 +-
 include/linux/kexec_handover.h         | 18 -----
 include/linux/kho/abi/kexec_handover.h | 77 +-------------------
 include/linux/kho/abi/memfd.h          |  3 +-
 include/linux/kho/abi/vmalloc.h        | 99 ++++++++++++++++++++++++++
 include/linux/kho/vmalloc.h            | 34 +++++++++
 6 files changed, 137 insertions(+), 97 deletions(-)
 create mode 100644 include/linux/kho/abi/vmalloc.h
 create mode 100644 include/linux/kho/vmalloc.h

diff --git a/Documentation/core-api/kho/abi.rst b/Documentation/core-api/kho/abi.rst
index da5c6636bb17..b61363679829 100644
--- a/Documentation/core-api/kho/abi.rst
+++ b/Documentation/core-api/kho/abi.rst
@@ -13,8 +13,7 @@ Core Kexec Handover ABI
 vmalloc preservation ABI
 ========================
 
-.. kernel-doc:: include/linux/kho/abi/kexec_handover.h
-   :doc: Kexec Handover ABI for vmalloc Preservation
+.. kernel-doc:: include/linux/kho/abi/vmalloc.h
 
 memblock preservation ABI
 =========================
diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h
index 8968c56d2d73..518fdab2a4d1 100644
--- a/include/linux/kexec_handover.h
+++ b/include/linux/kexec_handover.h
@@ -11,8 +11,6 @@ struct kho_scratch {
 	phys_addr_t size;
 };
 
-struct kho_vmalloc;
-
 struct folio;
 struct page;
 
@@ -24,14 +22,11 @@ int kho_preserve_folio(struct folio *folio);
 void kho_unpreserve_folio(struct folio *folio);
 int kho_preserve_pages(struct page *page, unsigned long nr_pages);
 void kho_unpreserve_pages(struct page *page, unsigned long nr_pages);
-int kho_preserve_vmalloc(void *ptr, struct kho_vmalloc *preservation);
-void kho_unpreserve_vmalloc(struct kho_vmalloc *preservation);
 void *kho_alloc_preserve(size_t size);
 void kho_unpreserve_free(void *mem);
 void kho_restore_free(void *mem);
 struct folio *kho_restore_folio(phys_addr_t phys);
 struct page *kho_restore_pages(phys_addr_t phys, unsigned long nr_pages);
-void *kho_restore_vmalloc(const struct kho_vmalloc *preservation);
 int kho_add_subtree(const char *name, void *blob, size_t size);
 void kho_remove_subtree(void *blob);
 int kho_retrieve_subtree(const char *name, phys_addr_t *phys, size_t *size);
@@ -65,14 +60,6 @@ static inline int kho_preserve_pages(struct page *page, unsigned int nr_pages)
 
 static inline void kho_unpreserve_pages(struct page *page, unsigned int nr_pages) { }
 
-static inline int kho_preserve_vmalloc(void *ptr,
-				       struct kho_vmalloc *preservation)
-{
-	return -EOPNOTSUPP;
-}
-
-static inline void kho_unpreserve_vmalloc(struct kho_vmalloc *preservation) { }
-
 static inline void *kho_alloc_preserve(size_t size)
 {
 	return ERR_PTR(-EOPNOTSUPP);
@@ -92,11 +79,6 @@ static inline struct page *kho_restore_pages(phys_addr_t phys,
 	return NULL;
 }
 
-static inline void *kho_restore_vmalloc(const struct kho_vmalloc *preservation)
-{
-	return NULL;
-}
-
 static inline int kho_add_subtree(const char *name, void *blob, size_t size)
 {
 	return -EOPNOTSUPP;
diff --git a/include/linux/kho/abi/kexec_handover.h b/include/linux/kho/abi/kexec_handover.h
index 99e4a53d4e35..c893b5045078 100644
--- a/include/linux/kho/abi/kexec_handover.h
+++ b/include/linux/kho/abi/kexec_handover.h
@@ -96,80 +96,5 @@
 /* The FDT property for the size of preserved data blobs. */
 #define KHO_SUB_TREE_SIZE_PROP_NAME "blob-size"
 
-/**
- * DOC: Kexec Handover ABI for vmalloc Preservation
- *
- * The Kexec Handover ABI for preserving vmalloc'ed memory is defined by
- * a set of structures and helper macros. The layout of these structures is a
- * stable contract between kernels and is versioned by the KHO_FDT_COMPATIBLE
- * string.
- *
- * The preservation is managed through a main descriptor &struct kho_vmalloc,
- * which points to a linked list of &struct kho_vmalloc_chunk structures. These
- * chunks contain the physical addresses of the preserved pages, allowing the
- * next kernel to reconstruct the vmalloc area with the same content and layout.
- * Helper macros are also defined for storing and loading pointers within
- * these structures.
- */
-
-/* Helper macro to define a union for a serializable pointer. */
-#define DECLARE_KHOSER_PTR(name, type)	\
-	union {                        \
-		u64 phys;              \
-		type ptr;              \
-	} name
-
-/* Stores the physical address of a serializable pointer. */
-#define KHOSER_STORE_PTR(dest, val)               \
-	({                                        \
-		typeof(val) v = val;              \
-		typecheck(typeof((dest).ptr), v); \
-		(dest).phys = virt_to_phys(v);    \
-	})
-
-/* Loads the stored physical address back to a pointer. */
-#define KHOSER_LOAD_PTR(src)						\
-	({                                                                   \
-		typeof(src) s = src;                                         \
-		(typeof((s).ptr))((s).phys ? phys_to_virt((s).phys) : NULL); \
-	})
-
-/*
- * This header is embedded at the beginning of each `kho_vmalloc_chunk`
- * and contains a pointer to the next chunk in the linked list,
- * stored as a physical address for handover.
- */
-struct kho_vmalloc_hdr {
-	DECLARE_KHOSER_PTR(next, struct kho_vmalloc_chunk *);
-};
-
-#define KHO_VMALLOC_SIZE				\
-	((PAGE_SIZE - sizeof(struct kho_vmalloc_hdr)) / \
-	 sizeof(u64))
-
-/*
- * Each chunk is a single page and is part of a linked list that describes
- * a preserved vmalloc area. It contains the header with the link to the next
- * chunk and a zero terminated array of physical addresses of the pages that
- * make up the preserved vmalloc area.
- */
-struct kho_vmalloc_chunk {
-	struct kho_vmalloc_hdr hdr;
-	u64 phys[KHO_VMALLOC_SIZE];
-};
-
-static_assert(sizeof(struct kho_vmalloc_chunk) == PAGE_SIZE);
-
-/*
- * Describes a preserved vmalloc memory area, including the
- * total number of pages, allocation flags, page order, and a pointer to the
- * first chunk of physical page addresses.
- */
-struct kho_vmalloc {
-	DECLARE_KHOSER_PTR(first, struct kho_vmalloc_chunk *);
-	unsigned int total_pages;
-	unsigned short flags;
-	unsigned short order;
-};
-
 #endif	/* _LINUX_KHO_ABI_KEXEC_HANDOVER_H */
+
diff --git a/include/linux/kho/abi/memfd.h b/include/linux/kho/abi/memfd.h
index 08b10fea2afc..af310c0c9fdf 100644
--- a/include/linux/kho/abi/memfd.h
+++ b/include/linux/kho/abi/memfd.h
@@ -11,8 +11,9 @@
 #ifndef _LINUX_KHO_ABI_MEMFD_H
 #define _LINUX_KHO_ABI_MEMFD_H
 
-#include <linux/types.h>
 #include <linux/kho/abi/kexec_handover.h>
+#include <linux/kho/abi/vmalloc.h>
+#include <linux/types.h>
 
 /**
  * DOC: memfd Live Update ABI
diff --git a/include/linux/kho/abi/vmalloc.h b/include/linux/kho/abi/vmalloc.h
new file mode 100644
index 000000000000..87650e1dd774
--- /dev/null
+++ b/include/linux/kho/abi/vmalloc.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2025 Microsoft Corporation, Mike Rapoport <rppt@kernel.org>
+ * Copyright (C) 2025 Pasha Tatashin <pasha.tatashin@soleen.com>
+ */
+
+/**
+ * DOC: Kexec Handover ABI for vmalloc Preservation
+ *
+ * The Kexec Handover ABI for preserving vmalloc'ed memory is defined by
+ * a set of structures and helper macros. The layout of these structures is a
+ * stable contract between kernels and is versioned by the KHO_FDT_COMPATIBLE
+ * string.
+ *
+ * This interface is a contract. Any modification to the structure fields,
+ * compatible strings, or the layout of the serialization structures defined
+ * here constitutes a breaking change. Such changes require incrementing the
+ * version number in the `KHO_FDT_COMPATIBLE` string to prevent a new kernel
+ * from misinterpreting data from an old kernel.
+ *
+ * Changes are allowed provided the compatibility version is incremented;
+ * however, backward/forward compatibility is only guaranteed for kernels
+ * supporting the same ABI version.
+ *
+ * The preservation is managed through a main descriptor &struct kho_vmalloc,
+ * which points to a linked list of &struct kho_vmalloc_chunk structures. These
+ * chunks contain the physical addresses of the preserved pages, allowing the
+ * next kernel to reconstruct the vmalloc area with the same content and layout.
+ * Helper macros are also defined for storing and loading pointers within
+ * these structures.
+ */
+
+#ifndef _LINUX_KHO_ABI_VMALLOC_H
+#define _LINUX_KHO_ABI_VMALLOC_H
+
+#include <linux/types.h>
+#include <asm/page.h>
+
+/* Helper macro to define a union for a serializable pointer. */
+#define DECLARE_KHOSER_PTR(name, type)	\
+	union {                        \
+		u64 phys;              \
+		type ptr;              \
+	} name
+
+/* Stores the physical address of a serializable pointer. */
+#define KHOSER_STORE_PTR(dest, val)               \
+	({                                        \
+		typeof(val) v = val;              \
+		typecheck(typeof((dest).ptr), v); \
+		(dest).phys = virt_to_phys(v);    \
+	})
+
+/* Loads the stored physical address back to a pointer. */
+#define KHOSER_LOAD_PTR(src)						\
+	({                                                                   \
+		typeof(src) s = src;                                         \
+		(typeof((s).ptr))((s).phys ? phys_to_virt((s).phys) : NULL); \
+	})
+
+/*
+ * This header is embedded at the beginning of each `kho_vmalloc_chunk`
+ * and contains a pointer to the next chunk in the linked list,
+ * stored as a physical address for handover.
+ */
+struct kho_vmalloc_hdr {
+	DECLARE_KHOSER_PTR(next, struct kho_vmalloc_chunk *);
+};
+
+#define KHO_VMALLOC_SIZE				\
+	((PAGE_SIZE - sizeof(struct kho_vmalloc_hdr)) / \
+	 sizeof(u64))
+
+/*
+ * Each chunk is a single page and is part of a linked list that describes
+ * a preserved vmalloc area. It contains the header with the link to the next
+ * chunk and a zero terminated array of physical addresses of the pages that
+ * make up the preserved vmalloc area.
+ */
+struct kho_vmalloc_chunk {
+	struct kho_vmalloc_hdr hdr;
+	u64 phys[KHO_VMALLOC_SIZE];
+};
+
+static_assert(sizeof(struct kho_vmalloc_chunk) == PAGE_SIZE);
+
+/*
+ * Describes a preserved vmalloc memory area, including the
+ * total number of pages, allocation flags, page order, and a pointer to the
+ * first chunk of physical page addresses.
+ */
+struct kho_vmalloc {
+	DECLARE_KHOSER_PTR(first, struct kho_vmalloc_chunk *);
+	unsigned int total_pages;
+	unsigned short flags;
+	unsigned short order;
+};
+
+#endif /* _LINUX_KHO_ABI_VMALLOC_H */
diff --git a/include/linux/kho/vmalloc.h b/include/linux/kho/vmalloc.h
new file mode 100644
index 000000000000..2d1b5d282a93
--- /dev/null
+++ b/include/linux/kho/vmalloc.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_KHO_VMALLOC_H
+#define _LINUX_KHO_VMALLOC_H
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/kho/abi/vmalloc.h>
+
+struct page;
+
+#ifdef CONFIG_KEXEC_HANDOVER
+
+int kho_preserve_vmalloc(void *ptr, struct kho_vmalloc *preservation);
+void kho_unpreserve_vmalloc(struct kho_vmalloc *preservation);
+void *kho_restore_vmalloc(const struct kho_vmalloc *preservation);
+
+#else /* CONFIG_KEXEC_HANDOVER */
+
+static inline int kho_preserve_vmalloc(void *ptr,
+				       struct kho_vmalloc *preservation)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void kho_unpreserve_vmalloc(struct kho_vmalloc *preservation) { }
+
+static inline void *kho_restore_vmalloc(const struct kho_vmalloc *preservation)
+{
+	return NULL;
+}
+
+#endif /* CONFIG_KEXEC_HANDOVER */
+
+#endif /* _LINUX_KHO_VMALLOC_H */
-- 
2.53.0


^ permalink raw reply related

* [RFC v1 5/9] kho: move kho_block.h to kho/block.h
From: Pasha Tatashin @ 2026-06-05  3:32 UTC (permalink / raw)
  To: linux-kselftest, rppt, shuah, akpm, linux-mm, skhan, linux-doc,
	jasonmiu, linux-kernel, corbet, ran.xiaokai, pasha.tatashin,
	kexec, pratyush, graf
In-Reply-To: <20260605033235.717351-1-pasha.tatashin@soleen.com>

Move kho_block.h to kho/block.h, organizing it within the existing
kho directory structure as more KHO data structures are introduced.

This is a pure code movement patch; no logic or functional changes are
introduced.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 Documentation/core-api/kho/index.rst       | 2 +-
 MAINTAINERS                                | 1 -
 include/linux/{kho_block.h => kho/block.h} | 2 +-
 kernel/liveupdate/kho_block.c              | 2 +-
 kernel/liveupdate/luo_internal.h           | 2 +-
 kernel/liveupdate/luo_session.c            | 2 +-
 6 files changed, 5 insertions(+), 6 deletions(-)
 rename include/linux/{kho_block.h => kho/block.h} (100%)

diff --git a/Documentation/core-api/kho/index.rst b/Documentation/core-api/kho/index.rst
index a10b10700fb9..4a5477221fe4 100644
--- a/Documentation/core-api/kho/index.rst
+++ b/Documentation/core-api/kho/index.rst
@@ -95,7 +95,7 @@ KHO Serialization Blocks API
 .. kernel-doc:: kernel/liveupdate/kho_block.c
   :doc: KHO Serialization Blocks
 
-.. kernel-doc:: include/linux/kho_block.h
+.. kernel-doc:: include/linux/kho/block.h
 
 .. kernel-doc:: kernel/liveupdate/kho_block.c
   :internal:
diff --git a/MAINTAINERS b/MAINTAINERS
index 920ba7622afa..9ec290e38b44 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14208,7 +14208,6 @@ F:	Documentation/admin-guide/mm/kho.rst
 F:	Documentation/core-api/kho/*
 F:	include/linux/kexec_handover.h
 F:	include/linux/kho/
-F:	include/linux/kho_block.h
 F:	kernel/liveupdate/kexec_handover*
 F:	lib/test_kho.c
 F:	tools/testing/selftests/kho/
diff --git a/include/linux/kho_block.h b/include/linux/kho/block.h
similarity index 100%
rename from include/linux/kho_block.h
rename to include/linux/kho/block.h
index 93a7cc2be5f5..2b9d5a080a6a 100644
--- a/include/linux/kho_block.h
+++ b/include/linux/kho/block.h
@@ -7,9 +7,9 @@
 #ifndef _LINUX_KHO_BLOCK_H
 #define _LINUX_KHO_BLOCK_H
 
+#include <linux/kho/abi/block.h>
 #include <linux/list.h>
 #include <linux/types.h>
-#include <linux/kho/abi/block.h>
 
 /**
  * struct kho_block - Internal representation of a serialization block.
diff --git a/kernel/liveupdate/kho_block.c b/kernel/liveupdate/kho_block.c
index 0d2a342ef422..6cedcd36bfd2 100644
--- a/kernel/liveupdate/kho_block.c
+++ b/kernel/liveupdate/kho_block.c
@@ -23,7 +23,7 @@
 #include <linux/io.h>
 #include <linux/kexec_handover.h>
 #include <linux/kho/abi/block.h>
-#include <linux/kho_block.h>
+#include <linux/kho/block.h>
 #include <linux/slab.h>
 
 /*
diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_internal.h
index 64879ffe7378..349f6d141873 100644
--- a/kernel/liveupdate/luo_internal.h
+++ b/kernel/liveupdate/luo_internal.h
@@ -8,9 +8,9 @@
 #ifndef _LINUX_LUO_INTERNAL_H
 #define _LINUX_LUO_INTERNAL_H
 
+#include <linux/kho/block.h>
 #include <linux/liveupdate.h>
 #include <linux/uaccess.h>
-#include <linux/kho_block.h>
 
 struct luo_ucmd {
 	void __user *ubuffer;
diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
index b79b2a488974..01c0ccf09919 100644
--- a/kernel/liveupdate/luo_session.c
+++ b/kernel/liveupdate/luo_session.c
@@ -90,8 +90,8 @@
 #include <linux/fs.h>
 #include <linux/io.h>
 #include <linux/kexec_handover.h>
-#include <linux/kho_block.h>
 #include <linux/kho/abi/luo.h>
+#include <linux/kho/block.h>
 #include <linux/list.h>
 #include <linux/liveupdate.h>
 #include <linux/mutex.h>
-- 
2.53.0


^ permalink raw reply related

* [RFC v1 6/9] kho: introduce compatibility helpers and decouple block version
From: Pasha Tatashin @ 2026-06-05  3:32 UTC (permalink / raw)
  To: linux-kselftest, rppt, shuah, akpm, linux-mm, skhan, linux-doc,
	jasonmiu, linux-kernel, corbet, ran.xiaokai, pasha.tatashin,
	kexec, pratyush, graf
In-Reply-To: <20260605033235.717351-1-pasha.tatashin@soleen.com>

Decouple the block compatibility string from the global KHO version.

Introduce a compatibility helper header (compat.h) defining utility
macros for constructing subsystem compatibility strings, specifically:
- KHO_SUB_COMPAT() to append sub-component compatibility strings using
  a semicolon separator.
- KHO_COMPAT_ALIGN() to align compatibility string sizes to 8-byte
  boundaries.

Define the individual block compatibility string "block-v1" in block.h,
and integrate it into the composite LUO compatibility string (LUO_ABI_COMPATIBLE)
via the new compatibility helpers.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 include/linux/kho/abi/block.h  |  4 +++-
 include/linux/kho/abi/compat.h | 33 +++++++++++++++++++++++++++++++++
 include/linux/kho/abi/luo.h    |  8 ++++++--
 3 files changed, 42 insertions(+), 3 deletions(-)
 create mode 100644 include/linux/kho/abi/compat.h

diff --git a/include/linux/kho/abi/block.h b/include/linux/kho/abi/block.h
index d06d64b963be..95d13cf677cf 100644
--- a/include/linux/kho/abi/block.h
+++ b/include/linux/kho/abi/block.h
@@ -14,7 +14,7 @@
  * This interface is a contract. Any modification to the structure fields,
  * compatible strings, or the layout of the `__packed` serialization
  * structures defined here constitutes a breaking change. Such changes require
- * incrementing the version number in the `KHO_FDT_COMPATIBLE` string to
+ * incrementing the version number in the `KHO_BLOCK_COMPATIBLE` string to
  * prevent a new kernel from misinterpreting data from an old kernel.
  *
  * Changes are allowed provided the compatibility version is incremented;
@@ -28,6 +28,8 @@
 #include <asm/page.h>
 #include <linux/types.h>
 
+#define KHO_BLOCK_COMPATIBLE "block-v1"
+
 /**
  * KHO_BLOCK_SIZE - The size of each serialization block.
  *
diff --git a/include/linux/kho/abi/compat.h b/include/linux/kho/abi/compat.h
new file mode 100644
index 000000000000..25edd964c390
--- /dev/null
+++ b/include/linux/kho/abi/compat.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2026 Google LLC.
+ * Pasha Tatashin <pasha.tatashin@soleen.com>
+ */
+
+#ifndef _LINUX_KHO_ABI_COMPAT_H
+#define _LINUX_KHO_ABI_COMPAT_H
+
+#include <linux/align.h>
+
+/**
+ * KHO_SUB_COMPAT - Helper to append a sub-component compatibility string.
+ * @str: The compatibility string of the sub-component.
+ *
+ * Appends a KHO safe data structure compatibility string to a sub-system
+ * compatibility string using a semicolon ';' as a separator.
+ *
+ * NOTE: Sub-components MUST be added in strict alphabetical order to maintain
+ * a consistent and predictable compatibility string value.
+ */
+#define KHO_SUB_COMPAT(str) ";" str
+
+/**
+ * KHO_COMPAT_ALIGN - Align a compatibility string size to 8 bytes.
+ * @str: The compatibility string.
+ *
+ * Aligns the size of a compatibility string to an 8-byte boundary for use
+ * in ABI structures.
+ */
+#define KHO_COMPAT_ALIGN(str)	ALIGN(sizeof(str), 8)
+
+#endif /* _LINUX_KHO_ABI_COMPAT_H */
diff --git a/include/linux/kho/abi/luo.h b/include/linux/kho/abi/luo.h
index 288076de6d4a..b502670cd2a6 100644
--- a/include/linux/kho/abi/luo.h
+++ b/include/linux/kho/abi/luo.h
@@ -58,6 +58,7 @@
 #define _LINUX_KHO_ABI_LUO_H
 
 #include <linux/align.h>
+#include <linux/kho/abi/compat.h>
 #include <linux/kho/abi/block.h>
 #include <uapi/linux/liveupdate.h>
 
@@ -65,8 +66,11 @@
  * The LUO state is registered under this KHO entry name.
  */
 #define LUO_KHO_ENTRY_NAME	"LUO"
-#define LUO_ABI_COMPATIBLE	"luo-v5"
-#define LUO_ABI_COMPAT_LEN	ALIGN(sizeof(LUO_ABI_COMPATIBLE), 8)
+#define LUO_ABI_COMPAT_BASE	"luo-v5"
+#define LUO_ABI_COMPATIBLE						\
+	LUO_ABI_COMPAT_BASE						\
+	KHO_SUB_COMPAT(KHO_BLOCK_COMPATIBLE)
+#define LUO_ABI_COMPAT_LEN	KHO_COMPAT_ALIGN(LUO_ABI_COMPATIBLE)
 
 /**
  * struct luo_ser - Centralized LUO ABI header.
-- 
2.53.0


^ permalink raw reply related

* [RFC v1 7/9] kho: decouple radix tree compatibility from global KHO version
From: Pasha Tatashin @ 2026-06-05  3:32 UTC (permalink / raw)
  To: linux-kselftest, rppt, shuah, akpm, linux-mm, skhan, linux-doc,
	jasonmiu, linux-kernel, corbet, ran.xiaokai, pasha.tatashin,
	kexec, pratyush, graf
In-Reply-To: <20260605033235.717351-1-pasha.tatashin@soleen.com>

Decouple the kho radix tree compatibility version from the global
KHO compatibility version KHO_FDT_COMPATIBLE.

Define the independent compatibility version "radix-v1" for the radix
tree KHO_RADIX_COMPATIBLE in radix_tree.h.

Integrate KHO_RADIX_COMPATIBLE into the composite root compatibility
string KHO_FDT_COMPATIBLE.

Additionally, document the new KHO Compatibility ABI under the
Documentation/core-api/kho/abi.rst section.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 Documentation/core-api/kho/abi.rst     |  5 +++++
 include/linux/kho/abi/kexec_handover.h | 10 ++++++----
 include/linux/kho/abi/radix_tree.h     |  4 +++-
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/Documentation/core-api/kho/abi.rst b/Documentation/core-api/kho/abi.rst
index b61363679829..6acdb7c85239 100644
--- a/Documentation/core-api/kho/abi.rst
+++ b/Documentation/core-api/kho/abi.rst
@@ -10,6 +10,11 @@ Core Kexec Handover ABI
 .. kernel-doc:: include/linux/kho/abi/kexec_handover.h
    :doc: Kexec Handover ABI
 
+KHO Compatibility ABI
+=====================
+
+.. kernel-doc:: include/linux/kho/abi/compat.h
+
 vmalloc preservation ABI
 ========================
 
diff --git a/include/linux/kho/abi/kexec_handover.h b/include/linux/kho/abi/kexec_handover.h
index c893b5045078..49ac4b47cc3d 100644
--- a/include/linux/kho/abi/kexec_handover.h
+++ b/include/linux/kho/abi/kexec_handover.h
@@ -8,9 +8,8 @@
 
 #ifndef _LINUX_KHO_ABI_KEXEC_HANDOVER_H
 #define _LINUX_KHO_ABI_KEXEC_HANDOVER_H
-#include <linux/types.h>
-
-#include <asm/page.h>
+#include <linux/kho/abi/compat.h>
+#include <linux/kho/abi/radix_tree.h>
 
 /**
  * DOC: Kexec Handover ABI
@@ -85,7 +84,10 @@
  */
 
 /* The compatible string for the KHO FDT root node. */
-#define KHO_FDT_COMPATIBLE "kho-v4"
+#define KHO_FDT_COMPAT_BASE "kho-v4"
+#define KHO_FDT_COMPATIBLE						\
+	KHO_FDT_COMPAT_BASE						\
+	KHO_SUB_COMPAT(KHO_RADIX_COMPATIBLE)
 
 /* The FDT property for the preserved memory map. */
 #define KHO_FDT_MEMORY_MAP_PROP_NAME "preserved-memory-map"
diff --git a/include/linux/kho/abi/radix_tree.h b/include/linux/kho/abi/radix_tree.h
index f4cc5c02f37a..89cd7eb4a91d 100644
--- a/include/linux/kho/abi/radix_tree.h
+++ b/include/linux/kho/abi/radix_tree.h
@@ -20,7 +20,7 @@
  * This interface is a contract. Any modification to the structure fields,
  * compatible strings, or the layout of the serialization structures defined
  * here constitutes a breaking change. Such changes require incrementing the
- * version number in the `KHO_FDT_COMPATIBLE` string to prevent a new kernel
+ * version number in the `KHO_RADIX_COMPATIBLE` string to prevent a new kernel
  * from misinterpreting data from an old kernel.
  *
  * Changes are allowed provided the compatibility version is incremented;
@@ -94,6 +94,8 @@
  * 4KB.
  */
 
+#define KHO_RADIX_COMPATIBLE "radix-v1"
+
 /*
  * Defines constants for the KHO radix tree structure, used to track preserved
  * memory. These constants govern the indexing, sizing, and depth of the tree.
-- 
2.53.0


^ permalink raw reply related

* [RFC v1 8/9] kho: decouple vmalloc compatibility from global KHO version and update memfd
From: Pasha Tatashin @ 2026-06-05  3:32 UTC (permalink / raw)
  To: linux-kselftest, rppt, shuah, akpm, linux-mm, skhan, linux-doc,
	jasonmiu, linux-kernel, corbet, ran.xiaokai, pasha.tatashin,
	kexec, pratyush, graf
In-Reply-To: <20260605033235.717351-1-pasha.tatashin@soleen.com>

Decouple the vmalloc preservation compatibility version from the global
KHO compatibility version KHO_FDT_COMPATIBLE.

Define the independent compatibility version "vmalloc-v1" for vmalloc
preservation KHO_VMALLOC_COMPATIBLE in vmalloc.h.

Integrate KHO_VMALLOC_COMPATIBLE into the composite root compatibility
string KHO_FDT_COMPATIBLE.

Additionally, update the memfd compatibility string
MEMFD_LUO_FH_COMPATIBLE to include the vmalloc compatibility dependency,
and add a static assertion to verify its length limit.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 include/linux/kho/abi/kexec_handover.h | 4 +++-
 include/linux/kho/abi/memfd.h          | 9 ++++++++-
 include/linux/kho/abi/vmalloc.h        | 6 ++++--
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/include/linux/kho/abi/kexec_handover.h b/include/linux/kho/abi/kexec_handover.h
index 49ac4b47cc3d..f048bc95fed3 100644
--- a/include/linux/kho/abi/kexec_handover.h
+++ b/include/linux/kho/abi/kexec_handover.h
@@ -10,6 +10,7 @@
 #define _LINUX_KHO_ABI_KEXEC_HANDOVER_H
 #include <linux/kho/abi/compat.h>
 #include <linux/kho/abi/radix_tree.h>
+#include <linux/kho/abi/vmalloc.h>
 
 /**
  * DOC: Kexec Handover ABI
@@ -87,7 +88,8 @@
 #define KHO_FDT_COMPAT_BASE "kho-v4"
 #define KHO_FDT_COMPATIBLE						\
 	KHO_FDT_COMPAT_BASE						\
-	KHO_SUB_COMPAT(KHO_RADIX_COMPATIBLE)
+	KHO_SUB_COMPAT(KHO_RADIX_COMPATIBLE)				\
+	KHO_SUB_COMPAT(KHO_VMALLOC_COMPATIBLE)
 
 /* The FDT property for the preserved memory map. */
 #define KHO_FDT_MEMORY_MAP_PROP_NAME "preserved-memory-map"
diff --git a/include/linux/kho/abi/memfd.h b/include/linux/kho/abi/memfd.h
index af310c0c9fdf..24ecbf48cbe1 100644
--- a/include/linux/kho/abi/memfd.h
+++ b/include/linux/kho/abi/memfd.h
@@ -11,7 +11,9 @@
 #ifndef _LINUX_KHO_ABI_MEMFD_H
 #define _LINUX_KHO_ABI_MEMFD_H
 
+#include <linux/kho/abi/compat.h>
 #include <linux/kho/abi/kexec_handover.h>
+#include <linux/kho/abi/luo.h>
 #include <linux/kho/abi/vmalloc.h>
 #include <linux/types.h>
 
@@ -89,6 +91,11 @@ struct memfd_luo_ser {
 } __packed;
 
 /* The compatibility string for memfd file handler */
-#define MEMFD_LUO_FH_COMPATIBLE	"memfd-v2"
+#define MEMFD_LUO_FH_COMPAT_BASE "memfd-v2"
+#define MEMFD_LUO_FH_COMPATIBLE						\
+	MEMFD_LUO_FH_COMPAT_BASE					\
+	KHO_SUB_COMPAT(KHO_VMALLOC_COMPATIBLE)
+
+static_assert(KHO_COMPAT_ALIGN(MEMFD_LUO_FH_COMPATIBLE) <= LIVEUPDATE_HNDL_COMPAT_LENGTH);
 
 #endif /* _LINUX_KHO_ABI_MEMFD_H */
diff --git a/include/linux/kho/abi/vmalloc.h b/include/linux/kho/abi/vmalloc.h
index 87650e1dd774..1847b82e147b 100644
--- a/include/linux/kho/abi/vmalloc.h
+++ b/include/linux/kho/abi/vmalloc.h
@@ -9,13 +9,13 @@
  *
  * The Kexec Handover ABI for preserving vmalloc'ed memory is defined by
  * a set of structures and helper macros. The layout of these structures is a
- * stable contract between kernels and is versioned by the KHO_FDT_COMPATIBLE
+ * stable contract between kernels and is versioned by the KHO_VMALLOC_COMPATIBLE
  * string.
  *
  * This interface is a contract. Any modification to the structure fields,
  * compatible strings, or the layout of the serialization structures defined
  * here constitutes a breaking change. Such changes require incrementing the
- * version number in the `KHO_FDT_COMPATIBLE` string to prevent a new kernel
+ * version number in the `KHO_VMALLOC_COMPATIBLE` string to prevent a new kernel
  * from misinterpreting data from an old kernel.
  *
  * Changes are allowed provided the compatibility version is incremented;
@@ -36,6 +36,8 @@
 #include <linux/types.h>
 #include <asm/page.h>
 
+#define KHO_VMALLOC_COMPATIBLE "vmalloc-v1"
+
 /* Helper macro to define a union for a serializable pointer. */
 #define DECLARE_KHOSER_PTR(name, type)	\
 	union {                        \
-- 
2.53.0


^ permalink raw reply related

* [RFC v1 9/9] liveupdate: add KUnit test to verify alphabetical order of compatibility strings
From: Pasha Tatashin @ 2026-06-05  3:32 UTC (permalink / raw)
  To: linux-kselftest, rppt, shuah, akpm, linux-mm, skhan, linux-doc,
	jasonmiu, linux-kernel, corbet, ran.xiaokai, pasha.tatashin,
	kexec, pratyush, graf
In-Reply-To: <20260605033235.717351-1-pasha.tatashin@soleen.com>

Introduce a KUnit test suite to verify that composite compatibility
strings are formatted correctly, specifically ensuring that all KHO
sub-component compatibility strings are unique and strictly sorted
in alphabetical order.

Maintaining alphabetical order in composite compatibility strings
is required to guarantee consistent, predictable, and reproducible
compatibility string representation across different system configurations.

The test suite validates:
- KHO_FDT_COMPATIBLE (the root composite compatibility string)
- LUO_ABI_COMPATIBLE (the LUO composite compatibility string)
- MEMFD_LUO_FH_COMPATIBLE (the memfd file handler composite compatibility string)

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 kernel/liveupdate/Kconfig                 | 15 ++++++
 kernel/liveupdate/Makefile                |  2 +
 kernel/liveupdate/liveupdate_test.c       | 56 +++++++++++++++++++++++
 tools/testing/selftests/liveupdate/config |  1 +
 4 files changed, 74 insertions(+)
 create mode 100644 kernel/liveupdate/liveupdate_test.c

diff --git a/kernel/liveupdate/Kconfig b/kernel/liveupdate/Kconfig
index c13af38ba23a..617a31dcee73 100644
--- a/kernel/liveupdate/Kconfig
+++ b/kernel/liveupdate/Kconfig
@@ -86,4 +86,19 @@ config LIVEUPDATE_MEMFD
 
 	  If unsure, say N.
 
+config LIVEUPDATE_KUNIT_TEST
+	tristate "KUnit tests for LUO and KHO" if !KUNIT_ALL_TESTS
+	depends on KUNIT
+	depends on LIVEUPDATE
+	default KUNIT_ALL_TESTS
+	help
+	  Enable KUnit tests for LUO and KHO. These tests verify that the
+	  composite KHO, LUO, and memfd compatibility strings remain unique
+	  and sorted alphabetically.
+
+	  For more information on KUnit and unit tests in general, please refer
+	  to the KUnit documentation in Documentation/dev-tools/kunit/.
+
+	  If unsure, say N.
+
 endmenu
diff --git a/kernel/liveupdate/Makefile b/kernel/liveupdate/Makefile
index b481e21a311a..5e0deb85e1b1 100644
--- a/kernel/liveupdate/Makefile
+++ b/kernel/liveupdate/Makefile
@@ -17,3 +17,5 @@ obj-$(CONFIG_KEXEC_HANDOVER_DEBUG)	+= kexec_handover_debug.o
 obj-$(CONFIG_KEXEC_HANDOVER_DEBUGFS)	+= kexec_handover_debugfs.o
 
 obj-$(CONFIG_LIVEUPDATE)		+= luo.o
+obj-$(CONFIG_LIVEUPDATE_KUNIT_TEST)		+= liveupdate_test.o
+
diff --git a/kernel/liveupdate/liveupdate_test.c b/kernel/liveupdate/liveupdate_test.c
new file mode 100644
index 000000000000..15688d69735e
--- /dev/null
+++ b/kernel/liveupdate/liveupdate_test.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * KUnit test for Live Update compatibility strings.
+ */
+#include <kunit/test.h>
+#include <linux/string.h>
+#include <linux/kho/abi/kexec_handover.h>
+#include <linux/kho/abi/luo.h>
+#include <linux/kho/abi/memfd.h>
+
+/* Verify that compatibility sub-components are unique and sorted alphabetically */
+static bool is_alphabetical_unique(const char *compat)
+{
+	char buf[1024];
+	char *string = buf;
+	char *token;
+	char *prev = NULL;
+	char *sub;
+
+	strscpy(buf, compat, sizeof(buf));
+
+	sub = strchr(string, ';');
+	if (!sub)
+		return true;
+
+	sub++;
+
+	while ((token = strsep(&sub, ";")) != NULL) {
+		if (prev && strcmp(prev, token) >= 0)
+			return false;
+		prev = token;
+	}
+
+	return true;
+}
+
+static void test_compatibility_alphabetical(struct kunit *test)
+{
+	KUNIT_EXPECT_TRUE(test, is_alphabetical_unique(KHO_FDT_COMPATIBLE));
+	KUNIT_EXPECT_TRUE(test, is_alphabetical_unique(LUO_ABI_COMPATIBLE));
+	KUNIT_EXPECT_TRUE(test, is_alphabetical_unique(MEMFD_LUO_FH_COMPATIBLE));
+}
+
+static struct kunit_case liveupdate_test_cases[] = {
+	KUNIT_CASE(test_compatibility_alphabetical),
+	{}
+};
+
+static struct kunit_suite liveupdate_test_suite = {
+	.name = "liveupdate-compatibility",
+	.test_cases = liveupdate_test_cases,
+};
+
+kunit_test_suite(liveupdate_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/tools/testing/selftests/liveupdate/config b/tools/testing/selftests/liveupdate/config
index 91d03f9a6a39..28c54bb473b8 100644
--- a/tools/testing/selftests/liveupdate/config
+++ b/tools/testing/selftests/liveupdate/config
@@ -6,6 +6,7 @@ CONFIG_KEXEC_HANDOVER_DEBUGFS=y
 CONFIG_KEXEC_HANDOVER_DEBUG=y
 CONFIG_LIVEUPDATE=y
 CONFIG_LIVEUPDATE_TEST=y
+CONFIG_LIVEUPDATE_KUNIT_TEST=y
 CONFIG_MEMFD_CREATE=y
 CONFIG_TMPFS=y
 CONFIG_SHMEM=y
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH v3 11/15] riscv: dts: sophgo: sg2044: Add Zic64b ISA extension
From: Inochi Amaoto @ 2026-06-05  3:50 UTC (permalink / raw)
  To: Guodong Xu, Jonathan Corbet, Shuah Khan, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zong Li, Deepak Gupta,
	Anup Patel, Atish Patra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Yixun Lan, Chen Wang, Inochi Amaoto, Conor Dooley,
	Shuah Khan, Christian Brauner
  Cc: linux-doc, linux-riscv, linux-kernel, kvm, kvm-riscv,
	Paul Walmsley, Palmer Dabbelt, Conor Dooley, devicetree, spacemit,
	sophgo, linux-kselftest, Andrew Jones, Charles Jenkins,
	Samuel Holland
In-Reply-To: <20260603-rva23u64-hwprobe-v2-v3-11-5529a7b28384@gmail.com>

On Wed, Jun 03, 2026 at 07:12:06AM -0400, Guodong Xu wrote:
> The SG2044 cores have 64-byte cache blocks, described by their
> cbom/cbop/cboz-block-size of 64, so they implement Zic64b.  Declare it in
> each core's riscv,isa-extensions.
> 
> Signed-off-by: Guodong Xu <docular.xu@gmail.com>

I have confirmed SG2044 supports this features.

Acked-by: Inochi Amaoto <inochiama@gmail.com>

Regards,
Inochi

> ---
> v3: New patch.
> ---
>  arch/riscv/boot/dts/sophgo/sg2044-cpus.dtsi | 128 ++++++++++++++--------------
>  1 file changed, 64 insertions(+), 64 deletions(-)
> 
> diff --git a/arch/riscv/boot/dts/sophgo/sg2044-cpus.dtsi b/arch/riscv/boot/dts/sophgo/sg2044-cpus.dtsi
> index 3135409c21492..2ac4a41bbc3a7 100644
> --- a/arch/riscv/boot/dts/sophgo/sg2044-cpus.dtsi
> +++ b/arch/riscv/boot/dts/sophgo/sg2044-cpus.dtsi
> @@ -31,7 +31,7 @@ cpu0: cpu@0 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -67,7 +67,7 @@ cpu1: cpu@1 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -103,7 +103,7 @@ cpu2: cpu@2 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -139,7 +139,7 @@ cpu3: cpu@3 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -175,7 +175,7 @@ cpu4: cpu@4 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -211,7 +211,7 @@ cpu5: cpu@5 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -247,7 +247,7 @@ cpu6: cpu@6 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -283,7 +283,7 @@ cpu7: cpu@7 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -319,7 +319,7 @@ cpu8: cpu@8 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -355,7 +355,7 @@ cpu9: cpu@9 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -391,7 +391,7 @@ cpu10: cpu@10 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -427,7 +427,7 @@ cpu11: cpu@11 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -463,7 +463,7 @@ cpu12: cpu@12 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -499,7 +499,7 @@ cpu13: cpu@13 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -535,7 +535,7 @@ cpu14: cpu@14 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -571,7 +571,7 @@ cpu15: cpu@15 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -607,7 +607,7 @@ cpu16: cpu@16 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -643,7 +643,7 @@ cpu17: cpu@17 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -679,7 +679,7 @@ cpu18: cpu@18 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -715,7 +715,7 @@ cpu19: cpu@19 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -751,7 +751,7 @@ cpu20: cpu@20 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -787,7 +787,7 @@ cpu21: cpu@21 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -823,7 +823,7 @@ cpu22: cpu@22 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -859,7 +859,7 @@ cpu23: cpu@23 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -895,7 +895,7 @@ cpu24: cpu@24 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -931,7 +931,7 @@ cpu25: cpu@25 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -967,7 +967,7 @@ cpu26: cpu@26 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1003,7 +1003,7 @@ cpu27: cpu@27 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1039,7 +1039,7 @@ cpu28: cpu@28 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1075,7 +1075,7 @@ cpu29: cpu@29 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1111,7 +1111,7 @@ cpu30: cpu@30 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1147,7 +1147,7 @@ cpu31: cpu@31 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1183,7 +1183,7 @@ cpu32: cpu@32 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1219,7 +1219,7 @@ cpu33: cpu@33 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1255,7 +1255,7 @@ cpu34: cpu@34 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1291,7 +1291,7 @@ cpu35: cpu@35 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1327,7 +1327,7 @@ cpu36: cpu@36 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1363,7 +1363,7 @@ cpu37: cpu@37 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1399,7 +1399,7 @@ cpu38: cpu@38 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1435,7 +1435,7 @@ cpu39: cpu@39 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1471,7 +1471,7 @@ cpu40: cpu@40 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1507,7 +1507,7 @@ cpu41: cpu@41 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1543,7 +1543,7 @@ cpu42: cpu@42 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1579,7 +1579,7 @@ cpu43: cpu@43 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1615,7 +1615,7 @@ cpu44: cpu@44 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1651,7 +1651,7 @@ cpu45: cpu@45 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1687,7 +1687,7 @@ cpu46: cpu@46 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1723,7 +1723,7 @@ cpu47: cpu@47 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1759,7 +1759,7 @@ cpu48: cpu@48 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1795,7 +1795,7 @@ cpu49: cpu@49 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1831,7 +1831,7 @@ cpu50: cpu@50 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1867,7 +1867,7 @@ cpu51: cpu@51 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1903,7 +1903,7 @@ cpu52: cpu@52 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1939,7 +1939,7 @@ cpu53: cpu@53 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -1975,7 +1975,7 @@ cpu54: cpu@54 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -2011,7 +2011,7 @@ cpu55: cpu@55 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -2047,7 +2047,7 @@ cpu56: cpu@56 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -2083,7 +2083,7 @@ cpu57: cpu@57 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -2119,7 +2119,7 @@ cpu58: cpu@58 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -2155,7 +2155,7 @@ cpu59: cpu@59 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -2191,7 +2191,7 @@ cpu60: cpu@60 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -2227,7 +2227,7 @@ cpu61: cpu@61 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -2263,7 +2263,7 @@ cpu62: cpu@62 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> @@ -2299,7 +2299,7 @@ cpu63: cpu@63 {
>  					       "svinval", "svnapot", "svpbmt",
>  					       "zawrs", "zba", "zbb", "zbc",
>  					       "zbs", "zca", "zcb", "zcd",
> -					       "zfa", "zfbfmin", "zfh", "zfhmin",
> +					       "zfa", "zfbfmin", "zfh", "zfhmin", "zic64b",
>  					       "zicbom", "zicbop", "zicboz", "ziccrse",
>  					       "zicntr", "zicond","zicsr", "zifencei",
>  					       "zihintntl", "zihintpause", "zihpm",
> 
> -- 
> 2.43.0
> 
> 
> -- 
> kvm-riscv mailing list
> kvm-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kvm-riscv

^ permalink raw reply

* Re: [PATCH net-next V2 7/7] devlink: Add eswitch mode boot defaults
From: Randy Dunlap @ 2026-06-05  4:02 UTC (permalink / raw)
  To: Mark Bloch, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, David S. Miller
  Cc: Jonathan Corbet, Shuah Khan, Jiri Pirko, Simon Horman,
	Sunil Goutham, Linu Cherian, Geetha sowjanya, hariprasad,
	Subbaraya Sundeep, Bharat Bhushan, Saeed Mahameed,
	Leon Romanovsky, Tariq Toukan, Borislav Petkov (AMD),
	Andrew Morton, Peter Zijlstra (Intel), Thomas Gleixner,
	Petr Mladek, Tejun Heo, Vlastimil Babka, Feng Tang, Dave Hansen,
	Christian Brauner, Dapeng Mi, Kees Cook, Marco Elver,
	Eric Biggers, Li RongQing, Paul E. McKenney, Ethan Nelson-Moore,
	linux-doc, linux-kernel, netdev, linux-rdma
In-Reply-To: <91d12ffd-6bd9-4951-8351-655262d44874@nvidia.com>



On 6/4/26 2:49 AM, Mark Bloch wrote:
> 
> 
> On 04/06/2026 6:53, Randy Dunlap wrote:
>>
>>
>> On 6/3/26 6:16 PM, Mark Bloch wrote:
>>>
>>>
>>> On 03/06/2026 23:06, Randy Dunlap wrote:
>>>> Hi.
>>>>
>>>> On 6/3/26 12:32 PM, Mark Bloch wrote:
>>>>> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
>>>>> index 063c11ca33e5..7af9f2898d92 100644
>>>>> --- a/Documentation/admin-guide/kernel-parameters.txt
>>>>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>>>>> @@ -1264,6 +1264,31 @@ Kernel parameters
>>>>>  	dell_smm_hwmon.fan_max=
>>>>>  			[HW] Maximum configurable fan speed.
>>>>>  
>>>>> +	devlink_eswitch_mode=
>>>>> +			[NET]
>>>>> +			Format:
>>>>> +			[<selector>]:<mode>
>>>>
>>>> It appears (please correct me if I am mistaken) that the '[' and ']'
>>>> above don't mean "optional" but instead they are required characters...
>>>>
>>>>> +
>>>>> +			<selector>:
>>>>> +			* | <handle>[,<handle>...]
>>>>
>>>> while here they mean "optional".
>>>>
>>>> That is confusing (inconsistent). Also, if the square brackets are
>>>> always required around the <selector>, what purpose do they serve?
>>>
>>> Yes, you are right, this is confusing. The outer square brackets are part of
>>> the syntax and are required, while the brackets in "[,<handle>...]" mean that
>>> additional handles are optional.
>>>
>>> I couldn't find a better way to describe this. What I want to say is that the
>>> selector is always wrapped in square brackets. Inside the brackets it can either
>>> be "*" to match all devices, or a comma separated list of handles. If "*" is
>>> not used, then at least one handle has to be provided.
>>>
>>> Maybe it would be clearer to spell it out explicitly, something like:
>>>
>>> Format:
>>>   [<selector>]:<mode>
>>>
>>> The '[' and ']' characters are literal and required.
>>>
>>> <selector>:
>>>   * | <handle>[,<handle>...]
>>>
>>> If '*' is not used, <selector> must contain at least one <handle>.
>>>
>>> Does that sound like a reasonable way to document it?
>>
>> Yes, that helps a little bit. Better than nothing.
>>
>> But why are they required at all?
> 
> Jiri suggested using the square brackets, and I liked that they made the
> selector look like a grouped argument. But if that is too confusing, I can
> also drop them and use a simpler separator, for example:
> 
> 	devlink_eswitch_mode=
> 			[NET]
> 			Format:
> 			<selector>=<mode>
> 
> 			<selector>:
> 			* | <handle>[,<handle>...]
> 
> 			<handle>:
> 			<bus-name>/<dev-name>
> 
> 			Configure default devlink eswitch mode for matching
> 			devlink instances during device initialization.
> 
> 			<mode>:
> 			legacy | switchdev | switchdev_inactive
> 
> 			Examples:
> 			devlink_eswitch_mode=*=switchdev
> 			devlink_eswitch_mode=pci/0000:08:00.0=switchdev
> 			devlink_eswitch_mode=pci/0000:08:00.0,pci/0000:09:00.1=switchdev_inactive
> 
> Does this look better to you?

Yes, that looks much better to me.
But you should do whatever you think is right.

>>>>> +
>>>>> +			<handle>:
>>>>> +			<bus-name>/<dev-name>
>>>>> +
>>>>> +			Configure default devlink eswitch mode for matching
>>>>> +			devlink instances during device initialization.
>>>>> +
>>>>> +			<mode>:
>>>>> +			legacy | switchdev | switchdev_inactive
>>>>> +
>>>>> +			Examples:
>>>>> +			devlink_eswitch_mode=[*]:switchdev
>>>>> +			devlink_eswitch_mode=[pci/0000:08:00.0]:switchdev
>>>>> +			devlink_eswitch_mode=[pci/0000:08:00.0,pci/0000:09:00.1]:legacy
>>>>> +
>>>>> +			See Documentation/networking/devlink/devlink-defaults.rst
>>>>> +			for the full syntax.
>>>>> +
>>>>>  	dfltcc=		[HW,S390]
>>>>>  			Format: { on | off | def_only | inf_only | always }
>>>>>  			on:       s390 zlib hardware support for compression on
>>>>
>>>>
>>>
>>
> 

-- 
~Randy


^ permalink raw reply

* Re: [PATCH 3/3] hwmon: Add documentation for SQ24860
From: Randy Dunlap @ 2026-06-05  4:36 UTC (permalink / raw)
  To: Ziming Zhu, Guenter Roeck
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Shuah Khan, linux-hwmon, devicetree, linux-kernel, linux-doc,
	Ziming Zhu
In-Reply-To: <20260605020450.89638-4-zmzhu0630@163.com>



On 6/4/26 7:04 PM, Ziming Zhu wrote:
> From: Ziming Zhu <ziming.zhu@silergycorp.com>
> 
> Document the supported sysfs attributes for the Silergy SQ24860 PMBus
> hwmon driver.
> 
> Signed-off-by: Ziming Zhu <ziming.zhu@silergycorp.com>
> ---
>  Documentation/hwmon/index.rst   |  1 +
>  Documentation/hwmon/sq24860.rst | 96 +++++++++++++++++++++++++++++++++
>  2 files changed, 97 insertions(+)
>  create mode 100644 Documentation/hwmon/sq24860.rst
> 

Tested-by: Randy Dunlap <rdunlap@infradead.org>

-- 
~Randy

^ permalink raw reply

* Re: [PATCH v2 2/3] PM: dpm_watchdog: Allow disabling DPM watchdog by default
From: Randy Dunlap @ 2026-06-05  4:53 UTC (permalink / raw)
  To: Tzung-Bi Shih, Jonathan Corbet, Rafael J. Wysocki,
	Greg Kroah-Hartman, Danilo Krummrich
  Cc: Shuah Khan, Pavel Machek, Len Brown, linux-doc, linux-kernel,
	linux-pm, driver-core, tfiga, senozhatsky
In-Reply-To: <20260604090756.2884671-3-tzungbi@kernel.org>

Hi--

On 6/4/26 2:07 AM, Tzung-Bi Shih wrote:
> Introduce the CONFIG_DPM_WATCHDOG_DEFAULT_ENABLED Kconfig option to
> allow the device suspend/resume watchdog (DPM watchdog) to be disabled
> by default at compile time.
> 
> Additionally, introduce the "dpm_watchdog_enabled" module parameter to
> allow the watchdog to be enabled or disabled at boot time (via
> "power.dpm_watchdog_enabled") and at runtime (via sysfs).
> 
> This provides flexibility for systems that want the watchdog code
> compiled in but inactive by default, allowing it to be enabled only when
> needed.
> 
> Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
> ---
> v2:
> - Use module parameter and bool for dpm_watchdog_enabled.
> - Use IS_ENABLED().
> 
> v1: https://lore.kernel.org/all/20260528103215.505795-1-tzungbi@kernel.org
> 
>  Documentation/admin-guide/kernel-parameters.txt |  8 ++++++++
>  drivers/base/power/main.c                       | 11 +++++++++++
>  kernel/power/Kconfig                            |  9 +++++++++
>  3 files changed, 28 insertions(+)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 00375193bd26..0a0d5340b0c7 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -5399,6 +5399,14 @@ Kernel parameters
>  			function to NULL. On Idle the CPU just reduces
>  			execution priority.
>  
> +	power.dpm_watchdog_enabled=
> +			[KNL] Enable or disable the device suspend/resume

I think that [KNL] isn't very useful here (nor in many of its uses in
kernel-parameters.txt).
What is required to use this option are:
  CONFIG_PM_SLEEP, CONFIG_DPM_WATCHDOG
You should convey that information somehow.

Also, in kernel-parameters.txt, "pm_async=" is only valid when [PM]
is enabled, but "PM" is not defined/described anywhere.
That should be added near the beginning of kernel-parameters.txt (in
alphabetical order).


> +			watchdog (DPM watchdog).
> +			Format: {"0" | "1"}
> +			0: disable
> +			1: enable
> +			Default value is set by CONFIG_DPM_WATCHDOG_DEFAULT_ENABLED.
> +
>  	ppc_strict_facility_enable
>  			[PPC,ENABLE] This option catches any kernel floating point,
>  			Altivec, VSX and SPE outside of regions specifically
> diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
> index cd864f3a2799..7822c29b7c8d 100644
> --- a/drivers/base/power/main.c
> +++ b/drivers/base/power/main.c
> @@ -534,6 +534,11 @@ module_param(dpm_watchdog_all_cpu_backtrace, bool, 0644);
>  MODULE_PARM_DESC(dpm_watchdog_all_cpu_backtrace,
>  		 "Backtrace all CPUs on DPM watchdog timeout");
>  
> +static bool __read_mostly dpm_watchdog_enabled =
> +				IS_ENABLED(CONFIG_DPM_WATCHDOG_DEFAULT_ENABLED);
> +module_param(dpm_watchdog_enabled, bool, 0644);
> +MODULE_PARM_DESC(dpm_watchdog_enabled, "Enable DPM watchdog");
> +
>  /**
>   * dpm_watchdog_handler - Driver suspend / resume watchdog handler.
>   * @t: The timer that PM watchdog depends on.
> @@ -577,6 +582,9 @@ static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
>  {
>  	struct timer_list *timer = &wd->timer;
>  
> +	if (!dpm_watchdog_enabled)
> +		return;
> +
>  	wd->dev = dev;
>  	wd->tsk = current;
>  	wd->fatal = CONFIG_DPM_WATCHDOG_TIMEOUT == CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
> @@ -595,6 +603,9 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd)
>  {
>  	struct timer_list *timer = &wd->timer;
>  
> +	if (!dpm_watchdog_enabled)
> +		return;
> +
>  	timer_delete_sync(timer);
>  	timer_destroy_on_stack(timer);
>  }
> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index 530c897311d4..12a4a66d48d4 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -268,6 +268,15 @@ config DPM_WATCHDOG
>  	  captured in pstore device for inspection in subsequent
>  	  boot session.
>  
> +config DPM_WATCHDOG_DEFAULT_ENABLED
> +	bool "Enable DPM watchdog by default"
> +	depends on DPM_WATCHDOG
> +	default y
> +	help
> +	  If you say Y here, the DPM watchdog will be enabled by default.
> +	  If you say N, it will be compiled in but disabled, requiring a
> +	  boot parameter to activate.
> +
>  config DPM_WATCHDOG_TIMEOUT
>  	int "Watchdog timeout to panic in seconds"
>  	range 1 120

-- 
~Randy


^ permalink raw reply

* Re: [PATCH v6 10/11] x86/virt/tdx: Enable Dynamic PAMT
From: Chao Gao @ 2026-06-05  5:25 UTC (permalink / raw)
  To: Kiryl Shutsemau
  Cc: Rick Edgecombe, bp, dave.hansen, hpa, kvm, linux-coco, linux-doc,
	linux-kernel, mingo, nik.borisov, pbonzini, seanjc, tglx,
	vannapurve, x86, yan.y.zhao, kai.huang, Kirill A. Shutemov
In-Reply-To: <aiGyIQvudD5ZF3lf@thinkstation>

On Thu, Jun 04, 2026 at 06:14:17PM +0100, Kiryl Shutsemau wrote:
>On Mon, May 25, 2026 at 07:35:14PM -0700, Rick Edgecombe wrote:
>> @@ -152,7 +156,12 @@ const struct tdx_sys_info *tdx_get_sysinfo(void);
>>  
>>  static inline bool tdx_supports_dynamic_pamt(const struct tdx_sys_info *sysinfo)
>>  {
>> -	return false; /* To be enabled when kernel is ready */
>> +	/*
>> +	 * The TDX Module's internal Dynamic PAMT tree structure can't
>> +	 * handle physical addresses with more than 48 bits.
>> +	 */
>> +	return sysinfo->features.tdx_features0 & TDX_FEATURES0_DYNAMIC_PAMT &&
>> +	       boot_cpu_data.x86_phys_bits <= 48;
>
>Should we warn for >48?

Maybe we should drop this check. If the TDX module cannot handle that case,
advertising TDX_FEATURES0_DYNAMIC_PAMT is a bug and should be fixed by the
module.

^ permalink raw reply

* [PATCH 1/1] docs: Fix minor grammatical error
From: Brigham Campbell @ 2026-06-05  5:38 UTC (permalink / raw)
  To: Thorsten Leemhuis, Jonathan Corbet, Shuah Khan,
	open list:DOCUMENTATION REPORTING ISSUES, open list
  Cc: Brigham Campbell

Fix minor grammatical error in the admin guide docs.

Signed-off-by: Brigham Campbell <me@brighamcampbell.com>
---

I happened across this minor mistake while investigating techniques to
use a partial kernel config to generate a complete config. If
maintainers that I don't send out minor fixes like this, please let me
know and I'll remember that for the future.

 Documentation/admin-guide/quickly-build-trimmed-linux.rst | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/admin-guide/quickly-build-trimmed-linux.rst b/Documentation/admin-guide/quickly-build-trimmed-linux.rst
index cb178e0a6208..194d22f56449 100644
--- a/Documentation/admin-guide/quickly-build-trimmed-linux.rst
+++ b/Documentation/admin-guide/quickly-build-trimmed-linux.rst
@@ -217,10 +217,10 @@ again.
 
    There is a catch: 'localmodconfig' is likely to disable kernel features you
    did not use since you booted your Linux -- like drivers for currently
-   disconnected peripherals or a virtualization software not haven't used yet.
-   You can reduce or nearly eliminate that risk with tricks the reference
-   section outlines; but when building a kernel just for quick testing purposes
-   it is often negligible if such features are missing. But you should keep that
+   disconnected peripherals or virtualization software not currently in use. You
+   can reduce or nearly eliminate that risk with tricks the reference section
+   outlines; but when building a kernel just for quick testing purposes it is
+   often negligible if such features are missing. But you should keep that
    aspect in mind when using a kernel built with this make target, as it might
    be the reason why something you only use occasionally stopped working.
 
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH v6 06/11] x86/virt/tdx: Optimize tdx_pamt_get/put()
From: Chao Gao @ 2026-06-05  5:40 UTC (permalink / raw)
  To: Kiryl Shutsemau
  Cc: Edgecombe, Rick P, kvm@vger.kernel.org,
	linux-coco@lists.linux.dev, Huang, Kai, Hansen, Dave, Zhao, Yan Y,
	seanjc@google.com, mingo@redhat.com, linux-kernel@vger.kernel.org,
	pbonzini@redhat.com, nik.borisov@suse.com,
	linux-doc@vger.kernel.org, hpa@zytor.com, tglx@kernel.org,
	Annapurve, Vishal, bp@alien8.de, kirill.shutemov@linux.intel.com,
	x86@kernel.org
In-Reply-To: <aiGq7XjmMrsqdBY5@thinkstation>

On Thu, Jun 04, 2026 at 05:59:02PM +0100, Kiryl Shutsemau wrote:
>On Tue, May 26, 2026 at 04:42:24PM +0000, Edgecombe, Rick P wrote:
>> On Tue, 2026-05-26 at 16:57 +0800, Chao Gao wrote:
>> > > -	scoped_guard(spinlock, &pamt_lock) {
>> > 
>> > This converts the scoped_guard() added by the previous patch to
>> > explicit lock/unlock and goto. It would reduce code churn if the
>> > previous patch used that form directly.
>> 
>> Yea, it's a good point. I actually debated doing it, but decided not to because
>> the scoped version is cleaner for the non-optimized version. But for
>> reviewability, never doing the scoped version is probably better.
>
>I don't see a reason why we can't keep the scoped_guard() on get side.

One additional reason to drop scoped_guard() is that it mixes cleanup helpers
with goto, which is discouraged. See [*]

 :Lastly, given that the benefit of cleanup helpers is removal of “goto”, and
 :that the “goto” statement can jump between scopes, the expectation is that
 :usage of “goto” and cleanup helpers is never mixed in the same function.

Removing scoped_guard() here also reduces indentation.

*: https://www.kernel.org/doc/html/v7.1-rc6/core-api/cleanup.html

>
>On put side, we cannot get atomic_get_and_lock() semantics without
>dropping the scoped_guard().
>
>Maybe we should keep it for get?
>
>-- 
>  Kiryl Shutsemau / Kirill A. Shutemov

^ permalink raw reply

* Re: [PATCH v6 01/12] PCI: liveupdate: Set up FLB handler for the PCI core
From: Pranjal Shrivastava @ 2026-06-05  5:41 UTC (permalink / raw)
  To: David Matlack
  Cc: kexec, linux-doc, linux-kernel, linux-mm, linux-pci,
	Adithya Jayachandran, Alexander Graf, Alex Williamson,
	Bjorn Helgaas, Chris Li, David Rientjes, Jacob Pan,
	Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Leon Romanovsky,
	Lukas Wunner, Mike Rapoport, Parav Pandit, Pasha Tatashin,
	Pratyush Yadav, Saeed Mahameed, Samiullah Khawaja, Shuah Khan,
	Vipin Sharma, William Tu, Yi Liu
In-Reply-To: <20260522202410.3104264-2-dmatlack@google.com>

On Fri, May 22, 2026 at 08:23:59PM +0000, David Matlack wrote:
> Set up a File-Lifecycle-Bound (FLB) handler for the PCI core to enable
> it to participate in the preservation of PCI devices across Live Update.
> Essentially, this commit enables the PCI core to allocate a struct
> (struct pci_ser) and preserve it across a Live Update whenever at least
> one device is preserved.
> 
> Preserving PCI devices across Live Update is built on top of the Live
> Update Orchestrator's (LUO) support for file preservation. Drivers are
> expected to expose a file to userspace to represent a single PCI device
> and support preservation of that file. This is intended primarily to
> support preservation of PCI devices bound to VFIO drivers.
> 
> This commit enables drivers to register their liveupdate_file_handler
> with the PCI core so that the PCI core can do its own tracking and
> enforcement of which devices are preserved.
> 
>   pci_liveupdate_register_flb(driver_file_handler);
>   pci_liveupdate_unregister_flb(driver_file_handler);
> 
> When the first file (with a handler registered with the PCI core) is
> preserved, the PCI core will be notified to allocate its tracking struct
> (pci_ser). When the last file is unpreserved (i.e. preservation
> cancelled) the PCI core will be notified to free struct pci_ser.
> 
> This struct is preserved across a Live Update using KHO and can be
> fetched by the PCI core during early boot (e.g. during device
> enumeration) so that it knows which devices were preserved.
> 
> Note: This commit only allocates struct pci_ser and preserves it across
> Live Update. A subsequent commit will add an API for drivers to tell the
> PCI core exactly which devices are being preserved.
> 
> Note: There is no reason to check for kho_is_enabled() since it can be
> assumed to return true. If KHO was not enabled then Live Update would
> not be enabled and these routines would never run.
> 

[...]

> +/**
> + * struct pci_dev_ser - Serialized state about a single PCI device.
> + *
> + * @domain: The device's PCI domain number (segment).
> + * @bdf: The device's PCI bus, device, and function number.
> + * @padding: Padding to naturally align struct pci_dev_ser.
> + */
> +struct pci_dev_ser {
> +	u32 domain;
> +	u16 bdf;
> +	u16 padding;
> +} __packed;
> +
> +/**
> + * struct pci_ser - PCI Subsystem Live Update State
> + *
> + * This struct tracks state about all devices that are being preserved across
> + * a Live Update for the next kernel.
> + *
> + * @max_nr_devices: The length of the devices[] flexible array.
> + * @nr_devices: The number of devices that were preserved.
> + * @devices: Flexible array of pci_dev_ser structs for each device.
> + */
> +struct pci_ser {
> +	u32 max_nr_devices;
> +	u32 nr_devices;
> +	struct pci_dev_ser devices[];
> +} __packed;
> +
> +/* Ensure all elements of devices[] are naturally aligned. */
> +static_assert(offsetof(struct pci_ser, devices) % sizeof(unsigned long) == 0);
> +static_assert(sizeof(struct pci_dev_ser) % sizeof(unsigned long) == 0);

Minor Nit: Shall we consider using specific bitwidth types here?
I'm wondering if down the line another u32 field is added to 
struct pci_dev_ser.. in that case on a 32-bit machine 12 % 4 == 0 but on
a 64-bit machine 12 % 8 != 0..

[...]

With the nit:

Reviewed-by: Pranjal Shrivastava <praan@google.com>

Thanks,
Praan

^ permalink raw reply

* Re: [PATCH v6 02/12] PCI: liveupdate: Track outgoing preserved PCI devices
From: Pranjal Shrivastava @ 2026-06-05  6:11 UTC (permalink / raw)
  To: David Matlack
  Cc: kexec, linux-doc, linux-kernel, linux-mm, linux-pci,
	Adithya Jayachandran, Alexander Graf, Alex Williamson,
	Bjorn Helgaas, Chris Li, David Rientjes, Jacob Pan,
	Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Leon Romanovsky,
	Lukas Wunner, Mike Rapoport, Parav Pandit, Pasha Tatashin,
	Pratyush Yadav, Saeed Mahameed, Samiullah Khawaja, Shuah Khan,
	Vipin Sharma, William Tu, Yi Liu
In-Reply-To: <20260522202410.3104264-3-dmatlack@google.com>

On Fri, May 22, 2026 at 08:24:00PM +0000, David Matlack wrote:
> Add APIs to allow drivers to notify the PCI core of which devices are
> being preserved across a Live Update for the next kernel, i.e.
> "outgoing" devices.
> 
> Drivers must notify the PCI core when devices are preserved so that the
> PCI core can update its FLB data (struct pci_ser) and track the list of
> outgoing devices. pci_liveupdate_preserve() notifies the PCI core that a
> device must be preserved across Live Update. pci_liveupdate_unpreserve()
> reverses this (cancels the preservation of the device).
> 
> This tracking ensures the PCI core is fully aware of which devices may
> need special handling during shutdown and kexec, and so that it can be
> handed off to the next kernel.
> 
> Signed-off-by: David Matlack <dmatlack@google.com>

[...]

>  
>  /**
>   * struct pci_dev_ser - Serialized state about a single PCI device.
>   *
>   * @domain: The device's PCI domain number (segment).
>   * @bdf: The device's PCI bus, device, and function number.
> - * @padding: Padding to naturally align struct pci_dev_ser.
> + * @refcount: Reference count used by the PCI core to keep track of whether it
> + *            is done using a device's struct pci_dev_ser. The value of the
> + *            refcount is equal to 1 when the struct pci_dev_ser is in use, and
> + *            0 otherwise.

Note to fellow reviewers: This may seem like a bool instead of refcount,
but this is changed in Patch 6. 

Reviewed-by: Pranjal Shrivastava <praan@google.com>

Thanks,
Praan

^ permalink raw reply

* [PATCH v2 0/3] Add support for Silergy SQ24860
From: Ziming Zhu @ 2026-06-05  6:30 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Shuah Khan, linux-hwmon, devicetree, linux-kernel, linux-doc,
	Ziming Zhu

From: Ziming Zhu <ziming.zhu@silergycorp.com>

Changes in v2:
- Validate silergy,rimon-micro-ohms before programming the current
  calibration gain.
- Avoid underflow when programming PMBUS_IIN_OC_FAULT_LIMIT.
- Replace brittle samples limit calculation with SQ24860_MAX_SAMPLES.
- Update the current/power scaling comment to match the implementation.
- Fix the documented DT property name in sq24860.rst.

Ziming Zhu (3):
  dt-bindings: hwmon: pmbus: Add bindings for Silergy SQ24860
  hwmon: pmbus: Add support for Silergy SQ24860
  hwmon: Add documentation for SQ24860

 .../bindings/hwmon/pmbus/silergy,sq24860.yaml |  74 +++
 Documentation/hwmon/index.rst                 |   1 +
 Documentation/hwmon/sq24860.rst               |  96 ++++
 drivers/hwmon/pmbus/Kconfig                   |  19 +
 drivers/hwmon/pmbus/Makefile                  |   1 +
 drivers/hwmon/pmbus/sq24860.c                 | 432 ++++++++++++++++++
 6 files changed, 623 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/pmbus/silergy,sq24860.yaml
 create mode 100644 Documentation/hwmon/sq24860.rst
 create mode 100644 drivers/hwmon/pmbus/sq24860.c

-- 
2.25.1


^ permalink raw reply

* [PATCH v2 2/3] hwmon: pmbus: Add support for Silergy SQ24860
From: Ziming Zhu @ 2026-06-05  6:30 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Shuah Khan, linux-hwmon, devicetree, linux-kernel, linux-doc,
	Ziming Zhu
In-Reply-To: <20260605063042.91776-1-zmzhu0630@163.com>

From: Ziming Zhu <ziming.zhu@silergycorp.com>

Add PMBus hwmon support for the Silergy SQ24860 eFuse.

The driver reports input voltage, output voltage, auxiliary voltage,
input current, input power, and temperature. It also exposes peak,
average, and minimum history attributes, sample count configuration,
and maps the manufacturer-specific VIREF register to the generic input
over-current fault limit attribute.

The IMON resistor value is read from the silergy,rimon-micro-ohms device
property and used to configure the input current calibration gain.

Signed-off-by: Ziming Zhu <ziming.zhu@silergycorp.com>
---
 drivers/hwmon/pmbus/Kconfig   |  19 ++
 drivers/hwmon/pmbus/Makefile  |   1 +
 drivers/hwmon/pmbus/sq24860.c | 432 ++++++++++++++++++++++++++++++++++
 3 files changed, 452 insertions(+)
 create mode 100644 drivers/hwmon/pmbus/sq24860.c

diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 8f4bff375ecb..a905b5af137c 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -612,6 +612,25 @@ config SENSORS_STEF48H28
 	  This driver can also be built as a module. If so, the module will
 	  be called stef48h28.
 
+config SENSORS_SQ24860
+	tristate "Silergy SQ24860"
+	help
+	  If you say yes here you get hardware monitoring support for Silergy
+	  SQ24860 eFuse.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called sq24860.
+
+config SENSORS_SQ24860_REGULATOR
+	bool "Regulator support for SQ24860"
+	depends on SENSORS_SQ24860 && REGULATOR
+	default SENSORS_SQ24860
+	help
+	  If you say yes here you get regulator support for Silergy SQ24860.
+	  The regulator is registered through the PMBus regulator framework and
+	  can be used to control the output exposed by the device.
+	  This option is only useful if regulator framework support is needed.
+
 config SENSORS_STPDDC60
 	tristate "ST STPDDC60"
 	help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index 7129b62bc00f..86bc93c6c091 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_PM6764TR)	+= pm6764tr.o
 obj-$(CONFIG_SENSORS_PXE1610)	+= pxe1610.o
 obj-$(CONFIG_SENSORS_Q54SJ108A2)	+= q54sj108a2.o
 obj-$(CONFIG_SENSORS_STEF48H28)	+= stef48h28.o
+obj-$(CONFIG_SENSORS_SQ24860)	+= sq24860.o
 obj-$(CONFIG_SENSORS_STPDDC60)	+= stpddc60.o
 obj-$(CONFIG_SENSORS_TDA38640)	+= tda38640.o
 obj-$(CONFIG_SENSORS_TPS25990)	+= tps25990.o
diff --git a/drivers/hwmon/pmbus/sq24860.c b/drivers/hwmon/pmbus/sq24860.c
new file mode 100644
index 000000000000..43a2cb542169
--- /dev/null
+++ b/drivers/hwmon/pmbus/sq24860.c
@@ -0,0 +1,432 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2024.
+// Author: Ziming Zhu <ziming.zhu@silergycorp.com>
+#include <linux/bitfield.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "pmbus.h"
+
+#define SQ24860_IIN_CAL_GAIN		0x38
+#define SQ24860_READ_VAUX		0xd0
+#define SQ24860_READ_VIN_MIN		0xd1
+#define SQ24860_READ_VIN_PEAK		0xd2
+#define SQ24860_READ_IIN_PEAK		0xd4
+#define SQ24860_READ_PIN_PEAK		0xd5
+#define SQ24860_READ_TEMP_AVG		0xd6
+#define SQ24860_READ_TEMP_PEAK		0xd7
+#define SQ24860_READ_VOUT_MIN		0xda
+#define SQ24860_READ_VIN_AVG		0xdc
+#define SQ24860_READ_VOUT_AVG		0xdd
+#define SQ24860_READ_IIN_AVG		0xde
+#define SQ24860_READ_PIN_AVG		0xdf
+#define SQ24860_VIREF			0xe0
+#define SQ24860_PK_MIN_AVG		0xea
+#define PK_MIN_AVG_RST_PEAK		BIT(7)
+#define PK_MIN_AVG_RST_AVG		BIT(6)
+#define PK_MIN_AVG_RST_MIN		BIT(5)
+#define PK_MIN_AVG_AVG_CNT		GENMASK(2, 0)
+#define SQ24860_MFR_WRITE_PROTECT	0xf8
+#define SQ24860_UNLOCKED		BIT(7)
+
+#define SQ24860_8B_SHIFT		2
+#define SQ24860_IIN_OCF_NUM		1000000
+#define SQ24860_IIN_OCF_DIV		129278
+#define SQ24860_IIN_OCF_OFF		165
+
+#define PK_MIN_AVG_RST_MASK		(PK_MIN_AVG_RST_PEAK | \
+					 PK_MIN_AVG_RST_AVG  | \
+					 PK_MIN_AVG_RST_MIN)
+#define SQ24860_MAX_SAMPLES		BIT(FIELD_MAX(PK_MIN_AVG_AVG_CNT))
+/*
+ * Arbitrary default Rimon value: 1.6kOhm
+ */
+#define SQ24860_DEFAULT_RIMON		1600000000
+#define SQ24860_DEFAULT_GIMON		18180
+
+#define SQ24860_VAUX_DIV		20
+
+static int sq24860_write_iin_cal_gain(struct i2c_client *client, u32 rimon,
+					u32 gimon)
+{
+	u64 temp = (u64)6400 * 1000000000 * 1000;
+	u64 denom;
+	u64 word;
+
+	if (!rimon || !gimon)
+		return -EINVAL;
+
+	denom = (u64)rimon * gimon;
+	word = div_u64(temp, denom);
+	if (word > U16_MAX)
+		return -ERANGE;
+
+	return i2c_smbus_write_word_data(client, SQ24860_IIN_CAL_GAIN,
+						(u16)word);
+}
+
+static int sq24860_mfr_write_protect_set(struct i2c_client *client,
+					  u8 protect)
+{
+	u8 val;
+
+	switch (protect) {
+	case 0:
+		val = 0xa2;
+		break;
+	case PB_WP_ALL:
+		val = 0x0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return pmbus_write_byte_data(client, -1, SQ24860_MFR_WRITE_PROTECT,
+				     val);
+}
+
+static int sq24860_mfr_write_protect_get(struct i2c_client *client)
+{
+	int ret = pmbus_read_byte_data(client, -1, SQ24860_MFR_WRITE_PROTECT);
+
+	if (ret < 0)
+		return ret;
+
+	return (ret & SQ24860_UNLOCKED) ? 0 : PB_WP_ALL;
+}
+
+static int sq24860_read_word_data(struct i2c_client *client,
+				   int page, int phase, int reg)
+{
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_READ_VIN_MAX:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_VIN_PEAK);
+		break;
+
+	case PMBUS_VIRT_READ_VIN_MIN:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_VIN_MIN);
+		break;
+
+	case PMBUS_VIRT_READ_VIN_AVG:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_VIN_AVG);
+		break;
+
+	case PMBUS_VIRT_READ_VOUT_MIN:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_VOUT_MIN);
+		break;
+
+	case PMBUS_VIRT_READ_VOUT_AVG:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_VOUT_AVG);
+		break;
+
+	case PMBUS_VIRT_READ_IIN_AVG:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_IIN_AVG);
+		break;
+
+	case PMBUS_VIRT_READ_IIN_MAX:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_IIN_PEAK);
+		break;
+
+	case PMBUS_VIRT_READ_TEMP_AVG:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_TEMP_AVG);
+		break;
+
+	case PMBUS_VIRT_READ_TEMP_MAX:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_TEMP_PEAK);
+		break;
+
+	case PMBUS_VIRT_READ_PIN_AVG:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_PIN_AVG);
+		break;
+
+	case PMBUS_VIRT_READ_PIN_MAX:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_PIN_PEAK);
+		break;
+
+	case PMBUS_VIRT_READ_VMON:
+		ret = pmbus_read_word_data(client, page, phase,
+					   SQ24860_READ_VAUX);
+		if (ret < 0)
+			break;
+		ret = DIV_ROUND_CLOSEST(ret, SQ24860_VAUX_DIV);
+		break;
+
+	case PMBUS_VIN_UV_WARN_LIMIT:
+	case PMBUS_VIN_UV_FAULT_LIMIT:
+	case PMBUS_VIN_OV_WARN_LIMIT:
+	case PMBUS_VIN_OV_FAULT_LIMIT:
+	case PMBUS_VOUT_UV_WARN_LIMIT:
+	case PMBUS_IIN_OC_WARN_LIMIT:
+	case PMBUS_OT_WARN_LIMIT:
+	case PMBUS_OT_FAULT_LIMIT:
+	case PMBUS_PIN_OP_WARN_LIMIT:
+		/*
+		 * These registers provide an 8 bits value instead of a
+		 * 10bits one. Just shifting twice the register value is
+		 * enough to make the sensor type conversion work, even
+		 * if the datasheet provides different m, b and R for
+		 * those.
+		 */
+		ret = pmbus_read_word_data(client, page, phase, reg);
+		if (ret < 0)
+			break;
+		ret <<= SQ24860_8B_SHIFT;
+		break;
+
+	case PMBUS_IIN_OC_FAULT_LIMIT:
+		/*
+		 * VIREF directly sets the over-current limit at which the eFuse
+		 * will turn the FET off and trigger a fault. Expose it through
+		 * this generic property instead of a manufacturer specific one.
+		 */
+		ret = pmbus_read_byte_data(client, page, SQ24860_VIREF);
+		if (ret < 0)
+			break;
+		ret = DIV_ROUND_CLOSEST(ret * SQ24860_IIN_OCF_NUM,
+					SQ24860_IIN_OCF_DIV);
+		ret += SQ24860_IIN_OCF_OFF;
+		break;
+
+	case PMBUS_VIRT_SAMPLES:
+		ret = pmbus_read_byte_data(client, page, SQ24860_PK_MIN_AVG);
+		if (ret < 0)
+			break;
+		ret = BIT(FIELD_GET(PK_MIN_AVG_AVG_CNT, ret));
+		break;
+
+	case PMBUS_VIRT_RESET_TEMP_HISTORY:
+	case PMBUS_VIRT_RESET_VIN_HISTORY:
+	case PMBUS_VIRT_RESET_IIN_HISTORY:
+	case PMBUS_VIRT_RESET_PIN_HISTORY:
+	case PMBUS_VIRT_RESET_VOUT_HISTORY:
+		ret = 0;
+		break;
+
+	default:
+		ret = -ENODATA;
+		break;
+	}
+
+	return ret;
+}
+
+static int sq24860_write_word_data(struct i2c_client *client,
+				    int page, int reg, u16 value)
+{
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIN_UV_WARN_LIMIT:
+	case PMBUS_VIN_UV_FAULT_LIMIT:
+	case PMBUS_VIN_OV_WARN_LIMIT:
+	case PMBUS_VIN_OV_FAULT_LIMIT:
+	case PMBUS_VOUT_UV_WARN_LIMIT:
+	case PMBUS_IIN_OC_WARN_LIMIT:
+	case PMBUS_OT_WARN_LIMIT:
+	case PMBUS_OT_FAULT_LIMIT:
+	case PMBUS_PIN_OP_WARN_LIMIT:
+		value >>= SQ24860_8B_SHIFT;
+		value = clamp_val(value, 0, 0xff);
+		ret = pmbus_write_word_data(client, page, reg, value);
+		break;
+
+	case PMBUS_IIN_OC_FAULT_LIMIT:
+		value -= SQ24860_IIN_OCF_OFF;
+		value = DIV_ROUND_CLOSEST(((unsigned int)value) * SQ24860_IIN_OCF_DIV,
+					  SQ24860_IIN_OCF_NUM);
+		value = clamp_val(value, 0, 0x3f);
+		ret = pmbus_write_byte_data(client, page, SQ24860_VIREF, value);
+		break;
+
+	case PMBUS_VIRT_SAMPLES:
+		value = clamp_val(value, 1, SQ24860_MAX_SAMPLES);
+		value = ilog2(value);
+		ret = pmbus_update_byte_data(client, page, SQ24860_PK_MIN_AVG,
+					     PK_MIN_AVG_AVG_CNT,
+					     FIELD_PREP(PK_MIN_AVG_AVG_CNT, value));
+		break;
+
+	case PMBUS_VIRT_RESET_TEMP_HISTORY:
+	case PMBUS_VIRT_RESET_VIN_HISTORY:
+	case PMBUS_VIRT_RESET_IIN_HISTORY:
+	case PMBUS_VIRT_RESET_PIN_HISTORY:
+	case PMBUS_VIRT_RESET_VOUT_HISTORY:
+		/*
+		 * SQ24860 has history resets based on MIN/AVG/PEAK instead of per
+		 * sensor type. Exposing this quirk in hwmon is not desirable so
+		 * reset MIN, AVG and PEAK together. Even is there effectively only
+		 * one reset, which resets everything, expose the 5 entries so
+		 * userspace is not required map a sensor type to another to trigger
+		 * a reset
+		 */
+		ret = pmbus_update_byte_data(client, 0, SQ24860_PK_MIN_AVG,
+					     PK_MIN_AVG_RST_MASK,
+					     PK_MIN_AVG_RST_MASK);
+		break;
+
+	default:
+		ret = -ENODATA;
+		break;
+	}
+
+	return ret;
+}
+
+static int sq24860_read_byte_data(struct i2c_client *client,
+				   int page, int reg)
+{
+	int ret;
+
+	switch (reg) {
+	case PMBUS_WRITE_PROTECT:
+		ret = sq24860_mfr_write_protect_get(client);
+		break;
+
+	default:
+		ret = -ENODATA;
+		break;
+	}
+
+	return ret;
+}
+
+static int sq24860_write_byte_data(struct i2c_client *client,
+				    int page, int reg, u8 byte)
+{
+	int ret;
+
+	switch (reg) {
+	case PMBUS_WRITE_PROTECT:
+		ret = sq24860_mfr_write_protect_set(client, byte);
+		break;
+
+	default:
+		ret = -ENODATA;
+		break;
+	}
+
+	return ret;
+}
+
+#if IS_ENABLED(CONFIG_SENSORS_SQ24860_REGULATOR)
+static const struct regulator_desc sq24860_reg_desc[] = {
+	PMBUS_REGULATOR_ONE_NODE("vout"),
+};
+#endif
+
+static const struct pmbus_driver_info sq24860_base_info = {
+	.pages = 1,
+	.format[PSC_VOLTAGE_IN] = direct,
+	.m[PSC_VOLTAGE_IN] = 64,
+	.b[PSC_VOLTAGE_IN] = 0,
+	.R[PSC_VOLTAGE_IN] = 0,
+	.format[PSC_VOLTAGE_OUT] = direct,
+	.m[PSC_VOLTAGE_OUT] = 64,
+	.b[PSC_VOLTAGE_OUT] = 0,
+	.R[PSC_VOLTAGE_OUT] = 0,
+	.format[PSC_TEMPERATURE] = direct,
+	.m[PSC_TEMPERATURE] = 1,
+	.b[PSC_TEMPERATURE] = 0,
+	.R[PSC_TEMPERATURE] = 0,
+	/*
+	* Current and power measurements depend on the calibration gain
+	* programmed from the board-specific IMON resistor value.
+	*/
+	.format[PSC_CURRENT_IN] = direct,
+	.m[PSC_CURRENT_IN] = 16,
+	.b[PSC_CURRENT_IN] = 0,
+	.R[PSC_CURRENT_IN] = 0,
+	.format[PSC_POWER] = direct,
+	.m[PSC_POWER] = 2,
+	.b[PSC_POWER] = 0,
+	.R[PSC_POWER] = 0,
+	.func[0] = (PMBUS_HAVE_VIN |
+		    PMBUS_HAVE_VOUT |
+		    PMBUS_HAVE_VMON |
+		    PMBUS_HAVE_IIN |
+		    PMBUS_HAVE_PIN |
+		    PMBUS_HAVE_TEMP |
+		    PMBUS_HAVE_STATUS_VOUT |
+		    PMBUS_HAVE_STATUS_IOUT |
+		    PMBUS_HAVE_STATUS_INPUT |
+		    PMBUS_HAVE_STATUS_TEMP |
+		    PMBUS_HAVE_SAMPLES),
+	.read_word_data = sq24860_read_word_data,
+	.write_word_data = sq24860_write_word_data,
+	.read_byte_data = sq24860_read_byte_data,
+	.write_byte_data = sq24860_write_byte_data,
+
+#if IS_ENABLED(CONFIG_SENSORS_SQ24860_REGULATOR)
+	.reg_desc = sq24860_reg_desc,
+	.num_regulators = ARRAY_SIZE(sq24860_reg_desc),
+#endif
+};
+
+static const struct i2c_device_id sq24860_i2c_id[] = {
+	{ "sq24860" },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, sq24860_i2c_id);
+
+static const struct of_device_id sq24860_of_match[] = {
+	{ .compatible = "silergy,sq24860" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sq24860_of_match);
+
+static int sq24860_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct pmbus_driver_info *info;
+	u32 rimon = SQ24860_DEFAULT_RIMON;
+	u32 gimon = SQ24860_DEFAULT_GIMON;
+	int ret;
+
+	ret = device_property_read_u32(dev, "silergy,rimon-micro-ohms", &rimon);
+	if (ret < 0 && ret != -EINVAL)
+		return dev_err_probe(dev, ret, "failed to get rimon\n");
+
+	ret = sq24860_write_iin_cal_gain(client, rimon, gimon);
+	if (ret < 0)
+		return dev_err_probe(&client->dev, ret,
+					     "Failed to set gain\n");
+	info = devm_kmemdup(dev, &sq24860_base_info, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	return pmbus_do_probe(client, info);
+}
+
+static struct i2c_driver sq24860_driver = {
+	.driver = {
+		.name = "sq24860",
+		.of_match_table = sq24860_of_match,
+	},
+	.probe = sq24860_probe,
+	.id_table = sq24860_i2c_id,
+};
+module_i2c_driver(sq24860_driver);
+
+MODULE_AUTHOR("Ziming Zhu <ziming.zhu@silergycorp.com>");
+MODULE_DESCRIPTION("PMBUS driver for SQ24860 eFuse");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("PMBUS");
-- 
2.25.1


^ permalink raw reply related

* [PATCH v2 3/3] hwmon: Add documentation for SQ24860
From: Ziming Zhu @ 2026-06-05  6:30 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Shuah Khan, linux-hwmon, devicetree, linux-kernel, linux-doc,
	Ziming Zhu
In-Reply-To: <20260605063042.91776-1-zmzhu0630@163.com>

From: Ziming Zhu <ziming.zhu@silergycorp.com>

Document the supported sysfs attributes for the Silergy SQ24860 PMBus
hwmon driver.

Signed-off-by: Ziming Zhu <ziming.zhu@silergycorp.com>
---
 Documentation/hwmon/index.rst   |  1 +
 Documentation/hwmon/sq24860.rst | 96 +++++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+)
 create mode 100644 Documentation/hwmon/sq24860.rst

diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 8b655e5d6b68..1888905cd234 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -242,6 +242,7 @@ Hardware Monitoring Kernel Drivers
    smsc47m192
    smsc47m1
    sparx5-temp
+   sq24860
    spd5118
    stpddc60
    surface_fan
diff --git a/Documentation/hwmon/sq24860.rst b/Documentation/hwmon/sq24860.rst
new file mode 100644
index 000000000000..f0182b955d8a
--- /dev/null
+++ b/Documentation/hwmon/sq24860.rst
@@ -0,0 +1,96 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver sq24860
+=====================
+
+Supported chips:
+
+  * Silergy SQ24860
+
+    Prefix: 'sq24860'
+
+Author:
+
+	Ziming Zhu <ziming.zhu@silergycorp.com>
+
+Description
+------------
+
+This driver implements support for the Silergy SQ24860 eFuse. The device is an
+integrated circuit protection and power management device with a PMBus
+interface.
+
+The device supports direct format for reading input voltage, output voltage,
+auxiliary voltage, input current, input power, and temperature.
+
+The current and power measurement scale depends on the resistor connected
+between the IMON pin and ground. The resistor value can be configured with the
+``silergy,rimon-micro-ohms`` device tree property. See
+``Documentation/devicetree/bindings/hwmon/pmbus/silergy,sq24860.yaml`` for details.
+
+Due to the specificities of the chip, all history reset attributes are tied
+together. Resetting the history of one sensor resets the history of all sensors.
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+======================= ======================================================
+in1_label               "vin"
+in1_input               Measured input voltage.
+in1_average             Average measured input voltage.
+in1_min                 Minimum input voltage limit.
+in1_lcrit               Critical low input voltage limit.
+in1_max                 Maximum input voltage limit.
+in1_crit                Critical high input voltage limit.
+in1_min_alarm           Input voltage low warning alarm.
+in1_lcrit_alarm         Input voltage low fault alarm.
+in1_max_alarm           Input voltage high warning alarm.
+in1_crit_alarm          Input voltage high fault alarm.
+in1_highest             Historical maximum input voltage.
+in1_lowest              Historical minimum input voltage.
+in1_reset_history       Write any value to reset history.
+
+in2_label               "vmon"
+in2_input               Measured auxiliary input voltage.
+
+in3_label               "vout1"
+in3_input               Measured output voltage.
+in3_average             Average measured output voltage.
+in3_min                 Minimum output voltage limit.
+in3_min_alarm           Output voltage low alarm.
+in3_lowest              Historical minimum output voltage.
+in3_reset_history       Write any value to reset history.
+
+curr1_label             "iin"
+curr1_input             Measured input current.
+curr1_average           Average measured input current.
+curr1_max               Maximum input current warning limit.
+curr1_crit              Critical input over-current fault limit.
+curr1_max_alarm         Input current warning alarm.
+curr1_crit_alarm        Input over-current fault alarm.
+curr1_highest           Historical maximum input current.
+curr1_reset_history     Write any value to reset history.
+
+power1_label            "pin"
+power1_input            Measured input power.
+power1_average          Average measured input power.
+power1_max              Maximum input power warning limit.
+power1_alarm            Input power warning alarm.
+power1_input_highest    Historical maximum input power.
+power1_reset_history    Write any value to reset history.
+
+temp1_input             Measured temperature.
+temp1_average           Average measured temperature.
+temp1_max               Maximum temperature warning limit.
+temp1_crit              Critical temperature fault limit.
+temp1_max_alarm         Temperature warning alarm.
+temp1_crit_alarm        Temperature fault alarm.
+temp1_highest           Historical maximum temperature.
+temp1_reset_history     Write any value to reset history.
+
+samples                 Number of samples used for average values.
+======================= ======================================================
+
-- 
2.25.1


^ permalink raw reply related

* [PATCH v2 1/3] dt-bindings: hwmon: pmbus: Add bindings for Silergy SQ24860
From: Ziming Zhu @ 2026-06-05  6:30 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Shuah Khan, linux-hwmon, devicetree, linux-kernel, linux-doc,
	Ziming Zhu
In-Reply-To: <20260605063042.91776-1-zmzhu0630@163.com>

From: Ziming Zhu <ziming.zhu@silergycorp.com>

Add devicetree binding documentation for the Silergy SQ24860 eFuse.

The device is a PMBus hardware monitoring device which reports voltage,
current, power, and temperature telemetry. The board-specific IMON
resistor value is described with silergy,rimon-micro-ohms.

Signed-off-by: Ziming Zhu <ziming.zhu@silergycorp.com>
---
 .../bindings/hwmon/pmbus/silergy,sq24860.yaml | 74 +++++++++++++++++++
 1 file changed, 74 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/pmbus/silergy,sq24860.yaml

diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/silergy,sq24860.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/silergy,sq24860.yaml
new file mode 100644
index 000000000000..03ef82c11e1a
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/silergy,sq24860.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/pmbus/silergy,sq24860.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Silergy SQ24860 eFuse
+
+maintainers:
+  - Ziming Zhu <ziming.zhu@silergycorp.com>
+
+description:
+  The Silergy SQ24860 is an integrated, high-current circuit protection and
+  power management device with PMBus interface.
+
+properties:
+  compatible:
+    const: silergy,sq24860
+
+  reg:
+    maxItems: 1
+
+  silergy,rimon-micro-ohms:
+    description:
+      Micro-ohms value of the resistance installed between the IMON pin and
+      the ground reference.
+
+  interrupts:
+    description: PMBus SMBAlert interrupt.
+    maxItems: 1
+
+  regulators:
+    type: object
+    description:
+      List of regulators provided by this controller.
+
+    properties:
+      vout:
+        $ref: /schemas/regulator/regulator.yaml#
+        type: object
+        unevaluatedProperties: false
+
+    additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - silergy,rimon-micro-ohms
+
+additionalProperties: false
+
+examples:
+  - |
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        hw-monitor@40 {
+            compatible = "silergy,sq24860";
+            reg = <0x40>;
+
+            interrupt-parent = <&gpio>;
+            interrupts = <42 8>;
+            silergy,rimon-micro-ohms = <1600000000>;
+
+            regulators {
+                cpu0_vout: vout {
+                    regulator-name = "main_cpu0";
+                };
+            };
+        };
+    };
-- 
2.25.1


^ permalink raw reply related

* [PATCH RESEND] checkpatch: Suppress warnings when Reported-by: is followed by Link:
From: Cryolitia PukNgae @ 2026-06-05  6:57 UTC (permalink / raw)
  To: Andy Whitcroft, Joe Perches, Dwaipayan Ray, Lukas Bulwahn
  Cc: Andrew Morton, linux-doc, linux-mm, linux-kernel, zhanjun,
	niecheng1, kernel, Cryolitia PukNgae, Petr Vorel

From: Cryolitia PukNgae <cryolitia@uniontech.com>

> The tag should be followed by a Closes: tag pointing to the report,
> unless the report is not available on the web. The Link: tag can be
> used instead of Closes: if the patch fixes a part of the issue(s)
> being reported.

Accroding to Documentation/process/submitting-patches.rst , Link: is
also acceptable to followed a Reported-by:, if the patch fixes a part
of the issue(s) being reported.

Reviewed-by: Petr Vorel <pvorel@suse.cz>
Signed-off-by: Cryolitia PukNgae <cryolitia@uniontech.com>
---
 scripts/checkpatch.pl | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 0492d6afc9a1..bb452f5313b6 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -3233,10 +3233,10 @@ sub process {
 			if ($sign_off =~ /^reported(?:|-and-tested)-by:$/i) {
 				if (!defined $lines[$linenr]) {
 					WARN("BAD_REPORTED_BY_LINK",
-					     "Reported-by: should be immediately followed by Closes: with a URL to the report\n" . $herecurr . "\n");
-				} elsif ($rawlines[$linenr] !~ /^closes:\s*/i) {
+					     "Reported-by: should be immediately followed by Closes: or Link: with a URL to the report\n" . $herecurr . "\n");
+				} elsif ($rawlines[$linenr] !~ /^(closes|link):\s*/i) {
 					WARN("BAD_REPORTED_BY_LINK",
-					     "Reported-by: should be immediately followed by Closes: with a URL to the report\n" . $herecurr . $rawlines[$linenr] . "\n");
+					     "Reported-by: should be immediately followed by Closes: or Link: with a URL to the report\n" . $herecurr . $rawlines[$linenr] . "\n");
 				}
 			}
 		}

---
base-commit: ddd664bbff63e09e7a7f9acae9c43605d4cf185f
change-id: 20260401-checkpatch-b97d0cbe7ee9

Best regards,
--  
Cryolitia PukNgae <cryolitia.pukngae@linux.dev>



^ permalink raw reply related

* Re: [PATCH v2 2/3] PM: dpm_watchdog: Allow disabling DPM watchdog by default
From: Tzung-Bi Shih @ 2026-06-05  7:10 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Jonathan Corbet, Rafael J. Wysocki, Greg Kroah-Hartman,
	Danilo Krummrich, Shuah Khan, Pavel Machek, Len Brown, linux-doc,
	linux-kernel, linux-pm, driver-core, tfiga, senozhatsky
In-Reply-To: <32fda49e-f246-4fae-9e4e-05c12fdb3ea6@infradead.org>

On Thu, Jun 04, 2026 at 09:53:11PM -0700, Randy Dunlap wrote:
> On 6/4/26 2:07 AM, Tzung-Bi Shih wrote:
> > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> > index 00375193bd26..0a0d5340b0c7 100644
> > --- a/Documentation/admin-guide/kernel-parameters.txt
> > +++ b/Documentation/admin-guide/kernel-parameters.txt
> > @@ -5399,6 +5399,14 @@ Kernel parameters
> >  			function to NULL. On Idle the CPU just reduces
> >  			execution priority.
> >  
> > +	power.dpm_watchdog_enabled=
> > +			[KNL] Enable or disable the device suspend/resume
> 
> I think that [KNL] isn't very useful here (nor in many of its uses in
> kernel-parameters.txt).
> What is required to use this option are:
>   CONFIG_PM_SLEEP, CONFIG_DPM_WATCHDOG
> You should convey that information somehow.
> 
> Also, in kernel-parameters.txt, "pm_async=" is only valid when [PM]
> is enabled, but "PM" is not defined/described anywhere.
> That should be added near the beginning of kernel-parameters.txt (in
> alphabetical order).

Thank you for your review.  Will fix them in the next version.

^ permalink raw reply

* htmldocs: Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/net/toshiba,tc956x-dwmac.yaml
From: kernel test robot @ 2026-06-05  7:15 UTC (permalink / raw)
  To: Daniel Thompson; +Cc: oe-kbuild-all, 0day robot, Alex Elder, linux-doc

tree:   https://github.com/intel-lab-lkp/linux/commits/Alex-Elder/dt-bindings-net-qca-qca808x-Add-regulator-properties/20260605-091912
head:   a2cf643cd5401eea03d3f1a49d81e7d066ae6047
commit: b6d9c722ce11c43b1e14ca3a15d993e470299502 dt-bindings: net: toshiba,tc9654-dwmac: add TC9564 Ethernet bridge
date:   6 hours ago
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project f43d6834093b19baf79beda8c0337ab020ac5f17)
docutils: docutils (Docutils 0.21.2, Python 3.13.5, on linux)
reproduce: (https://download.01.org/0day-ci/archive/20260605/202606050946.JGkrxO1C-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202606050946.JGkrxO1C-lkp@intel.com/

All warnings (new ones prefixed by >>):

   Warning: Documentation/translations/zh_CN/how-to.rst references a file that doesn't exist: Documentation/xxx/xxx.rst
   Warning: Documentation/translations/zh_CN/networking/xfrm_proc.rst references a file that doesn't exist: Documentation/networking/xfrm_proc.rst
   Warning: Documentation/translations/zh_CN/scsi/scsi_mid_low_api.rst references a file that doesn't exist: Documentation/Configure.help
   Warning: MAINTAINERS references a file that doesn't exist: Documentation/ABI/testing/sysfs-platform-ayaneo
   Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/display/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt
>> Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/net/toshiba,tc956x-dwmac.yaml
   Warning: arch/powerpc/sysdev/mpic.c references a file that doesn't exist: Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
   Warning: drivers/net/ethernet/smsc/Kconfig references a file that doesn't exist: file:Documentation/networking/device_drivers/ethernet/smsc/smc9.rst
   Warning: rust/kernel/sync/atomic/ordering.rs references a file that doesn't exist: srctree/tools/memory-model/Documentation/explanation.txt
   Warning: tools/docs/documentation-file-ref-check references a file that doesn't exist: Documentation/virtual/lguest/lguest.c
   Warning: tools/docs/documentation-file-ref-check references a file that doesn't exist: m,\b(\S*)(Documentation/[A-Za-z0-9

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH mm-unstable v18 06/14] mm/khugepaged: generalize collapse_huge_page for mTHP collapse
From: David Hildenbrand (Arm) @ 2026-06-05  7:18 UTC (permalink / raw)
  To: Nico Pache
  Cc: Lance Yang, linux-doc, linux-kernel, linux-mm, linux-trace-kernel,
	aarcange, akpm, anshuman.khandual, apopple, baohua, baolin.wang,
	byungchul, catalin.marinas, cl, corbet, dave.hansen, dev.jain,
	gourry, hannes, hughd, jack, jackmanb, jannh, jglisse,
	joshua.hahnjy, kas, liam, ljs, mathieu.desnoyers, matthew.brost,
	mhiramat, mhocko, peterx, pfalcato, rakie.kim, raquini, rdunlap,
	richard.weiyang, rientjes, rostedt, rppt, ryan.roberts, shivankg,
	sunnanyong, surenb, thomas.hellstrom, tiwai, usamaarif642, vbabka,
	vishal.moola, wangkefeng.wang, will, willy, yang, ying.huang, ziy,
	zokeefe, usama.arif
In-Reply-To: <CAA1CXcBSPVG4CJFCBDvbuodcJ_7eXoDQTpK0ZN0HEhkDPi-DEw@mail.gmail.com>

On 6/4/26 19:04, Nico Pache wrote:
> On Mon, Jun 1, 2026 at 9:00 AM Nico Pache <npache@redhat.com> wrote:
>>
>> On Mon, Jun 1, 2026 at 5:14 AM David Hildenbrand (Arm) <david@kernel.org> wrote:
>>>
>>>
>>> Yeah. BTW, I think we'd need a spin_lock_nested(), so @Nico, treat my code as a
>>> draft.
>>
>> Okay, I read the above and did some investigating.
>>
>> I will try to implement and verify the changes you suggested :)
> 
> I've implemented something slightly different actually and I *think* its better!
> 
> } else {
>        /* this is map_anon_folio_pte_nopf with no mmu update */
>         __map_anon_folio_pte_nopf(folio, pte, vma, start_addr,
>                       /*uffd_wp=*/ false);
>        smp_wmb();
>         pmd_populate(mm, pmd, pmd_pgtable(_pmd));
>         /*
>          * Some architectures (e.g. MIPS) walk the live page table in
>          * their implementation. update_mmu_cache_range() must be called
>          * with a valid page table hierarchy and the PTE lock held.
>          * Acquire it nested inside pmd_ptl when they are distinct locks.
>          */
>         if (pte_ptl != pmd_ptl)
>             spin_lock_nested(pte_ptl, SINGLE_DEPTH_NESTING);
>         update_mmu_cache_range(NULL, vma, start_addr, pte, nr_pages);
>         if (pte_ptl != pmd_ptl)
>             spin_unlock(pte_ptl);
>     }
> spin_unlock(pmd_ptl);
> 
> The logic here is that when the PMD becomes visible, PTEs are already
> populated (no possibility of spurious faults on local CPU)
> 
> the SMP_WMB makes sure of the above
> 
> And the pmd is installed with the pte and pmd lock both held through
> the mmu_cache update.
> 
> This follows the conventions used in pmd_install() and clears the
> potential for local CPU faults hitting cleared PTE entries.

After the pmdp_collapse_flush() we'd be getting CPU faults due to the cleared
PMD already? So the case here is rather different.

-- 
Cheers,

David

^ permalink raw reply

* Re: configurable block error injection
From: Christoph Hellwig @ 2026-06-05  7:23 UTC (permalink / raw)
  To: Daniel Gomez
  Cc: Christoph Hellwig, Jens Axboe, Jonathan Corbet, linux-block,
	linux-doc, bpf, linux-kselftest, Luis Chamberlain,
	Masami Hiramatsu, Brendan Gregg, GOST, Shin'ichiro Kawasaki
In-Reply-To: <d9a5b911-7692-4df2-b67c-c33bc80b61aa@kernel.org>

On Thu, Jun 04, 2026 at 01:06:13PM +0200, Daniel Gomez wrote:
> IIU the series correctly, and oversimplifying: when
> injection is enabled and a bio matches, the block layer completes the
> bio inline with the chosen blk_status_t (the status= rule from debugfs)
> via bio_endio_status(). The submission path returns to the caller
> immediately, with the bio already in the error state. Nothing is ever
> sent to the device, but the completion path sees the injected error.

Yes.

> > I'd have to allow access to certain bio
> 
> With struct_ops the bio is passed to the ebpf side as read-only, bio 
> fields can be read to decide the policy but cannot write them. Is 
> read-only access to bio fields itself a concern?

Yes, for the reason state below.

> 
> > fields and would have create a stable UAPI for commands and status
> > using the fake BTF struct access which really would not be a good
> > idea here as we need to be able to change internals.  
> 
> That should not be a problem at all. With CO-RE (compile once, run
> everywhere) the program resolves the bio field offsets against the
> BTF of the kernel it loads on, so it adapts dynamically if the layout
> changes. The contract is just the struct_ops callback signature: a
> struct bio * argument and a blk_status_t return. And that doesn't imply
> any UAPI commitment AFAIK.

That assumes the fields even exists in this form.  And we definitively
need to do things about the iter going ahead.  In other words we have
to build up a huge abstraction here first.

> > Additionally
> > having fully BTF-enabled toolchains in test VMs is not great either.
> 
> Are you referring to the old BCC toolchain requirements [1]? This is
> solved in CO-RE [2]. The toolchain (Clang/LLVM, pahole) stays on the
> build host; the test VM only needs the prebuilt BPF object, libbpf at
> runtime, and the kernel's own BTF (CONFIG_DEBUG_INFO_BTF). No compiler
> or BTF toolchain is required inside the VM. Clang/LLVM 10+ is enough to
> build CO-RE libbpf tools [3].

libbpf and BTF support is what I mean.  And of course whatever code
you write to communicate with it as a simple shell script won't work
any more.

> Are you referring to the bio sector range comparison in
> __blk_error_inject()?

Yes.

> I don't think that needs to be delegated to a
> BPF map (Documentation/bpf/maps.rst). The ebpf side has direct access
> to the bio fields, so it can apply the same sector/op filtering
> __blk_error_inject() does today. That match is already a linear list
> walk, so the ebpf program just runs the same [start, end] condition
> check.

Which means I need to write eBPF code for every specific range I
want to inject, which makes the thing very hard to use.

> In summary: what do you think of evolving this series
> into eBPF, but BPF_PROG_TYPE_STRUCT_OPS instead of
> ALLOW_ERROR_INJECTION/bpf_override_return()?.

As said before, I prototyped it and it was a mess.  Having about 300
lines of simple code that can be directly used from a shell script
seems much preferable.


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox