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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <sys/mdb_modapi.h> 26 #include <sys/proc.h> 27 #include <sys/types.h> 28 #include <sys/sunddi.h> 29 #include <sys/ddi_intr.h> 30 #include <sys/ddi_intr_impl.h> 31 #include <stddef.h> 32 33 #include "list.h" 34 35 extern int mdb_devinfo2driver(uintptr_t, char *, size_t); 36 37 static char * 38 irm_get_type(int type) 39 { 40 if (type == (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_MSIX)) 41 return ("MSI/X"); 42 43 switch (type) { 44 case DDI_INTR_TYPE_FIXED: 45 return ("Fixed"); 46 case DDI_INTR_TYPE_MSI: 47 return ("MSI"); 48 case DDI_INTR_TYPE_MSIX: 49 return ("MSI-X"); 50 default: 51 return ("Unknown"); 52 } 53 } 54 55 static int 56 check_irm_enabled(void) 57 { 58 GElf_Sym sym; 59 uintptr_t addr; 60 int value; 61 62 if (mdb_lookup_by_name("irm_enable", &sym) == -1) { 63 mdb_warn("couldn't find irm_enable"); 64 return (0); 65 } 66 67 addr = (uintptr_t)sym.st_value; 68 69 if (mdb_vread(&value, sizeof (value), addr) != sizeof (value)) { 70 mdb_warn("couldn't read irm_enable at %p", addr); 71 return (0); 72 } 73 74 return (value); 75 } 76 77 int 78 irmpools_walk_init(mdb_walk_state_t *wsp) 79 { 80 GElf_Sym sym; 81 82 if (mdb_lookup_by_name("irm_pools_list", &sym) == -1) { 83 mdb_warn("couldn't find irm_pools_list"); 84 return (WALK_ERR); 85 } 86 87 wsp->walk_addr = (uintptr_t)sym.st_value; 88 89 return (list_walk_init_named(wsp, "interrupt pools", "pool")); 90 } 91 92 int 93 irmreqs_walk_init(mdb_walk_state_t *wsp) 94 { 95 wsp->walk_addr = (uintptr_t)(wsp->walk_addr + 96 offsetof(ddi_irm_pool_t, ipool_req_list)); 97 98 return (list_walk_init_named(wsp, "interrupt requests", "request")); 99 } 100 101 int 102 irmpools_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 103 { 104 ddi_irm_pool_t pool; 105 struct dev_info dev; 106 char driver[MODMAXNAMELEN + 1] = ""; 107 char devname[MODMAXNAMELEN + 1] = ""; 108 109 if (argc != 0) 110 return (DCMD_USAGE); 111 112 if (check_irm_enabled() == 0) { 113 mdb_warn("IRM is not enabled"); 114 return (DCMD_ERR); 115 } 116 117 if (!(flags & DCMD_ADDRSPEC)) { 118 if (mdb_walk_dcmd("irmpools", "irmpools", argc, argv) == -1) { 119 mdb_warn("can't walk interrupt pools"); 120 return (DCMD_ERR); 121 } 122 return (DCMD_OK); 123 } 124 125 if (DCMD_HDRSPEC(flags)) { 126 mdb_printf("%<u>%?s %-18s %-8s %-6s %-9s %-8s%</u>\n", 127 "ADDR", "OWNER", "TYPE", "SIZE", "REQUESTED", "RESERVED"); 128 } 129 130 if (mdb_vread(&pool, sizeof (pool), addr) != sizeof (pool)) { 131 mdb_warn("couldn't read interrupt pool at %p", addr); 132 return (DCMD_ERR); 133 } 134 135 if (mdb_vread(&dev, sizeof (dev), 136 (uintptr_t)pool.ipool_owner) != sizeof (dev)) { 137 mdb_warn("couldn't read dev_info at %p", pool.ipool_owner); 138 return (DCMD_ERR); 139 } 140 141 mdb_devinfo2driver((uintptr_t)pool.ipool_owner, driver, 142 sizeof (driver)); 143 /* 144 * Include driver instance number only if the node has an 145 * instance number assigned (i.e. instance != -1) to it. 146 * This will cover cases like rootnex driver which doesn't 147 * have instance number assigned to it. 148 */ 149 if (dev.devi_instance != -1) 150 mdb_snprintf(devname, sizeof (devname), "%s#%d", driver, 151 dev.devi_instance); 152 else 153 mdb_snprintf(devname, sizeof (devname), "%s", driver); 154 155 mdb_printf("%0?p %-18s %-8s %-6d %-9d %-8d\n", addr, devname, 156 irm_get_type(pool.ipool_types), pool.ipool_totsz, 157 pool.ipool_reqno, pool.ipool_resno); 158 159 return (DCMD_OK); 160 } 161 162 int 163 irmreqs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 164 { 165 if (argc != 0) 166 return (DCMD_USAGE); 167 168 if (check_irm_enabled() == 0) { 169 mdb_warn("IRM is not enabled"); 170 return (DCMD_ERR); 171 } 172 173 if (!(flags & DCMD_ADDRSPEC)) { 174 mdb_warn("can't perform global interrupt request walk"); 175 return (DCMD_ERR); 176 } 177 178 if (mdb_pwalk_dcmd("irmreqs", "irmreq", argc, argv, addr) == -1) { 179 mdb_warn("can't walk interrupt requests"); 180 return (DCMD_ERR); 181 } 182 183 return (DCMD_OK); 184 } 185 186 /*ARGSUSED*/ 187 int 188 irmreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 189 { 190 ddi_irm_req_t req; 191 struct dev_info dev; 192 struct devinfo_intr intr; 193 char driver[MODMAXNAMELEN + 1] = ""; 194 char devname[MODMAXNAMELEN + 1] = ""; 195 196 if (argc != 0) 197 return (DCMD_USAGE); 198 199 if (!(flags & DCMD_ADDRSPEC)) { 200 return (DCMD_ERR); 201 } 202 203 if (DCMD_HDRSPEC(flags)) { 204 mdb_printf("%<u>%?s %-18s %-8s %-8s %-6s %-4s " 205 "%-6s%</u>\n", "ADDR", "OWNER", "TYPE", "CALLBACK", 206 "NINTRS", "NREQ", "NAVAIL"); 207 } 208 209 if (mdb_vread(&req, sizeof (req), addr) != sizeof (req)) { 210 mdb_warn("couldn't read interrupt request at %p", addr); 211 return (DCMD_ERR); 212 } 213 214 if (mdb_vread(&dev, sizeof (dev), 215 (uintptr_t)req.ireq_dip) != sizeof (dev)) { 216 mdb_warn("couldn't read dev_info at %p", req.ireq_dip); 217 return (DCMD_ERR); 218 } 219 220 if (mdb_vread(&intr, sizeof (intr), 221 (uintptr_t)dev.devi_intr_p) != sizeof (intr)) { 222 mdb_warn("couldn't read devinfo_intr at %p", dev.devi_intr_p); 223 return (DCMD_ERR); 224 } 225 226 mdb_devinfo2driver((uintptr_t)req.ireq_dip, driver, sizeof (driver)); 227 mdb_snprintf(devname, sizeof (devname), "%s#%d", driver, 228 dev.devi_instance); 229 230 mdb_printf("%0?p %-18s %-8s %-8s %-6d %-4d %-6d\n", 231 addr, devname, irm_get_type(req.ireq_type), 232 (req.ireq_flags & DDI_IRM_FLAG_CALLBACK) ? "Yes" : "No", 233 intr.devi_intr_sup_nintrs, req.ireq_nreq, req.ireq_navail); 234 235 return (DCMD_OK); 236 } 237