Ejemplo n.º 1
0
/*ARGSUSED*/
static int
scalehrtime_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	uint32_t nsec_scale;
	hrtime_t tsc = addr, hrt;
	unsigned int *tscp = (unsigned int *)&tsc;
	uintptr_t scalehrtimef;
	uint64_t scale;
	GElf_Sym sym;

	if (!(flags & DCMD_ADDRSPEC)) {
		if (argc != 1)
			return (DCMD_USAGE);

		switch (argv[0].a_type) {
		case MDB_TYPE_STRING:
			tsc = mdb_strtoull(argv[0].a_un.a_str);
			break;
		case MDB_TYPE_IMMEDIATE:
			tsc = argv[0].a_un.a_val;
			break;
		default:
			return (DCMD_USAGE);
		}
	}

	if (mdb_readsym(&scalehrtimef,
	    sizeof (scalehrtimef), "scalehrtimef") == -1) {
		mdb_warn("couldn't read 'scalehrtimef'");
		return (DCMD_ERR);
	}

	if (mdb_lookup_by_name("tsc_scalehrtime", &sym) == -1) {
		mdb_warn("couldn't find 'tsc_scalehrtime'");
		return (DCMD_ERR);
	}

	if (sym.st_value != scalehrtimef) {
		mdb_warn("::scalehrtime requires that scalehrtimef "
		    "be set to tsc_scalehrtime\n");
		return (DCMD_ERR);
	}

	if (mdb_readsym(&nsec_scale, sizeof (nsec_scale), "nsec_scale") == -1) {
		mdb_warn("couldn't read 'nsec_scale'");
		return (DCMD_ERR);
	}

	scale = (uint64_t)nsec_scale;

	hrt = ((uint64_t)tscp[1] * scale) << NSEC_SHIFT;
	hrt += ((uint64_t)tscp[0] * scale) >> (32 - NSEC_SHIFT);

	mdb_printf("0x%llx\n", hrt);

	return (DCMD_OK);
}
Ejemplo n.º 2
0
/*ARGSUSED*/
static int
find_uhci_instance(uintptr_t uhci_instancep, const void *local_ss, void *cb_arg)
{
	int			td_pool_size, qh_pool_size;
	find_instance_cb_t	*cb_data = (find_instance_cb_t *)cb_arg;
	uhci_state_t		*uhcip = cb_data->fic_uhci_statep;


	if (mdb_vread(cb_data->fic_uhci_statep, sizeof (uhci_state_t),
	    uhci_instancep) == -1) {
		mdb_warn("failed to read uhci_state at %p", uhci_instancep);
		return (-1);
	}

	if (mdb_readsym(&td_pool_size, sizeof (int), "uhci_td_pool_size") ==
	    -1) {
		mdb_warn("failed to read uhci_td_pool_size");
		return (-1);
	}

	if (mdb_readsym(&qh_pool_size, sizeof (int), "uhci_qh_pool_size") ==
	    -1) {
		mdb_warn("failed to read uhci_td_pool_size");
		return (-1);
	}

	/*
	 * See if the addr is within the appropriate pool for this instance.
	 */
	if ((cb_data->fic_td_or_qh == UHCI_TD &&

	    ((uhci_td_t *)cb_data->fic_td_qh >= uhcip->uhci_td_pool_addr &&
	    (uhci_td_t *)cb_data->fic_td_qh <= (uhcip->uhci_td_pool_addr +
	    td_pool_size - sizeof (uhci_td_t)))) ||

	    (cb_data->fic_td_or_qh == UHCI_QH &&

	    ((queue_head_t *)cb_data->fic_td_qh >= uhcip->uhci_qh_pool_addr &&
	    (queue_head_t *)cb_data->fic_td_qh <= (uhcip->uhci_qh_pool_addr +
	    qh_pool_size - sizeof (queue_head_t))))) {

		/* td/qh address is within pool for this instance of uhci. */
		cb_data->fic_found = TRUE;
		return (WALK_DONE);
	}

	return (WALK_NEXT);
}
Ejemplo n.º 3
0
int
ttrace_walk_init(mdb_walk_state_t *wsp)
{
	trap_trace_ctl_t *ttcp;
	size_t ttc_size = sizeof (trap_trace_ctl_t) * NCPU;
	int i;

	if (!ttrace_ttr_size_check())
		return (WALK_ERR);

	ttcp = mdb_zalloc(ttc_size, UM_SLEEP);

	if (wsp->walk_addr != NULL) {
		mdb_warn("ttrace only supports global walks\n");
		return (WALK_ERR);
	}

	if (mdb_readsym(ttcp, ttc_size, "trap_trace_ctl") == -1) {
		mdb_warn("symbol 'trap_trace_ctl' not found; "
		    "non-TRAPTRACE kernel?\n");
		mdb_free(ttcp, ttc_size);
		return (WALK_ERR);
	}

	/*
	 * We'll poach the ttc_current pointer (which isn't used for
	 * anything) to store a pointer to our current TRAPTRACE record.
	 * This allows us to only keep the array of trap_trace_ctl structures
	 * as our walker state (ttc_current may be the only kernel data
	 * structure member added exclusively to make writing the mdb walker
	 * a little easier).
	 */
	for (i = 0; i < NCPU; i++) {
		trap_trace_ctl_t *ttc = &ttcp[i];

		if (ttc->ttc_first == NULL)
			continue;

		/*
		 * Assign ttc_current to be the last completed record.
		 * Note that the error checking (i.e. in the ttc_next ==
		 * ttc_first case) is performed in the step function.
		 */
		ttc->ttc_current = ttc->ttc_next - sizeof (trap_trace_rec_t);
	}

	wsp->walk_data = ttcp;
	return (WALK_NEXT);
}
Ejemplo n.º 4
0
/*
 * Figure out which instance of uhci owns a td/qh.
 *
 * - td_qh: a pointer to a uhci td or qh
 * - td_or_qh: a flag indicating which it is (td/qh),
 * - uhci_statep, pointer to a uhci_state_t, to be filled in with data from
 * the found instance of uhci_state_t.
 *
 * Only works for Cntl/Interrupt tds/qhs; others are dynamically allocated
 * and so cannot be found with this method.
 *
 * Returns 0 on success (no match found), 1 on success (match found),
 * -1 on errors.
 */
