14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * CDDL HEADER START
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * The contents of this file are subject to the terms of the
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * Common Development and Distribution License (the "License").
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * You may not use this file except in compliance with the License.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * See the License for the specific language governing permissions
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * and limitations under the License.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * When distributing Covered Code, include this CDDL HEADER in each
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * If applicable, add the following below this CDDL HEADER, with the
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * fields enclosed by brackets "[]" replaced with your own identifying
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * information: Portions Copyright [yyyy] [name of copyright owner]
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * CDDL HEADER END
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * Use is subject to license terms.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync#define SDT_ADDR2NDX(addr) ((((uintptr_t)(addr)) >> 4) & sdt_probetab_mask)
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync#define SDT_PROBETAB_SIZE 0x1000 /* 4k entries -- 16K total */
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*ARGSUSED*/
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsyncsdt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync sdt_probe_t *sdt = sdt_probetab[SDT_ADDR2NDX(addr)];
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * On amd64, stack[0] contains the dereferenced stack pointer,
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * stack[1] contains savfp, stack[2] contains savpc. We want
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * to step over these entries.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * When accessing the arguments on the stack, we must
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * protect against accessing beyond the stack. We can
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * safely set NOFAULT here -- we know that interrupts
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * are already disabled.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync return (0);
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*ARGSUSED*/
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * One for all, and all for one: if we haven't yet registered all of
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * our providers, we'll refuse to provide anything.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync if (mp->sdt_nprobes != 0 || (sdpd = mp->sdt_probes) == NULL)
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync for (sdpd = mp->sdt_probes; sdpd != NULL; sdpd = sdpd->sdpd_next) {
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync for (prov = sdt_providers; prov->sdtp_prefix != NULL; prov++) {
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync nname = kmem_alloc(len = strlen(name) + 1, KM_SLEEP);
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync func = kobj_searchsym(mp, sdpd->sdpd_offset, &offs);
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * We have our provider. Now create the probe.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync if ((id = dtrace_probe_lookup(prov->sdtp_id, modname,
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync sdt_probetab[SDT_ADDR2NDX(sdpd->sdpd_offset)] = sdp;
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync sdp->sdp_patchpoint = (uint8_t *)sdpd->sdpd_offset;
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*ARGSUSED*/
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync if (ctl != NULL && ctl->mod_loadcnt == sdp->sdp_loadcnt) {
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * Now we need to remove this probe from the sdt_probetab.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*ARGSUSED*/
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * If this module has disappeared since we discovered its probes,
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * refuse to enable it.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync "(module %s unloaded)",
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * Now check that our modctl has the expected load count. If it
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * doesn't, this module must have been unloaded and reloaded -- and
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * we're not going to touch it.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync "(module %s reloaded)",
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync return (0);
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*ARGSUSED*/
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync if (!ctl->mod_loaded || ctl->mod_loadcnt != sdp->sdp_loadcnt)
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*ARGSUSED*/
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsyncsdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno, int aframes)
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * A total of 6 arguments are passed via registers; any argument with
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * index of 5 or lower is therefore in a register.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync#if !defined(__amd64)
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * If we pass through the invalid op handler, we will
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * use the pointer that it passed to the stack as the
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * second argument to dtrace_invop() as the pointer to
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * the stack.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * In the case of amd64, we will use the pointer to the
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * regs structure that was pushed when we took the
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * trap. To get this structure, we must increment
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * beyond the frame structure. If the argument that
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * we're seeking is passed on the stack, we'll pull
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * the true stack pointer out of the saved registers
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * and decrement our argument by the number of
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * arguments passed in registers; if the argument
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * we're seeking is passed in regsiters, we can just
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * load it directly.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync struct regs *rp = (struct regs *)((uintptr_t)&fp[1] +
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * We know that we did not come through a trap to get into
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * dtrace_probe() -- the provider simply called dtrace_probe()
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * directly. As this is the case, we need to shift the argument
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * that we're looking for: the probe ID is the first argument to
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * dtrace_probe(), so the argument n will actually be found where
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * one would expect to find argument (n + 1).
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * This shouldn't happen. If the argument is passed in a
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * register then it should have been, well, passed in a
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * register...
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync return (0);
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*ARGSUSED*/
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync cmn_err(CE_NOTE, "/dev/sdt couldn't create minor node");
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync kmem_zalloc(sdt_probetab_size * sizeof (sdt_probe_t *), KM_SLEEP);
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync if (dtrace_register(prov->sdtp_name, prov->sdtp_attr,
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync cmn_err(CE_WARN, "failed to register sdt provider %s",
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*ARGSUSED*/
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync kmem_free(sdt_probetab, sdt_probetab_size * sizeof (sdt_probe_t *));
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*ARGSUSED*/
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsyncsdt_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync *result = (void *)0;
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*ARGSUSED*/
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsyncsdt_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync return (0);
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync 0, /* streamtab */
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync 0, /* refcnt */
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * Module linkage information for the kernel.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync &mod_driverops, /* module type (this is a pseudo driver) */