summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorahl <none@none>2005-07-20 01:15:45 -0700
committerahl <none@none>2005-07-20 01:15:45 -0700
commit0b38a8bdfd75ac6144f9d462bb38d0c1b3f0ca50 (patch)
treeb1914d8b26048f30b052b54b9625a9f6f8d153ca
parentb52a2671b74561fd8e88284bba4b0b834687951e (diff)
downloadillumos-joyent-0b38a8bdfd75ac6144f9d462bb38d0c1b3f0ca50.tar.gz
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
-rw-r--r--usr/src/cmd/dtrace/dtrace.c30
-rw-r--r--usr/src/cmd/intrstat/intrstat.c3
-rw-r--r--usr/src/cmd/plockstat/plockstat.c2
-rw-r--r--usr/src/lib/libdtrace/common/dt_link.c56
-rw-r--r--usr/src/lib/libdtrace/common/dt_map.c5
-rw-r--r--usr/src/lib/libdtrace/common/dt_open.c11
-rw-r--r--usr/src/lib/libdtrace/common/dt_options.c6
-rw-r--r--usr/src/uts/common/dtrace/dtrace.c95
-rw-r--r--usr/src/uts/common/dtrace/sdt_subr.c5
-rw-r--r--usr/src/uts/common/io/avintr.c7
-rw-r--r--usr/src/uts/common/os/modctl.c10
-rw-r--r--usr/src/uts/common/sys/dtrace.h1
-rw-r--r--usr/src/uts/common/sys/dtrace_impl.h3
-rw-r--r--usr/src/uts/i86pc/ml/locore.s4
-rw-r--r--usr/src/uts/intel/dtrace/dtrace_isa.c146
-rw-r--r--usr/src/uts/sparc/dtrace/dtrace_asm.s43
-rw-r--r--usr/src/uts/sparc/dtrace/dtrace_isa.c139
17 files changed, 411 insertions, 155 deletions
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 <sys/machpcb.h>
#include <sys/procfs_isa.h>
#include <sys/cmn_err.h>
+#include <sys/sysmacros.h>
#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--;