xref: /linux/arch/arm/probes/kprobes/actions-thumb.c (revision ca55b2fef3a9373fcfc30f82fd26bc7fccbda732)
1 /*
2  * arch/arm/probes/kprobes/actions-thumb.c
3  *
4  * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 
11 #include <linux/types.h>
12 #include <linux/kernel.h>
13 #include <linux/ptrace.h>
14 #include <linux/kprobes.h>
15 
16 #include "../decode-thumb.h"
17 #include "core.h"
18 #include "checkers.h"
19 
20 /* These emulation encodings are functionally equivalent... */
21 #define t32_emulate_rd8rn16rm0ra12_noflags \
22 		t32_emulate_rdlo12rdhi8rn16rm0_noflags
23 
24 /* t32 thumb actions */
25 
26 static void __kprobes
27 t32_simulate_table_branch(probes_opcode_t insn,
28 		struct arch_probes_insn *asi, struct pt_regs *regs)
29 {
30 	unsigned long pc = regs->ARM_pc;
31 	int rn = (insn >> 16) & 0xf;
32 	int rm = insn & 0xf;
33 
34 	unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn];
35 	unsigned long rmv = regs->uregs[rm];
36 	unsigned int halfwords;
37 
38 	if (insn & 0x10) /* TBH */
39 		halfwords = ((u16 *)rnv)[rmv];
40 	else /* TBB */
41 		halfwords = ((u8 *)rnv)[rmv];
42 
43 	regs->ARM_pc = pc + 2 * halfwords;
44 }
45 
46 static void __kprobes
47 t32_simulate_mrs(probes_opcode_t insn,
48 		struct arch_probes_insn *asi, struct pt_regs *regs)
49 {
50 	int rd = (insn >> 8) & 0xf;
51 	unsigned long mask = 0xf8ff03df; /* Mask out execution state */
52 	regs->uregs[rd] = regs->ARM_cpsr & mask;
53 }
54 
55 static void __kprobes
56 t32_simulate_cond_branch(probes_opcode_t insn,
57 		struct arch_probes_insn *asi, struct pt_regs *regs)
58 {
59 	unsigned long pc = regs->ARM_pc;
60 
61 	long offset = insn & 0x7ff;		/* imm11 */
62 	offset += (insn & 0x003f0000) >> 5;	/* imm6 */
63 	offset += (insn & 0x00002000) << 4;	/* J1 */
64 	offset += (insn & 0x00000800) << 7;	/* J2 */
65 	offset -= (insn & 0x04000000) >> 7;	/* Apply sign bit */
66 
67 	regs->ARM_pc = pc + (offset * 2);
68 }
69 
70 static enum probes_insn __kprobes
71 t32_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi,
72 		const struct decode_header *d)
73 {
74 	int cc = (insn >> 22) & 0xf;
75 	asi->insn_check_cc = probes_condition_checks[cc];
76 	asi->insn_handler = t32_simulate_cond_branch;
77 	return INSN_GOOD_NO_SLOT;
78 }
79 
80 static void __kprobes
81 t32_simulate_branch(probes_opcode_t insn,
82 		    struct arch_probes_insn *asi, struct pt_regs *regs)
83 {
84 	unsigned long pc = regs->ARM_pc;
85 
86 	long offset = insn & 0x7ff;		/* imm11 */
87 	offset += (insn & 0x03ff0000) >> 5;	/* imm10 */
88 	offset += (insn & 0x00002000) << 9;	/* J1 */
89 	offset += (insn & 0x00000800) << 10;	/* J2 */
90 	if (insn & 0x04000000)
91 		offset -= 0x00800000; /* Apply sign bit */
92 	else
93 		offset ^= 0x00600000; /* Invert J1 and J2 */
94 
95 	if (insn & (1 << 14)) {
96 		/* BL or BLX */
97 		regs->ARM_lr = regs->ARM_pc | 1;
98 		if (!(insn & (1 << 12))) {
99 			/* BLX so switch to ARM mode */
100 			regs->ARM_cpsr &= ~PSR_T_BIT;
101 			pc &= ~3;
102 		}
103 	}
104 
105 	regs->ARM_pc = pc + (offset * 2);
106 }
107 
108 static void __kprobes
109 t32_simulate_ldr_literal(probes_opcode_t insn,
110 		struct arch_probes_insn *asi, struct pt_regs *regs)
111 {
112 	unsigned long addr = regs->ARM_pc & ~3;
113 	int rt = (insn >> 12) & 0xf;
114 	unsigned long rtv;
115 
116 	long offset = insn & 0xfff;
117 	if (insn & 0x00800000)
118 		addr += offset;
119 	else
120 		addr -= offset;
121 
122 	if (insn & 0x00400000) {
123 		/* LDR */
124 		rtv = *(unsigned long *)addr;
125 		if (rt == 15) {
126 			bx_write_pc(rtv, regs);
127 			return;
128 		}
129 	} else if (insn & 0x00200000) {
130 		/* LDRH */
131 		if (insn & 0x01000000)
132 			rtv = *(s16 *)addr;
133 		else
134 			rtv = *(u16 *)addr;
135 	} else {
136 		/* LDRB */
137 		if (insn & 0x01000000)
138 			rtv = *(s8 *)addr;
139 		else
140 			rtv = *(u8 *)addr;
141 	}
142 
143 	regs->uregs[rt] = rtv;
144 }
145 
146 static enum probes_insn __kprobes
147 t32_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi,
148 		const struct decode_header *d)
149 {
150 	enum probes_insn ret = kprobe_decode_ldmstm(insn, asi, d);
151 
152 	/* Fixup modified instruction to have halfwords in correct order...*/
153 	insn = __mem_to_opcode_arm(asi->insn[0]);
154 	((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn >> 16);
155 	((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0xffff);
156 
157 	return ret;
158 }
159 
160 static void __kprobes
161 t32_emulate_ldrdstrd(probes_opcode_t insn,
162 		struct arch_probes_insn *asi, struct pt_regs *regs)
163 {
164 	unsigned long pc = regs->ARM_pc & ~3;
165 	int rt1 = (insn >> 12) & 0xf;
166 	int rt2 = (insn >> 8) & 0xf;
167 	int rn = (insn >> 16) & 0xf;
168 
169 	register unsigned long rt1v asm("r0") = regs->uregs[rt1];
170 	register unsigned long rt2v asm("r1") = regs->uregs[rt2];
171 	register unsigned long rnv asm("r2") = (rn == 15) ? pc
172 							  : regs->uregs[rn];
173 
174 	__asm__ __volatile__ (
175 		"blx    %[fn]"
176 		: "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
177 		: "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (asi->insn_fn)
178 		: "lr", "memory", "cc"
179 	);
180 
181 	if (rn != 15)
182 		regs->uregs[rn] = rnv; /* Writeback base register */
183 	regs->uregs[rt1] = rt1v;
184 	regs->uregs[rt2] = rt2v;
185 }
186 
187 static void __kprobes
188 t32_emulate_ldrstr(probes_opcode_t insn,
189 		struct arch_probes_insn *asi, struct pt_regs *regs)
190 {
191 	int rt = (insn >> 12) & 0xf;
192 	int rn = (insn >> 16) & 0xf;
193 	int rm = insn & 0xf;
194 
195 	register unsigned long rtv asm("r0") = regs->uregs[rt];
196 	register unsigned long rnv asm("r2") = regs->uregs[rn];
197 	register unsigned long rmv asm("r3") = regs->uregs[rm];
198 
199 	__asm__ __volatile__ (
200 		"blx    %[fn]"
201 		: "=r" (rtv), "=r" (rnv)
202 		: "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
203 		: "lr", "memory", "cc"
204 	);
205 
206 	regs->uregs[rn] = rnv; /* Writeback base register */
207 	if (rt == 15) /* Can't be true for a STR as they aren't allowed */
208 		bx_write_pc(rtv, regs);
209 	else
210 		regs->uregs[rt] = rtv;
211 }
212 
213 static void __kprobes
214 t32_emulate_rd8rn16rm0_rwflags(probes_opcode_t insn,
215 		struct arch_probes_insn *asi, struct pt_regs *regs)
216 {
217 	int rd = (insn >> 8) & 0xf;
218 	int rn = (insn >> 16) & 0xf;
219 	int rm = insn & 0xf;
220 
221 	register unsigned long rdv asm("r1") = regs->uregs[rd];
222 	register unsigned long rnv asm("r2") = regs->uregs[rn];
223 	register unsigned long rmv asm("r3") = regs->uregs[rm];
224 	unsigned long cpsr = regs->ARM_cpsr;
225 
226 	__asm__ __volatile__ (
227 		"msr	cpsr_fs, %[cpsr]	\n\t"
228 		"blx    %[fn]			\n\t"
229 		"mrs	%[cpsr], cpsr		\n\t"
230 		: "=r" (rdv), [cpsr] "=r" (cpsr)
231 		: "0" (rdv), "r" (rnv), "r" (rmv),
232 		  "1" (cpsr), [fn] "r" (asi->insn_fn)
233 		: "lr", "memory", "cc"
234 	);
235 
236 	regs->uregs[rd] = rdv;
237 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
238 }
239 
240 static void __kprobes
241 t32_emulate_rd8pc16_noflags(probes_opcode_t insn,
242 		struct arch_probes_insn *asi, struct pt_regs *regs)
243 {
244 	unsigned long pc = regs->ARM_pc;
245 	int rd = (insn >> 8) & 0xf;
246 
247 	register unsigned long rdv asm("r1") = regs->uregs[rd];
248 	register unsigned long rnv asm("r2") = pc & ~3;
249 
250 	__asm__ __volatile__ (
251 		"blx    %[fn]"
252 		: "=r" (rdv)
253 		: "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
254 		: "lr", "memory", "cc"
255 	);
256 
257 	regs->uregs[rd] = rdv;
258 }
259 
260 static void __kprobes
261 t32_emulate_rd8rn16_noflags(probes_opcode_t insn,
262 		struct arch_probes_insn *asi, struct pt_regs *regs)
263 {
264 	int rd = (insn >> 8) & 0xf;
265 	int rn = (insn >> 16) & 0xf;
266 
267 	register unsigned long rdv asm("r1") = regs->uregs[rd];
268 	register unsigned long rnv asm("r2") = regs->uregs[rn];
269 
270 	__asm__ __volatile__ (
271 		"blx    %[fn]"
272 		: "=r" (rdv)
273 		: "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
274 		: "lr", "memory", "cc"
275 	);
276 
277 	regs->uregs[rd] = rdv;
278 }
279 
280 static void __kprobes
281 t32_emulate_rdlo12rdhi8rn16rm0_noflags(probes_opcode_t insn,
282 		struct arch_probes_insn *asi,
283 		struct pt_regs *regs)
284 {
285 	int rdlo = (insn >> 12) & 0xf;
286 	int rdhi = (insn >> 8) & 0xf;
287 	int rn = (insn >> 16) & 0xf;
288 	int rm = insn & 0xf;
289 
290 	register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
291 	register unsigned long rdhiv asm("r1") = regs->uregs[rdhi];
292 	register unsigned long rnv asm("r2") = regs->uregs[rn];
293 	register unsigned long rmv asm("r3") = regs->uregs[rm];
294 
295 	__asm__ __volatile__ (
296 		"blx    %[fn]"
297 		: "=r" (rdlov), "=r" (rdhiv)
298 		: "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
299 		  [fn] "r" (asi->insn_fn)
300 		: "lr", "memory", "cc"
301 	);
302 
303 	regs->uregs[rdlo] = rdlov;
304 	regs->uregs[rdhi] = rdhiv;
305 }
306 /* t16 thumb actions */
307 
308 static void __kprobes
309 t16_simulate_bxblx(probes_opcode_t insn,
310 		struct arch_probes_insn *asi, struct pt_regs *regs)
311 {
312 	unsigned long pc = regs->ARM_pc + 2;
313 	int rm = (insn >> 3) & 0xf;
314 	unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
315 
316 	if (insn & (1 << 7)) /* BLX ? */
317 		regs->ARM_lr = regs->ARM_pc | 1;
318 
319 	bx_write_pc(rmv, regs);
320 }
321 
322 static void __kprobes
323 t16_simulate_ldr_literal(probes_opcode_t insn,
324 		struct arch_probes_insn *asi, struct pt_regs *regs)
325 {
326 	unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3);
327 	long index = insn & 0xff;
328 	int rt = (insn >> 8) & 0x7;
329 	regs->uregs[rt] = base[index];
330 }
331 
332 static void __kprobes
333 t16_simulate_ldrstr_sp_relative(probes_opcode_t insn,
334 		struct arch_probes_insn *asi, struct pt_regs *regs)
335 {
336 	unsigned long* base = (unsigned long *)regs->ARM_sp;
337 	long index = insn & 0xff;
338 	int rt = (insn >> 8) & 0x7;
339 	if (insn & 0x800) /* LDR */
340 		regs->uregs[rt] = base[index];
341 	else /* STR */
342 		base[index] = regs->uregs[rt];
343 }
344 
345 static void __kprobes
346 t16_simulate_reladr(probes_opcode_t insn,
347 		struct arch_probes_insn *asi, struct pt_regs *regs)
348 {
349 	unsigned long base = (insn & 0x800) ? regs->ARM_sp
350 					    : ((regs->ARM_pc + 2) & ~3);
351 	long offset = insn & 0xff;
352 	int rt = (insn >> 8) & 0x7;
353 	regs->uregs[rt] = base + offset * 4;
354 }
355 
356 static void __kprobes
357 t16_simulate_add_sp_imm(probes_opcode_t insn,
358 		struct arch_probes_insn *asi, struct pt_regs *regs)
359 {
360 	long imm = insn & 0x7f;
361 	if (insn & 0x80) /* SUB */
362 		regs->ARM_sp -= imm * 4;
363 	else /* ADD */
364 		regs->ARM_sp += imm * 4;
365 }
366 
367 static void __kprobes
368 t16_simulate_cbz(probes_opcode_t insn,
369 		struct arch_probes_insn *asi, struct pt_regs *regs)
370 {
371 	int rn = insn & 0x7;
372 	probes_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
373 	if (nonzero & 0x800) {
374 		long i = insn & 0x200;
375 		long imm5 = insn & 0xf8;
376 		unsigned long pc = regs->ARM_pc + 2;
377 		regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
378 	}
379 }
380 
381 static void __kprobes
382 t16_simulate_it(probes_opcode_t insn,
383 		struct arch_probes_insn *asi, struct pt_regs *regs)
384 {
385 	/*
386 	 * The 8 IT state bits are split into two parts in CPSR:
387 	 *	ITSTATE<1:0> are in CPSR<26:25>
388 	 *	ITSTATE<7:2> are in CPSR<15:10>
389 	 * The new IT state is in the lower byte of insn.
390 	 */
391 	unsigned long cpsr = regs->ARM_cpsr;
392 	cpsr &= ~PSR_IT_MASK;
393 	cpsr |= (insn & 0xfc) << 8;
394 	cpsr |= (insn & 0x03) << 25;
395 	regs->ARM_cpsr = cpsr;
396 }
397 
398 static void __kprobes
399 t16_singlestep_it(probes_opcode_t insn,
400 		  struct arch_probes_insn *asi, struct pt_regs *regs)
401 {
402 	regs->ARM_pc += 2;
403 	t16_simulate_it(insn, asi, regs);
404 }
405 
406 static enum probes_insn __kprobes
407 t16_decode_it(probes_opcode_t insn, struct arch_probes_insn *asi,
408 		const struct decode_header *d)
409 {
410 	asi->insn_singlestep = t16_singlestep_it;
411 	return INSN_GOOD_NO_SLOT;
412 }
413 
414 static void __kprobes
415 t16_simulate_cond_branch(probes_opcode_t insn,
416 		struct arch_probes_insn *asi, struct pt_regs *regs)
417 {
418 	unsigned long pc = regs->ARM_pc + 2;
419 	long offset = insn & 0x7f;
420 	offset -= insn & 0x80; /* Apply sign bit */
421 	regs->ARM_pc = pc + (offset * 2);
422 }
423 
424 static enum probes_insn __kprobes
425 t16_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi,
426 		const struct decode_header *d)
427 {
428 	int cc = (insn >> 8) & 0xf;
429 	asi->insn_check_cc = probes_condition_checks[cc];
430 	asi->insn_handler = t16_simulate_cond_branch;
431 	return INSN_GOOD_NO_SLOT;
432 }
433 
434 static void __kprobes
435 t16_simulate_branch(probes_opcode_t insn,
436 		   struct arch_probes_insn *asi, struct pt_regs *regs)
437 {
438 	unsigned long pc = regs->ARM_pc + 2;
439 	long offset = insn & 0x3ff;
440 	offset -= insn & 0x400; /* Apply sign bit */
441 	regs->ARM_pc = pc + (offset * 2);
442 }
443 
444 static unsigned long __kprobes
445 t16_emulate_loregs(probes_opcode_t insn,
446 		   struct arch_probes_insn *asi, struct pt_regs *regs)
447 {
448 	unsigned long oldcpsr = regs->ARM_cpsr;
449 	unsigned long newcpsr;
450 
451 	__asm__ __volatile__ (
452 		"msr	cpsr_fs, %[oldcpsr]	\n\t"
453 		"ldmia	%[regs], {r0-r7}	\n\t"
454 		"blx	%[fn]			\n\t"
455 		"stmia	%[regs], {r0-r7}	\n\t"
456 		"mrs	%[newcpsr], cpsr	\n\t"
457 		: [newcpsr] "=r" (newcpsr)
458 		: [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
459 		  [fn] "r" (asi->insn_fn)
460 		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
461 		  "lr", "memory", "cc"
462 		);
463 
464 	return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
465 }
466 
467 static void __kprobes
468 t16_emulate_loregs_rwflags(probes_opcode_t insn,
469 		struct arch_probes_insn *asi, struct pt_regs *regs)
470 {
471 	regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs);
472 }
473 
474 static void __kprobes
475 t16_emulate_loregs_noitrwflags(probes_opcode_t insn,
476 		struct arch_probes_insn *asi, struct pt_regs *regs)
477 {
478 	unsigned long cpsr = t16_emulate_loregs(insn, asi, regs);
479 	if (!in_it_block(cpsr))
480 		regs->ARM_cpsr = cpsr;
481 }
482 
483 static void __kprobes
484 t16_emulate_hiregs(probes_opcode_t insn,
485 		struct arch_probes_insn *asi, struct pt_regs *regs)
486 {
487 	unsigned long pc = regs->ARM_pc + 2;
488 	int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
489 	int rm = (insn >> 3) & 0xf;
490 
491 	register unsigned long rdnv asm("r1");
492 	register unsigned long rmv asm("r0");
493 	unsigned long cpsr = regs->ARM_cpsr;
494 
495 	rdnv = (rdn == 15) ? pc : regs->uregs[rdn];
496 	rmv = (rm == 15) ? pc : regs->uregs[rm];
497 
498 	__asm__ __volatile__ (
499 		"msr	cpsr_fs, %[cpsr]	\n\t"
500 		"blx    %[fn]			\n\t"
501 		"mrs	%[cpsr], cpsr		\n\t"
502 		: "=r" (rdnv), [cpsr] "=r" (cpsr)
503 		: "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (asi->insn_fn)
504 		: "lr", "memory", "cc"
505 	);
506 
507 	if (rdn == 15)
508 		rdnv &= ~1;
509 
510 	regs->uregs[rdn] = rdnv;
511 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
512 }
513 
514 static enum probes_insn __kprobes
515 t16_decode_hiregs(probes_opcode_t insn, struct arch_probes_insn *asi,
516 		const struct decode_header *d)
517 {
518 	insn &= ~0x00ff;
519 	insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
520 	((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn);
521 	asi->insn_handler = t16_emulate_hiregs;
522 	return INSN_GOOD;
523 }
524 
525 static void __kprobes
526 t16_emulate_push(probes_opcode_t insn,
527 		struct arch_probes_insn *asi, struct pt_regs *regs)
528 {
529 	__asm__ __volatile__ (
530 		"ldr	r9, [%[regs], #13*4]	\n\t"
531 		"ldr	r8, [%[regs], #14*4]	\n\t"
532 		"ldmia	%[regs], {r0-r7}	\n\t"
533 		"blx	%[fn]			\n\t"
534 		"str	r9, [%[regs], #13*4]	\n\t"
535 		:
536 		: [regs] "r" (regs), [fn] "r" (asi->insn_fn)
537 		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
538 		  "lr", "memory", "cc"
539 		);
540 }
541 
542 static enum probes_insn __kprobes
543 t16_decode_push(probes_opcode_t insn, struct arch_probes_insn *asi,
544 		const struct decode_header *d)
545 {
546 	/*
547 	 * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}"
548 	 * and call it with R9=SP and LR in the register list represented
549 	 * by R8.
550 	 */
551 	/* 1st half STMDB R9!,{} */
552 	((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe929);
553 	/* 2nd half (register list) */
554 	((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff);
555 	asi->insn_handler = t16_emulate_push;
556 	return INSN_GOOD;
557 }
558 
559 static void __kprobes
560 t16_emulate_pop_nopc(probes_opcode_t insn,
561 		struct arch_probes_insn *asi, struct pt_regs *regs)
562 {
563 	__asm__ __volatile__ (
564 		"ldr	r9, [%[regs], #13*4]	\n\t"
565 		"ldmia	%[regs], {r0-r7}	\n\t"
566 		"blx	%[fn]			\n\t"
567 		"stmia	%[regs], {r0-r7}	\n\t"
568 		"str	r9, [%[regs], #13*4]	\n\t"
569 		:
570 		: [regs] "r" (regs), [fn] "r" (asi->insn_fn)
571 		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
572 		  "lr", "memory", "cc"
573 		);
574 }
575 
576 static void __kprobes
577 t16_emulate_pop_pc(probes_opcode_t insn,
578 		struct arch_probes_insn *asi, struct pt_regs *regs)
579 {
580 	register unsigned long pc asm("r8");
581 
582 	__asm__ __volatile__ (
583 		"ldr	r9, [%[regs], #13*4]	\n\t"
584 		"ldmia	%[regs], {r0-r7}	\n\t"
585 		"blx	%[fn]			\n\t"
586 		"stmia	%[regs], {r0-r7}	\n\t"
587 		"str	r9, [%[regs], #13*4]	\n\t"
588 		: "=r" (pc)
589 		: [regs] "r" (regs), [fn] "r" (asi->insn_fn)
590 		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
591 		  "lr", "memory", "cc"
592 		);
593 
594 	bx_write_pc(pc, regs);
595 }
596 
597 static enum probes_insn __kprobes
598 t16_decode_pop(probes_opcode_t insn, struct arch_probes_insn *asi,
599 		const struct decode_header *d)
600 {
601 	/*
602 	 * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}"
603 	 * and call it with R9=SP and PC in the register list represented
604 	 * by R8.
605 	 */
606 	/* 1st half LDMIA R9!,{} */
607 	((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe8b9);
608 	/* 2nd half (register list) */
609 	((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff);
610 	asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
611 					 : t16_emulate_pop_nopc;
612 	return INSN_GOOD;
613 }
614 
615 const union decode_action kprobes_t16_actions[NUM_PROBES_T16_ACTIONS] = {
616 	[PROBES_T16_ADD_SP] = {.handler = t16_simulate_add_sp_imm},
617 	[PROBES_T16_CBZ] = {.handler = t16_simulate_cbz},
618 	[PROBES_T16_SIGN_EXTEND] = {.handler = t16_emulate_loregs_rwflags},
619 	[PROBES_T16_PUSH] = {.decoder = t16_decode_push},
620 	[PROBES_T16_POP] = {.decoder = t16_decode_pop},
621 	[PROBES_T16_SEV] = {.handler = probes_emulate_none},
622 	[PROBES_T16_WFE] = {.handler = probes_simulate_nop},
623 	[PROBES_T16_IT] = {.decoder = t16_decode_it},
624 	[PROBES_T16_CMP] = {.handler = t16_emulate_loregs_rwflags},
625 	[PROBES_T16_ADDSUB] = {.handler = t16_emulate_loregs_noitrwflags},
626 	[PROBES_T16_LOGICAL] = {.handler = t16_emulate_loregs_noitrwflags},
627 	[PROBES_T16_LDR_LIT] = {.handler = t16_simulate_ldr_literal},
628 	[PROBES_T16_BLX] = {.handler = t16_simulate_bxblx},
629 	[PROBES_T16_HIREGOPS] = {.decoder = t16_decode_hiregs},
630 	[PROBES_T16_LDRHSTRH] = {.handler = t16_emulate_loregs_rwflags},
631 	[PROBES_T16_LDRSTR] = {.handler = t16_simulate_ldrstr_sp_relative},
632 	[PROBES_T16_ADR] = {.handler = t16_simulate_reladr},
633 	[PROBES_T16_LDMSTM] = {.handler = t16_emulate_loregs_rwflags},
634 	[PROBES_T16_BRANCH_COND] = {.decoder = t16_decode_cond_branch},
635 	[PROBES_T16_BRANCH] = {.handler = t16_simulate_branch},
636 };
637 
638 const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = {
639 	[PROBES_T32_LDMSTM] = {.decoder = t32_decode_ldmstm},
640 	[PROBES_T32_LDRDSTRD] = {.handler = t32_emulate_ldrdstrd},
641 	[PROBES_T32_TABLE_BRANCH] = {.handler = t32_simulate_table_branch},
642 	[PROBES_T32_TST] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
643 	[PROBES_T32_MOV] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
644 	[PROBES_T32_ADDSUB] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
645 	[PROBES_T32_LOGICAL] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
646 	[PROBES_T32_CMP] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
647 	[PROBES_T32_ADDWSUBW_PC] = {.handler = t32_emulate_rd8pc16_noflags,},
648 	[PROBES_T32_ADDWSUBW] = {.handler = t32_emulate_rd8rn16_noflags},
649 	[PROBES_T32_MOVW] = {.handler = t32_emulate_rd8rn16_noflags},
650 	[PROBES_T32_SAT] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
651 	[PROBES_T32_BITFIELD] = {.handler = t32_emulate_rd8rn16_noflags},
652 	[PROBES_T32_SEV] = {.handler = probes_emulate_none},
653 	[PROBES_T32_WFE] = {.handler = probes_simulate_nop},
654 	[PROBES_T32_MRS] = {.handler = t32_simulate_mrs},
655 	[PROBES_T32_BRANCH_COND] = {.decoder = t32_decode_cond_branch},
656 	[PROBES_T32_BRANCH] = {.handler = t32_simulate_branch},
657 	[PROBES_T32_PLDI] = {.handler = probes_simulate_nop},
658 	[PROBES_T32_LDR_LIT] = {.handler = t32_simulate_ldr_literal},
659 	[PROBES_T32_LDRSTR] = {.handler = t32_emulate_ldrstr},
660 	[PROBES_T32_SIGN_EXTEND] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
661 	[PROBES_T32_MEDIA] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
662 	[PROBES_T32_REVERSE] = {.handler = t32_emulate_rd8rn16_noflags},
663 	[PROBES_T32_MUL_ADD] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
664 	[PROBES_T32_MUL_ADD2] = {.handler = t32_emulate_rd8rn16rm0ra12_noflags},
665 	[PROBES_T32_MUL_ADD_LONG] = {
666 		.handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags},
667 };
668 
669 const struct decode_checker *kprobes_t32_checkers[] = {t32_stack_checker, NULL};
670 const struct decode_checker *kprobes_t16_checkers[] = {t16_stack_checker, NULL};
671