1/*
2 *  User-space Probes (UProbes) for s390
3 *
4 *    Copyright IBM Corp. 2014
5 *    Author(s): Jan Willeke,
6 */
7
8#include <linux/uaccess.h>
9#include <linux/uprobes.h>
10#include <linux/compat.h>
11#include <linux/kdebug.h>
12#include <asm/switch_to.h>
13#include <asm/facility.h>
14#include <asm/kprobes.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}
333