Exemplo n.º 1
0
/*
 * Packet descriptor slab (pdesc_slab_t) walker initialization routine.
 */
int
pdesc_slab_walk_init(mdb_walk_state_t *wsp)
{
    uintptr_t q_head;

    if (wsp->walk_addr == NULL)
        return (WALK_DONE);

    /*
     * If we're called from multidata dcmd, then we're passed in
     * the address of ql_t head; otherwise we'd have to get the
     * address ourselves.
     */
    if (wsp->walk_cbdata == NULL) {
        pdesc_slab_t slab;

        /* Read in pdesc_slab_t */
        if (mdb_vread(&slab, sizeof (slab), wsp->walk_addr) == -1) {
            mdb_warn("failed to read pdesc_slab_t at %p",
                     wsp->walk_addr);
            return (WALK_ERR);
        }

        /* pdesc_slab_t head is inside multidata_t */
        q_head = (uintptr_t)VA_OFF(slab.pds_mmd,
                                   offsetof(multidata_t, mmd_pd_slab_q));
    } else
        q_head = wsp->walk_addr;

    /* Pass it on to our generic ql_t walker init */
    return (mmdq_walk_init(wsp, "pdesc_slab_t", q_head,
                           sizeof (pdesc_slab_t), offsetof(pdesc_slab_t, pds_next)));
}
Exemplo n.º 2
0
/*
 * Packet attribute (pattr_t) walker initialization routine.
 */
