* [PATCH v7 3/5] kunit: Add backtrace suppression self-tests
From: Albert Esteve @ 2026-04-20 12:28 UTC (permalink / raw)
To: Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton
Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
workflows, linux-doc, peterz, Guenter Roeck,
Linux Kernel Functional Testing, Dan Carpenter,
Alessandro Carminati, Albert Esteve, Kees Cook
In-Reply-To: <20260420-kunit_add_support-v7-0-e8bc6e0f70de@redhat.com>
From: Guenter Roeck <linux@roeck-us.net>
Add unit tests to verify that warning backtrace suppression works,
covering WARN() and WARN_ON() with direct calls, indirect calls
through helper functions, and multiple warnings in a single window.
If backtrace suppression does _not_ work, the unit tests will likely
trigger unsuppressed backtraces, which should actually help to get
the affected architectures / platforms fixed.
Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
Acked-by: Dan Carpenter <dan.carpenter@linaro.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina@redhat.com>
Signed-off-by: Albert Esteve <aesteve@redhat.com>
---
lib/kunit/Makefile | 3 ++
lib/kunit/backtrace-suppression-test.c | 90 ++++++++++++++++++++++++++++++++++
2 files changed, 93 insertions(+)
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index fe177ff3ebdef..b2f2b8ada7b71 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -23,6 +23,9 @@ obj-$(if $(CONFIG_KUNIT),y) += hooks.o \
obj-$(CONFIG_KUNIT_TEST) += kunit-test.o
obj-$(CONFIG_KUNIT_TEST) += platform-test.o
+ifeq ($(CONFIG_KUNIT_SUPPRESS_BACKTRACE),y)
+obj-$(CONFIG_KUNIT_TEST) += backtrace-suppression-test.o
+endif
# string-stream-test compiles built-in only.
ifeq ($(CONFIG_KUNIT_TEST),y)
diff --git a/lib/kunit/backtrace-suppression-test.c b/lib/kunit/backtrace-suppression-test.c
new file mode 100644
index 0000000000000..2ba5dcb5fef35
--- /dev/null
+++ b/lib/kunit/backtrace-suppression-test.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit test for suppressing warning tracebacks.
+ *
+ * Copyright (C) 2024, Guenter Roeck
+ * Author: Guenter Roeck <linux@roeck-us.net>
+ */
+
+#include <kunit/test.h>
+#include <linux/bug.h>
+
+static void backtrace_suppression_test_warn_direct(struct kunit *test)
+{
+ KUNIT_START_SUPPRESSED_WARNING(test);
+ WARN(1, "This backtrace should be suppressed");
+ KUNIT_END_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), 1);
+}
+
+static void trigger_backtrace_warn(void)
+{
+ WARN(1, "This backtrace should be suppressed");
+}
+
+static void backtrace_suppression_test_warn_indirect(struct kunit *test)
+{
+ KUNIT_START_SUPPRESSED_WARNING(test);
+ trigger_backtrace_warn();
+ KUNIT_END_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), 1);
+}
+
+static void backtrace_suppression_test_warn_multi(struct kunit *test)
+{
+ KUNIT_START_SUPPRESSED_WARNING(test);
+ WARN(1, "This backtrace should be suppressed");
+ trigger_backtrace_warn();
+ KUNIT_END_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), 2);
+}
+
+static void backtrace_suppression_test_warn_on_direct(struct kunit *test)
+{
+ if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE) && !IS_ENABLED(CONFIG_KALLSYMS))
+ kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE or CONFIG_KALLSYMS");
+
+ KUNIT_START_SUPPRESSED_WARNING(test);
+ WARN_ON(1);
+ KUNIT_END_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), 1);
+}
+
+static void trigger_backtrace_warn_on(void)
+{
+ WARN_ON(1);
+}
+
+static void backtrace_suppression_test_warn_on_indirect(struct kunit *test)
+{
+ if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE))
+ kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE");
+
+ KUNIT_START_SUPPRESSED_WARNING(test);
+ trigger_backtrace_warn_on();
+ KUNIT_END_SUPPRESSED_WARNING(test);
+
+ KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), 1);
+}
+
+static struct kunit_case backtrace_suppression_test_cases[] = {
+ KUNIT_CASE(backtrace_suppression_test_warn_direct),
+ KUNIT_CASE(backtrace_suppression_test_warn_indirect),
+ KUNIT_CASE(backtrace_suppression_test_warn_multi),
+ KUNIT_CASE(backtrace_suppression_test_warn_on_direct),
+ KUNIT_CASE(backtrace_suppression_test_warn_on_indirect),
+ {}
+};
+
+static struct kunit_suite backtrace_suppression_test_suite = {
+ .name = "backtrace-suppression-test",
+ .test_cases = backtrace_suppression_test_cases,
+};
+kunit_test_suites(&backtrace_suppression_test_suite);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("KUnit test to verify warning backtrace suppression");
--
2.52.0
^ permalink raw reply related
* [PATCH v7 2/5] bug/kunit: Reduce runtime impact of warning backtrace suppression
From: Albert Esteve @ 2026-04-20 12:28 UTC (permalink / raw)
To: Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton
Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
workflows, linux-doc, peterz, Alessandro Carminati, Albert Esteve
In-Reply-To: <20260420-kunit_add_support-v7-0-e8bc6e0f70de@redhat.com>
From: Alessandro Carminati <acarmina@redhat.com>
KUnit support is not consistently present across distributions, some
include it in their stock kernels, while others do not.
While both KUNIT and KUNIT_SUPPRESS_BACKTRACE can be considered debug
features, the fact that some distros ship with KUnit enabled means it's
important to minimize the runtime impact of this patch.
To that end, this patch adds an atomic counter that tracks the number
of active suppressions. __kunit_is_suppressed_warning() checks this
counter first and returns immediately when no suppressions are active,
avoiding RCU-protected list traversal in the common case.
Signed-off-by: Alessandro Carminati <acarmina@redhat.com>
Signed-off-by: Albert Esteve <aesteve@redhat.com>
---
lib/kunit/bug.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/lib/kunit/bug.c b/lib/kunit/bug.c
index 356c8a5928828..a7a88f0670d44 100644
--- a/lib/kunit/bug.c
+++ b/lib/kunit/bug.c
@@ -8,6 +8,7 @@
#include <kunit/bug.h>
#include <kunit/resource.h>
+#include <linux/atomic.h>
#include <linux/export.h>
#include <linux/rculist.h>
#include <linux/sched.h>
@@ -15,11 +16,13 @@
#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
static LIST_HEAD(suppressed_warnings);
+static atomic_t suppressed_warnings_cnt = ATOMIC_INIT(0);
static void __kunit_suppress_warning_remove(struct __suppressed_warning *warning)
{
list_del_rcu(&warning->node);
synchronize_rcu(); /* Wait for readers to finish */
+ atomic_dec(&suppressed_warnings_cnt);
}
KUNIT_DEFINE_ACTION_WRAPPER(__kunit_suppress_warning_cleanup,
@@ -37,6 +40,7 @@ __kunit_start_suppress_warning(struct kunit *test)
return NULL;
warning->task = current;
+ atomic_inc(&suppressed_warnings_cnt);
list_add_rcu(&warning->node, &suppressed_warnings);
ret = kunit_add_action_or_reset(test,
@@ -68,6 +72,9 @@ bool __kunit_is_suppressed_warning(void)
{
struct __suppressed_warning *warning;
+ if (!atomic_read(&suppressed_warnings_cnt))
+ return false;
+
rcu_read_lock();
list_for_each_entry_rcu(warning, &suppressed_warnings, node) {
if (warning->task == current) {
--
2.52.0
^ permalink raw reply related
* [PATCH v7 1/5] bug/kunit: Core support for suppressing warning backtraces
From: Albert Esteve @ 2026-04-20 12:28 UTC (permalink / raw)
To: Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton
Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
workflows, linux-doc, peterz, Alessandro Carminati, Guenter Roeck,
Kees Cook, Albert Esteve
In-Reply-To: <20260420-kunit_add_support-v7-0-e8bc6e0f70de@redhat.com>
From: Alessandro Carminati <acarmina@redhat.com>
Some unit tests intentionally trigger warning backtraces by passing bad
parameters to kernel API functions. Such unit tests typically check the
return value from such calls, not the existence of the warning backtrace.
Such intentionally generated warning backtraces are neither desirable
nor useful for a number of reasons:
- They can result in overlooked real problems.
- A warning that suddenly starts to show up in unit tests needs to be
investigated and has to be marked to be ignored, for example by
adjusting filter scripts. Such filters are ad hoc because there is
no real standard format for warnings. On top of that, such filter
scripts would require constant maintenance.
Solve the problem by providing a means to identify and suppress specific
warning backtraces while executing test code. Support suppressing multiple
backtraces while at the same time limiting changes to generic code to the
absolute minimum.
Implementation details:
Suppression is checked at two points in the warning path:
- In warn_slowpath_fmt(), the check runs before any output, fully
suppressing both message and backtrace.
- In __report_bug(), the check runs before __warn() is called,
suppressing the backtrace and stack dump. Note that on this path,
the WARN() format message may still appear in the kernel log since
__warn_printk() runs before the trap that enters __report_bug().
A helper function, `__kunit_is_suppressed_warning()`, walks an
RCU-protected list of active suppressions, matching by current task.
The suppression state is tied to the KUnit test lifecycle via
kunit_add_action(), ensuring automatic cleanup at test exit.
The list of suppressed warnings is protected with RCU to allow
concurrent read access without locks.
The implementation is deliberately simple and avoids architecture-specific
optimizations to preserve portability.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Alessandro Carminati <acarmina@redhat.com>
Reviewed-by: Kees Cook <kees@kernel.org>
Signed-off-by: Albert Esteve <aesteve@redhat.com>
---
include/kunit/bug.h | 56 +++++++++++++++++++++++++++++++++++
include/kunit/test.h | 1 +
kernel/panic.c | 8 ++++-
lib/bug.c | 8 +++++
lib/kunit/Kconfig | 9 ++++++
lib/kunit/Makefile | 6 ++--
lib/kunit/bug.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 169 insertions(+), 3 deletions(-)
diff --git a/include/kunit/bug.h b/include/kunit/bug.h
new file mode 100644
index 0000000000000..e52c9d21d9fe6
--- /dev/null
+++ b/include/kunit/bug.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KUnit helpers for backtrace suppression
+ *
+ * Copyright (C) 2025 Alessandro Carminati <acarmina@redhat.com>
+ * Copyright (C) 2024 Guenter Roeck <linux@roeck-us.net>
+ */
+
+#ifndef _KUNIT_BUG_H
+#define _KUNIT_BUG_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/kconfig.h>
+
+struct kunit;
+
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+
+#include <linux/types.h>
+
+struct task_struct;
+
+struct __suppressed_warning {
+ struct list_head node;
+ struct task_struct *task;
+ int counter;
+};
+
+struct __suppressed_warning *
+__kunit_start_suppress_warning(struct kunit *test);
+void __kunit_end_suppress_warning(struct kunit *test,
+ struct __suppressed_warning *warning);
+int __kunit_suppressed_warning_count(struct __suppressed_warning *warning);
+bool __kunit_is_suppressed_warning(void);
+
+#define KUNIT_START_SUPPRESSED_WARNING(test) \
+ struct __suppressed_warning *__kunit_suppress = \
+ __kunit_start_suppress_warning(test)
+
+#define KUNIT_END_SUPPRESSED_WARNING(test) \
+ __kunit_end_suppress_warning(test, __kunit_suppress)
+
+#define KUNIT_SUPPRESSED_WARNING_COUNT() \
+ __kunit_suppressed_warning_count(__kunit_suppress)
+
+#else /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+
+#define KUNIT_START_SUPPRESSED_WARNING(test)
+#define KUNIT_END_SUPPRESSED_WARNING(test)
+#define KUNIT_SUPPRESSED_WARNING_COUNT() 0
+static inline bool __kunit_is_suppressed_warning(void) { return false; }
+
+#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
+#endif /* __ASSEMBLY__ */
+#endif /* _KUNIT_BUG_H */
diff --git a/include/kunit/test.h b/include/kunit/test.h
index 9cd1594ab697d..4ec07b3fa0204 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -10,6 +10,7 @@
#define _KUNIT_TEST_H
#include <kunit/assert.h>
+#include <kunit/bug.h>
#include <kunit/try-catch.h>
#include <linux/args.h>
diff --git a/kernel/panic.c b/kernel/panic.c
index c78600212b6c1..d7a7a679f56c4 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -39,6 +39,7 @@
#include <linux/sys_info.h>
#include <trace/events/error_report.h>
#include <asm/sections.h>
+#include <kunit/bug.h>
#define PANIC_TIMER_STEP 100
#define PANIC_BLINK_SPD 18
@@ -1080,9 +1081,14 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
void warn_slowpath_fmt(const char *file, int line, unsigned taint,
const char *fmt, ...)
{
- bool rcu = warn_rcu_enter();
+ bool rcu;
struct warn_args args;
+ if (__kunit_is_suppressed_warning())
+ return;
+
+ rcu = warn_rcu_enter();
+
pr_warn(CUT_HERE);
if (!fmt) {
diff --git a/lib/bug.c b/lib/bug.c
index 623c467a8b76c..606205c8c302f 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -48,6 +48,7 @@
#include <linux/rculist.h>
#include <linux/ftrace.h>
#include <linux/context_tracking.h>
+#include <kunit/bug.h>
extern struct bug_entry __start___bug_table[], __stop___bug_table[];
@@ -223,6 +224,13 @@ static enum bug_trap_type __report_bug(struct bug_entry *bug, unsigned long buga
no_cut = bug->flags & BUGFLAG_NO_CUT_HERE;
has_args = bug->flags & BUGFLAG_ARGS;
+ /*
+ * Before the once logic so suppressed warnings do not consume
+ * the single-fire budget of WARN_ON_ONCE().
+ */
+ if (warning && __kunit_is_suppressed_warning())
+ return BUG_TRAP_TYPE_WARN;
+
if (warning && once) {
if (done)
return BUG_TRAP_TYPE_WARN;
diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig
index 498cc51e493dc..57527418fcf09 100644
--- a/lib/kunit/Kconfig
+++ b/lib/kunit/Kconfig
@@ -15,6 +15,15 @@ menuconfig KUNIT
if KUNIT
+config KUNIT_SUPPRESS_BACKTRACE
+ bool "KUnit - Enable backtrace suppression"
+ default y
+ help
+ Enable backtrace suppression for KUnit. If enabled, backtraces
+ generated intentionally by KUnit tests are suppressed. Disable
+ to reduce kernel image size if image size is more important than
+ suppression of backtraces generated by KUnit tests.
+
config KUNIT_DEBUGFS
bool "KUnit - Enable /sys/kernel/debug/kunit debugfs representation" if !KUNIT_ALL_TESTS
default KUNIT_ALL_TESTS
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 656f1fa35abcc..fe177ff3ebdef 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -16,8 +16,10 @@ ifeq ($(CONFIG_KUNIT_DEBUGFS),y)
kunit-objs += debugfs.o
endif
-# KUnit 'hooks' are built-in even when KUnit is built as a module.
-obj-$(if $(CONFIG_KUNIT),y) += hooks.o
+# KUnit 'hooks' and bug handling are built-in even when KUnit is built
+# as a module.
+obj-$(if $(CONFIG_KUNIT),y) += hooks.o \
+ bug.o
obj-$(CONFIG_KUNIT_TEST) += kunit-test.o
obj-$(CONFIG_KUNIT_TEST) += platform-test.o
diff --git a/lib/kunit/bug.c b/lib/kunit/bug.c
new file mode 100644
index 0000000000000..356c8a5928828
--- /dev/null
+++ b/lib/kunit/bug.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit helpers for backtrace suppression
+ *
+ * Copyright (C) 2025 Alessandro Carminati <acarmina@redhat.com>
+ * Copyright (C) 2024 Guenter Roeck <linux@roeck-us.net>
+ */
+
+#include <kunit/bug.h>
+#include <kunit/resource.h>
+#include <linux/export.h>
+#include <linux/rculist.h>
+#include <linux/sched.h>
+
+#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
+
+static LIST_HEAD(suppressed_warnings);
+
+static void __kunit_suppress_warning_remove(struct __suppressed_warning *warning)
+{
+ list_del_rcu(&warning->node);
+ synchronize_rcu(); /* Wait for readers to finish */
+}
+
+KUNIT_DEFINE_ACTION_WRAPPER(__kunit_suppress_warning_cleanup,
+ __kunit_suppress_warning_remove,
+ struct __suppressed_warning *);
+
+struct __suppressed_warning *
+__kunit_start_suppress_warning(struct kunit *test)
+{
+ struct __suppressed_warning *warning;
+ int ret;
+
+ warning = kunit_kzalloc(test, sizeof(*warning), GFP_KERNEL);
+ if (!warning)
+ return NULL;
+
+ warning->task = current;
+ list_add_rcu(&warning->node, &suppressed_warnings);
+
+ ret = kunit_add_action_or_reset(test,
+ __kunit_suppress_warning_cleanup,
+ warning);
+ if (ret)
+ return NULL;
+
+ return warning;
+}
+EXPORT_SYMBOL_GPL(__kunit_start_suppress_warning);
+
+void __kunit_end_suppress_warning(struct kunit *test,
+ struct __suppressed_warning *warning)
+{
+ if (!warning)
+ return;
+ kunit_release_action(test, __kunit_suppress_warning_cleanup, warning);
+}
+EXPORT_SYMBOL_GPL(__kunit_end_suppress_warning);
+
+int __kunit_suppressed_warning_count(struct __suppressed_warning *warning)
+{
+ return warning ? warning->counter : 0;
+}
+EXPORT_SYMBOL_GPL(__kunit_suppressed_warning_count);
+
+bool __kunit_is_suppressed_warning(void)
+{
+ struct __suppressed_warning *warning;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(warning, &suppressed_warnings, node) {
+ if (warning->task == current) {
+ warning->counter++;
+ rcu_read_unlock();
+ return true;
+ }
+ }
+ rcu_read_unlock();
+
+ return false;
+}
+
+#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
--
2.52.0
^ permalink raw reply related
* [PATCH v7 0/5] kunit: Add support for suppressing warning backtraces
From: Albert Esteve @ 2026-04-20 12:28 UTC (permalink / raw)
To: Arnd Bergmann, Brendan Higgins, David Gow, Rae Moar,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton
Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
workflows, linux-doc, peterz, Alessandro Carminati, Guenter Roeck,
Kees Cook, Albert Esteve, Linux Kernel Functional Testing,
Dan Carpenter, Maíra Canal, Kees Cook, Simona Vetter,
David Gow
Some unit tests intentionally trigger warning backtraces by passing bad
parameters to kernel API functions. Such unit tests typically check the
return value from such calls, not the existence of the warning backtrace.
Such intentionally generated warning backtraces are neither desirable
nor useful for a number of reasons:
- They can result in overlooked real problems.
- A warning that suddenly starts to show up in unit tests needs to be
investigated and has to be marked to be ignored, for example by
adjusting filter scripts. Such filters are ad hoc because there is
no real standard format for warnings. On top of that, such filter
scripts would require constant maintenance.
One option to address the problem would be to add messages such as
"expected warning backtraces start/end here" to the kernel log.
However, that would again require filter scripts, might result in
missing real problematic warning backtraces triggered while the test
is running, and the irrelevant backtrace(s) would still clog the
kernel log.
Solve the problem by providing a means to identify and suppress specific
warning backtraces while executing test code. Support suppressing multiple
backtraces while at the same time limiting changes to generic code to the
absolute minimum.
Overview:
Patch#1 Introduces the suppression infrastructure.
Patch#2 Mitigates the impact of suppression.
Patch#3 Adds selftests to validate the functionality.
Patch#4 Demonstrates real-world usage in the DRM subsystem.
Patch#5 Documents the new API and usage guidelines.
Design Notes:
The objective is to suppress unwanted WARN*() generated messages.
Although most major architectures share common bug handling via `lib/bug.c`
and `report_bug()`, some minor or legacy architectures still rely on their
own platform-specific handling. This divergence must be considered in any
such feature. Additionally, a key challenge in implementing this feature is
the fragmentation of `WARN*()` message emission: part of the output is
produced in the macro itself (via __warn_printk()), and part in the exception
handler.
Lessons from the Previous Attempt:
In earlier iterations, suppression logic was added inside the
`__report_bug()` function to intercept WARN*() output. To implement the
check in the bug handler code, two strategies were considered:
* Strategy #1: Use `kallsyms` to infer the originating function. This
approach proved unreliable due to compiler-induced transformations
such as inlining, cloning, and code fragmentation.
* Strategy #2: Store function name `__func__` in `struct bug_entry` in
the `__bug_table`. However, `__func__` is a compiler-generated symbol,
which complicates relocation and linking in position-independent code.
Additionally, architectures not using the unified `BUG()` path would
still require ad-hoc handling.
A per-macro solution was also attempted (v5-v6), injecting checks
directly into the `WARN*()` macros in `include/asm-generic/bug.h`.
While this offered full control, it required modifying the generic
bug header and was considered too invasive and damaging the critical
path, and thus incorrect [1].
Current Proposal: Check in `warn_slowpath_fmt()` and `__report_bug()`.
Suppression is checked at two points in the warning path:
- In `warn_slowpath_fmt()` (kernel/panic.c), for architectures without
__WARN_FLAGS. The check runs before any output, fully suppressing
both message and backtrace.
- In `__report_bug()` (lib/bug.c), for architectures that define
__WARN_FLAGS. The check runs before `__warn()` is called, suppressing
the backtrace and stack dump. On this path, the `WARN()` format message
may still appear in the kernel log since `__warn_printk()` executes
before the trap.
This approach avoids modifying include/asm-generic/bug.h entirely,
requires no architecture-specific code, and limits changes to generic
code to the absolute minimum.
A helper function, `__kunit_is_suppressed_warning()`, walks an RCU-
protected list of active suppressions, matching by current task. The
suppression state is dynamically allocated via kunit_kzalloc() and
tied to the KUnit test lifecycle via kunit_add_action(), ensuring
automatic cleanup at test exit.
To minimize runtime impact when no suppressions are active, an atomic
counter tracks the number of active suppressions.
`__kunit_is_suppressed_warning()` checks this counter first and returns
immediately when it is zero, avoiding the RCU-protected list traversal
in the common case.
This series is based on the RFC patch and subsequent discussion at
https://patchwork.kernel.org/project/linux-kselftest/patch/02546e59-1afe-4b08-ba81-d94f3b691c9a@moroto.mountain/
and offers a more comprehensive solution of the problem discussed there.
[1] https://lore.kernel.org/all/CAGegRW76X8Fk_5qqOBw_aqBwAkQTsc8kXKHEuu9ECeXzdJwMSw@mail.gmail.com/
Changes since RFC:
- Introduced CONFIG_KUNIT_SUPPRESS_BACKTRACE
- Minor cleanups and bug fixes
- Added support for all affected architectures
- Added support for counting suppressed warnings
- Added unit tests using those counters
- Added patch to suppress warning backtraces in dev_addr_lists tests
Changes since v1:
- Rebased to v6.9-rc1
- Added Tested-by:, Acked-by:, and Reviewed-by: tags
[I retained those tags since there have been no functional changes]
- Introduced KUNIT_SUPPRESS_BACKTRACE configuration option, enabled by
default.
Changes since v2:
- Rebased to v6.9-rc2
- Added comments to drm warning suppression explaining why it is needed.
- Added patch to move conditional code in arch/sh/include/asm/bug.h
to avoid kerneldoc warning
- Added architecture maintainers to Cc: for architecture specific patches
- No functional changes
Changes since v3:
- Rebased to v6.14-rc6
- Dropped net: "kunit: Suppress lock warning noise at end of dev_addr_lists tests"
since 3db3b62955cd6d73afde05a17d7e8e106695c3b9
- Added __kunit_ and KUNIT_ prefixes.
- Tested on interessed architectures.
Changes since v4:
- Rebased to v6.15-rc7
- Dropped all code in __report_bug()
- Moved all checks in WARN*() macros.
- Dropped all architecture specific code.
- Made __kunit_is_suppressed_warning nice to noinstr functions.
Changes since v5:
- Rebased to v7.0-rc3
- Added RCU protection for the suppressed warnings list.
- Added static key and branching optimization.
- Removed custom `strcmp` implementation and reworked
__kunit_is_suppressed_warning() entrypoint function.
Changes since v6:
- Moved suppression checks from WARN*() macros to warn_slowpath_fmt()
and __report_bug().
- Replaced stack-allocated suppression struct with kunit_kzalloc() heap
allocation tied to the KUnit test lifecycle.
- Changed suppression strategy from function-name matching to task-scoped:
all warnings on the current task are suppressed between START and END,
rather than only warnings originating from a specific named function.
- Simplified macro API: removed KUNIT_DECLARE_SUPPRESSED_WARNING(),
the START macro now takes (test) and handles allocation internally.
- Removed static key and branching optiomization, as by the time it
was executed, callers are already in warn slowpaths.
- Link to v6: https://lore.kernel.org/r/20260317-kunit_add_support-v6-0-dd22aeb3fe5d@redhat.com
Alessandro Carminati (2):
bug/kunit: Core support for suppressing warning backtraces
bug/kunit: Suppressing warning backtraces reduced impact on WARN*()
sites
Guenter Roeck (3):
Add unit tests to verify that warning backtrace suppression works.
drm: Suppress intentional warning backtraces in scaling unit tests
kunit: Add documentation for warning backtrace suppression API
Documentation/dev-tools/kunit/usage.rst | 30 ++++++-
drivers/gpu/drm/tests/drm_rect_test.c | 16 ++++
include/asm-generic/bug.h | 48 +++++++----
include/kunit/bug.h | 62 ++++++++++++++
include/kunit/test.h | 1 +
lib/kunit/Kconfig | 9 ++
lib/kunit/Makefile | 9 +-
lib/kunit/backtrace-suppression-test.c | 105 ++++++++++++++++++++++++
lib/kunit/bug.c | 54 ++++++++++++
9 files changed, 316 insertions(+), 18 deletions(-)
create mode 100644 include/kunit/bug.h
create mode 100644 lib/kunit/backtrace-suppression-test.c
create mode 100644 lib/kunit/bug.c
--
2.34.1
---
Alessandro Carminati (2):
bug/kunit: Core support for suppressing warning backtraces
bug/kunit: Reduce runtime impact of warning backtrace suppression
Guenter Roeck (3):
kunit: Add backtrace suppression self-tests
drm: Suppress intentional warning backtraces in scaling unit tests
kunit: Add documentation for warning backtrace suppression API
Documentation/dev-tools/kunit/usage.rst | 30 ++++++++++-
drivers/gpu/drm/tests/drm_rect_test.c | 14 +++++
include/kunit/bug.h | 56 ++++++++++++++++++++
include/kunit/test.h | 1 +
kernel/panic.c | 8 ++-
lib/bug.c | 8 +++
lib/kunit/Kconfig | 9 ++++
lib/kunit/Makefile | 9 +++-
lib/kunit/backtrace-suppression-test.c | 90 ++++++++++++++++++++++++++++++++
lib/kunit/bug.c | 91 +++++++++++++++++++++++++++++++++
10 files changed, 312 insertions(+), 4 deletions(-)
---
base-commit: 80234b5ab240f52fa45d201e899e207b9265ef91
change-id: 20260312-kunit_add_support-2f35806b19dd
Best regards,
--
Albert Esteve <aesteve@redhat.com>
^ permalink raw reply
* Re: [PATCH v7 3/4] KVM: arm64: PMU: Introduce FIXED_COUNTERS_ONLY
From: Akihiko Odaki @ 2026-04-20 12:07 UTC (permalink / raw)
To: Marc Zyngier
Cc: Oliver Upton, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Catalin Marinas, Will Deacon, Kees Cook, Gustavo A. R. Silva,
Paolo Bonzini, Jonathan Corbet, Shuah Khan, linux-arm-kernel,
kvmarm, linux-kernel, linux-hardening, devel, kvm, linux-doc,
linux-kselftest
In-Reply-To: <86qzoa0xj6.wl-maz@kernel.org>
On 2026/04/20 18:51, Marc Zyngier wrote:
> On Mon, 20 Apr 2026 09:36:16 +0100,
> Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>>
>> On 2026/04/20 2:19, Marc Zyngier wrote:
>>> On Sat, 18 Apr 2026 09:14:25 +0100,
>>> Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>>>>
>>>> On a heterogeneous arm64 system, KVM's PMU emulation is based on the
>>>> features of a single host PMU instance. When a vCPU is migrated to a
>>>> pCPU with an incompatible PMU, counters such as PMCCNTR_EL0 stop
>>>> incrementing.
>>>>
>>>> Although this behavior is permitted by the architecture, Windows does
>>>> not handle it gracefully and may crash with a division-by-zero error.
>>>>
>>>> The current workaround requires VMMs to pin vCPUs to a set of pCPUs
>>>> that share a compatible PMU. This is difficult to implement correctly in
>>>> QEMU/libvirt, where pinning occurs after vCPU initialization, and it
>>>> also restricts the guest to a subset of available pCPUs.
>>>>
>>>> Introduce the KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY attribute to
>>>> create a "fixed-counters-only" PMU. When set, KVM exposes a PMU that is
>>>> compatible with all pCPUs but that does not support programmable
>>>> event counters which may have different feature sets on different PMUs.
>>>>
>>>> This allows Windows guests to run reliably on heterogeneous systems
>>>> without crashing, even without vCPU pinning, and enables VMMs to
>>>> schedule vCPUs across all available pCPUs, making full use of the host
>>>> hardware.
>>>>
>>>> Much like KVM_ARM_VCPU_PMU_V3_IRQ and other read-write attributes, this
>>>> attribute provides a getter that facilitates kernel and userspace
>>>> debugging/testing.
>>>
>>> OK, so that's the sales pitch. But how is it implemented? I would like
>>> to be able to read a high-level description of the implementation
>>> trade-offs.
>>
>> Implementation-wise it is very trivial. Essentially the following
>> addition in kvm_arm_pmu_v3_get_attr() is the entire implementation:
>> + case KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY:
>> + if (test_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY,
>> &vcpu->kvm->arch.flags))
>> + return 0;
>>
>> Both its functionality and code complexity is trivial. So we can argue that:
>> - the functionality is too trivial to be useful or
>> - the interface/implementation complexity is so trivial that it does not
>> incur maintenance burden
>>
>> In this case the selftest uses the getter so I was more inclined to
>> have it, but adding one just for the selftest sounds too ad-hoc, so
>> here I looked into other attributes to ensure that it was not
>> introducing inconsistency with existing interfaces.
>>
>> As the result, I found there are other read-write attributes; in fact
>> there are more read-write attributes than write-only ones.
>
> You're completely missing the point. I'm referring to the whole of the
> commit message, which is more of a marketing slide than a technical
> description.
In terms of implementation, the obvious tradeoff is that it adds more
code to implement the feature. One thing to note is that
kvm_vcpu_load_pmu() is added and is called each time a vCPU migrates
across pCPUs. The heavy part, making the KVM_REQ_RELOAD_PMU request,
only happens when the feature is enabled.
>
> I really don't care about the getter at this stage, which while
> pointless, does not make things more awful than they already are.
>
>>
>>>
>>>>
>>>> Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
>>>> ---
>>>> Documentation/virt/kvm/devices/vcpu.rst | 29 ++++++
>>>> arch/arm64/include/asm/kvm_host.h | 2 +
>>>> arch/arm64/include/uapi/asm/kvm.h | 1 +
>>>> arch/arm64/kvm/arm.c | 1 +
>>>> arch/arm64/kvm/pmu-emul.c | 155 +++++++++++++++++++++++---------
>>>> include/kvm/arm_pmu.h | 2 +
>>>> 6 files changed, 147 insertions(+), 43 deletions(-)
>>>>
>>>> diff --git a/Documentation/virt/kvm/devices/vcpu.rst b/Documentation/virt/kvm/devices/vcpu.rst
>>>> index 60bf205cb373..e0aeb1897d77 100644
>>>> --- a/Documentation/virt/kvm/devices/vcpu.rst
>>>> +++ b/Documentation/virt/kvm/devices/vcpu.rst
>>>> @@ -161,6 +161,35 @@ explicitly selected, or the number of counters is out of range for the
>>>> selected PMU. Selecting a new PMU cancels the effect of setting this
>>>> attribute.
>>>> +1.6 ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY
>>>> +------------------------------------------------------
>>>> +
>>>> +:Parameters: no additional parameter in kvm_device_attr.addr
>>>> +
>>>> +:Returns:
>>>> +
>>>> + ======= =====================================================
>>>> + -EBUSY Attempted to set after initializing PMUv3 or running
>>>> + VCPU, or attempted to set for the first time after
>>>> + setting an event filter
>>>> + -ENXIO Attempted to get before setting
>>>> + -ENODEV Attempted to set while PMUv3 not supported
>>>> + ======= =====================================================
>>>> +
>>>> +If set, PMUv3 will be emulated without programmable event counters. The VCPU
>>>> +will use any compatible hardware PMU. This attribute is particularly useful on
>>>
>>> Not quite "any PMU". It will use *the* PMU of the physical CPU,
>>> irrespective of the implementation.
>>
>> I think:
>>
>> - this comment
>> - one on the KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED note
>> - one on kvm_pmu_create_perf_event()
>> - and one on kvm_arm_pmu_v3_set_pmu_fixed_counters_only()
>>
>> All boil down into one question: will it support all possible CPUs, or
>> will it support a subset? Let me answer here:
>>
>> This patch is written to support a subset instead of all possible
>> CPUs. If a pCPU does not have a compatible PMU, the pCPU will not be
>> supported and cause KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED.
>
> This is not a thing. Either *all* the CPUs have a PMU that can be used
> for KVM, or PMU support is not offered to guests. That's a hard line
> in the sand. And the code already upholds this by checking the
> sanitised PMUVer field.
>
>>
>> This patch does not enforce all possible CPUs are covered by the
>> compatible PMUs. Theoretically speaking,
>> kvm_arm_pmu_get_pmuver_limit() enables the PMU emulation when real
>> PMUv3 hardware covers all possible CPUs *or* the relevant registers
>> can be trapped with IMPDEF, so some pCPU may not have a compatible PMU
>> and only provide the IMPDEF trapping.
>
> How is that possible? Please describe the case where that can happen,
> and I will make sure that such a system stops booting. The intent is
> definitely that that:
>
> - for early CPUs, we take the minimal capability of all CPUs
>
> - for late CPUs, either they match at least the capability recorded by
> early CPUs, or they don't boot.
All CPUs may trap the relevant registers with IMPDEF but some of them
may not have compatible PMUs. As I wrote in the previous email, I don't
think it will happen in practice.
>
>> Practically, I don't think any sane configuration will ever have such
>> a subset support, so we can explicitly enforce all possible CPUs are
>> covered by the compatible PMUs if desired.
>
> That's not just desired. This is a requirement. And it is already
> enforced AFAICS.
>
>>
>>>
>>>> +heterogeneous systems where different hardware PMUs cover different physical
>>>> +CPUs. The compatibility of hardware PMUs can be checked with
>>>> +KVM_ARM_VCPU_PMU_V3_SET_PMU. All VCPUs in a VM share this attribute. It isn't
>>>> +possible to set it for the first time if a PMU event filter is already present.
>>>
>>> "for the first time" gives the impression that it will work if you try
>>> again. I'd rather we say that "This feature is incompatible with the
>>> existence of a PMU event filter".
>>
>> The following sequence will work:
>> 1. Set KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY
>> 2. Set KVM_ARM_VCPU_PMU_V3_FILTER
>> 3. Set KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY
>>
>> This is to make the behavior conistent with KVM_ARM_VCPU_PMU_V3_SET_PMU.
>
> I don't think this is correct. Filtering is completely at odds with
> this patch, and I don't want to have to reason about the combination.
kvm_arm_pmu_v3_set_pmu() has the following condition:
if (kvm_vm_has_ran_once(kvm) ||
(kvm->arch.pmu_filter && kvm->arch.arm_pmu != arm_pmu)) {
ret = -EBUSY;
break;
}
kvm_arm_pmu_v3_set_pmu_fixed_counters_only() has the corresponding
condition for consistency:
if (kvm_vm_has_ran_once(kvm) ||
(kvm->arch.pmu_filter &&
!test_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY,
&kvm->arch.flags)))
return -EBUSY;
We can of course kill the PMU event filter for FIXED_COUNTERS_ONLY. The
filter is effectively no-op with FIXED_COUNTERS_ONLY and I don't think
that consistency matters much.
>
> [...]
>
>>>> + int i;
>>>> +
>>>> + for_each_set_bit(i, &mask, 32) {
>>>> + pmc = kvm_vcpu_idx_to_pmc(vcpu, i);
>>>> + if (!pmc->perf_event)
>>>> + continue;
>>>> +
>>>> + cpu_pmu = to_arm_pmu(pmc->perf_event->pmu);
>>>> + if (!cpumask_test_cpu(vcpu->cpu, &cpu_pmu->supported_cpus)) {
>>>> + kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
>>>> + break;
>>>> + }
>>>> + }
>>>> +}
>>>> +
>>>
>>> Why do we need to inflict this on VMs that do not have the fixed
>>> counter restriction?
>>
>> This function is to re-create the perf_event in case the current
>> perf_event does not support the pCPU because e.g., the pCPU is a
>> E-core while the perf_event only covers the P-cores.
>
> That's not what I meant. This code is only here to support the
> fixed-function feature. It makes no sense outside of it, because *we
> don't support counter migration across implementations*.
>
> So what's the purpose of this stuff for the normal KVM setup?
None. It's only for this feature. We can add a check of the feature flag
at the beginning of the function to avoid that loop.
>
>>
>>>
>>> And even then, all you have to reconfigure is the cycle counter. So
>>> why the loop? All we want to find out is whether the cycle counter is
>>> instantiated on the PMU that matches the current CPU.
>>
>> I just wanted to avoid hardcoding assumptions on the fixed
>> counter(s). FEAT_PMUv3_ICNTR will be naturaly handled with a loop, for
>> example.
>
> Well, not that loop, since ICNTR is counter 32. So please let's stop
> the nonsense and only add what is required?
>
> [...]
>
>>>> +
>>>> clear_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY,
>>>> &kvm->arch.flags);
>>>
>>> Why does this need to be cleared? I'd rather we make sure it is never
>>> set the first place.
>>
>> KVM_ARM_VCPU_PMU_V3_SET_PMU and
>> KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY can be set on the same
>> VCPU. The last KVM_ARM_VCPU_PMU_V3_SET_PMU or
>> KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY setting will be effective.
>>
>> A VMM may try set these attributes to check if the setting is
>> supported. For example, the RFC QEMU patch first uses
>> KVM_ARM_VCPU_PMU_V3_SET_PMU to find a compatible PMU that covers all
>> pCPUs, and then falls back to
>> KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY. The order of such probing is
>> up to the VMM.
>
> KVM_ARM_VCPU_PMU_V3_SET_PMU is not a probing mechanism. You must probe
> the PMUs by looking in /sys/bus/event_source/devices/, like kvmtool
> does.
>
> So there is no reason to support this stuff, and the two flags should
> be made mutually exclusive.
Thanks for the pointer. I'll make a change to make the flags mutually
exclusive and test it with an amended QEMU patch that follows what
kvmtool does.
>
> [...]
>
>>>>
>>>
>>> In conclusion, I find this patch to be rather messy. For a start, it
>>> needs to be split in at least 5 patches:
>>>
>>> - at least two for the refactoring
>>> - one for the PMU core changes
>>> - one for the UAPI
>>> - one for documentation
>>
>> That clarifies the expected granurarity of patches. The next version
>> will be in that layout, perhaps with more patches if an additional
>> change. Thanks for the guidance.
>>
>>>
>>> I'd also like some clarification on how this is intended to work if we
>>> enable FEAT_PMUv3_ICNTR, because the definition seems to be designed
>>> to encompass all fixed-function counters, and I expect this to grow
>>> over time.
>>
>> Indeed the UAPI was designed to encompass all fixed-function counters
>> as suggested by Oliver.
>>
>> To support the UAPI, the implementation avoids hardcoding the
>> assumption on the fixed counter(s). FEAT_PMUv3_INCTR will be naturaly
>> supported once the common code is properly updated (i.e., the size of
>> the event counter bitmask is grown the corresponding registers are
>> wired up with a proper check of the feature.)
>>
>> I expect migration will be handled with the conventional register
>> getters and setters, but please share if you have a concern.
>
> At the very least I want to see some documentation explaining that.
What kind of documentation do you expect? If we change
kvm_vcpu_load_pmu() to avoid for_each_set_bit(), there would be a good
chance to forget updating it when mechanically updating existing
for_each_set_bit() instances, so it is a candidate for documentation.
But I don't have a good idea where to place it either.
Regards,
Akihiko Odaki
^ permalink raw reply
* Re: [PATCH v3] docs/zh_CN: add module-signing Chinese translation
From: Dongliang Mu @ 2026-04-20 12:03 UTC (permalink / raw)
To: Yan Zhu; +Cc: alexs, seakeel, si.yanteng, corbet, skhan, linux-doc,
linux-kernel
In-Reply-To: <tencent_91B9F750970BCBFEAC86BBACA3DF31480407@qq.com>
On 4/18/26 10:15 PM, Yan Zhu wrote:
> Hi Dongliang,
>
> On 4/18/2026 2:20 PM, Dongliang Mu wrote:
>>
>> On 4/18/26 12:45 PM, Yan Zhu wrote:
>>> Translate .../admin-guide/module-signing.rst into Chinese.
>>>
>>> Update the translation through commit 0ad9a71933e7
>>> ("modsign: Enable ML-DSA module signing")
>>>
>>> Signed-off-by: Yan Zhu <zhuyan2015@qq.com>
>>> ---
>>
>> Hi Yan,
>>
>> Please remember to add your changelog under the "---". For example,
>> v1- >v2: XXX
>>
>
> I replied to the email according to the guidance of how-to.rst in the
> Chinese thanslation. There was no special explanation there, so I
> thought that the Chinese translation did not need the explanation of
> version change. I think I should resend a patch to fill in this
> description.
https://lore.kernel.org/all/20260420115647.2718959-1-dzm91@hust.edu.cn/
I sent a new patch to explain how to deal with changelog.
Dongliang Mu
>
>> And I wonder where the v2 patch is as I don't find it in my mbox. Do
>> I miss something?
>
> There may be something wrong with the mailbox. I see that you are in
> the copy list for the v2 patch. The link is
> https://lore.kernel.org/lkml/tencent_0101EEFDDBC5D532222BFE0EF2487DCC0805@qq.com
>
>> Dongliang Mu
>>
>>> .../zh_CN/admin-guide/module-signing.rst | 249 ++++++++++++++++++
>>> 1 file changed, 249 insertions(+)
>>> create mode 100644 Documentation/translations/zh_CN/admin-guide/
>>> module-signing.rst
>>>
>>> diff --git a/Documentation/translations/zh_CN/admin-guide/module-
>>> signing.rst b/Documentation/translations/zh_CN/admin-guide/module-
>>> signing.rst
>>> new file mode 100644
>>> index 000000000000..04b0f1cbafd5
>>> --- /dev/null
>>> +++ b/Documentation/translations/zh_CN/admin-guide/module-signing.rst
>>> @@ -0,0 +1,249 @@
>>> +.. SPDX-License-Identifier: GPL-2.0
>>> +.. include:: ../disclaimer-zh_CN.rst
>>> +
>>> +:Original: Documentation/admin-guide/module-signing.rst
>>> +:翻译:
>>> + 朱岩 Yan Zhu <zhuyan2015@qq.com>
>>> +
>>> +
>>> +==========================
>>> +内核模块签名机制
>>> +==========================
>>> +
>>> +.. 目录
>>> +..
>>> +.. - 概述
>>> +.. - 配置模块签名
>>> +.. - 生成签名密钥
>>> +.. - 内核中的公钥
>>> +.. - 模块手动签名
>>> +.. - 已签名模块和剥离
>>> +.. - 加载已签名模块
>>> +.. - 无效签名和未签名模块
>>> +.. - 管理/保护私钥
>>> +
>>> +
>>> +概述
>>> +====
>>> +
>>> +内核模块签名机制在安装过程中对模块进行加密签名,然后在加载模块时检查
>>> 签名。这
>>> +通过禁止加载未签名的模块或使用无效密钥签名的模块来提高内核安全性。模
>>> 块签名通
>>> +过使恶意模块更难加载到内核中来增加安全性。模块签名检查在内核中完成,
>>> 因此不需
>>> +要受信任的用户空间位。
>>> +
>>> +此机制使用 X.509 ITU-T 标准证书对涉及的公钥进行编码。签名本身不以任何
>>> 工业标准
>>> +类型编码。内置机制目前仅支持 RSA、NIST P-384 ECDSA 和 NIST FIPS-204
>>> ML-DSA
>>> +公钥签名标准(尽管它是可插拔的并允许使用其他标准)。对于 RSA 和
>>> ECDSA,可以使
>>> +用的可能的哈希算法是大小为 256、384 和 512 的 SHA-2 和 SHA-3(算法由
>>> 签名中的
>>> +数据选择);ML-DSA会自行进行哈希运算,但允许与SHA512哈希算法结合用于
>>> 签名属性。
>>> +
>>> +配置模块签名
>>> +============
>>> +
>>> +通过进入内核配置的 :menuselection:`Enable Loadable Module Support` 菜
>>> 单并打
>>> +开以下选项来启用模块签名机制::
>>> +
>>> + CONFIG_MODULE_SIG "Module signature verification"
>>> +
>>> +这有多个可用选项:
>>> +
>>> + (1) :menuselection:`Require modules to be validly signed`
>>> + (``CONFIG_MODULE_SIG_FORCE``)
>>> +
>>> + 这指定了内核应如何处理其密钥未知或未签名的模块。
>>> +
>>> + 如果关闭(即"宽松模式"),则允许使用不可用密钥和未签名的模块,但
>>> 内核将被
>>> + 标记为受污染,并且相关模块将被标记为受污染,显示字符'E'。
>>> +
>>> + 如果打开(即"限制模式"),只有具有有效签名且可由内核拥有的公钥验
>>> 证的模块
>>> + 才会被加载。所有其他模块将生成错误。
>>> +
>>> + 无论此处的设置如何,如果模块的签名块无法解析,它将被直接拒绝。
>>> +
>>> +
>>> + (2) :menuselection:`Automatically sign all modules`
>>> + (``CONFIG_MODULE_SIG_ALL``)
>>> +
>>> + 如果打开此选项,则在构建的 modules_install
>>> 阶段期间将自动签名模块。
>>> + 如果关闭,则必须使用以下命令手动签名模块::
>>> +
>>> + scripts/sign-file
>>> +
>>> +
>>> + (3) :menuselection:`Which hash algorithm should modules be signed
>>> with?`
>>> +
>>> + 这提供了安装阶段将用于签名模块的哈希算法选择:
>>> +
>>> + ===============================
>>> ==========================================
>>> + ``CONFIG_MODULE_SIG_SHA256`` :menuselection:`Sign modules
>>> with SHA-256`
>>> + ``CONFIG_MODULE_SIG_SHA384`` :menuselection:`Sign modules
>>> with SHA-384`
>>> + ``CONFIG_MODULE_SIG_SHA512`` :menuselection:`Sign modules
>>> with SHA-512`
>>> + ``CONFIG_MODULE_SIG_SHA3_256`` :menuselection:`Sign modules
>>> with SHA3-256`
>>> + ``CONFIG_MODULE_SIG_SHA3_384`` :menuselection:`Sign modules
>>> with SHA3-384`
>>> + ``CONFIG_MODULE_SIG_SHA3_512`` :menuselection:`Sign modules
>>> with SHA3-512`
>>> + ===============================
>>> ==========================================
>>> +
>>> + 此处选择的算法也将被构建到内核中(而不是作为模块),以便使用该算
>>> 法签名的
>>> + 模块可以在不导致循环依赖的情况下检查其签名。
>>> +
>>> +
>>> + (4) :menuselection:`File name or PKCS#11 URI of module signing key`
>>> + (``CONFIG_MODULE_SIG_KEY``)
>>> +
>>> + 将此选项设置为除默认值 ``certs/signing_key.pem`` 之外的其他值将
>>> 禁用签名
>>> + 密钥的自动生成,并允许使用您选择的密钥对内核模块进行签名。提供的
>>> 字符串应
>>> + 标识包含私钥及其对应的 PEM 格式 X.509 证书的文件,或者在 OpenSSL
>>> + ENGINE_pkcs11 功能正常的系统上,使用 RFC7512 定义的 PKCS#11
>>> URI。在后一
>>> + 种情况下,PKCS#11 URI 应引用证书和私钥。
>>> +
>>> + 如果包含私钥的 PEM 文件已加密,或者 PKCS#11 令牌需要 PIN,可以通过
>>>
>>> + ``KBUILD_SIGN_PIN`` 变量在构建时提供。
>>> +
>>> +
>>> + (5) :menuselection:`Additional X.509 keys for default system keyring`
>>> + (``CONFIG_SYSTEM_TRUSTED_KEYS``)
>>> +
>>> + 此选项可设置为包含附加证书的 PEM 编码文件的文件名,这些证书将默
>>> 认包含在
>>> + 系统密钥环中。
>>> +
>>> +请注意,启用模块签名会为内核构建过程添加对执行签名工具的OpenSSL开发包
>>> 的依赖。
>>> +
>>> +
>>> +生成签名密钥
>>> +============
>>> +
>>> +生成和检查签名需要加密密钥对。私钥用于生成签名,相应的公钥用于检查签
>>> 名。私钥
>>> +仅在构建期间需要,之后可以删除或安全存储。公钥被构建到内核中,以便在
>>> 加载模块
>>> +时可以使用它来检查签名。
>>> +
>>> +在正常情况下,当 ``CONFIG_MODULE_SIG_KEY`` 保持默认值时,如果文件中不
>>> 存在密
>>> +钥对,内核构建将使用 openssl 自动生成新的密钥对::
>>> +
>>> + certs/signing_key.pem
>>> +
>>> +在构建 vmlinux 期间(公钥需要构建到 vmlinux 中)使用参数::
>>> +
>>> + certs/x509.genkey
>>> +
>>> +文件(如果尚不存在也会生成)。
>>> +
>>> +可以在 RSA(``MODULE_SIG_KEY_TYPE_RSA``)、
>>> +ECDSA(``MODULE_SIG_KEY_TYPE_ECDSA``)和
>>> +ML-DSA(``MODULE_SIG_KEY_TYPE_MLDSA_*``)之间选择生成 RSA 4k、NIST
>>> P-384
>>> +密钥对或 ML-DSA 44、65 或 87 密钥对。
>>> +
>>> +强烈建议您提供自己的 x509.genkey 文件。
>>> +
>>> +最值得注意的是,在 x509.genkey 文件中,req_distinguished_name 部分应
>>> 从默认值
>>> +更改::
>>> +
>>> + [ req_distinguished_name ]
>>> + #O = Unspecified company
>>> + CN = Build time autogenerated kernel key
>>> + #emailAddress = unspecified.user@unspecified.company
>>> +
>>> +生成的 RSA 密钥大小也可以通过以下方式设置::
>>> +
>>> + [ req ]
>>> + default_bits = 4096
>>> +
>>> +也可以使用位于 Linux 内核源代码树根节点中的 x509.genkey 密钥生成配置
>>> 文件和
>>> +openssl 命令手动生成公钥/私钥文件。以下是生成公钥/私钥文件的示例::
>>> +
>>> + openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
>>> + -config x509.genkey -outform PEM -out kernel_key.pem \
>>> + -keyout kernel_key.pem
>>> +
>>> +然后可以将生成的 kernel_key.pem 文件的完整路径名指定在
>>> +``CONFIG_MODULE_SIG_KEY``选项中,并且将使用其中的证书和密钥而不是自动
>>> 生成的
>>> +密钥对。
>>> +
>>> +
>>> +内核中的公钥
>>> +============
>>> +
>>> +内核包含一个可由 root 查看的公钥环。它们在名为 ".builtin_trusted_keys"
>>> 的密
>>> +钥环中,可以通过以下方式查看::
>>> +
>>> + [root@deneb ~]# cat /proc/keys
>>> + ...
>>> + 223c7853 I------ 1 perm 1f030000 0 0 keyring
>>> .builtin_trusted_keys: 1
>>> + 302d2d52 I------ 1 perm 1f010000 0 0 asymmetri
>>> Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079:
>>> X509.RSA a7118079 []
>>> +
>>> +除了专门为模块签名生成的公钥外,还可以在 ``CONFIG_SYSTEM_TRUSTED_KEYS``
>>> 配置
>>> +选项引用的 PEM 编码文件中提供其他受信任的证书。
>>> +
>>> +此外,架构代码可以从硬件存储中获取公钥并将其添加(例如从 UEFI 密钥数
>>> 据库)。
>>> +
>>> +最后,可以通过以下方式添加其他公钥::
>>> +
>>> + keyctl padd asymmetric "" [.builtin_trusted_keys-ID] <[key-file]
>>> +
>>> +例如::
>>> +
>>> + keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509
>>> +
>>> +但是,请注意,内核只允许将由已驻留在 ``.builtin_trusted_keys`` 中的密
>>> 钥有效
>>> +签名的密钥添加到 ``.builtin_trusted_keys``。
>>> +
>>> +模块手动签名
>>> +============
>>> +
>>> +要手动对模块进行签名,请使用 Linux 内核源代码树中可用的 scripts/sign-
>>> file 工
>>> +具。该脚本需要 4 个参数:
>>> +
>>> + 1. 哈希算法(例如,sha256)
>>> + 2. 私钥文件名或 PKCS#11 URI
>>> + 3. 公钥文件名
>>> + 4. 要签名的内核模块
>>> +
>>> +以下是签名内核模块的示例::
>>> +
>>> + scripts/sign-file sha512 kernel-signkey.priv \
>>> + kernel-signkey.x509 module.ko
>>> +
>>> +使用的哈希算法不必与配置的算法匹配,但如果不同,应确保哈希算法要么内
>>> 置在内核
>>> +中,要么可以在不需要自身的情况下加载。
>>> +
>>> +如果私钥需要密码或 PIN,可以在 $KBUILD_SIGN_PIN 环境变量中提供。
>>> +
>>> +
>>> +已签名模块和剥离
>>> +================
>>> +
>>> +已签名模块在末尾简单地附加了数字签名。模块文件末尾的字符串
>>> +``~Module signature appended~.`` 确认签名存在,但不能确认签名有效!
>>> +
>>> +已签名模块是脆弱的,因为签名在定义的ELF容器之外。因此,一旦计算并附加
>>> 签名,就
>>> +不得剥离它们。请注意,整个模块都是签名的有效载荷,包括签名时存在的任
>>> 何和所有
>>> +调试信息。
>>> +
>>> +
>>> +加载已签名模块
>>> +==============
>>> +
>>> +模块通过 insmod、modprobe、``init_module()`` 或 ``finit_module()`` 加
>>> 载,
>>> +与未签名模块完全一样,因为在用户空间中不进行任何处理。
>>> +所有签名检查都在内核内完成。
>>> +
>>> +
>>> +无效签名和未签名模块
>>> +====================
>>> +
>>> +如果启用了 ``CONFIG_MODULE_SIG_FORCE`` 或在内核启动命令提供了
>>> +module.sig_enforce=1,内核将仅加载具有有效签名且具有公钥的模块。否
>>> 则,它还将
>>> +加载未签名的模块。任何具有不匹配签名的模块将不被允许加载。
>>> +
>>> +任何具有不可解析签名的模块将被拒绝。
>>> +
>>> +
>>> +管理/保护私钥
>>> +==============
>>> +
>>> +由于私钥用于签名模块,病毒和恶意软件可以使用私钥签名模块并危害操作系
>>> 统。私钥
>>> +必须被销毁或移动到安全位置,而不是保存在内核源代码树的根节点中。
>>> +
>>> +如果使用相同的私钥为多个内核配置签名模块,必须确保模块版本信息足以防
>>> 止将模块
>>> +加载到不同的内核中。要么设置 ``CONFIG_MODVERSIONS=y``,要么通过更改
>>> +``EXTRAVERSION`` 或 ``CONFIG_LOCALVERSION`` 确保每个配置具有不同的内
>>> 核发布字
>>> +符串。
>
^ permalink raw reply
* [PATCH] docs/zh_CN: restructure how-to.rst patch submission workflow
From: Dongliang Mu @ 2026-04-20 11:56 UTC (permalink / raw)
To: Alex Shi, Yanteng Si, Dongliang Mu, Jonathan Corbet, Shuah Khan
Cc: linux-doc, linux-kernel
Split "导出补丁和制作封面" into separate "导出补丁" and
"为补丁集制作封面" sections, and document the single-patch
(git format-patch -1) and multi-patch (-N) flows side by side
so new contributors do not have to infer one from the other.
Replace the invalid "git am --amend" invocations with "git commit
--amend" in both the checkpatch fix-up and the iteration sections.
Expand the iteration section with a worked v2 example showing where the
changelog goes relative to the --- separator, and describe how v3/v4
changelogs stack newest-on-top.
Finally, add a note reminding submitters to carry Reviewed-by tags from
reviewers into the next revision, placed below Signed-off-by.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Dongliang Mu <dzm91@hust.edu.cn>
---
Documentation/translations/zh_CN/how-to.rst | 105 ++++++++++++++------
1 file changed, 77 insertions(+), 28 deletions(-)
diff --git a/Documentation/translations/zh_CN/how-to.rst b/Documentation/translations/zh_CN/how-to.rst
index 3dcf6754d1df..9ec2384e1e76 100644
--- a/Documentation/translations/zh_CN/how-to.rst
+++ b/Documentation/translations/zh_CN/how-to.rst
@@ -269,13 +269,22 @@ Git 和邮箱配置
**请注意** 以上四行,缺少任何一行,您都将会在第一轮审阅后返工,如果您需要一个
更加明确的示例,请对 zh_CN 目录执行 git log。
-导出补丁和制作封面
-------------------
+导出补丁
+--------
+
+这个时候,可以导出补丁,做发送邮件列表最后的准备了。对于单个补丁,
+命令行执行::
+
+ git format-patch -1
+
+然后命令行会输出类似下面的内容::
+
+ 0001-docs-zh_CN-add-xxxxxxxx.patch
-这个时候,可以导出补丁,做发送邮件列表最后的准备了。命令行执行::
+如果您有多个补丁,命令行执行::
git format-patch -N
- # N 要替换为补丁数量,一般 N 大于等于 1
+ # N 要替换为补丁数量,一般 N 大于 1
然后命令行会输出类似下面的内容::
@@ -290,13 +299,12 @@ Git 和邮箱配置
./scripts/checkpatch.pl *.patch
-参考脚本输出,解决掉所有的 error 和 warning,通常情况下,只有下面这个
+参考脚本输出,解决掉所有的 error 和 warning。通常情况下,只有下面这个
warning 不需要解决::
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
-一个简单的解决方法是一次只检查一个补丁,然后打上该补丁,直接对译文进行修改,
-然后执行以下命令为补丁追加更改::
+对于单个补丁,解决方案很简单,只需要打上该补丁,直接对译文进行修改,为补丁追加后续更改::
git checkout docs-next
git checkout -b test-trans-new
@@ -304,15 +312,21 @@ warning 不需要解决::
./scripts/checkpatch.pl 0001-xxxxx.patch
# 直接修改您的翻译
git add .
- git am --amend
+ git commit --amend
# 保存退出
- git am 0002-xxxxx.patch
- ……
-重新导出再次检测,重复这个过程,直到处理完所有的补丁。
+随后,重新导出补丁再次检测,重复这个过程,直到处理完所有 warning 和
+error。
+
+如果您有多个补丁,请按补丁集中补丁顺序对每个补丁重复上述流程,一次只处理
+一个,不要一次 git am 多个补丁。全部处理完毕后再重新导出并再次测试。
-最后,如果检测时没有需要处理的 warning 和 error,或者您只有一个补丁,请
-跳过下面这个步骤,否则请重新导出补丁制作封面::
+为补丁集制作封面
+----------------
+
+对于单个补丁,请跳过本节。
+
+如果您有多个补丁,则需要为补丁集制作一份封面,即 0 号补丁::
git format-patch -N --cover-letter --thread=shallow
# N 要替换为补丁数量,一般 N 大于 1
@@ -329,18 +343,14 @@ warning 不需要解决::
vim 0000-cover-letter.patch
...
- Subject: [PATCH 0/N] *** SUBJECT HERE *** #修改该字段,概括您的补丁集都做了哪些事情
+ Subject: [PATCH 0/N] *** SUBJECT HERE *** # 修改该字段,概括您的补丁集都做了哪些事情
- *** BLURB HERE *** #修改该字段,详细描述您的补丁集做了哪些事情
+ *** BLURB HERE *** # 修改该字段,详细描述您的补丁集做了哪些事情
Yanteng Si (1):
docs/zh_CN: add xxxxx
...
-如果您只有一个补丁,则无需制作封面(即 0 号补丁),只需执行::
-
- git format-patch -1
-
把补丁提交到邮件列表
====================
@@ -392,28 +402,67 @@ reviewer 的评论,做到每条都有回复,每个回复都落实到位。
迭代补丁
--------
-建议您每回复一条评论,就修改一处翻译。然后重新生成补丁,相信您现在已经具
-备了灵活使用 git am --amend 的能力。
+建议您每回复一条评论,就修改一处翻译,然后重新生成补丁,相信您现在
+已经具备了灵活使用 git am 与 git commit --amend 的能力。
-每次迭代一个补丁,不要一次多个::
+对于单个补丁,每回复完评论后修改、追加::
- git am <您要修改的补丁>
+ git am 0001-xxxxx.patch
# 直接对文件进行您的修改
git add .
git commit --amend
-当您将所有的评论落实到位后,导出第二版补丁,并修改封面::
+当您将所有的评论落实到位后,导出第二版补丁::
- git format-patch -N -v 2 --cover-letter --thread=shallow
+ git format-patch -1 -v 2
+
+命令行会输出 v2-0001-xxxxx.patch。打开该文件,在 --- 分割线下方追加
+changelog。注意,分割线以下的内容不会进入 git 提交历史,仅作为邮件中的
+说明供 reviewer 检查::
+
+ Subject: [PATCH v2] docs/zh_CN: add xxxxxx translation
+
+ Translate .../xxx.rst into Chinese.
+
+ Signed-off-by: Yanteng Si <si.yanteng@linux.dev>
+ ---
+ v1->v2:
+ - 修正第二节的错别字,Reviewer-A 提出的意见
+ - 根据 Reviewer-B 的建议调整段落顺序
-打开 0 号补丁,在 BLURB HERE 处编写相较于上个版本,您做了哪些改动。
+ Documentation/translations/zh_CN/xxx.rst | 100 ++++++
+ 1 file changed, 100 insertions(+)
-然后执行::
+后续迭代 v3、v4 …… 时,新的 changelog 放在最上面,旧的保留在下方,按
+从新到旧的顺序叠加。例如 v3 补丁的 --- 下方::
- git send-email v2* --to <maintainer email addr> --cc <others addr>
+ ---
+ v2->v3:
+ - ...本次相较 v2 的改动...
+ v1->v2:
+ - ...上一次相较 v1 的改动...
+
+然后发送::
+
+ git send-email v2-0001-*.patch --to <maintainer email addr> --cc <others addr>
+
+如果您有多个补丁,迭代时请按以下原则:每次只迭代一个补丁,不要一次多个,
+每个补丁独立重复上述流程。所有评论落实到位后,导出 v2 时附带封面::
+
+ git format-patch -N -v 2 --cover-letter --thread=shallow
+
+打开 0 号补丁,在 BLURB HERE 处写明整组补丁相较 v1 的总体改动,格式
+同上面的单个补丁 changelog 示例。如果某个补丁需要单独说明,可在该
+补丁文件的 --- 分割线下方追加单个补丁的 changelog。最后执行::
+
+ git send-email v2-*.patch --to <maintainer email addr> --cc <others addr>
这样,新的一版补丁就又发送到邮件列表等待审阅,之后就是重复这个过程。
+此外,如果审阅者或维护者在邮件回复中给出了 Reviewed-by tag,请在下
+一版补丁的 commit 信息中加入该 tag,放在 Signed-off-by 行的下方,以
+便维护者合入时保留您的审阅记录。
+
审阅周期
--------
--
2.43.0
^ permalink raw reply related
* [PATCH] docs: maintainer-netdev: fix typo in "targeting"
From: Ariful Islam Shoikot @ 2026-04-20 11:45 UTC (permalink / raw)
To: netdev; +Cc: linux-doc, workflows, linux-kernel, Ariful Islam Shoikot
Fix spelling mistake "targgeting" -> "targeting" in
maintainer-netdev.rst
No functional change.
Signed-off-by: Ariful Islam Shoikot <islamarifulshoikat@gmail.com>
---
Documentation/process/maintainer-netdev.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/process/maintainer-netdev.rst b/Documentation/process/maintainer-netdev.rst
index bda93b459a05..ec7b9aa2877f 100644
--- a/Documentation/process/maintainer-netdev.rst
+++ b/Documentation/process/maintainer-netdev.rst
@@ -528,7 +528,7 @@ The exact rules a driver must follow to acquire the ``Supported`` status:
status will be withdrawn.
5. Test failures due to bugs either in the driver or the test itself,
- or lack of support for the feature the test is targgeting are
+ or lack of support for the feature the test is targeting are
*not* a basis for losing the ``Supported`` status.
netdev CI will maintain an official page of supported devices, listing their
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] docs: Add overview and SLUB allocator sections to slab documentation
From: Nick Huang @ 2026-04-20 10:43 UTC (permalink / raw)
To: Jonathan Corbet
Cc: Lorenzo Stoakes, David Hildenbrand (Arm), Matthew Wilcox,
Vlastimil Babka, Harry Yoo, Andrew Morton, Hao Li,
Christoph Lameter, David Rientjes, Roman Gushchin,
Liam R . Howlett, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Shuah Khan, linux-mm, linux-doc, linux-kernel
In-Reply-To: <87jyu2w2rs.fsf@trenco.lwn.net>
Jonathan Corbet <corbet@lwn.net> 於 2026年4月20日週一 下午2:43寫道:
>
> Nick Huang <sef1548@gmail.com> writes:
>
> > I am really sorry for causing trouble for everyone. I would like to
> > ask which aspect of mine was disrespectful, so that I can be more
> > careful next time.
> >
> > If I want to make this kind of change, should I send an [RFC patch] to
> > ask for everyone's opinion?
>
> If you want to be respectful, start by reading what has been sent to
> you; the problems with your submission were well explained, more than
> once.
>
> To reiterate:
>
> - Do not send LLM-generated material without marking it as such as
> described in our developer documentation.
>
> - Do not attempt to document systems that you do not, yourself,
> understand; you have no hope of getting it right, and you will only
> succeed in wasting the time of the people who have to review your
> changes.
>
> The point of documentation is to be informative, accurate, and useful;
> simply filling in a bunch of words is not helpful to anybody.
>
> Thanks,
>
> jon
Thank you for your feedback.
--
Regards,
Nick Huang
^ permalink raw reply
* Re: [PATCH] docs: Add overview and SLUB allocator sections to slab documentation
From: Nick Huang @ 2026-04-20 10:41 UTC (permalink / raw)
To: Mike Rapoport
Cc: Lorenzo Stoakes, David Hildenbrand (Arm), Matthew Wilcox,
Vlastimil Babka, Harry Yoo, Andrew Morton, Jonathan Corbet,
Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Liam R . Howlett, Suren Baghdasaryan, Michal Hocko, Shuah Khan,
linux-mm, linux-doc, linux-kernel
In-Reply-To: <aeXK4tjGFUgKDf5-@kernel.org>
Mike Rapoport <rppt@kernel.org> 於 2026年4月20日週一 下午2:42寫道:
>
> Hi Nick,
>
> On Mon, Apr 20, 2026 at 12:52:25PM +0800, Nick Huang wrote:
> >
> > I am really sorry for causing trouble for everyone. I would like to
> > ask which aspect of mine was disrespectful, so that I can be more
> > careful next time.
>
> Maintainers time is valuable and sending LLM generated patch completely
> without understanding what it is about is disrespect for maintainers wasted
> time.
>
> > If I want to make this kind of change, should I send an [RFC patch] to
> > ask for everyone's opinion?
>
> If you want to make that kind of change, you should start with researching
> and understanding yourself what the code is doing, double check the LLM
> output and verify it and not just take an LLM slop and send it.
>
> > Sorry, I really am not very clear about the process.
>
> Start with reading kernel process documentation:
> https://docs.kernel.org/process/development-process.html
>
> > --
> > Regards,
> > Nick Huang
>
> --
> Sincerely yours,
> Mike.
Thank you for your suggestion. I will read the kernel process
documentation carefully.
--
Regards,
Nick Huang
^ permalink raw reply
* Re: [PATCH v7 3/4] KVM: arm64: PMU: Introduce FIXED_COUNTERS_ONLY
From: Marc Zyngier @ 2026-04-20 9:51 UTC (permalink / raw)
To: Akihiko Odaki
Cc: Oliver Upton, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Catalin Marinas, Will Deacon, Kees Cook, Gustavo A. R. Silva,
Paolo Bonzini, Jonathan Corbet, Shuah Khan, linux-arm-kernel,
kvmarm, linux-kernel, linux-hardening, devel, kvm, linux-doc,
linux-kselftest
In-Reply-To: <06c6664c-7f0c-47b2-babf-ba2a541fd9f2@rsg.ci.i.u-tokyo.ac.jp>
On Mon, 20 Apr 2026 09:36:16 +0100,
Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>
> On 2026/04/20 2:19, Marc Zyngier wrote:
> > On Sat, 18 Apr 2026 09:14:25 +0100,
> > Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
> >>
> >> On a heterogeneous arm64 system, KVM's PMU emulation is based on the
> >> features of a single host PMU instance. When a vCPU is migrated to a
> >> pCPU with an incompatible PMU, counters such as PMCCNTR_EL0 stop
> >> incrementing.
> >>
> >> Although this behavior is permitted by the architecture, Windows does
> >> not handle it gracefully and may crash with a division-by-zero error.
> >>
> >> The current workaround requires VMMs to pin vCPUs to a set of pCPUs
> >> that share a compatible PMU. This is difficult to implement correctly in
> >> QEMU/libvirt, where pinning occurs after vCPU initialization, and it
> >> also restricts the guest to a subset of available pCPUs.
> >>
> >> Introduce the KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY attribute to
> >> create a "fixed-counters-only" PMU. When set, KVM exposes a PMU that is
> >> compatible with all pCPUs but that does not support programmable
> >> event counters which may have different feature sets on different PMUs.
> >>
> >> This allows Windows guests to run reliably on heterogeneous systems
> >> without crashing, even without vCPU pinning, and enables VMMs to
> >> schedule vCPUs across all available pCPUs, making full use of the host
> >> hardware.
> >>
> >> Much like KVM_ARM_VCPU_PMU_V3_IRQ and other read-write attributes, this
> >> attribute provides a getter that facilitates kernel and userspace
> >> debugging/testing.
> >
> > OK, so that's the sales pitch. But how is it implemented? I would like
> > to be able to read a high-level description of the implementation
> > trade-offs.
>
> Implementation-wise it is very trivial. Essentially the following
> addition in kvm_arm_pmu_v3_get_attr() is the entire implementation:
> + case KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY:
> + if (test_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY,
> &vcpu->kvm->arch.flags))
> + return 0;
>
> Both its functionality and code complexity is trivial. So we can argue that:
> - the functionality is too trivial to be useful or
> - the interface/implementation complexity is so trivial that it does not
> incur maintenance burden
>
> In this case the selftest uses the getter so I was more inclined to
> have it, but adding one just for the selftest sounds too ad-hoc, so
> here I looked into other attributes to ensure that it was not
> introducing inconsistency with existing interfaces.
>
> As the result, I found there are other read-write attributes; in fact
> there are more read-write attributes than write-only ones.
You're completely missing the point. I'm referring to the whole of the
commit message, which is more of a marketing slide than a technical
description.
I really don't care about the getter at this stage, which while
pointless, does not make things more awful than they already are.
>
> >
> >>
> >> Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> >> ---
> >> Documentation/virt/kvm/devices/vcpu.rst | 29 ++++++
> >> arch/arm64/include/asm/kvm_host.h | 2 +
> >> arch/arm64/include/uapi/asm/kvm.h | 1 +
> >> arch/arm64/kvm/arm.c | 1 +
> >> arch/arm64/kvm/pmu-emul.c | 155 +++++++++++++++++++++++---------
> >> include/kvm/arm_pmu.h | 2 +
> >> 6 files changed, 147 insertions(+), 43 deletions(-)
> >>
> >> diff --git a/Documentation/virt/kvm/devices/vcpu.rst b/Documentation/virt/kvm/devices/vcpu.rst
> >> index 60bf205cb373..e0aeb1897d77 100644
> >> --- a/Documentation/virt/kvm/devices/vcpu.rst
> >> +++ b/Documentation/virt/kvm/devices/vcpu.rst
> >> @@ -161,6 +161,35 @@ explicitly selected, or the number of counters is out of range for the
> >> selected PMU. Selecting a new PMU cancels the effect of setting this
> >> attribute.
> >> +1.6 ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY
> >> +------------------------------------------------------
> >> +
> >> +:Parameters: no additional parameter in kvm_device_attr.addr
> >> +
> >> +:Returns:
> >> +
> >> + ======= =====================================================
> >> + -EBUSY Attempted to set after initializing PMUv3 or running
> >> + VCPU, or attempted to set for the first time after
> >> + setting an event filter
> >> + -ENXIO Attempted to get before setting
> >> + -ENODEV Attempted to set while PMUv3 not supported
> >> + ======= =====================================================
> >> +
> >> +If set, PMUv3 will be emulated without programmable event counters. The VCPU
> >> +will use any compatible hardware PMU. This attribute is particularly useful on
> >
> > Not quite "any PMU". It will use *the* PMU of the physical CPU,
> > irrespective of the implementation.
>
> I think:
>
> - this comment
> - one on the KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED note
> - one on kvm_pmu_create_perf_event()
> - and one on kvm_arm_pmu_v3_set_pmu_fixed_counters_only()
>
> All boil down into one question: will it support all possible CPUs, or
> will it support a subset? Let me answer here:
>
> This patch is written to support a subset instead of all possible
> CPUs. If a pCPU does not have a compatible PMU, the pCPU will not be
> supported and cause KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED.
This is not a thing. Either *all* the CPUs have a PMU that can be used
for KVM, or PMU support is not offered to guests. That's a hard line
in the sand. And the code already upholds this by checking the
sanitised PMUVer field.
>
> This patch does not enforce all possible CPUs are covered by the
> compatible PMUs. Theoretically speaking,
> kvm_arm_pmu_get_pmuver_limit() enables the PMU emulation when real
> PMUv3 hardware covers all possible CPUs *or* the relevant registers
> can be trapped with IMPDEF, so some pCPU may not have a compatible PMU
> and only provide the IMPDEF trapping.
How is that possible? Please describe the case where that can happen,
and I will make sure that such a system stops booting. The intent is
definitely that that:
- for early CPUs, we take the minimal capability of all CPUs
- for late CPUs, either they match at least the capability recorded by
early CPUs, or they don't boot.
> Practically, I don't think any sane configuration will ever have such
> a subset support, so we can explicitly enforce all possible CPUs are
> covered by the compatible PMUs if desired.
That's not just desired. This is a requirement. And it is already
enforced AFAICS.
>
> >
> >> +heterogeneous systems where different hardware PMUs cover different physical
> >> +CPUs. The compatibility of hardware PMUs can be checked with
> >> +KVM_ARM_VCPU_PMU_V3_SET_PMU. All VCPUs in a VM share this attribute. It isn't
> >> +possible to set it for the first time if a PMU event filter is already present.
> >
> > "for the first time" gives the impression that it will work if you try
> > again. I'd rather we say that "This feature is incompatible with the
> > existence of a PMU event filter".
>
> The following sequence will work:
> 1. Set KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY
> 2. Set KVM_ARM_VCPU_PMU_V3_FILTER
> 3. Set KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY
>
> This is to make the behavior conistent with KVM_ARM_VCPU_PMU_V3_SET_PMU.
I don't think this is correct. Filtering is completely at odds with
this patch, and I don't want to have to reason about the combination.
[...]
> >> + int i;
> >> +
> >> + for_each_set_bit(i, &mask, 32) {
> >> + pmc = kvm_vcpu_idx_to_pmc(vcpu, i);
> >> + if (!pmc->perf_event)
> >> + continue;
> >> +
> >> + cpu_pmu = to_arm_pmu(pmc->perf_event->pmu);
> >> + if (!cpumask_test_cpu(vcpu->cpu, &cpu_pmu->supported_cpus)) {
> >> + kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
> >> + break;
> >> + }
> >> + }
> >> +}
> >> +
> >
> > Why do we need to inflict this on VMs that do not have the fixed
> > counter restriction?
>
> This function is to re-create the perf_event in case the current
> perf_event does not support the pCPU because e.g., the pCPU is a
> E-core while the perf_event only covers the P-cores.
That's not what I meant. This code is only here to support the
fixed-function feature. It makes no sense outside of it, because *we
don't support counter migration across implementations*.
So what's the purpose of this stuff for the normal KVM setup?
>
> >
> > And even then, all you have to reconfigure is the cycle counter. So
> > why the loop? All we want to find out is whether the cycle counter is
> > instantiated on the PMU that matches the current CPU.
>
> I just wanted to avoid hardcoding assumptions on the fixed
> counter(s). FEAT_PMUv3_ICNTR will be naturaly handled with a loop, for
> example.
Well, not that loop, since ICNTR is counter 32. So please let's stop
the nonsense and only add what is required?
[...]
> >> +
> >> clear_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY,
> >> &kvm->arch.flags);
> >
> > Why does this need to be cleared? I'd rather we make sure it is never
> > set the first place.
>
> KVM_ARM_VCPU_PMU_V3_SET_PMU and
> KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY can be set on the same
> VCPU. The last KVM_ARM_VCPU_PMU_V3_SET_PMU or
> KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY setting will be effective.
>
> A VMM may try set these attributes to check if the setting is
> supported. For example, the RFC QEMU patch first uses
> KVM_ARM_VCPU_PMU_V3_SET_PMU to find a compatible PMU that covers all
> pCPUs, and then falls back to
> KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY. The order of such probing is
> up to the VMM.
KVM_ARM_VCPU_PMU_V3_SET_PMU is not a probing mechanism. You must probe
the PMUs by looking in /sys/bus/event_source/devices/, like kvmtool
does.
So there is no reason to support this stuff, and the two flags should
be made mutually exclusive.
[...]
> >>
> >
> > In conclusion, I find this patch to be rather messy. For a start, it
> > needs to be split in at least 5 patches:
> >
> > - at least two for the refactoring
> > - one for the PMU core changes
> > - one for the UAPI
> > - one for documentation
>
> That clarifies the expected granurarity of patches. The next version
> will be in that layout, perhaps with more patches if an additional
> change. Thanks for the guidance.
>
> >
> > I'd also like some clarification on how this is intended to work if we
> > enable FEAT_PMUv3_ICNTR, because the definition seems to be designed
> > to encompass all fixed-function counters, and I expect this to grow
> > over time.
>
> Indeed the UAPI was designed to encompass all fixed-function counters
> as suggested by Oliver.
>
> To support the UAPI, the implementation avoids hardcoding the
> assumption on the fixed counter(s). FEAT_PMUv3_INCTR will be naturaly
> supported once the common code is properly updated (i.e., the size of
> the event counter bitmask is grown the corresponding registers are
> wired up with a proper check of the feature.)
>
> I expect migration will be handled with the conventional register
> getters and setters, but please share if you have a concern.
At the very least I want to see some documentation explaining that.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v2 3/3] misc: Remove old APDS990x driver
From: Andy Shevchenko @ 2026-04-20 8:41 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Jonathan Cameron, Svyatoslav Ryhel, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jonathan Corbet, Shuah Khan, Greg Kroah-Hartman, Randy Dunlap,
linux-iio, devicetree, linux-kernel, linux-doc
In-Reply-To: <68c671b4-6754-49df-9fdb-2b3382033fb3@app.fastmail.com>
On Mon, Apr 20, 2026 at 10:33:22AM +0200, Arnd Bergmann wrote:
> On Mon, Apr 20, 2026, at 10:21, Andy Shevchenko wrote:
> > On Sun, Apr 19, 2026 at 05:22:16PM +0100, Jonathan Cameron wrote:
> >> On Sun, 19 Apr 2026 16:41:24 +0300 Svyatoslav Ryhel <clamor95@gmail.com> wrote:
> >> > нд, 19 квіт. 2026 р. о 16:33 Jonathan Cameron <jic23@kernel.org> пише:
>
> >> Their userspace will be broken by dropping it. The lack of upstream users
> >> makes this less critical but it can be argued it's still a possible regression.
> >
> > Usual recommendation is to google, and check Debian code search engine.
> > I randomly chose a couple of sysfs nodes and only kernel code refers to them.
> > So, at least there is a good sign that it likely not in use. But one has
> > to perform more checks (all attributes, more sources of information) and
> > summarise that in the commit message.
>
> I think in this case it's sufficient to point out that there is no
> devicetree support in the driver, and no pre-DT board file ever
> declared a platform_device with apds990x_platform_data in mainline
> kernels. The ambient light sensor drivers in drivers/misc/ were
> all added in before the change from boardfile to DT, and from custom
> ABI to drivers/iio.
Works for me. I am all for removing old and legacy (especially non-FW node
compatible) code.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v7 3/4] KVM: arm64: PMU: Introduce FIXED_COUNTERS_ONLY
From: Akihiko Odaki @ 2026-04-20 8:36 UTC (permalink / raw)
To: Marc Zyngier
Cc: Oliver Upton, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Catalin Marinas, Will Deacon, Kees Cook, Gustavo A. R. Silva,
Paolo Bonzini, Jonathan Corbet, Shuah Khan, linux-arm-kernel,
kvmarm, linux-kernel, linux-hardening, devel, kvm, linux-doc,
linux-kselftest
In-Reply-To: <87ldeic1gk.wl-maz@kernel.org>
On 2026/04/20 2:19, Marc Zyngier wrote:
> On Sat, 18 Apr 2026 09:14:25 +0100,
> Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>>
>> On a heterogeneous arm64 system, KVM's PMU emulation is based on the
>> features of a single host PMU instance. When a vCPU is migrated to a
>> pCPU with an incompatible PMU, counters such as PMCCNTR_EL0 stop
>> incrementing.
>>
>> Although this behavior is permitted by the architecture, Windows does
>> not handle it gracefully and may crash with a division-by-zero error.
>>
>> The current workaround requires VMMs to pin vCPUs to a set of pCPUs
>> that share a compatible PMU. This is difficult to implement correctly in
>> QEMU/libvirt, where pinning occurs after vCPU initialization, and it
>> also restricts the guest to a subset of available pCPUs.
>>
>> Introduce the KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY attribute to
>> create a "fixed-counters-only" PMU. When set, KVM exposes a PMU that is
>> compatible with all pCPUs but that does not support programmable
>> event counters which may have different feature sets on different PMUs.
>>
>> This allows Windows guests to run reliably on heterogeneous systems
>> without crashing, even without vCPU pinning, and enables VMMs to
>> schedule vCPUs across all available pCPUs, making full use of the host
>> hardware.
>>
>> Much like KVM_ARM_VCPU_PMU_V3_IRQ and other read-write attributes, this
>> attribute provides a getter that facilitates kernel and userspace
>> debugging/testing.
>
> OK, so that's the sales pitch. But how is it implemented? I would like
> to be able to read a high-level description of the implementation
> trade-offs.
Implementation-wise it is very trivial. Essentially the following
addition in kvm_arm_pmu_v3_get_attr() is the entire implementation:
+ case KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY:
+ if (test_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY,
&vcpu->kvm->arch.flags))
+ return 0;
Both its functionality and code complexity is trivial. So we can argue that:
- the functionality is too trivial to be useful or
- the interface/implementation complexity is so trivial that it does not
incur maintenance burden
In this case the selftest uses the getter so I was more inclined to have
it, but adding one just for the selftest sounds too ad-hoc, so here I
looked into other attributes to ensure that it was not introducing
inconsistency with existing interfaces.
As the result, I found there are other read-write attributes; in fact
there are more read-write attributes than write-only ones.
>
>>
>> Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
>> ---
>> Documentation/virt/kvm/devices/vcpu.rst | 29 ++++++
>> arch/arm64/include/asm/kvm_host.h | 2 +
>> arch/arm64/include/uapi/asm/kvm.h | 1 +
>> arch/arm64/kvm/arm.c | 1 +
>> arch/arm64/kvm/pmu-emul.c | 155 +++++++++++++++++++++++---------
>> include/kvm/arm_pmu.h | 2 +
>> 6 files changed, 147 insertions(+), 43 deletions(-)
>>
>> diff --git a/Documentation/virt/kvm/devices/vcpu.rst b/Documentation/virt/kvm/devices/vcpu.rst
>> index 60bf205cb373..e0aeb1897d77 100644
>> --- a/Documentation/virt/kvm/devices/vcpu.rst
>> +++ b/Documentation/virt/kvm/devices/vcpu.rst
>> @@ -161,6 +161,35 @@ explicitly selected, or the number of counters is out of range for the
>> selected PMU. Selecting a new PMU cancels the effect of setting this
>> attribute.
>>
>> +1.6 ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY
>> +------------------------------------------------------
>> +
>> +:Parameters: no additional parameter in kvm_device_attr.addr
>> +
>> +:Returns:
>> +
>> + ======= =====================================================
>> + -EBUSY Attempted to set after initializing PMUv3 or running
>> + VCPU, or attempted to set for the first time after
>> + setting an event filter
>> + -ENXIO Attempted to get before setting
>> + -ENODEV Attempted to set while PMUv3 not supported
>> + ======= =====================================================
>> +
>> +If set, PMUv3 will be emulated without programmable event counters. The VCPU
>> +will use any compatible hardware PMU. This attribute is particularly useful on
>
> Not quite "any PMU". It will use *the* PMU of the physical CPU,
> irrespective of the implementation.
I think:
- this comment
- one on the KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED note
- one on kvm_pmu_create_perf_event()
- and one on kvm_arm_pmu_v3_set_pmu_fixed_counters_only()
All boil down into one question: will it support all possible CPUs, or
will it support a subset? Let me answer here:
This patch is written to support a subset instead of all possible CPUs.
If a pCPU does not have a compatible PMU, the pCPU will not be supported
and cause KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED.
This patch does not enforce all possible CPUs are covered by the
compatible PMUs. Theoretically speaking, kvm_arm_pmu_get_pmuver_limit()
enables the PMU emulation when real PMUv3 hardware covers all possible
CPUs *or* the relevant registers can be trapped with IMPDEF, so some
pCPU may not have a compatible PMU and only provide the IMPDEF trapping.
Practically, I don't think any sane configuration will ever have such a
subset support, so we can explicitly enforce all possible CPUs are
covered by the compatible PMUs if desired.
>
>> +heterogeneous systems where different hardware PMUs cover different physical
>> +CPUs. The compatibility of hardware PMUs can be checked with
>> +KVM_ARM_VCPU_PMU_V3_SET_PMU. All VCPUs in a VM share this attribute. It isn't
>> +possible to set it for the first time if a PMU event filter is already present.
>
> "for the first time" gives the impression that it will work if you try
> again. I'd rather we say that "This feature is incompatible with the
> existence of a PMU event filter".
The following sequence will work:
1. Set KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY
2. Set KVM_ARM_VCPU_PMU_V3_FILTER
3. Set KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY
This is to make the behavior conistent with KVM_ARM_VCPU_PMU_V3_SET_PMU.
>
> Furthermore, the architecture currently describes *two* fixed-function
> counters (cycles and instructions), while KVM only expose the cycle
> counter. I'm all for the extra abstraction, but what does it mean for
> migration if we enable FEAT_PMUv3_ICNTR?
I'll answe this at the end of this email.
>
>> +
>> +Note that KVM will not make any attempts to run the VCPU on the physical CPUs
>> +with compatible hardware PMUs. This is entirely left to userspace. However,
>> +attempting to run the VCPU on an unsupported CPU will fail and KVM_RUN will
>> +return with exit_reason = KVM_EXIT_FAIL_ENTRY and populate the fail_entry struct
>> +by setting hardware_entry_failure_reason field to
>> +KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED and the cpu field to the processor id.
>> +
>
> This is mostly a copy-paste of the previous section. How relevant is
> this to the fixed-counters-only feature? If the whole point of this
> stuff is to ensure compatibility across CPUs with different PMU
> implementations, surely what you describe here is the opposite of what
> you want.
Please see the earlier discussion of supported pCPUs.
>
> My preference would be to move this to a separate patch in any case,
> more on that below.
I will do so with the next version.
>
>> 2. GROUP: KVM_ARM_VCPU_TIMER_CTRL
>> =================================
>>
>> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
>> index 59f25b85be2b..b59e0182472c 100644
>> --- a/arch/arm64/include/asm/kvm_host.h
>> +++ b/arch/arm64/include/asm/kvm_host.h
>> @@ -353,6 +353,8 @@ struct kvm_arch {
>> #define KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS 10
>> /* Unhandled SEAs are taken to userspace */
>> #define KVM_ARCH_FLAG_EXIT_SEA 11
>> + /* PMUv3 is emulated without progammable event counters */
>> +#define KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY 12
>> unsigned long flags;
>>
>> /* VM-wide vCPU feature set */
>> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
>> index a792a599b9d6..474c84fa757f 100644
>> --- a/arch/arm64/include/uapi/asm/kvm.h
>> +++ b/arch/arm64/include/uapi/asm/kvm.h
>> @@ -436,6 +436,7 @@ enum {
>> #define KVM_ARM_VCPU_PMU_V3_FILTER 2
>> #define KVM_ARM_VCPU_PMU_V3_SET_PMU 3
>> #define KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS 4
>> +#define KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY 5
>> #define KVM_ARM_VCPU_TIMER_CTRL 1
>> #define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
>> #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
>> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
>> index 620a465248d1..dca16ca26d32 100644
>> --- a/arch/arm64/kvm/arm.c
>> +++ b/arch/arm64/kvm/arm.c
>> @@ -634,6 +634,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>> if (has_vhe())
>> kvm_vcpu_load_vhe(vcpu);
>> kvm_arch_vcpu_load_fp(vcpu);
>> + kvm_vcpu_load_pmu(vcpu);
>> kvm_vcpu_pmu_restore_guest(vcpu);
>> if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
>> kvm_make_request(KVM_REQ_RECORD_STEAL, vcpu);
>> diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
>> index ef5140bbfe28..d1009c144581 100644
>> --- a/arch/arm64/kvm/pmu-emul.c
>> +++ b/arch/arm64/kvm/pmu-emul.c
>> @@ -326,7 +326,10 @@ u64 kvm_pmu_implemented_counter_mask(struct kvm_vcpu *vcpu)
>>
>> static void kvm_pmc_enable_perf_event(struct kvm_pmc *pmc)
>> {
>> - if (!pmc->perf_event) {
>> + struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
>> +
>> + if (!pmc->perf_event ||
>> + !cpumask_test_cpu(vcpu->cpu, &to_arm_pmu(pmc->perf_event->pmu)->supported_cpus)) {
>> kvm_pmu_create_perf_event(pmc);
>> return;
>> }
>> @@ -667,10 +670,8 @@ static bool kvm_pmc_counts_at_el2(struct kvm_pmc *pmc)
>> return kvm_pmc_read_evtreg(pmc) & ARMV8_PMU_INCLUDE_EL2;
>> }
>>
>> -static int kvm_map_pmu_event(struct kvm *kvm, unsigned int eventsel)
>> +static int kvm_map_pmu_event(struct arm_pmu *pmu, unsigned int eventsel)
>> {
>> - struct arm_pmu *pmu = kvm->arch.arm_pmu;
>> -
>> /*
>> * The CPU PMU likely isn't PMUv3; let the driver provide a mapping
>> * for the guest's PMUv3 event ID.
>
> This refactor should be in its own patch. This sort of minor change is
> adding noise to the mean of the patch, for no good reason.
I'll make that change with the next version too.
>
>> @@ -681,6 +682,23 @@ static int kvm_map_pmu_event(struct kvm *kvm, unsigned int eventsel)
>> return eventsel;
>> }
>>
>> +static struct arm_pmu *kvm_pmu_probe_armpmu(int cpu)
>> +{
>> + struct arm_pmu_entry *entry;
>> + struct arm_pmu *pmu;
>> +
>> + guard(rcu)();
>> +
>> + list_for_each_entry_rcu(entry, &arm_pmus, entry) {
>> + pmu = entry->arm_pmu;
>> +
>> + if (cpumask_test_cpu(cpu, &pmu->supported_cpus))
>> + return pmu;
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> /**
>> * kvm_pmu_create_perf_event - create a perf event for a counter
>> * @pmc: Counter context
>> @@ -694,6 +712,12 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
>> int eventsel;
>> u64 evtreg;
>>
>> + if (test_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY, &vcpu->kvm->arch.flags)) {
>> + arm_pmu = kvm_pmu_probe_armpmu(vcpu->cpu);
>> + if (!arm_pmu)
>> + return;
>
> How is it possible to not get a PMU here? We don't expose the PMU to a
> guest at all if there are CPUs without PMUs, see the comment in
> kvm_host_pmu_init(). So I'd expect this to never fail.
Please see the earlier comment.
>
>> + }
>> +
>> evtreg = kvm_pmc_read_evtreg(pmc);
>>
>> kvm_pmu_stop_counter(pmc);
>> @@ -722,7 +746,7 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
>> * Don't create an event if we're running on hardware that requires
>> * PMUv3 event translation and we couldn't find a valid mapping.
>> */
>> - eventsel = kvm_map_pmu_event(vcpu->kvm, eventsel);
>> + eventsel = kvm_map_pmu_event(arm_pmu, eventsel);
>> if (eventsel < 0)
>> return;
>>
>> @@ -810,42 +834,6 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
>> list_add_tail_rcu(&entry->entry, &arm_pmus);
>> }
>>
>> -static struct arm_pmu *kvm_pmu_probe_armpmu(void)
>> -{
>> - struct arm_pmu_entry *entry;
>> - struct arm_pmu *pmu;
>> - int cpu;
>> -
>> - guard(rcu)();
>> -
>> - /*
>> - * It is safe to use a stale cpu to iterate the list of PMUs so long as
>> - * the same value is used for the entirety of the loop. Given this, and
>> - * the fact that no percpu data is used for the lookup there is no need
>> - * to disable preemption.
>> - *
>> - * It is still necessary to get a valid cpu, though, to probe for the
>> - * default PMU instance as userspace is not required to specify a PMU
>> - * type. In order to uphold the preexisting behavior KVM selects the
>> - * PMU instance for the core during vcpu init. A dependent use
>> - * case would be a user with disdain of all things big.LITTLE that
>> - * affines the VMM to a particular cluster of cores.
>> - *
>> - * In any case, userspace should just do the sane thing and use the UAPI
>> - * to select a PMU type directly. But, be wary of the baggage being
>> - * carried here.
>> - */
>> - cpu = raw_smp_processor_id();
>> - list_for_each_entry_rcu(entry, &arm_pmus, entry) {
>> - pmu = entry->arm_pmu;
>> -
>> - if (cpumask_test_cpu(cpu, &pmu->supported_cpus))
>> - return pmu;
>> - }
>> -
>> - return NULL;
>> -}
>> -
>
> Same thing for the refactoring of this function. Moving it, changing
> the signature and moving the comment somewhere else would be better
> placed on its own.
This will be in a separate patch with the next version.
>
>> static u64 __compute_pmceid(struct arm_pmu *pmu, bool pmceid1)
>> {
>> u32 hi[2], lo[2];
>> @@ -888,6 +876,9 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
>> u64 val, mask = 0;
>> int base, i, nr_events;
>>
>> + if (test_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY, &vcpu->kvm->arch.flags))
>> + return 0;
>> +
>> if (!pmceid1) {
>> val = compute_pmceid0(cpu_pmu);
>> base = 0;
>> @@ -915,6 +906,26 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
>> return val & mask;
>> }
>>
>> +void kvm_vcpu_load_pmu(struct kvm_vcpu *vcpu)
>> +{
>> + unsigned long mask = kvm_pmu_enabled_counter_mask(vcpu);
>> + struct kvm_pmc *pmc;
>> + struct arm_pmu *cpu_pmu;
>
> Move these to be inside the loop.
I followed the pattern of other functions, but I agree this new code can
follow a more modern style. It will be done with the next version.
>
>> + int i;
>> +
>> + for_each_set_bit(i, &mask, 32) {
>> + pmc = kvm_vcpu_idx_to_pmc(vcpu, i);
>> + if (!pmc->perf_event)
>> + continue;
>> +
>> + cpu_pmu = to_arm_pmu(pmc->perf_event->pmu);
>> + if (!cpumask_test_cpu(vcpu->cpu, &cpu_pmu->supported_cpus)) {
>> + kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
>> + break;
>> + }
>> + }
>> +}
>> +
>
> Why do we need to inflict this on VMs that do not have the fixed
> counter restriction?
This function is to re-create the perf_event in case the current
perf_event does not support the pCPU because e.g., the pCPU is a E-core
while the perf_event only covers the P-cores.
>
> And even then, all you have to reconfigure is the cycle counter. So
> why the loop? All we want to find out is whether the cycle counter is
> instantiated on the PMU that matches the current CPU.
I just wanted to avoid hardcoding assumptions on the fixed counter(s).
FEAT_PMUv3_ICNTR will be naturaly handled with a loop, for example.
>
>> void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
>> {
>> u64 mask = kvm_pmu_implemented_counter_mask(vcpu);
>> @@ -1016,6 +1027,9 @@ u8 kvm_arm_pmu_get_max_counters(struct kvm *kvm)
>> {
>> struct arm_pmu *arm_pmu = kvm->arch.arm_pmu;
>>
>> + if (test_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY, &kvm->arch.flags))
>> + return 0;
>> +
>> /*
>> * PMUv3 requires that all event counters are capable of counting any
>> * event, though the same may not be true of non-PMUv3 hardware.
>> @@ -1070,7 +1084,24 @@ static void kvm_arm_set_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu)
>> */
>> int kvm_arm_set_default_pmu(struct kvm *kvm)
>> {
>> - struct arm_pmu *arm_pmu = kvm_pmu_probe_armpmu();
>> + /*
>> + * It is safe to use a stale cpu to iterate the list of PMUs so long as
>> + * the same value is used for the entirety of the loop. Given this, and
>> + * the fact that no percpu data is used for the lookup there is no need
>> + * to disable preemption.
>> + *
>> + * It is still necessary to get a valid cpu, though, to probe for the
>> + * default PMU instance as userspace is not required to specify a PMU
>> + * type. In order to uphold the preexisting behavior KVM selects the
>> + * PMU instance for the core during vcpu init. A dependent use
>> + * case would be a user with disdain of all things big.LITTLE that
>> + * affines the VMM to a particular cluster of cores.
>> + *
>> + * In any case, userspace should just do the sane thing and use the UAPI
>> + * to select a PMU type directly. But, be wary of the baggage being
>> + * carried here.
>> + */
>> + struct arm_pmu *arm_pmu = kvm_pmu_probe_armpmu(raw_smp_processor_id());
>>
>> if (!arm_pmu)
>> return -ENODEV;
>> @@ -1098,6 +1129,7 @@ static int kvm_arm_pmu_v3_set_pmu(struct kvm_vcpu *vcpu, int pmu_id)
>> break;
>> }
>>
>> + clear_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY, &kvm->arch.flags);
>
> Why does this need to be cleared? I'd rather we make sure it is never
> set the first place.
KVM_ARM_VCPU_PMU_V3_SET_PMU and KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY
can be set on the same VCPU. The last KVM_ARM_VCPU_PMU_V3_SET_PMU or
KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY setting will be effective.
A VMM may try set these attributes to check if the setting is supported.
For example, the RFC QEMU patch first uses KVM_ARM_VCPU_PMU_V3_SET_PMU
to find a compatible PMU that covers all pCPUs, and then falls back to
KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY. The order of such probing is up
to the VMM.
This rationale applies also to the next comment.
>
>> kvm_arm_set_pmu(kvm, arm_pmu);
>> cpumask_copy(kvm->arch.supported_cpus, &arm_pmu->supported_cpus);
>> ret = 0;
>> @@ -1108,11 +1140,42 @@ static int kvm_arm_pmu_v3_set_pmu(struct kvm_vcpu *vcpu, int pmu_id)
>> return ret;
>> }
>>
>> +static int kvm_arm_pmu_v3_set_pmu_fixed_counters_only(struct kvm_vcpu *vcpu)
>> +{
>> + struct kvm *kvm = vcpu->kvm;
>> + struct arm_pmu_entry *entry;
>> + struct arm_pmu *arm_pmu;
>> + struct cpumask *supported_cpus = kvm->arch.supported_cpus;
>> +
>> + lockdep_assert_held(&kvm->arch.config_lock);
>> +
>> + if (kvm_vm_has_ran_once(kvm) ||
>> + (kvm->arch.pmu_filter &&
>> + !test_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY, &kvm->arch.flags)))
>> + return -EBUSY;
>> +
>> + set_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY, &kvm->arch.flags);
>> + kvm_arm_set_nr_counters(kvm, 0);
>> + cpumask_clear(supported_cpus);
>
> What is the purpose of this cpumask_clear()? Under what conditions can
> you have something else?
>
>> +
>> + guard(rcu)();
>> +
>> + list_for_each_entry_rcu(entry, &arm_pmus, entry) {
>> + arm_pmu = entry->arm_pmu;
>> + cpumask_or(supported_cpus, supported_cpus, &arm_pmu->supported_cpus);
>
> Why isn't supported_cpus directly set to possible_cpus? Isn't that the
> base requirement that you can run on any CPU at all?
Please see the earlier discussion of supported pCPUs.
>
>> + }
>> +
>> + return 0;
>> +}
>> +
>> static int kvm_arm_pmu_v3_set_nr_counters(struct kvm_vcpu *vcpu, unsigned int n)
>> {
>> struct kvm *kvm = vcpu->kvm;
>>
>> - if (!kvm->arch.arm_pmu)
>> + lockdep_assert_held(&kvm->arch.config_lock);
>> +
>> + if (!kvm->arch.arm_pmu &&
>> + !test_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY, &kvm->arch.flags))
>> return -EINVAL;
>>
>> if (n > kvm_arm_pmu_get_max_counters(kvm))
>> @@ -1227,6 +1290,8 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
>>
>> return kvm_arm_pmu_v3_set_nr_counters(vcpu, n);
>> }
>> + case KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY:
>> + return kvm_arm_pmu_v3_set_pmu_fixed_counters_only(vcpu);
>> case KVM_ARM_VCPU_PMU_V3_INIT:
>> return kvm_arm_pmu_v3_init(vcpu);
>> }
>> @@ -1253,6 +1318,9 @@ int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
>> irq = vcpu->arch.pmu.irq_num;
>> return put_user(irq, uaddr);
>> }
>> + case KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY:
>> + if (test_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY, &vcpu->kvm->arch.flags))
>
> With 6 occurrences of this test_bit(), it feels like it'd be valuable
> to have a dedicate predicate to help with readability.
I'll add one with the next version.
>
>> + return 0;
>> }
>>
>> return -ENXIO;
>> @@ -1266,6 +1334,7 @@ int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
>> case KVM_ARM_VCPU_PMU_V3_FILTER:
>> case KVM_ARM_VCPU_PMU_V3_SET_PMU:
>> case KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS:
>> + case KVM_ARM_VCPU_PMU_V3_FIXED_COUNTERS_ONLY:
>> if (kvm_vcpu_has_pmu(vcpu))
>> return 0;
>> }
>> diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
>> index 96754b51b411..1375cbaf97b2 100644
>> --- a/include/kvm/arm_pmu.h
>> +++ b/include/kvm/arm_pmu.h
>> @@ -56,6 +56,7 @@ void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val);
>> void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val);
>> void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
>> u64 select_idx);
>> +void kvm_vcpu_load_pmu(struct kvm_vcpu *vcpu);
>> void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu);
>> int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu,
>> struct kvm_device_attr *attr);
>> @@ -161,6 +162,7 @@ static inline u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
>> static inline void kvm_pmu_update_vcpu_events(struct kvm_vcpu *vcpu) {}
>> static inline void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu) {}
>> static inline void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu) {}
>> +static inline void kvm_vcpu_load_pmu(struct kvm_vcpu *vcpu) {}
>> static inline void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu) {}
>> static inline u8 kvm_arm_pmu_get_pmuver_limit(void)
>> {
>>
>
> In conclusion, I find this patch to be rather messy. For a start, it
> needs to be split in at least 5 patches:
>
> - at least two for the refactoring
> - one for the PMU core changes
> - one for the UAPI
> - one for documentation
That clarifies the expected granurarity of patches. The next version
will be in that layout, perhaps with more patches if an additional
change. Thanks for the guidance.
>
> I'd also like some clarification on how this is intended to work if we
> enable FEAT_PMUv3_ICNTR, because the definition seems to be designed
> to encompass all fixed-function counters, and I expect this to grow
> over time.
Indeed the UAPI was designed to encompass all fixed-function counters as
suggested by Oliver.
To support the UAPI, the implementation avoids hardcoding the assumption
on the fixed counter(s). FEAT_PMUv3_INCTR will be naturaly supported
once the common code is properly updated (i.e., the size of the event
counter bitmask is grown the corresponding registers are wired up with a
proper check of the feature.)
I expect migration will be handled with the conventional register
getters and setters, but please share if you have a concern.
>
> I'm also not planning to look at the selftest at this stage.
That is completely understandable; I'll focus on refining the design and
implementation for the next version first.
Regards,
Akihiko Odaki
^ permalink raw reply
* Re: [PATCH v2 3/3] misc: Remove old APDS990x driver
From: Arnd Bergmann @ 2026-04-20 8:33 UTC (permalink / raw)
To: Andy Shevchenko, Jonathan Cameron
Cc: Svyatoslav Ryhel, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
Shuah Khan, Greg Kroah-Hartman, Randy Dunlap, linux-iio,
devicetree, linux-kernel, linux-doc
In-Reply-To: <aeXh7j410AxESy4U@ashevche-desk.local>
On Mon, Apr 20, 2026, at 10:21, Andy Shevchenko wrote:
> On Sun, Apr 19, 2026 at 05:22:16PM +0100, Jonathan Cameron wrote:
>> On Sun, 19 Apr 2026 16:41:24 +0300 Svyatoslav Ryhel <clamor95@gmail.com> wrote:
>> > нд, 19 квіт. 2026 р. о 16:33 Jonathan Cameron <jic23@kernel.org> пише:
>>
>> Their userspace will be broken by dropping it. The lack of upstream users
>> makes this less critical but it can be argued it's still a possible regression.
>
> Usual recommendation is to google, and check Debian code search engine.
> I randomly chose a couple of sysfs nodes and only kernel code refers to them.
> So, at least there is a good sign that it likely not in use. But one has
> to perform more checks (all attributes, more sources of information) and
> summarise that in the commit message.
I think in this case it's sufficient to point out that there is no
devicetree support in the driver, and no pre-DT board file ever
declared a platform_device with apds990x_platform_data in mainline
kernels. The ambient light sensor drivers in drivers/misc/ were
all added in before the change from boardfile to DT, and from custom
ABI to drivers/iio.
Arnd
^ permalink raw reply
* Re: [PATCH v2 3/3] misc: Remove old APDS990x driver
From: Andy Shevchenko @ 2026-04-20 8:21 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Svyatoslav Ryhel, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
Shuah Khan, Arnd Bergmann, Greg Kroah-Hartman, Randy Dunlap,
linux-iio, devicetree, linux-kernel, linux-doc
In-Reply-To: <20260419172216.3cf10e51@jic23-huawei>
On Sun, Apr 19, 2026 at 05:22:16PM +0100, Jonathan Cameron wrote:
> On Sun, 19 Apr 2026 16:41:24 +0300
> Svyatoslav Ryhel <clamor95@gmail.com> wrote:
> > нд, 19 квіт. 2026 р. о 16:33 Jonathan Cameron <jic23@kernel.org> пише:
> > > On Sun, 19 Apr 2026 11:31:24 +0300
> > > Svyatoslav Ryhel <clamor95@gmail.com> wrote:
...
> > > There is the obvious point of ABI compatibility raised as well, but given
> > > we don't seem to be getting much push back on that maybe that's not a significant
> > > concern.
> >
> > I did not found any ABI in the Documentation/ABI regarding this sensor
> > using grep,
The code is what is in use, it has an ABI. The question if it's in use or not.
> > maybe you are more familiar?
> Doesn't matter if it's documented explicitly (many older drivers are not).
> The question is whether anyone has supported parts and userspace code that
> makes use of the sysfs files this driver provides.
>
> Their userspace will be broken by dropping it. The lack of upstream users
> makes this less critical but it can be argued it's still a possible regression.
Usual recommendation is to google, and check Debian code search engine.
I randomly chose a couple of sysfs nodes and only kernel code refers to them.
So, at least there is a good sign that it likely not in use. But one has
to perform more checks (all attributes, more sources of information) and
summarise that in the commit message.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v7 2/4] KVM: arm64: PMU: Protect the list of PMUs with RCU
From: Akihiko Odaki @ 2026-04-20 7:17 UTC (permalink / raw)
To: Marc Zyngier
Cc: Oliver Upton, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Catalin Marinas, Will Deacon, Kees Cook, Gustavo A. R. Silva,
Paolo Bonzini, Jonathan Corbet, Shuah Khan, linux-arm-kernel,
kvmarm, linux-kernel, linux-hardening, devel, kvm, linux-doc,
linux-kselftest
In-Reply-To: <86se8q15eo.wl-maz@kernel.org>
On 2026/04/20 16:01, Marc Zyngier wrote:
> On Mon, 20 Apr 2026 07:21:45 +0100,
> Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>>
>> On 2026/04/19 23:34, Marc Zyngier wrote:
>>> On Sat, 18 Apr 2026 09:14:24 +0100,
>>> Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>>>>
>>>> Convert the list of PMUs to a RCU-protected list that has primitives to
>>>> avoid read-side contention.
>>>>
>>>> Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
>>>> ---
>>>> arch/arm64/kvm/pmu-emul.c | 14 ++++++--------
>>>> 1 file changed, 6 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
>>>> index 59ec96e09321..ef5140bbfe28 100644
>>>> --- a/arch/arm64/kvm/pmu-emul.c
>>>> +++ b/arch/arm64/kvm/pmu-emul.c
>>>> @@ -7,9 +7,9 @@
>>>> #include <linux/cpu.h>
>>>> #include <linux/kvm.h>
>>>> #include <linux/kvm_host.h>
>>>> -#include <linux/list.h>
>>>> #include <linux/perf_event.h>
>>>> #include <linux/perf/arm_pmu.h>
>>>> +#include <linux/rculist.h>
>>>> #include <linux/uaccess.h>
>>>> #include <asm/kvm_emulate.h>
>>>> #include <kvm/arm_pmu.h>
>>>> @@ -26,7 +26,6 @@ static bool kvm_pmu_counter_is_enabled(struct kvm_pmc *pmc);
>>>> bool kvm_supports_guest_pmuv3(void)
>>>> {
>>>> - guard(mutex)(&arm_pmus_lock);
>>>> return !list_empty(&arm_pmus);
>>>
>>> Please read include/linux/rculist.h and the discussion about the
>>> interaction of list_empty() with RCU-protected lists. How about using
>>> list_first_or_null_rcu() for peace of mind?
>>
>> list_first_or_null_rcu() is useful to replace a sequence of
>> list_empty() and list_first_entry() that is protected by a lock, but
>> this function instead requires the invariant that nobody deletes an
>> element from the list, and list_first_or_null_rcu() does not allow
>> removing the requirement.
>>
>> The header file says:
>>> Where are list_empty_rcu() and list_first_entry_rcu()?
>>>
>>> They do not exist because they would lead to subtle race conditions:
>>>
>>> if (!list_empty_rcu(mylist)) {
>>> struct foo *bar = list_first_entry_rcu(mylist, struct foo,
>>> list_member);
>>> do_something(bar);
>>> }
>>>
>>> The list might be non-empty when list_empty_rcu() checks it, but it
>>> might have become empty by the time that list_first_entry_rcu()
>>> rereads the ->next pointer, which would result in a SEGV.
>>>
>>> When not using RCU, it is OK for list_first_entry() to re-read that
>>> pointer because both functions should be protected by some lock that
>>> blocks writers.
>>>
>>> When using RCU, list_empty() uses READ_ONCE() to fetch the
>>> RCU-protected ->next pointer and then compares it to the address of
>>> the list head. However, it neither dereferences this pointer nor
>>> provides this pointer to its caller. Thus, READ_ONCE() suffices
>>> (that is, rcu_dereference() is not needed), which means that
>>> list_empty() can be used anywhere you would want to use
>>> list_empty_rcu(). Just don't expect anything useful to happen if you
>>> do a subsequent lockless call to list_first_entry_rcu()!!!
>>>
>>> See list_first_or_null_rcu for an alternative.
>>
>> However, kvm_supports_guest_pmuv3() locked a mutex when calling
>> list_empty() and unlocked it immediately after that, instead of
>> re-reading list_first_entry(). This construct inherently had a race
>> condition with code that deletes an element; when the caller of
>> kvm_supports_guest_pmuv3() decides to enable guest PMUv3, the host PMU
>> may have been gone. But it was still safe because no one deletes an
>> element.
>>
>> The same logic also applies when using RCU. As the comment says, we
>> can use list_empty() instead of the hypothetical list_empty_rcu()
>> macro because we don't expect it to magically enable something like
>> list_first_entry_rcu(). This function instead keep relying on the fact
>> that no one deletes an element of the list.
>
> And that's exactly the sort of thing I am trying to plan for. *Should*
> we introduce a way to remove PMUs from the list, this predicate
> becomes unsafe.
Perhaps so. In regards to this series, I'd rather like to keep it out of
scope as the requirement is not new.
>
> So I want at least a comment explaining this to the unsuspecting
> reader, as this is rather subtle.
I agree. I had to put some effort to understand the previous
mutex-protected implementation and to design the new RCU-protected one.
I'll add one with the next version.
Regards,
Akihiko Odaki
^ permalink raw reply
* Re: [PATCH v7 2/4] KVM: arm64: PMU: Protect the list of PMUs with RCU
From: Marc Zyngier @ 2026-04-20 7:01 UTC (permalink / raw)
To: Akihiko Odaki
Cc: Oliver Upton, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Catalin Marinas, Will Deacon, Kees Cook, Gustavo A. R. Silva,
Paolo Bonzini, Jonathan Corbet, Shuah Khan, linux-arm-kernel,
kvmarm, linux-kernel, linux-hardening, devel, kvm, linux-doc,
linux-kselftest
In-Reply-To: <483e5cf2-a54c-4781-ac6d-49f5bc7128ba@rsg.ci.i.u-tokyo.ac.jp>
On Mon, 20 Apr 2026 07:21:45 +0100,
Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>
> On 2026/04/19 23:34, Marc Zyngier wrote:
> > On Sat, 18 Apr 2026 09:14:24 +0100,
> > Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
> >>
> >> Convert the list of PMUs to a RCU-protected list that has primitives to
> >> avoid read-side contention.
> >>
> >> Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> >> ---
> >> arch/arm64/kvm/pmu-emul.c | 14 ++++++--------
> >> 1 file changed, 6 insertions(+), 8 deletions(-)
> >>
> >> diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
> >> index 59ec96e09321..ef5140bbfe28 100644
> >> --- a/arch/arm64/kvm/pmu-emul.c
> >> +++ b/arch/arm64/kvm/pmu-emul.c
> >> @@ -7,9 +7,9 @@
> >> #include <linux/cpu.h>
> >> #include <linux/kvm.h>
> >> #include <linux/kvm_host.h>
> >> -#include <linux/list.h>
> >> #include <linux/perf_event.h>
> >> #include <linux/perf/arm_pmu.h>
> >> +#include <linux/rculist.h>
> >> #include <linux/uaccess.h>
> >> #include <asm/kvm_emulate.h>
> >> #include <kvm/arm_pmu.h>
> >> @@ -26,7 +26,6 @@ static bool kvm_pmu_counter_is_enabled(struct kvm_pmc *pmc);
> >> bool kvm_supports_guest_pmuv3(void)
> >> {
> >> - guard(mutex)(&arm_pmus_lock);
> >> return !list_empty(&arm_pmus);
> >
> > Please read include/linux/rculist.h and the discussion about the
> > interaction of list_empty() with RCU-protected lists. How about using
> > list_first_or_null_rcu() for peace of mind?
>
> list_first_or_null_rcu() is useful to replace a sequence of
> list_empty() and list_first_entry() that is protected by a lock, but
> this function instead requires the invariant that nobody deletes an
> element from the list, and list_first_or_null_rcu() does not allow
> removing the requirement.
>
> The header file says:
> > Where are list_empty_rcu() and list_first_entry_rcu()?
> >
> > They do not exist because they would lead to subtle race conditions:
> >
> > if (!list_empty_rcu(mylist)) {
> > struct foo *bar = list_first_entry_rcu(mylist, struct foo,
> > list_member);
> > do_something(bar);
> > }
> >
> > The list might be non-empty when list_empty_rcu() checks it, but it
> > might have become empty by the time that list_first_entry_rcu()
> > rereads the ->next pointer, which would result in a SEGV.
> >
> > When not using RCU, it is OK for list_first_entry() to re-read that
> > pointer because both functions should be protected by some lock that
> > blocks writers.
> >
> > When using RCU, list_empty() uses READ_ONCE() to fetch the
> > RCU-protected ->next pointer and then compares it to the address of
> > the list head. However, it neither dereferences this pointer nor
> > provides this pointer to its caller. Thus, READ_ONCE() suffices
> > (that is, rcu_dereference() is not needed), which means that
> > list_empty() can be used anywhere you would want to use
> > list_empty_rcu(). Just don't expect anything useful to happen if you
> > do a subsequent lockless call to list_first_entry_rcu()!!!
> >
> > See list_first_or_null_rcu for an alternative.
>
> However, kvm_supports_guest_pmuv3() locked a mutex when calling
> list_empty() and unlocked it immediately after that, instead of
> re-reading list_first_entry(). This construct inherently had a race
> condition with code that deletes an element; when the caller of
> kvm_supports_guest_pmuv3() decides to enable guest PMUv3, the host PMU
> may have been gone. But it was still safe because no one deletes an
> element.
>
> The same logic also applies when using RCU. As the comment says, we
> can use list_empty() instead of the hypothetical list_empty_rcu()
> macro because we don't expect it to magically enable something like
> list_first_entry_rcu(). This function instead keep relying on the fact
> that no one deletes an element of the list.
And that's exactly the sort of thing I am trying to plan for. *Should*
we introduce a way to remove PMUs from the list, this predicate
becomes unsafe.
So I want at least a comment explaining this to the unsuspecting
reader, as this is rather subtle.
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH] Documentation: fix spelling mistake "Minumum" -> "Minimum"
From: Jonathan Corbet @ 2026-04-20 6:47 UTC (permalink / raw)
To: Derek J. Clark, Mark Pearson, Ninad Naik, Armin Wolf, skhan
Cc: platform-driver-x86@vger.kernel.org, linux-doc, linux-kernel, me,
linux-kernel-mentees
In-Reply-To: <BAA4F3A7-E892-4904-95A6-64B177CDA7AD@gmail.com>
"Derek J. Clark" <derekjohn.clark@gmail.com> writes:
> The MOF spelling mistakes are well known. We've left them is as to
> ensure match with what the hardware actually reports.
>
> See: https://lore.kernel.org/platform-driver-x86/cfd7977e-d612-4e08-a68a-65fed8e164b6@gmx.de
>
> I suppose if we're going to continue getting these types or PR I
> should add a note to the documentation. I'll add that soon.
Perhaps worth adding, but I'm not sure I would expect it to help. The
people generating these patches aren't putting much attention into the
context surrounding them.
Thanks,
jon
^ permalink raw reply
* Re: [PATCH] docs: Add overview and SLUB allocator sections to slab documentation
From: Jonathan Corbet @ 2026-04-20 6:43 UTC (permalink / raw)
To: Nick Huang, Lorenzo Stoakes
Cc: David Hildenbrand (Arm), Matthew Wilcox, Vlastimil Babka,
Harry Yoo, Andrew Morton, Hao Li, Christoph Lameter,
David Rientjes, Roman Gushchin, Liam R . Howlett, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Shuah Khan, linux-mm, linux-doc,
linux-kernel
In-Reply-To: <CABZAGRHXtjzGJrgR1NAmVHFMP9eL5zZr3DaTAtAvywv_1sOHdw@mail.gmail.com>
Nick Huang <sef1548@gmail.com> writes:
> I am really sorry for causing trouble for everyone. I would like to
> ask which aspect of mine was disrespectful, so that I can be more
> careful next time.
>
> If I want to make this kind of change, should I send an [RFC patch] to
> ask for everyone's opinion?
If you want to be respectful, start by reading what has been sent to
you; the problems with your submission were well explained, more than
once.
To reiterate:
- Do not send LLM-generated material without marking it as such as
described in our developer documentation.
- Do not attempt to document systems that you do not, yourself,
understand; you have no hope of getting it right, and you will only
succeed in wasting the time of the people who have to review your
changes.
The point of documentation is to be informative, accurate, and useful;
simply filling in a bunch of words is not helpful to anybody.
Thanks,
jon
^ permalink raw reply
* Re: [PATCH] docs: Add overview and SLUB allocator sections to slab documentation
From: Mike Rapoport @ 2026-04-20 6:42 UTC (permalink / raw)
To: Nick Huang
Cc: Lorenzo Stoakes, David Hildenbrand (Arm), Matthew Wilcox,
Vlastimil Babka, Harry Yoo, Andrew Morton, Jonathan Corbet,
Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Liam R . Howlett, Suren Baghdasaryan, Michal Hocko, Shuah Khan,
linux-mm, linux-doc, linux-kernel
In-Reply-To: <CABZAGRHXtjzGJrgR1NAmVHFMP9eL5zZr3DaTAtAvywv_1sOHdw@mail.gmail.com>
Hi Nick,
On Mon, Apr 20, 2026 at 12:52:25PM +0800, Nick Huang wrote:
>
> I am really sorry for causing trouble for everyone. I would like to
> ask which aspect of mine was disrespectful, so that I can be more
> careful next time.
Maintainers time is valuable and sending LLM generated patch completely
without understanding what it is about is disrespect for maintainers wasted
time.
> If I want to make this kind of change, should I send an [RFC patch] to
> ask for everyone's opinion?
If you want to make that kind of change, you should start with researching
and understanding yourself what the code is doing, double check the LLM
output and verify it and not just take an LLM slop and send it.
> Sorry, I really am not very clear about the process.
Start with reading kernel process documentation:
https://docs.kernel.org/process/development-process.html
> --
> Regards,
> Nick Huang
--
Sincerely yours,
Mike.
^ permalink raw reply
* Re: [PATCH v7 2/4] KVM: arm64: PMU: Protect the list of PMUs with RCU
From: Akihiko Odaki @ 2026-04-20 6:21 UTC (permalink / raw)
To: Marc Zyngier
Cc: Oliver Upton, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Catalin Marinas, Will Deacon, Kees Cook, Gustavo A. R. Silva,
Paolo Bonzini, Jonathan Corbet, Shuah Khan, linux-arm-kernel,
kvmarm, linux-kernel, linux-hardening, devel, kvm, linux-doc,
linux-kselftest
In-Reply-To: <87mryzauib.wl-maz@kernel.org>
On 2026/04/19 23:34, Marc Zyngier wrote:
> On Sat, 18 Apr 2026 09:14:24 +0100,
> Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>>
>> Convert the list of PMUs to a RCU-protected list that has primitives to
>> avoid read-side contention.
>>
>> Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
>> ---
>> arch/arm64/kvm/pmu-emul.c | 14 ++++++--------
>> 1 file changed, 6 insertions(+), 8 deletions(-)
>>
>> diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
>> index 59ec96e09321..ef5140bbfe28 100644
>> --- a/arch/arm64/kvm/pmu-emul.c
>> +++ b/arch/arm64/kvm/pmu-emul.c
>> @@ -7,9 +7,9 @@
>> #include <linux/cpu.h>
>> #include <linux/kvm.h>
>> #include <linux/kvm_host.h>
>> -#include <linux/list.h>
>> #include <linux/perf_event.h>
>> #include <linux/perf/arm_pmu.h>
>> +#include <linux/rculist.h>
>> #include <linux/uaccess.h>
>> #include <asm/kvm_emulate.h>
>> #include <kvm/arm_pmu.h>
>> @@ -26,7 +26,6 @@ static bool kvm_pmu_counter_is_enabled(struct kvm_pmc *pmc);
>>
>> bool kvm_supports_guest_pmuv3(void)
>> {
>> - guard(mutex)(&arm_pmus_lock);
>> return !list_empty(&arm_pmus);
>
> Please read include/linux/rculist.h and the discussion about the
> interaction of list_empty() with RCU-protected lists. How about using
> list_first_or_null_rcu() for peace of mind?
list_first_or_null_rcu() is useful to replace a sequence of list_empty()
and list_first_entry() that is protected by a lock, but this function
instead requires the invariant that nobody deletes an element from the
list, and list_first_or_null_rcu() does not allow removing the requirement.
The header file says:
> Where are list_empty_rcu() and list_first_entry_rcu()?
>
> They do not exist because they would lead to subtle race conditions:
>
> if (!list_empty_rcu(mylist)) {
> struct foo *bar = list_first_entry_rcu(mylist, struct foo,
> list_member);
> do_something(bar);
> }
>
> The list might be non-empty when list_empty_rcu() checks it, but it
> might have become empty by the time that list_first_entry_rcu()
> rereads the ->next pointer, which would result in a SEGV.
>
> When not using RCU, it is OK for list_first_entry() to re-read that
> pointer because both functions should be protected by some lock that
> blocks writers.
>
> When using RCU, list_empty() uses READ_ONCE() to fetch the
> RCU-protected ->next pointer and then compares it to the address of
> the list head. However, it neither dereferences this pointer nor
> provides this pointer to its caller. Thus, READ_ONCE() suffices
> (that is, rcu_dereference() is not needed), which means that
> list_empty() can be used anywhere you would want to use
> list_empty_rcu(). Just don't expect anything useful to happen if you
> do a subsequent lockless call to list_first_entry_rcu()!!!
>
> See list_first_or_null_rcu for an alternative.
However, kvm_supports_guest_pmuv3() locked a mutex when calling
list_empty() and unlocked it immediately after that, instead of
re-reading list_first_entry(). This construct inherently had a race
condition with code that deletes an element; when the caller of
kvm_supports_guest_pmuv3() decides to enable guest PMUv3, the host PMU
may have been gone. But it was still safe because no one deletes an element.
The same logic also applies when using RCU. As the comment says, we can
use list_empty() instead of the hypothetical list_empty_rcu() macro
because we don't expect it to magically enable something like
list_first_entry_rcu(). This function instead keep relying on the fact
that no one deletes an element of the list.
Regards,
Akihiko Odaki
^ permalink raw reply
* Re: [PATCH v7 1/4] KVM: arm64: PMU: Add kvm_pmu_enabled_counter_mask()
From: Akihiko Odaki @ 2026-04-20 5:27 UTC (permalink / raw)
To: Marc Zyngier
Cc: Oliver Upton, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Catalin Marinas, Will Deacon, Kees Cook, Gustavo A. R. Silva,
Paolo Bonzini, Jonathan Corbet, Shuah Khan, linux-arm-kernel,
kvmarm, linux-kernel, linux-hardening, devel, kvm, linux-doc,
linux-kselftest
In-Reply-To: <87o6jfavhx.wl-maz@kernel.org>
On 2026/04/19 23:13, Marc Zyngier wrote:
> On Sat, 18 Apr 2026 09:14:23 +0100,
> Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>>
>> This function will be useful to enumerate enabled counters.
>
> Consider expanding this commit message a bit. Something along the
> lines of:
>
> "Add kvm_pmu_enabled_counter_mask() as an accessor returning a 64bit
> mask of the counters enabled on a given vcpu.
>
> This will eventually be useful to iterate over the counters."
That looks better. I think I'll use that message for the next version.
Regards,
Akihiko Odaki
^ permalink raw reply
* Re: [PATCH] docs: Add overview and SLUB allocator sections to slab documentation
From: Nick Huang @ 2026-04-20 4:52 UTC (permalink / raw)
To: Lorenzo Stoakes
Cc: David Hildenbrand (Arm), Matthew Wilcox, Vlastimil Babka,
Harry Yoo, Andrew Morton, Jonathan Corbet, Hao Li,
Christoph Lameter, David Rientjes, Roman Gushchin,
Liam R . Howlett, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Shuah Khan, linux-mm, linux-doc, linux-kernel
In-Reply-To: <aeTTw4gziJigaNbU@lucifer>
Lorenzo Stoakes <ljs@kernel.org> 於 2026年4月19日週日 下午9:17寫道:
>
> On Sun, Apr 19, 2026 at 10:35:44AM +0200, David Hildenbrand (Arm) wrote:
> > On 4/18/26 18:15, Matthew Wilcox wrote:
> > > On Sat, Apr 18, 2026 at 10:07:22AM +0100, Lorenzo Stoakes wrote:
> > >> On Sat, Apr 18, 2026 at 12:06:19AM +0000, Nick Huang wrote:
> > >>> - Add "Overview" section explaining the slab allocator's role and purpose
> > >>> - Document the three main slab allocator implementations (SLAB, SLUB, SLOB)
> > >>
> > >> The fact you're insanely wrong about the current state of slab only makes this
> > >> worse.
> > >
> > > This is actually a new low. We've always had to contend with people
> > > putting up outdated or just wrong information on web pages, and there's
> > > little we can do about it. Witness all the outdated information about
> > > THP that's based on code that's been deleted for over a decade.
> > >
> > > But now we've got AI trained on all this wrong/ out of date information,
> > > and, er, "enthusiasts" who are trying to change the correct information
> > > in the kernel to match what the deluded AI "thinks" should be true.
> > >
> > > Let that sink in.
>
> Ugh ye gawds. My attitude is nip this in the bud early.
>
> I'm very harsh in response to these things for a reason - firstly, it's rude,
> obnoxious + disrespectful, so a negative response is wholly appropriate.
>
> But more importantly, I want to SET A PRECEDENT that if you send this crap
> you'll get a VERY negative response.
>
> Clueless but good faith or bad faith - it's straight up plagiarism and that's
> totally unacceptable.
>
> > >
> >
> > I think we should make it very clear that we don't want doc updates from someone
> > that is not a renowned expert in that area or wants to become an expert in that
> > area (and already discussed working on the docs with maintainers/experts).
> >
> > Otherwise we'll have this same discussion over and over again.
> >
> > diff --git a/Documentation/mm/index.rst b/Documentation/mm/index.rst
> > index 7aa2a88869083..8c5721001c8bb 100644
> > --- a/Documentation/mm/index.rst
> > +++ b/Documentation/mm/index.rst
> > @@ -7,6 +7,11 @@ of Linux. If you are looking for advice on simply allocating
> > memory,
> > see the :ref:`memory_allocation`. For controlling and tuning guides,
> > see the :doc:`admin guide <../admin-guide/mm/index>`.
> >
> > +A lot of documentation in this guide is still incomplete. If you are not
> > +a renowned expert in the specific area, but you want to contribute bigger
> > +chunks of documentation, talk to the respective MM experts first. LLM
> > +generated slop from non-experts will be rejected without further comments.
> > +
> > .. toctree::
> > :maxdepth: 1
> >
> >
> >
> > LLMs are just the tip of the iceberg. It will all be developmend-by review with
> > inexperienced contributors. And we are only willing to put in the effort to
> > teach contributors if the contributors are not actually worth our time: i.e.,
> > LLM kiddies that will actually stick around and help the subsystem in the long run.
> >
> >
> > The whole doc update stuff is similar to people just grepping for TODOs in the
> > kernel and then using an LLM to produce code they have no idea about.
> >
> > It's the evolution of typo fixes: review load without any benefit.
>
> Agree with all of that!
>
> Let's do that, happy to give tags on a patch for the above :)
>
> >
> > --
> > Cheers,
> >
> > David
> >
>
> Cheers, Lorenzo
Hi Lorenzo Stoakes
I am really sorry for causing trouble for everyone. I would like to
ask which aspect of mine was disrespectful, so that I can be more
careful next time.
If I want to make this kind of change, should I send an [RFC patch] to
ask for everyone's opinion?
Sorry, I really am not very clear about the process.
--
Regards,
Nick Huang
^ permalink raw reply
* Re: [PATCH V10 00/10] famfs: port into fuse
From: Gregory Price @ 2026-04-20 0:27 UTC (permalink / raw)
To: John Groves
Cc: David Hildenbrand (Arm), Darrick J. Wong, Miklos Szeredi,
Joanne Koong, Bernd Schubert, John Groves, Dan Williams,
Bernd Schubert, Alison Schofield, John Groves, Jonathan Corbet,
Shuah Khan, Vishal Verma, Dave Jiang, Matthew Wilcox, Jan Kara,
Alexander Viro, Christian Brauner, Randy Dunlap, Jeff Layton,
Amir Goldstein, Jonathan Cameron, Stefan Hajnoczi, Josef Bacik,
Bagas Sanjaya, Chen Linxuan, James Morse, Fuad Tabba,
Sean Christopherson, Shivank Garg, Ackerley Tng, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org, djbw
In-Reply-To: <aeUU8hMwPij2WvfF@groves.net>
On Sun, Apr 19, 2026 at 03:36:30PM -0500, John Groves wrote:
> On 26/04/15 10:16AM, David Hildenbrand (Arm) wrote:
> > On 4/15/26 00:20, Gregory Price wrote:
> > > On Tue, Apr 14, 2026 at 11:57:40AM -0700, Darrick J. Wong wrote:
>
> Gregory's code, in the current form, still uses two new fuse messages,
> GET_FMAP and GET_DAXDEV, but it makes the fmap message format opaque by
> removing fmap format structs from the uapi. It also uses two BPF programs.
> One BPF program parses and validates the GET_FMAP payload for every file,
> and hangs it from a 'void *' in each fuse_inode (just like the current famfs
> code). The other BPF program is called during vma faults and reads the
> fuse_inode->'void *' in order to handle faults the same way famfs-fuse does
> today, but via BPF instead.
>
I'll just lay out what i've done and why.
For John's sanity, if there are NACKs, knowing sooner rather than later
would be a kindness.
=== Problem: Any lookup() in iomap_begin() is too much overhead.
No dax-backed server will want to eat the cost of a lookup() that
could be multiple microseconds on what should be a 1-5us soft-fault.
Joanne's prototype had this:
meta = bpf_map_lookup_elem(&inode_map, &nodeid);
But it was offsetting a single pointer dereference:
struct fuse_inode *fi = get_fuse_inode(inode);
struct famfs_file_meta *meta = fi->famfs_meta;
Not all O(1) are created equal here.
A single L3 LLC miss plus page table walk can cost you ~100ns.
If that pointer was cache-hot, it's almost free.
A pointer chase through any structure is N x ~100ns.
This is unlikely to ever be sufficiently cache hot by comparison.
So, lets just avoid this problem altogether.
=== Requirements
1) No hard-coded OMF structures in the FUSE API.
While RAID0 style interleaving isn't exactly fancy or novel,
folks think this should not be in the kernel headers.
(I'm not going to argue, I think the argument is pointless)
2) imap_begin() needs metadata accessible on the order of a single
pointer dereference - which is what John has implemented.
3) open() needs to validate the metadata and identify DAX devices
a) it needs to validate the DAX devices are available and
acquire them / set them up / etc. This is a kernel-side op.
b) it needs to validate the addressing information is valid for
the relevant dax devices
Both GET_FMAP and GET_DAXDEV are avoided if the metadata is
already cached or the DAXDEV is already setup. So keeping these
separate is actually important.
Joanne's code deals with #1 - but it doesn't handle #2 or #3.
(It also doesn't handle GET_DAXDEV at all).
John's code mananges #2 and #3 by having the fuse-server pass meta data
on open() via GET_FMAP and GET_DAXDEV.
GET_FMAP acquires the meta data on how dax devices are used
GET_DAXDEV just translates an ID to specific dax device.
iomap_being() then uses the OMF to do the mapping.
But it does this by hard-coding the format into kernel headers.
=== Observation: Add a BPF dax_fmap_parse() on open()
Pair Joanne's suggestion with John's GET_FMAP/GET_DAXDEV operations.
struct fuse_dax_fmap_ops {
char name[FUSE_DAX_FMAP_OPS_NAME_LEN]; // 16 bytes
int (*dax_fmap_parse)(struct fuse_dax_fmap_parse_ctx *ctx);
int (*iomap_begin)(struct fuse_dax_fmap_resolve_ctx *ctx,
struct fuse_iomap_io *io);
};
This parse function is used to do filesystem specific setup the (such as
populate the dax bitmap) based on filesystem-specific per-file metadata.
In John's case, essentially all it does is populate the dax bitmap and
toss the data onto fi->dax_fmap.meta.
Pseudo code:
fuse_dax_fmap_open(inode):
fmap_size = send_GET_FMAP(inode, fmap_buf)
/* Make space to store the metadata */
meta_buf = kzalloc(meta_size)
ctx = { ... }
kern = { .ctx, .blob = blob, .meta_buf = meta_buf }
/* Parse the metadata: i.e. fill out the daxdev bitmap */
fc->dax_fmap_ops->dax_fmap_parse(&ctx)
/* Call GET_DAXDEV for any new dax devices */
resolve_dev_bitmap(ctx.dev_bitmap)
/* cache the meta data on the inode */
inode_lock()
fi->dax_fmap.meta = meta_buf
... etc etc ...
inode_unlock()
And otherwise, imap_begin() works exactly as Joanne proposed, but with
in-kernel cached data instead of the bpfmap.
const struct dax_simple_meta *meta = (const struct dax_simple_meta *)
bpf_fuse_dax_resolve_get_meta(ctx, 0, sizeof(*meta));
And since both parse() and iomap_begin() are bpf programs - and they're
the only consumers of the metadata - FUSE itself no longer needs to know
anything about the server's particular strategy to use the dax devices.
struct fuse_inode {
...
#if IS_ENABLED(CONFIG_FUSE_DAX_FMAP)
struct {
void *meta;
u32 meta_size;
u64 file_size;
} dax_fmap;
#endif
};
Just a big ol' honkin' void* that otherwise gets ignored.
(Note: while i'm not a BPF wizard, this pattern seems well established in
existing BPF code, i found code in the network stack that caches
data on kernel objects this way as well)
==== Caveats
1) We don't know the overhead BPF introduces in the fault path.
My napkin math (and best understanding of BPF) suggests:
1) trampoline / vtable for bpf ops (iomap_begin func)
2) retpoline cost of BPF (assuming this is on, safe assumption)
3) bpf_fuse_dax_resolve_get_meta() overhead (extra pointer deref)
This *should* (i think) amount to an extra pointer dereference, a longjump,
and a retpoline, which hopefully is <100ns since any extra pointer
derefs here SHOULD be cache-hot (hard to know).
It's not 0 overhead, and if the average fault time is 1us then every
additional 10ns not an insignificant cost.
But this is napkin math. John will collect data.
2) FUSE needs to be ok with the BPF-driven changes:
https://github.com/joannekoong/linux/commits/prototype_generic_iomap_dax/
3) FUSE needs to be ok with GET_FMAP/GET_DAXDEV as opaque meta-data
handlers for DAX devices.
That means there is no default parser or format. If you don't
register ops, these functions are functionally dead.
(probably fine to enforce during init, which is what i did)
4) As John said: MM needs to be good with it.
Any server using DAX like this already essentially has CAP_SYS_RAWIO
for DAX, and most likely some form of CAP_SYS_ADMIN.
Additionally, as folks have pointed out, the resolution to PTE is
bounded by dax device extents, so it's not entirely arbitrary.
===
As mentioned at the start - you'd be doing John a kindness if there are
clear and obvious NACK's to be had here.
~Gregory
^ permalink raw reply
* Re: [PATCH] Documentation: fix spelling mistake "Minumum" -> "Minimum"
From: Derek J. Clark @ 2026-04-19 22:24 UTC (permalink / raw)
To: Mark Pearson, Ninad Naik, Armin Wolf, Jonathan Corbet, skhan
Cc: platform-driver-x86@vger.kernel.org, linux-doc, linux-kernel, me,
linux-kernel-mentees
In-Reply-To: <b94cef14-d02d-4544-abb5-ead7db6eaa72@app.fastmail.com>
On April 19, 2026 3:10:08 PM PDT, Mark Pearson <mpearson-lenovo@squebb.ca> wrote:
>
>
>On Sun, Apr 19, 2026, at 1:08 PM, Ninad Naik wrote:
>> There is a spelling mistake in Documentation/wmi/devices/lenovo-wmi-other.rst.
>> Fixing it.
>>
>> Signed-off-by: Ninad Naik <ninadnaik07@gmail.com>
>> ---
>> Documentation/wmi/devices/lenovo-wmi-other.rst | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/Documentation/wmi/devices/lenovo-wmi-other.rst
>> b/Documentation/wmi/devices/lenovo-wmi-other.rst
>> index 01d471156738..1d0410500d3f 100644
>> --- a/Documentation/wmi/devices/lenovo-wmi-other.rst
>> +++ b/Documentation/wmi/devices/lenovo-wmi-other.rst
>> @@ -144,5 +144,5 @@ data using the `bmfdec
>> <https://github.com/pali/bmfdec>`_ utility:
>> [WmiDataId(1), read, Description("Mode.")] uint32 NumOfFans;
>> [WmiDataId(2), read, Description("Fan ID."),
>> WmiSizeIs("NumOfFans")] uint32 FanId[];
>> [WmiDataId(3), read, Description("Maximum Fan Speed."),
>> WmiSizeIs("NumOfFans")] uint32 FanMaxSpeed[];
>> - [WmiDataId(4), read, Description("Minumum Fan Speed."),
>> WmiSizeIs("NumOfFans")] uint32 FanMinSpeed[];
>> + [WmiDataId(4), read, Description("Minimum Fan Speed."),
>> WmiSizeIs("NumOfFans")] uint32 FanMinSpeed[];
>> };
>> --
>> 2.53.0
>Looks good.
>Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Hi gents,
The MOF spelling mistakes are well known. We've left them is as to ensure match with what the hardware actually reports.
See: https://lore.kernel.org/platform-driver-x86/cfd7977e-d612-4e08-a68a-65fed8e164b6@gmx.de
I suppose if we're going to continue getting these types or PR I should add a note to the documentation. I'll add that soon.
Thanks,
Derek
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox