arch/riscv/include/asm/trace/exceptions.h | 60 +++++++++++++++++++++++ arch/riscv/mm/fault.c | 15 ++++++ 2 files changed, 75 insertions(+) create mode 100644 arch/riscv/include/asm/trace/exceptions.h
Introduce page_fault_user and page_fault_kernel for riscv page fault.
Help to get more detail information when page fault happen.
---
Simple test go below:
root@riscv-ubuntu2204 ~ # bin/perf list | grep exceptions
exceptions:page_fault_kernel [Tracepoint event]
exceptions:page_fault_user [Tracepoint event]
root@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 826 [007] 894.795520: exceptions:page_fault_user: user page fault, address=0x7fff95af4400 cause=0xd
perf 826 [007] 894.795970: exceptions:page_fault_user: user page fault, address=0x7fff95a73400 cause=0xd
perf 826 [007] 894.796738: exceptions:page_fault_user: user page fault, address=0x7fff959f2400 cause=0xd
perf 826 [007] 894.797088: exceptions:page_fault_user: user page fault, address=0x7fff95971400 cause=0xd
perf 826 [007] 894.797273: exceptions:page_fault_user: user page fault, address=0x7fff958f0400 cause=0xd
perf 826 [007] 894.797445: exceptions:page_fault_user: user page fault, address=0x7fff9586f400 cause=0xd
perf 826 [007] 894.797998: exceptions:page_fault_kernel: kernel page fault, address=0x7fff95870000 cause=0xd
Signed-off-by: Zhu Hengbo <zhuhengbo@iscas.ac.cn>
---
arch/riscv/include/asm/trace/exceptions.h | 60 +++++++++++++++++++++++
arch/riscv/mm/fault.c | 15 ++++++
2 files changed, 75 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..a9a68d471703
--- /dev/null
+++ b/arch/riscv/include/asm/trace/exceptions.h
@@ -0,0 +1,60 @@
+/* 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, cause)
+ ),
+
+ TP_fast_assign(
+ __entry->address = regs->badaddr;
+ __entry->cause = regs->cause;
+ ),
+
+ TP_printk("user page fault, address=%ps cause=0x%lx",
+ (void *)__entry->address, __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, cause)
+ ),
+
+ TP_fast_assign(
+ __entry->address = regs->badaddr;
+ __entry->cause = regs->cause;
+ ),
+
+ TP_printk("kernel page fault, address=%ps cause=0x%lx",
+ (void *)__entry->address, __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
On Mon, Jul 15, 2024 at 10:13:55AM +0000, Zhu Hengbo wrote:
> Introduce page_fault_user and page_fault_kernel for riscv page fault.
> Help to get more detail information when page fault happen.
Why be different from x86?
TP_printk("address=%ps ip=%ps error_code=0x%lx",
(void *)__entry->address, (void *)__entry->ip,
__entry->error_code) );
adding the instruction pointer (ip) seems like it would be useful.
> + TP_printk("user page fault, address=%ps cause=0x%lx",
> + (void *)__entry->address, __entry->cause)
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@iscas.ac.cn>
---
Changes in v2:
- Add print instruction point info
Simple test go below:
root@riscv-ubuntu2204 ~ # bin/perf list | grep exceptions
exceptions:page_fault_kernel [Tracepoint event]
exceptions:page_fault_user [Tracepoint event]
root@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
On Wed, Jul 17, 2024 at 08:27:19AM +0000, Zhu Hengbo wrote:
> Introduce page_fault_user and page_fault_kernel for riscv page fault.
> Help to get more detail information when page fault happen.
Just curious what's the expected usage? The mm subsystem has supported
page faults perf software event, is it enough?
>
> Signed-off-by: Zhu Hengbo <zhuhengbo@iscas.ac.cn>
> ---
> Changes in v2:
> - Add print instruction point info
>
> Simple test go below:
>
> root@riscv-ubuntu2204 ~ # bin/perf list | grep exceptions
> exceptions:page_fault_kernel [Tracepoint event]
> exceptions:page_fault_user [Tracepoint event]
>
> root@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
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
On 2024/7/20 18:18, Jisheng Zhang wrote:
> On Wed, Jul 17, 2024 at 08:27:19AM +0000, Zhu Hengbo wrote:
>> Introduce page_fault_user and page_fault_kernel for riscv page fault.
>> Help to get more detail information when page fault happen.
> Just curious what's the expected usage? The mm subsystem has supported
> page faults perf software event, is it enough?
I think there will still be situations where we need to use debugfs for debugging in cases where perf is not available.
In fact, I am working to achieve parity in functionality for RISC-V with x86 and ARM.
In x86, there are both perf software events and tracepoints.
>> Signed-off-by: Zhu Hengbo <zhuhengbo@iscas.ac.cn>
>> ---
>> Changes in v2:
>> - Add print instruction point info
>>
>> Simple test go below:
>>
>> root@riscv-ubuntu2204 ~ # bin/perf list | grep exceptions
>> exceptions:page_fault_kernel [Tracepoint event]
>> exceptions:page_fault_user [Tracepoint event]
>>
>> root@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
>>
>>
>> _______________________________________________
>> linux-riscv mailing list
>> linux-riscv@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-riscv
On 2024/7/22 11:21, Zhu Hengbo wrote:
> On 2024/7/20 18:18, Jisheng Zhang wrote:
>> On Wed, Jul 17, 2024 at 08:27:19AM +0000, Zhu Hengbo wrote:
>>> Introduce page_fault_user and page_fault_kernel for riscv page fault.
>>> Help to get more detail information when page fault happen.
>> Just curious what's the expected usage? The mm subsystem has supported
>> page faults perf software event, is it enough?
>
> I think there will still be situations where we need to use debugfs for debugging in cases where perf is not available.
>
> In fact, I am working to achieve parity in functionality for RISC-V with x86 and ARM.
> In x86, there are both perf software events and tracepoints.
>
If this is not needed, that's fine too. Please let me know.
Thanks for your attention.
>>> Signed-off-by: Zhu Hengbo <zhuhengbo@iscas.ac.cn>
>>> ---
>>> Changes in v2:
>>> - Add print instruction point info
>>>
>>> Simple test go below:
>>>
>>> root@riscv-ubuntu2204 ~ # bin/perf list | grep exceptions
>>> exceptions:page_fault_kernel [Tracepoint event]
>>> exceptions:page_fault_user [Tracepoint event]
>>>
>>> root@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
>>>
>>>
>>> _______________________________________________
>>> linux-riscv mailing list
>>> linux-riscv@lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-riscv
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
On Wed, Jul 17, 2024 at 08:27:19AM +0000, Zhu Hengbo wrote:
> + 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)
What is "epc"? You've made this gratuitously different from x86.
Never do that. Always copy what somebody else has done unless you have
a good reason to be different.
On 2024/7/17 22:55, Matthew Wilcox wrote:
> On Wed, Jul 17, 2024 at 08:27:19AM +0000, Zhu Hengbo wrote:
>> + 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)
> What is "epc"? You've made this gratuitously different from x86.
> Never do that. Always copy what somebody else has done unless you have
> a good reason to be different.
Yes, I have referred to the implementation in x86, but the fields in “struct pt_regs” are quite different between RISC-V and x86
On 2024/7/17 22:55, Matthew Wilcox wrote:
> On Wed, Jul 17, 2024 at 08:27:19AM +0000, Zhu Hengbo wrote:
>> + 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)
> What is "epc"? You've made this gratuitously different from x86.
> Never do that. Always copy what somebody else has done unless you have
> a good reason to be different.
“epc” stands for Exception Program Counter, which keeps track of where the CPU is within the code. It is the same as the Instruction Pointer in x86.
For example, here is the encapsulation of accessing the instruction pointer in risc-v:
/* Helpers for working with the instruction pointer */
static inline unsigned long instruction_pointer(struct pt_regs *regs)
{
return regs->epc;
}
© 2016 - 2025 Red Hat, Inc.