Home | History | Annotate | Download | only in genunix
      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