xref: /titanic_51/usr/src/cmd/mdb/sun4v/modules/mdesc/mdesc.c (revision d583b39bfb4e2571d3e41097c5c357ffe353ad45)
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