diff options
-rw-r--r-- | arch/s390/Kconfig | 2 | ||||
-rw-r--r-- | arch/s390/include/uapi/asm/perf_regs.h | 27 | ||||
-rw-r--r-- | arch/s390/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/kernel/perf_regs.c | 49 |
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 | |||
4 | enum 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 | |||
79 | obj-$(CONFIG_UPROBES) += uprobes.o | 79 | obj-$(CONFIG_UPROBES) += uprobes.o |
80 | 80 | ||
81 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o | 81 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o |
82 | obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o | 82 | obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o |
83 | 83 | ||
84 | obj-$(CONFIG_TRACEPOINTS) += trace.o | 84 | obj-$(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 | |||
8 | u64 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 | |||
23 | int perf_reg_validate(u64 mask) | ||
24 | { | ||
25 | if (!mask || mask & REG_RESERVED) | ||
26 | return -EINVAL; | ||
27 | |||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | u64 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 | |||
39 | void 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 | } | ||