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