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 */ 19 struct runtime_instr_cb runtime_instr_empty_cb; 20 21 static void disable_runtime_instr(void) 22 { 23 struct pt_regs *regs = task_pt_regs(current); 24 25 load_runtime_instr_cb(&runtime_instr_empty_cb); 26 27 /* 28 * Make sure the RI bit is deleted from the PSW. If the user did not 29 * switch off RI before the system call the process will get a 30 * specification exception otherwise. 31 */ 32 regs->psw.mask &= ~PSW_MASK_RI; 33 } 34 35 static void init_runtime_instr_cb(struct runtime_instr_cb *cb) 36 { 37 cb->buf_limit = 0xfff; 38 cb->pstate = 1; 39 cb->pstate_set_buf = 1; 40 cb->pstate_sample = 1; 41 cb->pstate_collect = 1; 42 cb->key = PAGE_DEFAULT_KEY; 43 cb->valid = 1; 44 } 45 46 void exit_thread_runtime_instr(void) 47 { 48 struct task_struct *task = current; 49 50 if (!task->thread.ri_cb) 51 return; 52 disable_runtime_instr(); 53 kfree(task->thread.ri_cb); 54 task->thread.ri_cb = NULL; 55 } 56 57 SYSCALL_DEFINE1(s390_runtime_instr, int, command) 58 { 59 struct runtime_instr_cb *cb; 60 61 if (!test_facility(64)) 62 return -EOPNOTSUPP; 63 64 if (command == S390_RUNTIME_INSTR_STOP) { 65 preempt_disable(); 66 exit_thread_runtime_instr(); 67 preempt_enable(); 68 return 0; 69 } 70 71 if (command != S390_RUNTIME_INSTR_START) 72 return -EINVAL; 73 74 if (!current->thread.ri_cb) { 75 cb = kzalloc(sizeof(*cb), GFP_KERNEL); 76 if (!cb) 77 return -ENOMEM; 78 } else { 79 cb = current->thread.ri_cb; 80 memset(cb, 0, sizeof(*cb)); 81 } 82 83 init_runtime_instr_cb(cb); 84 85 /* now load the control block to make it available */ 86 preempt_disable(); 87 current->thread.ri_cb = cb; 88 load_runtime_instr_cb(cb); 89 preempt_enable(); 90 return 0; 91 } 92