mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 15:03:52 +08:00
parisc: Add initial kernel-side perf_event support
Signed-off-by: Helge Deller <deller@gmx.de>
This commit is contained in:
@@ -31,6 +31,9 @@ config PARISC
|
||||
select HAVE_KERNEL_UNCOMPRESSED
|
||||
select HAVE_PCI
|
||||
select HAVE_PERF_EVENTS
|
||||
select HAVE_PERF_REGS
|
||||
select HAVE_PERF_USER_STACK_DUMP
|
||||
select PERF_USE_VMALLOC
|
||||
select HAVE_KERNEL_BZIP2
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_KERNEL_LZ4
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
#ifndef __ASM_PARISC_PERF_EVENT_H
|
||||
#define __ASM_PARISC_PERF_EVENT_H
|
||||
|
||||
/* Empty, just to avoid compiling error */
|
||||
#include <asm/psw.h>
|
||||
|
||||
#define perf_arch_fetch_caller_regs(regs, __ip) { \
|
||||
(regs)->gr[0] = KERNEL_PSW; \
|
||||
(regs)->iaoq[0] = (__ip); \
|
||||
asm volatile("copy %%sp, %0\n":"=r"((regs)->gr[30])); \
|
||||
}
|
||||
|
||||
#endif /* __ASM_PARISC_PERF_EVENT_H */
|
||||
|
||||
63
arch/parisc/include/uapi/asm/perf_regs.h
Normal file
63
arch/parisc/include/uapi/asm/perf_regs.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_ASM_PARISC_PERF_REGS_H
|
||||
#define _UAPI_ASM_PARISC_PERF_REGS_H
|
||||
|
||||
/* see struct user_regs_struct */
|
||||
enum perf_event_parisc_regs {
|
||||
PERF_REG_PARISC_R0, /* PSW is in gr[0] */
|
||||
PERF_REG_PARISC_R1,
|
||||
PERF_REG_PARISC_R2,
|
||||
PERF_REG_PARISC_R3,
|
||||
PERF_REG_PARISC_R4,
|
||||
PERF_REG_PARISC_R5,
|
||||
PERF_REG_PARISC_R6,
|
||||
PERF_REG_PARISC_R7,
|
||||
PERF_REG_PARISC_R8,
|
||||
PERF_REG_PARISC_R9,
|
||||
PERF_REG_PARISC_R10,
|
||||
PERF_REG_PARISC_R11,
|
||||
PERF_REG_PARISC_R12,
|
||||
PERF_REG_PARISC_R13,
|
||||
PERF_REG_PARISC_R14,
|
||||
PERF_REG_PARISC_R15,
|
||||
PERF_REG_PARISC_R16,
|
||||
PERF_REG_PARISC_R17,
|
||||
PERF_REG_PARISC_R18,
|
||||
PERF_REG_PARISC_R19,
|
||||
PERF_REG_PARISC_R20,
|
||||
PERF_REG_PARISC_R21,
|
||||
PERF_REG_PARISC_R22,
|
||||
PERF_REG_PARISC_R23,
|
||||
PERF_REG_PARISC_R24,
|
||||
PERF_REG_PARISC_R25,
|
||||
PERF_REG_PARISC_R26,
|
||||
PERF_REG_PARISC_R27,
|
||||
PERF_REG_PARISC_R28,
|
||||
PERF_REG_PARISC_R29,
|
||||
PERF_REG_PARISC_R30,
|
||||
PERF_REG_PARISC_R31,
|
||||
|
||||
PERF_REG_PARISC_SR0,
|
||||
PERF_REG_PARISC_SR1,
|
||||
PERF_REG_PARISC_SR2,
|
||||
PERF_REG_PARISC_SR3,
|
||||
PERF_REG_PARISC_SR4,
|
||||
PERF_REG_PARISC_SR5,
|
||||
PERF_REG_PARISC_SR6,
|
||||
PERF_REG_PARISC_SR7,
|
||||
|
||||
PERF_REG_PARISC_IAOQ0,
|
||||
PERF_REG_PARISC_IAOQ1,
|
||||
PERF_REG_PARISC_IASQ0,
|
||||
PERF_REG_PARISC_IASQ1,
|
||||
|
||||
PERF_REG_PARISC_SAR, /* CR11 */
|
||||
PERF_REG_PARISC_IIR, /* CR19 */
|
||||
PERF_REG_PARISC_ISR, /* CR20 */
|
||||
PERF_REG_PARISC_IOR, /* CR21 */
|
||||
PERF_REG_PARISC_IPSW, /* CR22 */
|
||||
|
||||
PERF_REG_PARISC_MAX
|
||||
};
|
||||
|
||||
#endif /* _UAPI_ASM_PARISC_PERF_REGS_H */
|
||||
@@ -38,6 +38,7 @@ obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += topology.o
|
||||
obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o
|
||||
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
|
||||
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_regs.o
|
||||
obj-$(CONFIG_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o
|
||||
obj-$(CONFIG_KEXEC_CORE) += kexec.o relocate_kernel.o
|
||||
|
||||
27
arch/parisc/kernel/perf_event.c
Normal file
27
arch/parisc/kernel/perf_event.c
Normal file
@@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Performance event support for parisc
|
||||
*
|
||||
* Copyright (C) 2025 by Helge Deller <deller@gmx.de>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <asm/unwind.h>
|
||||
|
||||
void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
|
||||
struct unwind_frame_info info;
|
||||
|
||||
unwind_frame_init_task(&info, current, NULL);
|
||||
while (1) {
|
||||
if (unwind_once(&info) < 0 || info.ip == 0)
|
||||
break;
|
||||
|
||||
if (!__kernel_text_address(info.ip) ||
|
||||
perf_callchain_store(entry, info.ip))
|
||||
return;
|
||||
}
|
||||
}
|
||||
61
arch/parisc/kernel/perf_regs.c
Normal file
61
arch/parisc/kernel/perf_regs.c
Normal file
@@ -0,0 +1,61 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
/* Copyright (C) 2025 by Helge Deller <deller@gmx.de> */
|
||||
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/perf_regs.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
u64 perf_reg_value(struct pt_regs *regs, int idx)
|
||||
{
|
||||
switch (idx) {
|
||||
case PERF_REG_PARISC_R0 ... PERF_REG_PARISC_R31:
|
||||
return regs->gr[idx - PERF_REG_PARISC_R0];
|
||||
case PERF_REG_PARISC_SR0 ... PERF_REG_PARISC_SR7:
|
||||
return regs->sr[idx - PERF_REG_PARISC_SR0];
|
||||
case PERF_REG_PARISC_IASQ0 ... PERF_REG_PARISC_IASQ1:
|
||||
return regs->iasq[idx - PERF_REG_PARISC_IASQ0];
|
||||
case PERF_REG_PARISC_IAOQ0 ... PERF_REG_PARISC_IAOQ1:
|
||||
return regs->iasq[idx - PERF_REG_PARISC_IAOQ0];
|
||||
case PERF_REG_PARISC_SAR: /* CR11 */
|
||||
return regs->sar;
|
||||
case PERF_REG_PARISC_IIR: /* CR19 */
|
||||
return regs->iir;
|
||||
case PERF_REG_PARISC_ISR: /* CR20 */
|
||||
return regs->isr;
|
||||
case PERF_REG_PARISC_IOR: /* CR21 */
|
||||
return regs->ior;
|
||||
case PERF_REG_PARISC_IPSW: /* CR22 */
|
||||
return regs->ipsw;
|
||||
};
|
||||
WARN_ON_ONCE((u32)idx >= PERF_REG_PARISC_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define REG_RESERVED (~((1ULL << PERF_REG_PARISC_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 (!IS_ENABLED(CONFIG_64BIT))
|
||||
return PERF_SAMPLE_REGS_ABI_32;
|
||||
|
||||
if (test_tsk_thread_flag(task, TIF_32BIT))
|
||||
return PERF_SAMPLE_REGS_ABI_32;
|
||||
|
||||
return PERF_SAMPLE_REGS_ABI_64;
|
||||
}
|
||||
|
||||
void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
regs_user->regs = task_pt_regs(current);
|
||||
regs_user->abi = perf_reg_abi(current);
|
||||
}
|
||||
Reference in New Issue
Block a user