Re: [PATCH v2] riscv: add tracepoints for page fault

From: Jisheng Zhang
Date: Sat Jul 20 2024 - 06:32:54 EST


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@xxxxxxxxxxx>
> ---
> 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@xxxxxxxxxxxxxxxxxxx
> http://lists.infradead.org/mailman/listinfo/linux-riscv