riscv: Add support for perf registers sampling
This patch implements the perf registers sampling and validation API for the riscv arch. The valid registers and their register ID are defined in perf_regs.h. Perf tool can backtrace in userspace with unwind library and the registers/user stack dump support. Signed-off-by: Mao Han <han_mao@c-sky.com> Cc: Paul Walmsley <paul.walmsley@sifive.com> Cc: Greentime Hu <green.hu@gmail.com> Cc: Palmer Dabbelt <palmer@sifive.com> Cc: linux-riscv <linux-riscv@lists.infradead.org> Cc: Christoph Hellwig <hch@lst.de> Cc: Guo Ren <guoren@kernel.org> Tested-by: Greentime Hu <greentime.hu@sifive.com> [paul.walmsley@sifive.com: minor patch description fix] Signed-off-by: Paul Walmsley <paul.walmsley@sifive.com>
This commit is contained in:
parent
dbeb90b0c1
commit
98a93b0b56
|
@ -35,6 +35,8 @@ config RISCV
|
|||
select HAVE_DMA_CONTIGUOUS
|
||||
select HAVE_FUTEX_CMPXCHG if FUTEX
|
||||
select HAVE_PERF_EVENTS
|
||||
select HAVE_PERF_REGS
|
||||
select HAVE_PERF_USER_STACK_DUMP
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
select IRQ_DOMAIN
|
||||
select SPARSE_IRQ
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. */
|
||||
|
||||
#ifndef _ASM_RISCV_PERF_REGS_H
|
||||
#define _ASM_RISCV_PERF_REGS_H
|
||||
|
||||
enum perf_event_riscv_regs {
|
||||
PERF_REG_RISCV_PC,
|
||||
PERF_REG_RISCV_RA,
|
||||
PERF_REG_RISCV_SP,
|
||||
PERF_REG_RISCV_GP,
|
||||
PERF_REG_RISCV_TP,
|
||||
PERF_REG_RISCV_T0,
|
||||
PERF_REG_RISCV_T1,
|
||||
PERF_REG_RISCV_T2,
|
||||
PERF_REG_RISCV_S0,
|
||||
PERF_REG_RISCV_S1,
|
||||
PERF_REG_RISCV_A0,
|
||||
PERF_REG_RISCV_A1,
|
||||
PERF_REG_RISCV_A2,
|
||||
PERF_REG_RISCV_A3,
|
||||
PERF_REG_RISCV_A4,
|
||||
PERF_REG_RISCV_A5,
|
||||
PERF_REG_RISCV_A6,
|
||||
PERF_REG_RISCV_A7,
|
||||
PERF_REG_RISCV_S2,
|
||||
PERF_REG_RISCV_S3,
|
||||
PERF_REG_RISCV_S4,
|
||||
PERF_REG_RISCV_S5,
|
||||
PERF_REG_RISCV_S6,
|
||||
PERF_REG_RISCV_S7,
|
||||
PERF_REG_RISCV_S8,
|
||||
PERF_REG_RISCV_S9,
|
||||
PERF_REG_RISCV_S10,
|
||||
PERF_REG_RISCV_S11,
|
||||
PERF_REG_RISCV_T3,
|
||||
PERF_REG_RISCV_T4,
|
||||
PERF_REG_RISCV_T5,
|
||||
PERF_REG_RISCV_T6,
|
||||
PERF_REG_RISCV_MAX,
|
||||
};
|
||||
#endif /* _ASM_RISCV_PERF_REGS_H */
|
|
@ -40,5 +40,6 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
|
|||
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
|
||||
obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o
|
||||
|
||||
clean:
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. */
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/bug.h>
|
||||
#include <asm/perf_regs.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
u64 perf_reg_value(struct pt_regs *regs, int idx)
|
||||
{
|
||||
if (WARN_ON_ONCE((u32)idx >= PERF_REG_RISCV_MAX))
|
||||
return 0;
|
||||
|
||||
return ((unsigned long *)regs)[idx];
|
||||
}
|
||||
|
||||
#define REG_RESERVED (~((1ULL << PERF_REG_RISCV_MAX) - 1))
|
||||
|
||||
int perf_reg_validate(u64 mask)
|
||||
{
|
||||
if (!mask || mask & REG_RESERVED)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 perf_reg_abi(struct task_struct *task)
|
||||
{
|
||||
#if __riscv_xlen == 64
|
||||
return PERF_SAMPLE_REGS_ABI_64;
|
||||
#else
|
||||
return PERF_SAMPLE_REGS_ABI_32;
|
||||
#endif
|
||||
}
|
||||
|
||||
void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy)
|
||||
{
|
||||
regs_user->regs = task_pt_regs(current);
|
||||
regs_user->abi = perf_reg_abi(current);
|
||||
}
|
Loading…
Reference in New Issue