xref: /titanic_52/usr/src/cmd/mdb/common/modules/genunix/irm.c (revision b285fe3084109ad5540fb5940547fb30561fdfd9)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include <sys/mdb_modapi.h>
26 #include <sys/proc.h>
27 #include <sys/types.h>
28 #include <sys/sunddi.h>
29 #include <sys/ddi_intr.h>
30 #include <sys/ddi_intr_impl.h>
31 #include <stddef.h>
32 
33 #include "list.h"
34 
35 extern int	mdb_devinfo2driver(uintptr_t, char *, size_t);
36 
37 static char *
38 irm_get_type(int type)
39 {
40 	if (type == (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_MSIX))
41 		return ("MSI/X");
42 
43 	switch (type) {
44 	case DDI_INTR_TYPE_FIXED:
45 		return ("Fixed");
46 	case DDI_INTR_TYPE_MSI:
47 		return ("MSI");
48 	case DDI_INTR_TYPE_MSIX:
49 		return ("MSI-X");
50 	default:
51 		return ("Unknown");
52 	}
53 }
54 
55 static int
56 check_irm_enabled(void)
57 {
58 	GElf_Sym	sym;
59 	uintptr_t	addr;
60 	int		value;
61 
62 	if (mdb_lookup_by_name("irm_enable", &sym) == -1) {
63 		mdb_warn("couldn't find irm_enable");
64 		return (0);
65 	}
66 
67 	addr = (uintptr_t)sym.st_value;
68 
69 	if (mdb_vread(&value, sizeof (value), addr) != sizeof (value)) {
70 		mdb_warn("couldn't read irm_enable at %p", addr);
71 		return (0);
72 	}
73 
74 	return (value);
75 }
76 
77 int
78 irmpools_walk_init(mdb_walk_state_t *wsp)
79 {
80 	GElf_Sym sym;
81 
82 	if (mdb_lookup_by_name("irm_pools_list", &sym) == -1) {
83 		mdb_warn("couldn't find irm_pools_list");
84 		return (WALK_ERR);
85 	}
86 
87 	wsp->walk_addr = (uintptr_t)sym.st_value;
88 
89 	return (list_walk_init_named(wsp, "interrupt pools", "pool"));
90 }
91 
92 int
93 irmreqs_walk_init(mdb_walk_state_t *wsp)
94 {
95 	wsp->walk_addr = (uintptr_t)(wsp->walk_addr +
96 	    offsetof(ddi_irm_pool_t, ipool_req_list));
97 
98 	return (list_walk_init_named(wsp, "interrupt requests", "request"));
99 }
100 
101 int
102 irmpools_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
103 {
104 	ddi_irm_pool_t	pool;
105 	struct dev_info	dev;
106 	char		driver[MODMAXNAMELEN + 1] = "";
107 	char		devname[MODMAXNAMELEN + 1] = "";
108 
109 	if (argc != 0)
110 		return (DCMD_USAGE);
111 
112 	if (check_irm_enabled() == 0) {
113 		mdb_warn("IRM is not enabled");
114 		return (DCMD_ERR);
115 	}
116 
117 	if (!(flags & DCMD_ADDRSPEC)) {
118 		if (mdb_walk_dcmd("irmpools", "irmpools", argc, argv) == -1) {
119 			mdb_warn("can't walk interrupt pools");
120 			return (DCMD_ERR);
121 		}
122 		return (DCMD_OK);
123 	}
124 
125 	if (DCMD_HDRSPEC(flags)) {
126 		mdb_printf("%<u>%?s  %-18s  %-8s  %-6s  %-9s  %-8s%</u>\n",
127 		    "ADDR", "OWNER", "TYPE", "SIZE", "REQUESTED", "RESERVED");
128 	}
129 
130 	if (mdb_vread(&pool, sizeof (pool), addr) != sizeof (pool)) {
131 		mdb_warn("couldn't read interrupt pool at %p", addr);
132 		return (DCMD_ERR);
133 	}
134 
135 	if (mdb_vread(&dev, sizeof (dev),
136 	    (uintptr_t)pool.ipool_owner) != sizeof (dev)) {
137 		mdb_warn("couldn't read dev_info at %p", pool.ipool_owner);
138 		return (DCMD_ERR);
139 	}
140 
141 	mdb_devinfo2driver((uintptr_t)pool.ipool_owner, driver,
142 	    sizeof (driver));
143 	mdb_snprintf(devname, sizeof (devname), "%s#%d", driver,
144 	    dev.devi_instance);
145 
146 	mdb_printf("%0?p  %-18s  %-8s  %-6d  %-9d  %-8d\n", addr, devname,
147 	    irm_get_type(pool.ipool_types), pool.ipool_totsz,
148 	    pool.ipool_reqno, pool.ipool_resno);
149 
150 	return (DCMD_OK);
151 }
152 
153 int
154 irmreqs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
155 {
156 	if (argc != 0)
157 		return (DCMD_USAGE);
158 
159 	if (check_irm_enabled() == 0) {
160 		mdb_warn("IRM is not enabled");
161 		return (DCMD_ERR);
162 	}
163 
164 	if (!(flags & DCMD_ADDRSPEC)) {
165 		mdb_warn("can't perform global interrupt request walk");
166 		return (DCMD_ERR);
167 	}
168 
169 	if (mdb_pwalk_dcmd("irmreqs", "irmreq", argc, argv, addr) == -1) {
170 		mdb_warn("can't walk interrupt requests");
171 		return (DCMD_ERR);
172 	}
173 
174 	return (DCMD_OK);
175 }
176 
177 /*ARGSUSED*/
178 int
179 irmreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
180 {
181 	ddi_irm_req_t		req;
182 	struct dev_info		dev;
183 	struct devinfo_intr	intr;
184 	char			driver[MODMAXNAMELEN + 1] = "";
185 	char			devname[MODMAXNAMELEN + 1] = "";
186 
187 	if (argc != 0)
188 		return (DCMD_USAGE);
189 
190 	if (!(flags & DCMD_ADDRSPEC)) {
191 		return (DCMD_ERR);
192 	}
193 
194 	if (DCMD_HDRSPEC(flags)) {
195 		mdb_printf("%<u>%?s  %-18s  %-8s  %-8s  %-6s  %-4s  "
196 		    "%-6s%</u>\n", "ADDR", "OWNER", "TYPE", "CALLBACK",
197 		    "NINTRS", "NREQ", "NAVAIL");
198 	}
199 
200 	if (mdb_vread(&req, sizeof (req), addr) != sizeof (req)) {
201 		mdb_warn("couldn't read interrupt request at %p", addr);
202 		return (DCMD_ERR);
203 	}
204 
205 	if (mdb_vread(&dev, sizeof (dev),
206 	    (uintptr_t)req.ireq_dip) != sizeof (dev)) {
207 		mdb_warn("couldn't read dev_info at %p", req.ireq_dip);
208 		return (DCMD_ERR);
209 	}
210 
211 	if (mdb_vread(&intr, sizeof (intr),
212 	    (uintptr_t)dev.devi_intr_p) != sizeof (intr)) {
213 		mdb_warn("couldn't read devinfo_intr at %p", dev.devi_intr_p);
214 		return (DCMD_ERR);
215 	}
216 
217 	mdb_devinfo2driver((uintptr_t)req.ireq_dip, driver, sizeof (driver));
218 	mdb_snprintf(devname, sizeof (devname), "%s#%d", driver,
219 	    dev.devi_instance);
220 
221 	mdb_printf("%0?p  %-18s  %-8s  %-8s  %-6d  %-4d  %-6d\n",
222 	    addr, devname, irm_get_type(req.ireq_type),
223 	    (req.ireq_flags & DDI_IRM_FLAG_CALLBACK) ? "Yes" : "No",
224 	    intr.devi_intr_sup_nintrs, req.ireq_nreq, req.ireq_navail);
225 
226 	return (DCMD_OK);
227 }
228