[PATCH v2] riscv: add tracepoints for page fault
Zhu Hengbo
zhuhengbo at iscas.ac.cn
Wed Jul 17 01:27:19 PDT 2024
Introduce page_fault_user and page_fault_kernel for riscv page fault.
Help to get more detail information when page fault happen.
Signed-off-by: Zhu Hengbo <zhuhengbo at iscas.ac.cn>
---
Changes in v2:
- Add print instruction point info
Simple test go below:
root at riscv-ubuntu2204 ~ # bin/perf list | grep exceptions
exceptions:page_fault_kernel [Tracepoint event]
exceptions:page_fault_user [Tracepoint event]
root at riscv-ubuntu2204 ~ # bin/perf record -e exceptions:page_fault_kernel -e exceptions:page_fault_user
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.091 MB perf.data (19 samples) ]
perf report tracepoint:
perf 563 [007] 115.824363: exceptions:page_fault_user: user page fault, address=0x7fff94cf6400 epc=0x55558632808e cause=0xd
perf 563 [007] 115.824441: exceptions:page_fault_user: user page fault, address=0x7fff94c75400 epc=0x55558632808e cause=0xd
perf 563 [007] 115.824518: exceptions:page_fault_user: user page fault, address=0x7fff94bf4400 epc=0x55558632808e cause=0xd
perf 563 [007] 115.824907: exceptions:page_fault_kernel: kernel page fault, address=0x7fff94bf5000 epc=fault_in_readable cause=0xd
perf 563 [007] 115.825238: exceptions:page_fault_user: user page fault, address=0x7fff94bf4408 epc=0x5555863281bc cause=0xf
perf 564 [000] 116.247999: exceptions:page_fault_user: user page fault, address=0x7fff94b73400 epc=0x55558632808e cause=0xd
perf 564 [000] 116.248558: exceptions:page_fault_user: user page fault, address=0x7fff94af2400 epc=0x55558632808e cause=0xd
---
arch/riscv/include/asm/trace/exceptions.h | 66 +++++++++++++++++++++++
arch/riscv/mm/fault.c | 15 ++++++
2 files changed, 81 insertions(+)
create mode 100644 arch/riscv/include/asm/trace/exceptions.h
diff --git a/arch/riscv/include/asm/trace/exceptions.h b/arch/riscv/include/asm/trace/exceptions.h
new file mode 100644
index 000000000000..ff258da2f45f
--- /dev/null
+++ b/arch/riscv/include/asm/trace/exceptions.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Tracepoints for RISC-V exceptions
+ *
+ * Copyright (C) 2024 ISCAS. All rights reserved
+ *
+ */
+
+#if !defined(_TRACE_PAGE_FAULT_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_PAGE_FAULT_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM exceptions
+
+TRACE_EVENT(page_fault_user,
+ TP_PROTO(struct pt_regs *regs),
+ TP_ARGS(regs),
+
+ TP_STRUCT__entry(
+ __field(unsigned long, address)
+ __field(unsigned long, epc)
+ __field(unsigned long, cause)
+ ),
+
+ TP_fast_assign(
+ __entry->address = regs->badaddr;
+ __entry->epc = regs->epc;
+ __entry->cause = regs->cause;
+ ),
+
+ TP_printk("user page fault, address=%ps epc=%ps cause=0x%lx",
+ (void *)__entry->address, (void *)__entry->epc,
+ __entry->cause)
+);
+
+TRACE_EVENT(page_fault_kernel,
+ TP_PROTO(struct pt_regs *regs),
+ TP_ARGS(regs),
+
+ TP_STRUCT__entry(
+ __field(unsigned long, address)
+ __field(unsigned long, epc)
+ __field(unsigned long, cause)
+ ),
+
+ TP_fast_assign(
+ __entry->address = regs->badaddr;
+ __entry->epc = regs->epc;
+ __entry->cause = regs->cause;
+ ),
+
+ TP_printk("kernel page fault, address=%ps epc=%ps cause=0x%lx",
+ (void *)__entry->address, (void *)__entry->epc,
+ __entry->cause)
+);
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH asm/trace/
+#define TRACE_INCLUDE_FILE exceptions
+#endif /* _TRACE_PAGE_FAULT_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c
index 5224f3733802..22874074c5bc 100644
--- a/arch/riscv/mm/fault.c
+++ b/arch/riscv/mm/fault.c
@@ -22,6 +22,10 @@
#include "../kernel/head.h"
+
+#define CREATE_TRACE_POINTS
+#include <asm/trace/exceptions.h>
+
static void die_kernel_fault(const char *msg, unsigned long addr,
struct pt_regs *regs)
{
@@ -215,6 +219,15 @@ static inline bool access_error(unsigned long cause, struct vm_area_struct *vma)
return false;
}
+
+static inline void trace_page_fault(struct pt_regs *regs)
+{
+ if (user_mode(regs))
+ trace_page_fault_user(regs);
+ else
+ trace_page_fault_kernel(regs);
+}
+
/*
* This routine handles page faults. It determines the address and the
* problem, and then passes it off to one of the appropriate routines.
@@ -235,6 +248,8 @@ void handle_page_fault(struct pt_regs *regs)
tsk = current;
mm = tsk->mm;
+ trace_page_fault(regs);
+
if (kprobe_page_fault(regs, cause))
return;
--
2.34.1
More information about the linux-riscv
mailing list