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