static int
find_uhci_statep(void *td_qh, boolean_t td_or_qh, uhci_state_t *uhci_statep)
{
	find_instance_cb_t	cb_data;
	uintptr_t		uhci_ss;


	if (uhci_statep == NULL) {
		mdb_warn("failed to find uhci statep: "
		    "NULL uhci_statep param\n");
		return (-1);
	}

	cb_data.fic_td_qh = td_qh;
	cb_data.fic_td_or_qh = td_or_qh;
	cb_data.fic_found = FALSE;
	cb_data.fic_uhci_statep = uhci_statep;


	if (mdb_readsym(&uhci_ss, sizeof (uhci_statep),
	    "uhci_statep") == -1) {
		mdb_warn("failed to read uhci_statep");
		return (-1);
	}


	/*
	 * Walk all instances of uhci.
	 * The callback func checks if td_qh belongs to a given instance
	 * of uhci.
	 */
	if (mdb_pwalk("softstate", find_uhci_instance, &cb_data,
	    uhci_ss) != 0) {
		mdb_warn("failed to walk softstate");
		return (-1);
	}

	if (cb_data.fic_found == TRUE) {
		return (1);
	}

	return (0);
}
Ejemplo n.º 5
0
/*ARGSUSED*/
static int
ii_info_all(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
    uintptr_t myaddr;
    /*
     * we use the global address.
     */
    if (flags & DCMD_ADDRSPEC)
        return (DCMD_USAGE);

    if (mdb_readsym(&myaddr, sizeof (myaddr), "_ii_info_top") !=
            sizeof (myaddr)) {
        return (DCMD_ERR);
    }

    mdb_printf("_ii_info_top contains 0x%lx\n", myaddr);

    while (myaddr) {
        ii_info(myaddr, DCMD_ADDRSPEC, 0, NULL);
        myaddr = nextaddr;
    }
    return (DCMD_OK);
}
Ejemplo n.º 6
0
/*
 * read mmu parameters from kernel
 */
