diff mbox series

[v2] riscv: add tracepoints for page fault

Message ID 20240717082728.84401-1-zhuhengbo@iscas.ac.cn (mailing list archive)
State Changes Requested
Headers show
Series [v2] riscv: add tracepoints for page fault | expand

Checks

Context Check Description
conchuod/vmtest-for-next-PR success PR summary
conchuod/patch-1-test-1 success .github/scripts/patches/tests/build_rv32_defconfig.sh
conchuod/patch-1-test-2 success .github/scripts/patches/tests/build_rv64_clang_allmodconfig.sh
conchuod/patch-1-test-3 success .github/scripts/patches/tests/build_rv64_gcc_allmodconfig.sh
conchuod/patch-1-test-4 success .github/scripts/patches/tests/build_rv64_nommu_k210_defconfig.sh
conchuod/patch-1-test-5 success .github/scripts/patches/tests/build_rv64_nommu_virt_defconfig.sh
conchuod/patch-1-test-6 warning .github/scripts/patches/tests/checkpatch.sh
conchuod/patch-1-test-7 success .github/scripts/patches/tests/dtb_warn_rv64.sh
conchuod/patch-1-test-8 success .github/scripts/patches/tests/header_inline.sh
conchuod/patch-1-test-9 success .github/scripts/patches/tests/kdoc.sh
conchuod/patch-1-test-10 success .github/scripts/patches/tests/module_param.sh
conchuod/patch-1-test-11 success .github/scripts/patches/tests/verify_fixes.sh
conchuod/patch-1-test-12 success .github/scripts/patches/tests/verify_signedoff.sh

Commit Message

Zhu Hengbo July 17, 2024, 8:27 a.m. UTC
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

Comments

Matthew Wilcox July 17, 2024, 2:55 p.m. UTC | #1
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.
Zhu Hengbo July 18, 2024, 1:29 a.m. UTC | #2
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;
    }
Zhu Hengbo July 18, 2024, 1:34 a.m. UTC | #3
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
Jisheng Zhang July 20, 2024, 10:18 a.m. UTC | #4
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
Zhu Hengbo July 22, 2024, 3:21 a.m. UTC | #5
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
Zhu Hengbo July 22, 2024, 3:26 a.m. UTC | #6
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
diff mbox series

Patch

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;