10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*8111SJordan.Vaughan@Sun.com  * Common Development and Distribution License (the "License").
6*8111SJordan.Vaughan@Sun.com  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*8111SJordan.Vaughan@Sun.com  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <mdb/mdb_param.h>
270Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
280Sstevel@tonic-gate #include <mdb/mdb_ks.h>
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include "zone.h"
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <stddef.h>
330Sstevel@tonic-gate #include <sys/zone.h>
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #define	ZONE_NAMELEN	20
360Sstevel@tonic-gate #ifdef _LP64
370Sstevel@tonic-gate #define	ZONE_PATHLEN	32
380Sstevel@tonic-gate #else
390Sstevel@tonic-gate #define	ZONE_PATHLEN	40
400Sstevel@tonic-gate #endif
410Sstevel@tonic-gate 
420Sstevel@tonic-gate int
430Sstevel@tonic-gate zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
440Sstevel@tonic-gate {
450Sstevel@tonic-gate 	zone_t zn;
460Sstevel@tonic-gate 	char name[ZONE_NAMELEN];
470Sstevel@tonic-gate 	char path[ZONE_PATHLEN];
480Sstevel@tonic-gate 	int len;
490Sstevel@tonic-gate 
500Sstevel@tonic-gate 	if (argc != 0)
510Sstevel@tonic-gate 		return (DCMD_USAGE);
520Sstevel@tonic-gate 
530Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
540Sstevel@tonic-gate 		if (mdb_walk_dcmd("zone", "zone", argc, argv) == -1) {
550Sstevel@tonic-gate 			mdb_warn("can't walk zones");
560Sstevel@tonic-gate 			return (DCMD_ERR);
570Sstevel@tonic-gate 		}
580Sstevel@tonic-gate 		return (DCMD_OK);
590Sstevel@tonic-gate 	}
600Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags)) {
610Sstevel@tonic-gate 		mdb_printf("%<u>%?s %6s %-20s %-s%</u>\n",
620Sstevel@tonic-gate 		    "ADDR", "ID", "NAME", "PATH");
630Sstevel@tonic-gate 	}
640Sstevel@tonic-gate 	if (mdb_vread(&zn, sizeof (zone_t), addr) == -1) {
650Sstevel@tonic-gate 		mdb_warn("can't read zone_t structure at %p", addr);
660Sstevel@tonic-gate 		return (DCMD_ERR);
670Sstevel@tonic-gate 	}
680Sstevel@tonic-gate 	len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zn.zone_name);
690Sstevel@tonic-gate 	if (len > 0) {
700Sstevel@tonic-gate 		if (len == ZONE_NAMELEN)
710Sstevel@tonic-gate 			(void) strcpy(&name[len - 4], "...");
720Sstevel@tonic-gate 	} else {
730Sstevel@tonic-gate 		(void) strcpy(name, "??");
740Sstevel@tonic-gate 	}
750Sstevel@tonic-gate 	len = mdb_readstr(path, ZONE_PATHLEN, (uintptr_t)zn.zone_rootpath);
760Sstevel@tonic-gate 	if (len > 0) {
770Sstevel@tonic-gate 		if (len == ZONE_PATHLEN)
780Sstevel@tonic-gate 			(void) strcpy(&path[len - 4], "...");
790Sstevel@tonic-gate 	} else {
800Sstevel@tonic-gate 		(void) strcpy(path, "??");
810Sstevel@tonic-gate 	}
820Sstevel@tonic-gate 	mdb_printf("%0?p %6d %-20s %s\n", addr, zn.zone_id, name, path);
830Sstevel@tonic-gate 	return (DCMD_OK);
840Sstevel@tonic-gate }
850Sstevel@tonic-gate 
860Sstevel@tonic-gate int
870Sstevel@tonic-gate zone_walk_init(mdb_walk_state_t *wsp)
880Sstevel@tonic-gate {
890Sstevel@tonic-gate 	GElf_Sym sym;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	if (wsp->walk_addr == NULL) {
920Sstevel@tonic-gate 		if (mdb_lookup_by_name("zone_active", &sym) == -1) {
930Sstevel@tonic-gate 			mdb_warn("failed to find 'zone_active'");
940Sstevel@tonic-gate 			return (WALK_ERR);
950Sstevel@tonic-gate 		}
960Sstevel@tonic-gate 		wsp->walk_addr = (uintptr_t)sym.st_value;
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate 	if (mdb_layered_walk("list", wsp) == -1) {
990Sstevel@tonic-gate 		mdb_warn("couldn't walk 'list'");
1000Sstevel@tonic-gate 		return (WALK_ERR);
1010Sstevel@tonic-gate 	}
1020Sstevel@tonic-gate 	return (WALK_NEXT);
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate int
1060Sstevel@tonic-gate zone_walk_step(mdb_walk_state_t *wsp)
1070Sstevel@tonic-gate {
1080Sstevel@tonic-gate 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
109*8111SJordan.Vaughan@Sun.com 	    wsp->walk_cbdata));
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate int
1130Sstevel@tonic-gate zsd_walk_init(mdb_walk_state_t *wsp)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate 	if (wsp->walk_addr == NULL) {
1160Sstevel@tonic-gate 		mdb_warn("global walk not supported\n");
1170Sstevel@tonic-gate 		return (WALK_ERR);
1180Sstevel@tonic-gate 	}
1190Sstevel@tonic-gate 	wsp->walk_addr += offsetof(struct zone, zone_zsd);
1200Sstevel@tonic-gate 	if (mdb_layered_walk("list", wsp) == -1) {
1210Sstevel@tonic-gate 		mdb_warn("couldn't walk 'list'");
1220Sstevel@tonic-gate 		return (WALK_ERR);
1230Sstevel@tonic-gate 	}
1240Sstevel@tonic-gate 	return (WALK_NEXT);
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate int
1280Sstevel@tonic-gate zsd_walk_step(mdb_walk_state_t *wsp)
1290Sstevel@tonic-gate {
1300Sstevel@tonic-gate 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
131*8111SJordan.Vaughan@Sun.com 	    wsp->walk_cbdata));
1320Sstevel@tonic-gate }
1330Sstevel@tonic-gate 
134*8111SJordan.Vaughan@Sun.com /*
135*8111SJordan.Vaughan@Sun.com  * Helper structure used when walking ZSD entries via zsd().
136*8111SJordan.Vaughan@Sun.com  */
1370Sstevel@tonic-gate struct zsd_cb_data {
138*8111SJordan.Vaughan@Sun.com 	uint_t		keygiven;	/* Was a key specified (are we */
139*8111SJordan.Vaughan@Sun.com 					/* searching for a specific ZSD */
140*8111SJordan.Vaughan@Sun.com 					/* entry)? */
141*8111SJordan.Vaughan@Sun.com 	zone_key_t	key;		/* Key of ZSD for which we're looking */
142*8111SJordan.Vaughan@Sun.com 	uint_t		found;		/* Was the specific ZSD entry found? */
143*8111SJordan.Vaughan@Sun.com 	uint_t		voptgiven;	/* Display verbose information? */
1440Sstevel@tonic-gate };
1450Sstevel@tonic-gate 
146*8111SJordan.Vaughan@Sun.com /*
147*8111SJordan.Vaughan@Sun.com  * Helper function for zsd() that displays information from a single ZSD struct.
148*8111SJordan.Vaughan@Sun.com  * 'datap' must point to a valid zsd_cb_data struct.
149*8111SJordan.Vaughan@Sun.com  */
1500Sstevel@tonic-gate /* ARGSUSED */
1510Sstevel@tonic-gate static int
152*8111SJordan.Vaughan@Sun.com zsd_print(uintptr_t addrp, const void * datap, void * privatep)
1530Sstevel@tonic-gate {
154*8111SJordan.Vaughan@Sun.com 	struct zsd_entry entry;
155*8111SJordan.Vaughan@Sun.com 	struct zsd_cb_data *cbdp;
1560Sstevel@tonic-gate 
157*8111SJordan.Vaughan@Sun.com 	if (mdb_vread(&entry, sizeof (entry), addrp) == -1) {
158*8111SJordan.Vaughan@Sun.com 		mdb_warn("couldn't read zsd_entry at %p", addrp);
1590Sstevel@tonic-gate 		return (WALK_ERR);
1600Sstevel@tonic-gate 	}
161*8111SJordan.Vaughan@Sun.com 	cbdp = (struct zsd_cb_data *)privatep;
162*8111SJordan.Vaughan@Sun.com 
163*8111SJordan.Vaughan@Sun.com 	/*
164*8111SJordan.Vaughan@Sun.com 	 * Are we looking for a single entry specified by a key?  Then make sure
165*8111SJordan.Vaughan@Sun.com 	 * that the current ZSD's key is what we're looking for.
166*8111SJordan.Vaughan@Sun.com 	 */
167*8111SJordan.Vaughan@Sun.com 	if (cbdp->keygiven == TRUE && cbdp->key != entry.zsd_key)
1680Sstevel@tonic-gate 		return (WALK_NEXT);
169*8111SJordan.Vaughan@Sun.com 
170*8111SJordan.Vaughan@Sun.com 	mdb_printf("%?x %0?p %8x\n", entry.zsd_key, entry.zsd_data,
171*8111SJordan.Vaughan@Sun.com 	    entry.zsd_flags);
172*8111SJordan.Vaughan@Sun.com 	if (cbdp->voptgiven == TRUE)
173*8111SJordan.Vaughan@Sun.com 		mdb_printf("    Create CB:   %a\n    Shutdown CB: %a\n"
174*8111SJordan.Vaughan@Sun.com 		    "    Destroy CB:  %a\n", entry.zsd_create,
175*8111SJordan.Vaughan@Sun.com 		    entry.zsd_shutdown, entry.zsd_destroy);
176*8111SJordan.Vaughan@Sun.com 	if (cbdp->keygiven == TRUE) {
177*8111SJordan.Vaughan@Sun.com 		cbdp->found = TRUE;
178*8111SJordan.Vaughan@Sun.com 		return (WALK_DONE);
179*8111SJordan.Vaughan@Sun.com 	}
180*8111SJordan.Vaughan@Sun.com 	return (WALK_NEXT);
1810Sstevel@tonic-gate }
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate int
1840Sstevel@tonic-gate zsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1850Sstevel@tonic-gate {
1860Sstevel@tonic-gate 	zone_t zone;
187*8111SJordan.Vaughan@Sun.com 	const mdb_arg_t *argp;
188*8111SJordan.Vaughan@Sun.com 	int argcindex;
1890Sstevel@tonic-gate 	struct zsd_cb_data cbd;
190*8111SJordan.Vaughan@Sun.com 	char name[ZONE_NAMELEN];
191*8111SJordan.Vaughan@Sun.com 	int len;
1920Sstevel@tonic-gate 
193*8111SJordan.Vaughan@Sun.com 	/*
194*8111SJordan.Vaughan@Sun.com 	 * Walk all zones if necessary.
195*8111SJordan.Vaughan@Sun.com 	 */
196*8111SJordan.Vaughan@Sun.com 	if (argc > 2)
197*8111SJordan.Vaughan@Sun.com 		return (DCMD_USAGE);
1980Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) == 0) {
199*8111SJordan.Vaughan@Sun.com 		if (mdb_walk_dcmd("zone", "zsd", argc, argv) == -1) {
200*8111SJordan.Vaughan@Sun.com 			mdb_warn("failed to walk zone\n");
201*8111SJordan.Vaughan@Sun.com 			return (DCMD_ERR);
202*8111SJordan.Vaughan@Sun.com 		}
203*8111SJordan.Vaughan@Sun.com 		return (DCMD_OK);
204*8111SJordan.Vaughan@Sun.com 	}
205*8111SJordan.Vaughan@Sun.com 
206*8111SJordan.Vaughan@Sun.com 	/*
207*8111SJordan.Vaughan@Sun.com 	 * Make sure a zone_t can be read from the specified address.
208*8111SJordan.Vaughan@Sun.com 	 */
209*8111SJordan.Vaughan@Sun.com 	if (mdb_vread(&zone, sizeof (zone), addr) == -1) {
210*8111SJordan.Vaughan@Sun.com 		mdb_warn("couldn't read zone_t at %p", (void *)addr);
2110Sstevel@tonic-gate 		return (DCMD_ERR);
2120Sstevel@tonic-gate 	}
213*8111SJordan.Vaughan@Sun.com 
214*8111SJordan.Vaughan@Sun.com 	/*
215*8111SJordan.Vaughan@Sun.com 	 * Get the optional arguments (key or -v or both).  Note that
216*8111SJordan.Vaughan@Sun.com 	 * mdb_getopts() will not parse a key argument because it is not
217*8111SJordan.Vaughan@Sun.com 	 * preceded by an option letter.  We'll get around this by requiring
218*8111SJordan.Vaughan@Sun.com 	 * that all options precede the optional key argument.
219*8111SJordan.Vaughan@Sun.com 	 */
220*8111SJordan.Vaughan@Sun.com 	cbd.keygiven = FALSE;
221*8111SJordan.Vaughan@Sun.com 	cbd.voptgiven = FALSE;
222*8111SJordan.Vaughan@Sun.com 	if (argc > 0 && (argcindex = mdb_getopts(argc, argv, 'v',
223*8111SJordan.Vaughan@Sun.com 	    MDB_OPT_SETBITS, TRUE, &cbd.voptgiven, NULL)) != argc) {
224*8111SJordan.Vaughan@Sun.com 		/*
225*8111SJordan.Vaughan@Sun.com 		 * No options may appear after the key.
226*8111SJordan.Vaughan@Sun.com 		 */
227*8111SJordan.Vaughan@Sun.com 		if (argcindex != argc - 1)
228*8111SJordan.Vaughan@Sun.com 			return (DCMD_USAGE);
229*8111SJordan.Vaughan@Sun.com 
230*8111SJordan.Vaughan@Sun.com 		/*
231*8111SJordan.Vaughan@Sun.com 		 * The missed argument should be a key.
232*8111SJordan.Vaughan@Sun.com 		 */
233*8111SJordan.Vaughan@Sun.com 		argp = &argv[argcindex];
234*8111SJordan.Vaughan@Sun.com 		if (argp->a_type == MDB_TYPE_IMMEDIATE)
235*8111SJordan.Vaughan@Sun.com 			cbd.key = argp->a_un.a_val;
236*8111SJordan.Vaughan@Sun.com 		else
237*8111SJordan.Vaughan@Sun.com 			cbd.key = mdb_strtoull(argp->a_un.a_str);
238*8111SJordan.Vaughan@Sun.com 		cbd.keygiven = TRUE;
239*8111SJordan.Vaughan@Sun.com 		cbd.found = FALSE;
240*8111SJordan.Vaughan@Sun.com 	}
241*8111SJordan.Vaughan@Sun.com 
242*8111SJordan.Vaughan@Sun.com 	/*
243*8111SJordan.Vaughan@Sun.com 	 * Prepare to output the specified zone's ZSD information.
244*8111SJordan.Vaughan@Sun.com 	 */
245*8111SJordan.Vaughan@Sun.com 	if (DCMD_HDRSPEC(flags))
246*8111SJordan.Vaughan@Sun.com 		mdb_printf("%<u>%-20s %?s %?s %8s%</u>\n", "ZONE", "KEY",
247*8111SJordan.Vaughan@Sun.com 		    "VALUE", "FLAGS");
248*8111SJordan.Vaughan@Sun.com 	len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zone.zone_name);
249*8111SJordan.Vaughan@Sun.com 	if (len > 0) {
250*8111SJordan.Vaughan@Sun.com 		if (len == ZONE_NAMELEN)
251*8111SJordan.Vaughan@Sun.com 			(void) strcpy(&name[len - 4], "...");
252*8111SJordan.Vaughan@Sun.com 	} else {
253*8111SJordan.Vaughan@Sun.com 		(void) strcpy(name, "??");
254*8111SJordan.Vaughan@Sun.com 	}
255*8111SJordan.Vaughan@Sun.com 	mdb_printf("%-20s ", name);
256*8111SJordan.Vaughan@Sun.com 
257*8111SJordan.Vaughan@Sun.com 	/*
258*8111SJordan.Vaughan@Sun.com 	 * Display the requested ZSD entries.
259*8111SJordan.Vaughan@Sun.com 	 */
260*8111SJordan.Vaughan@Sun.com 	mdb_inc_indent(21);
261*8111SJordan.Vaughan@Sun.com 	if (mdb_pwalk("zsd", zsd_print, &cbd, addr) != 0) {
262*8111SJordan.Vaughan@Sun.com 		mdb_warn("failed to walk zsd\n");
263*8111SJordan.Vaughan@Sun.com 		mdb_dec_indent(21);
2640Sstevel@tonic-gate 		return (DCMD_ERR);
2650Sstevel@tonic-gate 	}
266*8111SJordan.Vaughan@Sun.com 	if (cbd.keygiven == TRUE && cbd.found == FALSE) {
267*8111SJordan.Vaughan@Sun.com 		mdb_printf("no corresponding ZSD entry found\n");
268*8111SJordan.Vaughan@Sun.com 		mdb_dec_indent(21);
2690Sstevel@tonic-gate 		return (DCMD_ERR);
2700Sstevel@tonic-gate 	}
271*8111SJordan.Vaughan@Sun.com 	mdb_dec_indent(21);
2720Sstevel@tonic-gate 	return (DCMD_OK);
2730Sstevel@tonic-gate }
274