1*4c06356bSdh142964 /*
2*4c06356bSdh142964 * CDDL HEADER START
3*4c06356bSdh142964 *
4*4c06356bSdh142964 * The contents of this file are subject to the terms of the
5*4c06356bSdh142964 * Common Development and Distribution License (the "License").
6*4c06356bSdh142964 * You may not use this file except in compliance with the License.
7*4c06356bSdh142964 *
8*4c06356bSdh142964 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4c06356bSdh142964 * or http://www.opensolaris.org/os/licensing.
10*4c06356bSdh142964 * See the License for the specific language governing permissions
11*4c06356bSdh142964 * and limitations under the License.
12*4c06356bSdh142964 *
13*4c06356bSdh142964 * When distributing Covered Code, include this CDDL HEADER in each
14*4c06356bSdh142964 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4c06356bSdh142964 * If applicable, add the following below this CDDL HEADER, with the
16*4c06356bSdh142964 * fields enclosed by brackets "[]" replaced with your own identifying
17*4c06356bSdh142964 * information: Portions Copyright [yyyy] [name of copyright owner]
18*4c06356bSdh142964 *
19*4c06356bSdh142964 * CDDL HEADER END
20*4c06356bSdh142964 */
21*4c06356bSdh142964 /*
22*4c06356bSdh142964 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23*4c06356bSdh142964 * Use is subject to license terms.
24*4c06356bSdh142964 */
25*4c06356bSdh142964
26*4c06356bSdh142964 #include <mdb/mdb_modapi.h>
27*4c06356bSdh142964 #include <sys/bitset.h>
28*4c06356bSdh142964
29*4c06356bSdh142964 #include "bitset.h" /* XXX work out ifdef in include file... */
30*4c06356bSdh142964
31*4c06356bSdh142964 void
bitset_help(void)32*4c06356bSdh142964 bitset_help(void)
33*4c06356bSdh142964 {
34*4c06356bSdh142964 mdb_printf("Print the bitset at the address given\n");
35*4c06356bSdh142964 }
36*4c06356bSdh142964
37*4c06356bSdh142964 static void
bitset_free(bitset_t * bs)38*4c06356bSdh142964 bitset_free(bitset_t *bs)
39*4c06356bSdh142964 {
40*4c06356bSdh142964 if (bs == NULL)
41*4c06356bSdh142964 return;
42*4c06356bSdh142964 if (bs->bs_set && bs->bs_words)
43*4c06356bSdh142964 mdb_free(bs->bs_set, bs->bs_words * sizeof (ulong_t));
44*4c06356bSdh142964 mdb_free(bs, sizeof (*bs));
45*4c06356bSdh142964 }
46*4c06356bSdh142964
47*4c06356bSdh142964 static bitset_t *
bitset_get(uintptr_t bsaddr)48*4c06356bSdh142964 bitset_get(uintptr_t bsaddr)
49*4c06356bSdh142964 {
50*4c06356bSdh142964 bitset_t *bs;
51*4c06356bSdh142964
52*4c06356bSdh142964 bs = mdb_zalloc(sizeof (*bs), UM_SLEEP);
53*4c06356bSdh142964 if (mdb_vread(bs, sizeof (*bs), bsaddr) == -1) {
54*4c06356bSdh142964 mdb_warn("couldn't read bitset 0x%p", bsaddr);
55*4c06356bSdh142964 bitset_free(bs);
56*4c06356bSdh142964 return (NULL);
57*4c06356bSdh142964 }
58*4c06356bSdh142964
59*4c06356bSdh142964 bsaddr = (uintptr_t)bs->bs_set;
60*4c06356bSdh142964 bs->bs_set = mdb_alloc(bs->bs_words * sizeof (ulong_t), UM_SLEEP);
61*4c06356bSdh142964 if (mdb_vread(bs->bs_set,
62*4c06356bSdh142964 bs->bs_words * sizeof (ulong_t), bsaddr) == -1) {
63*4c06356bSdh142964 mdb_warn("couldn't read bitset bs_set 0x%p", bsaddr);
64*4c06356bSdh142964 bitset_free(bs);
65*4c06356bSdh142964 return (NULL);
66*4c06356bSdh142964 }
67*4c06356bSdh142964 return (bs);
68*4c06356bSdh142964
69*4c06356bSdh142964 }
70*4c06356bSdh142964
71*4c06356bSdh142964 static int
bitset_highbit(bitset_t * bs)72*4c06356bSdh142964 bitset_highbit(bitset_t *bs)
73*4c06356bSdh142964 {
74*4c06356bSdh142964 int high;
75*4c06356bSdh142964 int i;
76*4c06356bSdh142964
77*4c06356bSdh142964 if ((bs->bs_set == NULL) || (bs->bs_words == 0))
78*4c06356bSdh142964 return (-1);
79*4c06356bSdh142964
80*4c06356bSdh142964 /* move backwards through words */
81*4c06356bSdh142964 for (i = bs->bs_words; i >= 0; i--)
82*4c06356bSdh142964 if (bs->bs_set[i])
83*4c06356bSdh142964 break;
84*4c06356bSdh142964 if (i < 0)
85*4c06356bSdh142964 return (-1);
86*4c06356bSdh142964
87*4c06356bSdh142964 /* move backwards through bits */
88*4c06356bSdh142964 high = i << BT_ULSHIFT;
89*4c06356bSdh142964 for (i = BT_NBIPUL - 1; i; i--)
90*4c06356bSdh142964 if (BT_TEST(bs->bs_set, high + i))
91*4c06356bSdh142964 break;
92*4c06356bSdh142964 return (high + i + 1);
93*4c06356bSdh142964 }
94*4c06356bSdh142964
95*4c06356bSdh142964 static int
pow10(int exp)96*4c06356bSdh142964 pow10(int exp)
97*4c06356bSdh142964 {
98*4c06356bSdh142964 int res;
99*4c06356bSdh142964
100*4c06356bSdh142964 for (res = 1; exp; exp--)
101*4c06356bSdh142964 res *= 10;
102*4c06356bSdh142964 return (res);
103*4c06356bSdh142964 }
104*4c06356bSdh142964
105*4c06356bSdh142964 static int
log10(int val)106*4c06356bSdh142964 log10(int val)
107*4c06356bSdh142964 {
108*4c06356bSdh142964 int res = 0;
109*4c06356bSdh142964
110*4c06356bSdh142964 do {
111*4c06356bSdh142964 res++;
112*4c06356bSdh142964 val /= 10;
113*4c06356bSdh142964 } while (val);
114*4c06356bSdh142964 return (res);
115*4c06356bSdh142964 }
116*4c06356bSdh142964
117*4c06356bSdh142964 /*
118*4c06356bSdh142964 * The following prints a bitset with a 'ruler' that look like this
119*4c06356bSdh142964 *
120*4c06356bSdh142964 * 11111111112222222222333333333344444444445555555555666666666677
121*4c06356bSdh142964 * 012345678901234567890123456789012345678901234567890123456789012345678901
122*4c06356bSdh142964 * xx:........................................................................
123*4c06356bSdh142964 * 11111111111111111111111111111111111111111111
124*4c06356bSdh142964 * 777777778888888888999999999900000000001111111111222222222233333333334444
125*4c06356bSdh142964 * 234567890123456789012345678901234567890123456789012345678901234567890123
126*4c06356bSdh142964 * ........................................................................
127*4c06356bSdh142964 * 111111111111111111111111111111111111111111111111111111112222222222222222
128*4c06356bSdh142964 * 444444555555555566666666667777777777888888888899999999990000000000111111
129*4c06356bSdh142964 * 456789012345678901234567890123456789012345678901234567890123456789012345
130*4c06356bSdh142964 * ........................................................................
131*4c06356bSdh142964 * 2222222222
132*4c06356bSdh142964 * 1111222222
133*4c06356bSdh142964 * 6789012345
134*4c06356bSdh142964 * ..........
135*4c06356bSdh142964 *
136*4c06356bSdh142964 * to identify individual bits that are set.
137*4c06356bSdh142964 */
138*4c06356bSdh142964 static void
bitset_print(bitset_t * bs,char * label,int width)139*4c06356bSdh142964 bitset_print(bitset_t *bs, char *label, int width)
140*4c06356bSdh142964 {
141*4c06356bSdh142964 int val_start;
142*4c06356bSdh142964 int val_max;
143*4c06356bSdh142964 int label_width;
144*4c06356bSdh142964 int ruler_width;
145*4c06356bSdh142964 int v, vm, vi;
146*4c06356bSdh142964 int nl, l;
147*4c06356bSdh142964 int i;
148*4c06356bSdh142964 int p;
149*4c06356bSdh142964 char c;
150*4c06356bSdh142964
151*4c06356bSdh142964 val_start = 0;
152*4c06356bSdh142964 val_max = bitset_highbit(bs) + 1;
153*4c06356bSdh142964 if (val_max <= val_start) {
154*4c06356bSdh142964 mdb_printf("%s: empty-set", label);
155*4c06356bSdh142964 return;
156*4c06356bSdh142964 }
157*4c06356bSdh142964
158*4c06356bSdh142964 label_width = strlen(label) + 1;
159*4c06356bSdh142964 ruler_width = width - label_width;
160*4c06356bSdh142964
161*4c06356bSdh142964 for (v = val_start; v < val_max; v = vm) {
162*4c06356bSdh142964 if ((v + ruler_width) < val_max)
163*4c06356bSdh142964 vm = v + ruler_width;
164*4c06356bSdh142964 else
165*4c06356bSdh142964 vm = val_max;
166*4c06356bSdh142964
167*4c06356bSdh142964 nl = log10(vm) - 1;
168*4c06356bSdh142964 for (l = nl; l >= 0; l--) {
169*4c06356bSdh142964 p = pow10(l);
170*4c06356bSdh142964 for (i = 0; i < label_width; i++)
171*4c06356bSdh142964 mdb_printf(" ");
172*4c06356bSdh142964
173*4c06356bSdh142964 for (vi = v; vi < vm; vi++) {
174*4c06356bSdh142964 c = '0' + ((vi / p) % 10);
175*4c06356bSdh142964 if ((l == nl) && (c == '0'))
176*4c06356bSdh142964 c = ' ';
177*4c06356bSdh142964 mdb_printf("%c", c);
178*4c06356bSdh142964 }
179*4c06356bSdh142964
180*4c06356bSdh142964 mdb_printf("\n");
181*4c06356bSdh142964 }
182*4c06356bSdh142964
183*4c06356bSdh142964 if (v == val_start) {
184*4c06356bSdh142964 mdb_printf("%s:", label);
185*4c06356bSdh142964 } else {
186*4c06356bSdh142964 for (i = 0; i < label_width; i++)
187*4c06356bSdh142964 mdb_printf(" ");
188*4c06356bSdh142964 }
189*4c06356bSdh142964 for (vi = v; vi < vm; vi++) {
190*4c06356bSdh142964 if (BT_TEST(bs->bs_set, vi))
191*4c06356bSdh142964 mdb_printf("X");
192*4c06356bSdh142964 else
193*4c06356bSdh142964 mdb_printf(".");
194*4c06356bSdh142964 }
195*4c06356bSdh142964 mdb_printf("\n");
196*4c06356bSdh142964 }
197*4c06356bSdh142964 }
198*4c06356bSdh142964
199*4c06356bSdh142964 /*ARGSUSED*/
200*4c06356bSdh142964 int
bitset(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)201*4c06356bSdh142964 bitset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
202*4c06356bSdh142964 {
203*4c06356bSdh142964 bitset_t *bs;
204*4c06356bSdh142964
205*4c06356bSdh142964 bs = bitset_get(addr);
206*4c06356bSdh142964 if (bs == NULL)
207*4c06356bSdh142964 return (DCMD_ERR);
208*4c06356bSdh142964
209*4c06356bSdh142964 bitset_print(bs, "label", 80);
210*4c06356bSdh142964 bitset_free(bs);
211*4c06356bSdh142964 return (DCMD_OK);
212*4c06356bSdh142964 }
213