remove xen support
[unleashed/tickless.git] / usr / src / cmd / mdb / common / modules / genunix / damap.c
blob409768bc1abcf22e7ae83ee420fd9e05a01170ff
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <mdb/mdb_modapi.h>
26 #include <sys/sysmacros.h>
27 #include <sys/sunddi.h>
28 #include <sys/damap.h>
29 #include <sys/damap_impl.h>
31 #include "damap.h"
33 void
34 damap_help(void)
36 mdb_printf("Print the damap at the address given.\n");
37 mdb_printf("\n");
38 mdb_printf("EXAMPLE: SCSI: To display the SCSI tgtmap damaps ");
39 mdb_printf("associated with a scsi HBA driver iport dip:\n");
40 mdb_printf("\n");
41 mdb_printf("::devbindings -q <driver_name>\n");
42 mdb_printf("\n");
43 mdb_printf("<iport-dip>::print struct dev_info devi_driver_data|");
44 mdb_printf("::print scsi_hba_tran_t tran_tgtmap|");
45 mdb_printf("::print impl_scsi_tgtmap_t ");
46 mdb_printf("tgtmap_dam[0] tgtmap_dam[1]|::damap\n");
49 static char *
50 local_strdup(const char *s)
52 if (s)
53 return (strcpy(mdb_alloc(strlen(s) + 1, UM_SLEEP), s));
54 else
55 return (NULL);
58 static void
59 local_strfree(const char *s)
61 if (s)
62 mdb_free((void *)s, strlen(s) + 1);
65 static void
66 bitset_free(bitset_t *bs, int embedded)
68 if (bs == NULL)
69 return;
70 if (bs->bs_set && bs->bs_words)
71 mdb_free(bs->bs_set, bs->bs_words * sizeof (ulong_t));
72 if (!embedded)
73 mdb_free(bs, sizeof (*bs)); /* not embedded, free */
76 static bitset_t *
77 bitset_get(uintptr_t bsaddr)
79 bitset_t *bs;
81 bs = mdb_zalloc(sizeof (*bs), UM_SLEEP);
82 if (mdb_vread(bs, sizeof (*bs), bsaddr) == -1) {
83 mdb_warn("couldn't read bitset 0x%p", bsaddr);
84 bitset_free(bs, 0);
85 return (NULL);
88 bsaddr = (uintptr_t)bs->bs_set;
89 bs->bs_set = mdb_alloc(bs->bs_words * sizeof (ulong_t), UM_SLEEP);
90 if (mdb_vread(bs->bs_set,
91 bs->bs_words * sizeof (ulong_t), bsaddr) == -1) {
92 mdb_warn("couldn't read bitset bs_set 0x%p", bsaddr);
93 bitset_free(bs, 0);
94 return (NULL);
96 return (bs);
100 static void
101 damap_free(struct dam *dam, void **kdamda, int kdamda_n)
103 int i;
104 struct i_ddi_soft_state *ss;
105 dam_da_t *da;
107 if (dam) {
108 /* free in dam_da_t softstate */
109 ss = (struct i_ddi_soft_state *)dam->dam_da;
110 if (ss) {
111 if (ss->n_items && ss->array) {
112 for (i = 0; i < ss->n_items; i++) {
113 da = ss->array[i];
114 if (da == NULL)
115 continue;
116 local_strfree(da->da_addr);
117 mdb_free(da, sizeof (*da));
121 mdb_free(ss, sizeof (*ss));
124 /* free dam_active/stable/report_set embedded in dam */
125 bitset_free(&dam->dam_report_set, 1);
126 bitset_free(&dam->dam_stable_set, 1);
127 bitset_free(&dam->dam_active_set, 1);
129 /* free dam_name */
130 local_strfree(dam->dam_name);
132 /* free dam */
133 mdb_free(dam, sizeof (*dam));
136 if (kdamda)
137 mdb_free(kdamda, kdamda_n * sizeof (void *));
141 * The dam implementation uses a number of different abstractions. Given a
142 * pointer to a damap_t, this function make an mdb instantiation of the dam -
143 * many, but not all, of the different abstractions used in the dam
144 * implementation are also instantiated in mdb. This means that callers of
145 * damap_get can perform some (but not all) types of structure pointer
146 * traversals.
148 struct dam *
149 damap_get(uintptr_t damaddr, void ***pkdamda, int *pkdamda_n)
151 /* variables that hold instantiation read from kernel */
152 struct dam kdam;
153 char kstring[MAXPATHLEN];
154 struct i_ddi_soft_state kss;
155 void **kssarray = NULL;
156 int array_sz = 0;
158 /* variables that hold mdb instantiation */
159 struct dam *dam = NULL;
160 struct i_ddi_soft_state *ss;
161 bitset_t *bs;
162 dam_da_t *da;
164 int i;
166 /* read kernel: dam */
167 if (mdb_vread(&kdam, sizeof (kdam), damaddr) == -1) {
168 mdb_warn("couldn't read dam 0x%p", damaddr);
169 goto err;
172 /* read kernel: dam->dam_name */
173 mdb_readstr(kstring, sizeof (kstring), (uintptr_t)kdam.dam_name);
175 /* read kernel: dam->dam_da (softstate) */
176 if (mdb_vread(&kss, sizeof (kss), (uintptr_t)kdam.dam_da) == -1) {
177 mdb_warn("couldn't read dam dam_da 0x%p",
178 (uintptr_t)kdam.dam_da);
179 goto err;
182 /* read kernel ((struct i_ddi_soft_state *)dam->dam_da)->array */
183 array_sz = kss.n_items * sizeof (void *);
184 kssarray = mdb_alloc(array_sz, UM_SLEEP);
185 if (mdb_vread(kssarray, array_sz, (uintptr_t)kss.array) == -1) {
186 mdb_warn("couldn't read dam dam_da array 0x%p",
187 (uintptr_t)kss.array);
188 goto err;
192 * Produce mdb instantiation of kernel data structures.
194 * Structure copy kdam to dam, then clear out pointers in dam (some
195 * will be filled in by mdb instantiation code below).
197 dam = mdb_zalloc(sizeof (*dam), UM_SLEEP);
198 *dam = kdam;
199 dam->dam_name = NULL;
201 dam->dam_active_set.bs_set = NULL;
202 dam->dam_stable_set.bs_set = NULL;
203 dam->dam_report_set.bs_set = NULL;
205 dam->dam_da = NULL;
206 /* dam_addr_hash, dam_taskqp, dam_kstatp left as kernel addresses */
208 /* fill in dam_name */
209 dam->dam_name = local_strdup(kstring);
211 /* fill in dam_active/stable/report_set embedded in the dam */
212 bs = bitset_get(damaddr + (offsetof(struct dam, dam_active_set)));
213 if (bs) {
214 dam->dam_active_set = *bs;
215 mdb_free(bs, sizeof (*bs));
217 bs = bitset_get(damaddr + (offsetof(struct dam, dam_stable_set)));
218 if (bs) {
219 dam->dam_stable_set = *bs;
220 mdb_free(bs, sizeof (*bs));
222 bs = bitset_get(damaddr + (offsetof(struct dam, dam_report_set)));
223 if (bs) {
224 dam->dam_report_set = *bs;
225 mdb_free(bs, sizeof (*bs));
228 /* fill in dam_da_t softstate */
229 ss = mdb_zalloc(sizeof (struct i_ddi_soft_state), UM_SLEEP);
230 *ss = kss;
231 ss->next = NULL;
232 ss->array = mdb_zalloc(array_sz, UM_SLEEP);
233 dam->dam_da = ss;
234 for (i = 0; i < kss.n_items; i++) {
235 if (kssarray[i] == NULL)
236 continue;
237 da = ss->array[i] = mdb_zalloc(sizeof (*da), UM_SLEEP);
238 if (mdb_vread(da, sizeof (*da), (uintptr_t)kssarray[i]) == -1) {
239 mdb_warn("couldn't read dam dam_da %d 0x%p", i,
240 (uintptr_t)kss.array);
241 goto err;
243 /* da_nvl, da_ppriv_rpt, da_nvl_rpt left as kernel addresses */
245 /* read kernel: da->da_addr */
246 mdb_readstr(kstring, sizeof (kstring), (uintptr_t)da->da_addr);
247 da->da_addr = local_strdup(kstring);
250 /* return array of kernel dam_da_t pointers associated with each id */
251 *pkdamda = kssarray;
252 *pkdamda_n = array_sz / sizeof (void *);
254 /* return pointer to mdb instantiation of the dam */
255 return (dam);
257 err: damap_free(dam, kssarray, array_sz / sizeof (void *));
258 *pkdamda = NULL;
259 *pkdamda_n = 0;
260 return (NULL);
263 /*ARGSUSED*/
264 static void
265 damap_print(struct dam *dam, void **kdamda, int kdamda_n)
267 struct i_ddi_soft_state *ss;
268 dam_da_t *da;
269 int i;
271 mdb_printf("%s:\n", dam->dam_name);
273 ss = (struct i_ddi_soft_state *)dam->dam_da;
274 if (ss == NULL)
275 return;
277 if ((ss->n_items == 0) || (ss->array == NULL))
278 return;
280 mdb_printf(" #: %-20s [ASR] ref config-private provider-private\n",
281 "address");
282 for (i = 0; i < ss->n_items; i++) {
283 da = ss->array[i];
284 if (da == NULL)
285 continue;
287 /* Print index and address. */
288 mdb_printf(" %3d: %-20s [", i, da->da_addr);
290 /* Print shorthand of Active/Stable/Report set membership */
291 if (BT_TEST(dam->dam_active_set.bs_set, i))
292 mdb_printf("A");
293 else
294 mdb_printf(".");
295 if (BT_TEST(dam->dam_stable_set.bs_set, i))
296 mdb_printf("S");
297 else
298 mdb_printf(".");
299 if (BT_TEST(dam->dam_report_set.bs_set, i))
300 mdb_printf("R");
301 else
302 mdb_printf(".");
304 /* Print the reference count and priv */
305 mdb_printf("] %-3d %0?lx %0?lx\n",
306 da->da_ref, da->da_cfg_priv, da->da_ppriv);
308 mdb_printf(" %p::print -ta dam_da_t\n", kdamda[i]);
312 /*ARGSUSED*/
314 damap(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
316 struct dam *dam;
317 void **kdamda;
318 int kdamda_n;
320 if (!(flags & DCMD_ADDRSPEC)) {
321 return (DCMD_ERR);
324 dam = damap_get(addr, &kdamda, &kdamda_n);
325 if (dam == NULL)
326 return (DCMD_ERR);
328 damap_print(dam, kdamda, kdamda_n);
329 damap_free(dam, kdamda, kdamda_n);
330 return (DCMD_OK);