1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Multidata dcmds and walkers, part of the genunix mdb module, 31*7c478bd9Sstevel@tonic-gate * and operate on core Multidata structures. 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 35*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_ks.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/strft.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #include <sys/multidata.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/multidata_impl.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/pattr.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #include "mmd.h" 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate /* 52*7c478bd9Sstevel@tonic-gate * Structure for passing internal variables. 53*7c478bd9Sstevel@tonic-gate */ 54*7c478bd9Sstevel@tonic-gate typedef struct mmd_data_s { 55*7c478bd9Sstevel@tonic-gate uint_t flags; /* see flags values below */ 56*7c478bd9Sstevel@tonic-gate uint_t counter; /* scratch counter */ 57*7c478bd9Sstevel@tonic-gate } mmd_data_t; 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate #define MMD_VERBOSE 0x1 /* multidata: provide more info */ 60*7c478bd9Sstevel@tonic-gate #define MMD_STATS 0x2 /* multidata: provide statistics */ 61*7c478bd9Sstevel@tonic-gate #define PD_HDR 0x4 /* pdesc: count header region */ 62*7c478bd9Sstevel@tonic-gate #define PD_PLD 0x8 /* pdesc: count payload region(s) */ 63*7c478bd9Sstevel@tonic-gate #define PD_ATTR 0x10 /* pdesc: count local attributes */ 64*7c478bd9Sstevel@tonic-gate #define PD_REM_NOCNT 0x20 /* pdesc: do not count removed pdesc */ 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate /* 67*7c478bd9Sstevel@tonic-gate * Structure to support circular, doubly-linked list (ql_t) walker. 68*7c478bd9Sstevel@tonic-gate */ 69*7c478bd9Sstevel@tonic-gate typedef struct q_walk_s { 70*7c478bd9Sstevel@tonic-gate char *qw_name; /* name of opaque list structure */ 71*7c478bd9Sstevel@tonic-gate uintptr_t qw_head; /* address of list head */ 72*7c478bd9Sstevel@tonic-gate void *qw_data; /* opaque data structure */ 73*7c478bd9Sstevel@tonic-gate uint_t qw_sz; /* size of opaque data structure */ 74*7c478bd9Sstevel@tonic-gate uint_t qw_off; /* ql_t offset in opaque data structure */ 75*7c478bd9Sstevel@tonic-gate uint_t qw_step; /* walk_step has been called */ 76*7c478bd9Sstevel@tonic-gate uint_t qw_iprint; /* initial print */ 77*7c478bd9Sstevel@tonic-gate } q_walk_t; 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate static int pdesc_slab_print(uintptr_t, q_walk_t *, mmd_data_t *); 80*7c478bd9Sstevel@tonic-gate static int pdesc_print(uintptr_t, q_walk_t *, mmd_data_t *); 81*7c478bd9Sstevel@tonic-gate static int pdesc_count(uintptr_t, q_walk_t *, mmd_data_t *); 82*7c478bd9Sstevel@tonic-gate static int pattr_print(uintptr_t, q_walk_t *, mmd_data_t *); 83*7c478bd9Sstevel@tonic-gate static int pattr_count(uintptr_t, q_walk_t *, mmd_data_t *); 84*7c478bd9Sstevel@tonic-gate static int multidata_stats(uintptr_t addr, multidata_t *); 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate #define VA_OFF(x, o) (((uchar_t *)(x) + (o))) 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate /* 89*7c478bd9Sstevel@tonic-gate * A dcmd which prints a summary of a multidata_t structure. 90*7c478bd9Sstevel@tonic-gate */ 91*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 92*7c478bd9Sstevel@tonic-gate int 93*7c478bd9Sstevel@tonic-gate multidata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 94*7c478bd9Sstevel@tonic-gate { 95*7c478bd9Sstevel@tonic-gate mmd_data_t data; 96*7c478bd9Sstevel@tonic-gate multidata_t mmd; 97*7c478bd9Sstevel@tonic-gate char str[32] = "-"; 98*7c478bd9Sstevel@tonic-gate int i = 0; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate bzero(&data, sizeof (data)); 101*7c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || mdb_getopts(argc, argv, 102*7c478bd9Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, MMD_VERBOSE, &data.flags, 103*7c478bd9Sstevel@tonic-gate 's', MDB_OPT_SETBITS, MMD_STATS, &data.flags, NULL) != argc) 104*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate if (mdb_vread(&mmd, sizeof (mmd), addr) == -1) { 107*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read multidata_t structure at %p", addr); 108*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate if (mmd.mmd_magic != MULTIDATA_MAGIC) 112*7c478bd9Sstevel@tonic-gate mdb_printf("Incorrect Multidata magic number at %p\n", 113*7c478bd9Sstevel@tonic-gate VA_OFF(addr, offsetof(multidata_t, mmd_magic))); 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 116*7c478bd9Sstevel@tonic-gate if (data.flags & MMD_STATS) { 117*7c478bd9Sstevel@tonic-gate if ((i = multidata_stats(addr, &mmd)) != DCMD_OK) 118*7c478bd9Sstevel@tonic-gate return (i); 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate mdb_printf("%<b>%-5s %-?s %-4s %-?s %-4s %-4s %-4s %-?s%</b>", 122*7c478bd9Sstevel@tonic-gate "PDESC", "PATTBL", "HBUF", "HBUF", "PBUF", "PBUF", "PBUF", "PBUF"); 123*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 124*7c478bd9Sstevel@tonic-gate mdb_printf("%<b>%<u>%-5s %-?s %-4s %-?s %-4s %-4s %-4s %-?s%</u>%</b>", 125*7c478bd9Sstevel@tonic-gate "CNT", "ADDRESS", "REF", "ADDRESS", "REF", "CNT", "IDX", 126*7c478bd9Sstevel@tonic-gate "ADDRESS(ES)"); 127*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate if (mmd.mmd_pattbl != 0) 130*7c478bd9Sstevel@tonic-gate mdb_snprintf(str, sizeof (str), "%016p", mmd.mmd_pattbl); 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate i = 0; 133*7c478bd9Sstevel@tonic-gate mdb_printf("%-5d %-16s %-4d %016p %-4d %-4d %-4d %016p\n", 134*7c478bd9Sstevel@tonic-gate mmd.mmd_pd_cnt, str, mmd.mmd_hbuf_ref, mmd.mmd_hbuf, 135*7c478bd9Sstevel@tonic-gate mmd.mmd_pbuf_ref, mmd.mmd_pbuf_cnt, i, mmd.mmd_pbuf[i]); 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate for (++i; i < mmd.mmd_pbuf_cnt; i++) 138*7c478bd9Sstevel@tonic-gate mdb_printf("%-54s %-4d %016p\n", "", i, mmd.mmd_pbuf[i]); 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate if (!(data.flags & MMD_VERBOSE)) 141*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate /* Walk packet descriptor slab list */ 144*7c478bd9Sstevel@tonic-gate if (mdb_pwalk("pdesc_slab", (mdb_walk_cb_t)pdesc_slab_print, 145*7c478bd9Sstevel@tonic-gate &data, (uintptr_t)VA_OFF(addr, offsetof(multidata_t, 146*7c478bd9Sstevel@tonic-gate mmd_pd_slab_q))) == -1) { 147*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk pdesc_slab_t list"); 148*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate /* Walk packet descriptor list */ 152*7c478bd9Sstevel@tonic-gate data.counter = 0; 153*7c478bd9Sstevel@tonic-gate if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_print, 154*7c478bd9Sstevel@tonic-gate &data, (uintptr_t)VA_OFF(addr, offsetof(multidata_t, 155*7c478bd9Sstevel@tonic-gate mmd_pd_q))) == -1) { 156*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk pdesc_t list"); 157*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* 164*7c478bd9Sstevel@tonic-gate * Print additional Multidata statistics 165*7c478bd9Sstevel@tonic-gate */ 166*7c478bd9Sstevel@tonic-gate static int 167*7c478bd9Sstevel@tonic-gate multidata_stats(uintptr_t addr, multidata_t *mmd) 168*7c478bd9Sstevel@tonic-gate { 169*7c478bd9Sstevel@tonic-gate mblk_t mp; 170*7c478bd9Sstevel@tonic-gate uint_t i = 0, j = 0, k = 0, sz = 0; 171*7c478bd9Sstevel@tonic-gate mmd_data_t data; 172*7c478bd9Sstevel@tonic-gate uintptr_t patbkt; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate bzero(&data, sizeof (data)); 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate if (mmd->mmd_hbuf != 0) { 177*7c478bd9Sstevel@tonic-gate if (mdb_vread(&mp, sizeof (mp), 178*7c478bd9Sstevel@tonic-gate (uintptr_t)mmd->mmd_hbuf) == -1) { 179*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't read mblk_t at %p", mmd->mmd_hbuf); 180*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate i++; 184*7c478bd9Sstevel@tonic-gate sz = MBLKL(&mp); 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate k += sz; /* total bytes */ 188*7c478bd9Sstevel@tonic-gate j += i; /* total buffers */ 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate mdb_printf("%<b>%<u>BUFFER STATS%</b>%</u>\n"); 191*7c478bd9Sstevel@tonic-gate mdb_printf("Header:\t\t\t%-4d% buffer,\t%-12d bytes\n", i, sz); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate for (i = 0, sz = 0; i < mmd->mmd_pbuf_cnt; i++) { 194*7c478bd9Sstevel@tonic-gate if (mdb_vread(&mp, sizeof (mp), 195*7c478bd9Sstevel@tonic-gate (uintptr_t)mmd->mmd_pbuf[i]) == -1) { 196*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't read mblk_t at %p", 197*7c478bd9Sstevel@tonic-gate mmd->mmd_pbuf[i]); 198*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate sz += MBLKL(&mp); 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate k += sz; /* total bytes */ 204*7c478bd9Sstevel@tonic-gate j += i; /* total buffers */ 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate mdb_printf("%<u>Payload:\t\t%-4d buffers,\t%-12d bytes%</u>\n", i, sz); 207*7c478bd9Sstevel@tonic-gate mdb_printf("Total:\t\t\t%-4d buffers,\t%-12d bytes\n\n", j, k); 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate mdb_printf("%<b>%<u>PACKET DESCRIPTOR STATS%</u>%</b>\n"); 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * Total claimed packet descriptors 213*7c478bd9Sstevel@tonic-gate */ 214*7c478bd9Sstevel@tonic-gate data.flags = 0; 215*7c478bd9Sstevel@tonic-gate data.counter = 0; 216*7c478bd9Sstevel@tonic-gate if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data, 217*7c478bd9Sstevel@tonic-gate (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) { 218*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk pdesc_t list"); 219*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate i = data.counter; /* claimed */ 222*7c478bd9Sstevel@tonic-gate mdb_printf("Total claimed:\t\t%-4d", i); 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate /* 225*7c478bd9Sstevel@tonic-gate * Total active header references 226*7c478bd9Sstevel@tonic-gate */ 227*7c478bd9Sstevel@tonic-gate data.flags = (PD_HDR | PD_REM_NOCNT); 228*7c478bd9Sstevel@tonic-gate data.counter = 0; 229*7c478bd9Sstevel@tonic-gate if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data, 230*7c478bd9Sstevel@tonic-gate (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) { 231*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk pdesc_t list"); 232*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate mdb_printf("\tActive header refs:\t%-12d bytes\n", data.counter); 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate /* 237*7c478bd9Sstevel@tonic-gate * Total active packet descriptors 238*7c478bd9Sstevel@tonic-gate */ 239*7c478bd9Sstevel@tonic-gate data.flags = PD_REM_NOCNT; 240*7c478bd9Sstevel@tonic-gate data.counter = 0; 241*7c478bd9Sstevel@tonic-gate if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data, 242*7c478bd9Sstevel@tonic-gate (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) { 243*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk pdesc_t list"); 244*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate k = data.counter; /* active */ 247*7c478bd9Sstevel@tonic-gate mdb_printf("Active:\t\t\t%-4d", data.counter); 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate /* 250*7c478bd9Sstevel@tonic-gate * Total active payload references 251*7c478bd9Sstevel@tonic-gate */ 252*7c478bd9Sstevel@tonic-gate data.flags = (PD_PLD | PD_REM_NOCNT); 253*7c478bd9Sstevel@tonic-gate data.counter = 0; 254*7c478bd9Sstevel@tonic-gate if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data, 255*7c478bd9Sstevel@tonic-gate (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) { 256*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk pdesc_t list"); 257*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate mdb_printf("\t%<u>Active payload refs:\t%-12d bytes%</u>\n", 260*7c478bd9Sstevel@tonic-gate data.counter); 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate /* 263*7c478bd9Sstevel@tonic-gate * Number of removed packet descriptors (claimed - active) 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate mdb_printf("Removed:\t\t%-4d", i - k); 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate /* 268*7c478bd9Sstevel@tonic-gate * Total active header and payload references 269*7c478bd9Sstevel@tonic-gate */ 270*7c478bd9Sstevel@tonic-gate data.flags = (PD_PLD | PD_HDR | PD_REM_NOCNT); 271*7c478bd9Sstevel@tonic-gate data.counter = 0; 272*7c478bd9Sstevel@tonic-gate if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data, 273*7c478bd9Sstevel@tonic-gate (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) { 274*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk pdesc_t list"); 275*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate mdb_printf("\tTotal:\t\t\t%-12d bytes\n\n", data.counter); 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate mdb_printf("%<b>%<u>ACTIVE ATTRIBUTE STATS%</u>%</b>\n"); 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* 282*7c478bd9Sstevel@tonic-gate * Count local attributes 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate data.flags = (PD_ATTR | PD_REM_NOCNT); 285*7c478bd9Sstevel@tonic-gate data.counter = 0; 286*7c478bd9Sstevel@tonic-gate if (mdb_pwalk("pdesc", (mdb_walk_cb_t)pdesc_count, &data, 287*7c478bd9Sstevel@tonic-gate (uintptr_t)VA_OFF(addr, offsetof(multidata_t, mmd_pd_q))) == -1) { 288*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk pdesc_t list"); 289*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate mdb_printf("Local:\t\t\t%-4d", data.counter); 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate /* 294*7c478bd9Sstevel@tonic-gate * Count global attributes 295*7c478bd9Sstevel@tonic-gate */ 296*7c478bd9Sstevel@tonic-gate data.counter = 0; 297*7c478bd9Sstevel@tonic-gate patbkt = (uintptr_t)mmd->mmd_pattbl; 298*7c478bd9Sstevel@tonic-gate if (patbkt != 0) { 299*7c478bd9Sstevel@tonic-gate uint_t pattbl_sz; 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate /* Figure out the size of hash table */ 302*7c478bd9Sstevel@tonic-gate mdb_readvar(&pattbl_sz, "pattbl_sz"); 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* Walk each bucket and count its contents */ 305*7c478bd9Sstevel@tonic-gate for (i = 0; i < (pattbl_sz * sizeof (patbkt_t)); 306*7c478bd9Sstevel@tonic-gate i += sizeof (patbkt_t)) { 307*7c478bd9Sstevel@tonic-gate if (mdb_pwalk("pattr", 308*7c478bd9Sstevel@tonic-gate (mdb_walk_cb_t)pattr_count, &data, 309*7c478bd9Sstevel@tonic-gate patbkt + i + offsetof(patbkt_t, 310*7c478bd9Sstevel@tonic-gate pbkt_pattr_q)) == -1) { 311*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk pattr_t list"); 312*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate mdb_printf("\tGlobal:\t\t\t%-4d\n", data.counter); 317*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 320*7c478bd9Sstevel@tonic-gate } 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate /* 323*7c478bd9Sstevel@tonic-gate * Print the contents of a packet descriptor slab (pdesc_slab_t) structure. 324*7c478bd9Sstevel@tonic-gate */ 325*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 326*7c478bd9Sstevel@tonic-gate static int 327*7c478bd9Sstevel@tonic-gate pdesc_slab_print(uintptr_t addr, q_walk_t *qwp, mmd_data_t *data) 328*7c478bd9Sstevel@tonic-gate { 329*7c478bd9Sstevel@tonic-gate pdesc_slab_t *slab; 330*7c478bd9Sstevel@tonic-gate uint_t pdslab_sz, slab_sz; 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate /* Figure out how many descriptors in a slab */ 333*7c478bd9Sstevel@tonic-gate mdb_readvar(&pdslab_sz, "pdslab_sz"); 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate /* This shouldn't be true, unless something awful has happened */ 336*7c478bd9Sstevel@tonic-gate if (pdslab_sz < 1) { 337*7c478bd9Sstevel@tonic-gate mdb_warn("incorrect pdslab_sz (0)"); 338*7c478bd9Sstevel@tonic-gate pdslab_sz = 1; 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate /* Read in the entire slab chunk; may be of use one day */ 342*7c478bd9Sstevel@tonic-gate slab_sz = PDESC_SLAB_SIZE(pdslab_sz); 343*7c478bd9Sstevel@tonic-gate slab = mdb_alloc(slab_sz, UM_SLEEP); 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate if (mdb_vread(slab, slab_sz, addr) == -1) { 346*7c478bd9Sstevel@tonic-gate mdb_free(slab, slab_sz); 347*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read pdesc_slab_t at %p", addr); 348*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate if (!qwp->qw_step) 352*7c478bd9Sstevel@tonic-gate mdb_printf("\n%<b>%<u>%-?s %7s %7s%</u>%</b>\n", 353*7c478bd9Sstevel@tonic-gate "PDESC SLAB ADDR", "SIZE", "CLAIMED"); 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate mdb_printf("%016p %7d %7d\n", addr, slab->pds_sz, slab->pds_used); 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate mdb_free(slab, slab_sz); 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate return (WALK_NEXT); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate /* 363*7c478bd9Sstevel@tonic-gate * Generic packet descriptor (pdesc_t) counting routine. 364*7c478bd9Sstevel@tonic-gate */ 365*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 366*7c478bd9Sstevel@tonic-gate static int 367*7c478bd9Sstevel@tonic-gate pdesc_count(uintptr_t addr, q_walk_t *qwp, mmd_data_t *data) 368*7c478bd9Sstevel@tonic-gate { 369*7c478bd9Sstevel@tonic-gate pdesc_t pd; 370*7c478bd9Sstevel@tonic-gate int i; 371*7c478bd9Sstevel@tonic-gate uint_t f = data->flags; 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate if (mdb_vread(&pd, sizeof (pd), addr) == -1) { 374*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read pdesc_t at %p", addr); 375*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate if (pd.pd_magic != PDESC_MAGIC) 379*7c478bd9Sstevel@tonic-gate mdb_printf("Incorrect pdesc magic number at %p\n", 380*7c478bd9Sstevel@tonic-gate VA_OFF(addr, offsetof(pdesc_t, pd_magic))); 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate if (f == 0) { 383*7c478bd9Sstevel@tonic-gate /* No flags set, count all pdescs */ 384*7c478bd9Sstevel@tonic-gate data->counter++; 385*7c478bd9Sstevel@tonic-gate } else if (f == PD_REM_NOCNT && !(pd.pd_pdi.flags & PDESC_REM_DEFER)) { 386*7c478bd9Sstevel@tonic-gate /* Count only active (skip removed) pdescs */ 387*7c478bd9Sstevel@tonic-gate data->counter++; 388*7c478bd9Sstevel@tonic-gate } else if (f & PD_ATTR) { 389*7c478bd9Sstevel@tonic-gate uint_t pattbl_sz; 390*7c478bd9Sstevel@tonic-gate uintptr_t patbkt = (uintptr_t)pd.pd_pattbl; 391*7c478bd9Sstevel@tonic-gate mmd_data_t attr_data; 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate /* Count local attributes */ 394*7c478bd9Sstevel@tonic-gate if ((!(f & PD_REM_NOCNT) || ((f & PD_REM_NOCNT) && 395*7c478bd9Sstevel@tonic-gate !(pd.pd_pdi.flags & PDESC_REM_DEFER))) && patbkt != 0) { 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate /* Figure out the size of hash table */ 398*7c478bd9Sstevel@tonic-gate mdb_readvar(&pattbl_sz, "pattbl_sz"); 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate attr_data.counter = 0; 401*7c478bd9Sstevel@tonic-gate /* Walk each bucket and count its contents */ 402*7c478bd9Sstevel@tonic-gate for (i = 0; i < (pattbl_sz * sizeof (patbkt_t)); 403*7c478bd9Sstevel@tonic-gate i += sizeof (patbkt_t)) { 404*7c478bd9Sstevel@tonic-gate if (mdb_pwalk("pattr", 405*7c478bd9Sstevel@tonic-gate (mdb_walk_cb_t)pattr_count, &attr_data, 406*7c478bd9Sstevel@tonic-gate patbkt + i + offsetof(patbkt_t, 407*7c478bd9Sstevel@tonic-gate pbkt_pattr_q)) == -1) { 408*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk pattr_t list"); 409*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate data->counter += attr_data.counter; 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate } else { 415*7c478bd9Sstevel@tonic-gate if (f & PD_HDR) { 416*7c478bd9Sstevel@tonic-gate /* Count header span referenced by pdesc */ 417*7c478bd9Sstevel@tonic-gate if (!(f & PD_REM_NOCNT) || ((f & PD_REM_NOCNT) && 418*7c478bd9Sstevel@tonic-gate !(pd.pd_pdi.flags & PDESC_REM_DEFER))) 419*7c478bd9Sstevel@tonic-gate data->counter += PDESC_HDRL(&pd.pd_pdi); 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate if (f & PD_PLD) { 423*7c478bd9Sstevel@tonic-gate /* Count payload span referenced by pdesc */ 424*7c478bd9Sstevel@tonic-gate if (!(f & PD_REM_NOCNT) || ((f & PD_REM_NOCNT) && 425*7c478bd9Sstevel@tonic-gate !(pd.pd_pdi.flags & PDESC_REM_DEFER))) { 426*7c478bd9Sstevel@tonic-gate for (i = 0; i < pd.pd_pdi.pld_cnt; i++) 427*7c478bd9Sstevel@tonic-gate data->counter += PDESC_PLD_SPAN_SIZE( 428*7c478bd9Sstevel@tonic-gate &pd.pd_pdi, i); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate return (WALK_NEXT); 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate /* 437*7c478bd9Sstevel@tonic-gate * Print the contents of a packet descriptor (pdesc_t) structure. 438*7c478bd9Sstevel@tonic-gate */ 439*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 440*7c478bd9Sstevel@tonic-gate static int 441*7c478bd9Sstevel@tonic-gate pdesc_print(uintptr_t addr, q_walk_t *qwp, mmd_data_t *data) 442*7c478bd9Sstevel@tonic-gate { 443*7c478bd9Sstevel@tonic-gate pdesc_t pd; 444*7c478bd9Sstevel@tonic-gate int i = 0; 445*7c478bd9Sstevel@tonic-gate char str[32] = "-"; 446*7c478bd9Sstevel@tonic-gate static const mdb_bitmask_t pd_flags_bits[] = { 447*7c478bd9Sstevel@tonic-gate { "H", PDESC_HBUF_REF, PDESC_HBUF_REF }, 448*7c478bd9Sstevel@tonic-gate { "P", PDESC_PBUF_REF, PDESC_PBUF_REF }, 449*7c478bd9Sstevel@tonic-gate { "R", PDESC_REM_DEFER, PDESC_REM_DEFER }, 450*7c478bd9Sstevel@tonic-gate { NULL, 0, 0 } 451*7c478bd9Sstevel@tonic-gate }; 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate if (mdb_vread(&pd, sizeof (pd), addr) == -1) { 454*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read pdesc_t at %p", addr); 455*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate if (pd.pd_magic != PDESC_MAGIC) 459*7c478bd9Sstevel@tonic-gate mdb_printf("Incorrect pdesc magic number at %p\n", 460*7c478bd9Sstevel@tonic-gate VA_OFF(addr, offsetof(pdesc_t, pd_magic))); 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate if (!qwp->qw_step) { 463*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 464*7c478bd9Sstevel@tonic-gate mdb_printf("%<b>%-3s %-16s %-16s %-4s %-4s %-4s %-4s %-4s %-4s " 465*7c478bd9Sstevel@tonic-gate "%-4s %-6s%</b>", 466*7c478bd9Sstevel@tonic-gate "", "PDESC", "PATTBL", "HDR", "HDR", 467*7c478bd9Sstevel@tonic-gate "HDR", "HDR", "PLD", "PBUF", "PLD", ""); 468*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 469*7c478bd9Sstevel@tonic-gate mdb_printf( 470*7c478bd9Sstevel@tonic-gate "%<b>%<u>%-3s %-16s %-16s %-4s %-4s %-4s %-4s %-4s %-4s " 471*7c478bd9Sstevel@tonic-gate "%-4s %-6s%</u>%</b>", 472*7c478bd9Sstevel@tonic-gate "NO.", "ADDRESS", "ADDRESS", "SIZE", "HEAD", 473*7c478bd9Sstevel@tonic-gate "LEN", "TAIL", "CNT", "IDX", "SIZE", "FLAGS"); 474*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate if (pd.pd_pattbl != 0) 478*7c478bd9Sstevel@tonic-gate mdb_snprintf(str, sizeof (str), "%016p", pd.pd_pattbl); 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate mdb_printf("%-3d %016p %-16s %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-6b\n", 481*7c478bd9Sstevel@tonic-gate ++data->counter, addr, str, 482*7c478bd9Sstevel@tonic-gate PDESC_HDRSIZE(&pd.pd_pdi), PDESC_HDRHEAD(&pd.pd_pdi), 483*7c478bd9Sstevel@tonic-gate PDESC_HDRL(&pd.pd_pdi), PDESC_HDRTAIL(&pd.pd_pdi), 484*7c478bd9Sstevel@tonic-gate pd.pd_pdi.pld_cnt, pd.pd_pdi.pld_ary[i].pld_pbuf_idx, 485*7c478bd9Sstevel@tonic-gate PDESC_PLD_SPAN_SIZE(&pd.pd_pdi, i), pd.pd_pdi.flags, pd_flags_bits); 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate for (++i; i < pd.pd_pdi.pld_cnt; i++) 488*7c478bd9Sstevel@tonic-gate mdb_printf("%-62s %-4d %-4d\n", 489*7c478bd9Sstevel@tonic-gate "", pd.pd_pdi.pld_ary[i].pld_pbuf_idx, 490*7c478bd9Sstevel@tonic-gate PDESC_PLD_SPAN_SIZE(&pd.pd_pdi, i)); 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate return (WALK_NEXT); 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate /* 496*7c478bd9Sstevel@tonic-gate * General purpose ql_t walk_init routine. 497*7c478bd9Sstevel@tonic-gate */ 498*7c478bd9Sstevel@tonic-gate static int 499*7c478bd9Sstevel@tonic-gate mmdq_walk_init(mdb_walk_state_t *wsp, char *name, uintptr_t qh, 500*7c478bd9Sstevel@tonic-gate uint_t sz, uint_t ql_off) 501*7c478bd9Sstevel@tonic-gate { 502*7c478bd9Sstevel@tonic-gate q_walk_t *qwp; 503*7c478bd9Sstevel@tonic-gate ql_t ql; 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate /* Caller must have supplied an address */ 506*7c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL) 507*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate qwp = mdb_alloc(sizeof (*qwp), UM_SLEEP); 510*7c478bd9Sstevel@tonic-gate qwp->qw_name = name; 511*7c478bd9Sstevel@tonic-gate qwp->qw_head = qh; 512*7c478bd9Sstevel@tonic-gate qwp->qw_data = sz > 0 ? mdb_alloc(sz, UM_SLEEP) : NULL; 513*7c478bd9Sstevel@tonic-gate qwp->qw_sz = sz; 514*7c478bd9Sstevel@tonic-gate qwp->qw_off = ql_off; 515*7c478bd9Sstevel@tonic-gate qwp->qw_step = FALSE; 516*7c478bd9Sstevel@tonic-gate qwp->qw_iprint = TRUE; 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate wsp->walk_data = qwp; 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate if (mdb_vread(qwp->qw_data, qwp->qw_sz, wsp->walk_addr) == -1) { 521*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read %s at %p", qwp->qw_name, 522*7c478bd9Sstevel@tonic-gate wsp->walk_addr); 523*7c478bd9Sstevel@tonic-gate mmdq_walk_fini(wsp); 524*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate bcopy((uchar_t *)qwp->qw_data + qwp->qw_off, &ql, sizeof (ql)); 528*7c478bd9Sstevel@tonic-gate if (qh == (uintptr_t)ql.ql_next) { 529*7c478bd9Sstevel@tonic-gate mmdq_walk_fini(wsp); 530*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)ql.ql_next; 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate return (WALK_NEXT); 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate /* 539*7c478bd9Sstevel@tonic-gate * General purpose ql_t walk_step routine. 540*7c478bd9Sstevel@tonic-gate */ 541*7c478bd9Sstevel@tonic-gate int 542*7c478bd9Sstevel@tonic-gate mmdq_walk_step(mdb_walk_state_t *wsp) 543*7c478bd9Sstevel@tonic-gate { 544*7c478bd9Sstevel@tonic-gate q_walk_t *qwp = (q_walk_t *)wsp->walk_data; 545*7c478bd9Sstevel@tonic-gate int status = WALK_NEXT; 546*7c478bd9Sstevel@tonic-gate ql_t ql; 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate /* We've wrapped around the circular list */ 549*7c478bd9Sstevel@tonic-gate if (qwp->qw_step && wsp->walk_addr == qwp->qw_head) 550*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 553*7c478bd9Sstevel@tonic-gate wsp->walk_cbdata); 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate if (mdb_vread(qwp->qw_data, qwp->qw_sz, wsp->walk_addr) == -1) { 556*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read %s at %p", qwp->qw_name, 557*7c478bd9Sstevel@tonic-gate wsp->walk_addr); 558*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate /* Go forward to the next one */ 562*7c478bd9Sstevel@tonic-gate bcopy((uchar_t *)qwp->qw_data + qwp->qw_off, &ql, sizeof (ql)); 563*7c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)ql.ql_next; 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate /* We've done the first walk */ 566*7c478bd9Sstevel@tonic-gate qwp->qw_step = TRUE; 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate return (status); 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate /* 572*7c478bd9Sstevel@tonic-gate * General purpose ql_t walk_fini routine. 573*7c478bd9Sstevel@tonic-gate */ 574*7c478bd9Sstevel@tonic-gate void 575*7c478bd9Sstevel@tonic-gate mmdq_walk_fini(mdb_walk_state_t *wsp) 576*7c478bd9Sstevel@tonic-gate { 577*7c478bd9Sstevel@tonic-gate q_walk_t *qwp = (q_walk_t *)wsp->walk_data; 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate if (qwp->qw_data != NULL) 580*7c478bd9Sstevel@tonic-gate mdb_free(qwp->qw_data, qwp->qw_sz); 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate mdb_free(qwp, sizeof (*qwp)); 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate /* 586*7c478bd9Sstevel@tonic-gate * Packet descriptor slab (pdesc_slab_t) walker initialization routine. 587*7c478bd9Sstevel@tonic-gate */ 588*7c478bd9Sstevel@tonic-gate int 589*7c478bd9Sstevel@tonic-gate pdesc_slab_walk_init(mdb_walk_state_t *wsp) 590*7c478bd9Sstevel@tonic-gate { 591*7c478bd9Sstevel@tonic-gate uintptr_t q_head; 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL) 594*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate /* 597*7c478bd9Sstevel@tonic-gate * If we're called from multidata dcmd, then we're passed in 598*7c478bd9Sstevel@tonic-gate * the address of ql_t head; otherwise we'd have to get the 599*7c478bd9Sstevel@tonic-gate * address ourselves. 600*7c478bd9Sstevel@tonic-gate */ 601*7c478bd9Sstevel@tonic-gate if (wsp->walk_cbdata == NULL) { 602*7c478bd9Sstevel@tonic-gate pdesc_slab_t slab; 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate /* Read in pdesc_slab_t */ 605*7c478bd9Sstevel@tonic-gate if (mdb_vread(&slab, sizeof (slab), wsp->walk_addr) == -1) { 606*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read pdesc_slab_t at %p", 607*7c478bd9Sstevel@tonic-gate wsp->walk_addr); 608*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate /* pdesc_slab_t head is inside multidata_t */ 612*7c478bd9Sstevel@tonic-gate q_head = (uintptr_t)VA_OFF(slab.pds_mmd, 613*7c478bd9Sstevel@tonic-gate offsetof(multidata_t, mmd_pd_slab_q)); 614*7c478bd9Sstevel@tonic-gate } else 615*7c478bd9Sstevel@tonic-gate q_head = wsp->walk_addr; 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate /* Pass it on to our generic ql_t walker init */ 618*7c478bd9Sstevel@tonic-gate return (mmdq_walk_init(wsp, "pdesc_slab_t", q_head, 619*7c478bd9Sstevel@tonic-gate sizeof (pdesc_slab_t), offsetof(pdesc_slab_t, pds_next))); 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate /* 623*7c478bd9Sstevel@tonic-gate * A dcmd which returns a multidata_t pointer from a pdesc_slab_t structure. 624*7c478bd9Sstevel@tonic-gate */ 625*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 626*7c478bd9Sstevel@tonic-gate int 627*7c478bd9Sstevel@tonic-gate slab2multidata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 628*7c478bd9Sstevel@tonic-gate { 629*7c478bd9Sstevel@tonic-gate pdesc_slab_t slab; 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || argc != 0) 632*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate if (mdb_vread(&slab, sizeof (slab), addr) == -1) { 635*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't read pdesc_slab_t at %p", addr); 636*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate mdb_printf("%p\n", slab.pds_mmd); 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 642*7c478bd9Sstevel@tonic-gate } 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate /* 645*7c478bd9Sstevel@tonic-gate * Packet descriptor (pdesc_t) walker initialization routine. 646*7c478bd9Sstevel@tonic-gate */ 647*7c478bd9Sstevel@tonic-gate int 648*7c478bd9Sstevel@tonic-gate pdesc_walk_init(mdb_walk_state_t *wsp) 649*7c478bd9Sstevel@tonic-gate { 650*7c478bd9Sstevel@tonic-gate uintptr_t q_head; 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL) 653*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate /* 656*7c478bd9Sstevel@tonic-gate * If we're called from multidata dcmd, then we're passed in 657*7c478bd9Sstevel@tonic-gate * the address of ql_t head; otherwise we'd have to get the 658*7c478bd9Sstevel@tonic-gate * address ourselves. 659*7c478bd9Sstevel@tonic-gate */ 660*7c478bd9Sstevel@tonic-gate if (wsp->walk_cbdata == NULL) { 661*7c478bd9Sstevel@tonic-gate pdesc_t pd; 662*7c478bd9Sstevel@tonic-gate pdesc_slab_t slab; 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate /* First we get pdsec_t */ 665*7c478bd9Sstevel@tonic-gate if (mdb_vread(&pd, sizeof (pd), wsp->walk_addr) == -1) { 666*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read pdesc_t at %p", 667*7c478bd9Sstevel@tonic-gate wsp->walk_addr); 668*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate /* And then the pdesc_slab_t */ 672*7c478bd9Sstevel@tonic-gate if (mdb_vread(&slab, sizeof (slab), 673*7c478bd9Sstevel@tonic-gate (uintptr_t)pd.pd_slab) == -1) { 674*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read pdesc_slab_t at %p", 675*7c478bd9Sstevel@tonic-gate (uintptr_t)pd.pd_slab); 676*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate /* pdesc_t head is inside multidata_t */ 680*7c478bd9Sstevel@tonic-gate q_head = (uintptr_t)VA_OFF(slab.pds_mmd, 681*7c478bd9Sstevel@tonic-gate offsetof(multidata_t, mmd_pd_q)); 682*7c478bd9Sstevel@tonic-gate } else 683*7c478bd9Sstevel@tonic-gate q_head = wsp->walk_addr; 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate /* Pass it on to our generic ql_t walker init */ 686*7c478bd9Sstevel@tonic-gate return (mmdq_walk_init(wsp, "pdesc_t", q_head, 687*7c478bd9Sstevel@tonic-gate sizeof (pdesc_t), offsetof(pdesc_t, pd_next))); 688*7c478bd9Sstevel@tonic-gate } 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate /* 691*7c478bd9Sstevel@tonic-gate * A dcmd which prints the attribute hash table. 692*7c478bd9Sstevel@tonic-gate */ 693*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 694*7c478bd9Sstevel@tonic-gate int 695*7c478bd9Sstevel@tonic-gate pattbl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 696*7c478bd9Sstevel@tonic-gate { 697*7c478bd9Sstevel@tonic-gate mmd_data_t data; 698*7c478bd9Sstevel@tonic-gate uint_t pattbl_sz; 699*7c478bd9Sstevel@tonic-gate int i, j; 700*7c478bd9Sstevel@tonic-gate 701*7c478bd9Sstevel@tonic-gate bzero(&data, sizeof (data)); 702*7c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || argc != 0) 703*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate /* Figure out the size of hash table */ 706*7c478bd9Sstevel@tonic-gate mdb_readvar(&pattbl_sz, "pattbl_sz"); 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 709*7c478bd9Sstevel@tonic-gate mdb_printf("%<b>%<u>%-3s %-16s %-16s %-12s %-3s %-16s %-5s%</u>%</b>\n", 710*7c478bd9Sstevel@tonic-gate "BKT", "PATBKT ADDR", "PATTR ADDR", "TYPE", "LEN", "BUF ADDR", 711*7c478bd9Sstevel@tonic-gate "FLAGS"); 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate /* Walk each bucket and print its contents */ 714*7c478bd9Sstevel@tonic-gate for (i = 0, j = 0; i < (pattbl_sz * sizeof (patbkt_t)); 715*7c478bd9Sstevel@tonic-gate i += sizeof (patbkt_t)) { 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate mdb_printf("%-3d %016p ", j++, addr + i); 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate if (mdb_pwalk("pattr", (mdb_walk_cb_t)pattr_print, &data, 720*7c478bd9Sstevel@tonic-gate addr + i + offsetof(patbkt_t, pbkt_pattr_q)) == -1) { 721*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk pattr_t list"); 722*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 725*7c478bd9Sstevel@tonic-gate } 726*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate typedef struct pattr_type_s { 732*7c478bd9Sstevel@tonic-gate char *name; /* attribute name */ 733*7c478bd9Sstevel@tonic-gate uint_t type; /* attribute type value */ 734*7c478bd9Sstevel@tonic-gate } pattr_type_t; 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate /* 737*7c478bd9Sstevel@tonic-gate * Generic packet attribute (pattr_t) counting routine. 738*7c478bd9Sstevel@tonic-gate */ 739*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 740*7c478bd9Sstevel@tonic-gate static int 741*7c478bd9Sstevel@tonic-gate pattr_count(uintptr_t addr, q_walk_t *qwp, mmd_data_t *data) 742*7c478bd9Sstevel@tonic-gate { 743*7c478bd9Sstevel@tonic-gate pattr_t pattr; 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate if (mdb_vread(&pattr, sizeof (pattr), addr) == -1) { 746*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read pattr_t at %p", addr); 747*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate if (pattr.pat_magic != PATTR_MAGIC) 751*7c478bd9Sstevel@tonic-gate mdb_printf("Incorrect pattr magic number at %p\n", 752*7c478bd9Sstevel@tonic-gate VA_OFF(addr, offsetof(pattr_t, pat_magic))); 753*7c478bd9Sstevel@tonic-gate 754*7c478bd9Sstevel@tonic-gate data->counter++; 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate return (WALK_NEXT); 757*7c478bd9Sstevel@tonic-gate } 758*7c478bd9Sstevel@tonic-gate 759*7c478bd9Sstevel@tonic-gate /* 760*7c478bd9Sstevel@tonic-gate * Print the contents of a packet attribute (pattr_t) structure. 761*7c478bd9Sstevel@tonic-gate */ 762*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 763*7c478bd9Sstevel@tonic-gate static int 764*7c478bd9Sstevel@tonic-gate pattr_print(uintptr_t addr, q_walk_t *qwp, mmd_data_t *data) 765*7c478bd9Sstevel@tonic-gate { 766*7c478bd9Sstevel@tonic-gate pattr_t pattr; 767*7c478bd9Sstevel@tonic-gate int i; 768*7c478bd9Sstevel@tonic-gate char *pa_name = "UNKNOWN"; 769*7c478bd9Sstevel@tonic-gate static const pattr_type_t pa_type[] = { 770*7c478bd9Sstevel@tonic-gate { "DSTADDRSAP", PATTR_DSTADDRSAP }, 771*7c478bd9Sstevel@tonic-gate { "SRCADDRSAP", PATTR_SRCADDRSAP }, 772*7c478bd9Sstevel@tonic-gate { "HCKSUM", PATTR_HCKSUM } 773*7c478bd9Sstevel@tonic-gate }; 774*7c478bd9Sstevel@tonic-gate static const mdb_bitmask_t pa_flags_bits[] = { 775*7c478bd9Sstevel@tonic-gate { "R", PATTR_REM_DEFER, PATTR_REM_DEFER }, 776*7c478bd9Sstevel@tonic-gate { "P", PATTR_PERSIST, PATTR_PERSIST }, 777*7c478bd9Sstevel@tonic-gate { NULL, 0, 0 } 778*7c478bd9Sstevel@tonic-gate }; 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate if (mdb_vread(&pattr, sizeof (pattr), addr) == -1) { 781*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read pattr_t at %p", addr); 782*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate if (pattr.pat_magic != PATTR_MAGIC) 786*7c478bd9Sstevel@tonic-gate mdb_printf("Incorrect pattr magic number at %p\n", 787*7c478bd9Sstevel@tonic-gate VA_OFF(addr, offsetof(pattr_t, pat_magic))); 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate /* Find a matching string */ 790*7c478bd9Sstevel@tonic-gate for (i = 0; i < (sizeof (pa_type) / sizeof (*pa_type)); i++) { 791*7c478bd9Sstevel@tonic-gate if (pa_type[i].type == pattr.pat_type) 792*7c478bd9Sstevel@tonic-gate pa_name = pa_type[i].name; 793*7c478bd9Sstevel@tonic-gate } 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate if (!qwp->qw_iprint) { 796*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 797*7c478bd9Sstevel@tonic-gate mdb_inc_indent(21); 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate mdb_printf("%016p %x:%-10s %-3d %016p %-5b", addr, pattr.pat_type, 801*7c478bd9Sstevel@tonic-gate pa_name, pattr.pat_buflen - sizeof (pattr), addr + sizeof (pattr), 802*7c478bd9Sstevel@tonic-gate pattr.pat_flags, pa_flags_bits); 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate if (!qwp->qw_iprint) 805*7c478bd9Sstevel@tonic-gate mdb_dec_indent(21); 806*7c478bd9Sstevel@tonic-gate else 807*7c478bd9Sstevel@tonic-gate qwp->qw_iprint = FALSE; 808*7c478bd9Sstevel@tonic-gate 809*7c478bd9Sstevel@tonic-gate return (WALK_NEXT); 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate /* 813*7c478bd9Sstevel@tonic-gate * Packet attribute (pattr_t) walker initialization routine. 814*7c478bd9Sstevel@tonic-gate */ 815*7c478bd9Sstevel@tonic-gate int 816*7c478bd9Sstevel@tonic-gate pattr_walk_init(mdb_walk_state_t *wsp) 817*7c478bd9Sstevel@tonic-gate { 818*7c478bd9Sstevel@tonic-gate uintptr_t q_head; 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL) 821*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate /* 824*7c478bd9Sstevel@tonic-gate * If we're called from pattbl dcmd, then we're passed in 825*7c478bd9Sstevel@tonic-gate * the address of ql_t head; otherwise we'd have to get the 826*7c478bd9Sstevel@tonic-gate * address ourselves. 827*7c478bd9Sstevel@tonic-gate */ 828*7c478bd9Sstevel@tonic-gate if (wsp->walk_cbdata == NULL) { 829*7c478bd9Sstevel@tonic-gate pattr_t pattr; 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate if (mdb_vread(&pattr, sizeof (pattr), wsp->walk_addr) == -1) { 832*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read pattr_t at %p", 833*7c478bd9Sstevel@tonic-gate wsp->walk_addr); 834*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 835*7c478bd9Sstevel@tonic-gate } 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate q_head = (uintptr_t)VA_OFF(pattr.pat_lock, 838*7c478bd9Sstevel@tonic-gate -offsetof(patbkt_t, pbkt_lock)) + 839*7c478bd9Sstevel@tonic-gate offsetof(patbkt_t, pbkt_pattr_q); 840*7c478bd9Sstevel@tonic-gate } else 841*7c478bd9Sstevel@tonic-gate q_head = wsp->walk_addr; 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate /* Pass it on to our generic ql_t walker init */ 844*7c478bd9Sstevel@tonic-gate return (mmdq_walk_init(wsp, "pattr_t", q_head, 845*7c478bd9Sstevel@tonic-gate sizeof (pattr_t), offsetof(pattr_t, pat_next))); 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate 848*7c478bd9Sstevel@tonic-gate /* 849*7c478bd9Sstevel@tonic-gate * A dcmd which returns a multidata_t pointer from a pattr_t. 850*7c478bd9Sstevel@tonic-gate */ 851*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 852*7c478bd9Sstevel@tonic-gate int 853*7c478bd9Sstevel@tonic-gate pattr2multidata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 854*7c478bd9Sstevel@tonic-gate { 855*7c478bd9Sstevel@tonic-gate pattr_t pattr; 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || argc != 0) 858*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate if (mdb_vread(&pattr, sizeof (pattr), addr) == -1) { 861*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't read pattr_t at %p", addr); 862*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate if (pattr.pat_magic != PATTR_MAGIC) { 866*7c478bd9Sstevel@tonic-gate mdb_warn("Incorrect pattr magic number at %p", 867*7c478bd9Sstevel@tonic-gate VA_OFF(addr, offsetof(pattr_t, pat_magic))); 868*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 869*7c478bd9Sstevel@tonic-gate } 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate mdb_printf("%p\n", pattr.pat_mmd); 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate /* 877*7c478bd9Sstevel@tonic-gate * A dcmd which returns a pdesc_slab_t from a pdesc_t. 878*7c478bd9Sstevel@tonic-gate */ 879*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 880*7c478bd9Sstevel@tonic-gate int 881*7c478bd9Sstevel@tonic-gate pdesc2slab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 882*7c478bd9Sstevel@tonic-gate { 883*7c478bd9Sstevel@tonic-gate pdesc_t pd; 884*7c478bd9Sstevel@tonic-gate 885*7c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || argc != 0) 886*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 887*7c478bd9Sstevel@tonic-gate 888*7c478bd9Sstevel@tonic-gate if (mdb_vread(&pd, sizeof (pd), addr) == -1) { 889*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't read pdesc_t at %p", addr); 890*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate if (pd.pd_magic != PDESC_MAGIC) { 894*7c478bd9Sstevel@tonic-gate mdb_warn("Incorrect pdesc magic number at %p", 895*7c478bd9Sstevel@tonic-gate VA_OFF(addr, offsetof(pdesc_t, pd_magic))); 896*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate mdb_printf("%p\n", pd.pd_slab); 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate /* 905*7c478bd9Sstevel@tonic-gate * A dcmd which verifies the integrity of a pdesc_t. 906*7c478bd9Sstevel@tonic-gate */ 907*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 908*7c478bd9Sstevel@tonic-gate int 909*7c478bd9Sstevel@tonic-gate pdesc_verify(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 910*7c478bd9Sstevel@tonic-gate { 911*7c478bd9Sstevel@tonic-gate multidata_t mmd; 912*7c478bd9Sstevel@tonic-gate pdesc_t pd; 913*7c478bd9Sstevel@tonic-gate pdescinfo_t *pdi = &pd.pd_pdi; 914*7c478bd9Sstevel@tonic-gate pdesc_slab_t slab; 915*7c478bd9Sstevel@tonic-gate mblk_t hbuf, pbuf[MULTIDATA_MAX_PBUFS]; 916*7c478bd9Sstevel@tonic-gate uint_t i, idx; 917*7c478bd9Sstevel@tonic-gate boolean_t valid = B_TRUE; 918*7c478bd9Sstevel@tonic-gate struct pld_ary_s *pa; 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || argc != 0) 921*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 922*7c478bd9Sstevel@tonic-gate 923*7c478bd9Sstevel@tonic-gate if (mdb_vread(&pd, sizeof (pd), addr) == -1) { 924*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't read pdesc_t at %p", addr); 925*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 926*7c478bd9Sstevel@tonic-gate } 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate if (pd.pd_magic != PDESC_MAGIC) { 929*7c478bd9Sstevel@tonic-gate mdb_warn("Incorrect pdesc magic number at %p\n", 930*7c478bd9Sstevel@tonic-gate VA_OFF(addr, offsetof(pdesc_t, pd_magic))); 931*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate if (mdb_vread(&slab, sizeof (slab), (uintptr_t)pd.pd_slab) == -1) { 935*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't read pdesc_slab_t at %p", pd.pd_slab); 936*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate if (mdb_vread(&mmd, sizeof (mmd), (uintptr_t)slab.pds_mmd) == -1) { 940*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't read multidata_t at %p", slab.pds_mmd); 941*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 942*7c478bd9Sstevel@tonic-gate } 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate if (mmd.mmd_magic != MULTIDATA_MAGIC) 945*7c478bd9Sstevel@tonic-gate mdb_printf("Incorrect Multidata magic number at %p\n", 946*7c478bd9Sstevel@tonic-gate VA_OFF(slab.pds_mmd, offsetof(multidata_t, mmd_magic))); 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate if (mmd.mmd_hbuf != 0 && 949*7c478bd9Sstevel@tonic-gate mdb_vread(&hbuf, sizeof (hbuf), (uintptr_t)mmd.mmd_hbuf) == -1) { 950*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't read mblk_t at %p", mmd.mmd_hbuf); 951*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 952*7c478bd9Sstevel@tonic-gate } 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate if (mmd.mmd_pbuf_cnt > MULTIDATA_MAX_PBUFS) { 955*7c478bd9Sstevel@tonic-gate mdb_warn("Multidata pbuf count exceeds %d\n", 956*7c478bd9Sstevel@tonic-gate MULTIDATA_MAX_PBUFS); 957*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 958*7c478bd9Sstevel@tonic-gate } else if (pdi->pld_cnt > mmd.mmd_pbuf_cnt) { 959*7c478bd9Sstevel@tonic-gate mdb_warn("descriptor pbuf count exceeds Multidata " 960*7c478bd9Sstevel@tonic-gate "pbuf count %d\n", mmd.mmd_pbuf_cnt); 961*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate if (mmd.mmd_pbuf_cnt > 0) { 965*7c478bd9Sstevel@tonic-gate for (i = 0; i < mmd.mmd_pbuf_cnt; i++) { 966*7c478bd9Sstevel@tonic-gate if (mdb_vread(&pbuf[i], sizeof (mblk_t), 967*7c478bd9Sstevel@tonic-gate (uintptr_t)mmd.mmd_pbuf[i]) == -1) { 968*7c478bd9Sstevel@tonic-gate mdb_warn("couldn't read mblk_t at %p", 969*7c478bd9Sstevel@tonic-gate mmd.mmd_pbuf[i]); 970*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 971*7c478bd9Sstevel@tonic-gate } 972*7c478bd9Sstevel@tonic-gate } 973*7c478bd9Sstevel@tonic-gate } 974*7c478bd9Sstevel@tonic-gate 975*7c478bd9Sstevel@tonic-gate /* It should have at least one buffer reference */ 976*7c478bd9Sstevel@tonic-gate if (!(pdi->flags & PDESC_HAS_REF)) { 977*7c478bd9Sstevel@tonic-gate mdb_warn("descriptor has no buffer reference indicator " 978*7c478bd9Sstevel@tonic-gate "in flags (0x%x)\n", pdi->flags); 979*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 980*7c478bd9Sstevel@tonic-gate } else if (!(pdi->flags & PDESC_PBUF_REF) && pdi->pld_cnt > 0) { 981*7c478bd9Sstevel@tonic-gate mdb_warn("descriptor has no pbuf reference indicator in " 982*7c478bd9Sstevel@tonic-gate "flags (0x%x); but pld_cnt is %d\n", pdi->flags, 983*7c478bd9Sstevel@tonic-gate pdi->pld_cnt); 984*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 985*7c478bd9Sstevel@tonic-gate } 986*7c478bd9Sstevel@tonic-gate 987*7c478bd9Sstevel@tonic-gate /* Bounds check the header fragment, if any */ 988*7c478bd9Sstevel@tonic-gate if (!((pdi->flags & PDESC_HBUF_REF) && pdi->hdr_rptr != 0 && 989*7c478bd9Sstevel@tonic-gate pdi->hdr_wptr != 0 && pdi->hdr_base != 0 && 990*7c478bd9Sstevel@tonic-gate pdi->hdr_lim != 0 && pdi->hdr_lim >= pdi->hdr_base && 991*7c478bd9Sstevel@tonic-gate pdi->hdr_wptr >= pdi->hdr_rptr && pdi->hdr_base <= pdi->hdr_rptr && 992*7c478bd9Sstevel@tonic-gate pdi->hdr_lim >= pdi->hdr_wptr && pdi->hdr_base >= hbuf.b_rptr && 993*7c478bd9Sstevel@tonic-gate MBLKIN(&hbuf, (pdi->hdr_base - hbuf.b_rptr), 994*7c478bd9Sstevel@tonic-gate PDESC_HDRSIZE(pdi)))) { 995*7c478bd9Sstevel@tonic-gate mdb_warn("descriptor has invalid header fragment\n"); 996*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 997*7c478bd9Sstevel@tonic-gate } 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate i = 0; 1000*7c478bd9Sstevel@tonic-gate pa = &pdi->pld_ary[0]; 1001*7c478bd9Sstevel@tonic-gate /* Bounds check the payload fragment, if any */ 1002*7c478bd9Sstevel@tonic-gate while (valid && i < pdi->pld_cnt) { 1003*7c478bd9Sstevel@tonic-gate valid = (((idx = pa->pld_pbuf_idx) < mmd.mmd_pbuf_cnt) && 1004*7c478bd9Sstevel@tonic-gate pa->pld_rptr != NULL && pa->pld_wptr != NULL && 1005*7c478bd9Sstevel@tonic-gate pa->pld_wptr >= pa->pld_rptr && 1006*7c478bd9Sstevel@tonic-gate pa->pld_rptr >= pbuf[idx].b_rptr && 1007*7c478bd9Sstevel@tonic-gate MBLKIN(&pbuf[idx], (pa->pld_rptr - pbuf[idx].b_rptr), 1008*7c478bd9Sstevel@tonic-gate PDESC_PLD_SPAN_SIZE(pdi, i))); 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate if (!valid) { 1011*7c478bd9Sstevel@tonic-gate mdb_warn("descriptor has invalid payload fragment\n"); 1012*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 1013*7c478bd9Sstevel@tonic-gate } 1014*7c478bd9Sstevel@tonic-gate 1015*7c478bd9Sstevel@tonic-gate /* advance to next entry */ 1016*7c478bd9Sstevel@tonic-gate i++; 1017*7c478bd9Sstevel@tonic-gate pa++; 1018*7c478bd9Sstevel@tonic-gate } 1019*7c478bd9Sstevel@tonic-gate 1020*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 1021*7c478bd9Sstevel@tonic-gate } 1022