18561SScott.Carter@Sun.COM /*
28561SScott.Carter@Sun.COM  * CDDL HEADER START
38561SScott.Carter@Sun.COM  *
48561SScott.Carter@Sun.COM  * The contents of this file are subject to the terms of the
58561SScott.Carter@Sun.COM  * Common Development and Distribution License (the "License").
68561SScott.Carter@Sun.COM  * You may not use this file except in compliance with the License.
78561SScott.Carter@Sun.COM  *
88561SScott.Carter@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98561SScott.Carter@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108561SScott.Carter@Sun.COM  * See the License for the specific language governing permissions
118561SScott.Carter@Sun.COM  * and limitations under the License.
128561SScott.Carter@Sun.COM  *
138561SScott.Carter@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148561SScott.Carter@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158561SScott.Carter@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168561SScott.Carter@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178561SScott.Carter@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188561SScott.Carter@Sun.COM  *
198561SScott.Carter@Sun.COM  * CDDL HEADER END
208561SScott.Carter@Sun.COM  */
218561SScott.Carter@Sun.COM /*
22*12652SScott.Carter@Oracle.COM  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
238561SScott.Carter@Sun.COM  */
248561SScott.Carter@Sun.COM 
258561SScott.Carter@Sun.COM #include <sys/mdb_modapi.h>
268561SScott.Carter@Sun.COM #include <sys/proc.h>
278561SScott.Carter@Sun.COM #include <sys/types.h>
288561SScott.Carter@Sun.COM #include <sys/sunddi.h>
298561SScott.Carter@Sun.COM #include <sys/ddi_intr.h>
308561SScott.Carter@Sun.COM #include <sys/ddi_intr_impl.h>
318561SScott.Carter@Sun.COM #include <stddef.h>
328561SScott.Carter@Sun.COM 
338561SScott.Carter@Sun.COM #include "list.h"
348561SScott.Carter@Sun.COM 
358561SScott.Carter@Sun.COM extern int	mdb_devinfo2driver(uintptr_t, char *, size_t);
368561SScott.Carter@Sun.COM 
378561SScott.Carter@Sun.COM static char *
388561SScott.Carter@Sun.COM irm_get_type(int type)
398561SScott.Carter@Sun.COM {
408561SScott.Carter@Sun.COM 	if (type == (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_MSIX))
418561SScott.Carter@Sun.COM 		return ("MSI/X");
428561SScott.Carter@Sun.COM 
438561SScott.Carter@Sun.COM 	switch (type) {
448561SScott.Carter@Sun.COM 	case DDI_INTR_TYPE_FIXED:
458561SScott.Carter@Sun.COM 		return ("Fixed");
468561SScott.Carter@Sun.COM 	case DDI_INTR_TYPE_MSI:
478561SScott.Carter@Sun.COM 		return ("MSI");
488561SScott.Carter@Sun.COM 	case DDI_INTR_TYPE_MSIX:
498561SScott.Carter@Sun.COM 		return ("MSI-X");
508561SScott.Carter@Sun.COM 	default:
518561SScott.Carter@Sun.COM 		return ("Unknown");
528561SScott.Carter@Sun.COM 	}
538561SScott.Carter@Sun.COM }
548561SScott.Carter@Sun.COM 
55*12652SScott.Carter@Oracle.COM static int
56*12652SScott.Carter@Oracle.COM check_irm_enabled(void)
57*12652SScott.Carter@Oracle.COM {
58*12652SScott.Carter@Oracle.COM 	GElf_Sym	sym;
59*12652SScott.Carter@Oracle.COM 	uintptr_t	addr;
60*12652SScott.Carter@Oracle.COM 	int		value;
61*12652SScott.Carter@Oracle.COM 
62*12652SScott.Carter@Oracle.COM 	if (mdb_lookup_by_name("irm_enable", &sym) == -1) {
63*12652SScott.Carter@Oracle.COM 		mdb_warn("couldn't find irm_enable");
64*12652SScott.Carter@Oracle.COM 		return (0);
65*12652SScott.Carter@Oracle.COM 	}
66*12652SScott.Carter@Oracle.COM 
67*12652SScott.Carter@Oracle.COM 	addr = (uintptr_t)sym.st_value;
68*12652SScott.Carter@Oracle.COM 
69*12652SScott.Carter@Oracle.COM 	if (mdb_vread(&value, sizeof (value), addr) != sizeof (value)) {
70*12652SScott.Carter@Oracle.COM 		mdb_warn("couldn't read irm_enable at %p", addr);
71*12652SScott.Carter@Oracle.COM 		return (0);
72*12652SScott.Carter@Oracle.COM 	}
73*12652SScott.Carter@Oracle.COM 
74*12652SScott.Carter@Oracle.COM 	return (value);
75*12652SScott.Carter@Oracle.COM }
76*12652SScott.Carter@Oracle.COM 
778561SScott.Carter@Sun.COM int
788561SScott.Carter@Sun.COM irmpools_walk_init(mdb_walk_state_t *wsp)
798561SScott.Carter@Sun.COM {
808561SScott.Carter@Sun.COM 	GElf_Sym sym;
818561SScott.Carter@Sun.COM 
828561SScott.Carter@Sun.COM 	if (mdb_lookup_by_name("irm_pools_list", &sym) == -1) {
838561SScott.Carter@Sun.COM 		mdb_warn("couldn't find irm_pools_list");
848561SScott.Carter@Sun.COM 		return (WALK_ERR);
858561SScott.Carter@Sun.COM 	}
868561SScott.Carter@Sun.COM 
878561SScott.Carter@Sun.COM 	wsp->walk_addr = (uintptr_t)sym.st_value;
888561SScott.Carter@Sun.COM 
898561SScott.Carter@Sun.COM 	return (list_walk_init_named(wsp, "interrupt pools", "pool"));
908561SScott.Carter@Sun.COM }
918561SScott.Carter@Sun.COM 
928561SScott.Carter@Sun.COM int
938561SScott.Carter@Sun.COM irmreqs_walk_init(mdb_walk_state_t *wsp)
948561SScott.Carter@Sun.COM {
958561SScott.Carter@Sun.COM 	wsp->walk_addr = (uintptr_t)(wsp->walk_addr +
968561SScott.Carter@Sun.COM 	    offsetof(ddi_irm_pool_t, ipool_req_list));
978561SScott.Carter@Sun.COM 
988561SScott.Carter@Sun.COM 	return (list_walk_init_named(wsp, "interrupt requests", "request"));
998561SScott.Carter@Sun.COM }
1008561SScott.Carter@Sun.COM 
1018561SScott.Carter@Sun.COM int
1028561SScott.Carter@Sun.COM irmpools_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1038561SScott.Carter@Sun.COM {
1048561SScott.Carter@Sun.COM 	ddi_irm_pool_t	pool;
1058561SScott.Carter@Sun.COM 	struct dev_info	dev;
1068561SScott.Carter@Sun.COM 	char		driver[MODMAXNAMELEN + 1] = "";
1078561SScott.Carter@Sun.COM 	char		devname[MODMAXNAMELEN + 1] = "";
1088561SScott.Carter@Sun.COM 
1098561SScott.Carter@Sun.COM 	if (argc != 0)
1108561SScott.Carter@Sun.COM 		return (DCMD_USAGE);
1118561SScott.Carter@Sun.COM 
112*12652SScott.Carter@Oracle.COM 	if (check_irm_enabled() == 0) {
113*12652SScott.Carter@Oracle.COM 		mdb_warn("IRM is not enabled");
114*12652SScott.Carter@Oracle.COM 		return (DCMD_ERR);
115*12652SScott.Carter@Oracle.COM 	}
116*12652SScott.Carter@Oracle.COM 
1178561SScott.Carter@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
1188561SScott.Carter@Sun.COM 		if (mdb_walk_dcmd("irmpools", "irmpools", argc, argv) == -1) {
1198561SScott.Carter@Sun.COM 			mdb_warn("can't walk interrupt pools");
1208561SScott.Carter@Sun.COM 			return (DCMD_ERR);
1218561SScott.Carter@Sun.COM 		}
1228561SScott.Carter@Sun.COM 		return (DCMD_OK);
1238561SScott.Carter@Sun.COM 	}
1248561SScott.Carter@Sun.COM 
1258561SScott.Carter@Sun.COM 	if (DCMD_HDRSPEC(flags)) {
1268561SScott.Carter@Sun.COM 		mdb_printf("%<u>%?s  %-18s  %-8s  %-6s  %-9s  %-8s%</u>\n",
1278561SScott.Carter@Sun.COM 		    "ADDR", "OWNER", "TYPE", "SIZE", "REQUESTED", "RESERVED");
1288561SScott.Carter@Sun.COM 	}
1298561SScott.Carter@Sun.COM 
1308561SScott.Carter@Sun.COM 	if (mdb_vread(&pool, sizeof (pool), addr) != sizeof (pool)) {
1318561SScott.Carter@Sun.COM 		mdb_warn("couldn't read interrupt pool at %p", addr);
1328561SScott.Carter@Sun.COM 		return (DCMD_ERR);
1338561SScott.Carter@Sun.COM 	}
1348561SScott.Carter@Sun.COM 
1358561SScott.Carter@Sun.COM 	if (mdb_vread(&dev, sizeof (dev),
1368561SScott.Carter@Sun.COM 	    (uintptr_t)pool.ipool_owner) != sizeof (dev)) {
1378561SScott.Carter@Sun.COM 		mdb_warn("couldn't read dev_info at %p", pool.ipool_owner);
1388561SScott.Carter@Sun.COM 		return (DCMD_ERR);
1398561SScott.Carter@Sun.COM 	}
1408561SScott.Carter@Sun.COM 
1418561SScott.Carter@Sun.COM 	mdb_devinfo2driver((uintptr_t)pool.ipool_owner, driver,
1428561SScott.Carter@Sun.COM 	    sizeof (driver));
1438561SScott.Carter@Sun.COM 	mdb_snprintf(devname, sizeof (devname), "%s#%d", driver,
1448561SScott.Carter@Sun.COM 	    dev.devi_instance);
1458561SScott.Carter@Sun.COM 
1468561SScott.Carter@Sun.COM 	mdb_printf("%0?p  %-18s  %-8s  %-6d  %-9d  %-8d\n", addr, devname,
1478561SScott.Carter@Sun.COM 	    irm_get_type(pool.ipool_types), pool.ipool_totsz,
1488561SScott.Carter@Sun.COM 	    pool.ipool_reqno, pool.ipool_resno);
1498561SScott.Carter@Sun.COM 
1508561SScott.Carter@Sun.COM 	return (DCMD_OK);
1518561SScott.Carter@Sun.COM }
1528561SScott.Carter@Sun.COM 
1538561SScott.Carter@Sun.COM int
1548561SScott.Carter@Sun.COM irmreqs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1558561SScott.Carter@Sun.COM {
1568561SScott.Carter@Sun.COM 	if (argc != 0)
1578561SScott.Carter@Sun.COM 		return (DCMD_USAGE);
1588561SScott.Carter@Sun.COM 
159*12652SScott.Carter@Oracle.COM 	if (check_irm_enabled() == 0) {
160*12652SScott.Carter@Oracle.COM 		mdb_warn("IRM is not enabled");
161*12652SScott.Carter@Oracle.COM 		return (DCMD_ERR);
162*12652SScott.Carter@Oracle.COM 	}
163*12652SScott.Carter@Oracle.COM 
1648561SScott.Carter@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
1658561SScott.Carter@Sun.COM 		mdb_warn("can't perform global interrupt request walk");
1668561SScott.Carter@Sun.COM 		return (DCMD_ERR);
1678561SScott.Carter@Sun.COM 	}
1688561SScott.Carter@Sun.COM 
1698561SScott.Carter@Sun.COM 	if (mdb_pwalk_dcmd("irmreqs", "irmreq", argc, argv, addr) == -1) {
1708561SScott.Carter@Sun.COM 		mdb_warn("can't walk interrupt requests");
1718561SScott.Carter@Sun.COM 		return (DCMD_ERR);
1728561SScott.Carter@Sun.COM 	}
1738561SScott.Carter@Sun.COM 
1748561SScott.Carter@Sun.COM 	return (DCMD_OK);
1758561SScott.Carter@Sun.COM }
1768561SScott.Carter@Sun.COM 
1778561SScott.Carter@Sun.COM /*ARGSUSED*/
1788561SScott.Carter@Sun.COM int
1798561SScott.Carter@Sun.COM irmreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1808561SScott.Carter@Sun.COM {
1818561SScott.Carter@Sun.COM 	ddi_irm_req_t		req;
1828561SScott.Carter@Sun.COM 	struct dev_info		dev;
1838561SScott.Carter@Sun.COM 	struct devinfo_intr	intr;
1848561SScott.Carter@Sun.COM 	char			driver[MODMAXNAMELEN + 1] = "";
1858561SScott.Carter@Sun.COM 	char			devname[MODMAXNAMELEN + 1] = "";
1868561SScott.Carter@Sun.COM 
1878561SScott.Carter@Sun.COM 	if (argc != 0)
1888561SScott.Carter@Sun.COM 		return (DCMD_USAGE);
1898561SScott.Carter@Sun.COM 
1908561SScott.Carter@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
1918561SScott.Carter@Sun.COM 		return (DCMD_ERR);
1928561SScott.Carter@Sun.COM 	}
1938561SScott.Carter@Sun.COM 
1948561SScott.Carter@Sun.COM 	if (DCMD_HDRSPEC(flags)) {
1958561SScott.Carter@Sun.COM 		mdb_printf("%<u>%?s  %-18s  %-8s  %-8s  %-6s  %-4s  "
1968561SScott.Carter@Sun.COM 		    "%-6s%</u>\n", "ADDR", "OWNER", "TYPE", "CALLBACK",
1978561SScott.Carter@Sun.COM 		    "NINTRS", "NREQ", "NAVAIL");
1988561SScott.Carter@Sun.COM 	}
1998561SScott.Carter@Sun.COM 
2008561SScott.Carter@Sun.COM 	if (mdb_vread(&req, sizeof (req), addr) != sizeof (req)) {
2018561SScott.Carter@Sun.COM 		mdb_warn("couldn't read interrupt request at %p", addr);
2028561SScott.Carter@Sun.COM 		return (DCMD_ERR);
2038561SScott.Carter@Sun.COM 	}
2048561SScott.Carter@Sun.COM 
2058561SScott.Carter@Sun.COM 	if (mdb_vread(&dev, sizeof (dev),
2068561SScott.Carter@Sun.COM 	    (uintptr_t)req.ireq_dip) != sizeof (dev)) {
2078561SScott.Carter@Sun.COM 		mdb_warn("couldn't read dev_info at %p", req.ireq_dip);
2088561SScott.Carter@Sun.COM 		return (DCMD_ERR);
2098561SScott.Carter@Sun.COM 	}
2108561SScott.Carter@Sun.COM 
2118561SScott.Carter@Sun.COM 	if (mdb_vread(&intr, sizeof (intr),
2128561SScott.Carter@Sun.COM 	    (uintptr_t)dev.devi_intr_p) != sizeof (intr)) {
2138561SScott.Carter@Sun.COM 		mdb_warn("couldn't read devinfo_intr at %p", dev.devi_intr_p);
2148561SScott.Carter@Sun.COM 		return (DCMD_ERR);
2158561SScott.Carter@Sun.COM 	}
2168561SScott.Carter@Sun.COM 
2178561SScott.Carter@Sun.COM 	mdb_devinfo2driver((uintptr_t)req.ireq_dip, driver, sizeof (driver));
2188561SScott.Carter@Sun.COM 	mdb_snprintf(devname, sizeof (devname), "%s#%d", driver,
2198561SScott.Carter@Sun.COM 	    dev.devi_instance);
2208561SScott.Carter@Sun.COM 
2218561SScott.Carter@Sun.COM 	mdb_printf("%0?p  %-18s  %-8s  %-8s  %-6d  %-4d  %-6d\n",
2228561SScott.Carter@Sun.COM 	    addr, devname, irm_get_type(req.ireq_type),
2238561SScott.Carter@Sun.COM 	    (req.ireq_flags & DDI_IRM_FLAG_CALLBACK) ? "Yes" : "No",
2248561SScott.Carter@Sun.COM 	    intr.devi_intr_sup_nintrs, req.ireq_nreq, req.ireq_navail);
2258561SScott.Carter@Sun.COM 
2268561SScott.Carter@Sun.COM 	return (DCMD_OK);
2278561SScott.Carter@Sun.COM }
228