int
pattr_walk_init(mdb_walk_state_t *wsp)
{
    uintptr_t q_head;

    if (wsp->walk_addr == NULL)
        return (WALK_DONE);

    /*
     * If we're called from pattbl dcmd, then we're passed in
     * the address of ql_t head; otherwise we'd have to get the
     * address ourselves.
     */
    if (wsp->walk_cbdata == NULL) {
        pattr_t pattr;

        if (mdb_vread(&pattr, sizeof (pattr), wsp->walk_addr) == -1) {
            mdb_warn("failed to read pattr_t at %p",
                     wsp->walk_addr);
            return (WALK_ERR);
        }

        q_head = (uintptr_t)VA_OFF(pattr.pat_lock,
                                   -offsetof(patbkt_t, pbkt_lock)) +
                 offsetof(patbkt_t, pbkt_pattr_q);
    } else
        q_head = wsp->walk_addr;

    /* Pass it on to our generic ql_t walker init */
    return (mmdq_walk_init(wsp, "pattr_t", q_head,
                           sizeof (pattr_t), offsetof(pattr_t, pat_next)));
}
Exemplo n.º 3
0
/* ARGSUSED */
static int
pdesc_print(uintptr_t addr, q_walk_t *qwp, mmd_data_t *data)
{
    pdesc_t pd;
    int i = 0;
    char str[32] = "-";
    static const mdb_bitmask_t pd_flags_bits[] = {
        { "H", PDESC_HBUF_REF, PDESC_HBUF_REF },
        { "P", PDESC_PBUF_REF, PDESC_PBUF_REF },
        { "R", PDESC_REM_DEFER, PDESC_REM_DEFER },
        { NULL, 0, 0 }
    };

    if (mdb_vread(&pd, sizeof (pd), addr) == -1) {
        mdb_warn("failed to read pdesc_t at %p", addr);
        return (WALK_ERR);
    }

    if (pd.pd_magic != PDESC_MAGIC)
        mdb_printf("Incorrect pdesc magic number at %p\n",
                   VA_OFF(addr, offsetof(pdesc_t, pd_magic)));

    if (!qwp->qw_step) {
        mdb_printf("\n");
        mdb_printf("%<b>%-3s %-16s %-16s %-4s %-4s %-4s %-4s %-4s %-4s "
                   "%-4s %-6s%</b>",
                   "", "PDESC", "PATTBL", "HDR", "HDR",
                   "HDR", "HDR", "PLD", "PBUF", "PLD", "");
        mdb_printf("\n");
        mdb_printf(
            "%<b>%<u>%-3s %-16s %-16s %-4s %-4s %-4s %-4s %-4s %-4s "
            "%-4s %-6s%</u>%</b>",
            "NO.", "ADDRESS", "ADDRESS", "SIZE", "HEAD",
            "LEN", "TAIL", "CNT", "IDX", "SIZE", "FLAGS");
        mdb_printf("\n");
    }

    if (pd.pd_pattbl != 0)
        mdb_snprintf(str, sizeof (str), "%016p", pd.pd_pattbl);

    mdb_printf("%-3d %016p %-16s %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-6b\n",
               ++data->counter, addr, str,
               PDESC_HDRSIZE(&pd.pd_pdi), PDESC_HDRHEAD(&pd.pd_pdi),
               PDESC_HDRL(&pd.pd_pdi), PDESC_HDRTAIL(&pd.pd_pdi),
               pd.pd_pdi.pld_cnt, pd.pd_pdi.pld_ary[i].pld_pbuf_idx,
               PDESC_PLD_SPAN_SIZE(&pd.pd_pdi, i), pd.pd_pdi.flags, pd_flags_bits);

    for (++i; i < pd.pd_pdi.pld_cnt; i++)
        mdb_printf("%-62s %-4d %-4d\n",
                   "", pd.pd_pdi.pld_ary[i].pld_pbuf_idx,
                   PDESC_PLD_SPAN_SIZE(&pd.pd_pdi, i));

    return (WALK_NEXT);
}
Exemplo n.º 4
0
/* ARGSUSED */
static int
pattr_print(uintptr_t addr, q_walk_t *qwp, mmd_data_t *data)
{
    pattr_t pattr;
    int i;
    char *pa_name = "UNKNOWN";
    static const pattr_type_t pa_type[] = {
        { "DSTADDRSAP", PATTR_DSTADDRSAP },
        { "SRCADDRSAP", PATTR_SRCADDRSAP },
        { "HCKSUM", PATTR_HCKSUM }
    };
    static const mdb_bitmask_t pa_flags_bits[] = {
        { "R", PATTR_REM_DEFER, PATTR_REM_DEFER },
        { "P", PATTR_PERSIST, PATTR_PERSIST },
        { NULL, 0, 0 }
    };

    if (mdb_vread(&pattr, sizeof (pattr), addr) == -1) {
        mdb_warn("failed to read pattr_t at %p", addr);
        return (WALK_ERR);
    }

    if (pattr.pat_magic != PATTR_MAGIC)
        mdb_printf("Incorrect pattr magic number at %p\n",
                   VA_OFF(addr, offsetof(pattr_t, pat_magic)));

    /* Find a matching string */
    for (i = 0; i < (sizeof (pa_type) / sizeof (*pa_type)); i++) {
        if (pa_type[i].type == pattr.pat_type)
            pa_name = pa_type[i].name;
    }

    if (!qwp->qw_iprint) {
        mdb_printf("\n");
        mdb_inc_indent(21);
    }

    mdb_printf("%016p %x:%-10s %-3d %016p %-5b", addr, pattr.pat_type,
               pa_name, pattr.pat_buflen - sizeof (pattr), addr + sizeof (pattr),
               pattr.pat_flags, pa_flags_bits);

    if (!qwp->qw_iprint)
        mdb_dec_indent(21);
    else
        qwp->qw_iprint = FALSE;

    return (WALK_NEXT);
}
Exemplo n.º 5
0
int
_kvm_kvatop4m(kvm_t *kd, u_long va, u_long *pa)
{
	cpu_kcore_hdr_t *cpup = kd->cpu_data;
	struct regmap *rp;
	struct segmap *sp;
	int vr, vs, pte;
	off_t foff;

	if (va < KERNBASE)
		goto err;

	/*
	 * Layout of CPU segment:
	 *	cpu_kcore_hdr_t;
	 *	[alignment]
	 *	phys_ram_seg_t[cpup->nmemseg];
	 */
	vr = VA_VREG(va);
	vs = VA_VSEG(va);

	sp = &cpup->segmap_store[(vr-NUREG)*NSEGRG + vs];
	if (sp->sg_npte == 0)
		goto err;

	/* XXX - assume page tables in initial kernel DATA or BSS. */
	foff = _kvm_pa2off(kd, (u_long)&sp->sg_pte[VA_VPG(va)] - KERNBASE);
	if (foff == (off_t)-1)
		return (0);

	if (_kvm_pread(kd, kd->pmfd, (void *)&pte, sizeof(pte), foff) < 0) {
		_kvm_err(kd, kd->program, "cannot read pte for %x", va);
		return (0);
	}

	if ((pte & SRMMU_TETYPE) == SRMMU_TEPTE) {
		long p, off = VA_OFF(va);

		p = (pte & SRMMU_PPNMASK) << SRMMU_PPNPASHIFT;
		*pa = p + off;
		return (kd->nbpg - off);
	}
err:
	_kvm_err(kd, 0, "invalid address (%x)", va);
	return (0);
}
Exemplo n.º 6
0
/* ARGSUSED */
static int
pattr_count(uintptr_t addr, q_walk_t *qwp, mmd_data_t *data)
{
    pattr_t pattr;

    if (mdb_vread(&pattr, sizeof (pattr), addr) == -1) {
        mdb_warn("failed to read pattr_t at %p", addr);
        return (WALK_ERR);
    }

    if (pattr.pat_magic != PATTR_MAGIC)
        mdb_printf("Incorrect pattr magic number at %p\n",
                   VA_OFF(addr, offsetof(pattr_t, pat_magic)));

    data->counter++;

    return (WALK_NEXT);
}
Exemplo n.º 7
0
/*
 * (note: sun4 3-level MMU not yet supported)
 */
