17ff178cdSJimmy Vetayases /* 27ff178cdSJimmy Vetayases * CDDL HEADER START 37ff178cdSJimmy Vetayases * 47ff178cdSJimmy Vetayases * The contents of this file are subject to the terms of the 57ff178cdSJimmy Vetayases * Common Development and Distribution License (the "License"). 67ff178cdSJimmy Vetayases * You may not use this file except in compliance with the License. 77ff178cdSJimmy Vetayases * 87ff178cdSJimmy Vetayases * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97ff178cdSJimmy Vetayases * or http://www.opensolaris.org/os/licensing. 107ff178cdSJimmy Vetayases * See the License for the specific language governing permissions 117ff178cdSJimmy Vetayases * and limitations under the License. 127ff178cdSJimmy Vetayases * 137ff178cdSJimmy Vetayases * When distributing Covered Code, include this CDDL HEADER in each 147ff178cdSJimmy Vetayases * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157ff178cdSJimmy Vetayases * If applicable, add the following below this CDDL HEADER, with the 167ff178cdSJimmy Vetayases * fields enclosed by brackets "[]" replaced with your own identifying 177ff178cdSJimmy Vetayases * information: Portions Copyright [yyyy] [name of copyright owner] 187ff178cdSJimmy Vetayases * 197ff178cdSJimmy Vetayases * CDDL HEADER END 207ff178cdSJimmy Vetayases */ 217ff178cdSJimmy Vetayases /* 227ff178cdSJimmy Vetayases * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 237ff178cdSJimmy Vetayases */ 247ff178cdSJimmy Vetayases 257ff178cdSJimmy Vetayases #include "intr_common.h" 267ff178cdSJimmy Vetayases 277ff178cdSJimmy Vetayases /* 287ff178cdSJimmy Vetayases * Globals 297ff178cdSJimmy Vetayases */ 307ff178cdSJimmy Vetayases static apic_irq_t *irq_tbl[APIC_MAX_VECTOR+1]; 317ff178cdSJimmy Vetayases static char level_tbl[APIC_MAX_VECTOR+1]; 327ff178cdSJimmy Vetayases static apix_impl_t *d_apixs[NCPU]; 337ff178cdSJimmy Vetayases static int d_ncpus = NCPU; 347ff178cdSJimmy Vetayases 357ff178cdSJimmy Vetayases 367ff178cdSJimmy Vetayases /* 377ff178cdSJimmy Vetayases * Dump interrupt information for apix PSM. 387ff178cdSJimmy Vetayases */ 397ff178cdSJimmy Vetayases /* ARGSUSED */ 407ff178cdSJimmy Vetayases int 417ff178cdSJimmy Vetayases interrupt_dump_apix(uintptr_t addr, uint_t flags, int argc, 427ff178cdSJimmy Vetayases const mdb_arg_t *argv) 437ff178cdSJimmy Vetayases { 447ff178cdSJimmy Vetayases int i, j; 457ff178cdSJimmy Vetayases apix_impl_t apix; 467ff178cdSJimmy Vetayases apix_vector_t apix_vector; 477ff178cdSJimmy Vetayases struct autovec av; 487ff178cdSJimmy Vetayases apic_irq_t apic_irq; 497ff178cdSJimmy Vetayases 507ff178cdSJimmy Vetayases option_flags = 0; 517ff178cdSJimmy Vetayases if (mdb_getopts(argc, argv, 527ff178cdSJimmy Vetayases 'd', MDB_OPT_SETBITS, INTR_DISPLAY_DRVR_INST, &option_flags, 537ff178cdSJimmy Vetayases 'i', MDB_OPT_SETBITS, INTR_DISPLAY_INTRSTAT, &option_flags, 547ff178cdSJimmy Vetayases NULL) != argc) 557ff178cdSJimmy Vetayases return (DCMD_USAGE); 567ff178cdSJimmy Vetayases 577ff178cdSJimmy Vetayases if (mdb_readvar(&d_apixs, "apixs") == -1) { 587ff178cdSJimmy Vetayases mdb_warn("failed to read apixs"); 597ff178cdSJimmy Vetayases return (DCMD_ERR); 607ff178cdSJimmy Vetayases } 617ff178cdSJimmy Vetayases 627ff178cdSJimmy Vetayases if (mdb_readvar(&d_ncpus, "apic_nproc") == -1) { 637ff178cdSJimmy Vetayases mdb_warn("failed to read apic_nproc"); 647ff178cdSJimmy Vetayases d_ncpus = NCPU; 657ff178cdSJimmy Vetayases } 667ff178cdSJimmy Vetayases if (d_ncpus == 0 || d_ncpus > NCPU) 677ff178cdSJimmy Vetayases d_ncpus = NCPU; 687ff178cdSJimmy Vetayases 697ff178cdSJimmy Vetayases if (mdb_readvar(&irq_tbl, "apic_irq_table") == -1) { 707ff178cdSJimmy Vetayases mdb_warn("failed to read apic_irq_table"); 717ff178cdSJimmy Vetayases return (DCMD_ERR); 727ff178cdSJimmy Vetayases } 737ff178cdSJimmy Vetayases 747ff178cdSJimmy Vetayases if (mdb_readvar(&level_tbl, "apic_level_intr") == -1) { 757ff178cdSJimmy Vetayases mdb_warn("failed to read apic_level_intr"); 767ff178cdSJimmy Vetayases return (DCMD_ERR); 777ff178cdSJimmy Vetayases } 787ff178cdSJimmy Vetayases 797ff178cdSJimmy Vetayases /* Print the header first */ 807ff178cdSJimmy Vetayases if (option_flags & INTR_DISPLAY_INTRSTAT) 817ff178cdSJimmy Vetayases mdb_printf("%<u>CPU "); 827ff178cdSJimmy Vetayases else 837ff178cdSJimmy Vetayases mdb_printf("%<u>CPU/Vect IRQ IPL Bus Trg Type " 847ff178cdSJimmy Vetayases "Share APIC/INT# "); 857ff178cdSJimmy Vetayases mdb_printf("%s %</u>\n", option_flags & INTR_DISPLAY_DRVR_INST ? 867ff178cdSJimmy Vetayases "Driver Name(s)" : "ISR"); 877ff178cdSJimmy Vetayases 887ff178cdSJimmy Vetayases /* Walk all the entries */ 897ff178cdSJimmy Vetayases for (i = 0; i < d_ncpus; i++) { 907ff178cdSJimmy Vetayases /* Read the per CPU apix entry */ 917ff178cdSJimmy Vetayases if (mdb_vread(&apix, sizeof (apix_impl_t), 927ff178cdSJimmy Vetayases (uintptr_t)d_apixs[i]) == -1) 937ff178cdSJimmy Vetayases continue; 947ff178cdSJimmy Vetayases for (j = 0; j < APIX_NVECTOR; j++) { 957ff178cdSJimmy Vetayases /* Read the vector entry */ 967ff178cdSJimmy Vetayases if (mdb_vread(&apix_vector, sizeof (apix_vector_t), 977ff178cdSJimmy Vetayases (uintptr_t)apix.x_vectbl[j]) == -1) 987ff178cdSJimmy Vetayases continue; 997ff178cdSJimmy Vetayases /* If invalid vector state; continue */ 1007ff178cdSJimmy Vetayases if (apix_vector.v_state == APIX_STATE_FREED || 1017ff178cdSJimmy Vetayases apix_vector.v_state == APIX_STATE_OBSOLETED) 1027ff178cdSJimmy Vetayases continue; 1037ff178cdSJimmy Vetayases if (apix_vector.v_type == APIX_TYPE_IPI) 1047ff178cdSJimmy Vetayases continue; 1057ff178cdSJimmy Vetayases if (mdb_vread(&av, sizeof (struct autovec), 1067ff178cdSJimmy Vetayases (uintptr_t)(apix_vector.v_autovect)) == -1) 1077ff178cdSJimmy Vetayases continue; 1087ff178cdSJimmy Vetayases if ((apix_vector.v_type == APIX_TYPE_FIXED) && 1097ff178cdSJimmy Vetayases (mdb_vread(&apic_irq, sizeof (apic_irq_t), 1107ff178cdSJimmy Vetayases (uintptr_t)irq_tbl[apix_vector.v_inum]) == -1)) 1117ff178cdSJimmy Vetayases continue; 1127ff178cdSJimmy Vetayases 1137ff178cdSJimmy Vetayases apix_interrupt_dump(&apix_vector, &apic_irq, &av, 1147ff178cdSJimmy Vetayases NULL, level_tbl[apix_vector.v_inum]); 1157ff178cdSJimmy Vetayases } 1167ff178cdSJimmy Vetayases } 1177ff178cdSJimmy Vetayases /* print IPIs */ 1187ff178cdSJimmy Vetayases if (mdb_vread(&apix, sizeof (apix_impl_t), 1197ff178cdSJimmy Vetayases (uintptr_t)d_apixs[0]) != -1) { 1207ff178cdSJimmy Vetayases for (j = 0; j < APIX_NVECTOR; j++) { 1217ff178cdSJimmy Vetayases /* Read the vector entry */ 1227ff178cdSJimmy Vetayases if (mdb_vread(&apix_vector, sizeof (apix_vector_t), 1237ff178cdSJimmy Vetayases (uintptr_t)apix.x_vectbl[j]) == -1) 1247ff178cdSJimmy Vetayases continue; 1257ff178cdSJimmy Vetayases /* If invalid vector state; continue */ 1267ff178cdSJimmy Vetayases if (apix_vector.v_state == APIX_STATE_FREED || 1277ff178cdSJimmy Vetayases apix_vector.v_state == APIX_STATE_OBSOLETED) 1287ff178cdSJimmy Vetayases continue; 1297ff178cdSJimmy Vetayases if (apix_vector.v_type != APIX_TYPE_IPI) 1307ff178cdSJimmy Vetayases continue; 1317ff178cdSJimmy Vetayases if (mdb_vread(&av, sizeof (struct autovec), 1327ff178cdSJimmy Vetayases (uintptr_t)(apix_vector.v_autovect)) == -1) { 1337ff178cdSJimmy Vetayases /* v_share for poke_cpu is 0 */ 1347ff178cdSJimmy Vetayases if (apix_vector.v_share != 0) 1357ff178cdSJimmy Vetayases continue; 1367ff178cdSJimmy Vetayases } 1377ff178cdSJimmy Vetayases apix_interrupt_ipi_dump(&apix_vector, &av, NULL); 1387ff178cdSJimmy Vetayases } 1397ff178cdSJimmy Vetayases } 1407ff178cdSJimmy Vetayases 1417ff178cdSJimmy Vetayases return (DCMD_OK); 1427ff178cdSJimmy Vetayases } 1437ff178cdSJimmy Vetayases 1447ff178cdSJimmy Vetayases /* 1457ff178cdSJimmy Vetayases * MDB module linkage information: 1467ff178cdSJimmy Vetayases * 1477ff178cdSJimmy Vetayases * We declare a list of structures describing our dcmds, and a function 1487ff178cdSJimmy Vetayases * named _mdb_init to return a pointer to our module information. 1497ff178cdSJimmy Vetayases */ 1507ff178cdSJimmy Vetayases static const mdb_dcmd_t dcmds[] = { 1517ff178cdSJimmy Vetayases { "interrupts", "?[-di]", "print interrupts", interrupt_dump_apix, 1527ff178cdSJimmy Vetayases interrupt_help}, 1537ff178cdSJimmy Vetayases { "softint", "?[-d]", "print soft interrupts", soft_interrupt_dump, 1547ff178cdSJimmy Vetayases soft_interrupt_help}, 155*5cd376e8SJimmy Vetayases #ifdef _KMDB 1567ff178cdSJimmy Vetayases { "apic", NULL, "print apic register contents", apic }, 1577ff178cdSJimmy Vetayases { "ioapic", NULL, "print ioapic register contents", ioapic }, 158*5cd376e8SJimmy Vetayases #endif /* _KMDB */ 1597ff178cdSJimmy Vetayases { NULL } 1607ff178cdSJimmy Vetayases }; 1617ff178cdSJimmy Vetayases 1627ff178cdSJimmy Vetayases static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, NULL }; 1637ff178cdSJimmy Vetayases 1647ff178cdSJimmy Vetayases const mdb_modinfo_t * 1657ff178cdSJimmy Vetayases _mdb_init(void) 1667ff178cdSJimmy Vetayases { 1677ff178cdSJimmy Vetayases GElf_Sym sym; 1687ff178cdSJimmy Vetayases 1697ff178cdSJimmy Vetayases if (mdb_lookup_by_name("gld_intr", &sym) != -1) 1707ff178cdSJimmy Vetayases if (GELF_ST_TYPE(sym.st_info) == STT_FUNC) 1717ff178cdSJimmy Vetayases gld_intr_addr = (uintptr_t)sym.st_value; 1727ff178cdSJimmy Vetayases 1737ff178cdSJimmy Vetayases return (&modinfo); 1747ff178cdSJimmy Vetayases } 175