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