int
_kvm_kvatop44c(kvm_t *kd, u_long va, u_long *pa)
{
	cpu_kcore_hdr_t *cpup = kd->cpu_data;
	int vr, vs, pte, *ptes;
	struct regmap *rp;
	struct segmap *sp;

	if (va < KERNBASE)
		goto err;

	/*
	 * Layout of CPU segment:
	 *	cpu_kcore_hdr_t;
	 *	[alignment]
	 *	phys_ram_seg_t[cpup->nmemseg];
	 *	ptes[cpup->npmegs];
	 */
	ptes = (int *)((int)kd->cpu_data + cpup->pmegoffset);

	vr = VA_VREG(va);
	vs = VA_VSEG(va);

	sp = &cpup->segmap_store[(vr-NUREG)*NSEGRG + vs];
	if (sp->sg_npte == 0)
		goto err;
	if (sp->sg_pmeg == cpup->npmeg - 1) /* =seginval */
		goto err;
	pte = ptes[sp->sg_pmeg * nptesg + VA_VPG(va)];
	if ((pte & PG_V) != 0) {
		long p, off = VA_OFF(va);

		p = (pte & PG_PFNUM) << pgshift;
		*pa = p + off;
		return (kd->nbpg - off);
	}
err:
	_kvm_err(kd, 0, "invalid address (%x)", va);
	return (0);
}
Exemplo n.º 8
0
/* ARGSUSED */
int
pdesc2slab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
    pdesc_t pd;

    if (!(flags & DCMD_ADDRSPEC) || argc != 0)
        return (DCMD_USAGE);

    if (mdb_vread(&pd, sizeof (pd), addr) == -1) {
        mdb_warn("couldn't read pdesc_t at %p", addr);
        return (DCMD_ERR);
    }

    if (pd.pd_magic != PDESC_MAGIC) {
        mdb_warn("Incorrect pdesc magic number at %p",
                 VA_OFF(addr, offsetof(pdesc_t, pd_magic)));
        return (DCMD_ERR);
    }

    mdb_printf("%p\n", pd.pd_slab);

    return (DCMD_OK);
}
Exemplo n.º 9
0
/* ARGSUSED */
int
pattr2multidata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
    pattr_t pattr;

    if (!(flags & DCMD_ADDRSPEC) || argc != 0)
        return (DCMD_USAGE);

    if (mdb_vread(&pattr, sizeof (pattr), addr) == -1) {
        mdb_warn("couldn't read pattr_t at %p", addr);
        return (DCMD_ERR);
    }

    if (pattr.pat_magic != PATTR_MAGIC) {
        mdb_warn("Incorrect pattr magic number at %p",
                 VA_OFF(addr, offsetof(pattr_t, pat_magic)));
        return (DCMD_ERR);
    }

    mdb_printf("%p\n", pattr.pat_mmd);

    return (DCMD_OK);
}
Exemplo n.º 10
0
/* ARGSUSED */
int
multidata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
    mmd_data_t data;
    multidata_t mmd;
    char str[32] = "-";
    int i = 0;

    bzero(&data, sizeof (data));
    if (!(flags & DCMD_ADDRSPEC) || mdb_getopts(argc, argv,
            'v', MDB_OPT_SETBITS, MMD_VERBOSE, &data.flags,
            's', MDB_OPT_SETBITS, MMD_STATS, &data.flags, NULL) != argc)
        return (DCMD_USAGE);

    if (mdb_vread(&mmd, sizeof (mmd), addr) == -1) {
        mdb_warn("failed to read multidata_t structure at %p", addr);
        return (DCMD_ERR);
    }

    if (mmd.mmd_magic != MULTIDATA_MAGIC)
        mdb_printf("Incorrect Multidata magic number at %p\n",
                   VA_OFF(addr, offsetof(multidata_t, mmd_magic)));

    mdb_printf("\n");
    if (data.flags & MMD_STATS) {
        if ((i = multidata_stats(addr, &mmd)) != DCMD_OK)
            return (i);
    }

    mdb_printf("%<b>%-5s %-?s %-4s %-?s %-4s %-4s %-4s %-?s%</b>",
               "PDESC", "PATTBL", "HBUF", "HBUF", "PBUF", "PBUF", "PBUF", "PBUF");
    mdb_printf("\n");
    mdb_printf("%<b>%<u>%-5s %-?s %-4s %-?s %-4s %-4s %-4s %-?s%</u>%</b>",
               "CNT", "ADDRESS", "REF", "ADDRESS", "REF", "CNT", "IDX",
               "ADDRESS(ES)");
    mdb_printf("\n");

    if (mmd.mmd_pattbl != 0)
        mdb_snprintf(str, sizeof (str), "%016p", mmd.mmd_pattbl);

    i = 0;
    mdb_printf("%-5d %-16s %-4d %016p %-4d %-4d %-4d %016p\n",
               mmd.mmd_pd_cnt, str, mmd.mmd_hbuf_ref, mmd.mmd_hbuf,
               mmd.mmd_pbuf_ref, mmd.mmd_pbuf_cnt, i, mmd.mmd_pbuf[i]);

    for (++i; i < mmd.mmd_pbuf_cnt; i++)
        mdb_printf("%-54s %-4d %016p\n", "", i, mmd.mmd_pbuf[i]);

    if (!(data.flags & MMD_VERBOSE))
        return (DCMD_OK);

    /* Walk packet descriptor slab list */
    if (mdb_pwalk("pdesc_slab", (mdb_walk_cb_t)pdesc_slab_print,
                  &data, (uintptr_t)VA_OFF(addr, offsetof(multidata_t,
                                           mmd_pd_slab_q))) == -1) {
        mdb_warn("couldn't walk pdesc_slab_t list");
        return (DCMD_ERR);
    }

    /* Walk packet descriptor list */
    data.counter = 0;
    if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_print,
                  &data, (uintptr_t)VA_OFF(addr, offsetof(multidata_t,
                                           mmd_pd_q))) == -1) {
        mdb_warn("couldn't walk pdesc_t list");
        return (DCMD_ERR);
    }

    return (DCMD_OK);
}
Exemplo n.º 11
0
/* ARGSUSED */
int
pdesc_verify(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
    multidata_t mmd;
    pdesc_t pd;
    pdescinfo_t *pdi = &pd.pd_pdi;
    pdesc_slab_t slab;
    mblk_t hbuf, pbuf[MULTIDATA_MAX_PBUFS];
    uint_t i, idx;
    boolean_t valid = B_TRUE;
    struct pld_ary_s *pa;

    if (!(flags & DCMD_ADDRSPEC) || argc != 0)
        return (DCMD_USAGE);

    if (mdb_vread(&pd, sizeof (pd), addr) == -1) {
        mdb_warn("couldn't read pdesc_t at %p", addr);
        return (DCMD_ERR);
    }

    if (pd.pd_magic != PDESC_MAGIC) {
        mdb_warn("Incorrect pdesc magic number at %p\n",
                 VA_OFF(addr, offsetof(pdesc_t, pd_magic)));
        return (DCMD_ERR);
    }

    if (mdb_vread(&slab, sizeof (slab), (uintptr_t)pd.pd_slab) == -1) {
        mdb_warn("couldn't read pdesc_slab_t at %p", pd.pd_slab);
        return (DCMD_ERR);
    }

    if (mdb_vread(&mmd, sizeof (mmd), (uintptr_t)slab.pds_mmd) == -1) {
        mdb_warn("couldn't read multidata_t at %p", slab.pds_mmd);
        return (DCMD_ERR);
    }

    if (mmd.mmd_magic != MULTIDATA_MAGIC)
        mdb_printf("Incorrect Multidata magic number at %p\n",
                   VA_OFF(slab.pds_mmd, offsetof(multidata_t, mmd_magic)));

    if (mmd.mmd_hbuf != 0 &&
            mdb_vread(&hbuf, sizeof (hbuf), (uintptr_t)mmd.mmd_hbuf) == -1) {
        mdb_warn("couldn't read mblk_t at %p", mmd.mmd_hbuf);
        return (DCMD_ERR);
    }

    if (mmd.mmd_pbuf_cnt > MULTIDATA_MAX_PBUFS) {
        mdb_warn("Multidata pbuf count exceeds %d\n",
                 MULTIDATA_MAX_PBUFS);
        return (DCMD_ERR);
    } else if (pdi->pld_cnt > mmd.mmd_pbuf_cnt) {
        mdb_warn("descriptor pbuf count exceeds Multidata "
                 "pbuf count %d\n", mmd.mmd_pbuf_cnt);
        return (DCMD_ERR);
    }

    if (mmd.mmd_pbuf_cnt > 0) {
        for (i = 0; i < mmd.mmd_pbuf_cnt; i++) {
            if (mdb_vread(&pbuf[i], sizeof (mblk_t),
                          (uintptr_t)mmd.mmd_pbuf[i]) == -1) {
                mdb_warn("couldn't read mblk_t at %p",
                         mmd.mmd_pbuf[i]);
                return (DCMD_ERR);
            }
        }
    }

    /* It should have at least one buffer reference */
    if (!(pdi->flags & PDESC_HAS_REF)) {
        mdb_warn("descriptor has no buffer reference indicator "
                 "in flags (0x%x)\n", pdi->flags);
        return (DCMD_ERR);
    } else if (!(pdi->flags & PDESC_PBUF_REF) && pdi->pld_cnt > 0) {
        mdb_warn("descriptor has no pbuf reference indicator in "
                 "flags (0x%x); but pld_cnt is %d\n", pdi->flags,
                 pdi->pld_cnt);
        return (DCMD_ERR);
    }

    /* Bounds check the header fragment, if any */
    if (!((pdi->flags & PDESC_HBUF_REF) && pdi->hdr_rptr != 0 &&
            pdi->hdr_wptr != 0 && pdi->hdr_base != 0 &&
            pdi->hdr_lim != 0 && pdi->hdr_lim >= pdi->hdr_base &&
            pdi->hdr_wptr >= pdi->hdr_rptr && pdi->hdr_base <= pdi->hdr_rptr &&
            pdi->hdr_lim >= pdi->hdr_wptr && pdi->hdr_base >= hbuf.b_rptr &&
            MBLKIN(&hbuf, (pdi->hdr_base - hbuf.b_rptr),
                   PDESC_HDRSIZE(pdi)))) {
        mdb_warn("descriptor has invalid header fragment\n");
        return (DCMD_ERR);
    }

    i = 0;
    pa = &pdi->pld_ary[0];
    /* Bounds check the payload fragment, if any */
    while (valid && i < pdi->pld_cnt) {
        valid = (((idx = pa->pld_pbuf_idx) < mmd.mmd_pbuf_cnt) &&
                 pa->pld_rptr != NULL && pa->pld_wptr != NULL &&
                 pa->pld_wptr >= pa->pld_rptr &&
                 pa->pld_rptr >= pbuf[idx].b_rptr &&
                 MBLKIN(&pbuf[idx], (pa->pld_rptr - pbuf[idx].b_rptr),
                        PDESC_PLD_SPAN_SIZE(pdi, i)));

        if (!valid) {
            mdb_warn("descriptor has invalid payload fragment\n");
            return (DCMD_ERR);
        }

        /* advance to next entry */
        i++;
        pa++;
    }

    return (DCMD_OK);
}
Exemplo n.º 12
0
/* ARGSUSED */
static int
pdesc_count(uintptr_t addr, q_walk_t *qwp, mmd_data_t *data)
{
    pdesc_t pd;
    int i;
    uint_t f = data->flags;

    if (mdb_vread(&pd, sizeof (pd), addr) == -1) {
        mdb_warn("failed to read pdesc_t at %p", addr);
        return (WALK_ERR);
    }

    if (pd.pd_magic != PDESC_MAGIC)
        mdb_printf("Incorrect pdesc magic number at %p\n",
                   VA_OFF(addr, offsetof(pdesc_t, pd_magic)));

    if (f == 0) {
        /* No flags set, count all pdescs */
        data->counter++;
    } else if (f == PD_REM_NOCNT && !(pd.pd_pdi.flags & PDESC_REM_DEFER)) {
        /* Count only active (skip removed) pdescs */
        data->counter++;
    } else if (f & PD_ATTR) {
        uint_t pattbl_sz;
        uintptr_t patbkt = (uintptr_t)pd.pd_pattbl;
        mmd_data_t attr_data;

        /* Count local attributes */
        if ((!(f & PD_REM_NOCNT) || ((f & PD_REM_NOCNT) &&
                                     !(pd.pd_pdi.flags & PDESC_REM_DEFER))) && patbkt != 0) {

            /* Figure out the size of hash table */
            mdb_readvar(&pattbl_sz, "pattbl_sz");

            attr_data.counter = 0;
            /* Walk each bucket and count its contents */
            for (i = 0; i < (pattbl_sz * sizeof (patbkt_t));
                    i += sizeof (patbkt_t)) {
                if (mdb_pwalk("pattr",
                              (mdb_walk_cb_t)pattr_count, &attr_data,
                              patbkt + i + offsetof(patbkt_t,
                                                    pbkt_pattr_q)) == -1) {
                    mdb_warn("couldn't walk pattr_t list");
                    return (WALK_ERR);
                }
            }
            data->counter += attr_data.counter;
        }
    } else {
        if (f & PD_HDR) {
            /* Count header span referenced by pdesc */
            if (!(f & PD_REM_NOCNT) || ((f & PD_REM_NOCNT) &&
                                        !(pd.pd_pdi.flags & PDESC_REM_DEFER)))
                data->counter += PDESC_HDRL(&pd.pd_pdi);
        }

        if (f & PD_PLD) {
            /* Count payload span referenced by pdesc */
            if (!(f & PD_REM_NOCNT) || ((f & PD_REM_NOCNT) &&
                                        !(pd.pd_pdi.flags & PDESC_REM_DEFER))) {
                for (i = 0; i < pd.pd_pdi.pld_cnt; i++)
                    data->counter += PDESC_PLD_SPAN_SIZE(
                                         &pd.pd_pdi, i);
            }
        }
    }

    return (WALK_NEXT);
}
Exemplo n.º 13
0
/*
 * Print additional Multidata statistics
 */
