Commit 98a93b0b authored by Mao Han's avatar Mao Han Committed by Paul Walmsley
Browse files

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: default avatarMao 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: default avatarGreentime Hu <greentime.hu@sifive.com>
[paul.walmsley@sifive.com: minor patch description fix]
Signed-off-by: default avatarPaul Walmsley <paul.walmsley@sifive.com>
parent dbeb90b0
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
+42 −0
Original line number Diff line number Diff line
/* 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 */
+1 −0
Original line number Diff line number Diff line
@@ -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:
+44 −0
Original line number Diff line number Diff line
// 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);
}