s390/uprobes: architecture backend for uprobes
[linux-2.6-block.git] / arch / s390 / kernel / uprobes.c
CommitLineData
2a0a5b22
JW
1/*
2 * User-space Probes (UProbes) for s390
3 *
4 * Copyright IBM Corp. 2014
5 * Author(s): Jan Willeke,
6 */
7
8#include <linux/kprobes.h>
9#include <linux/uaccess.h>
10#include <linux/uprobes.h>
11#include <linux/compat.h>
12#include <linux/kdebug.h>
13#include <asm/switch_to.h>
14#include <asm/facility.h>
15#include <asm/dis.h>
16#include "entry.h"
17
18#define UPROBE_TRAP_NR UINT_MAX
19
20int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
21 unsigned long addr)
22{
23 return probe_is_prohibited_opcode(auprobe->insn);
24}
25
26int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
27{
28 if (psw_bits(regs->psw).eaba == PSW_AMODE_24BIT)
29 return -EINVAL;
30 if (!is_compat_task() && psw_bits(regs->psw).eaba == PSW_AMODE_31BIT)
31 return -EINVAL;
32 clear_pt_regs_flag(regs, PIF_PER_TRAP);
33 auprobe->saved_per = psw_bits(regs->psw).r;
34 auprobe->saved_int_code = regs->int_code;
35 regs->int_code = UPROBE_TRAP_NR;
36 regs->psw.addr = current->utask->xol_vaddr;
37 set_tsk_thread_flag(current, TIF_UPROBE_SINGLESTEP);
38 update_cr_regs(current);
39 return 0;
40}
41
42bool arch_uprobe_xol_was_trapped(struct task_struct *tsk)
43{
44 struct pt_regs *regs = task_pt_regs(tsk);
45
46 if (regs->int_code != UPROBE_TRAP_NR)
47 return true;
48 return false;
49}
50
51int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
52{
53 int fixup = probe_get_fixup_type(auprobe->insn);
54 struct uprobe_task *utask = current->utask;
55
56 clear_tsk_thread_flag(current, TIF_UPROBE_SINGLESTEP);
57 update_cr_regs(current);
58 psw_bits(regs->psw).r = auprobe->saved_per;
59 regs->int_code = auprobe->saved_int_code;
60
61 if (fixup & FIXUP_PSW_NORMAL)
62 regs->psw.addr += utask->vaddr - utask->xol_vaddr;
63 if (fixup & FIXUP_RETURN_REGISTER) {
64 int reg = (auprobe->insn[0] & 0xf0) >> 4;
65
66 regs->gprs[reg] += utask->vaddr - utask->xol_vaddr;
67 }
68 if (fixup & FIXUP_BRANCH_NOT_TAKEN) {
69 int ilen = insn_length(auprobe->insn[0] >> 8);
70
71 if (regs->psw.addr - utask->xol_vaddr == ilen)
72 regs->psw.addr = utask->vaddr + ilen;
73 }
74 /* If per tracing was active generate trap */
75 if (regs->psw.mask & PSW_MASK_PER)
76 do_per_trap(regs);
77 return 0;
78}
79
80int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val,
81 void *data)
82{
83 struct die_args *args = data;
84 struct pt_regs *regs = args->regs;
85
86 if (!user_mode(regs))
87 return NOTIFY_DONE;
88 if (regs->int_code & 0x200) /* Trap during transaction */
89 return NOTIFY_DONE;
90 switch (val) {
91 case DIE_BPT:
92 if (uprobe_pre_sstep_notifier(regs))
93 return NOTIFY_STOP;
94 break;
95 case DIE_SSTEP:
96 if (uprobe_post_sstep_notifier(regs))
97 return NOTIFY_STOP;
98 default:
99 break;
100 }
101 return NOTIFY_DONE;
102}
103
104void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
105{
106 clear_thread_flag(TIF_UPROBE_SINGLESTEP);
107 regs->int_code = auprobe->saved_int_code;
108 regs->psw.addr = current->utask->vaddr;
109}
110
111unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline,
112 struct pt_regs *regs)
113{
114 unsigned long orig;
115
116 orig = regs->gprs[14];
117 regs->gprs[14] = trampoline;
118 return orig;
119}
120
121/* Instruction Emulation */
122
123static void adjust_psw_addr(psw_t *psw, unsigned long len)
124{
125 psw->addr = __rewind_psw(*psw, -len);
126}
127
128#define EMU_ILLEGAL_OP 1
129#define EMU_SPECIFICATION 2
130#define EMU_ADDRESSING 3
131
132#define emu_load_ril(ptr, output) \
133({ \
134 unsigned int mask = sizeof(*(ptr)) - 1; \
135 __typeof__(*(ptr)) input; \
136 int __rc = 0; \
137 \
138 if (!test_facility(34)) \
139 __rc = EMU_ILLEGAL_OP; \
140 else if ((u64 __force)ptr & mask) \
141 __rc = EMU_SPECIFICATION; \
142 else if (get_user(input, ptr)) \
143 __rc = EMU_ADDRESSING; \
144 else \
145 *(output) = input; \
146 __rc; \
147})
148
149#define emu_store_ril(ptr, input) \
150({ \
151 unsigned int mask = sizeof(*(ptr)) - 1; \
152 int __rc = 0; \
153 \
154 if (!test_facility(34)) \
155 __rc = EMU_ILLEGAL_OP; \
156 else if ((u64 __force)ptr & mask) \
157 __rc = EMU_SPECIFICATION; \
158 else if (put_user(*(input), ptr)) \
159 __rc = EMU_ADDRESSING; \
160 __rc; \
161})
162
163#define emu_cmp_ril(regs, ptr, cmp) \
164({ \
165 unsigned int mask = sizeof(*(ptr)) - 1; \
166 __typeof__(*(ptr)) input; \
167 int __rc = 0; \
168 \
169 if (!test_facility(34)) \
170 __rc = EMU_ILLEGAL_OP; \
171 else if ((u64 __force)ptr & mask) \
172 __rc = EMU_SPECIFICATION; \
173 else if (get_user(input, ptr)) \
174 __rc = EMU_ADDRESSING; \
175 else if (input > *(cmp)) \
176 psw_bits((regs)->psw).cc = 1; \
177 else if (input < *(cmp)) \
178 psw_bits((regs)->psw).cc = 2; \
179 else \
180 psw_bits((regs)->psw).cc = 0; \
181 __rc; \
182})
183
184struct insn_ril {
185 u8 opc0;
186 u8 reg : 4;
187 u8 opc1 : 4;
188 s32 disp;
189} __packed;
190
191union split_register {
192 u64 u64;
193 u32 u32[2];
194 u16 u16[4];
195 s64 s64;
196 s32 s32[2];
197 s16 s16[4];
198};
199
200/*
201 * pc relative instructions are emulated, since parameters may not be
202 * accessible from the xol area due to range limitations.
203 */
204static void handle_insn_ril(struct arch_uprobe *auprobe, struct pt_regs *regs)
205{
206 union split_register *rx;
207 struct insn_ril *insn;
208 unsigned int ilen;
209 void *uptr;
210 int rc = 0;
211
212 insn = (struct insn_ril *) &auprobe->insn;
213 rx = (union split_register *) &regs->gprs[insn->reg];
214 uptr = (void *)(regs->psw.addr + (insn->disp * 2));
215 ilen = insn_length(insn->opc0);
216
217 switch (insn->opc0) {
218 case 0xc0:
219 switch (insn->opc1) {
220 case 0x00: /* larl */
221 rx->u64 = (unsigned long)uptr;
222 break;
223 }
224 break;
225 case 0xc4:
226 switch (insn->opc1) {
227 case 0x02: /* llhrl */
228 rc = emu_load_ril((u16 __user *)uptr, &rx->u32[1]);
229 break;
230 case 0x04: /* lghrl */
231 rc = emu_load_ril((s16 __user *)uptr, &rx->u64);
232 break;
233 case 0x05: /* lhrl */
234 rc = emu_load_ril((s16 __user *)uptr, &rx->u32[1]);
235 break;
236 case 0x06: /* llghrl */
237 rc = emu_load_ril((u16 __user *)uptr, &rx->u64);
238 break;
239 case 0x08: /* lgrl */
240 rc = emu_load_ril((u64 __user *)uptr, &rx->u64);
241 break;
242 case 0x0c: /* lgfrl */
243 rc = emu_load_ril((s32 __user *)uptr, &rx->u64);
244 break;
245 case 0x0d: /* lrl */
246 rc = emu_load_ril((u32 __user *)uptr, &rx->u32[1]);
247 break;
248 case 0x0e: /* llgfrl */
249 rc = emu_load_ril((u32 __user *)uptr, &rx->u64);
250 break;
251 case 0x07: /* sthrl */
252 rc = emu_store_ril((u16 __user *)uptr, &rx->u16[3]);
253 break;
254 case 0x0b: /* stgrl */
255 rc = emu_store_ril((u64 __user *)uptr, &rx->u64);
256 break;
257 case 0x0f: /* strl */
258 rc = emu_store_ril((u32 __user *)uptr, &rx->u32[1]);
259 break;
260 }
261 break;
262 case 0xc6:
263 switch (insn->opc1) {
264 case 0x02: /* pfdrl */
265 if (!test_facility(34))
266 rc = EMU_ILLEGAL_OP;
267 break;
268 case 0x04: /* cghrl */
269 rc = emu_cmp_ril(regs, (s16 __user *)uptr, &rx->s64);
270 break;
271 case 0x05: /* chrl */
272 rc = emu_cmp_ril(regs, (s16 __user *)uptr, &rx->s32[1]);
273 break;
274 case 0x06: /* clghrl */
275 rc = emu_cmp_ril(regs, (u16 __user *)uptr, &rx->u64);
276 break;
277 case 0x07: /* clhrl */
278 rc = emu_cmp_ril(regs, (u16 __user *)uptr, &rx->u32[1]);
279 break;
280 case 0x08: /* cgrl */
281 rc = emu_cmp_ril(regs, (s64 __user *)uptr, &rx->s64);
282 break;
283 case 0x0a: /* clgrl */
284 rc = emu_cmp_ril(regs, (u64 __user *)uptr, &rx->u64);
285 break;
286 case 0x0c: /* cgfrl */
287 rc = emu_cmp_ril(regs, (s32 __user *)uptr, &rx->s64);
288 break;
289 case 0x0d: /* crl */
290 rc = emu_cmp_ril(regs, (s32 __user *)uptr, &rx->s32[1]);
291 break;
292 case 0x0e: /* clgfrl */
293 rc = emu_cmp_ril(regs, (u32 __user *)uptr, &rx->u64);
294 break;
295 case 0x0f: /* clrl */
296 rc = emu_cmp_ril(regs, (u32 __user *)uptr, &rx->u32[1]);
297 break;
298 }
299 break;
300 }
301 adjust_psw_addr(&regs->psw, ilen);
302 switch (rc) {
303 case EMU_ILLEGAL_OP:
304 regs->int_code = ilen << 16 | 0x0001;
305 do_report_trap(regs, SIGILL, ILL_ILLOPC, NULL);
306 break;
307 case EMU_SPECIFICATION:
308 regs->int_code = ilen << 16 | 0x0006;
309 do_report_trap(regs, SIGILL, ILL_ILLOPC , NULL);
310 break;
311 case EMU_ADDRESSING:
312 regs->int_code = ilen << 16 | 0x0005;
313 do_report_trap(regs, SIGSEGV, SEGV_MAPERR, NULL);
314 break;
315 }
316}
317
318bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
319{
320 if ((psw_bits(regs->psw).eaba == PSW_AMODE_24BIT) ||
321 ((psw_bits(regs->psw).eaba == PSW_AMODE_31BIT) &&
322 !is_compat_task())) {
323 regs->psw.addr = __rewind_psw(regs->psw, UPROBE_SWBP_INSN_SIZE);
324 do_report_trap(regs, SIGILL, ILL_ILLADR, NULL);
325 return true;
326 }
327 if (probe_is_insn_relative_long(auprobe->insn)) {
328 handle_insn_ril(auprobe, regs);
329 return true;
330 }
331 return false;
332}