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]
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>
36 mdb_printf("Print the damap at the address given.\n");
38 mdb_printf("EXAMPLE: SCSI: To display the SCSI tgtmap damaps ");
39 mdb_printf("associated with a scsi HBA driver iport dip:\n");
41 mdb_printf("::devbindings -q <driver_name>\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");
50 local_strdup(const char *s
)
53 return (strcpy(mdb_alloc(strlen(s
) + 1, UM_SLEEP
), s
));
59 local_strfree(const char *s
)
62 mdb_free((void *)s
, strlen(s
) + 1);
66 bitset_free(bitset_t
*bs
, int embedded
)
70 if (bs
->bs_set
&& bs
->bs_words
)
71 mdb_free(bs
->bs_set
, bs
->bs_words
* sizeof (ulong_t
));
73 mdb_free(bs
, sizeof (*bs
)); /* not embedded, free */
77 bitset_get(uintptr_t bsaddr
)
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
);
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
);
101 damap_free(struct dam
*dam
, void **kdamda
, int kdamda_n
)
104 struct i_ddi_soft_state
*ss
;
108 /* free in dam_da_t softstate */
109 ss
= (struct i_ddi_soft_state
*)dam
->dam_da
;
111 if (ss
->n_items
&& ss
->array
) {
112 for (i
= 0; i
< ss
->n_items
; i
++) {
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);
130 local_strfree(dam
->dam_name
);
133 mdb_free(dam
, sizeof (*dam
));
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
149 damap_get(uintptr_t damaddr
, void ***pkdamda
, int *pkdamda_n
)
151 /* variables that hold instantiation read from kernel */
153 char kstring
[MAXPATHLEN
];
154 struct i_ddi_soft_state kss
;
155 void **kssarray
= NULL
;
158 /* variables that hold mdb instantiation */
159 struct dam
*dam
= NULL
;
160 struct i_ddi_soft_state
*ss
;
166 /* read kernel: dam */
167 if (mdb_vread(&kdam
, sizeof (kdam
), damaddr
) == -1) {
168 mdb_warn("couldn't read dam 0x%p", damaddr
);
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
);
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
);
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
);
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
;
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
)));
214 dam
->dam_active_set
= *bs
;
215 mdb_free(bs
, sizeof (*bs
));
217 bs
= bitset_get(damaddr
+ (offsetof(struct dam
, dam_stable_set
)));
219 dam
->dam_stable_set
= *bs
;
220 mdb_free(bs
, sizeof (*bs
));
222 bs
= bitset_get(damaddr
+ (offsetof(struct dam
, dam_report_set
)));
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
);
232 ss
->array
= mdb_zalloc(array_sz
, UM_SLEEP
);
234 for (i
= 0; i
< kss
.n_items
; i
++) {
235 if (kssarray
[i
] == NULL
)
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
);
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 */
252 *pkdamda_n
= array_sz
/ sizeof (void *);
254 /* return pointer to mdb instantiation of the dam */
257 err
: damap_free(dam
, kssarray
, array_sz
/ sizeof (void *));
265 damap_print(struct dam
*dam
, void **kdamda
, int kdamda_n
)
267 struct i_ddi_soft_state
*ss
;
271 mdb_printf("%s:\n", dam
->dam_name
);
273 ss
= (struct i_ddi_soft_state
*)dam
->dam_da
;
277 if ((ss
->n_items
== 0) || (ss
->array
== NULL
))
280 mdb_printf(" #: %-20s [ASR] ref config-private provider-private\n",
282 for (i
= 0; i
< ss
->n_items
; i
++) {
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
))
295 if (BT_TEST(dam
->dam_stable_set
.bs_set
, i
))
299 if (BT_TEST(dam
->dam_report_set
.bs_set
, i
))
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
]);
314 damap(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
320 if (!(flags
& DCMD_ADDRSPEC
)) {
324 dam
= damap_get(addr
, &kdamda
, &kdamda_n
);
328 damap_print(dam
, kdamda
, kdamda_n
);
329 damap_free(dam
, kdamda
, kdamda_n
);