[PATCH v2 2/3] DO NOT MERGE: arm64: perf: Add skip_vmio parameter to control device memory callchain guard

Fredrik Markstrom fredrik.markstrom at est.tech
Thu Apr 30 03:55:14 PDT 2026


Reproducing the synchronous external abort that the device memory
guard prevents requires disabling the guard at runtime. Without
this, there is no way to verify the guard is actually needed or
to regression-test the crash path.

Add a module parameter (skip_vmio, default true) that controls
whether the guard is active. Set to 0 to disable it:
  Boot:    stacktrace.skip_vmio=0
  Runtime: echo 0 > /sys/module/stacktrace/parameters/skip_vmio

When disabled, perf follows frame pointers into device memory
regions, triggering a synchronous external abort and kernel panic
on arm64.

Assisted-by: Kiro:claude-opus-4.6 [kiro-cli]
Signed-off-by: Fredrik Markstrom <fredrik.markstrom at est.tech>
Reviewed-by: Ivar Holmqvist <ivar.holmqvist at est.tech>
Reviewed-by: Malin Jonsson <malin.jonsson at est.tech>
---
 arch/arm64/kernel/stacktrace.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 4a28df9bbe763ea7e88f02c1797bf0d4f1bbac2d..19b5251f214f2f6e083e55894ebaed84a3a4f585 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -11,6 +11,7 @@
 #include <linux/filter.h>
 #include <linux/ftrace.h>
 #include <linux/kprobes.h>
+#include <linux/moduleparam.h>
 #include <linux/pgtable.h>
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
@@ -123,6 +124,10 @@ static bool range_is_device_mem(unsigned long start, unsigned long size)
 	return false;
 }
 
+static bool skip_vmio = true;
+module_param_unsafe(skip_vmio, bool, 0600);
+MODULE_PARM_DESC(skip_vmio, "Skip device memory during user callchain unwinding");
+
 enum kunwind_source {
 	KUNWIND_SOURCE_UNKNOWN,
 	KUNWIND_SOURCE_FRAME,
@@ -627,7 +632,8 @@ unwind_user_frame(struct frame_tail __user *tail, void *cookie,
 	if (!access_ok(tail, sizeof(buftail)))
 		return NULL;
 
-	if (range_is_device_mem((unsigned long)tail, sizeof(buftail)))
+	if (READ_ONCE(skip_vmio) &&
+	    range_is_device_mem((unsigned long)tail, sizeof(buftail)))
 		return NULL;
 
 	pagefault_disable();
@@ -678,7 +684,8 @@ unwind_compat_user_frame(struct compat_frame_tail __user *tail, void *cookie,
 	if (!access_ok(tail, sizeof(buftail)))
 		return NULL;
 
-	if (range_is_device_mem((unsigned long)tail, sizeof(buftail)))
+	if (READ_ONCE(skip_vmio) &&
+	    range_is_device_mem((unsigned long)tail, sizeof(buftail)))
 		return NULL;
 
 	pagefault_disable();

-- 
2.51.0




More information about the linux-arm-kernel mailing list