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