static void
init_mmu(void)
{
	struct as kas;

	if (mmu.num_level != 0)
		return;

	if (mdb_readsym(&mmu, sizeof (mmu), "mmu") == -1)
		mdb_warn("Can't use HAT information before mmu_init()\n");
	if (mdb_readsym(&kas, sizeof (kas), "kas") == -1)
		mdb_warn("Couldn't find kas - kernel's struct as\n");
	if (mdb_readsym(&kernelbase, sizeof (kernelbase), "kernelbase") == -1)
		mdb_warn("Couldn't find kernelbase\n");
	khat = kas.a_hat;

	/*
	 * Is this a paravirtualized domain image?
	 */
	if (mdb_readsym(&mfn_list_addr, sizeof (mfn_list_addr),
	    "mfn_list") == -1 ||
	    mdb_readsym(&xen_virt_start, sizeof (xen_virt_start),
	    "xen_virt_start") == -1 ||
	    mdb_readsym(&mfn_count, sizeof (mfn_count), "mfn_count") == -1) {
		mfn_list_addr = NULL;
	}

	is_xpv = mfn_list_addr != NULL;

#ifndef _KMDB
	/*
	 * recreate the local mfn_list
	 */
	if (is_xpv) {
		size_t sz = mfn_count * sizeof (pfn_t);
		mfn_list = mdb_zalloc(sz, UM_SLEEP);

		if (mdb_vread(mfn_list, sz, (uintptr_t)mfn_list_addr) == -1) {
			mdb_warn("Failed to read MFN list\n");
			mdb_free(mfn_list, sz);
			mfn_list = NULL;
		}
	}
#endif
}
Ejemplo n.º 7
0
/*ARGSUSED*/
static int
v8cfg_target_readsym(v8_cfg_t *cfgp, const char *name, intptr_t *valp)
{
	return (mdb_readsym(valp, sizeof (valp), name));
}
Ejemplo n.º 8
0
int
mdb_ia32_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp,
    mdb_tgt_stack_f *func, void *arg)
{
	mdb_tgt_gregset_t gregs;
	kreg_t *kregs = &gregs.kregs[0];
	int got_pc = (gsp->kregs[KREG_EIP] != 0);
	int err;

	struct fr {
		uintptr_t fr_savfp;
		uintptr_t fr_savpc;
		long fr_argv[32];
	} fr;

	uintptr_t fp = gsp->kregs[KREG_EBP];
	uintptr_t pc = gsp->kregs[KREG_EIP];
	uintptr_t lastfp = 0;

	ssize_t size;
	uint_t argc;
	int detect_exception_frames = 0;
	int advance_tortoise = 1;
	uintptr_t tortoise_fp = 0;
#ifndef	_KMDB
	int xp;

	if ((mdb_readsym(&xp, sizeof (xp), "xpv_panicking") != -1) && (xp > 0))
		detect_exception_frames = 1;
#endif

	bcopy(gsp, &gregs, sizeof (gregs));

	while (fp != 0) {
		if (fp & (STACK_ALIGN - 1)) {
			err = EMDB_STKALIGN;
			goto badfp;
		}
		if ((size = mdb_tgt_vread(t, &fr, sizeof (fr), fp)) >=
		    (ssize_t)(2 * sizeof (uintptr_t))) {
			size -= (ssize_t)(2 * sizeof (uintptr_t));
			argc = kvm_argcount(t, fr.fr_savpc, size);
		} else {
			err = EMDB_NOMAP;
			goto badfp;
		}

		if (tortoise_fp == 0) {
			tortoise_fp = fp;
		} else {
			/*
			 * Advance tortoise_fp every other frame, so we detect
			 * cycles with Floyd's tortoise/hare.
			 */
			if (advance_tortoise != 0) {
				struct fr tfr;

				if (mdb_tgt_vread(t, &tfr, sizeof (tfr),
				    tortoise_fp) != sizeof (tfr)) {
					err = EMDB_NOMAP;
					goto badfp;
				}

				tortoise_fp = tfr.fr_savfp;
			}

			if (fp == tortoise_fp) {
				err = EMDB_STKFRAME;
				goto badfp;
			}
		}

		advance_tortoise = !advance_tortoise;

		if (got_pc && func(arg, pc, argc, fr.fr_argv, &gregs) != 0)
			break;

		kregs[KREG_ESP] = kregs[KREG_EBP];

		lastfp = fp;
		fp = fr.fr_savfp;
		/*
		 * The Xen hypervisor marks a stack frame as belonging to
		 * an exception by inverting the bits of the pointer to
		 * that frame.  We attempt to identify these frames by
		 * inverting the pointer and seeing if it is within 0xfff
		 * bytes of the last frame.
		 */
		if (detect_exception_frames)
			if ((fp != 0) && (fp < lastfp) &&
			    ((lastfp ^ ~fp) < 0xfff))
				fp = ~fp;

		kregs[KREG_EBP] = fp;
		kregs[KREG_EIP] = pc = fr.fr_savpc;

		got_pc = (pc != 0);
	}

	return (0);

badfp:
	mdb_printf("%p [%s]", fp, mdb_strerror(err));
	return (set_errno(err));
}
Ejemplo n.º 9
0
int
ttrace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	ttrace_dcmd_t dcmd;
	trap_trace_ctl_t *ttc = dcmd.ttd_ttc;
	trap_trace_rec_t rec;
	size_t ttc_size = sizeof (trap_trace_ctl_t) * NCPU;

	if (!ttrace_ttr_size_check())
		return (WALK_ERR);

	bzero(&dcmd, sizeof (dcmd));
	dcmd.ttd_cpu = -1;
	dcmd.ttd_extended = FALSE;

	if (mdb_readsym(ttc, ttc_size, "trap_trace_ctl") == -1) {
		mdb_warn("symbol 'trap_trace_ctl' not found; "
		    "non-TRAPTRACE kernel?\n");
		return (DCMD_ERR);
	}

	if (mdb_getopts(argc, argv,
	    'x', MDB_OPT_SETBITS, TRUE, &dcmd.ttd_extended,
	    't', MDB_OPT_UINTPTR, &dcmd.ttd_kthread, NULL) != argc)
		return (DCMD_USAGE);

	if (DCMD_HDRSPEC(flags)) {
		mdb_printf("%3s %15s %4s %2s %-*s%s\n", "CPU",
		    "TIMESTAMP", "TYPE", "Vec", TT_HDLR_WIDTH, "HANDLER",
		    " EIP");
	}

	if (flags & DCMD_ADDRSPEC) {
		if (addr >= NCPU) {
			if (mdb_vread(&rec, sizeof (rec), addr) == -1) {
				mdb_warn("couldn't read trap trace record "
				    "at %p", addr);
				return (DCMD_ERR);
			}

			if (ttrace_walk(addr, &rec, &dcmd) == WALK_ERR)
				return (DCMD_ERR);

			return (DCMD_OK);
		}
		dcmd.ttd_cpu = addr;
	}

	if (mdb_readvar(&use_apix, "apix_enable") == -1) {
		mdb_warn("failed to read apix_enable");
		use_apix = 0;
	}

	if (use_apix) {
		if (mdb_readvar(&d_apixs, "apixs") == -1) {
			mdb_warn("\nfailed to read apixs.");
			return (DCMD_ERR);
		}
		/* change to apix ttrace interrupt handler */
		ttrace_hdlr[4].t_hdlr = ttrace_apix_interrupt;
	}

	if (mdb_walk("ttrace", (mdb_walk_cb_t)ttrace_walk, &dcmd) == -1) {
		mdb_warn("couldn't walk 'ttrace'");
		return (DCMD_ERR);
	}

	return (DCMD_OK);
}