dtrace_providerdesc_t pvd;
dtrace_provider_t *pvp;
-printk(KERN_INFO "IOCTL provider\n");
if (copy_from_user(&pvd, argp, sizeof(pvd)) != 0)
return -EFAULT;
uint8_t *dest;
int nrecs;
-printk(KERN_INFO "IOCTL eprobe\n");
if (copy_from_user(&epdesc, argp, sizeof(epdesc)) != 0)
return -EFAULT;
mutex_lock(&dtrace_lock);
-printk(KERN_INFO " Looking for ECB %ld\n", epdesc.dtepd_epid);
if ((ecb = dtrace_epid2ecb(state, epdesc.dtepd_epid)) == NULL) {
mutex_unlock(&dtrace_lock);
-printk(KERN_INFO " ECB not found\n");
return -EINVAL;
}
if (ecb->dte_probe == NULL) {
mutex_unlock(&dtrace_lock);
-printk(KERN_INFO " ECB has no probe\n");
return -EINVAL;
}
-printk(KERN_INFO " ECB has probe %ld\n", ecb->dte_probe->dtpr_id);
epdesc.dtepd_probeid = ecb->dte_probe->dtpr_id;
epdesc.dtepd_uarg = ecb->dte_uarg;
epdesc.dtepd_size = ecb->dte_size;
size_t size;
uint8_t *dest;
-printk(KERN_INFO "IOCTL aggdesc\n");
if (copy_from_user(&aggdesc, argp, sizeof(aggdesc)) != 0)
return -EFAULT;
mutex_unlock(&dtrace_lock);
return -EINVAL;
}
-printk(KERN_INFO "IOCTL aggdesc: Found agg %lu, ECB %lu\n", agg->dtag_id, agg->dtag_ecb->dte_epid);
aggdesc.dtagd_epid = agg->dtag_ecb->dte_epid;
int err = 0;
int rv;
-printk(KERN_INFO "IOCTL enable\n");
rv = 0;
/*
dtrace_probedesc_t *create = &desc.dtrpd_create;
int err;
-printk(KERN_INFO "IOCTL replicate\n");
if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
return -EFAULT;
uint32_t priv;
uid_t uid;
-printk(KERN_INFO "IOCTL %s\n", cmd == DTRACEIOC_PROBEMATCH ? "probematch" : "probes");
if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
return -EFAULT;
dtrace_probekey(&desc, &pkey);
pkey.dtpk_id = DTRACE_IDNONE;
}
-printk(KERN_INFO "IOCTL %s: id[%d] p[%s] m[%s] f[%s] n[%s]\n", cmd == DTRACEIOC_PROBEMATCH ? "probematch" : "probes", desc.dtpd_id, desc.dtpd_provider, desc.dtpd_mod, desc.dtpd_func, desc.dtpd_name);
dtrace_cred2priv(file->f_cred, &priv, &uid);
dtrace_probe_description(probe, &desc);
mutex_unlock(&dtrace_lock);
-printk(KERN_INFO "Returning probe [%s]\n", desc.dtpd_name);
if (copy_to_user(argp, &desc, sizeof(desc)) != 0)
return -EFAULT;
dtrace_probe_t *probe;
dtrace_provider_t *prov;
-printk(KERN_INFO "IOCTL probearg\n");
if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
return -EFAULT;
case DTRACEIOC_GO: {
processorid_t cpuid;
-printk(KERN_INFO "IOCTL go\n");
rval = dtrace_state_go(state, &cpuid);
if (rval != 0)
case DTRACEIOC_STOP: {
processorid_t cpuid;
-printk(KERN_INFO "IOCTL stop\n");
mutex_lock(&dtrace_lock);
rval = dtrace_state_stop(state, &cpuid);
mutex_unlock(&dtrace_lock);
dof_hdr_t hdr, *dof;
uint64_t len;
-printk(KERN_INFO "IOCTL dofget\n");
if (copy_from_user(&hdr, argp, sizeof(hdr)) != 0)
return -EFAULT;
caddr_t cached;
dtrace_buffer_t *buf;
-printk(KERN_INFO "IOCTL %s\n", cmd == DTRACEIOC_AGGSNAP ? "aggsnap" : "bufsnap");
if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
return -EFAULT;
case DTRACEIOC_CONF: {
dtrace_conf_t conf;
-printk(KERN_INFO "IOCTL conf\n");
memset(&conf, 0, sizeof(conf));
conf.dtc_difversion = DIF_VERSION;
conf.dtc_difintregs = DIF_DIR_NREGS;
int i, j;
uint64_t nerrs;
-printk(KERN_INFO "IOCTL status\n");
/*
* See the comment in dtrace_state_deadman() for the reason
* for setting dts_laststatus to INT64_MAX before setting
char *str;
int len;
-printk(KERN_INFO "IOCTL format\n");
if (copy_from_user(&fmt, argp, sizeof (fmt)) != 0)
return -EFAULT;
}
agg->dtag_id = aggid;
-printk(KERN_INFO "New aggregation: %u (for ECB %u)\n", aggid, ecb->dte_epid);
frec = &agg->dtag_first->dta_rec;
if (frec->dtrd_alignment < sizeof(dtrace_aggid_t))
state->dts_ecbs[(ecb->dte_epid = epid) - 1] = ecb;
-printk(KERN_INFO "ecb_add: ECB %u for probe ID %u\n", epid, probe ? probe->dtpr_id : 0xffff);
return ecb;
}
#endif
int nreg = sizeof(regmap) / sizeof(regmap[0]) - 1;
-printk(KERN_INFO "getarg(%d, %d) -> nreg = %d\n", arg, aframes, nreg);
for (i = 1; i <= aframes; i++) {
fp = fp->fr_savfp;
arg++;
#ifndef __i386__
-printk(KERN_INFO "getarg(%d, %d) [!i386]-> nreg = %d\n", arg, aframes, nreg);
if (arg <= nreg) {
/*
* This should not happen. If the argument was passed in a
if (provider != dtrace_provider)
mutex_unlock(&dtrace_lock);
-printk(KERN_INFO "probe_create(%s, %s, %s, %s) -> %d\n", provider->dtpv_name, mod, func, name, id);
return id;
}
EXPORT_SYMBOL(dtrace_probe_create);
dtrace_probekey(desc, &pkey);
dtrace_cred2priv(enab->dten_vstate->dtvs_state->dts_cred.dcr_cred,
&priv, &uid);
-printk(KERN_INFO "probe_enable(%d, %s, %s, %s, %s)\n", pkey.dtpk_id, pkey.dtpk_prov, pkey.dtpk_mod, pkey.dtpk_func, pkey.dtpk_name);
+
return dtrace_match(&pkey, priv, uid, dtrace_ecb_create_enable, enab);
}
NULL
};
-printk(KERN_INFO "unregister(%p)\n", old);
if (old->dtpv_pops.dtps_enable ==
(int (*)(void *, dtrace_id_t, void *))dtrace_enable_nullop) {
/*
* are anonymous probes that are still enabled, we refuse to deregister
* providers, unless the provider has been invalidated explicitly.
*/
-printk(KERN_INFO "unregister(%p) %d opens\n", old, dtrace_opens);
if (!old->dtpv_defunct &&
(dtrace_opens || (dtrace_anon.dta_state != NULL &&
dtrace_anon.dta_state->dts_necbs > 0))) {
*/
st.prov = old;
err = dtrace_probe_for_each(dtrace_unregister_check, &st);
-printk(KERN_INFO "unregister(%p) check -> %d\n", old, err);
if (err < 0) {
if (!self) {
mutex_unlock(&dtrace_lock);
* We chain all the probes together for further processing.
*/
dtrace_probe_for_each(dtrace_unregister_probe, &st);
-printk(KERN_INFO "unregister(%p) unregister_probe done\n", old);
/*
* The probes associated with the provider have been removed. Ensure
st.first = probe->dtpr_nextmod;
-printk(KERN_INFO "unregister(%p) Destroying probe %d\n", old, probe_id);
old->dtpv_pops.dtps_destroy(old->dtpv_arg, probe_id,
probe->dtpr_arg);
if (which == 0)
return;
-printk(KERN_INFO "spec-commit: CPU#%d, which %d\n", cpu, which);
if (which > state->dts_nspeculations) {
cpu_core[cpu].cpuc_dtrace_flags |= CPU_DTRACE_ILLOP;
return;
dest = &state->dts_buffer[cpu];
do {
-printk(KERN_INFO "spec-commit: a) CPU#%d, which %d, spec-state %d\n", cpu, which, spec->dtsp_state);
curr = spec->dtsp_state;
if (curr == DTRACESPEC_COMMITTINGMANY)
default:
ASSERT(0);
}
-printk(KERN_INFO "spec-commit: a) CPU#%d, which %d, spec-state %d -> %d\n", cpu, which, curr, new);
} while (cmpxchg((uint32_t *)&spec->dtsp_state, curr, new) !=
curr);
ASSERT(state->dts_activity == DTRACE_ACTIVITY_INACTIVE ||
(state == dtrace_anon.dta_state &&
state->dts_activity == DTRACE_ACTIVITY_ACTIVE));
-printk(KERN_INFO "state_buffer(%p, %p, %d) opt[%d] = %lld\n", state, buf, which, which, opt[which]);
if (opt[which] == DTRACEOPT_UNSET || opt[which] == 0)
return 0;
flags |= DTRACEBUF_NOSWITCH;
if (which == DTRACEOPT_BUFSIZE) {
-printk(KERN_INFO "state_buffer(%p, %p, %d) opt[CPU] = %lld, opt[BUFPOLICY] = %lld, sta_state = %p\n", state, buf, which, opt[DTRACEOPT_CPU], opt[DTRACEOPT_BUFPOLICY], dtrace_anon.dta_state);
if (opt[DTRACEOPT_BUFPOLICY] == DTRACEOPT_BUFPOLICY_RING)
flags |= DTRACEBUF_RING;
if (state != dtrace_anon.dta_state ||
state->dts_activity != DTRACE_ACTIVITY_ACTIVE)
flags |= DTRACEBUF_INACTIVE;
-printk(KERN_INFO "state_buffer(%p, %p, %d) flags = %08x\n", state, buf, which, flags);
}
for (size = opt[which]; size >= sizeof (uint64_t); size >>= 1) {
}
rval = dtrace_buffer_alloc(buf, size, flags, cpu);
-printk(KERN_INFO "state_buffer: Alloc %d buffer: tomax %p xamot %p\n", which, buf->dtb_tomax, buf->dtb_xamot);
if (rval != -ENOMEM) {
opt[which] = size;
mutex_lock(&cpu_lock);
mutex_lock(&dtrace_lock);
-printk(KERN_INFO "state_go(1): dts_activity = %d (vs warmup %d or draining %d)\n", state->dts_activity, DTRACE_ACTIVITY_WARMUP, DTRACE_ACTIVITY_DRAINING);
if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE) {
rval = -EBUSY;
goto out;
}
spec = kzalloc(nspec * sizeof(dtrace_speculation_t), GFP_KERNEL);
-printk(KERN_INFO "state_go: nspec = %d, spec = %p (%lld bytes)\n", (int)nspec, spec, nspec * sizeof(dtrace_speculation_t));
if (spec == NULL) {
rval = -ENOMEM;
goto out;
goto err;
}
-printk(KERN_INFO "state_go: spec[%d].buf = %p (%d bytes)\n", i, buf, bufsize);
spec[i].dtsp_buffer = buf;
}
state->dts_deadman = cyclic_add(&hdlr, &when);
state->dts_activity = DTRACE_ACTIVITY_WARMUP;
-printk(KERN_INFO "state_go(2): dts_activity = %d (vs warmup %d or draining %d)\n", state->dts_activity, DTRACE_ACTIVITY_WARMUP, DTRACE_ACTIVITY_DRAINING);
/*
* Now it's time to actually fire the BEGIN probe. We need to disable
* We may have had an exit action from a BEGIN probe; only change our
* state to ACTIVE if we're still in WARMUP.
*/
-printk(KERN_INFO "state_go(3): dts_activity = %d (vs warmup %d or draining %d)\n", state->dts_activity, DTRACE_ACTIVITY_WARMUP, DTRACE_ACTIVITY_DRAINING);
ASSERT(state->dts_activity == DTRACE_ACTIVITY_WARMUP ||
state->dts_activity == DTRACE_ACTIVITY_DRAINING);
* issue a sync to be sure that everyone is out of probe
* context before we start blowing away ECBs.
*/
-printk(KERN_INFO "state_destroy: Setting dts_activity from %d to %d (KILLED)\n", state->dts_activity, DTRACE_ACTIVITY_KILLED);
state->dts_activity = DTRACE_ACTIVITY_KILLED;
dtrace_sync();
}
*/
#include <linux/fs.h>
+#include <linux/ktime.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
+#include <asm/irq_regs.h>
+#include <asm/ptrace.h>
#include "dtrace.h"
#include "dtrace_dev.h"
static void profile_tick(void *arg)
{
profile_probe_t *prof = arg;
+ struct pt_regs *regs = get_irq_regs();
+ unsigned long pc = 0, upc = 0;
- dtrace_probe(prof->prof_id, 0, 0, 0, 0, 0); /* FIXME */
+ if (user_mode(regs))
+ upc = GET_IP(regs);
+ else
+ pc = GET_IP(regs);
+
+ dtrace_probe(prof->prof_id, pc, upc, 0, 0, 0);
+}
+
+static void profile_prof(void *arg)
+{
+ profile_probe_percpu_t *pcpu = arg;
+ profile_probe_t *prof = pcpu->profc_probe;
+ ktime_t late;
+ struct pt_regs *regs = get_irq_regs();
+ unsigned long pc = 0, upc = 0;
+
+ late = ktime_sub(dtrace_gethrtime(), pcpu->profc_expected);
+ pcpu->profc_expected = ktime_add(pcpu->profc_expected,
+ pcpu->profc_interval);
+
+ if (user_mode(regs))
+ upc = GET_IP(regs);
+ else
+ pc = GET_IP(regs);
+
+ dtrace_probe(prof->prof_id, pc, upc, ktime_to_ns(late), 0, 0);
+}
+
+static void profile_online(void *arg, processorid_t cpu, cyc_handler_t *hdlr,
+ cyc_time_t *when)
+{
+ profile_probe_t *prof = arg;
+ profile_probe_percpu_t *pcpu;
+
+ pcpu = kzalloc(sizeof(profile_probe_percpu_t), GFP_KERNEL);
+ pcpu->profc_probe = prof;
+
+ hdlr->cyh_func = profile_prof;
+ hdlr->cyh_arg = pcpu;
+ hdlr->cyh_level = CY_HIGH_LEVEL;
+
+ when->cyt_interval = prof->prof_interval;
+ when->cyt_when = ktime_add(dtrace_gethrtime(), when->cyt_interval);
+
+ pcpu->profc_expected = when->cyt_when;
+ pcpu->profc_interval = when->cyt_interval;
+}
+
+static void profile_offline(void *arg, processorid_t cpu, void *oarg)
+{
+ profile_probe_percpu_t *pcpu = oarg;
+
+ ASSERT(pcpu->profc_probe == arg);
+
+ kfree(pcpu);
}
static void profile_create(ktime_t interval, const char *name, int kind)
int profile_enable(void *arg, dtrace_id_t id, void *parg)
{
profile_probe_t *prof = parg;
-#ifdef FIXME
cyc_omni_handler_t omni;
-#endif
cyc_handler_t hdlr;
cyc_time_t when;
} else {
ASSERT(prof->prof_kind == PROF_PROFILE);
-#ifdef FIXME
omni.cyo_online = profile_online;
omni.cyo_offline = profile_offline;
omni.cyo_arg = prof;
prof->prof_cyclic = cyclic_add_omni(&omni);
-#else
- prof->prof_cyclic = CYCLIC_NONE;
- return -ENOTSUPP;
-#endif
}
return 0;
sz = strlen(nm);
if (sz > 4 && memcmp(nm, "sys_", 4) == 0)
nm += 4;
-#if 0
else if (sz > 5 && memcmp(nm, "stub_", 5) == 0)
nm += 5;
-#else
- else if (sz > 5 && memcmp(nm, "stub_", 5) == 0)
- continue;
-#endif
if (dtrace_probe_lookup(syscall_id, NULL, nm, "entry") != 0)
continue;
}
}
+static dt_sys_call_t get_intercept(int sysnum)
+{
+ switch (sysnum) {
+ default:
+ return systrace_info->syscall;
+ case __NR_clone:
+ return systrace_info->stubs[SCE_CLONE];
+ case __NR_fork:
+ return systrace_info->stubs[SCE_FORK];
+ case __NR_vfork:
+ return systrace_info->stubs[SCE_VFORK];
+ case __NR_sigaltstack:
+ return systrace_info->stubs[SCE_SIGALTSTACK];
+ case __NR_iopl:
+ return systrace_info->stubs[SCE_IOPL];
+ case __NR_execve:
+ return systrace_info->stubs[SCE_EXECVE];
+ case __NR_rt_sigreturn:
+ return systrace_info->stubs[SCE_RT_SIGRETURN];
+ }
+}
+
int systrace_enable(void *arg, dtrace_id_t id, void *parg)
{
- int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
- int enabled =
+ int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
+ int enabled =
systrace_info->sysent[sysnum].stsy_entry != DTRACE_IDNONE ||
systrace_info->sysent[sysnum].stsy_return != DTRACE_IDNONE;
+ dt_sys_call_t intercept = get_intercept(sysnum);;
-#if 0
- if (SYSTRACE_ISENTRY((uintptr_t)parg))
- systrace_info->sysent[sysnum].stsy_entry = id;
- else
- systrace_info->sysent[sysnum].stsy_return = id;
-
- if (enabled) {
- ASSERT((void *)*(systrace_info->sysent[sysnum].stsy_tblent) ==
- (void *)systrace_info->syscall);
-
- return 0;
- }
-
- (void)cmpxchg(systrace_info->sysent[sysnum].stsy_tblent,
- systrace_info->sysent[sysnum].stsy_underlying,
- systrace_info->syscall);
-#else
if (!enabled) {
if (cmpxchg(systrace_info->sysent[sysnum].stsy_tblent,
systrace_info->sysent[sysnum].stsy_underlying,
- systrace_info->syscall) !=
+ intercept) !=
systrace_info->sysent[sysnum].stsy_underlying)
return 0;
} else
ASSERT((void *)*(systrace_info->sysent[sysnum].stsy_tblent) ==
- (void *)systrace_info->syscall);
+ (void *)intercept);
if (SYSTRACE_ISENTRY((uintptr_t)parg))
systrace_info->sysent[sysnum].stsy_entry = id;
else
systrace_info->sysent[sysnum].stsy_return = id;
-#endif
return 0;
}
void systrace_disable(void *arg, dtrace_id_t id, void *parg)
{
- int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
- int enabled =
+ int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
+ int enabled =
systrace_info->sysent[sysnum].stsy_entry != DTRACE_IDNONE ||
systrace_info->sysent[sysnum].stsy_return != DTRACE_IDNONE;
+ dt_sys_call_t intercept = get_intercept(sysnum);;
if (enabled)
(void)cmpxchg(systrace_info->sysent[sysnum].stsy_tblent,
- systrace_info->syscall,
+ intercept,
systrace_info->sysent[sysnum].stsy_underlying);
if (SYSTRACE_ISENTRY((uintptr_t)parg))