xref: /freebsd/sys/cddl/contrib/opensolaris/uts/powerpc/dtrace/fasttrap_isa.c (revision 1f4bcc459a76b7aa664f3fd557684cd0ba6da352)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /* Portions Copyright 2013 Justin Hibbits */
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/fasttrap_isa.h>
28 #include <sys/fasttrap_impl.h>
29 #include <sys/dtrace.h>
30 #include <sys/dtrace_impl.h>
31 #include <cddl/dev/dtrace/dtrace_cddl.h>
32 #include <sys/proc.h>
33 #include <sys/types.h>
34 #include <sys/uio.h>
35 #include <sys/ptrace.h>
36 #include <sys/sysent.h>
37 
38 #define OP(x)	((x) >> 26)
39 #define OPX(x)	(((x) >> 2) & 0x3FF)
40 #define OP_BO(x) (((x) & 0x03E00000) >> 21)
41 #define OP_BI(x) (((x) & 0x001F0000) >> 16)
42 #define OP_RS(x) (((x) & 0x03E00000) >> 21)
43 #define OP_RA(x) (((x) & 0x001F0000) >> 16)
44 #define OP_RB(x) (((x) & 0x0000F100) >> 11)
45 
46 static int
47 uread(proc_t *p, void *kaddr, size_t len, uintptr_t uaddr)
48 {
49 	ssize_t n;
50 
51 	PHOLD(p);
52 	n = proc_readmem(curthread, p, uaddr, kaddr, len);
53 	PRELE(p);
54 	if (n <= 0 || n < len)
55 		return (ENOMEM);
56 	return (0);
57 }
58 
59 static int
60 uwrite(proc_t *p, void *kaddr, size_t len, uintptr_t uaddr)
61 {
62 	ssize_t n;
63 
64 	PHOLD(p);
65 	n = proc_writemem(curthread, p, uaddr, kaddr, len);
66 	PRELE(p);
67 	if (n <= 0 || n < len)
68 		return (ENOMEM);
69 	return (0);
70 }
71 
72 int
73 fasttrap_tracepoint_install(proc_t *p, fasttrap_tracepoint_t *tp)
74 {
75 	fasttrap_instr_t instr = FASTTRAP_INSTR;
76 
77 	if (uwrite(p, &instr, 4, tp->ftt_pc) != 0)
78 		return (-1);
79 
80 	return (0);
81 }
82 
83 int
84 fasttrap_tracepoint_remove(proc_t *p, fasttrap_tracepoint_t *tp)
85 {
86 	uint32_t instr;
87 
88 	/*
89 	 * Distinguish between read or write failures and a changed
90 	 * instruction.
91 	 */
92 	if (uread(p, &instr, 4, tp->ftt_pc) != 0)
93 		return (0);
94 	if (instr != FASTTRAP_INSTR)
95 		return (0);
96 	if (uwrite(p, &tp->ftt_instr, 4, tp->ftt_pc) != 0)
97 		return (-1);
98 
99 	return (0);
100 }
101 
102 int
103 fasttrap_tracepoint_init(proc_t *p, fasttrap_tracepoint_t *tp, uintptr_t pc,
104     fasttrap_probe_type_t type)
105 {
106 	uint32_t instr;
107 	//int32_t disp;
108 
109 	/*
110 	 * Read the instruction at the given address out of the process's
111 	 * address space. We don't have to worry about a debugger
112 	 * changing this instruction before we overwrite it with our trap
113 	 * instruction since P_PR_LOCK is set.
114 	 */
115 	if (uread(p, &instr, 4, pc) != 0)
116 		return (-1);
117 
118 	/*
119 	 * Decode the instruction to fill in the probe flags. We can have
120 	 * the process execute most instructions on its own using a pc/npc
121 	 * trick, but pc-relative control transfer present a problem since
122 	 * we're relocating the instruction. We emulate these instructions
123 	 * in the kernel. We assume a default type and over-write that as
124 	 * needed.
125 	 *
126 	 * pc-relative instructions must be emulated for correctness;
127 	 * other instructions (which represent a large set of commonly traced
128 	 * instructions) are emulated or otherwise optimized for performance.
129 	 */
130 	tp->ftt_type = FASTTRAP_T_COMMON;
131 	tp->ftt_instr = instr;
132 
133 	switch (OP(instr)) {
134 	/* The following are invalid for trapping (invalid opcodes, tw/twi). */
135 	case 0:
136 	case 1:
137 	case 2:
138 	case 4:
139 	case 5:
140 	case 6:
141 	case 30:
142 	case 39:
143 	case 58:
144 	case 62:
145 	case 3:	/* twi */
146 		return (-1);
147 	case 31:	/* tw */
148 		if (OPX(instr) == 4)
149 			return (-1);
150 		else if (OPX(instr) == 444 && OP_RS(instr) == OP_RA(instr) &&
151 		    OP_RS(instr) == OP_RB(instr))
152 			tp->ftt_type = FASTTRAP_T_NOP;
153 		break;
154 	case 16:
155 		tp->ftt_type = FASTTRAP_T_BC;
156 		tp->ftt_dest = instr & 0x0000FFFC; /* Extract target address */
157 		if (instr & 0x00008000)
158 			tp->ftt_dest |= 0xFFFF0000;
159 		/* Use as offset if not absolute address. */
160 		if (!(instr & 0x02))
161 			tp->ftt_dest += pc;
162 		tp->ftt_bo = OP_BO(instr);
163 		tp->ftt_bi = OP_BI(instr);
164 		break;
165 	case 18:
166 		tp->ftt_type = FASTTRAP_T_B;
167 		tp->ftt_dest = instr & 0x03FFFFFC; /* Extract target address */
168 		if (instr & 0x02000000)
169 			tp->ftt_dest |= 0xFC000000;
170 		/* Use as offset if not absolute address. */
171 		if (!(instr & 0x02))
172 			tp->ftt_dest += pc;
173 		break;
174 	case 19:
175 		switch (OPX(instr)) {
176 		case 528:	/* bcctr */
177 			tp->ftt_type = FASTTRAP_T_BCTR;
178 			tp->ftt_bo = OP_BO(instr);
179 			tp->ftt_bi = OP_BI(instr);
180 			break;
181 		case 16:	/* bclr */
182 			tp->ftt_type = FASTTRAP_T_BCTR;
183 			tp->ftt_bo = OP_BO(instr);
184 			tp->ftt_bi = OP_BI(instr);
185 			break;
186 		};
187 		break;
188 	case 24:
189 		if (OP_RS(instr) == OP_RA(instr) &&
190 		    (instr & 0x0000FFFF) == 0)
191 			tp->ftt_type = FASTTRAP_T_NOP;
192 		break;
193 	};
194 
195 	/*
196 	 * We don't know how this tracepoint is going to be used, but in case
197 	 * it's used as part of a function return probe, we need to indicate
198 	 * whether it's always a return site or only potentially a return
199 	 * site. If it's part of a return probe, it's always going to be a
200 	 * return from that function if it's a restore instruction or if
201 	 * the previous instruction was a return. If we could reliably
202 	 * distinguish jump tables from return sites, this wouldn't be
203 	 * necessary.
204 	 */
205 #if 0
206 	if (tp->ftt_type != FASTTRAP_T_RESTORE &&
207 	    (uread(p, &instr, 4, pc - sizeof (instr)) != 0 ||
208 	    !(OP(instr) == 2 && OP3(instr) == OP3_RETURN)))
209 		tp->ftt_flags |= FASTTRAP_F_RETMAYBE;
210 #endif
211 
212 	return (0);
213 }
214 
215 static uint64_t
216 fasttrap_anarg(struct reg *rp, int argno)
217 {
218 	uint64_t value;
219 	proc_t  *p = curproc;
220 
221 	/* The first 8 arguments are in registers. */
222 	if (argno < 8)
223 		return rp->fixreg[argno + 3];
224 
225 	/* Arguments on stack start after SP+LR (2 register slots). */
226 	if (SV_PROC_FLAG(p, SV_ILP32)) {
227 		DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
228 		value = dtrace_fuword32((void *)(rp->fixreg[1] + 8 +
229 		    ((argno - 8) * sizeof(uint32_t))));
230 		DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | CPU_DTRACE_BADADDR);
231 	} else {
232 		DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
233 		value = dtrace_fuword64((void *)(rp->fixreg[1] + 48 +
234 		    ((argno - 8) * sizeof(uint64_t))));
235 		DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | CPU_DTRACE_BADADDR);
236 	}
237 	return value;
238 }
239 
240 uint64_t
241 fasttrap_pid_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
242     int aframes)
243 {
244 	struct reg r;
245 
246 	fill_regs(curthread, &r);
247 
248 	return (fasttrap_anarg(&r, argno));
249 }
250 
251 uint64_t
252 fasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
253     int aframes)
254 {
255 	struct reg r;
256 
257 	fill_regs(curthread, &r);
258 
259 	return (fasttrap_anarg(&r, argno));
260 }
261 
262 static void
263 fasttrap_usdt_args(fasttrap_probe_t *probe, struct reg *rp, int argc,
264     uintptr_t *argv)
265 {
266 	int i, x, cap = MIN(argc, probe->ftp_nargs);
267 
268 	for (i = 0; i < cap; i++) {
269 		x = probe->ftp_argmap[i];
270 
271 		if (x < 8)
272 			argv[i] = rp->fixreg[x];
273 		else
274 			if (SV_PROC_FLAG(curproc, SV_ILP32))
275 				argv[i] = fuword32((void *)(rp->fixreg[1] + 8 +
276 				    (x * sizeof(uint32_t))));
277 			else
278 				argv[i] = fuword64((void *)(rp->fixreg[1] + 48 +
279 				    (x * sizeof(uint64_t))));
280 	}
281 
282 	for (; i < argc; i++) {
283 		argv[i] = 0;
284 	}
285 }
286 
287 static void
288 fasttrap_return_common(struct reg *rp, uintptr_t pc, pid_t pid,
289     uintptr_t new_pc)
290 {
291 	fasttrap_tracepoint_t *tp;
292 	fasttrap_bucket_t *bucket;
293 	fasttrap_id_t *id;
294 
295 	bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];
296 
297 	for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
298 		if (pid == tp->ftt_pid && pc == tp->ftt_pc &&
299 		    tp->ftt_proc->ftpc_acount != 0)
300 			break;
301 	}
302 
303 	/*
304 	 * Don't sweat it if we can't find the tracepoint again; unlike
305 	 * when we're in fasttrap_pid_probe(), finding the tracepoint here
306 	 * is not essential to the correct execution of the process.
307 	 */
308 	if (tp == NULL) {
309 		return;
310 	}
311 
312 	for (id = tp->ftt_retids; id != NULL; id = id->fti_next) {
313 		/*
314 		 * If there's a branch that could act as a return site, we
315 		 * need to trace it, and check here if the program counter is
316 		 * external to the function.
317 		 */
318 		/* Skip function-local branches. */
319 		if ((new_pc - id->fti_probe->ftp_faddr) < id->fti_probe->ftp_fsize)
320 			continue;
321 
322 		dtrace_probe(id->fti_probe->ftp_id,
323 		    pc - id->fti_probe->ftp_faddr,
324 		    rp->fixreg[3], rp->fixreg[4], 0, 0);
325 	}
326 }
327 
328 
329 static int
330 fasttrap_branch_taken(int bo, int bi, struct reg *regs)
331 {
332 	int crzero = 0;
333 
334 	/* Branch always? */
335 	if ((bo & 0x14) == 0x14)
336 		return 1;
337 
338 	/* Handle decrementing ctr */
339 	if (!(bo & 0x04)) {
340 		--regs->ctr;
341 		crzero = (regs->ctr == 0);
342 		if (bo & 0x10) {
343 			return (!(crzero ^ (bo >> 1)));
344 		}
345 	}
346 
347 	return (crzero | (((regs->cr >> (31 - bi)) ^ (bo >> 3)) ^ 1));
348 }
349 
350 
351 int
352 fasttrap_pid_probe(struct reg *rp)
353 {
354 	proc_t *p = curproc;
355 	uintptr_t pc = rp->pc;
356 	uintptr_t new_pc = 0;
357 	fasttrap_bucket_t *bucket;
358 	fasttrap_tracepoint_t *tp, tp_local;
359 	pid_t pid;
360 	dtrace_icookie_t cookie;
361 	uint_t is_enabled = 0;
362 
363 	/*
364 	 * It's possible that a user (in a veritable orgy of bad planning)
365 	 * could redirect this thread's flow of control before it reached the
366 	 * return probe fasttrap. In this case we need to kill the process
367 	 * since it's in a unrecoverable state.
368 	 */
369 	if (curthread->t_dtrace_step) {
370 		ASSERT(curthread->t_dtrace_on);
371 		fasttrap_sigtrap(p, curthread, pc);
372 		return (0);
373 	}
374 
375 	/*
376 	 * Clear all user tracing flags.
377 	 */
378 	curthread->t_dtrace_ft = 0;
379 	curthread->t_dtrace_pc = 0;
380 	curthread->t_dtrace_npc = 0;
381 	curthread->t_dtrace_scrpc = 0;
382 	curthread->t_dtrace_astpc = 0;
383 
384 
385 	PROC_LOCK(p);
386 	pid = p->p_pid;
387 	bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];
388 
389 	/*
390 	 * Lookup the tracepoint that the process just hit.
391 	 */
392 	for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
393 		if (pid == tp->ftt_pid && pc == tp->ftt_pc &&
394 		    tp->ftt_proc->ftpc_acount != 0)
395 			break;
396 	}
397 
398 	/*
399 	 * If we couldn't find a matching tracepoint, either a tracepoint has
400 	 * been inserted without using the pid<pid> ioctl interface (see
401 	 * fasttrap_ioctl), or somehow we have mislaid this tracepoint.
402 	 */
403 	if (tp == NULL) {
404 		PROC_UNLOCK(p);
405 		return (-1);
406 	}
407 
408 	if (tp->ftt_ids != NULL) {
409 		fasttrap_id_t *id;
410 
411 		for (id = tp->ftt_ids; id != NULL; id = id->fti_next) {
412 			fasttrap_probe_t *probe = id->fti_probe;
413 
414 			if (id->fti_ptype == DTFTP_ENTRY) {
415 				/*
416 				 * We note that this was an entry
417 				 * probe to help ustack() find the
418 				 * first caller.
419 				 */
420 				cookie = dtrace_interrupt_disable();
421 				DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY);
422 				dtrace_probe(probe->ftp_id, rp->fixreg[3],
423 						rp->fixreg[4], rp->fixreg[5], rp->fixreg[6],
424 						rp->fixreg[7]);
425 				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY);
426 				dtrace_interrupt_enable(cookie);
427 			} else if (id->fti_ptype == DTFTP_IS_ENABLED) {
428 				/*
429 				 * Note that in this case, we don't
430 				 * call dtrace_probe() since it's only
431 				 * an artificial probe meant to change
432 				 * the flow of control so that it
433 				 * encounters the true probe.
434 				 */
435 				is_enabled = 1;
436 			} else if (probe->ftp_argmap == NULL) {
437 				dtrace_probe(probe->ftp_id, rp->fixreg[3],
438 				    rp->fixreg[4], rp->fixreg[5], rp->fixreg[6],
439 				    rp->fixreg[7]);
440 			} else {
441 				uintptr_t t[5];
442 
443 				fasttrap_usdt_args(probe, rp,
444 				    sizeof (t) / sizeof (t[0]), t);
445 
446 				dtrace_probe(probe->ftp_id, t[0], t[1],
447 				    t[2], t[3], t[4]);
448 			}
449 		}
450 	}
451 
452 	/*
453 	 * We're about to do a bunch of work so we cache a local copy of
454 	 * the tracepoint to emulate the instruction, and then find the
455 	 * tracepoint again later if we need to light up any return probes.
456 	 */
457 	tp_local = *tp;
458 	PROC_UNLOCK(p);
459 	tp = &tp_local;
460 
461 	/*
462 	 * If there's an is-enabled probe connected to this tracepoint it
463 	 * means that there was a 'xor r3, r3, r3'
464 	 * instruction that was placed there by DTrace when the binary was
465 	 * linked. As this probe is, in fact, enabled, we need to stuff 1
466 	 * into R3. Accordingly, we can bypass all the instruction
467 	 * emulation logic since we know the inevitable result. It's possible
468 	 * that a user could construct a scenario where the 'is-enabled'
469 	 * probe was on some other instruction, but that would be a rather
470 	 * exotic way to shoot oneself in the foot.
471 	 */
472 	if (is_enabled) {
473 		rp->fixreg[3] = 1;
474 		new_pc = rp->pc + 4;
475 		goto done;
476 	}
477 
478 
479 	switch (tp->ftt_type) {
480 	case FASTTRAP_T_NOP:
481 		new_pc = rp->pc + 4;
482 		break;
483 	case FASTTRAP_T_BC:
484 		if (!fasttrap_branch_taken(tp->ftt_bo, tp->ftt_bi, rp))
485 			break;
486 		/* FALLTHROUGH */
487 	case FASTTRAP_T_B:
488 		if (tp->ftt_instr & 0x01)
489 			rp->lr = rp->pc + 4;
490 		new_pc = tp->ftt_dest;
491 		break;
492 	case FASTTRAP_T_BLR:
493 	case FASTTRAP_T_BCTR:
494 		if (!fasttrap_branch_taken(tp->ftt_bo, tp->ftt_bi, rp))
495 			break;
496 		/* FALLTHROUGH */
497 		if (tp->ftt_type == FASTTRAP_T_BCTR)
498 			new_pc = rp->ctr;
499 		else
500 			new_pc = rp->lr;
501 		if (tp->ftt_instr & 0x01)
502 			rp->lr = rp->pc + 4;
503 		break;
504 	case FASTTRAP_T_COMMON:
505 		break;
506 	};
507 done:
508 	/*
509 	 * If there were no return probes when we first found the tracepoint,
510 	 * we should feel no obligation to honor any return probes that were
511 	 * subsequently enabled -- they'll just have to wait until the next
512 	 * time around.
513 	 */
514 	if (tp->ftt_retids != NULL) {
515 		/*
516 		 * We need to wait until the results of the instruction are
517 		 * apparent before invoking any return probes. If this
518 		 * instruction was emulated we can just call
519 		 * fasttrap_return_common(); if it needs to be executed, we
520 		 * need to wait until the user thread returns to the kernel.
521 		 */
522 		if (tp->ftt_type != FASTTRAP_T_COMMON) {
523 			fasttrap_return_common(rp, pc, pid, new_pc);
524 		} else {
525 			ASSERT(curthread->t_dtrace_ret != 0);
526 			ASSERT(curthread->t_dtrace_pc == pc);
527 			ASSERT(curthread->t_dtrace_scrpc != 0);
528 			ASSERT(new_pc == curthread->t_dtrace_astpc);
529 		}
530 	}
531 
532 	rp->pc = new_pc;
533 	set_regs(curthread, rp);
534 
535 	return (0);
536 }
537 
538 int
539 fasttrap_return_probe(struct reg *rp)
540 {
541 	proc_t *p = curproc;
542 	uintptr_t pc = curthread->t_dtrace_pc;
543 	uintptr_t npc = curthread->t_dtrace_npc;
544 
545 	curthread->t_dtrace_pc = 0;
546 	curthread->t_dtrace_npc = 0;
547 	curthread->t_dtrace_scrpc = 0;
548 	curthread->t_dtrace_astpc = 0;
549 
550 	/*
551 	 * We set rp->pc to the address of the traced instruction so
552 	 * that it appears to dtrace_probe() that we're on the original
553 	 * instruction, and so that the user can't easily detect our
554 	 * complex web of lies. dtrace_return_probe() (our caller)
555 	 * will correctly set %pc after we return.
556 	 */
557 	rp->pc = pc;
558 
559 	fasttrap_return_common(rp, pc, p->p_pid, npc);
560 
561 	return (0);
562 }
563 
564