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 <[email protected]>
Reviewed-by: Ivar Holmqvist <[email protected]>
Reviewed-by: Malin Jonsson <[email protected]>
---
 arch/arm64/kernel/stacktrace.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 
6426a307b8f86ae756ea444247ae329591a89b4b..ebe909012e4edee7bb1ddbebac2d3c49bdb91665
 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>
@@ -112,6 +113,10 @@ static bool addr_is_device_mem(unsigned long addr)
 #endif
 }
 
+static bool skip_vmio = true;
+module_param(skip_vmio, bool, 0644);
+MODULE_PARM_DESC(skip_vmio, "Skip device memory during user callchain 
unwinding");
+
 enum kunwind_source {
        KUNWIND_SOURCE_UNKNOWN,
        KUNWIND_SOURCE_FRAME,
@@ -616,7 +621,7 @@ unwind_user_frame(struct frame_tail __user *tail, void 
*cookie,
        if (!access_ok(tail, sizeof(buftail)))
                return NULL;
 
-       if (addr_is_device_mem((unsigned long)tail))
+       if (READ_ONCE(skip_vmio) && addr_is_device_mem((unsigned long)tail))
                return NULL;
 
        pagefault_disable();
@@ -667,7 +672,7 @@ unwind_compat_user_frame(struct compat_frame_tail __user 
*tail, void *cookie,
        if (!access_ok(tail, sizeof(buftail)))
                return NULL;
 
-       if (addr_is_device_mem((unsigned long)tail))
+       if (READ_ONCE(skip_vmio) && addr_is_device_mem((unsigned long)tail))
                return NULL;
 
        pagefault_disable();

-- 
2.51.0


Reply via email to