aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/Kconfig2
-rw-r--r--arch/s390/include/uapi/asm/perf_regs.h27
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/perf_regs.c49
4 files changed, 79 insertions, 1 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 84767046daff..829c67986db7 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -159,6 +159,8 @@ config S390
159 select HAVE_KRETPROBES 159 select HAVE_KRETPROBES
160 select HAVE_KVM 160 select HAVE_KVM
161 select HAVE_LIVEPATCH 161 select HAVE_LIVEPATCH
162 select HAVE_PERF_REGS
163 select HAVE_PERF_USER_STACK_DUMP
162 select HAVE_MEMBLOCK 164 select HAVE_MEMBLOCK
163 select HAVE_MEMBLOCK_NODE_MAP 165 select HAVE_MEMBLOCK_NODE_MAP
164 select HAVE_MEMBLOCK_PHYS_MAP 166 select HAVE_MEMBLOCK_PHYS_MAP
diff --git a/arch/s390/include/uapi/asm/perf_regs.h b/arch/s390/include/uapi/asm/perf_regs.h
new file mode 100644
index 000000000000..f84ea6a181d3
--- /dev/null
+++ b/arch/s390/include/uapi/asm/perf_regs.h
@@ -0,0 +1,27 @@
1#ifndef _ASM_S390_PERF_REGS_H
2#define _ASM_S390_PERF_REGS_H
3
4enum perf_event_s390_regs {
5 PERF_REG_S390_R0,
6 PERF_REG_S390_R1,
7 PERF_REG_S390_R2,
8 PERF_REG_S390_R3,
9 PERF_REG_S390_R4,
10 PERF_REG_S390_R5,
11 PERF_REG_S390_R6,
12 PERF_REG_S390_R7,
13 PERF_REG_S390_R8,
14 PERF_REG_S390_R9,
15 PERF_REG_S390_R10,
16 PERF_REG_S390_R11,
17 PERF_REG_S390_R12,
18 PERF_REG_S390_R13,
19 PERF_REG_S390_R14,
20 PERF_REG_S390_R15,
21 PERF_REG_S390_MASK,
22 PERF_REG_S390_PC,
23
24 PERF_REG_S390_MAX
25};
26
27#endif /* _ASM_S390_PERF_REGS_H */
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 0319f4e81ea4..909bce65cb2b 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -79,7 +79,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
79obj-$(CONFIG_UPROBES) += uprobes.o 79obj-$(CONFIG_UPROBES) += uprobes.o
80 80
81obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o 81obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o
82obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o 82obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o
83 83
84obj-$(CONFIG_TRACEPOINTS) += trace.o 84obj-$(CONFIG_TRACEPOINTS) += trace.o
85 85
diff --git a/arch/s390/kernel/perf_regs.c b/arch/s390/kernel/perf_regs.c
new file mode 100644
index 000000000000..e883e6a2146a
--- /dev/null
+++ b/arch/s390/kernel/perf_regs.c
@@ -0,0 +1,49 @@
1#include <linux/perf_event.h>
2#include <linux/perf_regs.h>
3#include <linux/kernel.h>
4#include <linux/errno.h>
5#include <linux/bug.h>
6#include <asm/ptrace.h>
7
8u64 perf_reg_value(struct pt_regs *regs, int idx)
9{
10 if (WARN_ON_ONCE((u32)idx >= PERF_REG_S390_MAX))
11 return 0;
12
13 if (idx == PERF_REG_S390_MASK)
14 return regs->psw.mask;
15 if (idx == PERF_REG_S390_PC)
16 return regs->psw.addr;
17
18 return regs->gprs[idx];
19}
20
21#define REG_RESERVED (~((1UL << PERF_REG_S390_MAX) - 1))
22
23int perf_reg_validate(u64 mask)
24{
25 if (!mask || mask & REG_RESERVED)
26 return -EINVAL;
27
28 return 0;
29}
30
31u64 perf_reg_abi(struct task_struct *task)
32{
33 if (test_tsk_thread_flag(task, TIF_31BIT))
34 return PERF_SAMPLE_REGS_ABI_32;
35
36 return PERF_SAMPLE_REGS_ABI_64;
37}
38
39void perf_get_regs_user(struct perf_regs *regs_user,
40 struct pt_regs *regs,
41 struct pt_regs *regs_user_copy)
42{
43 /*
44 * Use the regs from the first interruption and let
45 * perf_sample_regs_intr() handle interrupts (regs == get_irq_regs()).
46 */
47 regs_user->regs = task_pt_regs(current);
48 regs_user->abi = perf_reg_abi(current);
49}