From 0b38a8bdfd75ac6144f9d462bb38d0c1b3f0ca50 Mon Sep 17 00:00:00 2001 From: ahl Date: Wed, 20 Jul 2005 01:15:45 -0700 Subject: 4970475 There should be a stackdepth equivalent for userland 5084954 value of dip can be incorrect in autovec 6181505 dtrace sysinfo:::modload probe does not fire when using 'modload' 6265417 schedctl-yield isn't listed in sdt_subr.c 6272558 gcc and dtrace don't get along 6276101 dtrace -G behaves strangely with multiple scripts 6284880 intrstat can leak dynamic variable state 6295662 plockstat needs more characters for stack addresses 6296903 invalid memory accesses clear other DTrace error bits --- usr/src/cmd/dtrace/dtrace.c | 30 ++++-- usr/src/cmd/intrstat/intrstat.c | 3 +- usr/src/cmd/plockstat/plockstat.c | 2 +- usr/src/lib/libdtrace/common/dt_link.c | 56 +++++++++++- usr/src/lib/libdtrace/common/dt_map.c | 5 +- usr/src/lib/libdtrace/common/dt_open.c | 11 ++- usr/src/lib/libdtrace/common/dt_options.c | 6 +- usr/src/uts/common/dtrace/dtrace.c | 95 +++++++++++-------- usr/src/uts/common/dtrace/sdt_subr.c | 5 +- usr/src/uts/common/io/avintr.c | 7 +- usr/src/uts/common/os/modctl.c | 10 +- usr/src/uts/common/sys/dtrace.h | 1 + usr/src/uts/common/sys/dtrace_impl.h | 3 + usr/src/uts/i86pc/ml/locore.s | 4 +- usr/src/uts/intel/dtrace/dtrace_isa.c | 146 +++++++++++++++++++++--------- usr/src/uts/sparc/dtrace/dtrace_asm.s | 43 ++++++++- usr/src/uts/sparc/dtrace/dtrace_isa.c | 139 ++++++++++++++++++++-------- 17 files changed, 411 insertions(+), 155 deletions(-) (limited to 'usr/src') diff --git a/usr/src/cmd/dtrace/dtrace.c b/usr/src/cmd/dtrace/dtrace.c index 7c9afbedea..a88aa26273 100644 --- a/usr/src/cmd/dtrace/dtrace.c +++ b/usr/src/cmd/dtrace/dtrace.c @@ -51,6 +51,7 @@ typedef struct dtrace_cmd { const char *dc_name; /* name for error messages */ const char *dc_desc; /* desc for error messages */ dtrace_prog_t *dc_prog; /* program compiled from arg */ + char dc_ofile[PATH_MAX]; /* derived output file name */ } dtrace_cmd_t; #define DMODE_VERS 0 /* display version information and exit (-V) */ @@ -616,25 +617,24 @@ anon_prog(const dtrace_cmd_t *dcp, dof_hdr_t *dof, int n) * file name. Otherwise we use "d.out" as the default output file name. */ static void -link_prog(const dtrace_cmd_t *dcp) +link_prog(dtrace_cmd_t *dcp) { - char file[PATH_MAX], *p; + char *p; - if (g_ofile != NULL) { - (void) snprintf(file, sizeof (file), g_cmdc > 1 ? - "%s.%d" : "%s", g_ofile, (int)(dcp - g_cmdv)); + if (g_cmdc == 1 && g_ofile != NULL) { + (void) strlcpy(dcp->dc_ofile, g_ofile, sizeof (dcp->dc_ofile)); } else if ((p = strrchr(dcp->dc_arg, '.')) != NULL && strcmp(p, ".d") == 0) { p[0] = '\0'; /* strip .d suffix */ - (void) snprintf(file, sizeof (file), + (void) snprintf(dcp->dc_ofile, sizeof (dcp->dc_ofile), "%s.o", basename(dcp->dc_arg)); } else { - (void) snprintf(file, sizeof (file), g_cmdc > 1 ? - "%s.%d" : "%s", "d.out", (int)(dcp - g_cmdv)); + (void) snprintf(dcp->dc_ofile, sizeof (dcp->dc_ofile), + g_cmdc > 1 ? "%s.%d" : "%s", "d.out", (int)(dcp - g_cmdv)); } if (dtrace_program_link(g_dtp, dcp->dc_prog, DTRACE_D_PROBES, - file, g_objc - 1, g_objv + 1) != 0) + dcp->dc_ofile, g_objc - 1, g_objv + 1) != 0) dfatal("failed to link %s %s", dcp->dc_desc, dcp->dc_name); } @@ -1393,6 +1393,18 @@ main(int argc, char *argv[]) case DMODE_LINK: for (i = 0; i < g_cmdc; i++) link_prog(&g_cmdv[i]); + + if (g_cmdc > 1 && g_ofile != NULL) { + char **objv = alloca(g_cmdc * sizeof (char *)); + + for (i = 0; i < g_cmdc; i++) + objv[i] = g_cmdv[i].dc_ofile; + + if (dtrace_program_link(g_dtp, NULL, DTRACE_D_PROBES, + g_ofile, g_cmdc, objv) != 0) + dfatal("failed to link %s", g_ofile); + } + return (g_status); case DMODE_LIST: diff --git a/usr/src/cmd/intrstat/intrstat.c b/usr/src/cmd/intrstat/intrstat.c index 73512d7014..35df72fe38 100644 --- a/usr/src/cmd/intrstat/intrstat.c +++ b/usr/src/cmd/intrstat/intrstat.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -59,6 +59,7 @@ static int g_cpus_per_line = INTRSTAT_CPUS_PER_LINE(80); static const char *g_pname = "intrstat"; static const char *g_prog = "interrupt-start" +"/arg0 != NULL/" "{" " self->ts = vtimestamp;" "}" diff --git a/usr/src/cmd/plockstat/plockstat.c b/usr/src/cmd/plockstat/plockstat.c index 9502d40f6b..10e418a996 100644 --- a/usr/src/cmd/plockstat/plockstat.c +++ b/usr/src/cmd/plockstat/plockstat.c @@ -437,7 +437,7 @@ process_aggregate(dtrace_aggdata_t *agg, void *arg) caddr_t data = agg->dtada_data; dtrace_recdesc_t *rec; uint64_t *a, count, avg; - char buf[40]; + char buf[256]; uintptr_t lock; pid_t pid; uint64_t *stack; diff --git a/usr/src/lib/libdtrace/common/dt_link.c b/usr/src/lib/libdtrace/common/dt_link.c index e6dc34a385..e680927059 100644 --- a/usr/src/lib/libdtrace/common/dt_link.c +++ b/usr/src/lib/libdtrace/common/dt_link.c @@ -1062,11 +1062,56 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags, { char drti[PATH_MAX]; dof_hdr_t *dof; - int fd, status, i; + int fd, status, i, cur; char *cmd, tmp; size_t len; int ret = 0; + /* + * A NULL program indicates a special use in which we just link + * together a bunch of object files specified in objv and then + * unlink(2) those object files. + */ + if (pgp == NULL) { + const char *fmt = "%s -o %s -r"; + + len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file) + 1; + + for (i = 0; i < objc; i++) + len += strlen(objv[i]) + 1; + + cmd = alloca(len); + + cur = snprintf(cmd, len, fmt, dtp->dt_ld_path, file); + + for (i = 0; i < objc; i++) + cur += snprintf(cmd + cur, len - cur, " %s", objv[i]); + + if ((status = system(cmd)) == -1) { + return (dt_link_error(dtp, "failed to run %s: %s", + dtp->dt_ld_path, strerror(errno))); + } + + if (WIFSIGNALED(status)) { + return (dt_link_error(dtp, + "failed to link %s: %s failed due to signal %d", + file, dtp->dt_ld_path, WTERMSIG(status))); + } + + if (WEXITSTATUS(status) != 0) { + return (dt_link_error(dtp, + "failed to link %s: %s exited with status %d\n", + file, dtp->dt_ld_path, WEXITSTATUS(status))); + } + + for (i = 0; i < objc; i++) { + if (strcmp(objv[i], file) != 0) + (void) unlink(objv[i]); + } + + return (0); + } + for (i = 0; i < objc; i++) { if (process_obj(dtp, objv[i]) != 0) return (-1); /* errno is set for us */ @@ -1127,6 +1172,8 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags, } if (!dtp->dt_lazyload) { + const char *fmt = "%s -o %s -r -Blocal -Breduce /dev/fd/%d %s"; + if (dtp->dt_oflags & DTRACE_O_LP64) { (void) snprintf(drti, sizeof (drti), "%s/64/drti.o", _dtrace_libdir); @@ -1135,13 +1182,12 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags, "%s/drti.o", _dtrace_libdir); } - len = snprintf(&tmp, 1, "%s -o %s -r /dev/fd/%d %s", - dtp->dt_ld_path, file, fd, drti) + 1; + len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, fd, + drti) + 1; cmd = alloca(len); - (void) snprintf(cmd, len, "%s -o %s -r /dev/fd/%d %s", - dtp->dt_ld_path, file, fd, drti); + (void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, fd, drti); if ((status = system(cmd)) == -1) { ret = dt_link_error(dtp, "failed to run %s: %s", diff --git a/usr/src/lib/libdtrace/common/dt_map.c b/usr/src/lib/libdtrace/common/dt_map.c index d2c699f101..d07a966be8 100644 --- a/usr/src/lib/libdtrace/common/dt_map.c +++ b/usr/src/lib/libdtrace/common/dt_map.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -355,7 +355,8 @@ dt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id) dtrace_stmtdesc_t *sdp; dt_ident_t *aid; - sdp = (dtrace_stmtdesc_t *)agg->dtagd_rec[0].dtrd_uarg; + sdp = (dtrace_stmtdesc_t *)(uintptr_t) + agg->dtagd_rec[0].dtrd_uarg; aid = sdp->dtsd_aggdata; agg->dtagd_name = aid->di_name; } diff --git a/usr/src/lib/libdtrace/common/dt_open.c b/usr/src/lib/libdtrace/common/dt_open.c index 3e7910815b..a6970ae8d0 100644 --- a/usr/src/lib/libdtrace/common/dt_open.c +++ b/usr/src/lib/libdtrace/common/dt_open.c @@ -81,12 +81,14 @@ #define DT_VERS_1_0 DT_VERSION_NUMBER(1, 0, 0) #define DT_VERS_1_1 DT_VERSION_NUMBER(1, 1, 0) -#define DT_VERS_LATEST DT_VERS_1_1 -#define DT_VERS_STRING "Sun D 1.1" +#define DT_VERS_1_2 DT_VERSION_NUMBER(1, 2, 0) +#define DT_VERS_LATEST DT_VERS_1_2 +#define DT_VERS_STRING "Sun D 1.2" const dt_version_t _dtrace_versions[] = { DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */ - DT_VERS_1_1, /* D API 1.1.0 Solaris 10 Update 1 */ + DT_VERS_1_1, /* D API 1.1.0 Solaris Express 6/05 */ + DT_VERS_1_2, /* D API 1.2.0 Solaris 10 Update 1 */ 0 }; @@ -315,6 +317,9 @@ static const dt_ident_t _dtrace_globals[] = { &dt_idops_regs, NULL }, { "ustack", DT_IDENT_ACTFUNC, 0, DT_ACT_USTACK, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_func, "stack(...)" }, +{ "ustackdepth", DT_IDENT_SCALAR, 0, DIF_VAR_USTACKDEPTH, + DT_ATTR_STABCMN, DT_VERS_1_2, + &dt_idops_type, "uint32_t" }, { "vtimestamp", DT_IDENT_SCALAR, 0, DIF_VAR_VTIMESTAMP, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "uint64_t" }, diff --git a/usr/src/lib/libdtrace/common/dt_options.c b/usr/src/lib/libdtrace/common/dt_options.c index 14c85eaff7..ae15a45413 100644 --- a/usr/src/lib/libdtrace/common/dt_options.c +++ b/usr/src/lib/libdtrace/common/dt_options.c @@ -744,7 +744,7 @@ dt_options_load(dtrace_hdl_t *dtp) return (dt_set_errno(dtp, errno)); for (i = 0; i < dof->dofh_secnum; i++) { - sec = (dof_sec_t *)((uintptr_t)dof + + sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof + dof->dofh_secoff + i * dof->dofh_secsize); if (sec->dofs_type != DOF_SECT_OPTDESC) @@ -754,8 +754,8 @@ dt_options_load(dtrace_hdl_t *dtp) } for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) { - dof_optdesc_t *opt = (dof_optdesc_t *)((uintptr_t)dof + - sec->dofs_offset + offs); + dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t) + ((uintptr_t)dof + sec->dofs_offset + offs); if (opt->dofo_strtab != DOF_SECIDX_NONE) continue; diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c index 6d794a5025..39c21c9136 100644 --- a/usr/src/uts/common/dtrace/dtrace.c +++ b/usr/src/uts/common/dtrace/dtrace.c @@ -2141,6 +2141,17 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v, } return (mstate->dtms_stackdepth); + case DIF_VAR_USTACKDEPTH: + if (!dtrace_priv_proc(state)) + return (0); + if (!(mstate->dtms_present & DTRACE_MSTATE_USTACKDEPTH)) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); + mstate->dtms_ustackdepth = dtrace_getustackdepth(); + DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); + mstate->dtms_present |= DTRACE_MSTATE_USTACKDEPTH; + } + return (mstate->dtms_ustackdepth); + case DIF_VAR_CALLER: if (!dtrace_priv_kernel(state)) return (0); @@ -2157,7 +2168,7 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v, pc_t caller[2]; dtrace_getpcstack(caller, 2, aframes, - (uint32_t *)mstate->dtms_arg[0]); + (uint32_t *)(uintptr_t)mstate->dtms_arg[0]); mstate->dtms_caller = caller[1]; } else if ((mstate->dtms_caller = dtrace_caller(aframes)) == -1) { @@ -2596,8 +2607,8 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, * relatively short, the complexity of Rabin-Karp or similar * hardly seems merited.) */ - char *addr = (char *)tupregs[0].dttk_value; - char *substr = (char *)tupregs[1].dttk_value; + char *addr = (char *)(uintptr_t)tupregs[0].dttk_value; + char *substr = (char *)(uintptr_t)tupregs[1].dttk_value; uint64_t size = state->dts_options[DTRACEOPT_STRSIZE]; size_t len = dtrace_strlen(addr, size); size_t sublen = dtrace_strlen(substr, size); @@ -3386,6 +3397,7 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, dtrace_key_t tupregs[DIF_DTR_NREGS + 2]; /* +2 for thread and id */ uint64_t regs[DIF_DIR_NREGS]; + uint64_t *tmp; uint8_t cc_n = 0, cc_z = 0, cc_v = 0, cc_c = 0; int64_t cc_r; @@ -3769,7 +3781,8 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, } ASSERT(svar->dtsv_size == NCPU * sizeof (uint64_t)); - regs[rd] = ((uint64_t *)svar->dtsv_data)[CPU->cpu_id]; + tmp = (uint64_t *)(uintptr_t)svar->dtsv_data; + regs[rd] = tmp[CPU->cpu_id]; break; case DIF_OP_STLS: @@ -3806,7 +3819,8 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, } ASSERT(svar->dtsv_size == NCPU * sizeof (uint64_t)); - ((uint64_t *)svar->dtsv_data)[CPU->cpu_id] = regs[rd]; + tmp = (uint64_t *)(uintptr_t)svar->dtsv_data; + tmp[CPU->cpu_id] = regs[rd]; break; case DIF_OP_LDTS: { @@ -6312,8 +6326,8 @@ dtrace_dofprov2hprov(dtrace_helper_provdesc_t *hprov, static void dtrace_helper_provide_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid) { - dof_hdr_t *dof = (dof_hdr_t *)dhp->dofhp_dof; uintptr_t daddr = (uintptr_t)dhp->dofhp_dof; + dof_hdr_t *dof = (dof_hdr_t *)daddr; dof_sec_t *str_sec, *prb_sec, *arg_sec, *off_sec; dof_provider_t *provider; dof_probe_t *probe; @@ -6327,19 +6341,19 @@ dtrace_helper_provide_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid) dtrace_mops_t *mops = &meta->dtm_mops; void *parg; - provider = (dof_provider_t *)(daddr + sec->dofs_offset); - str_sec = (dof_sec_t *)(daddr + dof->dofh_secoff + + provider = (dof_provider_t *)(uintptr_t)(daddr + sec->dofs_offset); + str_sec = (dof_sec_t *)(uintptr_t)(daddr + dof->dofh_secoff + provider->dofpv_strtab * dof->dofh_secsize); - prb_sec = (dof_sec_t *)(daddr + dof->dofh_secoff + + prb_sec = (dof_sec_t *)(uintptr_t)(daddr + dof->dofh_secoff + provider->dofpv_probes * dof->dofh_secsize); - arg_sec = (dof_sec_t *)(daddr + dof->dofh_secoff + + arg_sec = (dof_sec_t *)(uintptr_t)(daddr + dof->dofh_secoff + provider->dofpv_prargs * dof->dofh_secsize); - off_sec = (dof_sec_t *)(daddr + dof->dofh_secoff + + off_sec = (dof_sec_t *)(uintptr_t)(daddr + dof->dofh_secoff + provider->dofpv_proffs * dof->dofh_secsize); - strtab = (char *)(daddr + str_sec->dofs_offset); - off = (uint32_t *)(daddr + off_sec->dofs_offset); - arg = (uint8_t *)(daddr + arg_sec->dofs_offset); + strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset); + off = (uint32_t *)(uintptr_t)(daddr + off_sec->dofs_offset); + arg = (uint8_t *)(uintptr_t)(daddr + arg_sec->dofs_offset); nprobes = prb_sec->dofs_size / prb_sec->dofs_entsize; @@ -6357,8 +6371,8 @@ dtrace_helper_provide_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid) * Create the probes. */ for (i = 0; i < nprobes; i++) { - probe = (dof_probe_t *)(daddr + prb_sec->dofs_offset + - i * prb_sec->dofs_entsize); + probe = (dof_probe_t *)(uintptr_t)(daddr + + prb_sec->dofs_offset + i * prb_sec->dofs_entsize); dhpb.dthpb_mod = dhp->dofhp_mod; dhpb.dthpb_func = strtab + probe->dofpr_func; @@ -6379,15 +6393,15 @@ dtrace_helper_provide_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid) static void dtrace_helper_provide(dof_helper_t *dhp, pid_t pid) { - dof_hdr_t *dof = (dof_hdr_t *)dhp->dofhp_dof; uintptr_t daddr = (uintptr_t)dhp->dofhp_dof; + dof_hdr_t *dof = (dof_hdr_t *)daddr; int i; ASSERT(MUTEX_HELD(&dtrace_meta_lock)); for (i = 0; i < dof->dofh_secnum; i++) { - dof_sec_t *sec = (dof_sec_t *)(daddr + dof->dofh_secoff + - i * dof->dofh_secsize); + dof_sec_t *sec = (dof_sec_t *)(uintptr_t)(daddr + + dof->dofh_secoff + i * dof->dofh_secsize); if (sec->dofs_type != DOF_SECT_PROVIDER) continue; @@ -6399,8 +6413,8 @@ dtrace_helper_provide(dof_helper_t *dhp, pid_t pid) static void dtrace_helper_remove_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid) { - dof_hdr_t *dof = (dof_hdr_t *)dhp->dofhp_dof; uintptr_t daddr = (uintptr_t)dhp->dofhp_dof; + dof_hdr_t *dof = (dof_hdr_t *)daddr; dof_sec_t *str_sec; dof_provider_t *provider; char *strtab; @@ -6408,11 +6422,11 @@ dtrace_helper_remove_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid) dtrace_meta_t *meta = dtrace_meta_pid; dtrace_mops_t *mops = &meta->dtm_mops; - provider = (dof_provider_t *)(daddr + sec->dofs_offset); - str_sec = (dof_sec_t *)(daddr + dof->dofh_secoff + + provider = (dof_provider_t *)(uintptr_t)(daddr + sec->dofs_offset); + str_sec = (dof_sec_t *)(uintptr_t)(daddr + dof->dofh_secoff + provider->dofpv_strtab * dof->dofh_secsize); - strtab = (char *)(daddr + str_sec->dofs_offset); + strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset); /* * Create the provider. @@ -6427,15 +6441,15 @@ dtrace_helper_remove_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid) static void dtrace_helper_remove(dof_helper_t *dhp, pid_t pid) { - dof_hdr_t *dof = (dof_hdr_t *)dhp->dofhp_dof; uintptr_t daddr = (uintptr_t)dhp->dofhp_dof; + dof_hdr_t *dof = (dof_hdr_t *)daddr; int i; ASSERT(MUTEX_HELD(&dtrace_meta_lock)); for (i = 0; i < dof->dofh_secnum; i++) { - dof_sec_t *sec = (dof_sec_t *)(daddr + dof->dofh_secoff + - i * dof->dofh_secsize); + dof_sec_t *sec = (dof_sec_t *)(uintptr_t)(daddr + + dof->dofh_secoff + i * dof->dofh_secsize); if (sec->dofs_type != DOF_SECT_PROVIDER) continue; @@ -9769,7 +9783,7 @@ dtrace_dof_destroy(dof_hdr_t *dof) static dof_sec_t * dtrace_dof_sect(dof_hdr_t *dof, uint32_t type, dof_secidx_t i) { - dof_sec_t *sec = (dof_sec_t *) + dof_sec_t *sec = (dof_sec_t *)(uintptr_t) ((uintptr_t)dof + dof->dofh_secoff + i * dof->dofh_secsize); if (i >= dof->dofh_secnum) { @@ -9913,7 +9927,7 @@ dtrace_dof_difo(dof_hdr_t *dof, dof_sec_t *sec, dtrace_vstate_t *vstate, return (NULL); } - dofd = (dof_difohdr_t *)(daddr + sec->dofs_offset); + dofd = (dof_difohdr_t *)(uintptr_t)(daddr + sec->dofs_offset); n = (sec->dofs_size - sizeof (*dofd)) / sizeof (dof_secidx_t) + 1; dp = kmem_zalloc(sizeof (dtrace_difo_t), KM_SLEEP); @@ -10246,7 +10260,8 @@ static int dtrace_dof_relocate(dof_hdr_t *dof, dof_sec_t *sec, uint64_t ubase) { uintptr_t daddr = (uintptr_t)dof; - dof_relohdr_t *dofr = (dof_relohdr_t *)(daddr + sec->dofs_offset); + dof_relohdr_t *dofr = + (dof_relohdr_t *)(uintptr_t)(daddr + sec->dofs_offset); dof_sec_t *ss, *rs, *ts; dof_relodesc_t *r; uint_t i, n; @@ -10270,7 +10285,7 @@ dtrace_dof_relocate(dof_hdr_t *dof, dof_sec_t *sec, uint64_t ubase) return (-1); } - r = (dof_relodesc_t *)(daddr + rs->dofs_offset); + r = (dof_relodesc_t *)(uintptr_t)(daddr + rs->dofs_offset); n = rs->dofs_size / rs->dofs_entsize; for (i = 0; i < n; i++) { @@ -11589,7 +11604,7 @@ dtrace_helper_trace(dtrace_helper_action_t *helper, dtrace_vstate_t *vstate, ASSERT(svar->dtsv_size >= NCPU * sizeof (uint64_t)); ent->dtht_locals[i] = - ((uint64_t *)svar->dtsv_data)[CPU->cpu_id]; + ((uint64_t *)(uintptr_t)svar->dtsv_data)[CPU->cpu_id]; } } @@ -11939,8 +11954,10 @@ dtrace_helper_provider_remove(dtrace_helper_provider_t *hprov) mutex_enter(&dtrace_lock); if (--hprov->dthp_ref == 0) { + dof_hdr_t *dof; mutex_exit(&dtrace_lock); - dtrace_dof_destroy((dof_hdr_t *)hprov->dthp_prov.dofhp_dof); + dof = (dof_hdr_t *)(uintptr_t)hprov->dthp_prov.dofhp_dof; + dtrace_dof_destroy(dof); kmem_free(hprov, sizeof (dtrace_helper_provider_t)); } else { mutex_exit(&dtrace_lock); @@ -11967,7 +11984,7 @@ dtrace_helper_provider_validate(dof_hdr_t *dof, dof_sec_t *sec) return (-1); } - provider = (dof_provider_t *)(daddr + sec->dofs_offset); + provider = (dof_provider_t *)(uintptr_t)(daddr + sec->dofs_offset); str_sec = dtrace_dof_sect(dof, DOF_SECT_STRTAB, provider->dofpv_strtab); prb_sec = dtrace_dof_sect(dof, DOF_SECT_PROBES, provider->dofpv_probes); arg_sec = dtrace_dof_sect(dof, DOF_SECT_PRARGS, provider->dofpv_prargs); @@ -11977,7 +11994,7 @@ dtrace_helper_provider_validate(dof_hdr_t *dof, dof_sec_t *sec) arg_sec == NULL || off_sec == NULL) return (-1); - strtab = (char *)(daddr + str_sec->dofs_offset); + strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset); if (provider->dofpv_name >= str_sec->dofs_size || strlen(strtab + provider->dofpv_name) >= DTRACE_PROVNAMELEN) { @@ -12011,7 +12028,7 @@ dtrace_helper_provider_validate(dof_hdr_t *dof, dof_sec_t *sec) return (-1); } - arg = (uint8_t *)(daddr + arg_sec->dofs_offset); + arg = (uint8_t *)(uintptr_t)(daddr + arg_sec->dofs_offset); nprobes = prb_sec->dofs_size / prb_sec->dofs_entsize; @@ -12019,8 +12036,8 @@ dtrace_helper_provider_validate(dof_hdr_t *dof, dof_sec_t *sec) * Take a pass through the probes to check for errors. */ for (j = 0; j < nprobes; j++) { - probe = (dof_probe_t *)(daddr + prb_sec->dofs_offset + - j * prb_sec->dofs_entsize); + probe = (dof_probe_t *)(uintptr_t)(daddr + + prb_sec->dofs_offset + j * prb_sec->dofs_entsize); if (probe->dofpr_func >= str_sec->dofs_size) { dtrace_dof_error(dof, "invalid function name"); @@ -12168,7 +12185,7 @@ dtrace_helper_slurp(dof_hdr_t *dof, dof_helper_t *dhp) * Look for helper probes. */ for (i = 0; i < dof->dofh_secnum; i++) { - dof_sec_t *sec = (dof_sec_t *)(daddr + + dof_sec_t *sec = (dof_sec_t *)(uintptr_t)(daddr + dof->dofh_secoff + i * dof->dofh_secsize); if (sec->dofs_type != DOF_SECT_PROVIDER) @@ -12180,7 +12197,7 @@ dtrace_helper_slurp(dof_hdr_t *dof, dof_helper_t *dhp) } } - dhp->dofhp_dof = (uint64_t)dof; + dhp->dofhp_dof = (uint64_t)(uintptr_t)dof; if (err == 0 && dtrace_helper_provider_add(dhp) == 0) destroy = 0; else diff --git a/usr/src/uts/common/dtrace/sdt_subr.c b/usr/src/uts/common/dtrace/sdt_subr.c index 6ae5ccadda..7b31eb9e6c 100644 --- a/usr/src/uts/common/dtrace/sdt_subr.c +++ b/usr/src/uts/common/dtrace/sdt_subr.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -103,6 +103,9 @@ sdt_argdesc_t sdt_args[] = { { "sched", "schedctl-nopreempt", 2, 1, "int" }, { "sched", "schedctl-preempt", 0, 0, "kthread_t *", "lwpsinfo_t *" }, { "sched", "schedctl-preempt", 1, 0, "kthread_t *", "psinfo_t *" }, + { "sched", "schedctl-yield", 0, 0, "int" }, + { "sched", "surrender", 0, 0, "kthread_t *", "lwpsinfo_t *" }, + { "sched", "surrender", 1, 0, "kthread_t *", "psinfo_t *" }, { "proc", "create", 0, 0, "proc_t *", "psinfo_t *" }, { "proc", "exec", 0, 0, "string" }, { "proc", "exec-failure", 0, 0, "int" }, diff --git a/usr/src/uts/common/io/avintr.c b/usr/src/uts/common/io/avintr.c index 82d789f519..332acaffea 100644 --- a/usr/src/uts/common/io/avintr.c +++ b/usr/src/uts/common/io/avintr.c @@ -108,6 +108,7 @@ add_nmintr(int lvl, avfunc nmintr, char *name, caddr_t arg) mem->av_intarg2 = NULL; mem->av_intr_id = NULL; mem->av_prilevel = lvl; + mem->av_dip = NULL; mem->av_link = NULL; mutex_enter(&av_lock); @@ -296,6 +297,7 @@ insert_av(void *intr_id, struct av_head *vectp, avfunc f, caddr_t arg1, p->av_intarg2 = arg2; p->av_intr_id = intr_id; p->av_prilevel = pri_level; + p->av_dip = dip; if (pri_level > (int)vectp->avh_hi_pri) { vectp->avh_hi_pri = (ushort_t)pri_level; } @@ -437,11 +439,12 @@ remove_av(void *intr_id, struct av_head *vectp, avfunc f, int pri_level, target->av_vector = NULL; wait_till_seen(ipl); if (endp != target) { /* vector to be removed is not last in chain */ + target->av_vector = endp->av_vector; target->av_intarg1 = endp->av_intarg1; target->av_intarg2 = endp->av_intarg2; - target->av_prilevel = endp->av_prilevel; target->av_intr_id = endp->av_intr_id; - target->av_vector = endp->av_vector; + target->av_prilevel = endp->av_prilevel; + target->av_dip = endp->av_dip; /* * We have a hole here where the routine corresponding to * endp may not get called. Do a wait_till_seen to take care diff --git a/usr/src/uts/common/os/modctl.c b/usr/src/uts/common/os/modctl.c index 7538fe4d01..84aa333ce7 100644 --- a/usr/src/uts/common/os/modctl.c +++ b/usr/src/uts/common/os/modctl.c @@ -365,6 +365,7 @@ modctl_modload(int use_path, char *filename, int *rvp) modp->mod_loadflags |= MOD_NOAUTOUNLOAD; modid = modp->mod_id; mod_release_mod(modp); + CPU_STATS_ADDQ(CPU, sys, modload, 1); if (rvp != NULL && copyout(&modid, rvp, sizeof (modid)) != 0) retval = EFAULT; out: @@ -2968,8 +2969,10 @@ mod_uninstall_all(void) continue; } - if (moduninstall(mp) == 0) + if (moduninstall(mp) == 0) { mod_unload(mp); + CPU_STATS_ADDQ(CPU, sys, modunload, 1); + } mod_release_mod(mp); } @@ -3312,9 +3315,10 @@ mod_remove_by_name(char *name) return (0); } - if ((retval = moduninstall(mp)) == 0) + if ((retval = moduninstall(mp)) == 0) { mod_unload(mp); - else if (retval == EALREADY) + CPU_STATS_ADDQ(CPU, sys, modunload, 1); + } else if (retval == EALREADY) retval = 0; /* already unloaded, not an error */ mod_release_mod(mp); return (retval); diff --git a/usr/src/uts/common/sys/dtrace.h b/usr/src/uts/common/sys/dtrace.h index 3dcf21ea97..f10c15343e 100644 --- a/usr/src/uts/common/sys/dtrace.h +++ b/usr/src/uts/common/sys/dtrace.h @@ -227,6 +227,7 @@ typedef enum dtrace_probespec { #define DIF_VAR_EXECNAME 0x0118 /* name of executable */ #define DIF_VAR_ZONENAME 0x0119 /* zone name associated with process */ #define DIF_VAR_WALLTIMESTAMP 0x011a /* wall-clock timestamp */ +#define DIF_VAR_USTACKDEPTH 0x011b /* user-land stack depth */ #define DIF_SUBR_RAND 0 #define DIF_SUBR_MUTEX_OWNED 1 diff --git a/usr/src/uts/common/sys/dtrace_impl.h b/usr/src/uts/common/sys/dtrace_impl.h index 60b734a6fe..974fb5369a 100644 --- a/usr/src/uts/common/sys/dtrace_impl.h +++ b/usr/src/uts/common/sys/dtrace_impl.h @@ -889,6 +889,7 @@ typedef struct dtrace_vstate { #define DTRACE_MSTATE_IPL 0x00000040 #define DTRACE_MSTATE_FLTOFFS 0x00000080 #define DTRACE_MSTATE_WALLTIMESTAMP 0x00000100 +#define DTRACE_MSTATE_USTACKDEPTH 0x00000200 typedef struct dtrace_mstate { uintptr_t dtms_scratch_base; /* base of scratch space */ @@ -900,6 +901,7 @@ typedef struct dtrace_mstate { uint64_t dtms_timestamp; /* cached timestamp */ hrtime_t dtms_walltimestamp; /* cached wall timestamp */ int dtms_stackdepth; /* cached stackdepth */ + int dtms_ustackdepth; /* cached ustackdepth */ struct dtrace_probe *dtms_probe; /* current probe */ uintptr_t dtms_caller; /* cached caller */ int dtms_ipl; /* cached interrupt pri lev */ @@ -1218,6 +1220,7 @@ extern ulong_t dtrace_getreg(struct regs *, uint_t); extern int dtrace_getstackdepth(int); extern void dtrace_getupcstack(uint64_t *, int); extern void dtrace_getufpstack(uint64_t *, uint64_t *, int); +extern int dtrace_getustackdepth(void); extern uintptr_t dtrace_fulword(void *); extern uint8_t dtrace_fuword8(void *); extern uint16_t dtrace_fuword16(void *); diff --git a/usr/src/uts/i86pc/ml/locore.s b/usr/src/uts/i86pc/ml/locore.s index 753d33d8ac..2649a6df7e 100644 --- a/usr/src/uts/i86pc/ml/locore.s +++ b/usr/src/uts/i86pc/ml/locore.s @@ -1231,7 +1231,7 @@ cmntrap() leaq cpu_core(%rip), %r8 addq %r8, %rax movw CPUC_DTRACE_FLAGS(%rax), %cx - andw $CPU_DTRACE_NOFAULT, %cx + testw $CPU_DTRACE_NOFAULT, %cx jnz .dtrace_induced TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) /* Uses labels 8 and 9 */ @@ -1360,7 +1360,7 @@ cmntrap() shll $CPU_CORE_SHIFT, %eax addl $cpu_core, %eax movw CPUC_DTRACE_FLAGS(%eax), %cx - andw $CPU_DTRACE_NOFAULT, %cx + testw $CPU_DTRACE_NOFAULT, %cx jnz 0f /* diff --git a/usr/src/uts/intel/dtrace/dtrace_isa.c b/usr/src/uts/intel/dtrace/dtrace_isa.c index 04a1279829..9177d135fd 100644 --- a/usr/src/uts/intel/dtrace/dtrace_isa.c +++ b/usr/src/uts/intel/dtrace/dtrace_isa.c @@ -117,35 +117,19 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, } } -void -dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) +static int +dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc, + uintptr_t sp) { klwp_t *lwp = ttolwp(curthread); - proc_t *p = ttoproc(curthread); - struct regs *rp; - uintptr_t pc, sp, oldcontext; - volatile uint8_t *flags = - (volatile uint8_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags; + proc_t *p = curproc; + uintptr_t oldcontext = lwp->lwp_oldcontext; + volatile uint16_t *flags = + (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags; size_t s1, s2; + int ret = 0; - if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL) - return; - - if (*flags & CPU_DTRACE_FAULT) - return; - - if (pcstack_limit <= 0) - return; - - *pcstack++ = (uint64_t)p->p_pid; - pcstack_limit--; - - if (pcstack_limit <= 0) - return; - - pc = rp->r_pc; - sp = rp->r_fp; - oldcontext = lwp->lwp_oldcontext; + ASSERT(pcstack == NULL || pcstack_limit > 0); if (p->p_model == DATAMODEL_NATIVE) { s1 = sizeof (struct frame) + 2 * sizeof (long); @@ -155,23 +139,14 @@ dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) s2 = s1 + sizeof (siginfo32_t); } - if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { - *pcstack++ = (uint64_t)pc; - pcstack_limit--; - if (pcstack_limit <= 0) - return; - - if (p->p_model == DATAMODEL_NATIVE) - pc = dtrace_fulword((void *)rp->r_sp); - else - pc = dtrace_fuword32((void *)rp->r_sp); - } - while (pc != 0 && sp != 0) { - *pcstack++ = (uint64_t)pc; - pcstack_limit--; - if (pcstack_limit <= 0) - break; + ret++; + if (pcstack != NULL) { + *pcstack++ = (uint64_t)pc; + pcstack_limit--; + if (pcstack_limit <= 0) + break; + } if (oldcontext == sp + s1 || oldcontext == sp + s2) { if (p->p_model == DATAMODEL_NATIVE) { @@ -216,20 +191,103 @@ dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) } } + return (ret); +} + +void +dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) +{ + klwp_t *lwp = ttolwp(curthread); + proc_t *p = curproc; + struct regs *rp; + uintptr_t pc, sp; + volatile uint16_t *flags = + (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags; + int n; + + if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL) + return; + + if (*flags & CPU_DTRACE_FAULT) + return; + + if (pcstack_limit <= 0) + return; + + *pcstack++ = (uint64_t)p->p_pid; + pcstack_limit--; + + if (pcstack_limit <= 0) + return; + + pc = rp->r_pc; + sp = rp->r_fp; + + if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { + *pcstack++ = (uint64_t)pc; + pcstack_limit--; + if (pcstack_limit <= 0) + return; + + if (p->p_model == DATAMODEL_NATIVE) + pc = dtrace_fulword((void *)rp->r_sp); + else + pc = dtrace_fuword32((void *)rp->r_sp); + } + + n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp); + ASSERT(n >= 0); + ASSERT(n <= pcstack_limit); + + pcstack += n; + pcstack_limit -= n; + while (pcstack_limit-- > 0) *pcstack++ = NULL; } +int +dtrace_getustackdepth(void) +{ + klwp_t *lwp = ttolwp(curthread); + proc_t *p = curproc; + struct regs *rp; + uintptr_t pc, sp; + int n = 0; + + if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL) + return (0); + + if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) + return (-1); + + pc = rp->r_pc; + sp = rp->r_fp; + + if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { + n++; + + if (p->p_model == DATAMODEL_NATIVE) + pc = dtrace_fulword((void *)rp->r_sp); + else + pc = dtrace_fuword32((void *)rp->r_sp); + } + + n += dtrace_getustack_common(NULL, 0, pc, sp); + + return (n); +} + /*ARGSUSED*/ void dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) { klwp_t *lwp = ttolwp(curthread); - proc_t *p = ttoproc(curthread); + proc_t *p = curproc; struct regs *rp; uintptr_t pc, sp, oldcontext; - volatile uint8_t *flags = - (volatile uint8_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags; + volatile uint16_t *flags = + (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags; size_t s1, s2; if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL) diff --git a/usr/src/uts/sparc/dtrace/dtrace_asm.s b/usr/src/uts/sparc/dtrace/dtrace_asm.s index 62c8662548..a0cbd8f50e 100644 --- a/usr/src/uts/sparc/dtrace/dtrace_asm.s +++ b/usr/src/uts/sparc/dtrace/dtrace_asm.s @@ -555,7 +555,7 @@ dtrace_getupcstack_top(uint64_t *pcstack, int pcstack_limit, uintptr_t *sp) rdpr %cwp, %g4 ! remember our window so we can return rdpr %canrestore, %g2 ! compute the first non-user window - subcc %g4, %g2, %g2 ! current = %cwp - %otherwin + subcc %g4, %g2, %g2 ! current = %cwp - %canrestore bge,pt %xcc, 1f ! good to go if current is >= 0 mov %g5, %o0 ! we need to return the count @@ -592,6 +592,47 @@ dtrace_getupcstack_top(uint64_t *pcstack, int pcstack_limit, uintptr_t *sp) #endif +#if defined(lint) + +/*ARGSUSED*/ +int +dtrace_getustackdepth_top(uintptr_t *sp) +{ return (0); } + +#else + + ENTRY(dtrace_getustackdepth_top) + mov %o0, %o2 + rdpr %otherwin, %o0 + + brlez,a,pn %o0, 2f ! return 0 if there are no user wins + clr %o0 + + rdpr %cwp, %g4 ! remember our window so we can return + rdpr %canrestore, %g2 ! compute the first user window + sub %g4, %g2, %g2 ! current = %cwp - %canrestore - + subcc %g2, %o0, %g2 ! %otherwin + + bge,pt %xcc, 1f ! normalize the window if necessary + sethi %hi(nwin_minus_one), %g3 + ld [%g3 + %lo(nwin_minus_one)], %g3 + add %g2, %g3, %g2 + add %g2, 1, %g2 + +1: + wrpr %g2, %cwp ! change to the first user window + mov %i6, %g6 ! stash the frame pointer + wrpr %g4, %cwp ! change back to the original window + + stn %g6, [%o2] ! return the frame pointer + +2: + retl + nop + SET_SIZE(dtrace_getustackdepth_top) + +#endif + #if defined(lint) || defined(__lint) /* ARGSUSED */ diff --git a/usr/src/uts/sparc/dtrace/dtrace_isa.c b/usr/src/uts/sparc/dtrace/dtrace_isa.c index 615738c8ea..4c62ab0ec0 100644 --- a/usr/src/uts/sparc/dtrace/dtrace_isa.c +++ b/usr/src/uts/sparc/dtrace/dtrace_isa.c @@ -34,6 +34,7 @@ #include #include #include +#include #define DTRACE_FMT3OP3_MASK 0x81000000 #define DTRACE_FMT3OP3 0x80000000 @@ -55,6 +56,7 @@ #define DTRACE_JMPL 0x81c00000 extern int dtrace_getupcstack_top(uint64_t *, int, uintptr_t *); +extern int dtrace_getustackdepth_top(uintptr_t *); extern ulong_t dtrace_getreg_win(uint_t, uint_t); extern void dtrace_putreg_win(uint_t, ulong_t); extern int dtrace_fish(int, int, uintptr_t *); @@ -74,8 +76,8 @@ extern int dtrace_fish(int, int, uintptr_t *); * deliver as correct a stack as possible. Details on the issues * surrounding stack correctness are found below. * - * (c) dtrace_getpcstack() _always_ fills in pstack_limit pc_t's -- filling - * in the difference between the stack depth and pstack_limit with NULLs. + * (c) dtrace_getpcstack() _always_ fills in pcstack_limit pc_t's -- filling + * in the difference between the stack depth and pcstack_limit with NULLs. * Due to this behavior dtrace_getpcstack() returns void. * * (d) dtrace_getpcstack() takes a third parameter, aframes, that @@ -306,16 +308,77 @@ leaf: } } +static int +dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t sp) +{ + proc_t *p = curproc; + int ret = 0; + + ASSERT(pcstack == NULL || pcstack_limit > 0); + + if (p->p_model == DATAMODEL_NATIVE) { + for (;;) { + struct frame *fr = (struct frame *)(sp + STACK_BIAS); + uintptr_t pc; + + if (sp == 0 || fr == NULL || + !IS_P2ALIGNED((uintptr_t)fr, STACK_ALIGN)) + break; + + pc = dtrace_fulword(&fr->fr_savpc); + sp = dtrace_fulword(&fr->fr_savfp); + + if (pc == 0) + break; + + ret++; + + if (pcstack != NULL) { + *pcstack++ = pc; + pcstack_limit--; + if (pcstack_limit == 0) + break; + } + } + } else { + for (;;) { + struct frame32 *fr = (struct frame32 *)sp; + uint32_t pc; + + if (sp == 0 || + !IS_P2ALIGNED((uintptr_t)fr, STACK_ALIGN32)) + break; + + pc = dtrace_fuword32(&fr->fr_savpc); + sp = dtrace_fuword32(&fr->fr_savfp); + + if (pc == 0) + break; + + ret++; + + if (pcstack != NULL) { + *pcstack++ = pc; + pcstack_limit--; + if (pcstack_limit == 0) + break; + } + } + } + + return (ret); +} + void dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) { klwp_t *lwp = ttolwp(curthread); - proc_t *p = ttoproc(curthread); + proc_t *p = curproc; struct regs *rp; uintptr_t sp; int n; - if (lwp == NULL || p == NULL || lwp->lwp_regs == NULL) + if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL) return; if (pcstack_limit <= 0) @@ -327,7 +390,6 @@ dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) if (pcstack_limit <= 0) return; - rp = lwp->lwp_regs; *pcstack++ = (uint64_t)rp->r_pc; pcstack_limit--; @@ -349,46 +411,44 @@ dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) pcstack += n; pcstack_limit -= n; + if (pcstack_limit <= 0) + return; - if (p->p_model == DATAMODEL_NATIVE) { - while (pcstack_limit > 0) { - struct frame *fr = (struct frame *)(sp + STACK_BIAS); - uintptr_t pc; + n = dtrace_getustack_common(pcstack, pcstack_limit, sp); + ASSERT(n >= 0); + ASSERT(n <= pcstack_limit); - if (sp == 0 || fr == NULL || - ((uintptr_t)&fr->fr_savpc & 3) != 0 || - ((uintptr_t)&fr->fr_savfp & 3) != 0) - break; + pcstack += n; + pcstack_limit -= n; - pc = dtrace_fulword(&fr->fr_savpc); - sp = dtrace_fulword(&fr->fr_savfp); + while (pcstack_limit-- > 0) + *pcstack++ = NULL; +} - if (pc == 0) - break; +int +dtrace_getustackdepth(void) +{ + klwp_t *lwp = ttolwp(curthread); + proc_t *p = curproc; + struct regs *rp; + uintptr_t sp; + int n = 1; - *pcstack++ = pc; - pcstack_limit--; - } - } else { - while (pcstack_limit > 0) { - struct frame32 *fr = (struct frame32 *)sp; - uint32_t pc; + if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL) + return (0); - if (sp == 0 || - ((uintptr_t)&fr->fr_savpc & 3) != 0 || - ((uintptr_t)&fr->fr_savfp & 3) != 0) - break; + if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) + return (-1); - pc = dtrace_fuword32(&fr->fr_savpc); - sp = dtrace_fuword32(&fr->fr_savfp); + if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) + n++; - *pcstack++ = pc; - pcstack_limit--; - } - } + sp = rp->r_sp; - while (pcstack_limit-- > 0) - *pcstack++ = NULL; + n += dtrace_getustackdepth_top(&sp); + n += dtrace_getustack_common(NULL, 0, sp); + + return (n); } void @@ -399,7 +459,7 @@ dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) struct regs *rp; uintptr_t sp; - if (lwp == NULL || p == NULL || lwp->lwp_regs == NULL) + if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL) return; if (pcstack_limit <= 0) @@ -411,8 +471,6 @@ dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) if (pcstack_limit <= 0) return; - rp = lwp->lwp_regs; - if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { *fpstack++ = 0; *pcstack++ = (uint64_t)rp->r_pc; @@ -469,6 +527,9 @@ dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) pc = dtrace_fuword32(&fr->fr_savpc); sp = dtrace_fuword32(&fr->fr_savfp); + if (pc == 0) + break; + *fpstack++ = sp; *pcstack++ = pc; pcstack_limit--; -- cgit v1.2.3