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 /*
2212652SScott.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 *
irm_get_type(int type)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
5512652SScott.Carter@Oracle.COM static int
check_irm_enabled(void)5612652SScott.Carter@Oracle.COM check_irm_enabled(void)
5712652SScott.Carter@Oracle.COM {
5812652SScott.Carter@Oracle.COM GElf_Sym sym;
5912652SScott.Carter@Oracle.COM uintptr_t addr;
6012652SScott.Carter@Oracle.COM int value;
6112652SScott.Carter@Oracle.COM
6212652SScott.Carter@Oracle.COM if (mdb_lookup_by_name("irm_enable", &sym) == -1) {
6312652SScott.Carter@Oracle.COM mdb_warn("couldn't find irm_enable");
6412652SScott.Carter@Oracle.COM return (0);
6512652SScott.Carter@Oracle.COM }
6612652SScott.Carter@Oracle.COM
6712652SScott.Carter@Oracle.COM addr = (uintptr_t)sym.st_value;
6812652SScott.Carter@Oracle.COM
6912652SScott.Carter@Oracle.COM if (mdb_vread(&value, sizeof (value), addr) != sizeof (value)) {
7012652SScott.Carter@Oracle.COM mdb_warn("couldn't read irm_enable at %p", addr);
7112652SScott.Carter@Oracle.COM return (0);
7212652SScott.Carter@Oracle.COM }
7312652SScott.Carter@Oracle.COM
7412652SScott.Carter@Oracle.COM return (value);
7512652SScott.Carter@Oracle.COM }
7612652SScott.Carter@Oracle.COM
778561SScott.Carter@Sun.COM int
irmpools_walk_init(mdb_walk_state_t * wsp)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
irmreqs_walk_init(mdb_walk_state_t * wsp)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
irmpools_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
11212652SScott.Carter@Oracle.COM if (check_irm_enabled() == 0) {
11312652SScott.Carter@Oracle.COM mdb_warn("IRM is not enabled");
11412652SScott.Carter@Oracle.COM return (DCMD_ERR);
11512652SScott.Carter@Oracle.COM }
11612652SScott.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));
143*12683SJimmy.Vetayases@oracle.com /*
144*12683SJimmy.Vetayases@oracle.com * Include driver instance number only if the node has an
145*12683SJimmy.Vetayases@oracle.com * instance number assigned (i.e. instance != -1) to it.
146*12683SJimmy.Vetayases@oracle.com * This will cover cases like rootnex driver which doesn't
147*12683SJimmy.Vetayases@oracle.com * have instance number assigned to it.
148*12683SJimmy.Vetayases@oracle.com */
149*12683SJimmy.Vetayases@oracle.com if (dev.devi_instance != -1)
150*12683SJimmy.Vetayases@oracle.com mdb_snprintf(devname, sizeof (devname), "%s#%d", driver,
151*12683SJimmy.Vetayases@oracle.com dev.devi_instance);
152*12683SJimmy.Vetayases@oracle.com else
153*12683SJimmy.Vetayases@oracle.com mdb_snprintf(devname, sizeof (devname), "%s", driver);
1548561SScott.Carter@Sun.COM
1558561SScott.Carter@Sun.COM mdb_printf("%0?p %-18s %-8s %-6d %-9d %-8d\n", addr, devname,
1568561SScott.Carter@Sun.COM irm_get_type(pool.ipool_types), pool.ipool_totsz,
1578561SScott.Carter@Sun.COM pool.ipool_reqno, pool.ipool_resno);
1588561SScott.Carter@Sun.COM
1598561SScott.Carter@Sun.COM return (DCMD_OK);
1608561SScott.Carter@Sun.COM }
1618561SScott.Carter@Sun.COM
1628561SScott.Carter@Sun.COM int
irmreqs_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1638561SScott.Carter@Sun.COM irmreqs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1648561SScott.Carter@Sun.COM {
1658561SScott.Carter@Sun.COM if (argc != 0)
1668561SScott.Carter@Sun.COM return (DCMD_USAGE);
1678561SScott.Carter@Sun.COM
16812652SScott.Carter@Oracle.COM if (check_irm_enabled() == 0) {
16912652SScott.Carter@Oracle.COM mdb_warn("IRM is not enabled");
17012652SScott.Carter@Oracle.COM return (DCMD_ERR);
17112652SScott.Carter@Oracle.COM }
17212652SScott.Carter@Oracle.COM
1738561SScott.Carter@Sun.COM if (!(flags & DCMD_ADDRSPEC)) {
1748561SScott.Carter@Sun.COM mdb_warn("can't perform global interrupt request walk");
1758561SScott.Carter@Sun.COM return (DCMD_ERR);
1768561SScott.Carter@Sun.COM }
1778561SScott.Carter@Sun.COM
1788561SScott.Carter@Sun.COM if (mdb_pwalk_dcmd("irmreqs", "irmreq", argc, argv, addr) == -1) {
1798561SScott.Carter@Sun.COM mdb_warn("can't walk interrupt requests");
1808561SScott.Carter@Sun.COM return (DCMD_ERR);
1818561SScott.Carter@Sun.COM }
1828561SScott.Carter@Sun.COM
1838561SScott.Carter@Sun.COM return (DCMD_OK);
1848561SScott.Carter@Sun.COM }
1858561SScott.Carter@Sun.COM
1868561SScott.Carter@Sun.COM /*ARGSUSED*/
1878561SScott.Carter@Sun.COM int
irmreq_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1888561SScott.Carter@Sun.COM irmreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1898561SScott.Carter@Sun.COM {
1908561SScott.Carter@Sun.COM ddi_irm_req_t req;
1918561SScott.Carter@Sun.COM struct dev_info dev;
1928561SScott.Carter@Sun.COM struct devinfo_intr intr;
1938561SScott.Carter@Sun.COM char driver[MODMAXNAMELEN + 1] = "";
1948561SScott.Carter@Sun.COM char devname[MODMAXNAMELEN + 1] = "";
1958561SScott.Carter@Sun.COM
1968561SScott.Carter@Sun.COM if (argc != 0)
1978561SScott.Carter@Sun.COM return (DCMD_USAGE);
1988561SScott.Carter@Sun.COM
1998561SScott.Carter@Sun.COM if (!(flags & DCMD_ADDRSPEC)) {
2008561SScott.Carter@Sun.COM return (DCMD_ERR);
2018561SScott.Carter@Sun.COM }
2028561SScott.Carter@Sun.COM
2038561SScott.Carter@Sun.COM if (DCMD_HDRSPEC(flags)) {
2048561SScott.Carter@Sun.COM mdb_printf("%<u>%?s %-18s %-8s %-8s %-6s %-4s "
2058561SScott.Carter@Sun.COM "%-6s%</u>\n", "ADDR", "OWNER", "TYPE", "CALLBACK",
2068561SScott.Carter@Sun.COM "NINTRS", "NREQ", "NAVAIL");
2078561SScott.Carter@Sun.COM }
2088561SScott.Carter@Sun.COM
2098561SScott.Carter@Sun.COM if (mdb_vread(&req, sizeof (req), addr) != sizeof (req)) {
2108561SScott.Carter@Sun.COM mdb_warn("couldn't read interrupt request at %p", addr);
2118561SScott.Carter@Sun.COM return (DCMD_ERR);
2128561SScott.Carter@Sun.COM }
2138561SScott.Carter@Sun.COM
2148561SScott.Carter@Sun.COM if (mdb_vread(&dev, sizeof (dev),
2158561SScott.Carter@Sun.COM (uintptr_t)req.ireq_dip) != sizeof (dev)) {
2168561SScott.Carter@Sun.COM mdb_warn("couldn't read dev_info at %p", req.ireq_dip);
2178561SScott.Carter@Sun.COM return (DCMD_ERR);
2188561SScott.Carter@Sun.COM }
2198561SScott.Carter@Sun.COM
2208561SScott.Carter@Sun.COM if (mdb_vread(&intr, sizeof (intr),
2218561SScott.Carter@Sun.COM (uintptr_t)dev.devi_intr_p) != sizeof (intr)) {
2228561SScott.Carter@Sun.COM mdb_warn("couldn't read devinfo_intr at %p", dev.devi_intr_p);
2238561SScott.Carter@Sun.COM return (DCMD_ERR);
2248561SScott.Carter@Sun.COM }
2258561SScott.Carter@Sun.COM
2268561SScott.Carter@Sun.COM mdb_devinfo2driver((uintptr_t)req.ireq_dip, driver, sizeof (driver));
2278561SScott.Carter@Sun.COM mdb_snprintf(devname, sizeof (devname), "%s#%d", driver,
2288561SScott.Carter@Sun.COM dev.devi_instance);
2298561SScott.Carter@Sun.COM
2308561SScott.Carter@Sun.COM mdb_printf("%0?p %-18s %-8s %-8s %-6d %-4d %-6d\n",
2318561SScott.Carter@Sun.COM addr, devname, irm_get_type(req.ireq_type),
2328561SScott.Carter@Sun.COM (req.ireq_flags & DDI_IRM_FLAG_CALLBACK) ? "Yes" : "No",
2338561SScott.Carter@Sun.COM intr.devi_intr_sup_nintrs, req.ireq_nreq, req.ireq_navail);
2348561SScott.Carter@Sun.COM
2358561SScott.Carter@Sun.COM return (DCMD_OK);
2368561SScott.Carter@Sun.COM }
237