1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/time.h> 30 #include <sys/sysmacros.h> 31 #include <ctype.h> 32 #include <sys/mdb_modapi.h> 33 #include <sys/mach_descrip.h> 34 #include <sys/mdesc.h> 35 #include <sys/mdesc_impl.h> 36 37 /*ARGSUSED*/ 38 int 39 mdhdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 40 { 41 uint_t verbose = 0; 42 uintptr_t mdp; 43 machine_descrip_t md; 44 45 if (flags & DCMD_ADDRSPEC) 46 return (DCMD_USAGE); 47 48 if (mdb_getopts(argc, argv, 49 'v', MDB_OPT_SETBITS, 1, &verbose, NULL) != argc) 50 return (DCMD_USAGE); 51 52 /* curr_mach_descrip normally points to /dev/mdesc */ 53 if (mdb_readvar(&mdp, "curr_mach_descrip") == -1) { 54 mdb_warn("failed to read 'curr_mach_descrip'"); 55 return (DCMD_ERR); 56 } 57 58 if (verbose) 59 mdb_printf("ADDRESS VA MEMOPS SIZE\n"); 60 61 do { 62 if (mdb_vread(&md, sizeof (md), mdp) == -1) { 63 mdb_warn("failed to read machine_descrip_t at %p", mdp); 64 return (DCMD_ERR); 65 } 66 67 if (verbose) 68 mdb_printf("%-11lx %-11lx %-11lx %-11lx\n", 69 mdp, md.va, md.memops, md.size); 70 else 71 mdb_printf("%p\n", mdp); 72 73 } while ((mdp = (uintptr_t)md.next) != NULL); 74 75 return (DCMD_OK); 76 } 77 78 /*ARGSUSED*/ 79 int 80 mdinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 81 { 82 md_header_t mh; 83 machine_descrip_t md; 84 md_element_t *mdep; 85 char *namep; 86 uint8_t *datap; 87 int mdesize, namesize, datasize; 88 uintptr_t mdp; 89 md_element_t *mdeptr, *eof; 90 uintptr_t vaddr; 91 92 if (flags & DCMD_ADDRSPEC) { 93 if ((addr & 7) != 0) { 94 mdb_warn("misaligned address at %p", addr); 95 return (DCMD_ERR); 96 } 97 vaddr = addr; 98 } else { 99 /* curr_mach_descrip normally points to /dev/mdesc */ 100 if (mdb_readvar(&mdp, "curr_mach_descrip") == -1) { 101 mdb_warn("failed to read 'curr_mach_descrip'"); 102 return (DCMD_ERR); 103 } 104 if (mdb_vread(&md, sizeof (md), mdp) == -1) { 105 mdb_warn("failed to read machine_descrip_t at %p", mdp); 106 return (DCMD_ERR); 107 } 108 vaddr = (uintptr_t)md.va; 109 } 110 111 if (mdb_vread(&mh, sizeof (mh), vaddr) == -1) { 112 mdb_warn("failed to read md_header_t at %p", vaddr); 113 return (DCMD_ERR); 114 } 115 116 mdesize = mh.node_blk_sz; 117 namesize = mh.name_blk_sz; 118 datasize = mh.data_blk_sz; 119 120 /* find space for each section of the MD */ 121 if ((mdep = mdb_alloc(mdesize, UM_NOSLEEP)) == NULL) { 122 mdb_warn("failed to allocate memory for mde block"); 123 return (DCMD_ERR); 124 } 125 if ((namep = mdb_alloc(namesize, UM_NOSLEEP)) == NULL) { 126 mdb_warn("failed to allocate memory for name block"); 127 mdb_free(mdep, mdesize); 128 return (DCMD_ERR); 129 } 130 if ((datap = mdb_alloc(datasize, UM_NOSLEEP)) == NULL) { 131 mdb_warn("failed to allocate memory for data block"); 132 mdb_free(namep, namesize); 133 mdb_free(mdep, mdesize); 134 return (DCMD_ERR); 135 } 136 137 /* store each of the MD sections */ 138 if (mdb_vread(mdep, mdesize, vaddr + MD_HEADER_SIZE) != mdesize) { 139 mdb_warn("failed to read node block %p", vaddr 140 + MD_HEADER_SIZE); 141 mdb_free(datap, datasize); 142 mdb_free(namep, namesize); 143 mdb_free(mdep, mdesize); 144 return (DCMD_ERR); 145 } 146 if (mdb_vread(namep, namesize, vaddr + MD_HEADER_SIZE + mdesize) 147 != namesize) { 148 mdb_warn("failed to read node block %p", vaddr + MD_HEADER_SIZE 149 + mdesize); 150 mdb_free(datap, datasize); 151 mdb_free(namep, namesize); 152 mdb_free(mdep, mdesize); 153 return (DCMD_ERR); 154 } 155 if (mdb_vread(datap, datasize, vaddr + MD_HEADER_SIZE + mdesize 156 + namesize) != datasize) { 157 mdb_warn("failed to read node block %p", vaddr + MD_HEADER_SIZE 158 + mdesize + namesize); 159 mdb_free(datap, datasize); 160 mdb_free(namep, namesize); 161 mdb_free(mdep, mdesize); 162 return (DCMD_ERR); 163 } 164 165 mdb_printf("TYPE OFFSET NAME PROPERTY\n"); 166 eof = mdep + (mdesize / sizeof (md_element_t)); 167 for (mdeptr = mdep; mdeptr < eof; ++mdeptr) { 168 switch (MDE_TAG(mdeptr)) { 169 case MDET_NODE: 170 mdb_printf("node %-6x %-22s idx=%-11lx\n", 171 MDE_NAME(mdeptr), namep + mdeptr->name_offset, 172 MDE_PROP_INDEX(mdeptr)); 173 break; 174 case MDET_PROP_ARC: 175 mdb_printf("arc %-6x %-22s idx=%-11lx\n", 176 MDE_NAME(mdeptr), namep + mdeptr->name_offset, 177 MDE_PROP_INDEX(mdeptr)); 178 break; 179 case MDET_PROP_DAT: 180 mdb_printf("data %-6x %-22s len=%x, offset=%x\n", 181 MDE_NAME(mdeptr), namep + mdeptr->name_offset, 182 MDE_PROP_DATA_LEN(mdeptr), 183 MDE_PROP_DATA_OFFSET(mdeptr)); 184 break; 185 case MDET_PROP_STR: 186 mdb_printf("str %-6x %-22s len=%x, offset=%x\n", 187 MDE_NAME(mdeptr), namep + mdeptr->name_offset, 188 MDE_PROP_DATA_LEN(mdeptr), 189 MDE_PROP_DATA_OFFSET(mdeptr)); 190 break; 191 case MDET_PROP_VAL: 192 mdb_printf("val %-6x %-22s val=%-11lx\n", 193 MDE_NAME(mdeptr), namep + mdeptr->name_offset, 194 MDE_PROP_VALUE(mdeptr)); 195 break; 196 case MDET_NODE_END: 197 mdb_printf("end\n"); 198 break; 199 case MDET_NULL: 200 mdb_printf("null\n"); 201 break; 202 case MDET_LIST_END: 203 mdb_printf("end of list\n"); 204 break; 205 default: 206 mdb_printf("unkown tag=%x\n", MDE_TAG(mdeptr)); 207 break; 208 } 209 } 210 211 mdb_free(datap, datasize); 212 mdb_free(namep, namesize); 213 mdb_free(mdep, mdesize); 214 return (DCMD_OK); 215 } 216 217 /*ARGSUSED*/ 218 int 219 mdformat(uintptr_t addr, int size, int indent) 220 { 221 mdb_inc_indent(indent); 222 if (mdb_dumpptr((uintptr_t)addr, size, 223 MDB_DUMP_RELATIVE | MDB_DUMP_TRIM | MDB_DUMP_ASCII | 224 MDB_DUMP_HEADER | MDB_DUMP_GROUP(4), 225 (mdb_dumpptr_cb_t)mdb_vread, NULL)) { 226 mdb_dec_indent(indent); 227 return (DCMD_ERR); 228 } 229 mdb_dec_indent(indent); 230 return (DCMD_OK); 231 } 232 233 /*ARGSUSED*/ 234 int 235 mddump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 236 { 237 uintptr_t mdp, mdep, namep, datap; 238 machine_descrip_t md; 239 md_header_t mh; 240 uintptr_t vaddr; 241 242 if (flags & DCMD_ADDRSPEC) { 243 if ((addr & 7) != 0) { 244 mdb_warn("misaligned address at %p", addr); 245 return (DCMD_ERR); 246 } 247 vaddr = addr; 248 } else { 249 /* curr_mach_descrip normally points to /dev/mdesc */ 250 if (mdb_readvar(&mdp, "curr_mach_descrip") == -1) { 251 mdb_warn("failed to read 'curr_mach_descrip'"); 252 return (DCMD_ERR); 253 } 254 if (mdb_vread(&md, sizeof (md), mdp) == -1) { 255 mdb_warn("failed to read machine_descrip_t at %p", mdp); 256 return (DCMD_ERR); 257 } 258 vaddr = (uintptr_t)md.va; 259 } 260 261 if (mdb_vread(&mh, sizeof (mh), (uintptr_t)vaddr) == -1) { 262 mdb_warn("failed to read md_header_t at %p", vaddr); 263 return (DCMD_ERR); 264 } 265 266 mdep = (uintptr_t)vaddr + MD_HEADER_SIZE; 267 namep = mdep + mh.node_blk_sz; 268 datap = namep + mh.name_blk_sz; 269 270 mdb_printf("header (md_header_t) section at %lx:\n", vaddr); 271 if (mdformat((uintptr_t)md.va, MD_HEADER_SIZE, 4) != DCMD_OK) 272 return (DCMD_ERR); 273 274 mdb_printf("\nnode (md_element_t) section at %lx:\n", mdep); 275 if (mdformat(mdep, mh.node_blk_sz, 2) != DCMD_OK) 276 return (DCMD_ERR); 277 278 mdb_printf("\nname section at %lx:\n", namep); 279 if (mdformat(namep, mh.name_blk_sz, 2) != DCMD_OK) 280 return (DCMD_ERR); 281 282 mdb_printf("\ndata section at %lx:\n", datap); 283 if (mdformat(datap, mh.data_blk_sz, 2) != DCMD_OK) 284 return (DCMD_ERR); 285 286 return (DCMD_OK); 287 } 288 289 /* 290 * MDB module linkage information: 291 * 292 * Declare a list of structures describing dcmds, and a function 293 * named _mdb_init to return a pointer to module information. 294 */ 295 296 static const mdb_dcmd_t dcmds[] = { 297 { "mdeschdr", "[-v]", "addr of current sun4v MD header", mdhdr }, 298 { "mdescinfo", "?", "print md_elements with names from sun4v MD", 299 mdinfo }, 300 { "mdescdump", "?", "dump node, name, data sections of sun4v MD", 301 mddump }, 302 { NULL } 303 }; 304 305 static const mdb_modinfo_t modinfo = { 306 MDB_API_VERSION, dcmds, NULL 307 }; 308 309 const mdb_modinfo_t * 310 _mdb_init(void) 311 { 312 return (&modinfo); 313 } 314