1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1710 ahl * Common Development and Distribution License (the "License"). 6 1710 ahl * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 1048 raf 22 0 stevel /* 23 3944 ahl * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel */ 26 0 stevel 27 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 28 0 stevel 29 0 stevel #include <sys/fasttrap_isa.h> 30 0 stevel #include <sys/fasttrap_impl.h> 31 0 stevel #include <sys/dtrace.h> 32 0 stevel #include <sys/dtrace_impl.h> 33 0 stevel #include <sys/cmn_err.h> 34 0 stevel #include <sys/frame.h> 35 0 stevel #include <sys/stack.h> 36 0 stevel #include <sys/sysmacros.h> 37 0 stevel #include <sys/trap.h> 38 0 stevel 39 0 stevel #include <v9/sys/machpcb.h> 40 0 stevel #include <v9/sys/privregs.h> 41 0 stevel 42 0 stevel /* 43 0 stevel * Lossless User-Land Tracing on SPARC 44 0 stevel * ----------------------------------- 45 0 stevel * 46 0 stevel * The Basic Idea 47 0 stevel * 48 0 stevel * The most important design constraint is, of course, correct execution of 49 0 stevel * the user thread above all else. The next most important goal is rapid 50 0 stevel * execution. We combine execution of instructions in user-land with 51 0 stevel * emulation of certain instructions in the kernel to aim for complete 52 0 stevel * correctness and maximal performance. 53 0 stevel * 54 0 stevel * We take advantage of the split PC/NPC architecture to speed up logical 55 0 stevel * single-stepping; when we copy an instruction out to the scratch space in 56 0 stevel * the ulwp_t structure (held in the %g7 register on SPARC), we can 57 0 stevel * effectively single step by setting the PC to our scratch space and leaving 58 0 stevel * the NPC alone. This executes the replaced instruction and then continues 59 0 stevel * on without having to reenter the kernel as with single- stepping. The 60 0 stevel * obvious caveat is for instructions whose execution is PC dependant -- 61 0 stevel * branches, call and link instructions (call and jmpl), and the rdpc 62 0 stevel * instruction. These instructions cannot be executed in the manner described 63 0 stevel * so they must be emulated in the kernel. 64 0 stevel * 65 0 stevel * Emulation for this small set of instructions if fairly simple; the most 66 0 stevel * difficult part being emulating branch conditions. 67 0 stevel * 68 0 stevel * 69 0 stevel * A Cache Heavy Portfolio 70 0 stevel * 71 0 stevel * It's important to note at this time that copying an instruction out to the 72 0 stevel * ulwp_t scratch space in user-land is rather complicated. SPARC has 73 0 stevel * separate data and instruction caches so any writes to the D$ (using a 74 0 stevel * store instruction for example) aren't necessarily reflected in the I$. 75 0 stevel * The flush instruction can be used to synchronize the two and must be used 76 0 stevel * for any self-modifying code, but the flush instruction only applies to the 77 0 stevel * primary address space (the absence of a flusha analogue to the flush 78 0 stevel * instruction that accepts an ASI argument is an obvious omission from SPARC 79 0 stevel * v9 where the notion of the alternate address space was introduced on 80 0 stevel * SPARC). To correctly copy out the instruction we must use a block store 81 0 stevel * that doesn't allocate in the D$ and ensures synchronization with the I$; 82 0 stevel * see dtrace_blksuword32() for the implementation (this function uses 83 0 stevel * ASI_BLK_COMMIT_S to write a block through the secondary ASI in the manner 84 0 stevel * described). Refer to the UltraSPARC I/II manual for details on the 85 0 stevel * ASI_BLK_COMMIT_S ASI. 86 0 stevel * 87 0 stevel * 88 0 stevel * Return Subtleties 89 0 stevel * 90 0 stevel * When we're firing a return probe we need to expose the value returned by 91 0 stevel * the function being traced. Since the function can set the return value 92 0 stevel * in its last instruction, we need to fire the return probe only _after_ 93 0 stevel * the effects of the instruction are apparent. For instructions that we 94 0 stevel * emulate, we can call dtrace_probe() after we've performed the emulation; 95 0 stevel * for instructions that we execute after we return to user-land, we set 96 0 stevel * %pc to the instruction we copied out (as described above) and set %npc 97 0 stevel * to a trap instruction stashed in the ulwp_t structure. After the traced 98 0 stevel * instruction is executed, the trap instruction returns control to the 99 0 stevel * kernel where we can fire the return probe. 100 0 stevel * 101 0 stevel * This need for a second trap in cases where we execute the traced 102 0 stevel * instruction makes it all the more important to emulate the most common 103 0 stevel * instructions to avoid the second trip in and out of the kernel. 104 0 stevel * 105 0 stevel * 106 0 stevel * Making it Fast 107 0 stevel * 108 0 stevel * Since copying out an instruction is neither simple nor inexpensive for the 109 0 stevel * CPU, we should attempt to avoid doing it in as many cases as possible. 110 0 stevel * Since function entry and return are usually the most interesting probe 111 0 stevel * sites, we attempt to tune the performance of the fasttrap provider around 112 0 stevel * instructions typically in those places. 113 0 stevel * 114 0 stevel * Looking at a bunch of functions in libraries and executables reveals that 115 0 stevel * most functions begin with either a save or a sethi (to setup a larger 116 0 stevel * argument to the save) and end with a restore or an or (in the case of leaf 117 0 stevel * functions). To try to improve performance, we emulate all of these 118 0 stevel * instructions in the kernel. 119 0 stevel * 120 0 stevel * The save and restore instructions are a little tricky since they perform 121 0 stevel * register window maniplulation. Rather than trying to tinker with the 122 0 stevel * register windows from the kernel, we emulate the implicit add that takes 123 0 stevel * place as part of those instructions and set the %pc to point to a simple 124 0 stevel * save or restore we've hidden in the ulwp_t structure. If we're in a return 125 0 stevel * probe so want to make it seem as though the tracepoint has been completely 126 0 stevel * executed we need to remember that we've pulled this trick with restore and 127 0 stevel * pull registers from the previous window (the one that we'll switch to once 128 0 stevel * the simple store instruction is executed) rather than the current one. This 129 0 stevel * is why in the case of emulating a restore we set the DTrace CPU flag 130 0 stevel * CPU_DTRACE_FAKERESTORE before calling dtrace_probe() for the return probes 131 0 stevel * (see fasttrap_return_common()). 132 0 stevel */ 133 0 stevel 134 0 stevel #define OP(x) ((x) >> 30) 135 0 stevel #define OP2(x) (((x) >> 22) & 0x07) 136 0 stevel #define OP3(x) (((x) >> 19) & 0x3f) 137 0 stevel #define RCOND(x) (((x) >> 25) & 0x07) 138 0 stevel #define COND(x) (((x) >> 25) & 0x0f) 139 0 stevel #define A(x) (((x) >> 29) & 0x01) 140 0 stevel #define I(x) (((x) >> 13) & 0x01) 141 0 stevel #define RD(x) (((x) >> 25) & 0x1f) 142 0 stevel #define RS1(x) (((x) >> 14) & 0x1f) 143 0 stevel #define RS2(x) (((x) >> 0) & 0x1f) 144 0 stevel #define CC(x) (((x) >> 20) & 0x03) 145 0 stevel #define DISP16(x) ((((x) >> 6) & 0xc000) | ((x) & 0x3fff)) 146 0 stevel #define DISP22(x) ((x) & 0x3fffff) 147 0 stevel #define DISP19(x) ((x) & 0x7ffff) 148 0 stevel #define DISP30(x) ((x) & 0x3fffffff) 149 0 stevel #define SW_TRAP(x) ((x) & 0x7f) 150 0 stevel 151 0 stevel #define OP3_OR 0x02 152 0 stevel #define OP3_RD 0x28 153 0 stevel #define OP3_JMPL 0x38 154 0 stevel #define OP3_RETURN 0x39 155 0 stevel #define OP3_TCC 0x3a 156 0 stevel #define OP3_SAVE 0x3c 157 0 stevel #define OP3_RESTORE 0x3d 158 0 stevel 159 0 stevel #define OP3_PREFETCH 0x2d 160 0 stevel #define OP3_CASA 0x3c 161 0 stevel #define OP3_PREFETCHA 0x3d 162 0 stevel #define OP3_CASXA 0x3e 163 0 stevel 164 0 stevel #define OP2_ILLTRAP 0x0 165 0 stevel #define OP2_BPcc 0x1 166 0 stevel #define OP2_Bicc 0x2 167 0 stevel #define OP2_BPr 0x3 168 0 stevel #define OP2_SETHI 0x4 169 0 stevel #define OP2_FBPfcc 0x5 170 0 stevel #define OP2_FBfcc 0x6 171 0 stevel 172 0 stevel #define R_G0 0 173 0 stevel #define R_O0 8 174 0 stevel #define R_SP 14 175 0 stevel #define R_I0 24 176 0 stevel #define R_I1 25 177 0 stevel #define R_I2 26 178 0 stevel #define R_I3 27 179 4685 ahl #define R_I4 28 180 0 stevel 181 0 stevel /* 182 0 stevel * Check the comment in fasttrap.h when changing these offsets or adding 183 0 stevel * new instructions. 184 0 stevel */ 185 0 stevel #define FASTTRAP_OFF_SAVE 64 186 0 stevel #define FASTTRAP_OFF_RESTORE 68 187 0 stevel #define FASTTRAP_OFF_FTRET 72 188 0 stevel #define FASTTRAP_OFF_RETURN 76 189 0 stevel 190 0 stevel #define BREAKPOINT_INSTR 0x91d02001 /* ta 1 */ 191 0 stevel 192 0 stevel /* 193 0 stevel * Tunable to let users turn off the fancy save instruction optimization. 194 0 stevel * If a program is non-ABI compliant, there's a possibility that the save 195 0 stevel * instruction optimization could cause an error. 196 0 stevel */ 197 0 stevel int fasttrap_optimize_save = 1; 198 0 stevel 199 0 stevel static uint64_t 200 0 stevel fasttrap_anarg(struct regs *rp, int argno) 201 0 stevel { 202 0 stevel uint64_t value; 203 0 stevel 204 0 stevel if (argno < 6) 205 0 stevel return ((&rp->r_o0)[argno]); 206 0 stevel 207 0 stevel if (curproc->p_model == DATAMODEL_NATIVE) { 208 0 stevel struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS); 209 0 stevel 210 0 stevel DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 211 0 stevel value = dtrace_fulword(&fr->fr_argd[argno]); 212 0 stevel DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | CPU_DTRACE_BADADDR | 213 0 stevel CPU_DTRACE_BADALIGN); 214 0 stevel } else { 215 0 stevel struct frame32 *fr = (struct frame32 *)rp->r_sp; 216 0 stevel 217 0 stevel DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 218 0 stevel value = dtrace_fuword32(&fr->fr_argd[argno]); 219 0 stevel DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | CPU_DTRACE_BADADDR | 220 0 stevel CPU_DTRACE_BADALIGN); 221 0 stevel } 222 0 stevel 223 0 stevel return (value); 224 0 stevel } 225 0 stevel 226 0 stevel static ulong_t fasttrap_getreg(struct regs *, uint_t); 227 0 stevel static void fasttrap_putreg(struct regs *, uint_t, ulong_t); 228 0 stevel 229 0 stevel static void 230 4685 ahl fasttrap_usdt_args(fasttrap_probe_t *probe, struct regs *rp, 231 4685 ahl uint_t fake_restore, int argc, uintptr_t *argv) 232 0 stevel { 233 0 stevel int i, x, cap = MIN(argc, probe->ftp_nargs); 234 4685 ahl int inc = (fake_restore ? 16 : 0); 235 4685 ahl 236 4685 ahl /* 237 4685 ahl * The only way we'll hit the fake_restore case is if a USDT probe is 238 4685 ahl * invoked as a tail-call. While it wouldn't be incorrect, we can 239 4685 ahl * avoid a call to fasttrap_getreg(), and safely use rp->r_sp 240 4685 ahl * directly since a tail-call can't be made if the invoked function 241 4685 ahl * would use the argument dump space (i.e. if there were more than 242 4685 ahl * 6 arguments). We take this shortcut because unconditionally rooting 243 4685 ahl * around for R_FP (R_SP + 16) would be unnecessarily painful. 244 4685 ahl */ 245 0 stevel 246 0 stevel if (curproc->p_model == DATAMODEL_NATIVE) { 247 0 stevel struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS); 248 0 stevel uintptr_t v; 249 0 stevel 250 0 stevel for (i = 0; i < cap; i++) { 251 0 stevel x = probe->ftp_argmap[i]; 252 0 stevel 253 0 stevel if (x < 6) 254 4685 ahl argv[i] = fasttrap_getreg(rp, R_O0 + x + inc); 255 0 stevel else if (fasttrap_fulword(&fr->fr_argd[x], &v) != 0) 256 0 stevel argv[i] = 0; 257 0 stevel } 258 0 stevel 259 0 stevel } else { 260 0 stevel struct frame32 *fr = (struct frame32 *)rp->r_sp; 261 0 stevel uint32_t v; 262 0 stevel 263 0 stevel for (i = 0; i < cap; i++) { 264 0 stevel x = probe->ftp_argmap[i]; 265 0 stevel 266 0 stevel if (x < 6) 267 4685 ahl argv[i] = fasttrap_getreg(rp, R_O0 + x + inc); 268 0 stevel else if (fasttrap_fuword32(&fr->fr_argd[x], &v) != 0) 269 0 stevel argv[i] = 0; 270 0 stevel } 271 0 stevel } 272 0 stevel 273 0 stevel for (; i < argc; i++) { 274 0 stevel argv[i] = 0; 275 0 stevel } 276 0 stevel } 277 0 stevel 278 0 stevel static void 279 0 stevel fasttrap_return_common(struct regs *rp, uintptr_t pc, pid_t pid, 280 0 stevel uint_t fake_restore) 281 0 stevel { 282 0 stevel fasttrap_tracepoint_t *tp; 283 0 stevel fasttrap_bucket_t *bucket; 284 0 stevel fasttrap_id_t *id; 285 0 stevel kmutex_t *pid_mtx; 286 0 stevel dtrace_icookie_t cookie; 287 0 stevel 288 0 stevel pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock; 289 0 stevel mutex_enter(pid_mtx); 290 0 stevel bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; 291 0 stevel 292 0 stevel for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { 293 0 stevel if (pid == tp->ftt_pid && pc == tp->ftt_pc && 294 4821 ahl tp->ftt_proc->ftpc_acount != 0) 295 0 stevel break; 296 0 stevel } 297 0 stevel 298 0 stevel /* 299 0 stevel * Don't sweat it if we can't find the tracepoint again; unlike 300 0 stevel * when we're in fasttrap_pid_probe(), finding the tracepoint here 301 0 stevel * is not essential to the correct execution of the process. 302 0 stevel */ 303 0 stevel if (tp == NULL || tp->ftt_retids == NULL) { 304 0 stevel mutex_exit(pid_mtx); 305 0 stevel return; 306 0 stevel } 307 0 stevel 308 0 stevel for (id = tp->ftt_retids; id != NULL; id = id->fti_next) { 309 0 stevel fasttrap_probe_t *probe = id->fti_probe; 310 0 stevel 311 1710 ahl if (id->fti_ptype == DTFTP_POST_OFFSETS) { 312 4685 ahl if (probe->ftp_argmap != NULL && fake_restore) { 313 0 stevel uintptr_t t[5]; 314 0 stevel 315 4685 ahl fasttrap_usdt_args(probe, rp, fake_restore, 316 4685 ahl sizeof (t) / sizeof (t[0]), t); 317 4685 ahl 318 4685 ahl cookie = dtrace_interrupt_disable(); 319 4685 ahl DTRACE_CPUFLAG_SET(CPU_DTRACE_FAKERESTORE); 320 4685 ahl dtrace_probe(probe->ftp_id, t[0], t[1], 321 4685 ahl t[2], t[3], t[4]); 322 4685 ahl DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_FAKERESTORE); 323 4685 ahl dtrace_interrupt_enable(cookie); 324 4685 ahl 325 4685 ahl } else if (probe->ftp_argmap != NULL) { 326 4685 ahl uintptr_t t[5]; 327 4685 ahl 328 4685 ahl fasttrap_usdt_args(probe, rp, fake_restore, 329 0 stevel sizeof (t) / sizeof (t[0]), t); 330 0 stevel 331 0 stevel dtrace_probe(probe->ftp_id, t[0], t[1], 332 0 stevel t[2], t[3], t[4]); 333 4685 ahl 334 4685 ahl } else if (fake_restore) { 335 4685 ahl uintptr_t arg0 = fasttrap_getreg(rp, R_I0); 336 4685 ahl uintptr_t arg1 = fasttrap_getreg(rp, R_I1); 337 4685 ahl uintptr_t arg2 = fasttrap_getreg(rp, R_I2); 338 4685 ahl uintptr_t arg3 = fasttrap_getreg(rp, R_I3); 339 4685 ahl uintptr_t arg4 = fasttrap_getreg(rp, R_I4); 340 4685 ahl 341 4685 ahl cookie = dtrace_interrupt_disable(); 342 4685 ahl DTRACE_CPUFLAG_SET(CPU_DTRACE_FAKERESTORE); 343 4685 ahl dtrace_probe(probe->ftp_id, arg0, arg1, 344 4685 ahl arg2, arg3, arg4); 345 4685 ahl DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_FAKERESTORE); 346 4685 ahl dtrace_interrupt_enable(cookie); 347 4685 ahl 348 4685 ahl } else { 349 4685 ahl dtrace_probe(probe->ftp_id, rp->r_o0, rp->r_o1, 350 4685 ahl rp->r_o2, rp->r_o3, rp->r_o4); 351 0 stevel } 352 4685 ahl 353 0 stevel continue; 354 0 stevel } 355 0 stevel 356 0 stevel /* 357 0 stevel * If this is only a possible return point, we must 358 0 stevel * be looking at a potential tail call in leaf context. 359 0 stevel * If the %npc is still within this function, then we 360 0 stevel * must have misidentified a jmpl as a tail-call when it 361 0 stevel * is, in fact, part of a jump table. It would be nice to 362 0 stevel * remove this tracepoint, but this is neither the time 363 0 stevel * nor the place. 364 0 stevel */ 365 0 stevel if ((tp->ftt_flags & FASTTRAP_F_RETMAYBE) && 366 0 stevel rp->r_npc - probe->ftp_faddr < probe->ftp_fsize) 367 0 stevel continue; 368 0 stevel 369 0 stevel /* 370 0 stevel * It's possible for a function to branch to the delay slot 371 0 stevel * of an instruction that we've identified as a return site. 372 0 stevel * We can dectect this spurious return probe activation by 373 0 stevel * observing that in this case %npc will be %pc + 4 and %npc 374 0 stevel * will be inside the current function (unless the user is 375 0 stevel * doing _crazy_ instruction picking in which case there's 376 0 stevel * very little we can do). The second check is important 377 0 stevel * in case the last instructions of a function make a tail- 378 0 stevel * call to the function located immediately subsequent. 379 0 stevel */ 380 0 stevel if (rp->r_npc == rp->r_pc + 4 && 381 0 stevel rp->r_npc - probe->ftp_faddr < probe->ftp_fsize) 382 0 stevel continue; 383 0 stevel 384 0 stevel /* 385 0 stevel * The first argument is the offset of return tracepoint 386 0 stevel * in the function; the remaining arguments are the return 387 0 stevel * values. 388 0 stevel * 389 0 stevel * If fake_restore is set, we need to pull the return values 390 0 stevel * out of the %i's rather than the %o's -- a little trickier. 391 0 stevel */ 392 0 stevel if (!fake_restore) { 393 0 stevel dtrace_probe(probe->ftp_id, pc - probe->ftp_faddr, 394 0 stevel rp->r_o0, rp->r_o1, rp->r_o2, rp->r_o3); 395 0 stevel } else { 396 0 stevel uintptr_t arg0 = fasttrap_getreg(rp, R_I0); 397 0 stevel uintptr_t arg1 = fasttrap_getreg(rp, R_I1); 398 0 stevel uintptr_t arg2 = fasttrap_getreg(rp, R_I2); 399 0 stevel uintptr_t arg3 = fasttrap_getreg(rp, R_I3); 400 0 stevel 401 0 stevel cookie = dtrace_interrupt_disable(); 402 0 stevel DTRACE_CPUFLAG_SET(CPU_DTRACE_FAKERESTORE); 403 0 stevel dtrace_probe(probe->ftp_id, pc - probe->ftp_faddr, 404 0 stevel arg0, arg1, arg2, arg3); 405 0 stevel DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_FAKERESTORE); 406 0 stevel dtrace_interrupt_enable(cookie); 407 0 stevel } 408 0 stevel } 409 0 stevel 410 0 stevel mutex_exit(pid_mtx); 411 0 stevel } 412 0 stevel 413 0 stevel int 414 0 stevel fasttrap_pid_probe(struct regs *rp) 415 0 stevel { 416 0 stevel proc_t *p = curproc; 417 0 stevel fasttrap_tracepoint_t *tp, tp_local; 418 0 stevel fasttrap_id_t *id; 419 0 stevel pid_t pid; 420 0 stevel uintptr_t pc = rp->r_pc; 421 0 stevel uintptr_t npc = rp->r_npc; 422 0 stevel uintptr_t orig_pc = pc; 423 0 stevel fasttrap_bucket_t *bucket; 424 0 stevel kmutex_t *pid_mtx; 425 1710 ahl uint_t fake_restore = 0, is_enabled = 0; 426 0 stevel dtrace_icookie_t cookie; 427 0 stevel 428 0 stevel /* 429 0 stevel * It's possible that a user (in a veritable orgy of bad planning) 430 0 stevel * could redirect this thread's flow of control before it reached the 431 0 stevel * return probe fasttrap. In this case we need to kill the process 432 0 stevel * since it's in a unrecoverable state. 433 0 stevel */ 434 0 stevel if (curthread->t_dtrace_step) { 435 0 stevel ASSERT(curthread->t_dtrace_on); 436 0 stevel fasttrap_sigtrap(p, curthread, pc); 437 0 stevel return (0); 438 0 stevel } 439 0 stevel 440 0 stevel /* 441 0 stevel * Clear all user tracing flags. 442 0 stevel */ 443 0 stevel curthread->t_dtrace_ft = 0; 444 0 stevel curthread->t_dtrace_pc = 0; 445 0 stevel curthread->t_dtrace_npc = 0; 446 0 stevel curthread->t_dtrace_scrpc = 0; 447 0 stevel curthread->t_dtrace_astpc = 0; 448 0 stevel 449 0 stevel /* 450 0 stevel * Treat a child created by a call to vfork(2) as if it were its 451 0 stevel * parent. We know that there's only one thread of control in such a 452 0 stevel * process: this one. 453 0 stevel */ 454 0 stevel while (p->p_flag & SVFORK) { 455 0 stevel p = p->p_parent; 456 0 stevel } 457 0 stevel 458 0 stevel pid = p->p_pid; 459 0 stevel pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock; 460 0 stevel mutex_enter(pid_mtx); 461 0 stevel bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; 462 0 stevel 463 0 stevel /* 464 0 stevel * Lookup the tracepoint that the process just hit. 465 0 stevel */ 466 0 stevel for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { 467 0 stevel if (pid == tp->ftt_pid && pc == tp->ftt_pc && 468 4821 ahl tp->ftt_proc->ftpc_acount != 0) 469 0 stevel break; 470 0 stevel } 471 0 stevel 472 0 stevel /* 473 0 stevel * If we couldn't find a matching tracepoint, either a tracepoint has 474 0 stevel * been inserted without using the pid<pid> ioctl interface (see 475 0 stevel * fasttrap_ioctl), or somehow we have mislaid this tracepoint. 476 0 stevel */ 477 0 stevel if (tp == NULL) { 478 0 stevel mutex_exit(pid_mtx); 479 0 stevel return (-1); 480 0 stevel } 481 0 stevel 482 0 stevel for (id = tp->ftt_ids; id != NULL; id = id->fti_next) { 483 0 stevel fasttrap_probe_t *probe = id->fti_probe; 484 1710 ahl int isentry = (id->fti_ptype == DTFTP_ENTRY); 485 1710 ahl 486 1710 ahl if (id->fti_ptype == DTFTP_IS_ENABLED) { 487 1710 ahl is_enabled = 1; 488 1710 ahl continue; 489 1710 ahl } 490 1710 ahl 491 0 stevel /* 492 0 stevel * We note that this was an entry probe to help ustack() find 493 0 stevel * the first caller. 494 0 stevel */ 495 1710 ahl if (isentry) { 496 0 stevel cookie = dtrace_interrupt_disable(); 497 0 stevel DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY); 498 0 stevel } 499 0 stevel dtrace_probe(probe->ftp_id, rp->r_o0, rp->r_o1, rp->r_o2, 500 0 stevel rp->r_o3, rp->r_o4); 501 0 stevel if (isentry) { 502 0 stevel DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY); 503 0 stevel dtrace_interrupt_enable(cookie); 504 0 stevel } 505 0 stevel } 506 0 stevel 507 0 stevel /* 508 0 stevel * We're about to do a bunch of work so we cache a local copy of 509 0 stevel * the tracepoint to emulate the instruction, and then find the 510 0 stevel * tracepoint again later if we need to light up any return probes. 511 0 stevel */ 512 0 stevel tp_local = *tp; 513 0 stevel mutex_exit(pid_mtx); 514 0 stevel tp = &tp_local; 515 0 stevel 516 0 stevel /* 517 1710 ahl * If there's an is-enabled probe conntected to this tracepoint it 518 1710 ahl * means that there was a 'mov %g0, %o0' instruction that was placed 519 1710 ahl * there by DTrace when the binary was linked. As this probe is, in 520 1710 ahl * fact, enabled, we need to stuff 1 into %o0. Accordingly, we can 521 1710 ahl * bypass all the instruction emulation logic since we know the 522 1710 ahl * inevitable result. It's possible that a user could construct a 523 1710 ahl * scenario where the 'is-enabled' probe was on some other 524 1710 ahl * instruction, but that would be a rather exotic way to shoot oneself 525 1710 ahl * in the foot. 526 1710 ahl */ 527 1710 ahl if (is_enabled) { 528 1710 ahl rp->r_o0 = 1; 529 1710 ahl pc = rp->r_npc; 530 1710 ahl npc = pc + 4; 531 1710 ahl goto done; 532 1710 ahl } 533 1710 ahl 534 1710 ahl /* 535 1710 ahl * We emulate certain types of instructions to ensure correctness 536 0 stevel * (in the case of position dependent instructions) or optimize 537 0 stevel * common cases. The rest we have the thread execute back in user- 538 0 stevel * land. 539 0 stevel */ 540 0 stevel switch (tp->ftt_type) { 541 0 stevel case FASTTRAP_T_SAVE: 542 0 stevel { 543 0 stevel int32_t imm; 544 0 stevel 545 0 stevel /* 546 0 stevel * This an optimization to let us handle function entry 547 0 stevel * probes more efficiently. Many functions begin with a save 548 0 stevel * instruction that follows the pattern: 549 0 stevel * save %sp, <imm>, %sp 550 0 stevel * 551 0 stevel * Meanwhile, we've stashed the instruction: 552 0 stevel * save %g1, %g0, %sp 553 0 stevel * 554 0 stevel * off of %g7, so all we have to do is stick the right value 555 0 stevel * into %g1 and reset %pc to point to the instruction we've 556 0 stevel * cleverly hidden (%npc should not be touched). 557 0 stevel */ 558 0 stevel 559 0 stevel imm = tp->ftt_instr << 19; 560 0 stevel imm >>= 19; 561 0 stevel rp->r_g1 = rp->r_sp + imm; 562 0 stevel pc = rp->r_g7 + FASTTRAP_OFF_SAVE; 563 0 stevel break; 564 0 stevel } 565 0 stevel 566 0 stevel case FASTTRAP_T_RESTORE: 567 0 stevel { 568 0 stevel ulong_t value; 569 0 stevel uint_t rd; 570 0 stevel 571 0 stevel /* 572 0 stevel * This is an optimization to let us handle function 573 0 stevel * return probes more efficiently. Most non-leaf functions 574 0 stevel * end with the sequence: 575 0 stevel * ret 576 0 stevel * restore <reg>, <reg_or_imm>, %oX 577 0 stevel * 578 0 stevel * We've stashed the instruction: 579 0 stevel * restore %g0, %g0, %g0 580 0 stevel * 581 0 stevel * off of %g7 so we just need to place the correct value 582 0 stevel * in the right %i register (since after our fake-o 583 0 stevel * restore, the %i's will become the %o's) and set the %pc 584 0 stevel * to point to our hidden restore. We also set fake_restore to 585 0 stevel * let fasttrap_return_common() know that it will find the 586 0 stevel * return values in the %i's rather than the %o's. 587 0 stevel */ 588 0 stevel 589 0 stevel if (I(tp->ftt_instr)) { 590 0 stevel int32_t imm; 591 0 stevel 592 0 stevel imm = tp->ftt_instr << 19; 593 0 stevel imm >>= 19; 594 0 stevel value = fasttrap_getreg(rp, RS1(tp->ftt_instr)) + imm; 595 0 stevel } else { 596 0 stevel value = fasttrap_getreg(rp, RS1(tp->ftt_instr)) + 597 0 stevel fasttrap_getreg(rp, RS2(tp->ftt_instr)); 598 0 stevel } 599 0 stevel 600 0 stevel /* 601 0 stevel * Convert %o's to %i's; leave %g's as they are. 602 0 stevel */ 603 0 stevel rd = RD(tp->ftt_instr); 604 0 stevel fasttrap_putreg(rp, ((rd & 0x18) == 0x8) ? rd + 16 : rd, value); 605 0 stevel 606 0 stevel pc = rp->r_g7 + FASTTRAP_OFF_RESTORE; 607 0 stevel fake_restore = 1; 608 0 stevel break; 609 0 stevel } 610 0 stevel 611 0 stevel case FASTTRAP_T_RETURN: 612 0 stevel { 613 0 stevel uintptr_t target; 614 0 stevel 615 0 stevel /* 616 0 stevel * A return instruction is like a jmpl (without the link 617 0 stevel * part) that executes an implicit restore. We've stashed 618 0 stevel * the instruction: 619 0 stevel * return %o0 620 0 stevel * 621 0 stevel * off of %g7 so we just need to place the target in %o0 622 0 stevel * and set the %pc to point to the stashed return instruction. 623 0 stevel * We use %o0 since that register disappears after the return 624 0 stevel * executes, erasing any evidence of this tampering. 625 0 stevel */ 626 0 stevel if (I(tp->ftt_instr)) { 627 0 stevel int32_t imm; 628 0 stevel 629 0 stevel imm = tp->ftt_instr << 19; 630 0 stevel imm >>= 19; 631 0 stevel target = fasttrap_getreg(rp, RS1(tp->ftt_instr)) + imm; 632 0 stevel } else { 633 0 stevel target = fasttrap_getreg(rp, RS1(tp->ftt_instr)) + 634 0 stevel fasttrap_getreg(rp, RS2(tp->ftt_instr)); 635 0 stevel } 636 0 stevel 637 0 stevel fasttrap_putreg(rp, R_O0, target); 638 0 stevel 639 0 stevel pc = rp->r_g7 + FASTTRAP_OFF_RETURN; 640 0 stevel fake_restore = 1; 641 0 stevel break; 642 0 stevel } 643 0 stevel 644 0 stevel case FASTTRAP_T_OR: 645 0 stevel { 646 0 stevel ulong_t value; 647 0 stevel 648 0 stevel if (I(tp->ftt_instr)) { 649 0 stevel int32_t imm; 650 0 stevel 651 0 stevel imm = tp->ftt_instr << 19; 652 0 stevel imm >>= 19; 653 0 stevel value = fasttrap_getreg(rp, RS1(tp->ftt_instr)) | imm; 654 0 stevel } else { 655 0 stevel value = fasttrap_getreg(rp, RS1(tp->ftt_instr)) | 656 0 stevel fasttrap_getreg(rp, RS2(tp->ftt_instr)); 657 0 stevel } 658 0 stevel 659 0 stevel fasttrap_putreg(rp, RD(tp->ftt_instr), value); 660 0 stevel pc = rp->r_npc; 661 0 stevel npc = pc + 4; 662 0 stevel break; 663 0 stevel } 664 0 stevel 665 0 stevel case FASTTRAP_T_SETHI: 666 0 stevel if (RD(tp->ftt_instr) != R_G0) { 667 0 stevel uint32_t imm32 = tp->ftt_instr << 10; 668 0 stevel fasttrap_putreg(rp, RD(tp->ftt_instr), (ulong_t)imm32); 669 0 stevel } 670 0 stevel pc = rp->r_npc; 671 0 stevel npc = pc + 4; 672 0 stevel break; 673 0 stevel 674 0 stevel case FASTTRAP_T_CCR: 675 0 stevel { 676 0 stevel uint_t c, v, z, n, taken; 677 0 stevel uint_t ccr = rp->r_tstate >> TSTATE_CCR_SHIFT; 678 0 stevel 679 0 stevel if (tp->ftt_cc != 0) 680 0 stevel ccr >>= 4; 681 0 stevel 682 0 stevel c = (ccr >> 0) & 1; 683 0 stevel v = (ccr >> 1) & 1; 684 0 stevel z = (ccr >> 2) & 1; 685 0 stevel n = (ccr >> 3) & 1; 686 0 stevel 687 0 stevel switch (tp->ftt_code) { 688 0 stevel case 0x0: /* BN */ 689 0 stevel taken = 0; break; 690 0 stevel case 0x1: /* BE */ 691 0 stevel taken = z; break; 692 0 stevel case 0x2: /* BLE */ 693 0 stevel taken = z | (n ^ v); break; 694 0 stevel case 0x3: /* BL */ 695 0 stevel taken = n ^ v; break; 696 0 stevel case 0x4: /* BLEU */ 697 0 stevel taken = c | z; break; 698 0 stevel case 0x5: /* BCS (BLU) */ 699 0 stevel taken = c; break; 700 0 stevel case 0x6: /* BNEG */ 701 0 stevel taken = n; break; 702 0 stevel case 0x7: /* BVS */ 703 0 stevel taken = v; break; 704 0 stevel case 0x8: /* BA */ 705 0 stevel /* 706 0 stevel * We handle the BA case differently since the annul 707 0 stevel * bit means something slightly different. 708 0 stevel */ 709 0 stevel panic("fasttrap: mishandled a branch"); 710 0 stevel taken = 1; break; 711 0 stevel case 0x9: /* BNE */ 712 0 stevel taken = ~z; break; 713 0 stevel case 0xa: /* BG */ 714 0 stevel taken = ~(z | (n ^ v)); break; 715 0 stevel case 0xb: /* BGE */ 716 0 stevel taken = ~(n ^ v); break; 717 0 stevel case 0xc: /* BGU */ 718 0 stevel taken = ~(c | z); break; 719 0 stevel case 0xd: /* BCC (BGEU) */ 720 0 stevel taken = ~c; break; 721 0 stevel case 0xe: /* BPOS */ 722 0 stevel taken = ~n; break; 723 0 stevel case 0xf: /* BVC */ 724 0 stevel taken = ~v; break; 725 0 stevel } 726 0 stevel 727 0 stevel if (taken & 1) { 728 0 stevel pc = rp->r_npc; 729 0 stevel npc = tp->ftt_dest; 730 0 stevel } else if (tp->ftt_flags & FASTTRAP_F_ANNUL) { 731 0 stevel /* 732 0 stevel * Untaken annulled branches don't execute the 733 0 stevel * instruction in the delay slot. 734 0 stevel */ 735 0 stevel pc = rp->r_npc + 4; 736 0 stevel npc = pc + 4; 737 0 stevel } else { 738 0 stevel pc = rp->r_npc; 739 0 stevel npc = pc + 4; 740 0 stevel } 741 0 stevel break; 742 0 stevel } 743 0 stevel 744 0 stevel case FASTTRAP_T_FCC: 745 0 stevel { 746 0 stevel uint_t fcc; 747 0 stevel uint_t taken; 748 0 stevel uint64_t fsr; 749 0 stevel 750 0 stevel dtrace_getfsr(&fsr); 751 0 stevel 752 0 stevel if (tp->ftt_cc == 0) { 753 0 stevel fcc = (fsr >> 10) & 0x3; 754 0 stevel } else { 755 0 stevel uint_t shift; 756 0 stevel ASSERT(tp->ftt_cc <= 3); 757 0 stevel shift = 30 + tp->ftt_cc * 2; 758 0 stevel fcc = (fsr >> shift) & 0x3; 759 0 stevel } 760 0 stevel 761 0 stevel switch (tp->ftt_code) { 762 0 stevel case 0x0: /* FBN */ 763 0 stevel taken = (1 << fcc) & (0|0|0|0); break; 764 0 stevel case 0x1: /* FBNE */ 765 0 stevel taken = (1 << fcc) & (8|4|2|0); break; 766 0 stevel case 0x2: /* FBLG */ 767 0 stevel taken = (1 << fcc) & (0|4|2|0); break; 768 0 stevel case 0x3: /* FBUL */ 769 0 stevel taken = (1 << fcc) & (8|0|2|0); break; 770 0 stevel case 0x4: /* FBL */ 771 0 stevel taken = (1 << fcc) & (0|0|2|0); break; 772 0 stevel case 0x5: /* FBUG */ 773 0 stevel taken = (1 << fcc) & (8|4|0|0); break; 774 0 stevel case 0x6: /* FBG */ 775 0 stevel taken = (1 << fcc) & (0|4|0|0); break; 776 0 stevel case 0x7: /* FBU */ 777 0 stevel taken = (1 << fcc) & (8|0|0|0); break; 778 0 stevel case 0x8: /* FBA */ 779 0 stevel /* 780 0 stevel * We handle the FBA case differently since the annul 781 0 stevel * bit means something slightly different. 782 0 stevel */ 783 0 stevel panic("fasttrap: mishandled a branch"); 784 0 stevel taken = (1 << fcc) & (8|4|2|1); break; 785 0 stevel case 0x9: /* FBE */ 786 0 stevel taken = (1 << fcc) & (0|0|0|1); break; 787 0 stevel case 0xa: /* FBUE */ 788 0 stevel taken = (1 << fcc) & (8|0|0|1); break; 789 0 stevel case 0xb: /* FBGE */ 790 0 stevel taken = (1 << fcc) & (0|4|0|1); break; 791 0 stevel case 0xc: /* FBUGE */ 792 0 stevel taken = (1 << fcc) & (8|4|0|1); break; 793 0 stevel case 0xd: /* FBLE */ 794 0 stevel taken = (1 << fcc) & (0|0|2|1); break; 795 0 stevel case 0xe: /* FBULE */ 796 0 stevel taken = (1 << fcc) & (8|0|2|1); break; 797 0 stevel case 0xf: /* FBO */ 798 0 stevel taken = (1 << fcc) & (0|4|2|1); break; 799 0 stevel } 800 0 stevel 801 0 stevel if (taken) { 802 0 stevel pc = rp->r_npc; 803 0 stevel npc = tp->ftt_dest; 804 0 stevel } else if (tp->ftt_flags & FASTTRAP_F_ANNUL) { 805 0 stevel /* 806 0 stevel * Untaken annulled branches don't execute the 807 0 stevel * instruction in the delay slot. 808 0 stevel */ 809 0 stevel pc = rp->r_npc + 4; 810 0 stevel npc = pc + 4; 811 0 stevel } else { 812 0 stevel pc = rp->r_npc; 813 0 stevel npc = pc + 4; 814 0 stevel } 815 0 stevel break; 816 0 stevel } 817 0 stevel 818 0 stevel case FASTTRAP_T_REG: 819 0 stevel { 820 3944 ahl int64_t value; 821 0 stevel uint_t taken; 822 0 stevel uint_t reg = RS1(tp->ftt_instr); 823 0 stevel 824 0 stevel /* 825 0 stevel * An ILP32 process shouldn't be using a branch predicated on 826 0 stevel * an %i or an %l since it would violate the ABI. It's a 827 0 stevel * violation of the ABI because we can't ensure deterministic 828 0 stevel * behavior. We should have identified this case when we 829 0 stevel * enabled the probe. 830 0 stevel */ 831 0 stevel ASSERT(p->p_model == DATAMODEL_LP64 || reg < 16); 832 0 stevel 833 3944 ahl value = (int64_t)fasttrap_getreg(rp, reg); 834 0 stevel 835 0 stevel switch (tp->ftt_code) { 836 0 stevel case 0x1: /* BRZ */ 837 0 stevel taken = (value == 0); break; 838 0 stevel case 0x2: /* BRLEZ */ 839 0 stevel taken = (value <= 0); break; 840 0 stevel case 0x3: /* BRLZ */ 841 0 stevel taken = (value < 0); break; 842 0 stevel case 0x5: /* BRNZ */ 843 0 stevel taken = (value != 0); break; 844 0 stevel case 0x6: /* BRGZ */ 845 0 stevel taken = (value > 0); break; 846 0 stevel case 0x7: /* BRGEZ */ 847 3944 ahl taken = (value >= 0); break; 848 0 stevel default: 849 0 stevel case 0x0: 850 0 stevel case 0x4: 851 0 stevel panic("fasttrap: mishandled a branch"); 852 0 stevel } 853 0 stevel 854 0 stevel if (taken) { 855 0 stevel pc = rp->r_npc; 856 0 stevel npc = tp->ftt_dest; 857 0 stevel } else if (tp->ftt_flags & FASTTRAP_F_ANNUL) { 858 0 stevel /* 859 0 stevel * Untaken annulled branches don't execute the 860 0 stevel * instruction in the delay slot. 861 0 stevel */ 862 0 stevel pc = rp->r_npc + 4; 863 0 stevel npc = pc + 4; 864 0 stevel } else { 865 0 stevel pc = rp->r_npc; 866 0 stevel npc = pc + 4; 867 0 stevel } 868 0 stevel break; 869 0 stevel } 870 0 stevel 871 0 stevel case FASTTRAP_T_ALWAYS: 872 0 stevel /* 873 0 stevel * BAs, BA,As... 874 0 stevel */ 875 0 stevel 876 0 stevel if (tp->ftt_flags & FASTTRAP_F_ANNUL) { 877 0 stevel /* 878 0 stevel * Annulled branch always instructions never execute 879 0 stevel * the instruction in the delay slot. 880 0 stevel */ 881 0 stevel pc = tp->ftt_dest; 882 0 stevel npc = tp->ftt_dest + 4; 883 0 stevel } else { 884 0 stevel pc = rp->r_npc; 885 0 stevel npc = tp->ftt_dest; 886 0 stevel } 887 0 stevel break; 888 0 stevel 889 0 stevel case FASTTRAP_T_RDPC: 890 0 stevel fasttrap_putreg(rp, RD(tp->ftt_instr), rp->r_pc); 891 0 stevel pc = rp->r_npc; 892 0 stevel npc = pc + 4; 893 0 stevel break; 894 0 stevel 895 0 stevel case FASTTRAP_T_CALL: 896 0 stevel /* 897 0 stevel * It's a call _and_ link remember... 898 0 stevel */ 899 0 stevel rp->r_o7 = rp->r_pc; 900 0 stevel pc = rp->r_npc; 901 0 stevel npc = tp->ftt_dest; 902 0 stevel break; 903 0 stevel 904 0 stevel case FASTTRAP_T_JMPL: 905 0 stevel pc = rp->r_npc; 906 0 stevel 907 0 stevel if (I(tp->ftt_instr)) { 908 0 stevel uint_t rs1 = RS1(tp->ftt_instr); 909 0 stevel int32_t imm; 910 0 stevel 911 0 stevel imm = tp->ftt_instr << 19; 912 0 stevel imm >>= 19; 913 0 stevel npc = fasttrap_getreg(rp, rs1) + imm; 914 0 stevel } else { 915 0 stevel uint_t rs1 = RS1(tp->ftt_instr); 916 0 stevel uint_t rs2 = RS2(tp->ftt_instr); 917 0 stevel 918 0 stevel npc = fasttrap_getreg(rp, rs1) + 919 0 stevel fasttrap_getreg(rp, rs2); 920 0 stevel } 921 0 stevel 922 0 stevel /* 923 0 stevel * Do the link part of the jump-and-link instruction. 924 0 stevel */ 925 0 stevel fasttrap_putreg(rp, RD(tp->ftt_instr), rp->r_pc); 926 0 stevel 927 0 stevel break; 928 0 stevel 929 0 stevel case FASTTRAP_T_COMMON: 930 0 stevel { 931 0 stevel curthread->t_dtrace_scrpc = rp->r_g7; 932 0 stevel curthread->t_dtrace_astpc = rp->r_g7 + FASTTRAP_OFF_FTRET; 933 0 stevel 934 0 stevel /* 935 0 stevel * Copy the instruction to a reserved location in the 936 0 stevel * user-land thread structure, then set the PC to that 937 0 stevel * location and leave the NPC alone. We take pains to ensure 938 0 stevel * consistency in the instruction stream (See SPARC 939 0 stevel * Architecture Manual Version 9, sections 8.4.7, A.20, and 940 0 stevel * H.1.6; UltraSPARC I/II User's Manual, sections 3.1.1.1, 941 0 stevel * and 13.6.4) by using the ASI ASI_BLK_COMMIT_S to copy the 942 0 stevel * instruction into the user's address space without 943 0 stevel * bypassing the I$. There's no AS_USER version of this ASI 944 0 stevel * (as exist for other ASIs) so we use the lofault 945 0 stevel * mechanism to catch faults. 946 0 stevel */ 947 0 stevel if (dtrace_blksuword32(rp->r_g7, &tp->ftt_instr, 1) == -1) { 948 0 stevel /* 949 0 stevel * If the copyout fails, then the process's state 950 0 stevel * is not consistent (the effects of the traced 951 0 stevel * instruction will never be seen). This process 952 0 stevel * cannot be allowed to continue execution. 953 0 stevel */ 954 0 stevel fasttrap_sigtrap(curproc, curthread, pc); 955 0 stevel return (0); 956 0 stevel } 957 0 stevel 958 0 stevel curthread->t_dtrace_pc = pc; 959 0 stevel curthread->t_dtrace_npc = npc; 960 0 stevel curthread->t_dtrace_on = 1; 961 0 stevel 962 0 stevel pc = curthread->t_dtrace_scrpc; 963 0 stevel 964 0 stevel if (tp->ftt_retids != NULL) { 965 0 stevel curthread->t_dtrace_step = 1; 966 0 stevel curthread->t_dtrace_ret = 1; 967 0 stevel npc = curthread->t_dtrace_astpc; 968 0 stevel } 969 0 stevel break; 970 0 stevel } 971 0 stevel 972 0 stevel default: 973 0 stevel panic("fasttrap: mishandled an instruction"); 974 0 stevel } 975 0 stevel 976 0 stevel /* 977 0 stevel * This bit me in the ass a couple of times, so lets toss this 978 0 stevel * in as a cursory sanity check. 979 0 stevel */ 980 0 stevel ASSERT(pc != rp->r_g7 + 4); 981 0 stevel ASSERT(pc != rp->r_g7 + 8); 982 0 stevel 983 1710 ahl done: 984 0 stevel /* 985 0 stevel * If there were no return probes when we first found the tracepoint, 986 0 stevel * we should feel no obligation to honor any return probes that were 987 0 stevel * subsequently enabled -- they'll just have to wait until the next 988 0 stevel * time around. 989 0 stevel */ 990 0 stevel if (tp->ftt_retids != NULL) { 991 0 stevel /* 992 0 stevel * We need to wait until the results of the instruction are 993 0 stevel * apparent before invoking any return probes. If this 994 0 stevel * instruction was emulated we can just call 995 0 stevel * fasttrap_return_common(); if it needs to be executed, we 996 0 stevel * need to wait until we return to the kernel. 997 0 stevel */ 998 0 stevel if (tp->ftt_type != FASTTRAP_T_COMMON) { 999 0 stevel fasttrap_return_common(rp, orig_pc, pid, fake_restore); 1000 0 stevel } else { 1001 0 stevel ASSERT(curthread->t_dtrace_ret != 0); 1002 0 stevel ASSERT(curthread->t_dtrace_pc == orig_pc); 1003 0 stevel ASSERT(curthread->t_dtrace_scrpc == rp->r_g7); 1004 0 stevel ASSERT(npc == curthread->t_dtrace_astpc); 1005 0 stevel } 1006 0 stevel } 1007 0 stevel 1008 0 stevel ASSERT(pc != 0); 1009 0 stevel rp->r_pc = pc; 1010 0 stevel rp->r_npc = npc; 1011 0 stevel 1012 0 stevel return (0); 1013 0 stevel } 1014 0 stevel 1015 0 stevel int 1016 0 stevel fasttrap_return_probe(struct regs *rp) 1017 0 stevel { 1018 0 stevel proc_t *p = ttoproc(curthread); 1019 0 stevel pid_t pid; 1020 0 stevel uintptr_t pc = curthread->t_dtrace_pc; 1021 0 stevel uintptr_t npc = curthread->t_dtrace_npc; 1022 0 stevel 1023 0 stevel curthread->t_dtrace_pc = 0; 1024 0 stevel curthread->t_dtrace_npc = 0; 1025 0 stevel curthread->t_dtrace_scrpc = 0; 1026 0 stevel curthread->t_dtrace_astpc = 0; 1027 0 stevel 1028 0 stevel /* 1029 0 stevel * Treat a child created by a call to vfork(2) as if it were its 1030 0 stevel * parent. We know there's only one thread of control in such a 1031 0 stevel * process: this one. 1032 0 stevel */ 1033 0 stevel while (p->p_flag & SVFORK) { 1034 0 stevel p = p->p_parent; 1035 0 stevel } 1036 0 stevel 1037 0 stevel /* 1038 0 stevel * We set the %pc and %npc to their values when the traced 1039 0 stevel * instruction was initially executed so that it appears to 1040 0 stevel * dtrace_probe() that we're on the original instruction, and so that 1041 0 stevel * the user can't easily detect our complex web of lies. 1042 0 stevel * dtrace_return_probe() (our caller) will correctly set %pc and %npc 1043 0 stevel * after we return. 1044 0 stevel */ 1045 0 stevel rp->r_pc = pc; 1046 0 stevel rp->r_npc = npc; 1047 0 stevel 1048 0 stevel pid = p->p_pid; 1049 0 stevel fasttrap_return_common(rp, pc, pid, 0); 1050 0 stevel 1051 0 stevel return (0); 1052 0 stevel } 1053 0 stevel 1054 0 stevel int 1055 0 stevel fasttrap_tracepoint_install(proc_t *p, fasttrap_tracepoint_t *tp) 1056 0 stevel { 1057 0 stevel fasttrap_instr_t instr = FASTTRAP_INSTR; 1058 0 stevel 1059 0 stevel if (uwrite(p, &instr, 4, tp->ftt_pc) != 0) 1060 0 stevel return (-1); 1061 0 stevel 1062 0 stevel return (0); 1063 0 stevel } 1064 0 stevel 1065 0 stevel int 1066 0 stevel fasttrap_tracepoint_remove(proc_t *p, fasttrap_tracepoint_t *tp) 1067 0 stevel { 1068 0 stevel fasttrap_instr_t instr; 1069 0 stevel 1070 0 stevel /* 1071 0 stevel * Distinguish between read or write failures and a changed 1072 0 stevel * instruction. 1073 0 stevel */ 1074 0 stevel if (uread(p, &instr, 4, tp->ftt_pc) != 0) 1075 0 stevel return (0); 1076 0 stevel if (instr != FASTTRAP_INSTR && instr != BREAKPOINT_INSTR) 1077 0 stevel return (0); 1078 0 stevel if (uwrite(p, &tp->ftt_instr, 4, tp->ftt_pc) != 0) 1079 0 stevel return (-1); 1080 0 stevel 1081 0 stevel return (0); 1082 0 stevel } 1083 0 stevel 1084 0 stevel int 1085 1710 ahl fasttrap_tracepoint_init(proc_t *p, fasttrap_tracepoint_t *tp, uintptr_t pc, 1086 1710 ahl fasttrap_probe_type_t type) 1087 0 stevel { 1088 0 stevel uint32_t instr; 1089 0 stevel int32_t disp; 1090 0 stevel 1091 0 stevel /* 1092 0 stevel * Read the instruction at the given address out of the process's 1093 0 stevel * address space. We don't have to worry about a debugger 1094 0 stevel * changing this instruction before we overwrite it with our trap 1095 0 stevel * instruction since P_PR_LOCK is set. 1096 0 stevel */ 1097 0 stevel if (uread(p, &instr, 4, pc) != 0) 1098 0 stevel return (-1); 1099 0 stevel 1100 0 stevel /* 1101 0 stevel * Decode the instruction to fill in the probe flags. We can have 1102 0 stevel * the process execute most instructions on its own using a pc/npc 1103 0 stevel * trick, but pc-relative control transfer present a problem since 1104 0 stevel * we're relocating the instruction. We emulate these instructions 1105 0 stevel * in the kernel. We assume a default type and over-write that as 1106 0 stevel * needed. 1107 0 stevel * 1108 0 stevel * pc-relative instructions must be emulated for correctness; 1109 0 stevel * other instructions (which represent a large set of commonly traced 1110 0 stevel * instructions) are emulated or otherwise optimized for performance. 1111 0 stevel */ 1112 0 stevel tp->ftt_type = FASTTRAP_T_COMMON; 1113 0 stevel if (OP(instr) == 1) { 1114 0 stevel /* 1115 0 stevel * Call instructions. 1116 0 stevel */ 1117 0 stevel tp->ftt_type = FASTTRAP_T_CALL; 1118 0 stevel disp = DISP30(instr) << 2; 1119 0 stevel tp->ftt_dest = pc + (intptr_t)disp; 1120 0 stevel 1121 0 stevel } else if (OP(instr) == 0) { 1122 0 stevel /* 1123 0 stevel * Branch instructions. 1124 0 stevel * 1125 0 stevel * Unconditional branches need careful attention when they're 1126 0 stevel * annulled: annulled unconditional branches never execute 1127 0 stevel * the instruction in the delay slot. 1128 0 stevel */ 1129 0 stevel switch (OP2(instr)) { 1130 0 stevel case OP2_ILLTRAP: 1131 0 stevel case 0x7: 1132 0 stevel /* 1133 0 stevel * The compiler may place an illtrap after a call to 1134 0 stevel * a function that returns a structure. In the case of 1135 0 stevel * a returned structure, the compiler places an illtrap 1136 0 stevel * whose const22 field is the size of the returned 1137 0 stevel * structure immediately following the delay slot of 1138 0 stevel * the call. To stay out of the way, we refuse to 1139 0 stevel * place tracepoints on top of illtrap instructions. 1140 0 stevel * 1141 0 stevel * This is one of the dumbest architectural decisions 1142 0 stevel * I've ever had to work around. 1143 0 stevel * 1144 0 stevel * We also identify the only illegal op2 value (See 1145 0 stevel * SPARC Architecture Manual Version 9, E.2 table 31). 1146 0 stevel */ 1147 0 stevel return (-1); 1148 0 stevel 1149 0 stevel case OP2_BPcc: 1150 0 stevel if (COND(instr) == 8) { 1151 0 stevel tp->ftt_type = FASTTRAP_T_ALWAYS; 1152 0 stevel } else { 1153 0 stevel /* 1154 0 stevel * Check for an illegal instruction. 1155 0 stevel */ 1156 0 stevel if (CC(instr) & 1) 1157 0 stevel return (-1); 1158 0 stevel tp->ftt_type = FASTTRAP_T_CCR; 1159 0 stevel tp->ftt_cc = CC(instr); 1160 0 stevel tp->ftt_code = COND(instr); 1161 0 stevel } 1162 0 stevel 1163 0 stevel if (A(instr) != 0) 1164 0 stevel tp->ftt_flags |= FASTTRAP_F_ANNUL; 1165 0 stevel 1166 0 stevel disp = DISP19(instr); 1167 0 stevel disp <<= 13; 1168 0 stevel disp >>= 11; 1169 0 stevel tp->ftt_dest = pc + (intptr_t)disp; 1170 0 stevel break; 1171 0 stevel 1172 0 stevel case OP2_Bicc: 1173 0 stevel if (COND(instr) == 8) { 1174 0 stevel tp->ftt_type = FASTTRAP_T_ALWAYS; 1175 0 stevel } else { 1176 0 stevel tp->ftt_type = FASTTRAP_T_CCR; 1177 0 stevel tp->ftt_cc = 0; 1178 0 stevel tp->ftt_code = COND(instr); 1179 0 stevel } 1180 0 stevel 1181 0 stevel if (A(instr) != 0) 1182 0 stevel tp->ftt_flags |= FASTTRAP_F_ANNUL; 1183 0 stevel 1184 0 stevel disp = DISP22(instr); 1185 0 stevel disp <<= 10; 1186 0 stevel disp >>= 8; 1187 0 stevel tp->ftt_dest = pc + (intptr_t)disp; 1188 0 stevel break; 1189 0 stevel 1190 0 stevel case OP2_BPr: 1191 0 stevel /* 1192 0 stevel * Check for an illegal instruction. 1193 0 stevel */ 1194 0 stevel if ((RCOND(instr) & 3) == 0) 1195 0 stevel return (-1); 1196 0 stevel 1197 0 stevel /* 1198 0 stevel * It's a violation of the v8plus ABI to use a 1199 0 stevel * register-predicated branch in a 32-bit app if 1200 0 stevel * the register used is an %l or an %i (%gs and %os 1201 0 stevel * are legit because they're not saved to the stack 1202 0 stevel * in 32-bit words when we take a trap). 1203 0 stevel */ 1204 0 stevel if (p->p_model == DATAMODEL_ILP32 && RS1(instr) >= 16) 1205 0 stevel return (-1); 1206 0 stevel 1207 0 stevel tp->ftt_type = FASTTRAP_T_REG; 1208 0 stevel if (A(instr) != 0) 1209 0 stevel tp->ftt_flags |= FASTTRAP_F_ANNUL; 1210 0 stevel disp = DISP16(instr); 1211 0 stevel disp <<= 16; 1212 0 stevel disp >>= 14; 1213 0 stevel tp->ftt_dest = pc + (intptr_t)disp; 1214 0 stevel tp->ftt_code = RCOND(instr); 1215 0 stevel break; 1216 0 stevel 1217 0 stevel case OP2_SETHI: 1218 0 stevel tp->ftt_type = FASTTRAP_T_SETHI; 1219 0 stevel break; 1220 0 stevel 1221 0 stevel case OP2_FBPfcc: 1222 0 stevel if (COND(instr) == 8) { 1223 0 stevel tp->ftt_type = FASTTRAP_T_ALWAYS; 1224 0 stevel } else { 1225 0 stevel tp->ftt_type = FASTTRAP_T_FCC; 1226 0 stevel tp->ftt_cc = CC(instr); 1227 0 stevel tp->ftt_code = COND(instr); 1228 0 stevel } 1229 0 stevel 1230 0 stevel if (A(instr) != 0) 1231 0 stevel tp->ftt_flags |= FASTTRAP_F_ANNUL; 1232 0 stevel 1233 0 stevel disp = DISP19(instr); 1234 0 stevel disp <<= 13; 1235 0 stevel disp >>= 11; 1236 0 stevel tp->ftt_dest = pc + (intptr_t)disp; 1237 0 stevel break; 1238 0 stevel 1239 0 stevel case OP2_FBfcc: 1240 0 stevel if (COND(instr) == 8) { 1241 0 stevel tp->ftt_type = FASTTRAP_T_ALWAYS; 1242 0 stevel } else { 1243 0 stevel tp->ftt_type = FASTTRAP_T_FCC; 1244 0 stevel tp->ftt_cc = 0; 1245 0 stevel tp->ftt_code = COND(instr); 1246 0 stevel } 1247 0 stevel 1248 0 stevel if (A(instr) != 0) 1249 0 stevel tp->ftt_flags |= FASTTRAP_F_ANNUL; 1250 0 stevel 1251 0 stevel disp = DISP22(instr); 1252 0 stevel disp <<= 10; 1253 0 stevel disp >>= 8; 1254 0 stevel tp->ftt_dest = pc + (intptr_t)disp; 1255 0 stevel break; 1256 0 stevel } 1257 0 stevel 1258 0 stevel } else if (OP(instr) == 2) { 1259 0 stevel switch (OP3(instr)) { 1260 0 stevel case OP3_RETURN: 1261 0 stevel tp->ftt_type = FASTTRAP_T_RETURN; 1262 0 stevel break; 1263 0 stevel 1264 0 stevel case OP3_JMPL: 1265 0 stevel tp->ftt_type = FASTTRAP_T_JMPL; 1266 0 stevel break; 1267 0 stevel 1268 0 stevel case OP3_RD: 1269 0 stevel if (RS1(instr) == 5) 1270 0 stevel tp->ftt_type = FASTTRAP_T_RDPC; 1271 0 stevel break; 1272 0 stevel 1273 0 stevel case OP3_SAVE: 1274 0 stevel /* 1275 0 stevel * We optimize for save instructions at function 1276 0 stevel * entry; see the comment in fasttrap_pid_probe() 1277 0 stevel * (near FASTTRAP_T_SAVE) for details. 1278 0 stevel */ 1279 0 stevel if (fasttrap_optimize_save != 0 && 1280 1710 ahl type == DTFTP_ENTRY && 1281 0 stevel I(instr) == 1 && RD(instr) == R_SP) 1282 0 stevel tp->ftt_type = FASTTRAP_T_SAVE; 1283 0 stevel break; 1284 0 stevel 1285 0 stevel case OP3_RESTORE: 1286 0 stevel /* 1287 0 stevel * We optimize restore instructions at function 1288 0 stevel * return; see the comment in fasttrap_pid_probe() 1289 0 stevel * (near FASTTRAP_T_RESTORE) for details. 1290 0 stevel * 1291 0 stevel * rd must be an %o or %g register. 1292 0 stevel */ 1293 0 stevel if ((RD(instr) & 0x10) == 0) 1294 0 stevel tp->ftt_type = FASTTRAP_T_RESTORE; 1295 0 stevel break; 1296 0 stevel 1297 0 stevel case OP3_OR: 1298 0 stevel /* 1299 0 stevel * A large proportion of instructions in the delay 1300 0 stevel * slot of retl instructions are or's so we emulate 1301 0 stevel * these downstairs as an optimization. 1302 0 stevel */ 1303 0 stevel tp->ftt_type = FASTTRAP_T_OR; 1304 0 stevel break; 1305 0 stevel 1306 0 stevel case OP3_TCC: 1307 0 stevel /* 1308 0 stevel * Breakpoint instructions are effectively position- 1309 0 stevel * dependent since the debugger uses the %pc value 1310 0 stevel * to lookup which breakpoint was executed. As a 1311 0 stevel * result, we can't actually instrument breakpoints. 1312 0 stevel */ 1313 0 stevel if (SW_TRAP(instr) == ST_BREAKPOINT) 1314 0 stevel return (-1); 1315 0 stevel break; 1316 0 stevel 1317 0 stevel case 0x19: 1318 0 stevel case 0x1d: 1319 0 stevel case 0x29: 1320 0 stevel case 0x33: 1321 0 stevel case 0x3f: 1322 0 stevel /* 1323 0 stevel * Identify illegal instructions (See SPARC 1324 0 stevel * Architecture Manual Version 9, E.2 table 32). 1325 0 stevel */ 1326 0 stevel return (-1); 1327 0 stevel } 1328 0 stevel } else if (OP(instr) == 3) { 1329 0 stevel uint32_t op3 = OP3(instr); 1330 0 stevel 1331 0 stevel /* 1332 0 stevel * Identify illegal instructions (See SPARC Architecture 1333 0 stevel * Manual Version 9, E.2 table 33). 1334 0 stevel */ 1335 0 stevel if ((op3 & 0x28) == 0x28) { 1336 0 stevel if (op3 != OP3_PREFETCH && op3 != OP3_CASA && 1337 0 stevel op3 != OP3_PREFETCHA && op3 != OP3_CASXA) 1338 0 stevel return (-1); 1339 0 stevel } else { 1340 0 stevel if ((op3 & 0x0f) == 0x0c || (op3 & 0x3b) == 0x31) 1341 0 stevel return (-1); 1342 0 stevel } 1343 0 stevel } 1344 0 stevel 1345 0 stevel tp->ftt_instr = instr; 1346 0 stevel 1347 0 stevel /* 1348 0 stevel * We don't know how this tracepoint is going to be used, but in case 1349 0 stevel * it's used as part of a function return probe, we need to indicate 1350 0 stevel * whether it's always a return site or only potentially a return 1351 0 stevel * site. If it's part of a return probe, it's always going to be a 1352 0 stevel * return from that function if it's a restore instruction or if 1353 0 stevel * the previous instruction was a return. If we could reliably 1354 0 stevel * distinguish jump tables from return sites, this wouldn't be 1355 0 stevel * necessary. 1356 0 stevel */ 1357 0 stevel if (tp->ftt_type != FASTTRAP_T_RESTORE && 1358 0 stevel (uread(p, &instr, 4, pc - sizeof (instr)) != 0 || 1359 0 stevel !(OP(instr) == 2 && OP3(instr) == OP3_RETURN))) 1360 0 stevel tp->ftt_flags |= FASTTRAP_F_RETMAYBE; 1361 0 stevel 1362 0 stevel return (0); 1363 0 stevel } 1364 0 stevel 1365 0 stevel /*ARGSUSED*/ 1366 0 stevel uint64_t 1367 2179 ahl fasttrap_pid_getarg(void *arg, dtrace_id_t id, void *parg, int argno, 1368 2179 ahl int aframes) 1369 0 stevel { 1370 0 stevel return (fasttrap_anarg(ttolwp(curthread)->lwp_regs, argno)); 1371 0 stevel } 1372 0 stevel 1373 0 stevel /*ARGSUSED*/ 1374 0 stevel uint64_t 1375 0 stevel fasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno, 1376 0 stevel int aframes) 1377 0 stevel { 1378 0 stevel return (fasttrap_anarg(ttolwp(curthread)->lwp_regs, argno)); 1379 0 stevel } 1380 0 stevel 1381 0 stevel static uint64_t fasttrap_getreg_fast_cnt; 1382 0 stevel static uint64_t fasttrap_getreg_mpcb_cnt; 1383 0 stevel static uint64_t fasttrap_getreg_slow_cnt; 1384 0 stevel 1385 0 stevel static ulong_t 1386 0 stevel fasttrap_getreg(struct regs *rp, uint_t reg) 1387 0 stevel { 1388 0 stevel ulong_t value; 1389 0 stevel dtrace_icookie_t cookie; 1390 0 stevel struct machpcb *mpcb; 1391 0 stevel extern ulong_t dtrace_getreg_win(uint_t, uint_t); 1392 0 stevel 1393 0 stevel /* 1394 0 stevel * We have the %os and %gs in our struct regs, but if we need to 1395 0 stevel * snag a %l or %i we need to go scrounging around in the process's 1396 0 stevel * address space. 1397 0 stevel */ 1398 0 stevel if (reg == 0) 1399 0 stevel return (0); 1400 0 stevel 1401 0 stevel if (reg < 16) 1402 0 stevel return ((&rp->r_g1)[reg - 1]); 1403 0 stevel 1404 0 stevel /* 1405 0 stevel * Before we look at the user's stack, we'll check the register 1406 0 stevel * windows to see if the information we want is in there. 1407 0 stevel */ 1408 0 stevel cookie = dtrace_interrupt_disable(); 1409 0 stevel if (dtrace_getotherwin() > 0) { 1410 0 stevel value = dtrace_getreg_win(reg, 1); 1411 0 stevel dtrace_interrupt_enable(cookie); 1412 0 stevel 1413 0 stevel atomic_add_64(&fasttrap_getreg_fast_cnt, 1); 1414 0 stevel 1415 0 stevel return (value); 1416 0 stevel } 1417 0 stevel dtrace_interrupt_enable(cookie); 1418 0 stevel 1419 0 stevel /* 1420 0 stevel * First check the machpcb structure to see if we've already read 1421 0 stevel * in the register window we're looking for; if we haven't, (and 1422 0 stevel * we probably haven't) try to copy in the value of the register. 1423 0 stevel */ 1424 3944 ahl /* LINTED - alignment */ 1425 0 stevel mpcb = (struct machpcb *)((caddr_t)rp - REGOFF); 1426 0 stevel 1427 0 stevel if (get_udatamodel() == DATAMODEL_NATIVE) { 1428 0 stevel struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS); 1429 0 stevel 1430 0 stevel if (mpcb->mpcb_wbcnt > 0) { 1431 0 stevel struct rwindow *rwin = (void *)mpcb->mpcb_wbuf; 1432 0 stevel int i = mpcb->mpcb_wbcnt; 1433 0 stevel do { 1434 0 stevel i--; 1435 0 stevel if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp) 1436 0 stevel continue; 1437 0 stevel 1438 0 stevel atomic_add_64(&fasttrap_getreg_mpcb_cnt, 1); 1439 0 stevel return (rwin[i].rw_local[reg - 16]); 1440 0 stevel } while (i > 0); 1441 0 stevel } 1442 0 stevel 1443 0 stevel if (fasttrap_fulword(&fr->fr_local[reg - 16], &value) != 0) 1444 0 stevel goto err; 1445 0 stevel } else { 1446 1048 raf struct frame32 *fr = 1447 1048 raf (struct frame32 *)(uintptr_t)(caddr32_t)rp->r_sp; 1448 0 stevel uint32_t *v32 = (uint32_t *)&value; 1449 0 stevel 1450 0 stevel if (mpcb->mpcb_wbcnt > 0) { 1451 0 stevel struct rwindow32 *rwin = (void *)mpcb->mpcb_wbuf; 1452 0 stevel int i = mpcb->mpcb_wbcnt; 1453 0 stevel do { 1454 0 stevel i--; 1455 0 stevel if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp) 1456 0 stevel continue; 1457 0 stevel 1458 0 stevel atomic_add_64(&fasttrap_getreg_mpcb_cnt, 1); 1459 0 stevel return (rwin[i].rw_local[reg - 16]); 1460 0 stevel } while (i > 0); 1461 0 stevel } 1462 0 stevel 1463 0 stevel if (fasttrap_fuword32(&fr->fr_local[reg - 16], &v32[1]) != 0) 1464 0 stevel goto err; 1465 0 stevel 1466 0 stevel v32[0] = 0; 1467 0 stevel } 1468 0 stevel 1469 0 stevel atomic_add_64(&fasttrap_getreg_slow_cnt, 1); 1470 0 stevel return (value); 1471 0 stevel 1472 0 stevel err: 1473 0 stevel /* 1474 0 stevel * If the copy in failed, the process will be in a irrecoverable 1475 0 stevel * state, and we have no choice but to kill it. 1476 0 stevel */ 1477 0 stevel psignal(ttoproc(curthread), SIGILL); 1478 0 stevel return (0); 1479 0 stevel } 1480 0 stevel 1481 0 stevel static uint64_t fasttrap_putreg_fast_cnt; 1482 0 stevel static uint64_t fasttrap_putreg_mpcb_cnt; 1483 0 stevel static uint64_t fasttrap_putreg_slow_cnt; 1484 0 stevel 1485 0 stevel static void 1486 0 stevel fasttrap_putreg(struct regs *rp, uint_t reg, ulong_t value) 1487 0 stevel { 1488 0 stevel dtrace_icookie_t cookie; 1489 0 stevel struct machpcb *mpcb; 1490 0 stevel extern void dtrace_putreg_win(uint_t, ulong_t); 1491 0 stevel 1492 0 stevel if (reg == 0) 1493 0 stevel return; 1494 0 stevel 1495 0 stevel if (reg < 16) { 1496 0 stevel (&rp->r_g1)[reg - 1] = value; 1497 0 stevel return; 1498 0 stevel } 1499 0 stevel 1500 0 stevel /* 1501 0 stevel * If the user process is still using some register windows, we 1502 0 stevel * can just place the value in the correct window. 1503 0 stevel */ 1504 0 stevel cookie = dtrace_interrupt_disable(); 1505 0 stevel if (dtrace_getotherwin() > 0) { 1506 0 stevel dtrace_putreg_win(reg, value); 1507 0 stevel dtrace_interrupt_enable(cookie); 1508 0 stevel atomic_add_64(&fasttrap_putreg_fast_cnt, 1); 1509 0 stevel return; 1510 0 stevel } 1511 0 stevel dtrace_interrupt_enable(cookie); 1512 0 stevel 1513 0 stevel /* 1514 0 stevel * First see if there's a copy of the register window in the 1515 0 stevel * machpcb structure that we can modify; if there isn't try to 1516 0 stevel * copy out the value. If that fails, we try to create a new 1517 0 stevel * register window in the machpcb structure. While this isn't 1518 0 stevel * _precisely_ the intended use of the machpcb structure, it 1519 0 stevel * can't cause any problems since we know at this point in the 1520 0 stevel * code that all of the user's data have been flushed out of the 1521 0 stevel * register file (since %otherwin is 0). 1522 0 stevel */ 1523 3944 ahl /* LINTED - alignment */ 1524 0 stevel mpcb = (struct machpcb *)((caddr_t)rp - REGOFF); 1525 0 stevel 1526 0 stevel if (get_udatamodel() == DATAMODEL_NATIVE) { 1527 0 stevel struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS); 1528 3944 ahl /* LINTED - alignment */ 1529 0 stevel struct rwindow *rwin = (struct rwindow *)mpcb->mpcb_wbuf; 1530 0 stevel 1531 0 stevel if (mpcb->mpcb_wbcnt > 0) { 1532 0 stevel int i = mpcb->mpcb_wbcnt; 1533 0 stevel do { 1534 0 stevel i--; 1535 0 stevel if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp) 1536 0 stevel continue; 1537 0 stevel 1538 0 stevel rwin[i].rw_local[reg - 16] = value; 1539 0 stevel atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1); 1540 0 stevel return; 1541 0 stevel } while (i > 0); 1542 0 stevel } 1543 0 stevel 1544 0 stevel if (fasttrap_sulword(&fr->fr_local[reg - 16], value) != 0) { 1545 0 stevel if (mpcb->mpcb_wbcnt >= MAXWIN || copyin(fr, 1546 0 stevel &rwin[mpcb->mpcb_wbcnt], sizeof (*rwin)) != 0) 1547 0 stevel goto err; 1548 0 stevel 1549 0 stevel rwin[mpcb->mpcb_wbcnt].rw_local[reg - 16] = value; 1550 0 stevel mpcb->mpcb_spbuf[mpcb->mpcb_wbcnt] = (caddr_t)rp->r_sp; 1551 0 stevel mpcb->mpcb_wbcnt++; 1552 0 stevel atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1); 1553 0 stevel return; 1554 0 stevel } 1555 0 stevel } else { 1556 1048 raf struct frame32 *fr = 1557 1048 raf (struct frame32 *)(uintptr_t)(caddr32_t)rp->r_sp; 1558 3944 ahl /* LINTED - alignment */ 1559 0 stevel struct rwindow32 *rwin = (struct rwindow32 *)mpcb->mpcb_wbuf; 1560 0 stevel uint32_t v32 = (uint32_t)value; 1561 0 stevel 1562 0 stevel if (mpcb->mpcb_wbcnt > 0) { 1563 0 stevel int i = mpcb->mpcb_wbcnt; 1564 0 stevel do { 1565 0 stevel i--; 1566 0 stevel if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp) 1567 0 stevel continue; 1568 0 stevel 1569 0 stevel rwin[i].rw_local[reg - 16] = v32; 1570 0 stevel atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1); 1571 0 stevel return; 1572 0 stevel } while (i > 0); 1573 0 stevel } 1574 0 stevel 1575 0 stevel if (fasttrap_suword32(&fr->fr_local[reg - 16], v32) != 0) { 1576 0 stevel if (mpcb->mpcb_wbcnt >= MAXWIN || copyin(fr, 1577 0 stevel &rwin[mpcb->mpcb_wbcnt], sizeof (*rwin)) != 0) 1578 0 stevel goto err; 1579 0 stevel 1580 0 stevel rwin[mpcb->mpcb_wbcnt].rw_local[reg - 16] = v32; 1581 0 stevel mpcb->mpcb_spbuf[mpcb->mpcb_wbcnt] = (caddr_t)rp->r_sp; 1582 0 stevel mpcb->mpcb_wbcnt++; 1583 0 stevel atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1); 1584 0 stevel return; 1585 0 stevel } 1586 0 stevel } 1587 0 stevel 1588 0 stevel atomic_add_64(&fasttrap_putreg_slow_cnt, 1); 1589 0 stevel return; 1590 0 stevel 1591 0 stevel err: 1592 0 stevel /* 1593 0 stevel * If we couldn't record this register's value, the process is in an 1594 0 stevel * irrecoverable state and we have no choice but to euthanize it. 1595 0 stevel */ 1596 0 stevel psignal(ttoproc(curthread), SIGILL); 1597 0 stevel } 1598