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