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 cb->int_requested = 1; 44 cb->pstate = 1; 45 cb->pstate_set_buf = 1; 46 cb->pstate_sample = 1; 47 cb->pstate_collect = 1; 48 cb->key = PAGE_DEFAULT_KEY; 49 cb->valid = 1; 50} 51 52void exit_thread_runtime_instr(void) 53{ 54 struct task_struct *task = current; 55 56 if (!task->thread.ri_cb) 57 return; 58 disable_runtime_instr(); 59 kfree(task->thread.ri_cb); 60 task->thread.ri_signum = 0; 61 task->thread.ri_cb = NULL; 62} 63 64static void runtime_instr_int_handler(struct ext_code ext_code, 65 unsigned int param32, unsigned long param64) 66{ 67 struct siginfo info; 68 69 if (!(param32 & CPU_MF_INT_RI_MASK)) 70 return; 71 72 inc_irq_stat(IRQEXT_CMR); 73 74 if (!current->thread.ri_cb) 75 return; 76 if (current->thread.ri_signum < SIGRTMIN || 77 current->thread.ri_signum > SIGRTMAX) { 78 WARN_ON_ONCE(1); 79 return; 80 } 81 82 memset(&info, 0, sizeof(info)); 83 info.si_signo = current->thread.ri_signum; 84 info.si_code = SI_QUEUE; 85 if (param32 & CPU_MF_INT_RI_BUF_FULL) 86 info.si_int = ENOBUFS; 87 else if (param32 & CPU_MF_INT_RI_HALTED) 88 info.si_int = ECANCELED; 89 else 90 return; /* unknown reason */ 91 92 send_sig_info(current->thread.ri_signum, &info, current); 93} 94 95SYSCALL_DEFINE2(s390_runtime_instr, int, command, int, signum) 96{ 97 struct runtime_instr_cb *cb; 98 99 if (!runtime_instr_avail()) 100 return -EOPNOTSUPP; 101 102 if (command == S390_RUNTIME_INSTR_STOP) { 103 preempt_disable(); 104 exit_thread_runtime_instr(); 105 preempt_enable(); 106 return 0; 107 } 108 109 if (command != S390_RUNTIME_INSTR_START || 110 (signum < SIGRTMIN || signum > SIGRTMAX)) 111 return -EINVAL; 112 113 if (!current->thread.ri_cb) { 114 cb = kzalloc(sizeof(*cb), GFP_KERNEL); 115 if (!cb) 116 return -ENOMEM; 117 } else { 118 cb = current->thread.ri_cb; 119 memset(cb, 0, sizeof(*cb)); 120 } 121 122 init_runtime_instr_cb(cb); 123 current->thread.ri_signum = signum; 124 125 /* now load the control block to make it available */ 126 preempt_disable(); 127 current->thread.ri_cb = cb; 128 load_runtime_instr_cb(cb); 129 preempt_enable(); 130 return 0; 131} 132 133static int __init runtime_instr_init(void) 134{ 135 int rc; 136 137 if (!runtime_instr_avail()) 138 return 0; 139 140 irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT); 141 rc = register_external_irq(EXT_IRQ_MEASURE_ALERT, 142 runtime_instr_int_handler); 143 if (rc) 144 irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT); 145 else 146 pr_info("Runtime instrumentation facility initialized\n"); 147 return rc; 148} 149device_initcall(runtime_instr_init); 150