1242723Sjhibbits/* 2242723Sjhibbits * CDDL HEADER START 3242723Sjhibbits * 4242723Sjhibbits * The contents of this file are subject to the terms of the 5242723Sjhibbits * Common Development and Distribution License (the "License"). 6242723Sjhibbits * You may not use this file except in compliance with the License. 7242723Sjhibbits * 8242723Sjhibbits * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9242723Sjhibbits * or http://www.opensolaris.org/os/licensing. 10242723Sjhibbits * See the License for the specific language governing permissions 11242723Sjhibbits * and limitations under the License. 12242723Sjhibbits * 13242723Sjhibbits * When distributing Covered Code, include this CDDL HEADER in each 14242723Sjhibbits * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15242723Sjhibbits * If applicable, add the following below this CDDL HEADER, with the 16242723Sjhibbits * fields enclosed by brackets "[]" replaced with your own identifying 17242723Sjhibbits * information: Portions Copyright [yyyy] [name of copyright owner] 18242723Sjhibbits * 19242723Sjhibbits * CDDL HEADER END 20242723Sjhibbits */ 21260670Sjhibbits/* Portions Copyright 2013 Justin Hibbits */ 22242723Sjhibbits/* 23242723Sjhibbits * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24242723Sjhibbits * Use is subject to license terms. 25242723Sjhibbits */ 26242723Sjhibbits 27260670Sjhibbits#include <sys/fasttrap_isa.h> 28260670Sjhibbits#include <sys/fasttrap_impl.h> 29260670Sjhibbits#include <sys/dtrace.h> 30260670Sjhibbits#include <sys/dtrace_impl.h> 31260670Sjhibbits#include <cddl/dev/dtrace/dtrace_cddl.h> 32260670Sjhibbits#include <sys/proc.h> 33260670Sjhibbits#include <sys/types.h> 34260670Sjhibbits#include <sys/uio.h> 35260670Sjhibbits#include <sys/ptrace.h> 36260670Sjhibbits#include <sys/sysent.h> 37242723Sjhibbits 38260670Sjhibbits#define OP(x) ((x) >> 26) 39260670Sjhibbits#define OPX(x) (((x) >> 2) & 0x3FF) 40260670Sjhibbits#define OP_BO(x) (((x) & 0x03E00000) >> 21) 41260670Sjhibbits#define OP_BI(x) (((x) & 0x001F0000) >> 16) 42260670Sjhibbits#define OP_RS(x) (((x) & 0x03E00000) >> 21) 43260670Sjhibbits#define OP_RA(x) (((x) & 0x001F0000) >> 16) 44260670Sjhibbits#define OP_RB(x) (((x) & 0x0000F100) >> 11) 45260670Sjhibbits 46260670Sjhibbits 47260670Sjhibbitsstatic int 48260670Sjhibbitsproc_ops(int op, proc_t *p, void *kaddr, off_t uaddr, size_t len) 49260670Sjhibbits{ 50260670Sjhibbits struct iovec iov; 51260670Sjhibbits struct uio uio; 52260670Sjhibbits 53260670Sjhibbits iov.iov_base = kaddr; 54260670Sjhibbits iov.iov_len = len; 55260670Sjhibbits uio.uio_offset = uaddr; 56260670Sjhibbits uio.uio_iov = &iov; 57260670Sjhibbits uio.uio_resid = len; 58260670Sjhibbits uio.uio_iovcnt = 1; 59260670Sjhibbits uio.uio_segflg = UIO_SYSSPACE; 60260670Sjhibbits uio.uio_td = curthread; 61260670Sjhibbits uio.uio_rw = op; 62260670Sjhibbits PHOLD(p); 63269756Smarkj if (proc_rwmem(p, &uio) != 0) { 64260670Sjhibbits PRELE(p); 65260670Sjhibbits return (-1); 66260670Sjhibbits } 67260670Sjhibbits PRELE(p); 68260670Sjhibbits 69260670Sjhibbits return (0); 70260670Sjhibbits} 71260670Sjhibbits 72260670Sjhibbitsstatic int 73260670Sjhibbitsuread(proc_t *p, void *kaddr, size_t len, uintptr_t uaddr) 74260670Sjhibbits{ 75260670Sjhibbits 76260670Sjhibbits return (proc_ops(UIO_READ, p, kaddr, uaddr, len)); 77260670Sjhibbits} 78260670Sjhibbits 79260670Sjhibbitsstatic int 80260670Sjhibbitsuwrite(proc_t *p, void *kaddr, size_t len, uintptr_t uaddr) 81260670Sjhibbits{ 82260670Sjhibbits 83260670Sjhibbits return (proc_ops(UIO_WRITE, p, kaddr, uaddr, len)); 84260670Sjhibbits} 85260670Sjhibbits 86260670Sjhibbitsint 87260670Sjhibbitsfasttrap_tracepoint_install(proc_t *p, fasttrap_tracepoint_t *tp) 88260670Sjhibbits{ 89260670Sjhibbits fasttrap_instr_t instr = FASTTRAP_INSTR; 90260670Sjhibbits 91260670Sjhibbits if (uwrite(p, &instr, 4, tp->ftt_pc) != 0) 92260670Sjhibbits return (-1); 93260670Sjhibbits 94260670Sjhibbits return (0); 95260670Sjhibbits} 96260670Sjhibbits 97260670Sjhibbitsint 98260670Sjhibbitsfasttrap_tracepoint_remove(proc_t *p, fasttrap_tracepoint_t *tp) 99260670Sjhibbits{ 100260670Sjhibbits uint32_t instr; 101260670Sjhibbits 102260670Sjhibbits /* 103260670Sjhibbits * Distinguish between read or write failures and a changed 104260670Sjhibbits * instruction. 105260670Sjhibbits */ 106260670Sjhibbits if (uread(p, &instr, 4, tp->ftt_pc) != 0) 107260670Sjhibbits return (0); 108260670Sjhibbits if (instr != FASTTRAP_INSTR) 109260670Sjhibbits return (0); 110260670Sjhibbits if (uwrite(p, &tp->ftt_instr, 4, tp->ftt_pc) != 0) 111260670Sjhibbits return (-1); 112260670Sjhibbits 113260670Sjhibbits return (0); 114260670Sjhibbits} 115260670Sjhibbits 116260670Sjhibbitsint 117260670Sjhibbitsfasttrap_tracepoint_init(proc_t *p, fasttrap_tracepoint_t *tp, uintptr_t pc, 118260670Sjhibbits fasttrap_probe_type_t type) 119260670Sjhibbits{ 120260670Sjhibbits uint32_t instr; 121260670Sjhibbits //int32_t disp; 122260670Sjhibbits 123260670Sjhibbits /* 124260670Sjhibbits * Read the instruction at the given address out of the process's 125260670Sjhibbits * address space. We don't have to worry about a debugger 126260670Sjhibbits * changing this instruction before we overwrite it with our trap 127260670Sjhibbits * instruction since P_PR_LOCK is set. 128260670Sjhibbits */ 129260670Sjhibbits if (uread(p, &instr, 4, pc) != 0) 130260670Sjhibbits return (-1); 131260670Sjhibbits 132260670Sjhibbits /* 133260670Sjhibbits * Decode the instruction to fill in the probe flags. We can have 134260670Sjhibbits * the process execute most instructions on its own using a pc/npc 135260670Sjhibbits * trick, but pc-relative control transfer present a problem since 136260670Sjhibbits * we're relocating the instruction. We emulate these instructions 137260670Sjhibbits * in the kernel. We assume a default type and over-write that as 138260670Sjhibbits * needed. 139260670Sjhibbits * 140260670Sjhibbits * pc-relative instructions must be emulated for correctness; 141260670Sjhibbits * other instructions (which represent a large set of commonly traced 142260670Sjhibbits * instructions) are emulated or otherwise optimized for performance. 143260670Sjhibbits */ 144260670Sjhibbits tp->ftt_type = FASTTRAP_T_COMMON; 145260670Sjhibbits tp->ftt_instr = instr; 146260670Sjhibbits 147260670Sjhibbits switch (OP(instr)) { 148260670Sjhibbits /* The following are invalid for trapping (invalid opcodes, tw/twi). */ 149260670Sjhibbits case 0: 150260670Sjhibbits case 1: 151260670Sjhibbits case 2: 152260670Sjhibbits case 4: 153260670Sjhibbits case 5: 154260670Sjhibbits case 6: 155260670Sjhibbits case 30: 156260670Sjhibbits case 39: 157260670Sjhibbits case 58: 158260670Sjhibbits case 62: 159260670Sjhibbits case 3: /* twi */ 160260670Sjhibbits return (-1); 161260670Sjhibbits case 31: /* tw */ 162260670Sjhibbits if (OPX(instr) == 4) 163260670Sjhibbits return (-1); 164260670Sjhibbits else if (OPX(instr) == 444 && OP_RS(instr) == OP_RA(instr) && 165260670Sjhibbits OP_RS(instr) == OP_RB(instr)) 166260670Sjhibbits tp->ftt_type = FASTTRAP_T_NOP; 167260670Sjhibbits break; 168260670Sjhibbits case 16: 169260670Sjhibbits tp->ftt_type = FASTTRAP_T_BC; 170260670Sjhibbits tp->ftt_dest = instr & 0x0000FFFC; /* Extract target address */ 171260670Sjhibbits if (instr & 0x00008000) 172260670Sjhibbits tp->ftt_dest |= 0xFFFF0000; 173260670Sjhibbits /* Use as offset if not absolute address. */ 174260670Sjhibbits if (!(instr & 0x02)) 175260670Sjhibbits tp->ftt_dest += pc; 176260670Sjhibbits tp->ftt_bo = OP_BO(instr); 177260670Sjhibbits tp->ftt_bi = OP_BI(instr); 178260670Sjhibbits break; 179260670Sjhibbits case 18: 180260670Sjhibbits tp->ftt_type = FASTTRAP_T_B; 181260670Sjhibbits tp->ftt_dest = instr & 0x03FFFFFC; /* Extract target address */ 182260670Sjhibbits if (instr & 0x02000000) 183260670Sjhibbits tp->ftt_dest |= 0xFC000000; 184260670Sjhibbits /* Use as offset if not absolute address. */ 185260670Sjhibbits if (!(instr & 0x02)) 186260670Sjhibbits tp->ftt_dest += pc; 187260670Sjhibbits break; 188260670Sjhibbits case 19: 189260670Sjhibbits switch (OPX(instr)) { 190260670Sjhibbits case 528: /* bcctr */ 191260670Sjhibbits tp->ftt_type = FASTTRAP_T_BCTR; 192260670Sjhibbits tp->ftt_bo = OP_BO(instr); 193260670Sjhibbits tp->ftt_bi = OP_BI(instr); 194260670Sjhibbits break; 195260670Sjhibbits case 16: /* bclr */ 196260670Sjhibbits tp->ftt_type = FASTTRAP_T_BCTR; 197260670Sjhibbits tp->ftt_bo = OP_BO(instr); 198260670Sjhibbits tp->ftt_bi = OP_BI(instr); 199260670Sjhibbits break; 200260670Sjhibbits }; 201260670Sjhibbits break; 202260670Sjhibbits case 24: 203260670Sjhibbits if (OP_RS(instr) == OP_RA(instr) && 204260670Sjhibbits (instr & 0x0000FFFF) == 0) 205260670Sjhibbits tp->ftt_type = FASTTRAP_T_NOP; 206260670Sjhibbits break; 207260670Sjhibbits }; 208260670Sjhibbits 209260670Sjhibbits /* 210260670Sjhibbits * We don't know how this tracepoint is going to be used, but in case 211260670Sjhibbits * it's used as part of a function return probe, we need to indicate 212260670Sjhibbits * whether it's always a return site or only potentially a return 213260670Sjhibbits * site. If it's part of a return probe, it's always going to be a 214260670Sjhibbits * return from that function if it's a restore instruction or if 215260670Sjhibbits * the previous instruction was a return. If we could reliably 216260670Sjhibbits * distinguish jump tables from return sites, this wouldn't be 217260670Sjhibbits * necessary. 218260670Sjhibbits */ 219260670Sjhibbits#if 0 220260670Sjhibbits if (tp->ftt_type != FASTTRAP_T_RESTORE && 221260670Sjhibbits (uread(p, &instr, 4, pc - sizeof (instr)) != 0 || 222260670Sjhibbits !(OP(instr) == 2 && OP3(instr) == OP3_RETURN))) 223260670Sjhibbits tp->ftt_flags |= FASTTRAP_F_RETMAYBE; 224260670Sjhibbits#endif 225260670Sjhibbits 226260670Sjhibbits return (0); 227260670Sjhibbits} 228260670Sjhibbits 229260670Sjhibbitsstatic uint64_t 230260670Sjhibbitsfasttrap_anarg(struct reg *rp, int argno) 231260670Sjhibbits{ 232260670Sjhibbits uint64_t value; 233260670Sjhibbits proc_t *p = curproc; 234260670Sjhibbits 235260670Sjhibbits /* The first 8 arguments are in registers. */ 236260670Sjhibbits if (argno < 8) 237260670Sjhibbits return rp->fixreg[argno + 3]; 238260670Sjhibbits 239260670Sjhibbits /* Arguments on stack start after SP+LR (2 register slots). */ 240260670Sjhibbits if (SV_PROC_FLAG(p, SV_ILP32)) { 241260670Sjhibbits DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 242260670Sjhibbits value = dtrace_fuword32((void *)(rp->fixreg[1] + 8 + 243260670Sjhibbits ((argno - 8) * sizeof(uint32_t)))); 244260670Sjhibbits DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | CPU_DTRACE_BADADDR); 245260670Sjhibbits } else { 246260670Sjhibbits DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 247260670Sjhibbits value = dtrace_fuword64((void *)(rp->fixreg[1] + 16 + 248260670Sjhibbits ((argno - 8) * sizeof(uint32_t)))); 249260670Sjhibbits DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | CPU_DTRACE_BADADDR); 250260670Sjhibbits } 251260670Sjhibbits return value; 252260670Sjhibbits} 253260670Sjhibbits 254260670Sjhibbitsuint64_t 255260670Sjhibbitsfasttrap_pid_getarg(void *arg, dtrace_id_t id, void *parg, int argno, 256260670Sjhibbits int aframes) 257260670Sjhibbits{ 258260670Sjhibbits struct reg r; 259260670Sjhibbits 260260670Sjhibbits fill_regs(curthread, &r); 261260670Sjhibbits 262260670Sjhibbits return (fasttrap_anarg(&r, argno)); 263260670Sjhibbits} 264260670Sjhibbits 265260670Sjhibbitsuint64_t 266260670Sjhibbitsfasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno, 267260670Sjhibbits int aframes) 268260670Sjhibbits{ 269260670Sjhibbits struct reg r; 270260670Sjhibbits 271260670Sjhibbits fill_regs(curthread, &r); 272260670Sjhibbits 273260670Sjhibbits return (fasttrap_anarg(&r, argno)); 274260670Sjhibbits} 275260670Sjhibbits 276260670Sjhibbitsstatic void 277260670Sjhibbitsfasttrap_usdt_args(fasttrap_probe_t *probe, struct reg *rp, int argc, 278260670Sjhibbits uintptr_t *argv) 279260670Sjhibbits{ 280260670Sjhibbits int i, x, cap = MIN(argc, probe->ftp_nargs); 281260670Sjhibbits 282260670Sjhibbits for (i = 0; i < cap; i++) { 283260670Sjhibbits x = probe->ftp_argmap[i]; 284260670Sjhibbits 285260670Sjhibbits if (x < 8) 286260670Sjhibbits argv[i] = rp->fixreg[x]; 287260670Sjhibbits else 288260670Sjhibbits if (SV_PROC_FLAG(curproc, SV_ILP32)) 289260670Sjhibbits argv[i] = fuword32((void *)(rp->fixreg[1] + 8 + 290260670Sjhibbits (x * sizeof(uint32_t)))); 291260670Sjhibbits else 292260670Sjhibbits argv[i] = fuword32((void *)(rp->fixreg[1] + 16 + 293260670Sjhibbits (x * sizeof(uint64_t)))); 294260670Sjhibbits } 295260670Sjhibbits 296260670Sjhibbits for (; i < argc; i++) { 297260670Sjhibbits argv[i] = 0; 298260670Sjhibbits } 299260670Sjhibbits} 300260670Sjhibbits 301260670Sjhibbitsstatic void 302260670Sjhibbitsfasttrap_return_common(struct reg *rp, uintptr_t pc, pid_t pid, 303260670Sjhibbits uintptr_t new_pc) 304260670Sjhibbits{ 305260670Sjhibbits fasttrap_tracepoint_t *tp; 306260670Sjhibbits fasttrap_bucket_t *bucket; 307260670Sjhibbits fasttrap_id_t *id; 308260670Sjhibbits 309260670Sjhibbits bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; 310260670Sjhibbits 311260670Sjhibbits for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { 312260670Sjhibbits if (pid == tp->ftt_pid && pc == tp->ftt_pc && 313260670Sjhibbits tp->ftt_proc->ftpc_acount != 0) 314260670Sjhibbits break; 315260670Sjhibbits } 316260670Sjhibbits 317260670Sjhibbits /* 318260670Sjhibbits * Don't sweat it if we can't find the tracepoint again; unlike 319260670Sjhibbits * when we're in fasttrap_pid_probe(), finding the tracepoint here 320260670Sjhibbits * is not essential to the correct execution of the process. 321260670Sjhibbits */ 322260670Sjhibbits if (tp == NULL) { 323260670Sjhibbits return; 324260670Sjhibbits } 325260670Sjhibbits 326260670Sjhibbits for (id = tp->ftt_retids; id != NULL; id = id->fti_next) { 327260670Sjhibbits /* 328260670Sjhibbits * If there's a branch that could act as a return site, we 329260670Sjhibbits * need to trace it, and check here if the program counter is 330260670Sjhibbits * external to the function. 331260670Sjhibbits */ 332260670Sjhibbits /* Skip function-local branches. */ 333260670Sjhibbits if ((new_pc - id->fti_probe->ftp_faddr) < id->fti_probe->ftp_fsize) 334260670Sjhibbits continue; 335260670Sjhibbits 336260670Sjhibbits dtrace_probe(id->fti_probe->ftp_id, 337260670Sjhibbits pc - id->fti_probe->ftp_faddr, 338260670Sjhibbits rp->fixreg[3], rp->fixreg[4], 0, 0); 339260670Sjhibbits } 340260670Sjhibbits} 341260670Sjhibbits 342260670Sjhibbits 343260670Sjhibbitsstatic int 344260670Sjhibbitsfasttrap_branch_taken(int bo, int bi, struct reg *regs) 345260670Sjhibbits{ 346260670Sjhibbits int crzero = 0; 347260670Sjhibbits 348260670Sjhibbits /* Branch always? */ 349260670Sjhibbits if ((bo & 0x14) == 0x14) 350260670Sjhibbits return 1; 351260670Sjhibbits 352260670Sjhibbits /* Handle decrementing ctr */ 353260670Sjhibbits if (!(bo & 0x04)) { 354260670Sjhibbits --regs->ctr; 355260670Sjhibbits crzero = (regs->ctr == 0); 356260670Sjhibbits if (bo & 0x10) { 357260670Sjhibbits return (!(crzero ^ (bo >> 1))); 358260670Sjhibbits } 359260670Sjhibbits } 360260670Sjhibbits 361260670Sjhibbits return (crzero | (((regs->cr >> (31 - bi)) ^ (bo >> 3)) ^ 1)); 362260670Sjhibbits} 363260670Sjhibbits 364260670Sjhibbits 365260670Sjhibbitsint 366260670Sjhibbitsfasttrap_pid_probe(struct reg *rp) 367260670Sjhibbits{ 368260670Sjhibbits proc_t *p = curproc; 369260670Sjhibbits uintptr_t pc = rp->pc; 370260670Sjhibbits uintptr_t new_pc = 0; 371260670Sjhibbits fasttrap_bucket_t *bucket; 372260670Sjhibbits fasttrap_tracepoint_t *tp, tp_local; 373260670Sjhibbits pid_t pid; 374260670Sjhibbits dtrace_icookie_t cookie; 375260670Sjhibbits uint_t is_enabled = 0; 376260670Sjhibbits 377260670Sjhibbits /* 378260670Sjhibbits * It's possible that a user (in a veritable orgy of bad planning) 379260670Sjhibbits * could redirect this thread's flow of control before it reached the 380260670Sjhibbits * return probe fasttrap. In this case we need to kill the process 381260670Sjhibbits * since it's in a unrecoverable state. 382260670Sjhibbits */ 383260670Sjhibbits if (curthread->t_dtrace_step) { 384260670Sjhibbits ASSERT(curthread->t_dtrace_on); 385260670Sjhibbits fasttrap_sigtrap(p, curthread, pc); 386260670Sjhibbits return (0); 387260670Sjhibbits } 388260670Sjhibbits 389260670Sjhibbits /* 390260670Sjhibbits * Clear all user tracing flags. 391260670Sjhibbits */ 392260670Sjhibbits curthread->t_dtrace_ft = 0; 393260670Sjhibbits curthread->t_dtrace_pc = 0; 394260670Sjhibbits curthread->t_dtrace_npc = 0; 395260670Sjhibbits curthread->t_dtrace_scrpc = 0; 396260670Sjhibbits curthread->t_dtrace_astpc = 0; 397260670Sjhibbits 398260670Sjhibbits 399260670Sjhibbits PROC_LOCK(p); 400260670Sjhibbits pid = p->p_pid; 401260670Sjhibbits bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; 402260670Sjhibbits 403260670Sjhibbits /* 404260670Sjhibbits * Lookup the tracepoint that the process just hit. 405260670Sjhibbits */ 406260670Sjhibbits for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { 407260670Sjhibbits if (pid == tp->ftt_pid && pc == tp->ftt_pc && 408260670Sjhibbits tp->ftt_proc->ftpc_acount != 0) 409260670Sjhibbits break; 410260670Sjhibbits } 411260670Sjhibbits 412260670Sjhibbits /* 413260670Sjhibbits * If we couldn't find a matching tracepoint, either a tracepoint has 414260670Sjhibbits * been inserted without using the pid<pid> ioctl interface (see 415260670Sjhibbits * fasttrap_ioctl), or somehow we have mislaid this tracepoint. 416260670Sjhibbits */ 417260670Sjhibbits if (tp == NULL) { 418260670Sjhibbits PROC_UNLOCK(p); 419260670Sjhibbits return (-1); 420260670Sjhibbits } 421260670Sjhibbits 422260670Sjhibbits if (tp->ftt_ids != NULL) { 423260670Sjhibbits fasttrap_id_t *id; 424260670Sjhibbits 425260670Sjhibbits for (id = tp->ftt_ids; id != NULL; id = id->fti_next) { 426260670Sjhibbits fasttrap_probe_t *probe = id->fti_probe; 427260670Sjhibbits 428260670Sjhibbits if (id->fti_ptype == DTFTP_ENTRY) { 429260670Sjhibbits /* 430260670Sjhibbits * We note that this was an entry 431260670Sjhibbits * probe to help ustack() find the 432260670Sjhibbits * first caller. 433260670Sjhibbits */ 434260670Sjhibbits cookie = dtrace_interrupt_disable(); 435260670Sjhibbits DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY); 436260670Sjhibbits dtrace_probe(probe->ftp_id, rp->fixreg[3], 437260670Sjhibbits rp->fixreg[4], rp->fixreg[5], rp->fixreg[6], 438260670Sjhibbits rp->fixreg[7]); 439260670Sjhibbits DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY); 440260670Sjhibbits dtrace_interrupt_enable(cookie); 441260670Sjhibbits } else if (id->fti_ptype == DTFTP_IS_ENABLED) { 442260670Sjhibbits /* 443260670Sjhibbits * Note that in this case, we don't 444260670Sjhibbits * call dtrace_probe() since it's only 445260670Sjhibbits * an artificial probe meant to change 446260670Sjhibbits * the flow of control so that it 447260670Sjhibbits * encounters the true probe. 448260670Sjhibbits */ 449260670Sjhibbits is_enabled = 1; 450260670Sjhibbits } else if (probe->ftp_argmap == NULL) { 451260670Sjhibbits dtrace_probe(probe->ftp_id, rp->fixreg[3], 452260670Sjhibbits rp->fixreg[4], rp->fixreg[5], rp->fixreg[6], 453260670Sjhibbits rp->fixreg[7]); 454260670Sjhibbits } else { 455260670Sjhibbits uintptr_t t[5]; 456260670Sjhibbits 457260670Sjhibbits fasttrap_usdt_args(probe, rp, 458260670Sjhibbits sizeof (t) / sizeof (t[0]), t); 459260670Sjhibbits 460260670Sjhibbits dtrace_probe(probe->ftp_id, t[0], t[1], 461260670Sjhibbits t[2], t[3], t[4]); 462260670Sjhibbits } 463260670Sjhibbits } 464260670Sjhibbits } 465260670Sjhibbits 466260670Sjhibbits /* 467260670Sjhibbits * We're about to do a bunch of work so we cache a local copy of 468260670Sjhibbits * the tracepoint to emulate the instruction, and then find the 469260670Sjhibbits * tracepoint again later if we need to light up any return probes. 470260670Sjhibbits */ 471260670Sjhibbits tp_local = *tp; 472260670Sjhibbits PROC_UNLOCK(p); 473260670Sjhibbits tp = &tp_local; 474260670Sjhibbits 475260670Sjhibbits /* 476260670Sjhibbits * If there's an is-enabled probe connected to this tracepoint it 477260670Sjhibbits * means that there was a 'xor r3, r3, r3' 478260670Sjhibbits * instruction that was placed there by DTrace when the binary was 479260670Sjhibbits * linked. As this probe is, in fact, enabled, we need to stuff 1 480260670Sjhibbits * into R3. Accordingly, we can bypass all the instruction 481260670Sjhibbits * emulation logic since we know the inevitable result. It's possible 482260670Sjhibbits * that a user could construct a scenario where the 'is-enabled' 483260670Sjhibbits * probe was on some other instruction, but that would be a rather 484260670Sjhibbits * exotic way to shoot oneself in the foot. 485260670Sjhibbits */ 486260670Sjhibbits if (is_enabled) { 487260670Sjhibbits rp->fixreg[3] = 1; 488260670Sjhibbits new_pc = rp->pc + 4; 489260670Sjhibbits goto done; 490260670Sjhibbits } 491260670Sjhibbits 492260670Sjhibbits 493260670Sjhibbits switch (tp->ftt_type) { 494260670Sjhibbits case FASTTRAP_T_NOP: 495260670Sjhibbits new_pc = rp->pc + 4; 496260670Sjhibbits break; 497260670Sjhibbits case FASTTRAP_T_BC: 498260670Sjhibbits if (!fasttrap_branch_taken(tp->ftt_bo, tp->ftt_bi, rp)) 499260670Sjhibbits break; 500260670Sjhibbits /* FALLTHROUGH */ 501260670Sjhibbits case FASTTRAP_T_B: 502260670Sjhibbits if (tp->ftt_instr & 0x01) 503260670Sjhibbits rp->lr = rp->pc + 4; 504260670Sjhibbits new_pc = tp->ftt_dest; 505260670Sjhibbits break; 506260670Sjhibbits case FASTTRAP_T_BLR: 507260670Sjhibbits case FASTTRAP_T_BCTR: 508260670Sjhibbits if (!fasttrap_branch_taken(tp->ftt_bo, tp->ftt_bi, rp)) 509260670Sjhibbits break; 510260670Sjhibbits /* FALLTHROUGH */ 511260670Sjhibbits if (tp->ftt_type == FASTTRAP_T_BCTR) 512260670Sjhibbits new_pc = rp->ctr; 513260670Sjhibbits else 514260670Sjhibbits new_pc = rp->lr; 515260670Sjhibbits if (tp->ftt_instr & 0x01) 516260670Sjhibbits rp->lr = rp->pc + 4; 517260670Sjhibbits break; 518260670Sjhibbits case FASTTRAP_T_COMMON: 519260670Sjhibbits break; 520260670Sjhibbits }; 521260670Sjhibbitsdone: 522260670Sjhibbits /* 523260670Sjhibbits * If there were no return probes when we first found the tracepoint, 524260670Sjhibbits * we should feel no obligation to honor any return probes that were 525260670Sjhibbits * subsequently enabled -- they'll just have to wait until the next 526260670Sjhibbits * time around. 527260670Sjhibbits */ 528260670Sjhibbits if (tp->ftt_retids != NULL) { 529260670Sjhibbits /* 530260670Sjhibbits * We need to wait until the results of the instruction are 531260670Sjhibbits * apparent before invoking any return probes. If this 532260670Sjhibbits * instruction was emulated we can just call 533260670Sjhibbits * fasttrap_return_common(); if it needs to be executed, we 534260670Sjhibbits * need to wait until the user thread returns to the kernel. 535260670Sjhibbits */ 536260670Sjhibbits if (tp->ftt_type != FASTTRAP_T_COMMON) { 537260670Sjhibbits fasttrap_return_common(rp, pc, pid, new_pc); 538260670Sjhibbits } else { 539260670Sjhibbits ASSERT(curthread->t_dtrace_ret != 0); 540260670Sjhibbits ASSERT(curthread->t_dtrace_pc == pc); 541260670Sjhibbits ASSERT(curthread->t_dtrace_scrpc != 0); 542260670Sjhibbits ASSERT(new_pc == curthread->t_dtrace_astpc); 543260670Sjhibbits } 544260670Sjhibbits } 545260670Sjhibbits 546260670Sjhibbits rp->pc = new_pc; 547260670Sjhibbits set_regs(curthread, rp); 548260670Sjhibbits 549260670Sjhibbits return (0); 550260670Sjhibbits} 551260670Sjhibbits 552260670Sjhibbitsint 553260670Sjhibbitsfasttrap_return_probe(struct reg *rp) 554260670Sjhibbits{ 555260670Sjhibbits proc_t *p = curproc; 556260670Sjhibbits uintptr_t pc = curthread->t_dtrace_pc; 557260670Sjhibbits uintptr_t npc = curthread->t_dtrace_npc; 558260670Sjhibbits 559260670Sjhibbits curthread->t_dtrace_pc = 0; 560260670Sjhibbits curthread->t_dtrace_npc = 0; 561260670Sjhibbits curthread->t_dtrace_scrpc = 0; 562260670Sjhibbits curthread->t_dtrace_astpc = 0; 563260670Sjhibbits 564260670Sjhibbits /* 565260670Sjhibbits * We set rp->pc to the address of the traced instruction so 566260670Sjhibbits * that it appears to dtrace_probe() that we're on the original 567260670Sjhibbits * instruction, and so that the user can't easily detect our 568260670Sjhibbits * complex web of lies. dtrace_return_probe() (our caller) 569260670Sjhibbits * will correctly set %pc after we return. 570260670Sjhibbits */ 571260670Sjhibbits rp->pc = pc; 572260670Sjhibbits 573260670Sjhibbits fasttrap_return_common(rp, pc, p->p_pid, npc); 574260670Sjhibbits 575260670Sjhibbits return (0); 576260670Sjhibbits} 577260670Sjhibbits 578