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