summaryrefslogtreecommitdiff
path: root/usr/src
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 /usr/src
parentb52a2671b74561fd8e88284bba4b0b834687951e (diff)
downloadillumos-gate-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
Diffstat (limited to 'usr/src')
-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--;