Home | History | Annotate | Download | only in pcplusmp
      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 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #include "intr_common.h"
     29 
     30 /*
     31  * Globals
     32  */
     33 static struct av_head	avec_tbl[APIC_MAX_VECTOR+1];
     34 static apic_irq_t	*irq_tbl[APIC_MAX_VECTOR+1], airq;
     35 static char		level_tbl[APIC_MAX_VECTOR+1];
     36 
     37 /*
     38  * interrupt_dump:
     39  *
     40  *	Dump interrupt information.
     41  */
     42 /* ARGSUSED */
     43 int
     44 interrupt_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
     45 {
     46 	int		i;
     47 
     48 	option_flags = 0;
     49 	if (mdb_getopts(argc, argv,
     50 	    'd', MDB_OPT_SETBITS, INTR_DISPLAY_DRVR_INST, &option_flags,
     51 	    'i', MDB_OPT_SETBITS, INTR_DISPLAY_INTRSTAT, &option_flags,
     52 	    NULL) != argc)
     53 		return (DCMD_USAGE);
     54 
     55 	if (mdb_readvar(&irq_tbl, "apic_irq_table") == -1) {
     56 		mdb_warn("failed to read apic_irq_table");
     57 		return (DCMD_ERR);
     58 	}
     59 
     60 	if (mdb_readvar(&level_tbl, "apic_level_intr") == -1) {
     61 		mdb_warn("failed to read apic_level_intr");
     62 		return (DCMD_ERR);
     63 	}
     64 
     65 	if (mdb_readvar(&avec_tbl, "autovect") == -1) {
     66 		mdb_warn("failed to read autovect");
     67 		return (DCMD_ERR);
     68 	}
     69 
     70 	/* Print the header first */
     71 	if (option_flags & INTR_DISPLAY_INTRSTAT)
     72 		mdb_printf("%<u>CPU ");
     73 	else
     74 		mdb_printf(
     75 		    "%<u>IRQ  Vect IPL Bus    Trg Type   CPU Share APIC/INT# ");
     76 	mdb_printf("%s %</u>\n", option_flags & INTR_DISPLAY_DRVR_INST ?
     77 	    "Driver Name(s)" : "ISR(s)");
     78 
     79 	/* Walk all the entries */
     80 	for (i = 0; i < APIC_MAX_VECTOR + 1; i++) {
     81 		/* Read the entry */
     82 		if (mdb_vread(&airq, sizeof (apic_irq_t),
     83 		    (uintptr_t)irq_tbl[i]) == -1)
     84 			continue;
     85 
     86 		apic_interrupt_dump(&airq, &avec_tbl[i], i, NULL, level_tbl[i]);
     87 	}
     88 
     89 	return (DCMD_OK);
     90 }
     91 
     92 /* Macros for reading/writing the IOAPIC RDT entries */
     93 #define	READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, ipin) \
     94 	ioapic_read(ioapic_ix, APIC_RDT_CMD + (2 * (ipin)))
     95 
     96 #define	READ_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapic_ix, ipin) \
     97 	ioapic_read(ioapic_ix, APIC_RDT_CMD2 + (2 * (ipin)))
     98 
     99 static uint32_t *ioapic_adr[MAX_IO_APIC];
    100 
    101 uint32_t
    102 ioapic_read(int ioapic_ix, uint32_t reg)
    103 {
    104 	volatile uint32_t *ioapic;
    105 
    106 	ioapic = ioapic_adr[ioapic_ix];
    107 	ioapic[APIC_IO_REG] = reg;
    108 	return (ioapic[APIC_IO_DATA]);
    109 }
    110 
    111 /*
    112  * ioapic dcmd - Print out the ioapic registers, nicely formatted.
    113  */
    114 /*ARGSUSED*/
    115 static int
    116 ioapic(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    117 {
    118 	uint32_t apic_io_max;
    119 	int	reg;
    120 	int	reg_max;
    121 	int	i;
    122 
    123 
    124 	if ((flags & DCMD_ADDRSPEC) || argc != 0)
    125 		return (DCMD_USAGE);
    126 
    127 	if (mdb_readvar(&ioapic_adr, "apicioadr") == -1) {
    128 		/*
    129 		 * If the mdb_warn string does not end in a \n, mdb will
    130 		 * automatically append the reason for the failure.
    131 		 */
    132 		mdb_warn("failed to read ioapicadr");
    133 		return (DCMD_ERR);
    134 	}
    135 
    136 	if (mdb_readvar(&apic_io_max, "apic_io_max") == -1) {
    137 		/*
    138 		 * If the mdb_warn string does not end in a \n, mdb will
    139 		 * automatically append the reason for the failure.
    140 		 */
    141 		mdb_warn("failed to read apic_io_max");
    142 		return (DCMD_ERR);
    143 	}
    144 
    145 	mdb_printf("ioapicadr\t%p\n", ioapic_adr);
    146 
    147 	for (i = 0; i < apic_io_max; i++) {
    148 		/* Bits 23-16 define the maximum redirection entries */
    149 		reg_max = ioapic_read(i, APIC_VERS_CMD);
    150 		reg_max = (reg_max >> 16) & 0xff;
    151 
    152 		mdb_printf("%4s %8s %8s\n", "reg", "high", " low");
    153 		for (reg = 0; reg <= reg_max; reg++) {
    154 			uint32_t high, low;
    155 
    156 			high = READ_IOAPIC_RDT_ENTRY_HIGH_DWORD(i, reg);
    157 			low = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(i, reg);
    158 
    159 			mdb_printf("%2d   %8x %8x\n", reg, high, low);
    160 		}
    161 
    162 		mdb_printf("\n");
    163 
    164 	}
    165 
    166 	return (DCMD_OK);
    167 }
    168 
    169 
    170 /*
    171  * apic dcmd - Print out the apic registers, nicely formatted.
    172  */
    173 /*ARGSUSED*/
    174 static int
    175 apic(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    176 {
    177 	uint32_t *papic;
    178 
    179 	if ((flags & DCMD_ADDRSPEC) || argc != 0)
    180 		return (DCMD_USAGE);
    181 
    182 	if (mdb_readvar(&papic, "apicadr") == -1) {
    183 		/*
    184 		 * If the mdb_warn string does not end in a \n, mdb will
    185 		 * automatically append the reason for the failure.
    186 		 */
    187 		mdb_warn("failed to read apicadr");
    188 		return (DCMD_ERR);
    189 	}
    190 
    191 	mdb_printf("apicadr\t%p\n", papic);
    192 	mdb_printf("as_task_reg\t%x\n", papic[APIC_TASK_REG]);
    193 	mdb_printf("as_dest_reg\t%x\n", papic[APIC_DEST_REG]);
    194 	mdb_printf("as_format_reg\t%x\n", papic[APIC_FORMAT_REG]);
    195 	mdb_printf("as_local_timer\t%x\n", papic[APIC_LOCAL_TIMER]);
    196 	mdb_printf("as_pcint_vect\t%x\n", papic[APIC_PCINT_VECT]);
    197 	mdb_printf("as_int_vect0\t%x\n", papic[APIC_INT_VECT0]);
    198 	mdb_printf("as_int_vect1\t%x\n", papic[APIC_INT_VECT1]);
    199 	mdb_printf("as_err_vect\t%x\n", papic[APIC_ERR_VECT]);
    200 	mdb_printf("as_init_count\t%x\n", papic[APIC_INIT_COUNT]);
    201 	mdb_printf("as_divide_reg\t%x\n", papic[APIC_DIVIDE_REG]);
    202 	mdb_printf("as_spur_int_reg\t%x\n", papic[APIC_SPUR_INT_REG]);
    203 
    204 	return (DCMD_OK);
    205 }
    206 
    207 
    208 /*
    209  * MDB module linkage information:
    210  *
    211  * We declare a list of structures describing our dcmds, and a function
    212  * named _mdb_init to return a pointer to our module information.
    213  */
    214 static const mdb_dcmd_t dcmds[] = {
    215 	{ "interrupts", "?[-di]", "print interrupts", interrupt_dump,
    216 	    interrupt_help},
    217 	{ "softint", "?[-d]", "print soft interrupts", soft_interrupt_dump,
    218 	    soft_interrupt_help},
    219 	{ "apic", NULL, "print apic register contents", apic },
    220 	{ "ioapic", NULL, "print ioapic register contents", ioapic },
    221 	{ NULL }
    222 };
    223 
    224 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, NULL };
    225 
    226 const mdb_modinfo_t *
    227 _mdb_init(void)
    228 {
    229 	GElf_Sym	sym;
    230 
    231 	if (mdb_lookup_by_name("gld_intr", &sym) != -1)
    232 		if (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
    233 			gld_intr_addr = (uintptr_t)sym.st_value;
    234 
    235 	return (&modinfo);
    236 }
    237