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 * $FreeBSD$ 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/pcpu.h> 35 36 #include <machine/frame.h> 37 #include <machine/md_var.h> 38 #include <machine/pcb.h> 39 #include <machine/stack.h> 40 41 #include <vm/vm.h> 42 #include <vm/vm_param.h> 43 #include <vm/pmap.h> 44 45 #include "regset.h" 46 47 extern uintptr_t kernbase; 48 uintptr_t kernelbase = (uintptr_t) &kernbase; 49 50 #define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK && \ 51 ((vm_offset_t)(va)) < VM_MAX_KERNEL_ADDRESS) 52 53 uint8_t dtrace_fuword8_nocheck(void *); 54 uint16_t dtrace_fuword16_nocheck(void *); 55 uint32_t dtrace_fuword32_nocheck(void *); 56 uint64_t dtrace_fuword64_nocheck(void *); 57 58 void 59 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, 60 uint32_t *intrpc) 61 { 62 int depth = 0; 63 register_t ebp; 64 struct i386_frame *frame; 65 vm_offset_t callpc; 66 pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller; 67 68 if (intrpc != 0) 69 pcstack[depth++] = (pc_t) intrpc; 70 71 aframes++; 72 73 __asm __volatile("movl %%ebp,%0" : "=r" (ebp)); 74 75 frame = (struct i386_frame *)ebp; 76 while (depth < pcstack_limit) { 77 if (!INKERNEL(frame)) 78 break; 79 80 callpc = frame->f_retaddr; 81 82 if (!INKERNEL(callpc)) 83 break; 84 85 if (aframes > 0) { 86 aframes--; 87 if ((aframes == 0) && (caller != 0)) { 88 pcstack[depth++] = caller; 89 } 90 } 91 else { 92 pcstack[depth++] = callpc; 93 } 94 95 if (frame->f_frame <= frame || 96 (vm_offset_t)frame->f_frame >= 97 (vm_offset_t)ebp + KSTACK_PAGES * PAGE_SIZE) 98 break; 99 frame = frame->f_frame; 100 } 101 102 for (; depth < pcstack_limit; depth++) { 103 pcstack[depth] = 0; 104 } 105 } 106 107 static int 108 dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc, 109 uintptr_t sp) 110 { 111 #ifdef notyet 112 proc_t *p = curproc; 113 uintptr_t oldcontext = lwp->lwp_oldcontext; /* XXX signal stack. */ 114 size_t s1, s2; 115 #endif 116 volatile uint16_t *flags = 117 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 118 int ret = 0; 119 120 ASSERT(pcstack == NULL || pcstack_limit > 0); 121 122 #ifdef notyet /* XXX signal stack. */ 123 if (p->p_model == DATAMODEL_NATIVE) { 124 s1 = sizeof (struct frame) + 2 * sizeof (long); 125 s2 = s1 + sizeof (siginfo_t); 126 } else { 127 s1 = sizeof (struct frame32) + 3 * sizeof (int); 128 s2 = s1 + sizeof (siginfo32_t); 129 } 130 #endif 131 132 while (pc != 0) { 133 ret++; 134 if (pcstack != NULL) { 135 *pcstack++ = (uint64_t)pc; 136 pcstack_limit--; 137 if (pcstack_limit <= 0) 138 break; 139 } 140 141 if (sp == 0) 142 break; 143 144 #ifdef notyet /* XXX signal stack. */ 145 if (oldcontext == sp + s1 || oldcontext == sp + s2) { 146 if (p->p_model == DATAMODEL_NATIVE) { 147 ucontext_t *ucp = (ucontext_t *)oldcontext; 148 greg_t *gregs = ucp->uc_mcontext.gregs; 149 150 sp = dtrace_fulword(&gregs[REG_FP]); 151 pc = dtrace_fulword(&gregs[REG_PC]); 152 153 oldcontext = dtrace_fulword(&ucp->uc_link); 154 } else { 155 ucontext32_t *ucp = (ucontext32_t *)oldcontext; 156 greg32_t *gregs = ucp->uc_mcontext.gregs; 157 158 sp = dtrace_fuword32(&gregs[EBP]); 159 pc = dtrace_fuword32(&gregs[EIP]); 160 161 oldcontext = dtrace_fuword32(&ucp->uc_link); 162 } 163 } else { 164 if (p->p_model == DATAMODEL_NATIVE) { 165 struct frame *fr = (struct frame *)sp; 166 167 pc = dtrace_fulword(&fr->fr_savpc); 168 sp = dtrace_fulword(&fr->fr_savfp); 169 } else { 170 struct frame32 *fr = (struct frame32 *)sp; 171 172 pc = dtrace_fuword32(&fr->fr_savpc); 173 sp = dtrace_fuword32(&fr->fr_savfp); 174 } 175 } 176 #else 177 pc = dtrace_fuword32((void *)(sp + 178 offsetof(struct i386_frame, f_retaddr))); 179 sp = dtrace_fuword32((void *)sp); 180 #endif /* ! notyet */ 181 182 /* 183 * This is totally bogus: if we faulted, we're going to clear 184 * the fault and break. This is to deal with the apparently 185 * broken Java stacks on x86. 186 */ 187 if (*flags & CPU_DTRACE_FAULT) { 188 *flags &= ~CPU_DTRACE_FAULT; 189 break; 190 } 191 } 192 193 return (ret); 194 } 195 196 void 197 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 198 { 199 proc_t *p = curproc; 200 struct trapframe *tf; 201 uintptr_t pc, sp, fp; 202 volatile uint16_t *flags = 203 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 204 int n; 205 206 if (*flags & CPU_DTRACE_FAULT) 207 return; 208 209 if (pcstack_limit <= 0) 210 return; 211 212 /* 213 * If there's no user context we still need to zero the stack. 214 */ 215 if (p == NULL || (tf = curthread->td_frame) == NULL) 216 goto zero; 217 218 *pcstack++ = (uint64_t)p->p_pid; 219 pcstack_limit--; 220 221 if (pcstack_limit <= 0) 222 return; 223 224 pc = tf->tf_eip; 225 fp = tf->tf_ebp; 226 sp = tf->tf_esp; 227 228 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 229 /* 230 * In an entry probe. The frame pointer has not yet been 231 * pushed (that happens in the function prologue). The 232 * best approach is to add the current pc as a missing top 233 * of stack and back the pc up to the caller, which is stored 234 * at the current stack pointer address since the call 235 * instruction puts it there right before the branch. 236 */ 237 238 *pcstack++ = (uint64_t)pc; 239 pcstack_limit--; 240 if (pcstack_limit <= 0) 241 return; 242 243 pc = dtrace_fuword32((void *) sp); 244 } 245 246 n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp); 247 ASSERT(n >= 0); 248 ASSERT(n <= pcstack_limit); 249 250 pcstack += n; 251 pcstack_limit -= n; 252 253 zero: 254 while (pcstack_limit-- > 0) 255 *pcstack++ = 0; 256 } 257 258 int 259 dtrace_getustackdepth(void) 260 { 261 proc_t *p = curproc; 262 struct trapframe *tf; 263 uintptr_t pc, fp, sp; 264 int n = 0; 265 266 if (p == NULL || (tf = curthread->td_frame) == NULL) 267 return (0); 268 269 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) 270 return (-1); 271 272 pc = tf->tf_eip; 273 fp = tf->tf_ebp; 274 sp = tf->tf_esp; 275 276 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 277 /* 278 * In an entry probe. The frame pointer has not yet been 279 * pushed (that happens in the function prologue). The 280 * best approach is to add the current pc as a missing top 281 * of stack and back the pc up to the caller, which is stored 282 * at the current stack pointer address since the call 283 * instruction puts it there right before the branch. 284 */ 285 286 pc = dtrace_fuword32((void *) sp); 287 n++; 288 } 289 290 n += dtrace_getustack_common(NULL, 0, pc, fp); 291 292 return (n); 293 } 294 295 void 296 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 297 { 298 proc_t *p = curproc; 299 struct trapframe *tf; 300 uintptr_t pc, sp, fp; 301 volatile uint16_t *flags = 302 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 303 #ifdef notyet /* XXX signal stack */ 304 uintptr_t oldcontext; 305 size_t s1, s2; 306 #endif 307 308 if (*flags & CPU_DTRACE_FAULT) 309 return; 310 311 if (pcstack_limit <= 0) 312 return; 313 314 /* 315 * If there's no user context we still need to zero the stack. 316 */ 317 if (p == NULL || (tf = curthread->td_frame) == NULL) 318 goto zero; 319 320 *pcstack++ = (uint64_t)p->p_pid; 321 pcstack_limit--; 322 323 if (pcstack_limit <= 0) 324 return; 325 326 pc = tf->tf_eip; 327 fp = tf->tf_ebp; 328 sp = tf->tf_esp; 329 330 #ifdef notyet /* XXX signal stack */ 331 oldcontext = lwp->lwp_oldcontext; 332 333 if (p->p_model == DATAMODEL_NATIVE) { 334 s1 = sizeof (struct frame) + 2 * sizeof (long); 335 s2 = s1 + sizeof (siginfo_t); 336 } else { 337 s1 = sizeof (struct frame32) + 3 * sizeof (int); 338 s2 = s1 + sizeof (siginfo32_t); 339 } 340 #endif 341 342 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 343 *pcstack++ = (uint64_t)pc; 344 *fpstack++ = 0; 345 pcstack_limit--; 346 if (pcstack_limit <= 0) 347 return; 348 349 pc = dtrace_fuword32((void *)sp); 350 } 351 352 while (pc != 0) { 353 *pcstack++ = (uint64_t)pc; 354 *fpstack++ = fp; 355 pcstack_limit--; 356 if (pcstack_limit <= 0) 357 break; 358 359 if (fp == 0) 360 break; 361 362 #ifdef notyet /* XXX signal stack */ 363 if (oldcontext == sp + s1 || oldcontext == sp + s2) { 364 if (p->p_model == DATAMODEL_NATIVE) { 365 ucontext_t *ucp = (ucontext_t *)oldcontext; 366 greg_t *gregs = ucp->uc_mcontext.gregs; 367 368 sp = dtrace_fulword(&gregs[REG_FP]); 369 pc = dtrace_fulword(&gregs[REG_PC]); 370 371 oldcontext = dtrace_fulword(&ucp->uc_link); 372 } else { 373 ucontext_t *ucp = (ucontext_t *)oldcontext; 374 greg_t *gregs = ucp->uc_mcontext.gregs; 375 376 sp = dtrace_fuword32(&gregs[EBP]); 377 pc = dtrace_fuword32(&gregs[EIP]); 378 379 oldcontext = dtrace_fuword32(&ucp->uc_link); 380 } 381 } else 382 #endif /* XXX */ 383 { 384 pc = dtrace_fuword32((void *)(fp + 385 offsetof(struct i386_frame, f_retaddr))); 386 fp = dtrace_fuword32((void *)fp); 387 } 388 389 /* 390 * This is totally bogus: if we faulted, we're going to clear 391 * the fault and break. This is to deal with the apparently 392 * broken Java stacks on x86. 393 */ 394 if (*flags & CPU_DTRACE_FAULT) { 395 *flags &= ~CPU_DTRACE_FAULT; 396 break; 397 } 398 } 399 400 zero: 401 while (pcstack_limit-- > 0) 402 *pcstack++ = 0; 403 } 404 405 uint64_t 406 dtrace_getarg(int arg, int aframes) 407 { 408 uintptr_t val; 409 struct i386_frame *fp = (struct i386_frame *)dtrace_getfp(); 410 uintptr_t *stack; 411 int i; 412 413 for (i = 1; i <= aframes; i++) { 414 fp = fp->f_frame; 415 416 if (P2ROUNDUP(fp->f_retaddr, 4) == 417 (long)dtrace_invop_callsite) { 418 /* 419 * If we pass through the invalid op handler, we will 420 * use the pointer that it passed to the stack as the 421 * second argument to dtrace_invop() as the pointer to 422 * the stack. When using this stack, we must step 423 * beyond the EIP/RIP that was pushed when the trap was 424 * taken -- hence the "+ 1" below. 425 */ 426 stack = ((uintptr_t **)&fp[1])[0] + 1; 427 goto load; 428 } 429 430 } 431 432 /* 433 * We know that we did not come through a trap to get into 434 * dtrace_probe() -- the provider simply called dtrace_probe() 435 * directly. As this is the case, we need to shift the argument 436 * that we're looking for: the probe ID is the first argument to 437 * dtrace_probe(), so the argument n will actually be found where 438 * one would expect to find argument (n + 1). 439 */ 440 arg++; 441 442 stack = (uintptr_t *)fp + 2; 443 444 load: 445 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 446 val = stack[arg]; 447 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); 448 449 return (val); 450 } 451 452 int 453 dtrace_getstackdepth(int aframes) 454 { 455 int depth = 0; 456 struct i386_frame *frame; 457 vm_offset_t ebp; 458 459 aframes++; 460 ebp = dtrace_getfp(); 461 frame = (struct i386_frame *)ebp; 462 depth++; 463 for(;;) { 464 if (!INKERNEL((long) frame)) 465 break; 466 if (!INKERNEL((long) frame->f_frame)) 467 break; 468 depth++; 469 if (frame->f_frame <= frame || 470 (vm_offset_t)frame->f_frame >= 471 (vm_offset_t)ebp + KSTACK_PAGES * PAGE_SIZE) 472 break; 473 frame = frame->f_frame; 474 } 475 if (depth < aframes) 476 return 0; 477 else 478 return depth - aframes; 479 } 480 481 ulong_t 482 dtrace_getreg(struct trapframe *rp, uint_t reg) 483 { 484 struct pcb *pcb; 485 int regmap[] = { /* Order is dependent on reg.d */ 486 REG_GS, /* 0 GS */ 487 REG_FS, /* 1 FS */ 488 REG_ES, /* 2 ES */ 489 REG_DS, /* 3 DS */ 490 REG_RDI, /* 4 EDI */ 491 REG_RSI, /* 5 ESI */ 492 REG_RBP, /* 6 EBP, REG_FP */ 493 REG_RSP, /* 7 ESP */ 494 REG_RBX, /* 8 EBX */ 495 REG_RDX, /* 9 EDX, REG_R1 */ 496 REG_RCX, /* 10 ECX */ 497 REG_RAX, /* 11 EAX, REG_R0 */ 498 REG_TRAPNO, /* 12 TRAPNO */ 499 REG_ERR, /* 13 ERR */ 500 REG_RIP, /* 14 EIP, REG_PC */ 501 REG_CS, /* 15 CS */ 502 REG_RFL, /* 16 EFL, REG_PS */ 503 REG_RSP, /* 17 UESP, REG_SP */ 504 REG_SS /* 18 SS */ 505 }; 506 507 if (reg > SS) { 508 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 509 return (0); 510 } 511 512 if (reg >= sizeof (regmap) / sizeof (int)) { 513 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 514 return (0); 515 } 516 517 reg = regmap[reg]; 518 519 switch(reg) { 520 case REG_GS: 521 if ((pcb = curthread->td_pcb) == NULL) { 522 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 523 return (0); 524 } 525 return (pcb->pcb_gs); 526 case REG_FS: 527 return (rp->tf_fs); 528 case REG_ES: 529 return (rp->tf_es); 530 case REG_DS: 531 return (rp->tf_ds); 532 case REG_RDI: 533 return (rp->tf_edi); 534 case REG_RSI: 535 return (rp->tf_esi); 536 case REG_RBP: 537 return (rp->tf_ebp); 538 case REG_RSP: 539 return (rp->tf_isp); 540 case REG_RBX: 541 return (rp->tf_ebx); 542 case REG_RCX: 543 return (rp->tf_ecx); 544 case REG_RAX: 545 return (rp->tf_eax); 546 case REG_TRAPNO: 547 return (rp->tf_trapno); 548 case REG_ERR: 549 return (rp->tf_err); 550 case REG_RIP: 551 return (rp->tf_eip); 552 case REG_CS: 553 return (rp->tf_cs); 554 case REG_RFL: 555 return (rp->tf_eflags); 556 #if 0 557 case REG_RSP: 558 return (rp->tf_esp); 559 #endif 560 case REG_SS: 561 return (rp->tf_ss); 562 default: 563 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 564 return (0); 565 } 566 } 567 568 static int 569 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 570 { 571 ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr); 572 573 if (uaddr + size >= kernelbase || uaddr + size < uaddr) { 574 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 575 cpu_core[curcpu].cpuc_dtrace_illval = uaddr; 576 return (0); 577 } 578 579 return (1); 580 } 581 582 void 583 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, 584 volatile uint16_t *flags) 585 { 586 if (dtrace_copycheck(uaddr, kaddr, size)) 587 dtrace_copy(uaddr, kaddr, size); 588 } 589 590 void 591 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, 592 volatile uint16_t *flags) 593 { 594 if (dtrace_copycheck(uaddr, kaddr, size)) 595 dtrace_copy(kaddr, uaddr, size); 596 } 597 598 void 599 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 600 volatile uint16_t *flags) 601 { 602 if (dtrace_copycheck(uaddr, kaddr, size)) 603 dtrace_copystr(uaddr, kaddr, size, flags); 604 } 605 606 void 607 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, 608 volatile uint16_t *flags) 609 { 610 if (dtrace_copycheck(uaddr, kaddr, size)) 611 dtrace_copystr(kaddr, uaddr, size, flags); 612 } 613 614 uint8_t 615 dtrace_fuword8(void *uaddr) 616 { 617 if ((uintptr_t)uaddr >= kernelbase) { 618 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 619 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 620 return (0); 621 } 622 return (dtrace_fuword8_nocheck(uaddr)); 623 } 624 625 uint16_t 626 dtrace_fuword16(void *uaddr) 627 { 628 if ((uintptr_t)uaddr >= kernelbase) { 629 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 630 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 631 return (0); 632 } 633 return (dtrace_fuword16_nocheck(uaddr)); 634 } 635 636 uint32_t 637 dtrace_fuword32(void *uaddr) 638 { 639 if ((uintptr_t)uaddr >= kernelbase) { 640 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 641 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 642 return (0); 643 } 644 return (dtrace_fuword32_nocheck(uaddr)); 645 } 646 647 uint64_t 648 dtrace_fuword64(void *uaddr) 649 { 650 if ((uintptr_t)uaddr >= kernelbase) { 651 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 652 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 653 return (0); 654 } 655 return (dtrace_fuword64_nocheck(uaddr)); 656 } 657