static int
multidata_stats(uintptr_t addr, multidata_t *mmd)
{
    mblk_t mp;
    uint_t i = 0, j = 0, k = 0, sz = 0;
    mmd_data_t data;
    uintptr_t patbkt;

    bzero(&data, sizeof (data));

    if (mmd->mmd_hbuf != 0) {
        if (mdb_vread(&mp, sizeof (mp),
                      (uintptr_t)mmd->mmd_hbuf) == -1) {
            mdb_warn("couldn't read mblk_t at %p", mmd->mmd_hbuf);
            return (DCMD_ERR);
        }

        i++;
        sz = MBLKL(&mp);
    }

    k += sz;	/* total bytes */
    j += i;		/* total buffers */

    mdb_printf("%<b>%<u>BUFFER STATS%</b>%</u>\n");
    mdb_printf("Header:\t\t\t%-4d% buffer,\t%-12d bytes\n", i, sz);

    for (i = 0, sz = 0; i < mmd->mmd_pbuf_cnt; i++) {
        if (mdb_vread(&mp, sizeof (mp),
                      (uintptr_t)mmd->mmd_pbuf[i]) == -1) {
            mdb_warn("couldn't read mblk_t at %p",
                     mmd->mmd_pbuf[i]);
            return (DCMD_ERR);
        }
        sz += MBLKL(&mp);
    }

    k += sz;	/* total bytes */
    j += i;		/* total buffers */

    mdb_printf("%<u>Payload:\t\t%-4d buffers,\t%-12d bytes%</u>\n", i, sz);
    mdb_printf("Total:\t\t\t%-4d buffers,\t%-12d bytes\n\n", j, k);

    mdb_printf("%<b>%<u>PACKET DESCRIPTOR STATS%</u>%</b>\n");

    /*
     * Total claimed packet descriptors
     */
    data.flags = 0;
    data.counter = 0;
    if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data,
                  (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) {
        mdb_warn("couldn't walk pdesc_t list");
        return (DCMD_ERR);
    }
    i = data.counter;	/* claimed */
    mdb_printf("Total claimed:\t\t%-4d", i);

    /*
     * Total active header references
     */
    data.flags = (PD_HDR | PD_REM_NOCNT);
    data.counter = 0;
    if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data,
                  (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) {
        mdb_warn("couldn't walk pdesc_t list");
        return (DCMD_ERR);
    }
    mdb_printf("\tActive header refs:\t%-12d bytes\n", data.counter);

    /*
     * Total active packet descriptors
     */
    data.flags = PD_REM_NOCNT;
    data.counter = 0;
    if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data,
                  (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) {
        mdb_warn("couldn't walk pdesc_t list");
        return (DCMD_ERR);
    }
    k = data.counter;	/* active */
    mdb_printf("Active:\t\t\t%-4d", data.counter);

    /*
     * Total active payload references
     */
    data.flags = (PD_PLD | PD_REM_NOCNT);
    data.counter = 0;
    if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data,
                  (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) {
        mdb_warn("couldn't walk pdesc_t list");
        return (DCMD_ERR);
    }
    mdb_printf("\t%<u>Active payload refs:\t%-12d bytes%</u>\n",
               data.counter);

    /*
     * Number of removed packet descriptors (claimed - active)
     */
    mdb_printf("Removed:\t\t%-4d", i - k);

    /*
     * Total active header and payload references
     */
    data.flags = (PD_PLD | PD_HDR | PD_REM_NOCNT);
    data.counter = 0;
    if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data,
                  (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) {
        mdb_warn("couldn't walk pdesc_t list");
        return (DCMD_ERR);
    }
    mdb_printf("\tTotal:\t\t\t%-12d bytes\n\n", data.counter);

    mdb_printf("%<b>%<u>ACTIVE ATTRIBUTE STATS%</u>%</b>\n");

    /*
     * Count local attributes
     */
    data.flags = (PD_ATTR | PD_REM_NOCNT);
    data.counter = 0;
    if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data,
                  (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) {
        mdb_warn("couldn't walk pdesc_t list");
        return (DCMD_ERR);
    }
    mdb_printf("Local:\t\t\t%-4d", data.counter);

    /*
     * Count global attributes
     */
    data.counter = 0;
    patbkt = (uintptr_t)mmd->mmd_pattbl;
    if (patbkt != 0) {
        uint_t pattbl_sz;

        /* Figure out the size of hash table */
        mdb_readvar(&pattbl_sz, "pattbl_sz");

        /* Walk each bucket and count its contents */
        for (i = 0; i < (pattbl_sz * sizeof (patbkt_t));
                i += sizeof (patbkt_t)) {
            if (mdb_pwalk("pattr",
                          (mdb_walk_cb_t)pattr_count, &data,
                          patbkt + i + offsetof(patbkt_t,
                                                pbkt_pattr_q)) == -1) {
                mdb_warn("couldn't walk pattr_t list");
                return (DCMD_ERR);
            }
        }
    }
    mdb_printf("\tGlobal:\t\t\t%-4d\n", data.counter);
    mdb_printf("\n");

    return (DCMD_OK);
}