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