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 (fp->f_retaddr == (long)dtrace_invop_callsite) { 417 /* 418 * If we pass through the invalid op handler, we will 419 * use the pointer that it passed to the stack as the 420 * second argument to dtrace_invop() as the pointer to 421 * the stack. When using this stack, we must step 422 * beyond the EIP/RIP that was pushed when the trap was 423 * taken -- hence the "+ 1" below. 424 */ 425 stack = ((uintptr_t **)&fp[1])[1] + 1; 426 goto load; 427 } 428 429 } 430 431 /* 432 * We know that we did not come through a trap to get into 433 * dtrace_probe() -- the provider simply called dtrace_probe() 434 * directly. As this is the case, we need to shift the argument 435 * that we're looking for: the probe ID is the first argument to 436 * dtrace_probe(), so the argument n will actually be found where 437 * one would expect to find argument (n + 1). 438 */ 439 arg++; 440 441 stack = (uintptr_t *)&fp[1]; 442 443 load: 444 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 445 val = stack[arg]; 446 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); 447 448 return (val); 449 } 450 451 int 452 dtrace_getstackdepth(int aframes) 453 { 454 int depth = 0; 455 struct i386_frame *frame; 456 vm_offset_t ebp; 457 458 aframes++; 459 ebp = dtrace_getfp(); 460 frame = (struct i386_frame *)ebp; 461 depth++; 462 for(;;) { 463 if (!INKERNEL((long) frame)) 464 break; 465 if (!INKERNEL((long) frame->f_frame)) 466 break; 467 depth++; 468 if (frame->f_frame <= frame || 469 (vm_offset_t)frame->f_frame >= 470 (vm_offset_t)ebp + KSTACK_PAGES * PAGE_SIZE) 471 break; 472 frame = frame->f_frame; 473 } 474 if (depth < aframes) 475 return 0; 476 else 477 return depth - aframes; 478 } 479 480 ulong_t 481 dtrace_getreg(struct trapframe *rp, uint_t reg) 482 { 483 struct pcb *pcb; 484 int regmap[] = { /* Order is dependent on reg.d */ 485 REG_GS, /* 0 GS */ 486 REG_FS, /* 1 FS */ 487 REG_ES, /* 2 ES */ 488 REG_DS, /* 3 DS */ 489 REG_RDI, /* 4 EDI */ 490 REG_RSI, /* 5 ESI */ 491 REG_RBP, /* 6 EBP, REG_FP */ 492 REG_RSP, /* 7 ESP */ 493 REG_RBX, /* 8 EBX */ 494 REG_RDX, /* 9 EDX, REG_R1 */ 495 REG_RCX, /* 10 ECX */ 496 REG_RAX, /* 11 EAX, REG_R0 */ 497 REG_TRAPNO, /* 12 TRAPNO */ 498 REG_ERR, /* 13 ERR */ 499 REG_RIP, /* 14 EIP, REG_PC */ 500 REG_CS, /* 15 CS */ 501 REG_RFL, /* 16 EFL, REG_PS */ 502 REG_RSP, /* 17 UESP, REG_SP */ 503 REG_SS /* 18 SS */ 504 }; 505 506 if (reg > SS) { 507 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 508 return (0); 509 } 510 511 if (reg >= sizeof (regmap) / sizeof (int)) { 512 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 513 return (0); 514 } 515 516 reg = regmap[reg]; 517 518 switch(reg) { 519 case REG_GS: 520 if ((pcb = curthread->td_pcb) == NULL) { 521 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 522 return (0); 523 } 524 return (pcb->pcb_gs); 525 case REG_FS: 526 return (rp->tf_fs); 527 case REG_ES: 528 return (rp->tf_es); 529 case REG_DS: 530 return (rp->tf_ds); 531 case REG_RDI: 532 return (rp->tf_edi); 533 case REG_RSI: 534 return (rp->tf_esi); 535 case REG_RBP: 536 return (rp->tf_ebp); 537 case REG_RSP: 538 return (rp->tf_isp); 539 case REG_RBX: 540 return (rp->tf_ebx); 541 case REG_RCX: 542 return (rp->tf_ecx); 543 case REG_RAX: 544 return (rp->tf_eax); 545 case REG_TRAPNO: 546 return (rp->tf_trapno); 547 case REG_ERR: 548 return (rp->tf_err); 549 case REG_RIP: 550 return (rp->tf_eip); 551 case REG_CS: 552 return (rp->tf_cs); 553 case REG_RFL: 554 return (rp->tf_eflags); 555 #if 0 556 case REG_RSP: 557 return (rp->tf_esp); 558 #endif 559 case REG_SS: 560 return (rp->tf_ss); 561 default: 562 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 563 return (0); 564 } 565 } 566 567 static int 568 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 569 { 570 ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr); 571 572 if (uaddr + size >= kernelbase || uaddr + size < uaddr) { 573 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 574 cpu_core[curcpu].cpuc_dtrace_illval = uaddr; 575 return (0); 576 } 577 578 return (1); 579 } 580 581 void 582 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, 583 volatile uint16_t *flags) 584 { 585 if (dtrace_copycheck(uaddr, kaddr, size)) 586 dtrace_copy(uaddr, kaddr, size); 587 } 588 589 void 590 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, 591 volatile uint16_t *flags) 592 { 593 if (dtrace_copycheck(uaddr, kaddr, size)) 594 dtrace_copy(kaddr, uaddr, size); 595 } 596 597 void 598 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 599 volatile uint16_t *flags) 600 { 601 if (dtrace_copycheck(uaddr, kaddr, size)) 602 dtrace_copystr(uaddr, kaddr, size, flags); 603 } 604 605 void 606 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, 607 volatile uint16_t *flags) 608 { 609 if (dtrace_copycheck(uaddr, kaddr, size)) 610 dtrace_copystr(kaddr, uaddr, size, flags); 611 } 612 613 uint8_t 614 dtrace_fuword8(void *uaddr) 615 { 616 if ((uintptr_t)uaddr >= kernelbase) { 617 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 618 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 619 return (0); 620 } 621 return (dtrace_fuword8_nocheck(uaddr)); 622 } 623 624 uint16_t 625 dtrace_fuword16(void *uaddr) 626 { 627 if ((uintptr_t)uaddr >= kernelbase) { 628 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 629 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 630 return (0); 631 } 632 return (dtrace_fuword16_nocheck(uaddr)); 633 } 634 635 uint32_t 636 dtrace_fuword32(void *uaddr) 637 { 638 if ((uintptr_t)uaddr >= kernelbase) { 639 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 640 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 641 return (0); 642 } 643 return (dtrace_fuword32_nocheck(uaddr)); 644 } 645 646 uint64_t 647 dtrace_fuword64(void *uaddr) 648 { 649 if ((uintptr_t)uaddr >= kernelbase) { 650 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 651 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 652 return (0); 653 } 654 return (dtrace_fuword64_nocheck(uaddr)); 655 } 656