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
mdhdr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
mdinfo(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
mdformat(uintptr_t addr,int size,int indent)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
mddump(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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 *
_mdb_init(void)310 _mdb_init(void)
311 {
312 return (&modinfo);
313 }
314