/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include "intr_common.h" #ifdef _KMDB /* Macros for reading/writing the IOAPIC RDT entries */ #define APIC_READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, ipin) \ apic_ioapic_read(ioapic_ix, APIC_RDT_CMD + (2 * (ipin))) #define APIC_READ_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapic_ix, ipin) \ apic_ioapic_read(ioapic_ix, APIC_RDT_CMD2 + (2 * (ipin))) static uint32_t *ioapic_adr[MAX_IO_APIC]; static uint32_t apic_ioapic_read(int ioapic_ix, uint32_t reg) { volatile uint32_t *ioapic; ioapic = ioapic_adr[ioapic_ix]; ioapic[APIC_IO_REG] = reg; return (ioapic[APIC_IO_DATA]); } /* * ioapic dcmd - Print out the ioapic registers, nicely formatted. */ /*ARGSUSED*/ int ioapic(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uint32_t apic_io_max; int reg; int reg_max; int i; if ((flags & DCMD_ADDRSPEC) || argc != 0) return (DCMD_USAGE); if (mdb_readvar(&ioapic_adr, "apicioadr") == -1) { /* * If the mdb_warn string does not end in a \n, mdb will * automatically append the reason for the failure. */ mdb_warn("failed to read ioapicadr"); return (DCMD_ERR); } if (mdb_readvar(&apic_io_max, "apic_io_max") == -1) { /* * If the mdb_warn string does not end in a \n, mdb will * automatically append the reason for the failure. */ mdb_warn("failed to read apic_io_max"); return (DCMD_ERR); } mdb_printf("ioapicadr\t%p\n", ioapic_adr); for (i = 0; i < apic_io_max; i++) { /* Bits 23-16 define the maximum redirection entries */ reg_max = apic_ioapic_read(i, APIC_VERS_CMD); reg_max = (reg_max >> 16) & 0xff; mdb_printf("%4s %8s %8s\n", "reg", "high", " low"); for (reg = 0; reg <= reg_max; reg++) { uint32_t high, low; high = APIC_READ_IOAPIC_RDT_ENTRY_HIGH_DWORD(i, reg); low = APIC_READ_IOAPIC_RDT_ENTRY_LOW_DWORD(i, reg); mdb_printf("%2d %8x %8x\n", reg, high, low); } mdb_printf("\n"); } return (DCMD_OK); } /* * apic dcmd - Print out the apic registers, nicely formatted. */ /*ARGSUSED*/ int apic(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uint32_t *papic; if ((flags & DCMD_ADDRSPEC) || argc != 0) return (DCMD_USAGE); if (mdb_readvar(&papic, "apicadr") == -1) { /* * If the mdb_warn string does not end in a \n, mdb will * automatically append the reason for the failure. */ mdb_warn("failed to read apicadr"); return (DCMD_ERR); } mdb_printf("apicadr\t%p\n", papic); mdb_printf("as_task_reg\t%x\n", papic[APIC_TASK_REG]); mdb_printf("as_dest_reg\t%x\n", papic[APIC_DEST_REG]); mdb_printf("as_format_reg\t%x\n", papic[APIC_FORMAT_REG]); mdb_printf("as_local_timer\t%x\n", papic[APIC_LOCAL_TIMER]); mdb_printf("as_pcint_vect\t%x\n", papic[APIC_PCINT_VECT]); mdb_printf("as_int_vect0\t%x\n", papic[APIC_INT_VECT0]); mdb_printf("as_int_vect1\t%x\n", papic[APIC_INT_VECT1]); mdb_printf("as_err_vect\t%x\n", papic[APIC_ERR_VECT]); mdb_printf("as_init_count\t%x\n", papic[APIC_INIT_COUNT]); mdb_printf("as_divide_reg\t%x\n", papic[APIC_DIVIDE_REG]); mdb_printf("as_spur_int_reg\t%x\n", papic[APIC_SPUR_INT_REG]); return (DCMD_OK); } #endif /* _KMDB */