aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/cpu_mf.h4
-rw-r--r--arch/s390/include/asm/irq.h1
-rw-r--r--arch/s390/include/asm/processor.h4
-rw-r--r--arch/s390/include/asm/ptrace.h4
-rw-r--r--arch/s390/include/asm/runtime_instr.h98
-rw-r--r--arch/s390/include/asm/switch_to.h2
-rw-r--r--arch/s390/include/asm/unistd.h3
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/compat_wrapper.S5
-rw-r--r--arch/s390/kernel/dis.c21
-rw-r--r--arch/s390/kernel/irq.c1
-rw-r--r--arch/s390/kernel/process.c7
-rw-r--r--arch/s390/kernel/runtime_instr.c150
-rw-r--r--arch/s390/kernel/syscalls.S1
14 files changed, 300 insertions, 3 deletions
diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h
index a3afecdae145..35f0020b7ba7 100644
--- a/arch/s390/include/asm/cpu_mf.h
+++ b/arch/s390/include/asm/cpu_mf.h
@@ -21,11 +21,15 @@
21#define CPU_MF_INT_SF_LSDA (1 << 22) /* loss of sample data alert */ 21#define CPU_MF_INT_SF_LSDA (1 << 22) /* loss of sample data alert */
22#define CPU_MF_INT_CF_CACA (1 << 7) /* counter auth. change alert */ 22#define CPU_MF_INT_CF_CACA (1 << 7) /* counter auth. change alert */
23#define CPU_MF_INT_CF_LCDA (1 << 6) /* loss of counter data alert */ 23#define CPU_MF_INT_CF_LCDA (1 << 6) /* loss of counter data alert */
24#define CPU_MF_INT_RI_HALTED (1 << 5) /* run-time instr. halted */
25#define CPU_MF_INT_RI_BUF_FULL (1 << 4) /* run-time instr. program
26 buffer full */
24 27
25#define CPU_MF_INT_CF_MASK (CPU_MF_INT_CF_CACA|CPU_MF_INT_CF_LCDA) 28#define CPU_MF_INT_CF_MASK (CPU_MF_INT_CF_CACA|CPU_MF_INT_CF_LCDA)
26#define CPU_MF_INT_SF_MASK (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE| \ 29#define CPU_MF_INT_SF_MASK (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE| \
27 CPU_MF_INT_SF_PRA|CPU_MF_INT_SF_SACA| \ 30 CPU_MF_INT_SF_PRA|CPU_MF_INT_SF_SACA| \
28 CPU_MF_INT_SF_LSDA) 31 CPU_MF_INT_SF_LSDA)
32#define CPU_MF_INT_RI_MASK (CPU_MF_INT_RI_HALTED|CPU_MF_INT_RI_BUF_FULL)
29 33
30/* CPU measurement facility support */ 34/* CPU measurement facility support */
31static inline int cpum_cf_avail(void) 35static inline int cpum_cf_avail(void)
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h
index 33cc59071581..6703dd986fd4 100644
--- a/arch/s390/include/asm/irq.h
+++ b/arch/s390/include/asm/irq.h
@@ -19,6 +19,7 @@ enum interruption_class {
19 EXTINT_IUC, 19 EXTINT_IUC,
20 EXTINT_CMS, 20 EXTINT_CMS,
21 EXTINT_CMC, 21 EXTINT_CMC,
22 EXTINT_CMR,
22 IOINT_CIO, 23 IOINT_CIO,
23 IOINT_QAI, 24 IOINT_QAI,
24 IOINT_DAS, 25 IOINT_DAS,
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index d4477ba99a16..0fff583d2c7c 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -17,6 +17,7 @@
17#include <asm/page.h> 17#include <asm/page.h>
18#include <asm/ptrace.h> 18#include <asm/ptrace.h>
19#include <asm/setup.h> 19#include <asm/setup.h>
20#include <asm/runtime_instr.h>
20 21
21/* 22/*
22 * Default implementation of macro that returns current 23 * Default implementation of macro that returns current
@@ -78,6 +79,9 @@ struct thread_struct {
78 /* pfault_wait is used to block the process on a pfault event */ 79 /* pfault_wait is used to block the process on a pfault event */
79 unsigned long pfault_wait; 80 unsigned long pfault_wait;
80 struct list_head list; 81 struct list_head list;
82 /* cpu runtime instrumentation */
83 struct runtime_instr_cb *ri_cb;
84 int ri_signum;
81}; 85};
82 86
83typedef struct thread_struct thread_struct; 87typedef struct thread_struct thread_struct;
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index d5f08ea566ed..5c32bae6b760 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -235,6 +235,7 @@ typedef struct
235#define PSW_MASK_ASC 0x0000C000UL 235#define PSW_MASK_ASC 0x0000C000UL
236#define PSW_MASK_CC 0x00003000UL 236#define PSW_MASK_CC 0x00003000UL
237#define PSW_MASK_PM 0x00000F00UL 237#define PSW_MASK_PM 0x00000F00UL
238#define PSW_MASK_RI 0x00000000UL
238#define PSW_MASK_EA 0x00000000UL 239#define PSW_MASK_EA 0x00000000UL
239#define PSW_MASK_BA 0x00000000UL 240#define PSW_MASK_BA 0x00000000UL
240 241
@@ -264,10 +265,11 @@ typedef struct
264#define PSW_MASK_ASC 0x0000C00000000000UL 265#define PSW_MASK_ASC 0x0000C00000000000UL
265#define PSW_MASK_CC 0x0000300000000000UL 266#define PSW_MASK_CC 0x0000300000000000UL
266#define PSW_MASK_PM 0x00000F0000000000UL 267#define PSW_MASK_PM 0x00000F0000000000UL
268#define PSW_MASK_RI 0x0000008000000000UL
267#define PSW_MASK_EA 0x0000000100000000UL 269#define PSW_MASK_EA 0x0000000100000000UL
268#define PSW_MASK_BA 0x0000000080000000UL 270#define PSW_MASK_BA 0x0000000080000000UL
269 271
270#define PSW_MASK_USER 0x00003F0180000000UL 272#define PSW_MASK_USER 0x00003F8180000000UL
271 273
272#define PSW_ADDR_AMODE 0x0000000000000000UL 274#define PSW_ADDR_AMODE 0x0000000000000000UL
273#define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL 275#define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL
diff --git a/arch/s390/include/asm/runtime_instr.h b/arch/s390/include/asm/runtime_instr.h
new file mode 100644
index 000000000000..830da737ff85
--- /dev/null
+++ b/arch/s390/include/asm/runtime_instr.h
@@ -0,0 +1,98 @@
1#ifndef _RUNTIME_INSTR_H
2#define _RUNTIME_INSTR_H
3
4#define S390_RUNTIME_INSTR_START 0x1
5#define S390_RUNTIME_INSTR_STOP 0x2
6
7struct runtime_instr_cb {
8 __u64 buf_current;
9 __u64 buf_origin;
10 __u64 buf_limit;
11
12 __u32 valid : 1;
13 __u32 pstate : 1;
14 __u32 pstate_set_buf : 1;
15 __u32 home_space : 1;
16 __u32 altered : 1;
17 __u32 : 3;
18 __u32 pstate_sample : 1;
19 __u32 sstate_sample : 1;
20 __u32 pstate_collect : 1;
21 __u32 sstate_collect : 1;
22 __u32 : 1;
23 __u32 halted_int : 1;
24 __u32 int_requested : 1;
25 __u32 buffer_full_int : 1;
26 __u32 key : 4;
27 __u32 : 9;
28 __u32 rgs : 3;
29
30 __u32 mode : 4;
31 __u32 next : 1;
32 __u32 mae : 1;
33 __u32 : 2;
34 __u32 call_type_br : 1;
35 __u32 return_type_br : 1;
36 __u32 other_type_br : 1;
37 __u32 bc_other_type : 1;
38 __u32 emit : 1;
39 __u32 tx_abort : 1;
40 __u32 : 2;
41 __u32 bp_xn : 1;
42 __u32 bp_xt : 1;
43 __u32 bp_ti : 1;
44 __u32 bp_ni : 1;
45 __u32 suppr_y : 1;
46 __u32 suppr_z : 1;
47
48 __u32 dc_miss_extra : 1;
49 __u32 lat_lev_ignore : 1;
50 __u32 ic_lat_lev : 4;
51 __u32 dc_lat_lev : 4;
52
53 __u64 reserved1;
54 __u64 scaling_factor;
55 __u64 rsic;
56 __u64 reserved2;
57} __packed __aligned(8);
58
59extern struct runtime_instr_cb runtime_instr_empty_cb;
60
61static inline void load_runtime_instr_cb(struct runtime_instr_cb *cb)
62{
63 asm volatile(".insn rsy,0xeb0000000060,0,0,%0" /* LRIC */
64 : : "Q" (*cb));
65}
66
67static inline void store_runtime_instr_cb(struct runtime_instr_cb *cb)
68{
69 asm volatile(".insn rsy,0xeb0000000061,0,0,%0" /* STRIC */
70 : "=Q" (*cb) : : "cc");
71}
72
73static inline void save_ri_cb(struct runtime_instr_cb *cb_prev)
74{
75#ifdef CONFIG_64BIT
76 if (cb_prev)
77 store_runtime_instr_cb(cb_prev);
78#endif
79}
80
81static inline void restore_ri_cb(struct runtime_instr_cb *cb_next,
82 struct runtime_instr_cb *cb_prev)
83{
84#ifdef CONFIG_64BIT
85 if (cb_next)
86 load_runtime_instr_cb(cb_next);
87 else if (cb_prev)
88 load_runtime_instr_cb(&runtime_instr_empty_cb);
89#endif
90}
91
92#ifdef CONFIG_64BIT
93extern void exit_thread_runtime_instr(void);
94#else
95static inline void exit_thread_runtime_instr(void) { }
96#endif
97
98#endif /* _RUNTIME_INSTR_H */
diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h
index f223068b7822..dc4967b0e056 100644
--- a/arch/s390/include/asm/switch_to.h
+++ b/arch/s390/include/asm/switch_to.h
@@ -80,10 +80,12 @@ static inline void restore_access_regs(unsigned int *acrs)
80 if (prev->mm) { \ 80 if (prev->mm) { \
81 save_fp_regs(&prev->thread.fp_regs); \ 81 save_fp_regs(&prev->thread.fp_regs); \
82 save_access_regs(&prev->thread.acrs[0]); \ 82 save_access_regs(&prev->thread.acrs[0]); \
83 save_ri_cb(prev->thread.ri_cb); \
83 } \ 84 } \
84 if (next->mm) { \ 85 if (next->mm) { \
85 restore_fp_regs(&next->thread.fp_regs); \ 86 restore_fp_regs(&next->thread.fp_regs); \
86 restore_access_regs(&next->thread.acrs[0]); \ 87 restore_access_regs(&next->thread.acrs[0]); \
88 restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \
87 update_per_regs(next); \ 89 update_per_regs(next); \
88 } \ 90 } \
89 prev = __switch_to(prev,next); \ 91 prev = __switch_to(prev,next); \
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h
index 6756e78f4808..da2c2f4f7642 100644
--- a/arch/s390/include/asm/unistd.h
+++ b/arch/s390/include/asm/unistd.h
@@ -277,7 +277,8 @@
277#define __NR_setns 339 277#define __NR_setns 339
278#define __NR_process_vm_readv 340 278#define __NR_process_vm_readv 340
279#define __NR_process_vm_writev 341 279#define __NR_process_vm_writev 341
280#define NR_syscalls 342 280#define __NR_s390_runtime_instr 342
281#define NR_syscalls 343
281 282
282/* 283/*
283 * There are some system calls that are not present on 64 bit, some 284 * There are some system calls that are not present on 64 bit, some
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 9a111b621f4e..bba01bf678a6 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -49,7 +49,7 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
49obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o 49obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
50obj-$(CONFIG_CRASH_DUMP) += crash_dump.o 50obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
51obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o 51obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o
52obj-$(CONFIG_64BIT) += cache.o 52obj-$(CONFIG_64BIT) += runtime_instr.o cache.o
53 53
54# Kexec part 54# Kexec part
55S390_KEXEC_OBJS := machine_kexec.o 55S390_KEXEC_OBJS := machine_kexec.o
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 2d82cfcbce5b..5f7928fe34ce 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1646,3 +1646,8 @@ ENTRY(compat_sys_process_vm_writev_wrapper)
1646 llgf %r0,164(%r15) # unsigned long 1646 llgf %r0,164(%r15) # unsigned long
1647 stg %r0,160(%r15) 1647 stg %r0,160(%r15)
1648 jg compat_sys_process_vm_writev 1648 jg compat_sys_process_vm_writev
1649
1650ENTRY(sys_s390_runtime_instr_wrapper)
1651 lgfr %r2,%r2 # int
1652 lgfr %r3,%r3 # int
1653 jg sys_s390_runtime_instr
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index 84fd7e920bfe..4bc67db63522 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -315,6 +315,8 @@ enum {
315 LONG_INSN_POPCNT, 315 LONG_INSN_POPCNT,
316 LONG_INSN_RISBHG, 316 LONG_INSN_RISBHG,
317 LONG_INSN_RISBLG, 317 LONG_INSN_RISBLG,
318 LONG_INSN_RINEXT,
319 LONG_INSN_RIEMIT,
318}; 320};
319 321
320static char *long_insn_name[] = { 322static char *long_insn_name[] = {
@@ -330,6 +332,8 @@ static char *long_insn_name[] = {
330 [LONG_INSN_POPCNT] = "popcnt", 332 [LONG_INSN_POPCNT] = "popcnt",
331 [LONG_INSN_RISBHG] = "risbhg", 333 [LONG_INSN_RISBHG] = "risbhg",
332 [LONG_INSN_RISBLG] = "risblk", 334 [LONG_INSN_RISBLG] = "risblk",
335 [LONG_INSN_RINEXT] = "rinext",
336 [LONG_INSN_RIEMIT] = "riemit",
333}; 337};
334 338
335static struct insn opcode[] = { 339static struct insn opcode[] = {
@@ -582,6 +586,17 @@ static struct insn opcode_a7[] = {
582 { "", 0, INSTR_INVALID } 586 { "", 0, INSTR_INVALID }
583}; 587};
584 588
589static struct insn opcode_aa[] = {
590#ifdef CONFIG_64BIT
591 { { 0, LONG_INSN_RINEXT }, 0x00, INSTR_RI_RI },
592 { "rion", 0x01, INSTR_RI_RI },
593 { "tric", 0x02, INSTR_RI_RI },
594 { "rioff", 0x03, INSTR_RI_RI },
595 { { 0, LONG_INSN_RIEMIT }, 0x04, INSTR_RI_RI },
596#endif
597 { "", 0, INSTR_INVALID }
598};
599
585static struct insn opcode_b2[] = { 600static struct insn opcode_b2[] = {
586#ifdef CONFIG_64BIT 601#ifdef CONFIG_64BIT
587 { "sske", 0x2b, INSTR_RRF_M0RR }, 602 { "sske", 0x2b, INSTR_RRF_M0RR },
@@ -1210,6 +1225,9 @@ static struct insn opcode_eb[] = {
1210 { "cliy", 0x55, INSTR_SIY_URD }, 1225 { "cliy", 0x55, INSTR_SIY_URD },
1211 { "oiy", 0x56, INSTR_SIY_URD }, 1226 { "oiy", 0x56, INSTR_SIY_URD },
1212 { "xiy", 0x57, INSTR_SIY_URD }, 1227 { "xiy", 0x57, INSTR_SIY_URD },
1228 { "lric", 0x60, INSTR_RSY_RDRM },
1229 { "stric", 0x61, INSTR_RSY_RDRM },
1230 { "mric", 0x62, INSTR_RSY_RDRM },
1213 { "icmh", 0x80, INSTR_RSE_RURD }, 1231 { "icmh", 0x80, INSTR_RSE_RURD },
1214 { "icmh", 0x80, INSTR_RSY_RURD }, 1232 { "icmh", 0x80, INSTR_RSY_RURD },
1215 { "icmy", 0x81, INSTR_RSY_RURD }, 1233 { "icmy", 0x81, INSTR_RSY_RURD },
@@ -1408,6 +1426,9 @@ static struct insn *find_insn(unsigned char *code)
1408 case 0xa7: 1426 case 0xa7:
1409 table = opcode_a7; 1427 table = opcode_a7;
1410 break; 1428 break;
1429 case 0xaa:
1430 table = opcode_aa;
1431 break;
1411 case 0xb2: 1432 case 0xb2:
1412 table = opcode_b2; 1433 table = opcode_b2;
1413 break; 1434 break;
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index a22fdca6a663..c1b44934fe64 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -44,6 +44,7 @@ static const struct irq_class intrclass_names[] = {
44 {.name = "IUC", .desc = "[EXT] IUCV" }, 44 {.name = "IUC", .desc = "[EXT] IUCV" },
45 {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling" }, 45 {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling" },
46 {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter" }, 46 {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter" },
47 {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI" },
47 {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt" }, 48 {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt" },
48 {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt" }, 49 {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt" },
49 {.name = "DAS", .desc = "[I/O] DASD" }, 50 {.name = "DAS", .desc = "[I/O] DASD" },
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 733175373a4c..cb4328e49c75 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -30,6 +30,7 @@
30#include <asm/nmi.h> 30#include <asm/nmi.h>
31#include <asm/smp.h> 31#include <asm/smp.h>
32#include <asm/switch_to.h> 32#include <asm/switch_to.h>
33#include <asm/runtime_instr.h>
33#include "entry.h" 34#include "entry.h"
34 35
35asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); 36asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
@@ -132,6 +133,7 @@ EXPORT_SYMBOL(kernel_thread);
132 */ 133 */
133void exit_thread(void) 134void exit_thread(void)
134{ 135{
136 exit_thread_runtime_instr();
135} 137}
136 138
137void flush_thread(void) 139void flush_thread(void)
@@ -170,6 +172,11 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
170 /* Save access registers to new thread structure. */ 172 /* Save access registers to new thread structure. */
171 save_access_regs(&p->thread.acrs[0]); 173 save_access_regs(&p->thread.acrs[0]);
172 174
175 /* Don't copy runtime instrumentation info */
176 p->thread.ri_cb = NULL;
177 p->thread.ri_signum = 0;
178 frame->childregs.psw.mask &= ~PSW_MASK_RI;
179
173#ifndef CONFIG_64BIT 180#ifndef CONFIG_64BIT
174 /* 181 /*
175 * save fprs to current->thread.fp_regs to merge them with 182 * save fprs to current->thread.fp_regs to merge them with
diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c
new file mode 100644
index 000000000000..e27e23da0e60
--- /dev/null
+++ b/arch/s390/kernel/runtime_instr.c
@@ -0,0 +1,150 @@
1/*
2 * Copyright IBM Corp. 2012
3 * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
4 */
5
6#include <linux/kernel.h>
7#include <linux/syscalls.h>
8#include <linux/signal.h>
9#include <linux/mm.h>
10#include <linux/slab.h>
11#include <linux/init.h>
12#include <linux/errno.h>
13#include <linux/kernel_stat.h>
14#include <asm/runtime_instr.h>
15#include <asm/cpu_mf.h>
16#include <asm/irq.h>
17
18/* empty control block to disable RI by loading it */
19struct runtime_instr_cb runtime_instr_empty_cb;
20
21static int runtime_instr_avail(void)
22{
23 return test_facility(64);
24}
25
26static void disable_runtime_instr(void)
27{
28 struct pt_regs *regs = task_pt_regs(current);
29
30 load_runtime_instr_cb(&runtime_instr_empty_cb);
31
32 /*
33 * Make sure the RI bit is deleted from the PSW. If the user did not
34 * switch off RI before the system call the process will get a
35 * specification exception otherwise.
36 */
37 regs->psw.mask &= ~PSW_MASK_RI;
38}
39
40static void init_runtime_instr_cb(struct runtime_instr_cb *cb)
41{
42 cb->buf_limit = 0xfff;
43 if (addressing_mode == HOME_SPACE_MODE)
44 cb->home_space = 1;
45 cb->int_requested = 1;
46 cb->pstate = 1;
47 cb->pstate_set_buf = 1;
48 cb->pstate_sample = 1;
49 cb->pstate_collect = 1;
50 cb->key = PAGE_DEFAULT_KEY;
51 cb->valid = 1;
52}
53
54void exit_thread_runtime_instr(void)
55{
56 struct task_struct *task = current;
57
58 if (!task->thread.ri_cb)
59 return;
60 disable_runtime_instr();
61 kfree(task->thread.ri_cb);
62 task->thread.ri_signum = 0;
63 task->thread.ri_cb = NULL;
64}
65
66static void runtime_instr_int_handler(struct ext_code ext_code,
67 unsigned int param32, unsigned long param64)
68{
69 struct siginfo info;
70
71 if (!(param32 & CPU_MF_INT_RI_MASK))
72 return;
73
74 kstat_cpu(smp_processor_id()).irqs[EXTINT_CMR]++;
75
76 if (!current->thread.ri_cb)
77 return;
78 if (current->thread.ri_signum < SIGRTMIN ||
79 current->thread.ri_signum > SIGRTMAX) {
80 WARN_ON_ONCE(1);
81 return;
82 }
83
84 memset(&info, 0, sizeof(info));
85 info.si_signo = current->thread.ri_signum;
86 info.si_code = SI_QUEUE;
87 if (param32 & CPU_MF_INT_RI_BUF_FULL)
88 info.si_int = ENOBUFS;
89 else if (param32 & CPU_MF_INT_RI_HALTED)
90 info.si_int = ECANCELED;
91 else
92 return; /* unknown reason */
93
94 send_sig_info(current->thread.ri_signum, &info, current);
95}
96
97SYSCALL_DEFINE2(s390_runtime_instr, int, command, int, signum)
98{
99 struct runtime_instr_cb *cb;
100
101 if (!runtime_instr_avail())
102 return -EOPNOTSUPP;
103
104 if (command == S390_RUNTIME_INSTR_STOP) {
105 preempt_disable();
106 exit_thread_runtime_instr();
107 preempt_enable();
108 return 0;
109 }
110
111 if (command != S390_RUNTIME_INSTR_START ||
112 (signum < SIGRTMIN || signum > SIGRTMAX))
113 return -EINVAL;
114
115 if (!current->thread.ri_cb) {
116 cb = kzalloc(sizeof(*cb), GFP_KERNEL);
117 if (!cb)
118 return -ENOMEM;
119 } else {
120 cb = current->thread.ri_cb;
121 memset(cb, 0, sizeof(*cb));
122 }
123
124 init_runtime_instr_cb(cb);
125 current->thread.ri_signum = signum;
126
127 /* now load the control block to make it available */
128 preempt_disable();
129 current->thread.ri_cb = cb;
130 load_runtime_instr_cb(cb);
131 preempt_enable();
132 return 0;
133}
134
135static int __init runtime_instr_init(void)
136{
137 int rc;
138
139 if (!runtime_instr_avail())
140 return 0;
141
142 measurement_alert_subclass_register();
143 rc = register_external_interrupt(0x1407, runtime_instr_int_handler);
144 if (rc)
145 measurement_alert_subclass_unregister();
146 else
147 pr_info("Runtime instrumentation facility initialized\n");
148 return rc;
149}
150device_initcall(runtime_instr_init);
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index bcab2f04ba58..539f0a7701e4 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -350,3 +350,4 @@ SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper)
350SYSCALL(sys_setns,sys_setns,sys_setns_wrapper) 350SYSCALL(sys_setns,sys_setns,sys_setns_wrapper)
351SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */ 351SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */
352SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper) 352SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper)
353SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper)