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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 * 22 * Portions Copyright 2012,2013 Justin Hibbits <jhibbits@freebsd.org> 23 */ 24 /* 25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 #include <sys/cdefs.h> 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/stack.h> 34 #include <sys/sysent.h> 35 #include <sys/pcpu.h> 36 37 #include <machine/frame.h> 38 #include <machine/md_var.h> 39 #include <machine/psl.h> 40 #include <machine/stack.h> 41 42 #include <vm/vm.h> 43 #include <vm/vm_param.h> 44 #include <vm/pmap.h> 45 46 #include "regset.h" 47 48 /* Offset to the LR Save word (ppc32) */ 49 #define RETURN_OFFSET 4 50 /* Offset to LR Save word (ppc64). CR Save area sits between back chain and LR */ 51 #define RETURN_OFFSET64 16 52 53 #ifdef __powerpc64__ 54 #define OFFSET 4 /* Account for the TOC reload slot */ 55 #define FRAME_OFFSET 48 56 #else 57 #define OFFSET 0 58 #define FRAME_OFFSET 8 59 #endif 60 61 #define INKERNEL(x) (((x) <= VM_MAX_KERNEL_ADDRESS && \ 62 (x) >= VM_MIN_KERNEL_ADDRESS) || \ 63 (PMAP_HAS_DMAP && (x) >= DMAP_BASE_ADDRESS && \ 64 (x) <= DMAP_MAX_ADDRESS)) 65 66 static __inline int 67 dtrace_sp_inkernel(uintptr_t sp) 68 { 69 struct trapframe *frame; 70 vm_offset_t callpc; 71 72 /* Not within the kernel, or not aligned. */ 73 if (!INKERNEL(sp) || (sp & 0xf) != 0) 74 return (0); 75 #ifdef __powerpc64__ 76 callpc = *(vm_offset_t *)(sp + RETURN_OFFSET64); 77 #else 78 callpc = *(vm_offset_t *)(sp + RETURN_OFFSET); 79 #endif 80 if ((callpc & 3) || (callpc < 0x100)) 81 return (0); 82 83 /* 84 * trapexit() and asttrapexit() are sentinels 85 * for kernel stack tracing. 86 */ 87 if (callpc + OFFSET == (vm_offset_t) &trapexit || 88 callpc + OFFSET == (vm_offset_t) &asttrapexit) { 89 frame = (struct trapframe *)(sp + FRAME_OFFSET); 90 91 return ((frame->srr1 & PSL_PR) == 0); 92 } 93 94 return (1); 95 } 96 97 static __inline void 98 dtrace_next_sp_pc(uintptr_t sp, uintptr_t *nsp, uintptr_t *pc, uintptr_t *lr) 99 { 100 vm_offset_t callpc; 101 struct trapframe *frame; 102 103 if (lr != 0 && *lr != 0) 104 callpc = *lr; 105 else 106 #ifdef __powerpc64__ 107 callpc = *(vm_offset_t *)(sp + RETURN_OFFSET64); 108 #else 109 callpc = *(vm_offset_t *)(sp + RETURN_OFFSET); 110 #endif 111 112 /* 113 * trapexit() and asttrapexit() are sentinels 114 * for kernel stack tracing. 115 */ 116 if ((callpc + OFFSET == (vm_offset_t) &trapexit || 117 callpc + OFFSET == (vm_offset_t) &asttrapexit)) { 118 /* Access the trap frame */ 119 frame = (struct trapframe *)(sp + FRAME_OFFSET); 120 121 if (nsp != NULL) 122 *nsp = frame->fixreg[1]; 123 if (pc != NULL) 124 *pc = frame->srr0; 125 if (lr != NULL) 126 *lr = frame->lr; 127 return; 128 } 129 130 if (nsp != NULL) 131 *nsp = *(uintptr_t *)sp; 132 if (pc != NULL) 133 *pc = callpc; 134 /* lr is only valid for trap frames */ 135 if (lr != NULL) 136 *lr = 0; 137 } 138 139 void 140 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, 141 uint32_t *intrpc) 142 { 143 int depth = 0; 144 uintptr_t osp, sp, lr = 0; 145 vm_offset_t callpc; 146 pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller; 147 148 osp = PAGE_SIZE; 149 if (intrpc != 0) 150 pcstack[depth++] = (pc_t) intrpc; 151 152 aframes++; 153 154 sp = (uintptr_t)__builtin_frame_address(0); 155 156 while (depth < pcstack_limit) { 157 if (sp <= osp) 158 break; 159 160 if (!dtrace_sp_inkernel(sp)) 161 break; 162 osp = sp; 163 dtrace_next_sp_pc(osp, &sp, &callpc, &lr); 164 165 if (aframes > 0) { 166 aframes--; 167 if ((aframes == 0) && (caller != 0)) { 168 pcstack[depth++] = caller; 169 } 170 } 171 else { 172 pcstack[depth++] = callpc; 173 } 174 } 175 176 for (; depth < pcstack_limit; depth++) { 177 pcstack[depth] = 0; 178 } 179 } 180 181 static int 182 dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc, 183 uintptr_t sp) 184 { 185 proc_t *p = curproc; 186 int ret = 0; 187 188 ASSERT(pcstack == NULL || pcstack_limit > 0); 189 190 while (pc != 0) { 191 ret++; 192 if (pcstack != NULL) { 193 *pcstack++ = (uint64_t)pc; 194 pcstack_limit--; 195 if (pcstack_limit <= 0) 196 break; 197 } 198 199 if (sp == 0) 200 break; 201 202 if (SV_PROC_FLAG(p, SV_ILP32)) { 203 pc = dtrace_fuword32((void *)(sp + RETURN_OFFSET)); 204 sp = dtrace_fuword32((void *)sp); 205 } 206 else { 207 pc = dtrace_fuword64((void *)(sp + RETURN_OFFSET64)); 208 sp = dtrace_fuword64((void *)sp); 209 } 210 } 211 212 return (ret); 213 } 214 215 void 216 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 217 { 218 proc_t *p = curproc; 219 struct trapframe *tf; 220 uintptr_t pc, sp; 221 volatile uint16_t *flags = 222 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 223 int n; 224 225 if (*flags & CPU_DTRACE_FAULT) 226 return; 227 228 if (pcstack_limit <= 0) 229 return; 230 231 /* 232 * If there's no user context we still need to zero the stack. 233 */ 234 if (p == NULL || (tf = curthread->td_frame) == NULL) 235 goto zero; 236 237 *pcstack++ = (uint64_t)p->p_pid; 238 pcstack_limit--; 239 240 if (pcstack_limit <= 0) 241 return; 242 243 pc = tf->srr0; 244 sp = tf->fixreg[1]; 245 246 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 247 /* 248 * In an entry probe. The frame pointer has not yet been 249 * pushed (that happens in the function prologue). The 250 * best approach is to add the current pc as a missing top 251 * of stack and back the pc up to the caller, which is stored 252 * at the current stack pointer address since the call 253 * instruction puts it there right before the branch. 254 */ 255 256 *pcstack++ = (uint64_t)pc; 257 pcstack_limit--; 258 if (pcstack_limit <= 0) 259 return; 260 261 pc = tf->lr; 262 } 263 264 n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp); 265 ASSERT(n >= 0); 266 ASSERT(n <= pcstack_limit); 267 268 pcstack += n; 269 pcstack_limit -= n; 270 271 zero: 272 while (pcstack_limit-- > 0) 273 *pcstack++ = 0; 274 } 275 276 int 277 dtrace_getustackdepth(void) 278 { 279 proc_t *p = curproc; 280 struct trapframe *tf; 281 uintptr_t pc, sp; 282 int n = 0; 283 284 if (p == NULL || (tf = curthread->td_frame) == NULL) 285 return (0); 286 287 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) 288 return (-1); 289 290 pc = tf->srr0; 291 sp = tf->fixreg[1]; 292 293 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 294 /* 295 * In an entry probe. The frame pointer has not yet been 296 * pushed (that happens in the function prologue). The 297 * best approach is to add the current pc as a missing top 298 * of stack and back the pc up to the caller, which is stored 299 * at the current stack pointer address since the call 300 * instruction puts it there right before the branch. 301 */ 302 303 if (SV_PROC_FLAG(p, SV_ILP32)) { 304 pc = dtrace_fuword32((void *) sp); 305 } 306 else 307 pc = dtrace_fuword64((void *) sp); 308 n++; 309 } 310 311 n += dtrace_getustack_common(NULL, 0, pc, sp); 312 313 return (n); 314 } 315 316 void 317 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 318 { 319 proc_t *p = curproc; 320 struct trapframe *tf; 321 uintptr_t pc, sp; 322 volatile uint16_t *flags = 323 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 324 #ifdef notyet /* XXX signal stack */ 325 uintptr_t oldcontext; 326 size_t s1, s2; 327 #endif 328 329 if (*flags & CPU_DTRACE_FAULT) 330 return; 331 332 if (pcstack_limit <= 0) 333 return; 334 335 /* 336 * If there's no user context we still need to zero the stack. 337 */ 338 if (p == NULL || (tf = curthread->td_frame) == NULL) 339 goto zero; 340 341 *pcstack++ = (uint64_t)p->p_pid; 342 pcstack_limit--; 343 344 if (pcstack_limit <= 0) 345 return; 346 347 pc = tf->srr0; 348 sp = tf->fixreg[1]; 349 350 #ifdef notyet /* XXX signal stack */ 351 oldcontext = lwp->lwp_oldcontext; 352 s1 = sizeof (struct xframe) + 2 * sizeof (long); 353 s2 = s1 + sizeof (siginfo_t); 354 #endif 355 356 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 357 *pcstack++ = (uint64_t)pc; 358 *fpstack++ = 0; 359 pcstack_limit--; 360 if (pcstack_limit <= 0) 361 return; 362 363 if (SV_PROC_FLAG(p, SV_ILP32)) { 364 pc = dtrace_fuword32((void *)sp); 365 } 366 else { 367 pc = dtrace_fuword64((void *)sp); 368 } 369 } 370 371 while (pc != 0) { 372 *pcstack++ = (uint64_t)pc; 373 *fpstack++ = sp; 374 pcstack_limit--; 375 if (pcstack_limit <= 0) 376 break; 377 378 if (sp == 0) 379 break; 380 381 #ifdef notyet /* XXX signal stack */ 382 if (oldcontext == sp + s1 || oldcontext == sp + s2) { 383 ucontext_t *ucp = (ucontext_t *)oldcontext; 384 greg_t *gregs = ucp->uc_mcontext.gregs; 385 386 sp = dtrace_fulword(&gregs[REG_FP]); 387 pc = dtrace_fulword(&gregs[REG_PC]); 388 389 oldcontext = dtrace_fulword(&ucp->uc_link); 390 } else 391 #endif /* XXX */ 392 { 393 if (SV_PROC_FLAG(p, SV_ILP32)) { 394 pc = dtrace_fuword32((void *)(sp + RETURN_OFFSET)); 395 sp = dtrace_fuword32((void *)sp); 396 } 397 else { 398 pc = dtrace_fuword64((void *)(sp + RETURN_OFFSET64)); 399 sp = dtrace_fuword64((void *)sp); 400 } 401 } 402 403 /* 404 * This is totally bogus: if we faulted, we're going to clear 405 * the fault and break. This is to deal with the apparently 406 * broken Java stacks on x86. 407 */ 408 if (*flags & CPU_DTRACE_FAULT) { 409 *flags &= ~CPU_DTRACE_FAULT; 410 break; 411 } 412 } 413 414 zero: 415 while (pcstack_limit-- > 0) 416 *pcstack++ = 0; 417 } 418 419 /*ARGSUSED*/ 420 uint64_t 421 dtrace_getarg(int arg, int aframes) 422 { 423 uintptr_t val; 424 uintptr_t *fp = (uintptr_t *)__builtin_frame_address(0); 425 uintptr_t *stack; 426 int i; 427 428 /* 429 * A total of 8 arguments are passed via registers; any argument with 430 * index of 7 or lower is therefore in a register. 431 */ 432 int inreg = 7; 433 434 for (i = 1; i <= aframes; i++) { 435 fp = (uintptr_t *)*fp; 436 437 /* 438 * On ppc32 trapexit() is the immediately following label. On 439 * ppc64 AIM trapexit() follows a nop. 440 */ 441 #ifdef __powerpc64__ 442 if ((long)(fp[2]) + 4 == (long)trapexit) { 443 #else 444 if ((long)(fp[1]) == (long)trapexit) { 445 #endif 446 /* 447 * In the case of powerpc, we will use the pointer to the regs 448 * structure that was pushed when we took the trap. To get this 449 * structure, we must increment beyond the frame structure. If the 450 * argument that we're seeking is passed on the stack, we'll pull 451 * the true stack pointer out of the saved registers and decrement 452 * our argument by the number of arguments passed in registers; if 453 * the argument we're seeking is passed in regsiters, we can just 454 * load it directly. 455 */ 456 #ifdef __powerpc64__ 457 struct reg *rp = (struct reg *)((uintptr_t)fp[0] + 48); 458 #else 459 struct reg *rp = (struct reg *)((uintptr_t)fp[0] + 8); 460 #endif 461 462 if (arg <= inreg) { 463 stack = &rp->fixreg[3]; 464 } else { 465 stack = (uintptr_t *)(rp->fixreg[1]); 466 arg -= inreg; 467 } 468 goto load; 469 } 470 471 } 472 473 /* 474 * We know that we did not come through a trap to get into 475 * dtrace_probe() -- the provider simply called dtrace_probe() 476 * directly. As this is the case, we need to shift the argument 477 * that we're looking for: the probe ID is the first argument to 478 * dtrace_probe(), so the argument n will actually be found where 479 * one would expect to find argument (n + 1). 480 */ 481 arg++; 482 483 if (arg <= inreg) { 484 /* 485 * This shouldn't happen. If the argument is passed in a 486 * register then it should have been, well, passed in a 487 * register... 488 */ 489 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 490 return (0); 491 } 492 493 arg -= (inreg + 1); 494 stack = fp + 2; 495 496 load: 497 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 498 val = stack[arg]; 499 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); 500 501 return (val); 502 } 503 504 int 505 dtrace_getstackdepth(int aframes) 506 { 507 int depth = 0; 508 uintptr_t osp, sp; 509 vm_offset_t callpc; 510 511 osp = PAGE_SIZE; 512 sp = (uintptr_t)__builtin_frame_address(0); 513 for(;;) { 514 if (sp <= osp) 515 break; 516 517 if (!dtrace_sp_inkernel(sp)) 518 break; 519 520 depth++; 521 osp = sp; 522 dtrace_next_sp_pc(sp, &sp, NULL, NULL); 523 } 524 if (depth < aframes) 525 return (0); 526 527 return (depth - aframes); 528 } 529 530 ulong_t 531 dtrace_getreg(struct trapframe *frame, uint_t reg) 532 { 533 if (reg < 32) 534 return (frame->fixreg[reg]); 535 536 switch (reg) { 537 case 32: 538 return (frame->lr); 539 case 33: 540 return (frame->cr); 541 case 34: 542 return (frame->xer); 543 case 35: 544 return (frame->ctr); 545 case 36: 546 return (frame->srr0); 547 case 37: 548 return (frame->srr1); 549 case 38: 550 return (frame->exc); 551 default: 552 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 553 return (0); 554 } 555 } 556 557 static int 558 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 559 { 560 ASSERT(INKERNEL(kaddr) && kaddr + size >= kaddr); 561 562 if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) { 563 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 564 cpu_core[curcpu].cpuc_dtrace_illval = uaddr; 565 return (0); 566 } 567 568 return (1); 569 } 570 571 void 572 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, 573 volatile uint16_t *flags) 574 { 575 if (dtrace_copycheck(uaddr, kaddr, size)) 576 if (copyin((const void *)uaddr, (void *)kaddr, size)) { 577 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 578 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 579 } 580 } 581 582 void 583 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, 584 volatile uint16_t *flags) 585 { 586 if (dtrace_copycheck(uaddr, kaddr, size)) { 587 if (copyout((const void *)kaddr, (void *)uaddr, size)) { 588 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 589 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 590 } 591 } 592 } 593 594 void 595 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 596 volatile uint16_t *flags) 597 { 598 size_t actual; 599 int error; 600 601 if (dtrace_copycheck(uaddr, kaddr, size)) { 602 error = copyinstr((const void *)uaddr, (void *)kaddr, 603 size, &actual); 604 605 /* ENAMETOOLONG is not a fault condition. */ 606 if (error && error != ENAMETOOLONG) { 607 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 608 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 609 } 610 } 611 } 612 613 /* 614 * The bulk of this function could be replaced to match dtrace_copyinstr() 615 * if we ever implement a copyoutstr(). 616 */ 617 void 618 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, 619 volatile uint16_t *flags) 620 { 621 size_t len; 622 623 if (dtrace_copycheck(uaddr, kaddr, size)) { 624 len = strlen((const char *)kaddr); 625 if (len > size) 626 len = size; 627 628 if (copyout((const void *)kaddr, (void *)uaddr, len)) { 629 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 630 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 631 } 632 } 633 } 634 635 uint8_t 636 dtrace_fuword8(void *uaddr) 637 { 638 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 639 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 640 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 641 return (0); 642 } 643 return (fubyte(uaddr)); 644 } 645 646 uint16_t 647 dtrace_fuword16(void *uaddr) 648 { 649 uint16_t ret = 0; 650 651 if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) { 652 if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) { 653 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 654 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 655 } 656 } 657 return ret; 658 } 659 660 uint32_t 661 dtrace_fuword32(void *uaddr) 662 { 663 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 664 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 665 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 666 return (0); 667 } 668 return (fuword32(uaddr)); 669 } 670 671 uint64_t 672 dtrace_fuword64(void *uaddr) 673 { 674 uint64_t ret = 0; 675 676 if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) { 677 if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) { 678 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 679 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 680 } 681 } 682 return ret; 683 } 684 685 uintptr_t 686 dtrace_fulword(void *uaddr) 687 { 688 uintptr_t ret = 0; 689 690 if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) { 691 if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) { 692 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 693 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 694 } 695 } 696 return ret; 697 } 698