[PATCH] riscv: add tracepoints for page fault

Zhu Hengbo posted 1 patch 1 year, 5 months ago
There is a newer version of this series
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
[PATCH] riscv: add tracepoints for page fault
Posted by Zhu Hengbo 1 year, 5 months ago
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
Re: [PATCH] riscv: add tracepoints for page fault
Posted by Matthew Wilcox 1 year, 5 months ago
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)
[PATCH v2] riscv: add tracepoints for page fault
Posted by Zhu Hengbo 1 year, 5 months ago
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
Re: [PATCH v2] riscv: add tracepoints for page fault
Posted by Jisheng Zhang 1 year, 5 months ago
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
Re: [PATCH v2] riscv: add tracepoints for page fault
Posted by Zhu Hengbo 1 year, 4 months ago
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
Re: [PATCH v2] riscv: add tracepoints for page fault
Posted by Zhu Hengbo 1 year, 4 months ago
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
Re: [PATCH v2] riscv: add tracepoints for page fault
Posted by Matthew Wilcox 1 year, 5 months ago
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.
Re: [PATCH v2] riscv: add tracepoints for page fault
Posted by Zhu Hengbo 1 year, 5 months ago
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

Re: [PATCH v2] riscv: add tracepoints for page fault
Posted by Zhu Hengbo 1 year, 5 months ago
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;
    }