diff options
Diffstat (limited to 'usr/src/cmd')
21 files changed, 2923 insertions, 1974 deletions
diff --git a/usr/src/cmd/fm/dicts/PCIEX.dict b/usr/src/cmd/fm/dicts/PCIEX.dict index 5edb88e848..b2934b9de6 100644 --- a/usr/src/cmd/fm/dicts/PCIEX.dict +++ b/usr/src/cmd/fm/dicts/PCIEX.dict @@ -50,3 +50,7 @@ fault.io.pciex.device-interr-unaf=20 fault.io.pciex.device-interr-deg=21 fault.io.pciex.fw_corrupt=22 fault.io.pciex.fw_mismatch=23 +fault.io.pciex.rc.generic-ce=24 +fault.io.pciex.rc.generic-ue=25 +fault.io.pciex.rc.generic-sw=26 +fault.io.pciex.rc.generic-fw=27 diff --git a/usr/src/cmd/fm/dicts/PCIEX.po b/usr/src/cmd/fm/dicts/PCIEX.po index 09bb2c2fc2..a35c83b22a 100644 --- a/usr/src/cmd/fm/dicts/PCIEX.po +++ b/usr/src/cmd/fm/dicts/PCIEX.po @@ -390,7 +390,7 @@ msgstr "One or more device instances may be disabled.\n" msgid "PCIEX-8000-PY.impact" msgstr "Degraded services provided by the device instances associated with this fault.\n" msgid "PCIEX-8000-PY.action" -msgstr "Use fmadm faulty to identify the device and then update the firmware to the latest version or schedule a repair procedure to replace the affected device. Contact Sun support for further information.\n" +msgstr "Use 'fmadm faulty' to identify the device and then update the firmware to the latest version or schedule a repair procedure to replace the affected device. Contact Sun support for further information.\n" # # code: PCIEX-8000-Q3 # keys: fault.io.pciex.fw_mismatch @@ -406,4 +406,68 @@ msgstr "One or more device instances may be disabled.\n" msgid "PCIEX-8000-Q3.impact" msgstr "Degraded services provided by the device instances associated with this fault.\n" msgid "PCIEX-8000-Q3.action" -msgstr "Use fmadm faulty to identify the device and then update the firmware to the latest version. Contact Sun support for further information.\n" +msgstr "Use 'fmadm faulty' to identify the device and then update the firmware to the latest version. Contact Sun support for further information.\n" +# +# code: PCIEX-8000-RC +# keys: fault.io.pciex.rc.generic-ce +# +msgid "PCIEX-8000-RC.type" +msgstr "Fault" +msgid "PCIEX-8000-RC.severity" +msgstr "Critical" +msgid "PCIEX-8000-RC.description" +msgstr "The number of correctable errors detected in the PCIe Root Complex has crossed the allowed threshold.\n" +msgid "PCIEX-8000-RC.response" +msgstr "One or more device instances may be disabled\n" +msgid "PCIEX-8000-RC.impact" +msgstr "Loss of services provided by the device\ninstances associated with this fault\n" +msgid "PCIEX-8000-RC.action" +msgstr "Schedule a repair procedure to replace the affected\ndevice if necessary, or contact Sun for support.\n" +# +# code: PCIEX-8000-SQ +# keys: fault.io.pciex.rc.generic-ue +# +msgid "PCIEX-8000-SQ.type" +msgstr "Fault" +msgid "PCIEX-8000-SQ.severity" +msgstr "Critical" +msgid "PCIEX-8000-SQ.description" +msgstr "An uncorrectable error was detected in the PCIe Root Complex.\n Refer to %s for more information." +msgid "PCIEX-8000-SQ.response" +msgstr "One or more device instances may be disabled\n" +msgid "PCIEX-8000-SQ.impact" +msgstr "Loss of services provided by the device\ninstances associated with this fault\n" +msgid "PCIEX-8000-SQ.action" +msgstr "Schedule a repair procedure to replace the affected\ndevice if necessary, or contact Sun for support.\n" +# +# code: PCIEX-8000-T4 +# keys: fault.io.pciex.rc.generic-sw +# +msgid "PCIEX-8000-T4.type" +msgstr "Fault" +msgid "PCIEX-8000-T4.severity" +msgstr "Critical" +msgid "PCIEX-8000-T4.description" +msgstr "A defect in the PCIe Root Complex or Root Port code has been detected.\n Refer to %s for more information." +msgid "PCIEX-8000-T4.response" +msgstr "One or more device instances may be disabled\n" +msgid "PCIEX-8000-T4.impact" +msgstr "Loss of services provided by the device\ninstances associated with this fault\n" +msgid "PCIEX-8000-T4.action" +msgstr "Schedule a repair procedure to replace the affected\ndevice if necessary, or contact Sun for support.\n" +# +# code: PCIEX-8000-UR +# keys: fault.io.pciex.rc.generic-fw +# +msgid "PCIEX-8000-UR.type" +msgstr "Fault" +msgid "PCIEX-8000-UR.severity" +msgstr "Critical" +msgid "PCIEX-8000-UR.description" +msgstr "A defective firmware associated with the PCIe Root Complex has been detected.\n Refer to %s for more information." +msgid "PCIEX-8000-UR.response" +msgstr "One or more device instances may be disabled\n" +msgid "PCIEX-8000-UR.impact" +msgstr "Loss of services provided by the device\ninstances associated with this fault\n" +msgid "PCIEX-8000-UR.action" +msgstr "Schedule a repair procedure to replace the affected\ndevice if necessary, or contact Sun for support.\n" diff --git a/usr/src/cmd/fm/dicts/SUN4V.dict b/usr/src/cmd/fm/dicts/SUN4V.dict index cdf7683b33..ba51084f36 100644 --- a/usr/src/cmd/fm/dicts/SUN4V.dict +++ b/usr/src/cmd/fm/dicts/SUN4V.dict @@ -1,5 +1,5 @@ # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # CDDL HEADER START @@ -116,3 +116,4 @@ fault.memory.memlink-uc=87 defect.fw.generic-sparc.addr-oob=88 defect.fw.generic-sparc.erpt-gen=89 fault.cpu.generic-sparc.bootbus=90 +fault.sp.failed=91 diff --git a/usr/src/cmd/fm/dicts/SUN4V.po b/usr/src/cmd/fm/dicts/SUN4V.po index 7066e61dc3..34da106f9c 100644 --- a/usr/src/cmd/fm/dicts/SUN4V.po +++ b/usr/src/cmd/fm/dicts/SUN4V.po @@ -1463,3 +1463,19 @@ msgid "SUN4V-8002-T5.impact" msgstr "The system's integrity is seriously compromised. Processor chip(s)\nmay be unavailable.\n" msgid "SUN4V-8002-T5.action" msgstr "Schedule a repair procedure to replace the affected resource, the identity of which can be determined using 'fmadm faulty'.\n" +# +# code: SUN4V-8002-US +# keys: fault.sp.failed +# +msgid "SUN4V-8002-US.type" +msgstr "Fault" +msgid "SUN4V-8002-US.severity" +msgstr "Critical" +msgid "SUN4V-8002-US.description" +msgstr "The Service Processor failed.\n Refer to %s for more information." +msgid "SUN4V-8002-US.response" +msgstr "No automated response.\n" +msgid "SUN4V-8002-US.impact" +msgstr "Some services such as Fault Diagnosis may be degraded as a result.\n" +msgid "SUN4V-8002-US.action" +msgstr "Schedule a repair procedure for the Service Processor, or contact Sun for support.\n" diff --git a/usr/src/cmd/fm/eversholt/files/Makefile.com b/usr/src/cmd/fm/eversholt/files/Makefile.com index 88ed0680f2..c5a22b3a7b 100644 --- a/usr/src/cmd/fm/eversholt/files/Makefile.com +++ b/usr/src/cmd/fm/eversholt/files/Makefile.com @@ -19,10 +19,9 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" .SUFFIXES: .eft .esc @@ -54,8 +53,11 @@ clean clobber: $(RM) $(EFT_PLAT_FILES) $(EFT_COMMON_FILES) \ $(USR_PLAT_EFT_FILES) $(ROOT_COMMON_EFT_FILES) +ESCFLAGS= -D_ESC -I$(ROOT)/usr/include +pciexrc.eft := ESCFLAGS += -I$(SRC)/uts/sun4v/io/px + %.eft: ../common/%.esc - $(ESC) -I$(ROOT)/usr/include -o $@ $< + $(ESC) $(ESCFLAGS) -o $@ $< %.eft: %.esc - $(ESC) -o $@ $< + $(ESC) $(ESCFLAGS) -o $@ $< diff --git a/usr/src/cmd/fm/eversholt/files/common/pciexrc.esc b/usr/src/cmd/fm/eversholt/files/common/pciexrc.esc new file mode 100644 index 0000000000..66a4921b2d --- /dev/null +++ b/usr/src/cmd/fm/eversholt/files/common/pciexrc.esc @@ -0,0 +1,218 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma dictionary "PCIEX" + +#include <px_err.h> + +/* + * generic root complex/root port diagnosis rules + */ + +#define PCIEXFN pciexbus/pciexdev/pciexfn +#define PCIEXFNHZ pciexbus<>/pciexdev<>/pciexfn<> + +#define RC_N 5 +#define RC_T 72h + +#define SW_FIT 5000 +#define FW_FIT 5000 +#define HB_FIT 400 + +#define EPKT_DESC (payloadprop("desc") >> 12) +#define EPKT_B_BIT (payloadprop("desc") & (1 << 7)) +#define EPKT_C_BIT (payloadprop("desc") & (1 << 5)) +#define EPKT_H_BIT (payloadprop("desc") & (1 << 4)) + +#define MATCHES_DESC(b, o, p, c, d) \ + (EPKT_DESC == (b << 16 | o << 12 | p << 8 | c << 4 | d)) + +#define IS_CE (EPKT_C_BIT != 0 && setserdsuffix(EPKT_DESC)) +#define IS_UE (EPKT_C_BIT == 0) +#define IS_BLOCKED (EPKT_B_BIT != 0) + +#define EPKT(b, o, p, c, d) \ + ereport.io.pciex.rc.epkt@hostbridge { MATCHES_DESC(b, o, p, c, d) } + +/* Ereport Events */ +event ereport.io.pciex.rc.epkt@hostbridge {within(5s)}; + +/* Internal Events */ +event error.io.pciex.rc.stall@hostbridge; +event error.io.pciex.rc.poiscomp@hostbridge; +event error.io.pciex.nr-d@hostbridge/pciexrc/PCIEXFN; +event error.io.pciex.badreq-u@hostbridge/pciexrc/PCIEXFN; +event error.io.pciex.poiscomp-d@hostbridge/pciexrc/PCIEXFN; +event error.io.pciex.noimpact-d@hostbridge/pciexrc/PCIEXFN; +event error.io.pciex.lost-d@hostbridge/pciexrc/PCIEXFN; +event error.io.pciex.degraded-d@hostbridge/pciexrc/PCIEXFN; + +/* Upset event */ +event upset.io.pciex.rc.discard@hostbridge; + +/* + * Fault Events + * Do no retire and FRUs for SW/FW faults + */ +event fault.io.pciex.rc.generic-ue@hostbridge, + FITrate=HB_FIT, retire=0, response=0; +event fault.io.pciex.rc.generic-sw@hostbridge, + FITrate=SW_FIT, retire=0, response=0; +event fault.io.pciex.rc.generic-fw@hostbridge, + FITrate=FW_FIT, retire=0, response=0; + +/* Serd engine for CE errors */ +engine serd.io.pciex.rc.generic-ce@hostbridge, N=RC_N, T=RC_T; +event fault.io.pciex.rc.generic-ce@hostbridge, FITrate=HB_FIT, + engine=serd.io.pciex.rc.generic-ce@hostbridge; + +/* Fire faults */ +event fault.io.fire.pciex.device@PCIEXFN, FITrate=1000; +event fault.io.fire.pci.device@pcibus/pcidev/pcifn, FITrate=1000; + +/* Generic Root Complex Software faults */ +prop fault.io.pciex.rc.generic-sw@hostbridge -> + ereport.io.pciex.rc.epkt@hostbridge { + MATCHES_DESC(BLOCK_INTR,OP_FIXED,PH_UNKNOWN,CND_ILL,DIR_INGRESS) || + MATCHES_DESC(BLOCK_INTR,OP_MSI32,PH_UNKNOWN,CND_ILL,DIR_IRR) || + MATCHES_DESC(BLOCK_INTR,OP_PCIEMSG,PH_UNKNOWN,CND_ILL,DIR_INGRESS) + }; + +/* Generic Root Complex Firmware faults */ +prop fault.io.pciex.rc.generic-fw@hostbridge -> + ereport.io.pciex.rc.epkt@hostbridge { + MATCHES_DESC(BLOCK_HOSTBUS,OP_PIO,PH_ADDR,CND_UNMAP,DIR_WRITE) + }; + +/* Generic Root Complex CE faults */ +prop fault.io.pciex.rc.generic-ce@hostbridge { IS_CE } -> + ereport.io.pciex.rc.epkt@hostbridge; + +/* Generic Root Complex UE faults from propagations */ +event error.io.pciex.rc.generic-ue1@hostbridge; +event error.io.pciex.rc.generic-ue2@hostbridge; + +prop fault.io.pciex.rc.generic-ue@hostbridge -> + error.io.pciex.rc.generic-ue1@hostbridge, + error.io.pciex.rc.generic-ue2@hostbridge, + error.io.pciex.rc.stall@hostbridge, + error.io.pciex.rc.poiscomp@hostbridge; + +/* Generic Root Complex UE propagations */ +prop error.io.pciex.rc.generic-ue1@hostbridge { IS_UE && !IS_BLOCKED } -> + ereport.io.pciex.rc.epkt@hostbridge { + MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_INT,DIR_READ) || + MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_INT,DIR_UNKNOWN) || + MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_INT,DIR_WRITE) || + MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_TO,DIR_READ) || + MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_TO,DIR_WRITE) || + MATCHES_DESC(BLOCK_HOSTBUS,OP_PIO,PH_DATA,CND_INT,DIR_UNKNOWN) || + MATCHES_DESC(BLOCK_HOSTBUS,OP_UNKNOWN,PH_DATA,CND_INT,DIR_UNKNOWN) || + MATCHES_DESC(BLOCK_HOSTBUS,OP_UNKNOWN,PH_DATA,CND_INT,DIR_UNKNOWN) || + MATCHES_DESC(BLOCK_INTR,OP_MSI32,PH_DATA,CND_INT,DIR_UNKNOWN) || + MATCHES_DESC(BLOCK_INTR,OP_MSIQ,PH_DATA,CND_INT,DIR_UNKNOWN) + }; + +prop error.io.pciex.rc.generic-ue2@hostbridge { IS_UE && !IS_BLOCKED } -> + ereport.io.pciex.rc.epkt@hostbridge { + MATCHES_DESC(BLOCK_MMU,OP_TBW,PH_ADDR,CND_UNKNOWN,DIR_UNKNOWN) || + MATCHES_DESC(BLOCK_MMU,OP_TBW,PH_ADDR,CND_UNMAP,DIR_UNKNOWN) || + MATCHES_DESC(BLOCK_MMU,OP_TBW,PH_DATA,CND_INT,DIR_IRR) || + MATCHES_DESC(BLOCK_MMU,OP_TBW,PH_UNKNOWN,CND_UNKNOWN,DIR_UNKNOWN) || + MATCHES_DESC(BLOCK_MMU,OP_XLAT,PH_DATA,CND_INT,DIR_UNKNOWN) || + MATCHES_DESC(BLOCK_PORT,OP_DMA,PH_DATA,CND_INT,DIR_READ) || + MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_DATA,CND_INT,DIR_READ) || + MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_DATA,CND_INT,DIR_UNKNOWN) || + MATCHES_DESC(BLOCK_PORT,OP_UNKNOWN,PH_DATA,CND_INT,DIR_UNKNOWN) || + MATCHES_DESC(BLOCK_PORT,OP_UNKNOWN,PH_DATA,CND_INT,DIR_UNKNOWN) + }; + +/* Errors that will cause a pipe stall and thus a CTO in the fabric */ +prop error.io.pciex.rc.stall@hostbridge (0) -> + error.io.pciex.nr-d@hostbridge/pciexrc<>/PCIEXFNHZ; + +prop error.io.pciex.rc.stall@hostbridge { IS_UE && IS_BLOCKED } -> + ereport.io.pciex.rc.epkt@hostbridge; + +/* + * Errors that will send a poisoned data to the fabric + * Also the poiscomp-d could represent a fault that a hardened driver + * handled and reported a service impact. + */ +prop error.io.pciex.rc.poiscomp@hostbridge (0) -> + error.io.pciex.poiscomp-d@hostbridge/pciexrc<>/PCIEXFNHZ, + error.io.pciex.noimpact-d@hostbridge/pciexrc<>/PCIEXFNHZ, + error.io.pciex.lost-d@hostbridge/pciexrc<>/PCIEXFNHZ, + error.io.pciex.degraded-d@hostbridge/pciexrc<>/PCIEXFNHZ; + +prop error.io.pciex.rc.poiscomp@hostbridge { IS_UE && !IS_BLOCKED } -> + ereport.io.pciex.rc.epkt@hostbridge { + MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_INT,DIR_READ) + }; + +prop error.io.pciex.badreq-u@hostbridge/pciexrc/PCIEXFN { IS_UE && !IS_BLOCKED } (0) -> + ereport.io.pciex.rc.epkt@hostbridge { + MATCHES_DESC(BLOCK_MMU,OP_XLAT,PH_ADDR,CND_UNMAP,DIR_RDWR) || + MATCHES_DESC(BLOCK_MMU,OP_XLAT,PH_DATA,CND_INV,DIR_RDWR) || + MATCHES_DESC(BLOCK_MMU,OP_XLAT,PH_DATA,CND_PROT,DIR_RDWR) + }; + +prop upset.io.pciex.rc.discard@hostbridge -> + ereport.io.pciex.rc.epkt@hostbridge { + MATCHES_DESC(BLOCK_INTR,OP_MSI32,PH_DATA,CND_ILL,DIR_IRR) || + MATCHES_DESC(BLOCK_PORT,OP_LINK,PH_FC,CND_TO,DIR_IRR) || + MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_INV,DIR_RDWR) || + MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_RCA,DIR_WRITE) || + MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_RUR,DIR_WRITE) || + MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_TO,DIR_READ) || + MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_TO,DIR_WRITE) || + MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_UC,DIR_IRR) + }; + +/* Event queue overflow */ +#define PROP_PLAT_FRU "FRU" +#define GET_HB_FRU (confprop(asru(hostbridge), PROP_PLAT_FRU)) +#define GET_PCIE_FRU (confprop(asru(pciexbus[b]/pciexdev[d]/pciexfn[0]), PROP_PLAT_FRU)) +#define GET_PCI_FRU (confprop(asru(pcibus[b]/pcidev[d]/pcifn[0]), PROP_PLAT_FRU)) + +prop fault.io.fire.pciex.device@pciexbus[b]/pciexdev[d]/pciexfn[0] + { + /* + * Indict PCI-E FRU(s) under this root complex excluding the + * one that the Fire ASIC resides on. + */ + is_under(hostbridge, pciexbus[b]/pciexdev[d]/pciexfn[0]) && + (GET_HB_FRU != GET_PCIE_FRU) + } (0) -> EPKT(BLOCK_INTR,OP_MSIQ,PH_UNKNOWN,CND_OV,DIR_IRR); + +prop fault.io.fire.pci.device@pcibus[b]/pcidev[d]/pcifn[0] + { + /* + * Indict PCI FRU(s) under this root complex excluding the + * one that the Fire ASIC resides on. + */ + is_under(hostbridge, pcibus[b]/pcidev[d]/pcifn[0]) && + (GET_HB_FRU != GET_PCI_FRU) + } (0) -> EPKT(BLOCK_INTR,OP_MSIQ,PH_UNKNOWN,CND_OV,DIR_IRR); diff --git a/usr/src/cmd/fm/eversholt/files/i386/Makefile b/usr/src/cmd/fm/eversholt/files/i386/Makefile index 37ad297e4a..80c9314087 100644 --- a/usr/src/cmd/fm/eversholt/files/i386/Makefile +++ b/usr/src/cmd/fm/eversholt/files/i386/Makefile @@ -30,6 +30,7 @@ EFT_COMMON_FILES= \ neptune_xfp.eft \ pci.eft \ pciex.eft \ + pciexrc.eft \ sca500.eft \ sca1000.eft \ sensor.eft diff --git a/usr/src/cmd/fm/eversholt/files/sparc/Makefile b/usr/src/cmd/fm/eversholt/files/sparc/Makefile index c0ca8fbb4c..e128505266 100644 --- a/usr/src/cmd/fm/eversholt/files/sparc/Makefile +++ b/usr/src/cmd/fm/eversholt/files/sparc/Makefile @@ -30,6 +30,7 @@ EFT_COMMON_FILES= \ neptune_xfp.eft \ pci.eft \ pciex.eft \ + pciexrc.eft \ sca500.eft \ sca1000.eft \ sensor.eft diff --git a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/Makefile b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/Makefile index ea5a28b6e4..f884926bd5 100644 --- a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/Makefile +++ b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # @@ -28,7 +28,7 @@ include ../sun4/Makefile.sun4 EFT_PLAT= sun4v SUN4VEFTFILES= n2piu.eft vfncx.eft n2niu_xaui.eft n2niu_xfp.eft zambezi.eft \ -gcpu.eft gmem.eft +gcpu.eft gmem.eft sp.eft EFT_PLAT_FILES= $(SUN4VEFTFILES) $(SUN4EFTFILES) include ../../Makefile.com diff --git a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gcpu.esc b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gcpu.esc index fbb361ccfc..35af8529df 100644 --- a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gcpu.esc +++ b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gcpu.esc @@ -437,10 +437,11 @@ prop upset.fw.generic-sparc.erpt-gen@chassis { !DIAGNOSE_ERPT } (0) -> ereport.cpu.generic-sparc.inconsistent@chassis; /* - * bootbus-to and bootbus-par errors. Fault the detector. + * bootbus-prot, bootbus-to and bootbus-par errors. Fault the detector. */ event ereport.cpu.generic-sparc.bootbus-to@chip; event ereport.cpu.generic-sparc.bootbus-par@chip; +event ereport.cpu.generic-sparc.bootbus-prot@chip; event upset.cpu.generic-sparc.bootbus@chip; event fault.cpu.generic-sparc.bootbus@chip, retire=0; @@ -453,10 +454,15 @@ prop fault.cpu.generic-sparc.bootbus@chip { DIAGNOSE_ERPT } (0) -> ereport.cpu.generic-sparc.bootbus-par@chip; +prop fault.cpu.generic-sparc.bootbus@chip + { DIAGNOSE_ERPT } (0) -> + ereport.cpu.generic-sparc.bootbus-prot@chip; + prop upset.cpu.generic-sparc.bootbus@chip { !DIAGNOSE_ERPT } (0) -> ereport.cpu.generic-sparc.bootbus-to@chip, - ereport.cpu.generic-sparc.bootbus-par@chip; + ereport.cpu.generic-sparc.bootbus-par@chip, + ereport.cpu.generic-sparc.bootbus-prot@chip; /* * ignore the pio-read error. diff --git a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gmem.esc b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gmem.esc index 3f36baeda1..a63d0711bb 100644 --- a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gmem.esc +++ b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gmem.esc @@ -184,7 +184,7 @@ prop upset.memory.memlink@MEM_CTRL ereport.cpu.generic-sparc.membuf-crc@MEM_CTRL; /* - * membuf-crc-uc will fault the detector FRU and sender FRU + * membuf-crc-uc, membuf-other-uc will fault the detector FRU and sender FRU * if detector is CHIP or MEM_CTRL, the sender is MEM_BUFF. * if detector is MEM_BUFF, the sender is CHIP or MEM_CTRL */ @@ -192,6 +192,10 @@ event ereport.cpu.generic-sparc.membuf-crc-uc@CHIP { within(1s) }; event ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF { within(1s) }; event ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL { within(1s) }; +event ereport.cpu.generic-sparc.membuf-other-uc@CHIP { within(1s) }; +event ereport.cpu.generic-sparc.membuf-other-uc@MEM_BUFF { within(1s) }; +event ereport.cpu.generic-sparc.membuf-other-uc@MEM_CTRL { within(1s) }; + event fault.memory.memlink-uc@CHIP; event fault.memory.memlink-uc@MEM_BUFF; event fault.memory.memlink-uc@MEM_CTRL; @@ -201,55 +205,66 @@ event fault.memory.memlink-uc@MEM_CTRL; */ prop fault.memory.memlink-uc@CHIP { DIAGNOSE_ERPT } (0) -> - ereport.cpu.generic-sparc.membuf-crc-uc@CHIP; + ereport.cpu.generic-sparc.membuf-crc-uc@CHIP, + ereport.cpu.generic-sparc.membuf-other-uc@CHIP; prop fault.memory.memlink-uc@MEM_BUFF { DIAGNOSE_ERPT && CONTAINS_MEMBUFF } (0) -> - ereport.cpu.generic-sparc.membuf-crc-uc@CHIP<>; + ereport.cpu.generic-sparc.membuf-crc-uc@CHIP<>, + ereport.cpu.generic-sparc.membuf-other-uc@CHIP<>; event upset.memory.memlink-uc@CHIP; prop upset.memory.memlink-uc@CHIP { !DIAGNOSE_ERPT } (0)-> - ereport.cpu.generic-sparc.membuf-crc-uc@CHIP; + ereport.cpu.generic-sparc.membuf-crc-uc@CHIP, + ereport.cpu.generic-sparc.membuf-other-uc@CHIP; /* * memory-buffer is detector */ prop fault.memory.memlink-uc@MEM_BUFF { DIAGNOSE_ERPT } (0) -> - ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF; + ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF, + ereport.cpu.generic-sparc.membuf-other-uc@MEM_BUFF; prop fault.memory.memlink-uc@CHIP { DIAGNOSE_ERPT && CONTAINS_CHIP } (0) -> - ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF<>; + ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF<>, + ereport.cpu.generic-sparc.membuf-other-uc@MEM_BUFF<>; prop fault.memory.memlink-uc@MEM_CTRL { DIAGNOSE_ERPT && CONTAINS_MEMCTRL } (0) -> - ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF<>; + ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF<>, + ereport.cpu.generic-sparc.membuf-other-uc@MEM_BUFF<>; event upset.memory.memlink-uc@MEM_BUFF; prop upset.memory.memlink-uc@MEM_BUFF { !DIAGNOSE_ERPT } (0)-> - ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF; + ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF, + ereport.cpu.generic-sparc.membuf-other-uc@MEM_BUFF; /* * memory-controller is detector */ prop fault.memory.memlink-uc@MEM_CTRL { DIAGNOSE_ERPT } (0) -> - ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL; + ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL, + ereport.cpu.generic-sparc.membuf-other-uc@MEM_CTRL; prop fault.memory.memlink-uc@MEM_BUFF { DIAGNOSE_ERPT && CONTAINS_MEMBUFF } (0) -> - ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL<>; + ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL<>, + ereport.cpu.generic-sparc.membuf-other-uc@MEM_CTRL<>; event upset.memory.memlink-uc@MEM_CTRL; prop upset.memory.memlink-uc@MEM_CTRL { !DIAGNOSE_ERPT } (0)-> - ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL; + ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL, + ereport.cpu.generic-sparc.membuf-other-uc@MEM_CTRL; + /* * membuf-crc-failover will fault the detector FRU and sender FRU * if detector is chip or memory-controller, the sender is memory-buffer. diff --git a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/sp.esc b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/sp.esc new file mode 100644 index 0000000000..c1f272b244 --- /dev/null +++ b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/sp.esc @@ -0,0 +1,37 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma dictionary "SUN4V" + +/* + * Eversholt rule for a faulted Service Processor + */ + +event fault.sp.failed@sp; + +event ereport.chassis.sp.unavailable@chassis; + +prop fault.sp.failed@sp -> + ereport.chassis.sp.unavailable@chassis; diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/Makefile b/usr/src/cmd/fm/modules/common/fabric-xlate/Makefile index 8de8852eda..1609232d57 100644 --- a/usr/src/cmd/fm/modules/common/fabric-xlate/Makefile +++ b/usr/src/cmd/fm/modules/common/fabric-xlate/Makefile @@ -19,19 +19,18 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# MODULE = fabric-xlate CLASS = common -SRCS = fabric-xlate.c +SRCS = fabric-xlate.c fx_epkt.c fx_fabric.c fx_fire.c fx_subr.c include ../../Makefile.plugin CPPFLAGS += -I/usr/include/libxml2 -I$(KMFDIR)/include -I. +CPPFLAGS += -I$(SRC)/uts/sun4v/io/px INCDIRS = $(SRC)/uts/common CFLAGS += -I$(INCDIRS) LINTFLAGS += -I$(INCDIRS) diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c index 57df0ce38a..80f37075de 100644 --- a/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c +++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c @@ -23,1500 +23,22 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#include <assert.h> -#include <stddef.h> -#include <errno.h> -#include <strings.h> -#include <fm/fmd_api.h> #include <fm/libtopo.h> #include <sys/fm/util.h> -#include <sys/fm/protocol.h> -#include <sys/fm/io/pci.h> -#include <sys/fm/io/sun4_fire.h> -#include <sys/pci.h> -#include <sys/pcie.h> -#include <sys/nvpair.h> -#include <sys/nvpair_impl.h> -#include <libxml/xpath.h> -#include <libxml/parser.h> #include <libxml/xpathInternals.h> -#include <libxml/tree.h> -/* PCI-E config space data for error handling and fabric ereports */ -typedef struct fab_data { - /* Original ereport NVL */ - nvlist_t *nvl; +#include "fabric-xlate.h" - /* Device Information */ - uint16_t bdf; - uint16_t device_id; - uint16_t vendor_id; - uint8_t rev_id; - uint16_t dev_type; - uint16_t pcie_off; - uint16_t pcix_off; - uint16_t aer_off; - uint16_t ecc_ver; - - /* Ereport Information */ - uint32_t remainder; - uint32_t severity; - - /* Error Registers */ - uint16_t pci_err_status; /* pci status register */ - uint16_t pci_cfg_comm; /* pci command register */ - - uint16_t pci_bdg_sec_stat; /* PCI secondary status reg */ - uint16_t pci_bdg_ctrl; /* PCI bridge control reg */ - - uint16_t pcix_command; /* pcix command register */ - uint32_t pcix_status; /* pcix status register */ - - uint16_t pcix_bdg_sec_stat; /* pcix bridge secondary status reg */ - uint32_t pcix_bdg_stat; /* pcix bridge status reg */ - - uint16_t pcix_ecc_control_0; /* pcix ecc control status reg */ - uint16_t pcix_ecc_status_0; /* pcix ecc control status reg */ - uint32_t pcix_ecc_fst_addr_0; /* pcix ecc first address reg */ - uint32_t pcix_ecc_sec_addr_0; /* pcix ecc second address reg */ - uint32_t pcix_ecc_attr_0; /* pcix ecc attributes reg */ - uint16_t pcix_ecc_control_1; /* pcix ecc control status reg */ - uint16_t pcix_ecc_status_1; /* pcix ecc control status reg */ - uint32_t pcix_ecc_fst_addr_1; /* pcix ecc first address reg */ - uint32_t pcix_ecc_sec_addr_1; /* pcix ecc second address reg */ - uint32_t pcix_ecc_attr_1; /* pcix ecc attributes reg */ - - uint16_t pcie_err_status; /* pcie device status register */ - uint16_t pcie_err_ctl; /* pcie error control register */ - uint32_t pcie_dev_cap; /* pcie device capabilities register */ - - uint32_t pcie_adv_ctl; /* pcie advanced control reg */ - uint32_t pcie_ue_status; /* pcie ue error status reg */ - uint32_t pcie_ue_mask; /* pcie ue error mask reg */ - uint32_t pcie_ue_sev; /* pcie ue error severity reg */ - uint32_t pcie_ue_hdr[4]; /* pcie ue header log */ - uint32_t pcie_ce_status; /* pcie ce error status reg */ - uint32_t pcie_ce_mask; /* pcie ce error mask reg */ - uint32_t pcie_ue_tgt_trans; /* Fault trans type from AER Logs */ - uint64_t pcie_ue_tgt_addr; /* Fault addr from AER Logs */ - pcie_req_id_t pcie_ue_tgt_bdf; /* Fault bdf from SAER Logs */ - - uint32_t pcie_sue_ctl; /* pcie bridge secondary ue control */ - uint32_t pcie_sue_status; /* pcie bridge secondary ue status */ - uint32_t pcie_sue_mask; /* pcie bridge secondary ue mask */ - uint32_t pcie_sue_sev; /* pcie bridge secondary ue severity */ - uint32_t pcie_sue_hdr[4]; /* pcie bridge secondary ue hdr log */ - uint32_t pcie_sue_tgt_trans; /* Fault trans type from AER Logs */ - uint64_t pcie_sue_tgt_addr; /* Fault addr from AER Logs */ - pcie_req_id_t pcie_sue_tgt_bdf; /* Fault bdf from SAER Logs */ - - uint32_t pcie_rp_status; /* root complex status register */ - uint16_t pcie_rp_ctl; /* root complex control register */ - uint32_t pcie_rp_err_status; /* pcie root complex error status reg */ - uint32_t pcie_rp_err_cmd; /* pcie root complex error cmd reg */ - uint16_t pcie_rp_ce_src_id; /* pcie root complex ce sourpe id */ - uint16_t pcie_rp_ue_src_id; /* pcie root complex ue sourpe id */ -} fab_data_t; - -/* - * These values are used for the xxx_tgt_trans value in fab_data_t. They are - * originally set in pcie_fault.c and originally defined in pcie_impl.h. - */ -#define PF_ADDR_DMA (1 << 0) -#define PF_ADDR_PIO (1 << 1) -#define PF_ADDR_CFG (1 << 2) - -typedef struct fab_erpt_tbl { - const char *err_class; /* Final Ereport Class */ - uint32_t reg_bit; /* Error Bit Mask */ - /* Pointer to function that prepares the ereport body */ - const char *tgt_class; /* Target Ereport Class */ -} fab_erpt_tbl_t; - -typedef struct fab_err_tbl { - fab_erpt_tbl_t *erpt_tbl; /* ereport table */ - uint32_t reg_offset; /* sts reg for ereport table offset */ - uint32_t reg_size; /* size of the status register */ - /* Pointer to function that prepares the ereport body */ - int (*fab_prep)(fmd_hdl_t *, fab_data_t *, nvlist_t *, - fab_erpt_tbl_t *); -} fab_err_tbl_t; - -typedef struct fab_fire_tbl { - const char *err_class; - uint32_t fire_bit; /* Fire error bit */ - uint16_t pci_err_sts; /* Equivalent PCI Error Status */ - uint16_t pci_bdg_sts; /* Equivalent PCI Bridge Status */ -} fab_fire_tbl_t; - -/* Static FM Topo XML Format and XML XPath Context */ -static xmlDocPtr fab_doc = NULL; -static xmlXPathContextPtr fab_xpathCtx = NULL; -static int fab_valid_topo = 0; #define XMLTOPOFILE "/tmp/fab-xlate-topo.xml" -/* Functions that convert ereports to a common C data structure */ -static void fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, - fab_data_t *data); -static void fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data); - -/* Common functions for sending translated ereports */ -static int fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt, - boolean_t isRC); -static boolean_t fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath); -static char *fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr); -static char *fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf); -static void fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, - const char *class, boolean_t isPrimary); -static void fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl); - -/* - * Common functions for converting pci.fabric classes of - * ereports - */ -static int fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *erpt, fab_erpt_tbl_t *table); -static int fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *erpt, fab_erpt_tbl_t *table); -static int fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *erpt, fab_erpt_tbl_t *table); -static int fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *erpt, fab_erpt_tbl_t *table); -static int fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *erpt, fab_erpt_tbl_t *table); -static int fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *erpt, fab_erpt_tbl_t *table); -static int fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *erpt, fab_erpt_tbl_t *table); -static int fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *erpt, fab_erpt_tbl_t *table); -static void fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data); -static int fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *erpt, fab_erpt_tbl_t *table); -static void fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data); -static int fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *erpt, fab_erpt_tbl_t *table); -static int fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *erpt, fab_erpt_tbl_t *table); - -/* Functions for converting fire specific error registers */ -static int fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - const char *class); -static int fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - const char *class); -static int fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - const char *class); -static int fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - const char *class); - -/* Main functions for converting "fabric" ereports */ -static void fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data); -static void fab_xlate_fire_erpts(fmd_hdl_t *hdl, fab_data_t *data, - nvlist_t *nvl, const char *class); - -/* - * Translation tables for converting "fabric" error bits into "pci" ereports. - * <Ereport Class Name>, <Error Bit Mask>, <Preparation Function> - */ - -/* MACRO for table entries with no TGT ereports */ -#define NT(class, bit, prep) class, bit, prep, NULL -/* Translate Fabric ereports to ereport.io.pci.* */ -static fab_erpt_tbl_t fab_pci_erpt_tbl[] = { - PCI_DET_PERR, PCI_STAT_PERROR, NULL, - PCI_MDPE, PCI_STAT_S_PERROR, NULL, - PCI_SIG_SERR, PCI_STAT_S_SYSERR, NULL, - PCI_MA, PCI_STAT_R_MAST_AB, NULL, - PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL, - PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, - NULL, NULL, NULL -}; - -/* Translate Fabric ereports to ereport.io.pci.sec-* */ -static fab_erpt_tbl_t fab_pci_bdg_erpt_tbl[] = { - PCI_DET_PERR, PCI_STAT_PERROR, NULL, - PCI_MDPE, PCI_STAT_S_PERROR, NULL, - PCI_REC_SERR, PCI_STAT_S_SYSERR, NULL, -#ifdef sparc - PCI_MA, PCI_STAT_R_MAST_AB, NULL, -#endif - PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL, - PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, - NULL, NULL, NULL, NULL, -}; - - -/* Translate Fabric ereports to ereport.io.pci.dto */ -static fab_erpt_tbl_t fab_pci_bdg_ctl_erpt_tbl[] = { - PCI_DTO, PCI_BCNF_BCNTRL_DTO_STAT, NULL, - NULL, NULL, NULL -}; - -/* Translate Fabric ereports to ereport.io.pciex.* */ -static fab_erpt_tbl_t fab_pcie_ce_erpt_tbl[] = { - PCIEX_RE, PCIE_AER_CE_RECEIVER_ERR, NULL, - PCIEX_RNR, PCIE_AER_CE_REPLAY_ROLLOVER, NULL, - PCIEX_RTO, PCIE_AER_CE_REPLAY_TO, NULL, - PCIEX_BDP, PCIE_AER_CE_BAD_DLLP, NULL, - PCIEX_BTP, PCIE_AER_CE_BAD_TLP, NULL, - PCIEX_ANFE, PCIE_AER_CE_AD_NFE, NULL, - NULL, NULL, NULL -}; - -/* Translate Fabric ereports to ereport.io.pciex.* */ -static fab_erpt_tbl_t fab_pcie_ue_erpt_tbl[] = { - PCIEX_TE, PCIE_AER_UCE_TRAINING, NULL, - PCIEX_DLP, PCIE_AER_UCE_DLP, NULL, - PCIEX_SD, PCIE_AER_UCE_SD, NULL, - PCIEX_ROF, PCIE_AER_UCE_RO, NULL, - PCIEX_FCP, PCIE_AER_UCE_FCP, NULL, - PCIEX_MFP, PCIE_AER_UCE_MTLP, NULL, - PCIEX_CTO, PCIE_AER_UCE_TO, PCI_TARG_MA, - PCIEX_UC, PCIE_AER_UCE_UC, NULL, - PCIEX_ECRC, PCIE_AER_UCE_ECRC, NULL, - PCIEX_CA, PCIE_AER_UCE_CA, PCI_TARG_REC_TA, -#ifdef sparc - PCIEX_UR, PCIE_AER_UCE_UR, PCI_TARG_MA, -#endif - PCIEX_POIS, PCIE_AER_UCE_PTLP, PCI_TARG_MDPE, - NULL, NULL, NULL -}; - -/* Translate Fabric ereports to ereport.io.pciex.* */ -static fab_erpt_tbl_t fab_pcie_sue_erpt_tbl[] = { - PCIEX_S_TA_SC, PCIE_AER_SUCE_TA_ON_SC, PCI_TARG_REC_TA, - PCIEX_S_MA_SC, PCIE_AER_SUCE_MA_ON_SC, PCI_TARG_MA, - PCIEX_S_RTA, PCIE_AER_SUCE_RCVD_TA, PCI_TARG_REC_TA, -#ifdef sparc - PCIEX_S_RMA, PCIE_AER_SUCE_RCVD_MA, PCI_TARG_MA, -#endif - PCIEX_S_USC, PCIE_AER_SUCE_USC_ERR, NULL, - PCIEX_S_USCMD, PCIE_AER_SUCE_USC_MSG_DATA_ERR, PCI_TARG_REC_TA, - PCIEX_S_UDE, PCIE_AER_SUCE_UC_DATA_ERR, PCI_TARG_MDPE, - PCIEX_S_UAT, PCIE_AER_SUCE_UC_ATTR_ERR, PCI_TARG_MDPE, - PCIEX_S_UADR, PCIE_AER_SUCE_UC_ADDR_ERR, PCI_TARG_MDPE, - PCIEX_S_TEX, PCIE_AER_SUCE_TIMER_EXPIRED, NULL, - PCIEX_S_PERR, PCIE_AER_SUCE_PERR_ASSERT, PCI_TARG_MDPE, - PCIEX_S_SERR, PCIE_AER_SUCE_SERR_ASSERT, NULL, - PCIEX_INTERR, PCIE_AER_SUCE_INTERNAL_ERR, NULL, - NULL, NULL, NULL -}; - -/* Translate Fabric ereports to ereport.io.pcix.* */ -static fab_erpt_tbl_t fab_pcix_erpt_tbl[] = { - PCIX_SPL_DIS, PCI_PCIX_SPL_DSCD, NULL, - PCIX_UNEX_SPL, PCI_PCIX_UNEX_SPL, NULL, - PCIX_RX_SPL_MSG, PCI_PCIX_RX_SPL_MSG, NULL, - NULL, NULL, NULL -}; -static fab_erpt_tbl_t *fab_pcix_bdg_erpt_tbl = fab_pcix_erpt_tbl; - -/* Translate Fabric ereports to ereport.io.pcix.sec-* */ -static fab_erpt_tbl_t fab_pcix_bdg_sec_erpt_tbl[] = { - PCIX_SPL_DIS, PCI_PCIX_BSS_SPL_DSCD, NULL, - PCIX_UNEX_SPL, PCI_PCIX_BSS_UNEX_SPL, NULL, - PCIX_BSS_SPL_OR, PCI_PCIX_BSS_SPL_OR, NULL, - PCIX_BSS_SPL_DLY, PCI_PCIX_BSS_SPL_DLY, NULL, - NULL, NULL, NULL -}; - -/* Translate Fabric ereports to ereport.io.pciex.* */ -static fab_erpt_tbl_t fab_pcie_nadv_erpt_tbl[] = { -#ifdef sparc - PCIEX_UR, PCIE_DEVSTS_UR_DETECTED, NULL, -#endif - PCIEX_FAT, PCIE_DEVSTS_FE_DETECTED, NULL, - PCIEX_NONFAT, PCIE_DEVSTS_NFE_DETECTED, NULL, - PCIEX_CORR, PCIE_DEVSTS_CE_DETECTED, NULL, - NULL, NULL, NULL -}; - -/* Translate Fabric ereports to ereport.io.pciex.* */ -static fab_erpt_tbl_t fab_pcie_rc_erpt_tbl[] = { - PCIEX_RC_FE_MSG, PCIE_AER_RE_STS_FE_MSGS_RCVD, NULL, - PCIEX_RC_NFE_MSG, PCIE_AER_RE_STS_NFE_MSGS_RCVD, NULL, - PCIEX_RC_CE_MSG, PCIE_AER_RE_STS_CE_RCVD, NULL, - PCIEX_RC_MCE_MSG, PCIE_AER_RE_STS_MUL_CE_RCVD, NULL, - PCIEX_RC_MUE_MSG, PCIE_AER_RE_STS_MUL_FE_NFE_RCVD, NULL, - NULL, NULL, NULL -}; - -/* - * Translate Fabric ereports to pseudo ereport.io.pciex.* RC Fabric Messages. - * If the RP is not a PCIe compliant RP or does not support AER, rely on the - * leaf fabric ereport to help create a xxx_MSG ereport coming from the RC. - */ -static fab_erpt_tbl_t fab_pcie_fake_rc_erpt_tbl[] = { - PCIEX_RC_FE_MSG, PCIE_DEVSTS_FE_DETECTED, NULL, - PCIEX_RC_NFE_MSG, PCIE_DEVSTS_NFE_DETECTED, NULL, - PCIEX_RC_CE_MSG, PCIE_DEVSTS_CE_DETECTED, NULL, - NULL, NULL, NULL, -}; - -static fab_err_tbl_t *fab_master_err_tbl; - -/* - * Translation tables for converting fire error bits into "pci" ereports. - * <Fire Bit> - * <pci ereport Class> - * <pci error status reg> - * <pci bridge status reg> - * <pci target class> - */ -#define FAB_FIRE_PEC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_PEC_ ## fb -#define FAB_FIRE_DMC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_DMC_ ## fb -#define FAB_N2_DMU_BIT(fb) "ereport.io.n2.dmu." fb -#define FAB_OB_PEC_BIT(fb) "ereport.io." PCIEX_OBERON "." FIRE_PEC_ ## fb - -#define FAB_FIRE_UE(fb, bit, sts, bdg) \ - FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg -#define FAB_OB_UE(fb, bit, sts, bdg) \ - FAB_OB_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg -static fab_fire_tbl_t fab_fire_pec_ue_tbl[] = { - FAB_FIRE_UE(UR, UR, PCI_STAT_S_SYSERR, 0), - FAB_FIRE_UE(UC, UC, PCI_STAT_S_SYSERR, 0), - FAB_OB_UE(ECRC, ECRC, PCI_STAT_S_SYSERR, 0), - FAB_FIRE_UE(CTO, TO, PCI_STAT_S_SYSERR, 0), - FAB_FIRE_UE(ROF, RO, PCI_STAT_S_SYSERR, 0), - FAB_FIRE_UE(MFP, MTLP, PCI_STAT_S_SYSERR, 0), - FAB_FIRE_UE(PP, PTLP, PCI_STAT_S_PERROR, - (PCI_STAT_S_SYSERR | PCI_STAT_PERROR)), - FAB_FIRE_UE(FCP, FCP, PCI_STAT_S_SYSERR, 0), - FAB_FIRE_UE(DLP, DLP, PCI_STAT_S_SYSERR, 0), - FAB_FIRE_UE(TE, TRAINING, PCI_STAT_S_SYSERR, 0), - FAB_FIRE_UE(CA, CA, PCI_STAT_S_TARG_AB, - PCI_STAT_S_TARG_AB), - NULL, NULL, NULL, -}; - -#define FAB_FIRE_CE(fb, bit) \ - FAB_FIRE_PEC_BIT(fb), PCIE_AER_CE_ ## bit, 0, 0 -static fab_fire_tbl_t fab_fire_pec_ce_tbl[] = { - FAB_FIRE_CE(RTO, REPLAY_TO), - FAB_FIRE_CE(RNR, REPLAY_ROLLOVER), - FAB_FIRE_CE(BDP, BAD_DLLP), - FAB_FIRE_CE(BTP, BAD_TLP), - FAB_FIRE_CE(RE, RECEIVER_ERR), - NULL, NULL, NULL, -}; - -/* - * WUC/RUC will need to be special cased for the target ereports, because you - * need to decode the tlp log. - */ -#define FAB_FIRE_WUCRUC(fb) \ - FAB_FIRE_PEC_BIT(fb), 0, 0, (PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR) -#define FAB_FIRE_OE(fb, bit) \ - FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0 -#define FAB_OB_OE(fb, bit) \ - FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0 -static fab_fire_tbl_t fab_fire_pec_oe_tbl[] = { - FAB_FIRE_WUCRUC(WUC), - FAB_FIRE_WUCRUC(RUC), - FAB_FIRE_OE(ERU, DLP), - FAB_FIRE_OE(ERO, DLP), - FAB_FIRE_OE(EMP, DLP), - FAB_FIRE_OE(EPE, DLP), - NULL, NULL, NULL, -}; - -#define FAB_FIRE_DMC(fb) \ - FAB_FIRE_DMC_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB -#define FAB_N2_DMU(fb) \ - FAB_N2_DMU_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB -static fab_fire_tbl_t fab_fire_dmc_tbl[] = { - FAB_FIRE_DMC(BYP_ERR), - FAB_FIRE_DMC(BYP_OOR), - FAB_FIRE_DMC(TRN_OOR), - FAB_FIRE_DMC(TTE_INV), - FAB_FIRE_DMC(TTE_PRT), - FAB_N2_DMU("iotsbdesc_inv"), - FAB_N2_DMU("sun4v_adj_va_uf"), - FAB_N2_DMU("sun4v_inv_pg_sz"), - FAB_N2_DMU("sun4v_key_err"), - FAB_N2_DMU("sun4v_va_oor"), - NULL, NULL, NULL -}; - -static fmd_xprt_t *fab_fmd_xprt = NULL; /* FMD transport layer handle */ -static char fab_buf[FM_MAX_CLASS]; -static boolean_t fab_xlate_fake_rp = B_TRUE; - -#define HAS_PROP(node, name) xmlHasProp(node, (const xmlChar *)name) -#define GET_PROP(node, name) ((char *)xmlGetProp(node, (const xmlChar *)name)) -#define FREE_PROP(prop) xmlFree((xmlChar *)prop) -#define STRCMP(s1, s2) (strcmp((const char *)s1, (const char *)s2) == 0) - -#define FAB_LOOKUP(sz, name, field) \ - (void) nvlist_lookup_uint ## sz(nvl, name, field) -/* ARGSUSED */ -static void -fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) { - data->nvl = nvl; - - /* Generic PCI device information */ - FAB_LOOKUP(16, "bdf", &data->bdf); - FAB_LOOKUP(16, "device_id", &data->device_id); - FAB_LOOKUP(16, "vendor_id", &data->vendor_id); - FAB_LOOKUP(8, "rev_id", &data->rev_id); - FAB_LOOKUP(16, "dev_type", &data->dev_type); - FAB_LOOKUP(16, "pcie_off", &data->pcie_off); - FAB_LOOKUP(16, "pcix_off", &data->pcix_off); - FAB_LOOKUP(16, "aer_off", &data->aer_off); - FAB_LOOKUP(16, "ecc_ver", &data->ecc_ver); - - /* Misc ereport information */ - FAB_LOOKUP(32, "remainder", &data->remainder); - FAB_LOOKUP(32, "severity", &data->severity); - - /* PCI registers */ - FAB_LOOKUP(16, "pci_status", &data->pci_err_status); - FAB_LOOKUP(16, "pci_command", &data->pci_cfg_comm); - - /* PCI bridge registers */ - FAB_LOOKUP(16, "pci_bdg_sec_status", &data->pci_bdg_sec_stat); - FAB_LOOKUP(16, "pci_bdg_ctrl", &data->pci_bdg_ctrl); - - /* PCIx registers */ - FAB_LOOKUP(32, "pcix_status", &data->pcix_status); - FAB_LOOKUP(16, "pcix_command", &data->pcix_command); - - /* PCIx ECC Registers */ - FAB_LOOKUP(16, "pcix_ecc_control_0", &data->pcix_ecc_control_0); - FAB_LOOKUP(16, "pcix_ecc_status_0", &data->pcix_ecc_status_0); - FAB_LOOKUP(32, "pcix_ecc_fst_addr_0", &data->pcix_ecc_fst_addr_0); - FAB_LOOKUP(32, "pcix_ecc_sec_addr_0", &data->pcix_ecc_sec_addr_0); - FAB_LOOKUP(32, "pcix_ecc_attr_0", &data->pcix_ecc_attr_0); - - /* PCIx ECC Bridge Registers */ - FAB_LOOKUP(16, "pcix_ecc_control_1", &data->pcix_ecc_control_1); - FAB_LOOKUP(16, "pcix_ecc_status_1", &data->pcix_ecc_status_1); - FAB_LOOKUP(32, "pcix_ecc_fst_addr_1", &data->pcix_ecc_fst_addr_1); - FAB_LOOKUP(32, "pcix_ecc_sec_addr_1", &data->pcix_ecc_sec_addr_1); - FAB_LOOKUP(32, "pcix_ecc_attr_1", &data->pcix_ecc_attr_1); - - /* PCIx Bridge */ - FAB_LOOKUP(32, "pcix_bdg_status", &data->pcix_bdg_stat); - FAB_LOOKUP(16, "pcix_bdg_sec_status", &data->pcix_bdg_sec_stat); - - /* PCIe registers */ - FAB_LOOKUP(16, "pcie_status", &data->pcie_err_status); - FAB_LOOKUP(16, "pcie_command", &data->pcie_err_ctl); - FAB_LOOKUP(32, "pcie_dev_cap", &data->pcie_dev_cap); - - /* PCIe AER registers */ - FAB_LOOKUP(32, "pcie_adv_ctl", &data->pcie_adv_ctl); - FAB_LOOKUP(32, "pcie_ue_status", &data->pcie_ue_status); - FAB_LOOKUP(32, "pcie_ue_mask", &data->pcie_ue_mask); - FAB_LOOKUP(32, "pcie_ue_sev", &data->pcie_ue_sev); - FAB_LOOKUP(32, "pcie_ue_hdr0", &data->pcie_ue_hdr[0]); - FAB_LOOKUP(32, "pcie_ue_hdr1", &data->pcie_ue_hdr[1]); - FAB_LOOKUP(32, "pcie_ue_hdr2", &data->pcie_ue_hdr[2]); - FAB_LOOKUP(32, "pcie_ue_hdr3", &data->pcie_ue_hdr[3]); - FAB_LOOKUP(32, "pcie_ce_status", &data->pcie_ce_status); - FAB_LOOKUP(32, "pcie_ce_mask", &data->pcie_ce_mask); - FAB_LOOKUP(32, "pcie_ue_tgt_trans", &data->pcie_ue_tgt_trans); - FAB_LOOKUP(64, "pcie_ue_tgt_addr", &data->pcie_ue_tgt_addr); - FAB_LOOKUP(16, "pcie_ue_tgt_bdf", &data->pcie_ue_tgt_bdf); - - /* PCIe BDG AER registers */ - FAB_LOOKUP(32, "pcie_sue_adv_ctl", &data->pcie_sue_ctl); - FAB_LOOKUP(32, "pcie_sue_status", &data->pcie_sue_status); - FAB_LOOKUP(32, "pcie_sue_mask", &data->pcie_sue_mask); - FAB_LOOKUP(32, "pcie_sue_sev", &data->pcie_sue_sev); - FAB_LOOKUP(32, "pcie_sue_hdr0", &data->pcie_sue_hdr[0]); - FAB_LOOKUP(32, "pcie_sue_hdr1", &data->pcie_sue_hdr[1]); - FAB_LOOKUP(32, "pcie_sue_hdr2", &data->pcie_sue_hdr[2]); - FAB_LOOKUP(32, "pcie_sue_hdr3", &data->pcie_sue_hdr[3]); - FAB_LOOKUP(32, "pcie_sue_tgt_trans", &data->pcie_sue_tgt_trans); - FAB_LOOKUP(64, "pcie_sue_tgt_addr", &data->pcie_sue_tgt_addr); - FAB_LOOKUP(16, "pcie_sue_tgt_bdf", &data->pcie_sue_tgt_bdf); - - /* PCIe RP registers */ - FAB_LOOKUP(32, "pcie_rp_status", &data->pcie_rp_status); - FAB_LOOKUP(16, "pcie_rp_control", &data->pcie_rp_ctl); - - /* PCIe RP AER registers */ - FAB_LOOKUP(32, "pcie_adv_rp_status", &data->pcie_rp_err_status); - FAB_LOOKUP(32, "pcie_adv_rp_command", &data->pcie_rp_err_cmd); - FAB_LOOKUP(16, "pcie_adv_rp_ce_src_id", &data->pcie_rp_ce_src_id); - FAB_LOOKUP(16, "pcie_adv_rp_ue_src_id", &data->pcie_rp_ue_src_id); - - /* - * If the system has a PCIe complaint RP with AER, turn off translating - * fake RP ereports. - */ - if (fab_xlate_fake_rp && - (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) && - data->aer_off) - fab_xlate_fake_rp = B_FALSE; -} - -/* ARGSUSED */ -static void -fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) { - data->nvl = nvl; - - /* Always Root Complex */ - data->dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT; - - data->pcie_ue_sev = (PCIE_AER_UCE_DLP | PCIE_AER_UCE_SD | - PCIE_AER_UCE_FCP | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP); -} - -/* ARGSUSED */ -static int -fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt, - boolean_t isRC) { - uint64_t *now; - uint64_t ena; - uint_t nelem; - nvlist_t *detector, *new_detector; - char rcpath[255]; - int err = 0; - - /* Grab the tod, ena and detector(FMRI) */ - err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem); - err |= nvlist_lookup_uint64(nvl, "ena", &ena); - err |= nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector); - if (err) - return (err); - - /* Make a copy of the detector */ - err = nvlist_dup(detector, &new_detector, NV_UNIQUE_NAME); - if (err) - return (err); - - /* Copy the tod and ena to erpt */ - (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena); - (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem); - - /* - * Create the correct ROOT FMRI from PCIe leaf fabric ereports. Used - * only by fab_prep_fake_rc_erpt. See the fab_pciex_fake_rc_erpt_tbl - * comments for more information. - */ - if (isRC && fab_get_rcpath(hdl, nvl, rcpath)) { - /* Create the correct PCIe RC new_detector aka FMRI */ - (void) nvlist_remove(new_detector, FM_FMRI_DEV_PATH, - DATA_TYPE_STRING); - (void) nvlist_add_string(new_detector, FM_FMRI_DEV_PATH, - rcpath); - } - - /* Copy the FMRI to erpt */ - (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, new_detector); - - nvlist_free(new_detector); - return (err); -} - -static void -fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, const char *class, - boolean_t isPrimary) -{ - nvlist_t *nvl = data->nvl; - nvlist_t *erpt; - char *fmri = NULL; - uint32_t tgt_trans; - uint64_t tgt_addr; - uint16_t tgt_bdf; - - if (isPrimary) { - tgt_trans = data->pcie_ue_tgt_trans; - tgt_addr = data->pcie_ue_tgt_addr; - tgt_bdf = data->pcie_ue_tgt_bdf; - } else { - tgt_trans = data->pcie_sue_tgt_trans; - tgt_addr = data->pcie_sue_tgt_addr; - tgt_bdf = data->pcie_sue_tgt_bdf; - } - - fmd_hdl_debug(hdl, "Sending Target Ereport: " - "type 0x%x addr 0x%llx fltbdf 0x%x\n", - tgt_trans, tgt_addr, tgt_bdf); - - if (!tgt_trans) - return; - - if ((tgt_trans == PF_ADDR_PIO) && tgt_addr) - fmri = fab_find_addr(hdl, nvl, tgt_addr); - else if ((tgt_trans == PF_ADDR_CFG) && tgt_bdf) - fmri = fab_find_bdf(hdl, nvl, tgt_bdf); - - if (fmri) { - uint64_t *now; - uint64_t ena; - uint_t nelem; - nvlist_t *detector; - int err = 0; - - /* Allocate space for new erpt */ - if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) - goto done; - - /* Generate the target ereport class */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", - PCI_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - /* Grab the tod, ena and detector(FMRI) */ - err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem); - err |= nvlist_lookup_uint64(nvl, "ena", &ena); - - /* Copy the tod and ena to erpt */ - (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena); - (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem); - - /* Create the correct FMRI */ - if (nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0) { - nvlist_free(erpt); - goto done; - } - (void) nvlist_add_uint8(detector, FM_VERSION, - FM_DEV_SCHEME_VERSION); - (void) nvlist_add_string(detector, FM_FMRI_SCHEME, - FM_FMRI_SCHEME_DEV); - (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, fmri); - (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, detector); - nvlist_free(detector); - - /* Add the address payload */ - (void) nvlist_add_uint64(erpt, PCI_PA, tgt_addr); - - fmd_hdl_debug(hdl, "Sending target ereport: %s 0x%x\n", - fab_buf, tgt_addr); - fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); - if (fmd_xprt_error(hdl, fab_fmd_xprt)) - goto done; - xmlFree(fmri); - } else { - fmd_hdl_debug(hdl, "Cannot find Target FMRI addr:0x%llx", - tgt_addr); - } - - return; -done: - if (fmri) - xmlFree(fmri); - fmd_hdl_debug(hdl, "Failed to send Target PCI ereport\n"); -} - -static void -fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl) -{ - fab_erpt_tbl_t *erpt_tbl, *entry; - nvlist_t *erpt; - uint32_t reg; - - erpt_tbl = tbl->erpt_tbl; - if (tbl->reg_size == 16) { - reg = (uint32_t)*((uint16_t *) - ((uint32_t)data + tbl->reg_offset)); - } else { - reg = *((uint32_t *)((uint32_t)data + tbl->reg_offset)); - } - - for (entry = erpt_tbl; entry->err_class; entry++) { - if (!(reg & entry->reg_bit)) - continue; - - if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) - goto done; - if (tbl->fab_prep(hdl, data, erpt, entry) != 0) { - fmd_hdl_debug(hdl, "Prepping ereport failed\n"); - nvlist_free(erpt); - continue; - } - - fmd_hdl_debug(hdl, "Sending ereport: %s 0x%x\n", fab_buf, reg); - fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); - if (fmd_xprt_error(hdl, fab_fmd_xprt)) { - fmd_hdl_debug(hdl, "Failed to send PCI ereport\n"); - return; - } - } - - return; -done: - fmd_hdl_debug(hdl, "Failed to send PCI ereport\n"); -} - -static int -fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", - PCI_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - (void) nvlist_add_uint16(erpt, PCI_CONFIG_STATUS, data->pci_err_status); - (void) nvlist_add_uint16(erpt, PCI_CONFIG_COMMAND, data->pci_cfg_comm); - - return (err); -} - -static int -fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s-%s", - PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, - data->pci_bdg_sec_stat); - (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); - - return (err); -} - -static int -fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", - PCI_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, - data->pci_bdg_sec_stat); - (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); - - return (err); -} - - -static int -fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", - PCIEX_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); - (void) nvlist_add_uint32(erpt, PCIEX_CE_STATUS_REG, - data->pcie_ce_status); - - return (err); -} - -static int -fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - uint32_t first_err = 1 << (data->pcie_adv_ctl & - PCIE_AER_CTL_FST_ERR_PTR_MASK); - int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", - PCIEX_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); - (void) nvlist_add_uint32(erpt, PCIEX_UE_STATUS_REG, - data->pcie_ue_status); - (void) nvlist_add_uint32(erpt, PCIEX_UE_SEV_REG, data->pcie_ue_sev); - (void) nvlist_add_uint32(erpt, PCIEX_ADV_CTL, data->pcie_adv_ctl); - - fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); - - if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_bdf) { - (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, - data->pcie_ue_tgt_bdf); - (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); - } else { - (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); - (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); - } - - if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_trans) { - if (tbl->tgt_class) - fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_TRUE); - } - - return (err); -} - -static int -fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - uint32_t first_err = 1 << (data->pcie_sue_ctl & - PCIE_AER_SCTL_FST_ERR_PTR_MASK); - int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", - PCIEX_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - (void) nvlist_add_uint32(erpt, PCIEX_SEC_UE_STATUS, - data->pcie_sue_status); - - fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); - - if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_bdf) { - (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, - data->pcie_sue_tgt_bdf); - (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); - } else { - (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); - (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); - } - - if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_trans) { - if (tbl->tgt_class) - fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_FALSE); - } - - return (err); -} - -static int -fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - int err = 0; - - /* Only send if this is not a bridge */ - if (!data->pcix_status || data->pcix_bdg_sec_stat) - return (1); - - err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", - PCIX_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - (void) nvlist_add_uint8(erpt, PCIX_COMMAND, data->pcix_command); - (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); - - return (err); -} - -static void -fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) -{ - nvlist_t *erpt; - int ecc_phase = (data->pcix_ecc_status_0 & PCI_PCIX_ECC_PHASE) >> 0x4; - int ecc_corr = data->pcix_ecc_status_0 & PCI_PCIX_ECC_CORR; - int sec_ue = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_UE; - int sec_ce = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_CE; - uint32_t ctlstat = (data->pcix_ecc_control_0 << 16) | - data->pcix_ecc_status_0; - - switch (ecc_phase) { - case PCI_PCIX_ECC_PHASE_NOERR: - break; - case PCI_PCIX_ECC_PHASE_FADDR: - case PCI_PCIX_ECC_PHASE_SADDR: - (void) snprintf(fab_buf, FM_MAX_CLASS, - "%s.%s", PCIX_ERROR_SUBCLASS, - ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR); - break; - case PCI_PCIX_ECC_PHASE_ATTR: - (void) snprintf(fab_buf, FM_MAX_CLASS, - "%s.%s", PCIX_ERROR_SUBCLASS, - ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); - break; - case PCI_PCIX_ECC_PHASE_DATA32: - case PCI_PCIX_ECC_PHASE_DATA64: - (void) snprintf(fab_buf, FM_MAX_CLASS, - "%s.%s", PCIX_ERROR_SUBCLASS, - ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); - break; - } - - if (ecc_phase) { - if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) - goto done; - (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - (void) nvlist_add_uint16(erpt, PCIX_COMMAND, - data->pcix_command); - (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); - (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); - (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, - data->pcix_ecc_attr_0); - fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); - fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); - if (fmd_xprt_error(hdl, fab_fmd_xprt)) - fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); - } - - if (sec_ce || sec_ue) { - (void) snprintf(fab_buf, FM_MAX_CLASS, - "%s.%s", PCIX_ERROR_SUBCLASS, - sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); - if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) - goto done; - (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - (void) nvlist_add_uint16(erpt, PCIX_COMMAND, - data->pcix_command); - (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); - (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); - (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, - data->pcix_ecc_attr_0); - fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); - fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); - if (fmd_xprt_error(hdl, fab_fmd_xprt)) - fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); - } - - return; -done: - fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); -} - -static int -fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s%s", - PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, - data->pcix_bdg_sec_stat); - (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); - - return (err); -} - -static int -fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", - PCIX_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, - data->pcix_bdg_sec_stat); - (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); - - return (err); -} - -static void -fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) -{ - nvlist_t *erpt; - int ecc_phase = (data->pcix_ecc_status_1 & PCI_PCIX_ECC_PHASE) >> 0x4; - int ecc_corr = data->pcix_ecc_status_1 & PCI_PCIX_ECC_CORR; - int sec_ue = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_UE; - int sec_ce = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_CE; - uint32_t ctlstat = (data->pcix_ecc_control_1 << 16) | - data->pcix_ecc_status_1; - - switch (ecc_phase) { - case PCI_PCIX_ECC_PHASE_NOERR: - break; - case PCI_PCIX_ECC_PHASE_FADDR: - case PCI_PCIX_ECC_PHASE_SADDR: - (void) snprintf(fab_buf, FM_MAX_CLASS, - "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, - ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR); - break; - case PCI_PCIX_ECC_PHASE_ATTR: - (void) snprintf(fab_buf, FM_MAX_CLASS, - "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, - ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); - break; - case PCI_PCIX_ECC_PHASE_DATA32: - case PCI_PCIX_ECC_PHASE_DATA64: - (void) snprintf(fab_buf, FM_MAX_CLASS, - "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, - ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); - break; - } - if (ecc_phase) { - if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) - goto done; - (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, - data->pcix_bdg_sec_stat); - (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, - data->pcix_bdg_stat); - (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); - (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, - data->pcix_ecc_attr_1); - fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); - fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); - if (fmd_xprt_error(hdl, fab_fmd_xprt)) - fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); - } - - if (sec_ce || sec_ue) { - (void) snprintf(fab_buf, FM_MAX_CLASS, - "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, - sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); - if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) - goto done; - (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, - data->pcix_bdg_sec_stat); - (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, - data->pcix_bdg_stat); - (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); - (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, - data->pcix_ecc_attr_1); - fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); - fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); - if (fmd_xprt_error(hdl, fab_fmd_xprt)) - fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); - } - return; -done: - fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); -} - -static int -fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - int err = 0; - - /* Don't send this for PCI device, Root Ports, or PCIe with AER */ - if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || - (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || - data->aer_off) - return (1); - - err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", - PCIEX_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); - - return (err); -} - -static int -fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - uint32_t status = data->pcie_rp_err_status; - int err = 0; - int isFE = 0, isNFE = 0; - - fmd_hdl_debug(hdl, "XLATE RP Error Class %s", class); - - if (!data->aer_off) - return (-1); - - /* Only send a FE Msg if the 1st UE error is FE */ - if (STRCMP(class, PCIEX_RC_FE_MSG)) - if (!(status & PCIE_AER_RE_STS_FIRST_UC_FATAL)) - return (-1); - else - isFE = 1; - - /* Only send a NFE Msg is the 1st UE error is NFE */ - if (STRCMP(class, PCIEX_RC_NFE_MSG)) - if (status & PCIE_AER_RE_STS_FIRST_UC_FATAL) - return (-1); - else - isNFE = 1; - - fmd_hdl_debug(hdl, "XLATE RP Error"); - - err |= fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", - PCIEX_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, status); - if ((isFE || isNFE) && data->pcie_rp_ue_src_id) { - (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, - data->pcie_rp_ue_src_id); - (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); - } - if (STRCMP(class, PCIEX_RC_CE_MSG) && data->pcie_rp_ce_src_id) { - (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, - data->pcie_rp_ce_src_id); - (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); - } - - return (err); -} - -static int -fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - fab_erpt_tbl_t *tbl) -{ - const char *class = tbl->err_class; - uint32_t rc_err_sts = 0; - int err = 0; - - /* - * Don't send this for PCI device or Root Ports. Only send it on - * systems with non-compliant RPs. - */ - if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || - (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || - (!fab_xlate_fake_rp)) - return (-1); - - err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_TRUE); - - /* Generate an ereport for this error bit. */ - (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", - PCIEX_ERROR_SUBCLASS, class); - (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); - - /* Send PCIe RC Ereports */ - if (data->pcie_err_status & PCIE_DEVSTS_CE_DETECTED) { - rc_err_sts |= PCIE_AER_RE_STS_CE_RCVD; - } - - /* NFE/FE src id takes precedence over CE src id */ - if (data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) { - rc_err_sts |= PCIE_AER_RE_STS_NFE_MSGS_RCVD; - rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; - } - if (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED) { - rc_err_sts |= PCIE_AER_RE_STS_FE_MSGS_RCVD; - rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; - } - if ((data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) && - (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED)) { - rc_err_sts |= PCIE_AER_RE_STS_FIRST_UC_FATAL; - rc_err_sts |= PCIE_AER_RE_STS_MUL_FE_NFE_RCVD; - } - - (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, rc_err_sts); - - if (!(rc_err_sts & PCIE_AER_RE_STS_MUL_FE_NFE_RCVD)) { - (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, data->bdf); - (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); - } - - return (err); -} - -static int -fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - const char *class) -{ - fab_fire_tbl_t *entry; - uint64_t reg; - - for (entry = fab_fire_pec_ce_tbl; entry->err_class; entry++) { - if (STRCMP(class, entry->err_class)) - goto send; - } - - return (0); - -send: - fmd_hdl_debug(hdl, "Translate Fire CE %s\n", class); - - /* Fill in the device status register */ - data->pcie_err_status = PCIE_DEVSTS_CE_DETECTED; - - /* Fill in the AER CE register */ - if (nvlist_lookup_uint64(erpt, "tlu-cess", ®) == 0) { - data->pcie_ce_status = (uint32_t)reg | (uint32_t)(reg >> 32); - } - - return (1); -} - -static int -fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - const char *class) -{ - fab_fire_tbl_t *entry; - uint64_t reg; - uint32_t temp; - pcie_tlp_hdr_t *hdr; - - for (entry = fab_fire_pec_ue_tbl; entry->err_class; entry++) { - if (STRCMP(class, entry->err_class)) - goto send; - } - - return (0); - -send: - fmd_hdl_debug(hdl, "Translate Fire UE %s\n", class); +fmd_xprt_t *fab_fmd_xprt; /* FMD transport layer handle */ +char fab_buf[FM_MAX_CLASS]; - /* Fill in PCI Status Register */ - data->pci_err_status = entry->pci_err_sts; - data->pci_bdg_sec_stat = entry->pci_bdg_sts; - - /* Fill in the device status register */ - if (entry->fire_bit & data->pcie_ue_sev) - data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; - else - data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; - - if (entry->fire_bit == PCIE_AER_UCE_UR) - data->pcie_err_status |= PCIE_DEVSTS_UR_DETECTED; - - /* Fill in the AER UE register */ - if (nvlist_lookup_uint64(erpt, "tlu-uess", ®) == 0) { - data->pcie_ue_status = (uint32_t)reg | (uint32_t)(reg >> 32); - } - - /* Fill in the AER Control register */ - if ((reg & (uint64_t)entry->fire_bit) && - nvlist_lookup_boolean(erpt, "primary")) { - temp = entry->fire_bit; - for (data->pcie_adv_ctl = (uint32_t)-1; temp; - data->pcie_adv_ctl++) - temp = temp >> 1; - } - - /* If CTO create target information */ - if (entry->fire_bit == PCIE_AER_UCE_TO && - nvlist_lookup_boolean(erpt, "primary")) { - if (nvlist_lookup_uint64(erpt, "tlu-tueh1l", ®) == 0) { - data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); - data->pcie_ue_hdr[1] = (uint32_t)(reg); - } - if (nvlist_lookup_uint64(erpt, "tlu-tueh2l", ®) == 0) { - data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); - data->pcie_ue_hdr[3] = (uint32_t)(reg); - } - - hdr = (pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]); - switch (hdr->type) { - case PCIE_TLP_TYPE_IO: - case PCIE_TLP_TYPE_MEM: - case PCIE_TLP_TYPE_MEMLK: - data->pcie_ue_tgt_trans = PF_ADDR_PIO; - if (hdr->fmt & 0x1) { - data->pcie_ue_tgt_addr = reg; - } else { - data->pcie_ue_tgt_addr = data->pcie_ue_hdr[2]; - } - break; - case PCIE_TLP_TYPE_CFG0: - case PCIE_TLP_TYPE_CFG1: - data->pcie_ue_tgt_trans = PF_ADDR_CFG; - data->pcie_ue_tgt_bdf = data->pcie_ue_hdr[2] >> 16; - break; - } - } - - /* Fill in the AER Header registers */ - if (nvlist_lookup_uint64(erpt, "tlu-rueh1l", ®) == 0) { - data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); - data->pcie_ue_hdr[1] = (uint32_t)(reg); - } - if (nvlist_lookup_uint64(erpt, "tlu-rueh2l", ®) == 0) { - data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); - data->pcie_ue_hdr[3] = (uint32_t)(reg); - } - - return (1); -} - -static int -fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - const char *class) -{ - fab_fire_tbl_t *entry; - uint64_t reg; - - for (entry = fab_fire_pec_oe_tbl; entry->err_class; entry++) { - if (STRCMP(class, entry->err_class)) - goto send; - } - - return (0); - -send: - fmd_hdl_debug(hdl, "Translate Fire OE %s\n", class); - - /* Fill in PCI Status Register */ - if (entry->fire_bit) { - data->pci_err_status = entry->pci_err_sts; - data->pci_bdg_sec_stat = entry->pci_bdg_sts; - } else { - if (nvlist_lookup_uint64(erpt, "tlu-roeeh1l", ®) == 0) { - data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); - data->pcie_ue_hdr[1] = (uint32_t)(reg); - } - if (nvlist_lookup_uint64(erpt, "tlu-roeeh2l", ®) == 0) { - data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); - data->pcie_ue_hdr[3] = (uint32_t)(reg); - } - - if (((pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]))->type == - PCIE_TLP_TYPE_CPL) { - pcie_cpl_t *cpl = (pcie_cpl_t *)&data->pcie_ue_hdr[1]; - switch (cpl->status) { - case PCIE_CPL_STS_UR: - data->pci_err_status = 0; - data->pci_bdg_sec_stat = PCI_STAT_R_MAST_AB | - PCI_STAT_S_SYSERR; - break; - case PCIE_CPL_STS_CA: - data->pci_err_status = 0; - data->pci_bdg_sec_stat = PCI_STAT_R_TARG_AB | - PCI_STAT_S_SYSERR; - break; - } - } - } - - /* Fill in the device status register */ - if (entry->fire_bit & data->pcie_ue_sev) - data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; - else - data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; - - /* Fill in the AER UE register */ - data->pcie_ue_status = entry->fire_bit; - - return (1); -} - -static int -fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, - const char *class) -{ - fab_fire_tbl_t *entry; - uint64_t reg; - uint32_t temp; - - for (entry = fab_fire_dmc_tbl; entry->err_class; entry++) { - fmd_hdl_debug(hdl, "Matching %s\n", entry->err_class); - if (STRCMP(class, entry->err_class) && - nvlist_lookup_boolean(erpt, "primary")) - goto send; - } - - return (0); - -send: - fmd_hdl_debug(hdl, "Translate Fire DMC %s\n", class); - - /* Fill in PCI Status Register */ - data->pci_err_status = entry->pci_err_sts; - data->pci_bdg_sec_stat = entry->pci_bdg_sts; - - /* Fill in the device status register */ - data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; - - /* Fill in the AER UE register */ - data->pcie_ue_status = entry->fire_bit; - - /* Fill in the AER Control register */ - temp = entry->fire_bit; - for (data->pcie_adv_ctl = (uint32_t)-1; temp; data->pcie_adv_ctl++) - temp = temp >> 1; - - /* Fill in the AER Header registers */ - if (nvlist_lookup_uint64(erpt, "mmu-tfsr", ®) == 0) { - fmd_hdl_debug(hdl, "tfsr 0x%llx\n", reg); - /* Get the trans type */ - temp = (reg & 0x3F0000) >> 16; - data->pcie_ue_hdr[0] = (uint32_t)(temp << 24); - data->pcie_ue_tgt_trans = PF_ADDR_DMA; - /* Get the req id */ - temp = (reg & 0xFFFF); - data->pcie_ue_hdr[1] = (uint32_t)(temp << 16); - data->pcie_ue_tgt_bdf = temp; - } - - if (nvlist_lookup_uint64(erpt, "mmu-tfar", ®) == 0) { - fmd_hdl_debug(hdl, "tfar 0x%llx\n", reg); - /* Get the address */ - data->pcie_ue_hdr[2] = reg; - data->pcie_ue_hdr[3] = 0; - data->pcie_ue_tgt_addr = reg; - } - - fmd_hdl_debug(hdl, "HEADER 0 0x%x\n", data->pcie_ue_hdr[0]); - fmd_hdl_debug(hdl, "HEADER 1 0x%x\n", data->pcie_ue_hdr[1]); - fmd_hdl_debug(hdl, "HEADER 2 0x%x\n", data->pcie_ue_hdr[2]); - fmd_hdl_debug(hdl, "HEADER 3 0x%x\n", data->pcie_ue_hdr[3]); - - return (1); -} - -static void -fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data) -{ - fab_err_tbl_t *tbl; - - fmd_hdl_debug(hdl, "Sending Ereports Now"); - - /* Go through the error logs and send the relavant reports */ - for (tbl = fab_master_err_tbl; tbl->erpt_tbl; tbl++) { - fab_send_erpt(hdl, data, tbl); - } - - /* Send PCI-X ECC Ereports */ - fab_send_pcix_ecc_erpt(hdl, data); - fab_send_pcix_bdg_ecc_erpt(hdl, data); -} - -static void -fab_xlate_fire_erpts(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *nvl, - const char *class) -{ - if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.pec.*")) { - if (fab_xlate_fire_ce(hdl, data, nvl, class)) - return; - - if (fab_xlate_fire_ue(hdl, data, nvl, class)) - return; - - if (fab_xlate_fire_oe(hdl, data, nvl, class)) - return; - } else if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.dmc.*") || - fmd_nvl_class_match(hdl, nvl, "ereport.io.n2.dmu.*")) { - if (fab_xlate_fire_dmc(hdl, data, nvl, class)) - return; - } -} +/* Static FM Topo XML Format and XML XPath Context */ +static xmlDocPtr fab_doc = NULL; +xmlXPathContextPtr fab_xpathCtx = NULL; +static int fab_valid_topo = 0; static void fab_update_topo(fmd_hdl_t *hdl) @@ -1553,452 +75,33 @@ fab_update_topo(fmd_hdl_t *hdl) fab_valid_topo = 1; } -#define FAB_HC2DEV_QUERY_SIZE_MIN 160 -#define FAB_HC2DEV_QUERY_SIZE(sz) \ - ((sz + FAB_HC2DEV_QUERY_SIZE_MIN) * sizeof (char)) - -static boolean_t -fab_hc2dev(fmd_hdl_t *hdl, nvlist_t *detector, char **dev_path, - uint_t *dev_path_size) { - xmlXPathObjectPtr xpathObj; - xmlNodeSetPtr nodes; - char *query, *query_end, *temp; - uint_t i, size; - size_t query_size = 0; - nvlist_t **hcl; - - if (nvlist_lookup_nvlist_array(detector, FM_FMRI_HC_LIST, &hcl, - &size) != 0) - goto fail; - - for (i = 0; i < size; i++) { - if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &temp) != 0) - goto fail; - query_size += strlen(temp); - if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &temp) != 0) - goto fail; - query_size += strlen(temp); - /* Adjust for '=' and '/' later */ - query_size += 2; - } - - query = fmd_hdl_alloc(hdl, FAB_HC2DEV_QUERY_SIZE(query_size), - FMD_SLEEP); - (void) sprintf(query, "//propval[@name='resource' and " - "contains(substring(@value, string-length(@value) - %d), '", - query_size); - - query_end = query; - query_end += strlen(query); - - for (i = 0; i < size; i++) { - (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &temp); - (void) snprintf(query_end, query_size, "%s=", temp); - query_end += strlen(temp) + 1; - (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &temp); - (void) snprintf(query_end, query_size, "%s", temp); - query_end += strlen(temp); - if (i != (size - 1)) { - (void) sprintf(query_end++, "/"); - } - } - - (void) sprintf(query_end, "')]/parent::*/following-sibling::*/" - "propval[@name='dev']/@value"); - - fmd_hdl_debug(hdl, "xpathObj query %s\n", query); - - xpathObj = xmlXPathEvalExpression((const xmlChar *)query, - fab_xpathCtx); - fmd_hdl_free(hdl, query, FAB_HC2DEV_QUERY_SIZE(query_size)); - - if (xpathObj == NULL) - goto fail; - - fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, - xpathObj->type); - nodes = xpathObj->nodesetval; - - if (nodes) { - temp = (char *)xmlNodeGetContent(nodes->nodeTab[0]); - fmd_hdl_debug(hdl, "HC Dev Path: %s\n", temp); - *dev_path_size = strlen(temp) + 1; - *dev_path = fmd_hdl_alloc(hdl, *dev_path_size, FMD_SLEEP); - (void) strlcpy(*dev_path, (char *)temp, *dev_path_size); - xmlFree(temp); - xmlXPathFreeObject(xpathObj); - return (B_TRUE); - } - xmlXPathFreeObject(xpathObj); -fail: - return (B_FALSE); -} - -/* ARGSUSED */ -static boolean_t -fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath) { - nvlist_t *detector; - char *path, *scheme; - uint_t size; - - if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0) - goto fail; - if (nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0) - goto fail; - - if (STRCMP(scheme, FM_FMRI_SCHEME_DEV)) { - if (nvlist_lookup_string(detector, FM_FMRI_DEV_PATH, - &path) != 0) - goto fail; - (void) strncpy(rcpath, path, FM_MAX_CLASS); - } else if (STRCMP(scheme, FM_FMRI_SCHEME_HC)) { - /* - * This should only occur for ereports that come from the RC - * itself. In this case convert HC scheme to dev path. - */ - if (fab_hc2dev(hdl, detector, &path, &size)) { - (void) strncpy(rcpath, path, FM_MAX_CLASS); - fmd_hdl_free(hdl, path, size); - } else { - goto fail; - } - } else { - return (B_FALSE); - } - - /* - * Extract the RC path by taking the first device in the dev path - * - * /pci@0,0/pci8086,3605@2/pci8086,3500@0/pci8086,3514@1/pci8086,105e@0 - * - to - - * /pci@0,0 - */ - path = strchr(rcpath + 1, '/'); - if (path) - path[0] = '\0'; - - return (B_TRUE); -fail: - return (B_FALSE); -} - -static char * -fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf) { - xmlXPathObjectPtr xpathObj; - xmlNodeSetPtr nodes; - xmlChar *retval; - char query[500]; - int bus, dev, fn; - char rcpath[255]; - - if (bdf != (uint16_t)-1) { - bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT; - dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT; - fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT; - } - - if (!fab_get_rcpath(hdl, nvl, rcpath)) - goto fail; - - /* - * Explanation of the XSL XPATH Query - * Line 1: Look at all nodes with the node name "propval" - * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF - * Line 4-5: See if the "value" of the node ends with correct PCI BDF - * Line 6: Go up one level to the parent of the current node - * Line 7: See if child node contains "ASRU" with the same PCIe Root - * Line 8: Traverse up the parent and the other siblings and look for - * the io "propgroup" and get the value of the dev "propval" - */ - (void) snprintf(query, sizeof (query), "//propval[" - "contains(substring(@value, string-length(@value) - 34), " - "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or " - "contains(substring(@value, string-length(@value) - 28), " - "'pcibus=%d/pcidev=%d/pcifn=%d')" - "]/parent::" - "*/propval[@name='ASRU' and contains(@value, '%s')]" - "/parent::*/following-sibling::*[@name='io']/propval[@name='dev']/" - "@value", bus, dev, fn, bus, dev, fn, rcpath); - - fmd_hdl_debug(hdl, "xpathObj query %s\n", query); - - xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx); - - if (xpathObj == NULL) - goto fail; - - fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type); - - nodes = xpathObj->nodesetval; - if (nodes) { - retval = xmlNodeGetContent(nodes->nodeTab[0]); - fmd_hdl_debug(hdl, "BDF Dev Path: %s\n", retval); - xmlXPathFreeObject(xpathObj); - return ((char *)retval); - } -fail: - return (NULL); -} - -static char * -fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr) { - xmlXPathObjectPtr xpathObj; - xmlNodeSetPtr nodes; - xmlNodePtr devNode; - char *retval; - char query[500]; - int size, i, j; - uint32_t prop[50]; - char *token; - pci_regspec_t *assign_p; - uint64_t low, hi; - char rcpath[255]; - - if (!fab_get_rcpath(hdl, nvl, rcpath)) - goto fail; - - (void) snprintf(query, sizeof (query), "//propval[" - "@name='ASRU' and contains(@value, '%s')]/" - "parent::*/following-sibling::*[@name='pci']/" - "propval[@name='assigned-addresses']", rcpath); - - fmd_hdl_debug(hdl, "xpathObj query %s\n", query); - - xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx); - - if (xpathObj == NULL) - goto fail; - - fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type); - - nodes = xpathObj->nodesetval; - size = (nodes) ? nodes->nodeNr : 0; - - /* Decode the list of assigned addresses xml nodes for each device */ - for (i = 0; i < size; i++) { - char *tprop; - - devNode = nodes->nodeTab[i]; - if (!HAS_PROP(devNode, "value")) - continue; - - /* Convert "string" assigned-addresses to pci_regspec_t */ - j = 0; - tprop = GET_PROP(devNode, "value"); - for (token = strtok(tprop, " "); token; - token = strtok(NULL, " ")) { - prop[j++] = strtoul(token, (char **)NULL, 16); - } - prop[j] = (uint32_t)-1; - FREE_PROP(tprop); - - /* Check if address belongs to this device */ - for (assign_p = (pci_regspec_t *)prop; - assign_p->pci_phys_hi != (uint_t)-1; assign_p++) { - low = assign_p->pci_phys_low; - hi = low + assign_p->pci_size_low; - if ((addr < hi) && (addr >= low)) { - fmd_hdl_debug(hdl, "Found Address\n"); - goto found; - } - } - } - goto fail; - -found: - /* Traverse up the xml tree and back down to find the right propgroup */ - for (devNode = devNode->parent->parent->children; - devNode; devNode = devNode->next) { - char *tprop; - - tprop = GET_PROP(devNode, "name"); - if (STRCMP(devNode->name, "propgroup") && - STRCMP(tprop, "io")) { - FREE_PROP(tprop); - goto propgroup; - } - FREE_PROP(tprop); - } - goto fail; - -propgroup: - /* Retrive the "dev" propval and return */ - for (devNode = devNode->children; devNode; devNode = devNode->next) { - char *tprop; - - tprop = GET_PROP(devNode, "name"); - if (STRCMP(devNode->name, "propval") && - STRCMP(tprop, "dev")) { - FREE_PROP(tprop); - retval = GET_PROP(devNode, "value"); - fmd_hdl_debug(hdl, "Addr Dev Path: %s\n", retval); - xmlXPathFreeObject(xpathObj); - return (retval); - } - FREE_PROP(tprop); - } -fail: - if (xpathObj != NULL) - xmlXPathFreeObject(xpathObj); - return (NULL); -} - -static void -fab_pr(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl) { - nvpair_t *nvp; - - for (nvp = nvlist_next_nvpair(nvl, NULL); - nvp != NULL; - nvp = nvlist_next_nvpair(nvl, nvp)) { - - data_type_t type = nvpair_type(nvp); - const char *name = nvpair_name(nvp); - - boolean_t b; - uint8_t i8; - uint16_t i16; - uint32_t i32; - uint64_t i64; - char *str; - nvlist_t *cnv; - - nvlist_t **nvlarr; - uint_t arrsize; - int arri; - - - if (STRCMP(name, FM_CLASS)) - continue; /* already printed by caller */ - - fmd_hdl_debug(hdl, " %s=", name); - - switch (type) { - case DATA_TYPE_BOOLEAN: - fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN 1"); - break; - - case DATA_TYPE_BOOLEAN_VALUE: - (void) nvpair_value_boolean_value(nvp, &b); - fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN_VALUE %d", - b ? "1" : "0"); - break; - - case DATA_TYPE_BYTE: - (void) nvpair_value_byte(nvp, &i8); - fmd_hdl_debug(hdl, "DATA_TYPE_BYTE 0x%x", i8); - break; - - case DATA_TYPE_INT8: - (void) nvpair_value_int8(nvp, (void *)&i8); - fmd_hdl_debug(hdl, "DATA_TYPE_INT8 0x%x", i8); - break; - - case DATA_TYPE_UINT8: - (void) nvpair_value_uint8(nvp, &i8); - fmd_hdl_debug(hdl, "DATA_TYPE_UINT8 0x%x", i8); - break; - - case DATA_TYPE_INT16: - (void) nvpair_value_int16(nvp, (void *)&i16); - fmd_hdl_debug(hdl, "DATA_TYPE_INT16 0x%x", i16); - break; - - case DATA_TYPE_UINT16: - (void) nvpair_value_uint16(nvp, &i16); - fmd_hdl_debug(hdl, "DATA_TYPE_UINT16 0x%x", i16); - break; - - case DATA_TYPE_INT32: - (void) nvpair_value_int32(nvp, (void *)&i32); - fmd_hdl_debug(hdl, "DATA_TYPE_INT32 0x%x", i32); - break; - - case DATA_TYPE_UINT32: - (void) nvpair_value_uint32(nvp, &i32); - fmd_hdl_debug(hdl, "DATA_TYPE_UINT32 0x%x", i32); - break; - - case DATA_TYPE_INT64: - (void) nvpair_value_int64(nvp, (void *)&i64); - fmd_hdl_debug(hdl, "DATA_TYPE_INT64 0x%llx", - (u_longlong_t)i64); - break; - - case DATA_TYPE_UINT64: - (void) nvpair_value_uint64(nvp, &i64); - fmd_hdl_debug(hdl, "DATA_TYPE_UINT64 0x%llx", - (u_longlong_t)i64); - break; - - case DATA_TYPE_HRTIME: - (void) nvpair_value_hrtime(nvp, (void *)&i64); - fmd_hdl_debug(hdl, "DATA_TYPE_HRTIME 0x%llx", - (u_longlong_t)i64); - break; - - case DATA_TYPE_STRING: - (void) nvpair_value_string(nvp, &str); - fmd_hdl_debug(hdl, "DATA_TYPE_STRING \"%s\"", - str ? str : "<NULL>"); - break; - - case DATA_TYPE_NVLIST: - fmd_hdl_debug(hdl, "["); - (void) nvpair_value_nvlist(nvp, &cnv); - fab_pr(hdl, NULL, cnv); - fmd_hdl_debug(hdl, " ]"); - break; - - case DATA_TYPE_BOOLEAN_ARRAY: - case DATA_TYPE_BYTE_ARRAY: - case DATA_TYPE_INT8_ARRAY: - case DATA_TYPE_UINT8_ARRAY: - case DATA_TYPE_INT16_ARRAY: - case DATA_TYPE_UINT16_ARRAY: - case DATA_TYPE_INT32_ARRAY: - case DATA_TYPE_UINT32_ARRAY: - case DATA_TYPE_INT64_ARRAY: - case DATA_TYPE_UINT64_ARRAY: - case DATA_TYPE_STRING_ARRAY: - fmd_hdl_debug(hdl, "[...]"); - break; - case DATA_TYPE_NVLIST_ARRAY: - arrsize = 0; - (void) nvpair_value_nvlist_array(nvp, &nvlarr, - &arrsize); - - for (arri = 0; arri < arrsize; arri++) { - fab_pr(hdl, ep, nvlarr[arri]); - } - - break; - case DATA_TYPE_UNKNOWN: - fmd_hdl_debug(hdl, "<unknown>"); - break; - } - } -} - /*ARGSUSED*/ static void fab_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class) { - fab_data_t fab_data = {0}; + nvlist_t *new_nvl; if (!fab_valid_topo) fab_update_topo(hdl); - if (fmd_nvl_class_match(hdl, nvl, "ereport.io.pci.fabric")) { - fmd_hdl_debug(hdl, "PCI ereport received: %s\n", class); - fab_pci_fabric_to_data(hdl, nvl, &fab_data); - fab_xlate_pcie_erpts(hdl, &fab_data); + if (nvlist_dup(nvl, &new_nvl, NV_UNIQUE_NAME) != 0) { + fmd_hdl_error(hdl, "failed to duplicate event"); + return; + } + + if (fmd_nvl_class_match(hdl, new_nvl, "ereport.io.pci.fabric")) { + fab_xlate_fabric_erpts(hdl, new_nvl, class); } else { - fab_pr(hdl, ep, nvl); - fmd_hdl_debug(hdl, "Fire RC ereport received: %s\n", class); - fab_fire_to_data(hdl, nvl, &fab_data); - fab_xlate_fire_erpts(hdl, &fab_data, nvl, class); - fab_xlate_pcie_erpts(hdl, &fab_data); + fab_pr(hdl, ep, new_nvl); + if (fmd_nvl_class_match(hdl, new_nvl, + "ereport.io.pciex.rc.epkt")) { + fab_xlate_epkt_erpts(hdl, new_nvl, class); + } else { + fab_xlate_fire_erpts(hdl, new_nvl, class); + } } + + nvlist_free(new_nvl); } /* ARGSUSED */ @@ -2022,18 +125,9 @@ static const fmd_hdl_info_t fmd_info = { "Fabric Ereport Translater", "1.0", &fmd_ops, NULL }; -#define REG_OFF(reg) ((uint32_t)(uint32_t)&fab_data.reg - (uint32_t)&fab_data) -#define SET_TBL(n, err, reg, sz) \ - fab_master_err_tbl[n].erpt_tbl = fab_ ## err ## _erpt_tbl; \ - fab_master_err_tbl[n].reg_offset = REG_OFF(reg); \ - fab_master_err_tbl[n].reg_size = sz; \ - fab_master_err_tbl[n].fab_prep = fab_prep_ ## err ## _erpt; - void _fmd_init(fmd_hdl_t *hdl) { - fab_data_t fab_data; - if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) return; @@ -2043,22 +137,7 @@ _fmd_init(fmd_hdl_t *hdl) fab_fmd_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL); fmd_hdl_debug(hdl, "Fabric Translater Started\n"); - /* Setup the master error table */ - fab_master_err_tbl = (fab_err_tbl_t *)calloc(13, - sizeof (fab_err_tbl_t)); - - SET_TBL(0, pci, pci_err_status, 16); - SET_TBL(1, pci_bdg, pci_bdg_sec_stat, 16); - SET_TBL(2, pci_bdg_ctl, pci_bdg_ctrl, 16); - SET_TBL(3, pcie_ce, pcie_ce_status, 32); - SET_TBL(4, pcie_ue, pcie_ue_status, 32); - SET_TBL(5, pcie_sue, pcie_sue_status, 32); - SET_TBL(6, pcix, pcix_status, 32); - SET_TBL(7, pcix_bdg_sec, pcix_bdg_sec_stat, 16); - SET_TBL(8, pcix_bdg, pcix_bdg_stat, 32); - SET_TBL(9, pcie_nadv, pcie_err_status, 16); - SET_TBL(10, pcie_rc, pcie_rp_err_status, 32); - SET_TBL(11, pcie_fake_rc, pcie_err_status, 16); + fab_setup_master_table(); } void diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.conf b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.conf index 17c65ca987..53d6d17bdd 100644 --- a/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.conf +++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.conf @@ -37,4 +37,4 @@ subscribe ereport.io.n2.dmu.sun4v_adj_va_uf subscribe ereport.io.n2.dmu.sun4v_inv_pg_sz subscribe ereport.io.n2.dmu.sun4v_key_err subscribe ereport.io.n2.dmu.sun4v_va_oor - +subscribe ereport.io.pciex.rc.epkt diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.h b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.h new file mode 100644 index 0000000000..e03f310bfa --- /dev/null +++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.h @@ -0,0 +1,173 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _FABRIC_XLATE_H +#define _FABRIC_XLATE_H + +#include <fm/fmd_api.h> +#include <sys/fm/protocol.h> +#include <sys/nvpair.h> +#include <sys/types.h> +#include <sys/pcie.h> +#include <sys/fm/io/pci.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define STRCMP(s1, s2) (strcmp((const char *)s1, (const char *)s2) == 0) +/* + * These values are used for the xxx_tgt_trans value in fab_data_t. They are + * originally set in pcie_fault.c and originally defined in pcie_impl.h. + */ +#define PF_ADDR_DMA (1 << 0) +#define PF_ADDR_PIO (1 << 1) +#define PF_ADDR_CFG (1 << 2) + +extern fmd_xprt_t *fab_fmd_xprt; /* FMD transport layer handle */ +extern char fab_buf[]; + +/* PCI-E config space data for error handling and fabric ereports */ +typedef struct fab_data { + /* Original ereport NVL */ + nvlist_t *nvl; + + /* Device Information */ + uint16_t bdf; + uint16_t device_id; + uint16_t vendor_id; + uint8_t rev_id; + uint16_t dev_type; + uint16_t pcie_off; + uint16_t pcix_off; + uint16_t aer_off; + uint16_t ecc_ver; + + /* Ereport Information */ + uint32_t remainder; + uint32_t severity; + + /* Error Registers */ + uint16_t pci_err_status; /* pci status register */ + uint16_t pci_cfg_comm; /* pci command register */ + + uint16_t pci_bdg_sec_stat; /* PCI secondary status reg */ + uint16_t pci_bdg_ctrl; /* PCI bridge control reg */ + + uint16_t pcix_command; /* pcix command register */ + uint32_t pcix_status; /* pcix status register */ + + uint16_t pcix_bdg_sec_stat; /* pcix bridge secondary status reg */ + uint32_t pcix_bdg_stat; /* pcix bridge status reg */ + + uint16_t pcix_ecc_control_0; /* pcix ecc control status reg */ + uint16_t pcix_ecc_status_0; /* pcix ecc control status reg */ + uint32_t pcix_ecc_fst_addr_0; /* pcix ecc first address reg */ + uint32_t pcix_ecc_sec_addr_0; /* pcix ecc second address reg */ + uint32_t pcix_ecc_attr_0; /* pcix ecc attributes reg */ + uint16_t pcix_ecc_control_1; /* pcix ecc control status reg */ + uint16_t pcix_ecc_status_1; /* pcix ecc control status reg */ + uint32_t pcix_ecc_fst_addr_1; /* pcix ecc first address reg */ + uint32_t pcix_ecc_sec_addr_1; /* pcix ecc second address reg */ + uint32_t pcix_ecc_attr_1; /* pcix ecc attributes reg */ + + uint16_t pcie_err_status; /* pcie device status register */ + uint16_t pcie_err_ctl; /* pcie error control register */ + uint32_t pcie_dev_cap; /* pcie device capabilities register */ + + uint32_t pcie_adv_ctl; /* pcie advanced control reg */ + uint32_t pcie_ue_status; /* pcie ue error status reg */ + uint32_t pcie_ue_mask; /* pcie ue error mask reg */ + uint32_t pcie_ue_sev; /* pcie ue error severity reg */ + uint32_t pcie_ue_hdr[4]; /* pcie ue header log */ + uint32_t pcie_ce_status; /* pcie ce error status reg */ + uint32_t pcie_ce_mask; /* pcie ce error mask reg */ + uint32_t pcie_ue_tgt_trans; /* Fault trans type from AER Logs */ + uint64_t pcie_ue_tgt_addr; /* Fault addr from AER Logs */ + pcie_req_id_t pcie_ue_tgt_bdf; /* Fault bdf from SAER Logs */ + boolean_t pcie_ue_no_tgt_erpt; /* Don't send target ereports */ + + uint32_t pcie_sue_ctl; /* pcie bridge secondary ue control */ + uint32_t pcie_sue_status; /* pcie bridge secondary ue status */ + uint32_t pcie_sue_mask; /* pcie bridge secondary ue mask */ + uint32_t pcie_sue_sev; /* pcie bridge secondary ue severity */ + uint32_t pcie_sue_hdr[4]; /* pcie bridge secondary ue hdr log */ + uint32_t pcie_sue_tgt_trans; /* Fault trans type from AER Logs */ + uint64_t pcie_sue_tgt_addr; /* Fault addr from AER Logs */ + pcie_req_id_t pcie_sue_tgt_bdf; /* Fault bdf from SAER Logs */ + + uint32_t pcie_rp_status; /* root complex status register */ + uint16_t pcie_rp_ctl; /* root complex control register */ + uint32_t pcie_rp_err_status; /* pcie root complex error status reg */ + uint32_t pcie_rp_err_cmd; /* pcie root complex error cmd reg */ + uint16_t pcie_rp_ce_src_id; /* pcie root complex ce sourpe id */ + uint16_t pcie_rp_ue_src_id; /* pcie root complex ue sourpe id */ +} fab_data_t; + +typedef struct fab_erpt_tbl { + const char *err_class; /* Final Ereport Class */ + uint32_t reg_bit; /* Error Bit Mask */ + /* Pointer to function that prepares the ereport body */ + const char *tgt_class; /* Target Ereport Class */ +} fab_erpt_tbl_t; + +typedef struct fab_err_tbl { + fab_erpt_tbl_t *erpt_tbl; /* ereport table */ + uint32_t reg_offset; /* sts reg for ereport table offset */ + uint32_t reg_size; /* size of the status register */ + /* Pointer to function that prepares the ereport body */ + int (*fab_prep)(fmd_hdl_t *, fab_data_t *, nvlist_t *, + fab_erpt_tbl_t *); +} fab_err_tbl_t; + +extern void fab_setup_master_table(); + +/* Main functions for converting "fabric" ereports */ +extern void fab_xlate_pcie_erpts(fmd_hdl_t *, fab_data_t *); +extern void fab_xlate_fabric_erpts(fmd_hdl_t *, nvlist_t *, const char *); +extern void fab_xlate_fire_erpts(fmd_hdl_t *, nvlist_t *, const char *); +extern void fab_xlate_epkt_erpts(fmd_hdl_t *, nvlist_t *, const char *); + +/* Common functions for sending translated ereports */ +extern int fab_prep_basic_erpt(fmd_hdl_t *, nvlist_t *, nvlist_t *, boolean_t); +extern void fab_send_tgt_erpt(fmd_hdl_t *, fab_data_t *, const char *, + boolean_t); +extern void fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl); + +/* Misc Functions */ +extern void fab_pr(fmd_hdl_t *, fmd_event_t *, nvlist_t *); +extern boolean_t fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath); +extern char *fab_find_rppath_by_df(fmd_hdl_t *, nvlist_t *, uint8_t); +extern char *fab_find_rppath_by_devbdf(fmd_hdl_t *, nvlist_t *, pcie_req_id_t); +extern char *fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr); +extern char *fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf); +extern boolean_t fab_hc2dev(fmd_hdl_t *, const char *, char **); +extern boolean_t fab_hc2dev_nvl(fmd_hdl_t *, nvlist_t *, char **); + +#ifdef __cplusplus +} +#endif + +#endif /* _FABRIC_XLATE_H */ diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fx_epkt.c b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_epkt.c new file mode 100644 index 0000000000..ccace31212 --- /dev/null +++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_epkt.c @@ -0,0 +1,262 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +#include <sys/types.h> +#include <px_err.h> + +#include "fabric-xlate.h" + +#define EPKT_DESC(b, o, p, c, d) (BLOCK_##b << 16 | OP_##o << 12 | \ + PH_##p << 8 | CND_##c << 4 | DIR_##d) + +/* EPKT Table used only for RC/RP errors */ +typedef struct fab_epkt_tbl { + uint32_t epkt_desc; + uint32_t pcie_ue_sts; /* Equivalent PCIe UE Status */ + uint16_t pci_err_sts; /* Equivalent PCI Error Status */ + uint16_t pci_bdg_sts; /* Equivalent PCI Bridge Status */ + const char *tgt_class; /* Target Ereport Class */ +} fab_epkt_tbl_t; + +static fab_epkt_tbl_t fab_epkt_tbl[] = { + EPKT_DESC(MMU, XLAT, DATA, INV, RDWR), + PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB, 0, + EPKT_DESC(MMU, XLAT, ADDR, UNMAP, RDWR), + PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB, 0, + EPKT_DESC(MMU, XLAT, DATA, PROT, RDWR), + PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB, 0, + + EPKT_DESC(INTR, MSI32, DATA, ILL, IRR), + PCIE_AER_UCE_MTLP, PCI_STAT_S_SYSERR, 0, 0, + + EPKT_DESC(PORT, PIO, IRR, RCA, WRITE), + PCIE_AER_UCE_CA, PCI_STAT_S_SYSERR, PCI_STAT_S_TARG_AB, 0, + + EPKT_DESC(PORT, PIO, IRR, RUR, WRITE), + PCIE_AER_UCE_UR, PCI_STAT_S_SYSERR, 0, 0, + + EPKT_DESC(PORT, PIO, IRR, INV, RDWR), + PCIE_AER_UCE_MTLP, PCI_STAT_S_SYSERR, 0, 0, + + EPKT_DESC(PORT, PIO, IRR, TO, READ), + PCIE_AER_UCE_TO, PCI_STAT_S_SYSERR, 0, PCI_TARG_MA, + EPKT_DESC(PORT, PIO, IRR, TO, WRITE), + PCIE_AER_UCE_TO, PCI_STAT_S_SYSERR, 0, PCI_TARG_MA, + + EPKT_DESC(PORT, PIO, IRR, UC, IRR), + PCIE_AER_UCE_UC, PCI_STAT_S_SYSERR, 0, 0, + + EPKT_DESC(PORT, LINK, FC, TO, IRR), + PCIE_AER_UCE_FCP, PCI_STAT_S_SYSERR, 0, 0, + + 0, 0, 0, 0, 0 +}; + +/* ARGSUSED */ +void +fab_epkt_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) +{ + data->nvl = nvl; + + /* Always Root Complex */ + data->dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT; + + data->pcie_ue_sev = (PCIE_AER_UCE_DLP | PCIE_AER_UCE_SD | + PCIE_AER_UCE_FCP | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP); +} + +static int +fab_xlate_epkt(fmd_hdl_t *hdl, fab_data_t *data, px_rc_err_t *epktp) +{ + fab_epkt_tbl_t *entry; + uint32_t temp; + + for (entry = fab_epkt_tbl; entry->epkt_desc != 0; entry++) { + temp = *(uint32_t *)&epktp->rc_descr >> 12; + if (entry->epkt_desc == temp) + goto send; + } + + return (0); + +send: + fmd_hdl_debug(hdl, "Translate epkt DESC = %#x\n", temp); + + /* Fill in PCI Status Register */ + data->pci_err_status = entry->pci_err_sts; + data->pci_bdg_sec_stat = entry->pci_bdg_sts; + + /* Fill in the device status register */ + if (epktp->rc_descr.STOP) + data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; + else if (epktp->rc_descr.C) + data->pcie_err_status = PCIE_DEVSTS_CE_DETECTED; + else + data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; + + /* Fill in the AER UE register */ + data->pcie_ue_status = entry->pcie_ue_sts; + + /* Fill in the AER Control register */ + temp = entry->pcie_ue_sts; + for (data->pcie_adv_ctl = (uint32_t)-1; temp; data->pcie_adv_ctl++) + temp = temp >> 1; + + /* Send target ereports */ + data->pcie_ue_no_tgt_erpt = B_TRUE; + if (entry->tgt_class && !epktp->rc_descr.STOP) { + if (epktp->rc_descr.D) { + data->pcie_ue_tgt_trans = PF_ADDR_DMA; + data->pcie_ue_tgt_addr = epktp->addr; + } else if (epktp->rc_descr.M) { + data->pcie_ue_tgt_trans = PF_ADDR_PIO; + data->pcie_ue_tgt_addr = epktp->addr; + } + + if (data->pcie_ue_tgt_trans) + fab_send_tgt_erpt(hdl, data, entry->tgt_class, + B_TRUE); + } + return (1); +} + +void +fab_xlate_epkt_erpts(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class) +{ + fab_data_t data = {0}; + px_rc_err_t epkt = {0}; + pcie_tlp_hdr_t *tlp_hdr; + void *ptr; + uint8_t ver; + int err; + char *rppath = NULL; + nvlist_t *detector; + + fmd_hdl_debug(hdl, "epkt ereport received: %s\n", class); + fab_epkt_to_data(hdl, nvl, &data); + + err = nvlist_lookup_uint8(nvl, "epkt_ver", &ver); + err |= nvlist_lookup_uint32(nvl, "desc", (uint32_t *)&epkt.rc_descr); + err |= nvlist_lookup_uint32(nvl, "size", &epkt.size); + err |= nvlist_lookup_uint64(nvl, "addr", &epkt.addr); + err |= nvlist_lookup_uint64(nvl, "hdr1", &epkt.hdr[0]); + err |= nvlist_lookup_uint64(nvl, "hdr2", &epkt.hdr[1]); + err |= nvlist_lookup_uint64(nvl, "reserved", &epkt.reserved); + + if (err != 0) { + fmd_hdl_debug(hdl, "Failed to retrieve all epkt payloads"); + return; + } + + fmd_hdl_debug(hdl, "epkt flags: %c%c%c%c%c%c%c%c%c %s", + epkt.rc_descr.S ? 'S' : '-', epkt.rc_descr.M ? 'M' : '-', + epkt.rc_descr.S ? 'Q' : '-', epkt.rc_descr.D ? 'D' : '-', + epkt.rc_descr.R ? 'R' : '-', epkt.rc_descr.H ? 'H' : '-', + epkt.rc_descr.C ? 'C' : '-', epkt.rc_descr.I ? 'I' : '-', + epkt.rc_descr.B ? 'B' : '-', epkt.rc_descr.STOP ? "STOP" : ""); + + /* + * If the least byte of the 'reserved' is non zero, it is device + * and function of the port + */ + if (epkt.reserved && 0xff) + rppath = fab_find_rppath_by_df(hdl, nvl, epkt.reserved & 0xff); + + if (epkt.rc_descr.H) { + data.pcie_ue_hdr[0] = (uint32_t)(epkt.hdr[0] >> 32); + data.pcie_ue_hdr[1] = (uint32_t)epkt.hdr[0]; + data.pcie_ue_hdr[2] = (uint32_t)(epkt.hdr[1] >> 32); + data.pcie_ue_hdr[3] = (uint32_t)(epkt.hdr[1]); + + tlp_hdr = (pcie_tlp_hdr_t *)&data.pcie_ue_hdr[0]; + ptr = &data.pcie_ue_hdr[1]; + switch (tlp_hdr->type) { + case PCIE_TLP_TYPE_IO: + case PCIE_TLP_TYPE_MEM: + case PCIE_TLP_TYPE_MEMLK: + { + pcie_mem64_t *pmp = ptr; + data.pcie_ue_tgt_trans = PF_ADDR_PIO; + data.pcie_ue_tgt_bdf = pmp->rid; + if (tlp_hdr->fmt & 0x1) + data.pcie_ue_tgt_addr = + ((uint64_t)pmp->addr1 << 32) | pmp->addr0; + else + data.pcie_ue_tgt_addr = + ((pcie_memio32_t *)ptr)->addr0; + + break; + } + + case PCIE_TLP_TYPE_CFG0: + case PCIE_TLP_TYPE_CFG1: + { + pcie_cfg_t *pcp = ptr; + + data.pcie_ue_tgt_trans = PF_ADDR_CFG; + data.pcie_ue_tgt_bdf = + (pcp->bus << 8) | (pcp->dev << 3) | pcp->func; + break; + } + + case PCIE_TLP_TYPE_CPL: + case PCIE_TLP_TYPE_CPLLK: + data.pcie_ue_tgt_bdf = ((pcie_cpl_t *)ptr)->rid; + break; + } + + fmd_hdl_debug(hdl, "HEADER 0 0x%x", data.pcie_ue_hdr[0]); + fmd_hdl_debug(hdl, "HEADER 1 0x%x", data.pcie_ue_hdr[1]); + fmd_hdl_debug(hdl, "HEADER 2 0x%x", data.pcie_ue_hdr[2]); + fmd_hdl_debug(hdl, "HEADER 3 0x%x", data.pcie_ue_hdr[3]); + fmd_hdl_debug(hdl, "In header bdf = %#hx addr = %#llx", + data.pcie_ue_tgt_bdf, + (uint64_t)data.pcie_ue_tgt_addr); + + /* find the root port to which this error is related */ + if (data.pcie_ue_tgt_bdf) + rppath = fab_find_rppath_by_devbdf(hdl, nvl, + data.pcie_ue_tgt_bdf); + } + + /* + * reset the detector in the original ereport to the root port + */ + if (rppath && nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) == 0) { + (void) nvlist_add_string(detector, FM_VERSION, + FM_DEV_SCHEME_VERSION); + (void) nvlist_add_string(detector, FM_FMRI_SCHEME, + FM_FMRI_SCHEME_DEV); + (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, rppath); + (void) nvlist_remove_all(nvl, FM_EREPORT_DETECTOR); + (void) nvlist_add_nvlist(nvl, FM_EREPORT_DETECTOR, detector); + nvlist_free(detector); + } + + fmd_hdl_strfree(hdl, rppath); + + (void) fab_xlate_epkt(hdl, &data, &epkt); + fab_xlate_pcie_erpts(hdl, &data); +} diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fabric.c b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fabric.c new file mode 100644 index 0000000000..3a9b1e4f77 --- /dev/null +++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fabric.c @@ -0,0 +1,834 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +#include <stddef.h> +#include <strings.h> +#include <sys/fm/util.h> + +#include "fabric-xlate.h" + +#define FAB_LOOKUP(sz, name, field) \ + (void) nvlist_lookup_uint ## sz(nvl, name, field) + +static boolean_t fab_xlate_fake_rp = B_TRUE; +static fab_err_tbl_t *fab_master_err_tbl; + +/* + * Translation tables for converting "fabric" error bits into "pci" ereports. + * <Ereport Class Name>, <Error Bit Mask>, <Preparation Function> + */ + +/* MACRO for table entries with no TGT ereports */ +#define NT(class, bit, prep) class, bit, prep, NULL +/* Translate Fabric ereports to ereport.io.pci.* */ +fab_erpt_tbl_t fab_pci_erpt_tbl[] = { + PCI_DET_PERR, PCI_STAT_PERROR, NULL, + PCI_MDPE, PCI_STAT_S_PERROR, NULL, + PCI_SIG_SERR, PCI_STAT_S_SYSERR, NULL, + PCI_MA, PCI_STAT_R_MAST_AB, NULL, + PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL, + PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, + NULL, NULL, NULL +}; + +/* Translate Fabric ereports to ereport.io.pci.sec-* */ +static fab_erpt_tbl_t fab_pci_bdg_erpt_tbl[] = { + PCI_DET_PERR, PCI_STAT_PERROR, NULL, + PCI_MDPE, PCI_STAT_S_PERROR, NULL, + PCI_REC_SERR, PCI_STAT_S_SYSERR, NULL, +#ifdef sparc + PCI_MA, PCI_STAT_R_MAST_AB, NULL, +#endif + PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL, + PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, + NULL, NULL, NULL, NULL, +}; + + +/* Translate Fabric ereports to ereport.io.pci.dto */ +static fab_erpt_tbl_t fab_pci_bdg_ctl_erpt_tbl[] = { + PCI_DTO, PCI_BCNF_BCNTRL_DTO_STAT, NULL, + NULL, NULL, NULL +}; + +/* Translate Fabric ereports to ereport.io.pciex.* */ +static fab_erpt_tbl_t fab_pcie_ce_erpt_tbl[] = { + PCIEX_RE, PCIE_AER_CE_RECEIVER_ERR, NULL, + PCIEX_RNR, PCIE_AER_CE_REPLAY_ROLLOVER, NULL, + PCIEX_RTO, PCIE_AER_CE_REPLAY_TO, NULL, + PCIEX_BDP, PCIE_AER_CE_BAD_DLLP, NULL, + PCIEX_BTP, PCIE_AER_CE_BAD_TLP, NULL, + PCIEX_ANFE, PCIE_AER_CE_AD_NFE, NULL, + NULL, NULL, NULL +}; + +/* + * Translate Fabric ereports to ereport.io.pciex.* + * The Target Ereports for this section is only used on leaf devices, with the + * exception of TO + */ +static fab_erpt_tbl_t fab_pcie_ue_erpt_tbl[] = { + PCIEX_TE, PCIE_AER_UCE_TRAINING, NULL, + PCIEX_DLP, PCIE_AER_UCE_DLP, NULL, + PCIEX_SD, PCIE_AER_UCE_SD, NULL, + PCIEX_ROF, PCIE_AER_UCE_RO, NULL, + PCIEX_FCP, PCIE_AER_UCE_FCP, NULL, + PCIEX_MFP, PCIE_AER_UCE_MTLP, NULL, + PCIEX_CTO, PCIE_AER_UCE_TO, PCI_TARG_MA, + PCIEX_UC, PCIE_AER_UCE_UC, NULL, + PCIEX_ECRC, PCIE_AER_UCE_ECRC, NULL, + PCIEX_CA, PCIE_AER_UCE_CA, PCI_TARG_REC_TA, +#ifdef sparc + PCIEX_UR, PCIE_AER_UCE_UR, PCI_TARG_MA, +#endif + PCIEX_POIS, PCIE_AER_UCE_PTLP, PCI_TARG_MDPE, + NULL, NULL, NULL +}; + +/* Translate Fabric ereports to ereport.io.pciex.* */ +static fab_erpt_tbl_t fab_pcie_sue_erpt_tbl[] = { + PCIEX_S_TA_SC, PCIE_AER_SUCE_TA_ON_SC, PCI_TARG_REC_TA, + PCIEX_S_MA_SC, PCIE_AER_SUCE_MA_ON_SC, PCI_TARG_MA, + PCIEX_S_RTA, PCIE_AER_SUCE_RCVD_TA, PCI_TARG_REC_TA, +#ifdef sparc + PCIEX_S_RMA, PCIE_AER_SUCE_RCVD_MA, PCI_TARG_MA, +#endif + PCIEX_S_USC, PCIE_AER_SUCE_USC_ERR, NULL, + PCIEX_S_USCMD, PCIE_AER_SUCE_USC_MSG_DATA_ERR, PCI_TARG_REC_TA, + PCIEX_S_UDE, PCIE_AER_SUCE_UC_DATA_ERR, PCI_TARG_MDPE, + PCIEX_S_UAT, PCIE_AER_SUCE_UC_ATTR_ERR, PCI_TARG_MDPE, + PCIEX_S_UADR, PCIE_AER_SUCE_UC_ADDR_ERR, PCI_TARG_MDPE, + PCIEX_S_TEX, PCIE_AER_SUCE_TIMER_EXPIRED, NULL, + PCIEX_S_PERR, PCIE_AER_SUCE_PERR_ASSERT, PCI_TARG_MDPE, + PCIEX_S_SERR, PCIE_AER_SUCE_SERR_ASSERT, NULL, + PCIEX_INTERR, PCIE_AER_SUCE_INTERNAL_ERR, NULL, + NULL, NULL, NULL +}; + +/* Translate Fabric ereports to ereport.io.pcix.* */ +static fab_erpt_tbl_t fab_pcix_erpt_tbl[] = { + PCIX_SPL_DIS, PCI_PCIX_SPL_DSCD, NULL, + PCIX_UNEX_SPL, PCI_PCIX_UNEX_SPL, NULL, + PCIX_RX_SPL_MSG, PCI_PCIX_RX_SPL_MSG, NULL, + NULL, NULL, NULL +}; +static fab_erpt_tbl_t *fab_pcix_bdg_erpt_tbl = fab_pcix_erpt_tbl; + +/* Translate Fabric ereports to ereport.io.pcix.sec-* */ +static fab_erpt_tbl_t fab_pcix_bdg_sec_erpt_tbl[] = { + PCIX_SPL_DIS, PCI_PCIX_BSS_SPL_DSCD, NULL, + PCIX_UNEX_SPL, PCI_PCIX_BSS_UNEX_SPL, NULL, + PCIX_BSS_SPL_OR, PCI_PCIX_BSS_SPL_OR, NULL, + PCIX_BSS_SPL_DLY, PCI_PCIX_BSS_SPL_DLY, NULL, + NULL, NULL, NULL +}; + +/* Translate Fabric ereports to ereport.io.pciex.* */ +static fab_erpt_tbl_t fab_pcie_nadv_erpt_tbl[] = { +#ifdef sparc + PCIEX_UR, PCIE_DEVSTS_UR_DETECTED, NULL, +#endif + PCIEX_FAT, PCIE_DEVSTS_FE_DETECTED, NULL, + PCIEX_NONFAT, PCIE_DEVSTS_NFE_DETECTED, NULL, + PCIEX_CORR, PCIE_DEVSTS_CE_DETECTED, NULL, + NULL, NULL, NULL +}; + +/* Translate Fabric ereports to ereport.io.pciex.* */ +static fab_erpt_tbl_t fab_pcie_rc_erpt_tbl[] = { + PCIEX_RC_FE_MSG, PCIE_AER_RE_STS_FE_MSGS_RCVD, NULL, + PCIEX_RC_NFE_MSG, PCIE_AER_RE_STS_NFE_MSGS_RCVD, NULL, + PCIEX_RC_CE_MSG, PCIE_AER_RE_STS_CE_RCVD, NULL, + PCIEX_RC_MCE_MSG, PCIE_AER_RE_STS_MUL_CE_RCVD, NULL, + PCIEX_RC_MUE_MSG, PCIE_AER_RE_STS_MUL_FE_NFE_RCVD, NULL, + NULL, NULL, NULL +}; + +/* + * Translate Fabric ereports to pseudo ereport.io.pciex.* RC Fabric Messages. + * If the RP is not a PCIe compliant RP or does not support AER, rely on the + * leaf fabric ereport to help create a xxx_MSG ereport coming from the RC. + */ +static fab_erpt_tbl_t fab_pcie_fake_rc_erpt_tbl[] = { + PCIEX_RC_FE_MSG, PCIE_DEVSTS_FE_DETECTED, NULL, + PCIEX_RC_NFE_MSG, PCIE_DEVSTS_NFE_DETECTED, NULL, + PCIEX_RC_CE_MSG, PCIE_DEVSTS_CE_DETECTED, NULL, + NULL, NULL, NULL, +}; + +/* ARGSUSED */ +void +fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) +{ + data->nvl = nvl; + + /* Generic PCI device information */ + FAB_LOOKUP(16, "bdf", &data->bdf); + FAB_LOOKUP(16, "device_id", &data->device_id); + FAB_LOOKUP(16, "vendor_id", &data->vendor_id); + FAB_LOOKUP(8, "rev_id", &data->rev_id); + FAB_LOOKUP(16, "dev_type", &data->dev_type); + FAB_LOOKUP(16, "pcie_off", &data->pcie_off); + FAB_LOOKUP(16, "pcix_off", &data->pcix_off); + FAB_LOOKUP(16, "aer_off", &data->aer_off); + FAB_LOOKUP(16, "ecc_ver", &data->ecc_ver); + + /* Misc ereport information */ + FAB_LOOKUP(32, "remainder", &data->remainder); + FAB_LOOKUP(32, "severity", &data->severity); + + /* PCI registers */ + FAB_LOOKUP(16, "pci_status", &data->pci_err_status); + FAB_LOOKUP(16, "pci_command", &data->pci_cfg_comm); + + /* PCI bridge registers */ + FAB_LOOKUP(16, "pci_bdg_sec_status", &data->pci_bdg_sec_stat); + FAB_LOOKUP(16, "pci_bdg_ctrl", &data->pci_bdg_ctrl); + + /* PCIx registers */ + FAB_LOOKUP(32, "pcix_status", &data->pcix_status); + FAB_LOOKUP(16, "pcix_command", &data->pcix_command); + + /* PCIx ECC Registers */ + FAB_LOOKUP(16, "pcix_ecc_control_0", &data->pcix_ecc_control_0); + FAB_LOOKUP(16, "pcix_ecc_status_0", &data->pcix_ecc_status_0); + FAB_LOOKUP(32, "pcix_ecc_fst_addr_0", &data->pcix_ecc_fst_addr_0); + FAB_LOOKUP(32, "pcix_ecc_sec_addr_0", &data->pcix_ecc_sec_addr_0); + FAB_LOOKUP(32, "pcix_ecc_attr_0", &data->pcix_ecc_attr_0); + + /* PCIx ECC Bridge Registers */ + FAB_LOOKUP(16, "pcix_ecc_control_1", &data->pcix_ecc_control_1); + FAB_LOOKUP(16, "pcix_ecc_status_1", &data->pcix_ecc_status_1); + FAB_LOOKUP(32, "pcix_ecc_fst_addr_1", &data->pcix_ecc_fst_addr_1); + FAB_LOOKUP(32, "pcix_ecc_sec_addr_1", &data->pcix_ecc_sec_addr_1); + FAB_LOOKUP(32, "pcix_ecc_attr_1", &data->pcix_ecc_attr_1); + + /* PCIx Bridge */ + FAB_LOOKUP(32, "pcix_bdg_status", &data->pcix_bdg_stat); + FAB_LOOKUP(16, "pcix_bdg_sec_status", &data->pcix_bdg_sec_stat); + + /* PCIe registers */ + FAB_LOOKUP(16, "pcie_status", &data->pcie_err_status); + FAB_LOOKUP(16, "pcie_command", &data->pcie_err_ctl); + FAB_LOOKUP(32, "pcie_dev_cap", &data->pcie_dev_cap); + + /* PCIe AER registers */ + FAB_LOOKUP(32, "pcie_adv_ctl", &data->pcie_adv_ctl); + FAB_LOOKUP(32, "pcie_ue_status", &data->pcie_ue_status); + FAB_LOOKUP(32, "pcie_ue_mask", &data->pcie_ue_mask); + FAB_LOOKUP(32, "pcie_ue_sev", &data->pcie_ue_sev); + FAB_LOOKUP(32, "pcie_ue_hdr0", &data->pcie_ue_hdr[0]); + FAB_LOOKUP(32, "pcie_ue_hdr1", &data->pcie_ue_hdr[1]); + FAB_LOOKUP(32, "pcie_ue_hdr2", &data->pcie_ue_hdr[2]); + FAB_LOOKUP(32, "pcie_ue_hdr3", &data->pcie_ue_hdr[3]); + FAB_LOOKUP(32, "pcie_ce_status", &data->pcie_ce_status); + FAB_LOOKUP(32, "pcie_ce_mask", &data->pcie_ce_mask); + FAB_LOOKUP(32, "pcie_ue_tgt_trans", &data->pcie_ue_tgt_trans); + FAB_LOOKUP(64, "pcie_ue_tgt_addr", &data->pcie_ue_tgt_addr); + FAB_LOOKUP(16, "pcie_ue_tgt_bdf", &data->pcie_ue_tgt_bdf); + + /* PCIe BDG AER registers */ + FAB_LOOKUP(32, "pcie_sue_adv_ctl", &data->pcie_sue_ctl); + FAB_LOOKUP(32, "pcie_sue_status", &data->pcie_sue_status); + FAB_LOOKUP(32, "pcie_sue_mask", &data->pcie_sue_mask); + FAB_LOOKUP(32, "pcie_sue_sev", &data->pcie_sue_sev); + FAB_LOOKUP(32, "pcie_sue_hdr0", &data->pcie_sue_hdr[0]); + FAB_LOOKUP(32, "pcie_sue_hdr1", &data->pcie_sue_hdr[1]); + FAB_LOOKUP(32, "pcie_sue_hdr2", &data->pcie_sue_hdr[2]); + FAB_LOOKUP(32, "pcie_sue_hdr3", &data->pcie_sue_hdr[3]); + FAB_LOOKUP(32, "pcie_sue_tgt_trans", &data->pcie_sue_tgt_trans); + FAB_LOOKUP(64, "pcie_sue_tgt_addr", &data->pcie_sue_tgt_addr); + FAB_LOOKUP(16, "pcie_sue_tgt_bdf", &data->pcie_sue_tgt_bdf); + + /* PCIe RP registers */ + FAB_LOOKUP(32, "pcie_rp_status", &data->pcie_rp_status); + FAB_LOOKUP(16, "pcie_rp_control", &data->pcie_rp_ctl); + + /* PCIe RP AER registers */ + FAB_LOOKUP(32, "pcie_adv_rp_status", &data->pcie_rp_err_status); + FAB_LOOKUP(32, "pcie_adv_rp_command", &data->pcie_rp_err_cmd); + FAB_LOOKUP(16, "pcie_adv_rp_ce_src_id", &data->pcie_rp_ce_src_id); + FAB_LOOKUP(16, "pcie_adv_rp_ue_src_id", &data->pcie_rp_ue_src_id); + + /* + * If the system has a PCIe complaint RP with AER, turn off translating + * fake RP ereports. + */ + if (fab_xlate_fake_rp && + (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) && + data->aer_off) + fab_xlate_fake_rp = B_FALSE; +} + +static int +fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", + PCI_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + (void) nvlist_add_uint16(erpt, PCI_CONFIG_STATUS, data->pci_err_status); + (void) nvlist_add_uint16(erpt, PCI_CONFIG_COMMAND, data->pci_cfg_comm); + + return (err); +} + +static int +fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s-%s", + PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, + data->pci_bdg_sec_stat); + (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); + + return (err); +} + +static int +fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", + PCI_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, + data->pci_bdg_sec_stat); + (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); + + return (err); +} + + +static int +fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", + PCIEX_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); + (void) nvlist_add_uint32(erpt, PCIEX_CE_STATUS_REG, + data->pcie_ce_status); + + return (err); +} + +static int +fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + uint32_t first_err = 1 << (data->pcie_adv_ctl & + PCIE_AER_CTL_FST_ERR_PTR_MASK); + int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", + PCIEX_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); + (void) nvlist_add_uint32(erpt, PCIEX_UE_STATUS_REG, + data->pcie_ue_status); + (void) nvlist_add_uint32(erpt, PCIEX_UE_SEV_REG, data->pcie_ue_sev); + (void) nvlist_add_uint32(erpt, PCIEX_ADV_CTL, data->pcie_adv_ctl); + + fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); + + if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_bdf) { + (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, + data->pcie_ue_tgt_bdf); + (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); + } else { + (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); + (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); + } + + if ((tbl->reg_bit == first_err) && !data->pcie_ue_no_tgt_erpt && + data->pcie_ue_tgt_trans) { + if (tbl->tgt_class) + fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_TRUE); + } + + return (err); +} + +static int +fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + uint32_t first_err = 1 << (data->pcie_sue_ctl & + PCIE_AER_SCTL_FST_ERR_PTR_MASK); + int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", + PCIEX_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + (void) nvlist_add_uint32(erpt, PCIEX_SEC_UE_STATUS, + data->pcie_sue_status); + + fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); + + if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_bdf) { + (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, + data->pcie_sue_tgt_bdf); + (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); + } else { + (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); + (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); + } + + if ((tbl->reg_bit == first_err) && !data->pcie_ue_no_tgt_erpt && + data->pcie_sue_tgt_trans) { + if (tbl->tgt_class) + fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_FALSE); + } + + return (err); +} + +static int +fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + int err = 0; + + /* Only send if this is not a bridge */ + if (!data->pcix_status || data->pcix_bdg_sec_stat) + return (1); + + err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", + PCIX_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + (void) nvlist_add_uint8(erpt, PCIX_COMMAND, data->pcix_command); + (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); + + return (err); +} + +static void +fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) +{ + nvlist_t *erpt; + int ecc_phase = (data->pcix_ecc_status_0 & PCI_PCIX_ECC_PHASE) >> 0x4; + int ecc_corr = data->pcix_ecc_status_0 & PCI_PCIX_ECC_CORR; + int sec_ue = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_UE; + int sec_ce = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_CE; + uint32_t ctlstat = (data->pcix_ecc_control_0 << 16) | + data->pcix_ecc_status_0; + + switch (ecc_phase) { + case PCI_PCIX_ECC_PHASE_NOERR: + break; + case PCI_PCIX_ECC_PHASE_FADDR: + case PCI_PCIX_ECC_PHASE_SADDR: + (void) snprintf(fab_buf, FM_MAX_CLASS, + "%s.%s", PCIX_ERROR_SUBCLASS, + ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR); + break; + case PCI_PCIX_ECC_PHASE_ATTR: + (void) snprintf(fab_buf, FM_MAX_CLASS, + "%s.%s", PCIX_ERROR_SUBCLASS, + ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); + break; + case PCI_PCIX_ECC_PHASE_DATA32: + case PCI_PCIX_ECC_PHASE_DATA64: + (void) snprintf(fab_buf, FM_MAX_CLASS, + "%s.%s", PCIX_ERROR_SUBCLASS, + ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); + break; + } + + if (ecc_phase) { + if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) + goto done; + (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + (void) nvlist_add_uint16(erpt, PCIX_COMMAND, + data->pcix_command); + (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); + (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); + (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, + data->pcix_ecc_attr_0); + fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); + fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); + if (fmd_xprt_error(hdl, fab_fmd_xprt)) + fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); + } + + if (sec_ce || sec_ue) { + (void) snprintf(fab_buf, FM_MAX_CLASS, + "%s.%s", PCIX_ERROR_SUBCLASS, + sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); + if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) + goto done; + (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + (void) nvlist_add_uint16(erpt, PCIX_COMMAND, + data->pcix_command); + (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); + (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); + (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, + data->pcix_ecc_attr_0); + fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); + fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); + if (fmd_xprt_error(hdl, fab_fmd_xprt)) + fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); + } + + return; +done: + fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); +} + +static int +fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s%s", + PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, + data->pcix_bdg_sec_stat); + (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); + + return (err); +} + +static int +fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", + PCIX_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, + data->pcix_bdg_sec_stat); + (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); + + return (err); +} + +static void +fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) +{ + nvlist_t *erpt; + int ecc_phase = (data->pcix_ecc_status_1 & PCI_PCIX_ECC_PHASE) >> 0x4; + int ecc_corr = data->pcix_ecc_status_1 & PCI_PCIX_ECC_CORR; + int sec_ue = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_UE; + int sec_ce = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_CE; + uint32_t ctlstat = (data->pcix_ecc_control_1 << 16) | + data->pcix_ecc_status_1; + + switch (ecc_phase) { + case PCI_PCIX_ECC_PHASE_NOERR: + break; + case PCI_PCIX_ECC_PHASE_FADDR: + case PCI_PCIX_ECC_PHASE_SADDR: + (void) snprintf(fab_buf, FM_MAX_CLASS, + "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, + ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR); + break; + case PCI_PCIX_ECC_PHASE_ATTR: + (void) snprintf(fab_buf, FM_MAX_CLASS, + "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, + ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); + break; + case PCI_PCIX_ECC_PHASE_DATA32: + case PCI_PCIX_ECC_PHASE_DATA64: + (void) snprintf(fab_buf, FM_MAX_CLASS, + "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, + ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); + break; + } + if (ecc_phase) { + if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) + goto done; + (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, + data->pcix_bdg_sec_stat); + (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, + data->pcix_bdg_stat); + (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); + (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, + data->pcix_ecc_attr_1); + fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); + fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); + if (fmd_xprt_error(hdl, fab_fmd_xprt)) + fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); + } + + if (sec_ce || sec_ue) { + (void) snprintf(fab_buf, FM_MAX_CLASS, + "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, + sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); + if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) + goto done; + (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, + data->pcix_bdg_sec_stat); + (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, + data->pcix_bdg_stat); + (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); + (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, + data->pcix_ecc_attr_1); + fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); + fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); + if (fmd_xprt_error(hdl, fab_fmd_xprt)) + fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); + } + return; +done: + fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); +} + +static int +fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + int err = 0; + + /* Don't send this for PCI device, Root Ports, or PCIe with AER */ + if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || + (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || + data->aer_off) + return (1); + + err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", + PCIEX_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); + + return (err); +} + +static int +fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + uint32_t status = data->pcie_rp_err_status; + int err = 0; + int isFE = 0, isNFE = 0; + + fmd_hdl_debug(hdl, "XLATE RP Error Class %s", class); + + if (!data->aer_off) + return (-1); + + /* Only send a FE Msg if the 1st UE error is FE */ + if (STRCMP(class, PCIEX_RC_FE_MSG)) + if (!(status & PCIE_AER_RE_STS_FIRST_UC_FATAL)) + return (-1); + else + isFE = 1; + + /* Only send a NFE Msg is the 1st UE error is NFE */ + if (STRCMP(class, PCIEX_RC_NFE_MSG)) + if (status & PCIE_AER_RE_STS_FIRST_UC_FATAL) + return (-1); + else + isNFE = 1; + + fmd_hdl_debug(hdl, "XLATE RP Error"); + + err |= fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", + PCIEX_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, status); + if ((isFE || isNFE) && data->pcie_rp_ue_src_id) { + (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, + data->pcie_rp_ue_src_id); + (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); + } + if (STRCMP(class, PCIEX_RC_CE_MSG) && data->pcie_rp_ce_src_id) { + (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, + data->pcie_rp_ce_src_id); + (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); + } + + return (err); +} + +static int +fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + fab_erpt_tbl_t *tbl) +{ + const char *class = tbl->err_class; + uint32_t rc_err_sts = 0; + int err = 0; + + /* + * Don't send this for PCI device or Root Ports. Only send it on + * systems with non-compliant RPs. + */ + if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || + (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || + (!fab_xlate_fake_rp)) + return (-1); + + err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_TRUE); + + /* Generate an ereport for this error bit. */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", + PCIEX_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + /* Send PCIe RC Ereports */ + if (data->pcie_err_status & PCIE_DEVSTS_CE_DETECTED) { + rc_err_sts |= PCIE_AER_RE_STS_CE_RCVD; + } + + /* NFE/FE src id takes precedence over CE src id */ + if (data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) { + rc_err_sts |= PCIE_AER_RE_STS_NFE_MSGS_RCVD; + rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; + } + if (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED) { + rc_err_sts |= PCIE_AER_RE_STS_FE_MSGS_RCVD; + rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; + } + if ((data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) && + (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED)) { + rc_err_sts |= PCIE_AER_RE_STS_FIRST_UC_FATAL; + rc_err_sts |= PCIE_AER_RE_STS_MUL_FE_NFE_RCVD; + } + + (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, rc_err_sts); + + if (!(rc_err_sts & PCIE_AER_RE_STS_MUL_FE_NFE_RCVD)) { + (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, data->bdf); + (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); + } + + return (err); +} + +void +fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data) +{ + fab_err_tbl_t *tbl; + + fmd_hdl_debug(hdl, "Sending Ereports Now"); + + /* Go through the error logs and send the relavant reports */ + for (tbl = fab_master_err_tbl; tbl->erpt_tbl; tbl++) { + fab_send_erpt(hdl, data, tbl); + } + + /* Send PCI-X ECC Ereports */ + fab_send_pcix_ecc_erpt(hdl, data); + fab_send_pcix_bdg_ecc_erpt(hdl, data); +} + +void +fab_xlate_fabric_erpts(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class) +{ + fab_data_t data = {0}; + + fmd_hdl_debug(hdl, "fabric ereport received: %s\n", class); + + fab_pci_fabric_to_data(hdl, nvl, &data); + fab_xlate_pcie_erpts(hdl, &data); +} + +#define SET_TBL(n, err, reg, sz) \ + fab_master_err_tbl[n].erpt_tbl = fab_ ## err ## _erpt_tbl; \ + fab_master_err_tbl[n].reg_offset = offsetof(fab_data_t, reg); \ + fab_master_err_tbl[n].reg_size = sz; \ + fab_master_err_tbl[n].fab_prep = fab_prep_ ## err ## _erpt; + +void +fab_setup_master_table() +{ + /* Setup the master error table */ + fab_master_err_tbl = (fab_err_tbl_t *)calloc(13, + sizeof (fab_err_tbl_t)); + + SET_TBL(0, pci, pci_err_status, 16); + SET_TBL(1, pci_bdg, pci_bdg_sec_stat, 16); + SET_TBL(2, pci_bdg_ctl, pci_bdg_ctrl, 16); + SET_TBL(3, pcie_ce, pcie_ce_status, 32); + SET_TBL(4, pcie_ue, pcie_ue_status, 32); + SET_TBL(5, pcie_sue, pcie_sue_status, 32); + SET_TBL(6, pcix, pcix_status, 32); + SET_TBL(7, pcix_bdg_sec, pcix_bdg_sec_stat, 16); + SET_TBL(8, pcix_bdg, pcix_bdg_stat, 32); + SET_TBL(9, pcie_nadv, pcie_err_status, 16); + SET_TBL(10, pcie_rc, pcie_rp_err_status, 32); + SET_TBL(11, pcie_fake_rc, pcie_err_status, 16); +} diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fire.c b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fire.c new file mode 100644 index 0000000000..f508f24569 --- /dev/null +++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fire.c @@ -0,0 +1,396 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +#include <strings.h> +#include <sys/fm/io/sun4_fire.h> + +#include "fabric-xlate.h" + +typedef struct fab_fire_tbl { + const char *err_class; + uint32_t fire_bit; /* Fire error bit */ + uint16_t pci_err_sts; /* Equivalent PCI Error Status */ + uint16_t pci_bdg_sts; /* Equivalent PCI Bridge Status */ +} fab_fire_tbl_t; + +/* + * Translation tables for converting fire error bits into "pci" ereports. + * <Fire Bit> + * <pci ereport Class> + * <pci error status reg> + * <pci bridge status reg> + * <pci target class> + */ +#define FAB_FIRE_PEC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_PEC_ ## fb +#define FAB_FIRE_DMC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_DMC_ ## fb +#define FAB_N2_DMU_BIT(fb) "ereport.io.n2.dmu." fb +#define FAB_OB_PEC_BIT(fb) "ereport.io." PCIEX_OBERON "." FIRE_PEC_ ## fb + +#define FAB_FIRE_UE(fb, bit, sts, bdg) \ + FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg +#define FAB_OB_UE(fb, bit, sts, bdg) \ + FAB_OB_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg +static fab_fire_tbl_t fab_fire_pec_ue_tbl[] = { + FAB_FIRE_UE(UR, UR, PCI_STAT_S_SYSERR, 0), + FAB_FIRE_UE(UC, UC, PCI_STAT_S_SYSERR, 0), + FAB_OB_UE(ECRC, ECRC, PCI_STAT_S_SYSERR, 0), + FAB_FIRE_UE(CTO, TO, PCI_STAT_S_SYSERR, 0), + FAB_FIRE_UE(ROF, RO, PCI_STAT_S_SYSERR, 0), + FAB_FIRE_UE(MFP, MTLP, PCI_STAT_S_SYSERR, 0), + FAB_FIRE_UE(PP, PTLP, PCI_STAT_S_PERROR, + (PCI_STAT_S_SYSERR | PCI_STAT_PERROR)), + FAB_FIRE_UE(FCP, FCP, PCI_STAT_S_SYSERR, 0), + FAB_FIRE_UE(DLP, DLP, PCI_STAT_S_SYSERR, 0), + FAB_FIRE_UE(TE, TRAINING, PCI_STAT_S_SYSERR, 0), + FAB_FIRE_UE(CA, CA, PCI_STAT_S_TARG_AB, + PCI_STAT_S_TARG_AB), + NULL, NULL, NULL, +}; + +#define FAB_FIRE_CE(fb, bit) \ + FAB_FIRE_PEC_BIT(fb), PCIE_AER_CE_ ## bit, 0, 0 +static fab_fire_tbl_t fab_fire_pec_ce_tbl[] = { + FAB_FIRE_CE(RTO, REPLAY_TO), + FAB_FIRE_CE(RNR, REPLAY_ROLLOVER), + FAB_FIRE_CE(BDP, BAD_DLLP), + FAB_FIRE_CE(BTP, BAD_TLP), + FAB_FIRE_CE(RE, RECEIVER_ERR), + NULL, NULL, NULL, +}; + +/* + * WUC/RUC will need to be special cased for the target ereports, because you + * need to decode the tlp log. + */ +#define FAB_FIRE_WUCRUC(fb) \ + FAB_FIRE_PEC_BIT(fb), 0, 0, (PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR) +#define FAB_FIRE_OE(fb, bit) \ + FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0 +#define FAB_OB_OE(fb, bit) \ + FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0 +static fab_fire_tbl_t fab_fire_pec_oe_tbl[] = { + FAB_FIRE_WUCRUC(WUC), + FAB_FIRE_WUCRUC(RUC), + FAB_FIRE_OE(ERU, DLP), + FAB_FIRE_OE(ERO, DLP), + FAB_FIRE_OE(EMP, DLP), + FAB_FIRE_OE(EPE, DLP), + NULL, NULL, NULL, +}; + +#define FAB_FIRE_DMC(fb) \ + FAB_FIRE_DMC_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB +#define FAB_N2_DMU(fb) \ + FAB_N2_DMU_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB +static fab_fire_tbl_t fab_fire_dmc_tbl[] = { + FAB_FIRE_DMC(BYP_ERR), + FAB_FIRE_DMC(BYP_OOR), + FAB_FIRE_DMC(TRN_OOR), + FAB_FIRE_DMC(TTE_INV), + FAB_FIRE_DMC(TTE_PRT), + FAB_N2_DMU("iotsbdesc_inv"), + FAB_N2_DMU("sun4v_adj_va_uf"), + FAB_N2_DMU("sun4v_inv_pg_sz"), + FAB_N2_DMU("sun4v_key_err"), + FAB_N2_DMU("sun4v_va_oor"), + NULL, NULL, NULL +}; + +/* ARGSUSED */ +static void +fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) +{ + data->nvl = nvl; + + /* Always Root Complex */ + data->dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT; + + data->pcie_ue_sev = (PCIE_AER_UCE_DLP | PCIE_AER_UCE_SD | + PCIE_AER_UCE_FCP | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP); +} + +static int +fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + const char *class) +{ + fab_fire_tbl_t *entry; + uint64_t reg; + + for (entry = fab_fire_pec_ce_tbl; entry->err_class; entry++) { + if (STRCMP(class, entry->err_class)) + goto send; + } + + return (0); + +send: + fmd_hdl_debug(hdl, "Translate Fire CE %s\n", class); + + /* Fill in the device status register */ + data->pcie_err_status = PCIE_DEVSTS_CE_DETECTED; + + /* Fill in the AER CE register */ + if (nvlist_lookup_uint64(erpt, "tlu-cess", ®) == 0) { + data->pcie_ce_status = (uint32_t)reg | (uint32_t)(reg >> 32); + } + + return (1); +} + +static int +fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + const char *class) +{ + fab_fire_tbl_t *entry; + uint64_t reg; + uint32_t temp; + pcie_tlp_hdr_t *hdr; + + for (entry = fab_fire_pec_ue_tbl; entry->err_class; entry++) { + if (STRCMP(class, entry->err_class)) + goto send; + } + + return (0); + +send: + fmd_hdl_debug(hdl, "Translate Fire UE %s\n", class); + + /* Fill in PCI Status Register */ + data->pci_err_status = entry->pci_err_sts; + data->pci_bdg_sec_stat = entry->pci_bdg_sts; + + /* Fill in the device status register */ + if (entry->fire_bit & data->pcie_ue_sev) + data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; + else + data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; + + if (entry->fire_bit == PCIE_AER_UCE_UR) + data->pcie_err_status |= PCIE_DEVSTS_UR_DETECTED; + + /* Fill in the AER UE register */ + if (nvlist_lookup_uint64(erpt, "tlu-uess", ®) == 0) { + data->pcie_ue_status = (uint32_t)reg | (uint32_t)(reg >> 32); + } + + /* Fill in the AER Control register */ + if ((reg & (uint64_t)entry->fire_bit) && + nvlist_lookup_boolean(erpt, "primary")) { + temp = entry->fire_bit; + for (data->pcie_adv_ctl = (uint32_t)-1; temp; + data->pcie_adv_ctl++) + temp = temp >> 1; + } + + /* If CTO create target information */ + if (entry->fire_bit == PCIE_AER_UCE_TO && + nvlist_lookup_boolean(erpt, "primary")) { + if (nvlist_lookup_uint64(erpt, "tlu-tueh1l", ®) == 0) { + data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); + data->pcie_ue_hdr[1] = (uint32_t)(reg); + } + if (nvlist_lookup_uint64(erpt, "tlu-tueh2l", ®) == 0) { + data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); + data->pcie_ue_hdr[3] = (uint32_t)(reg); + } + + hdr = (pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]); + switch (hdr->type) { + case PCIE_TLP_TYPE_IO: + case PCIE_TLP_TYPE_MEM: + case PCIE_TLP_TYPE_MEMLK: + data->pcie_ue_tgt_trans = PF_ADDR_PIO; + if (hdr->fmt & 0x1) { + data->pcie_ue_tgt_addr = reg; + } else { + data->pcie_ue_tgt_addr = data->pcie_ue_hdr[2]; + } + break; + case PCIE_TLP_TYPE_CFG0: + case PCIE_TLP_TYPE_CFG1: + data->pcie_ue_tgt_trans = PF_ADDR_CFG; + data->pcie_ue_tgt_bdf = data->pcie_ue_hdr[2] >> 16; + break; + } + } + + /* Fill in the AER Header registers */ + if (nvlist_lookup_uint64(erpt, "tlu-rueh1l", ®) == 0) { + data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); + data->pcie_ue_hdr[1] = (uint32_t)(reg); + } + if (nvlist_lookup_uint64(erpt, "tlu-rueh2l", ®) == 0) { + data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); + data->pcie_ue_hdr[3] = (uint32_t)(reg); + } + + return (1); +} + +static int +fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + const char *class) +{ + fab_fire_tbl_t *entry; + uint64_t reg; + + for (entry = fab_fire_pec_oe_tbl; entry->err_class; entry++) { + if (STRCMP(class, entry->err_class)) + goto send; + } + + return (0); + +send: + fmd_hdl_debug(hdl, "Translate Fire OE %s\n", class); + + /* Fill in PCI Status Register */ + if (entry->fire_bit) { + data->pci_err_status = entry->pci_err_sts; + data->pci_bdg_sec_stat = entry->pci_bdg_sts; + } else { + if (nvlist_lookup_uint64(erpt, "tlu-roeeh1l", ®) == 0) { + data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); + data->pcie_ue_hdr[1] = (uint32_t)(reg); + } + if (nvlist_lookup_uint64(erpt, "tlu-roeeh2l", ®) == 0) { + data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); + data->pcie_ue_hdr[3] = (uint32_t)(reg); + } + + if (((pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]))->type == + PCIE_TLP_TYPE_CPL) { + pcie_cpl_t *cpl = (pcie_cpl_t *)&data->pcie_ue_hdr[1]; + switch (cpl->status) { + case PCIE_CPL_STS_UR: + data->pci_err_status = 0; + data->pci_bdg_sec_stat = PCI_STAT_R_MAST_AB | + PCI_STAT_S_SYSERR; + break; + case PCIE_CPL_STS_CA: + data->pci_err_status = 0; + data->pci_bdg_sec_stat = PCI_STAT_R_TARG_AB | + PCI_STAT_S_SYSERR; + break; + } + } + } + + /* Fill in the device status register */ + if (entry->fire_bit & data->pcie_ue_sev) + data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; + else + data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; + + /* Fill in the AER UE register */ + data->pcie_ue_status = entry->fire_bit; + + return (1); +} + +static int +fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, + const char *class) +{ + fab_fire_tbl_t *entry; + uint64_t reg; + uint32_t temp; + + for (entry = fab_fire_dmc_tbl; entry->err_class; entry++) { + fmd_hdl_debug(hdl, "Matching %s\n", entry->err_class); + if (STRCMP(class, entry->err_class) && + nvlist_lookup_boolean(erpt, "primary")) + goto send; + } + + return (0); + +send: + fmd_hdl_debug(hdl, "Translate Fire DMC %s\n", class); + + /* Fill in PCI Status Register */ + data->pci_err_status = entry->pci_err_sts; + data->pci_bdg_sec_stat = entry->pci_bdg_sts; + + /* Fill in the device status register */ + data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; + + /* Fill in the AER UE register */ + data->pcie_ue_status = entry->fire_bit; + + /* Fill in the AER Control register */ + temp = entry->fire_bit; + for (data->pcie_adv_ctl = (uint32_t)-1; temp; data->pcie_adv_ctl++) + temp = temp >> 1; + + /* Fill in the AER Header registers */ + if (nvlist_lookup_uint64(erpt, "mmu-tfsr", ®) == 0) { + fmd_hdl_debug(hdl, "tfsr 0x%llx\n", reg); + /* Get the trans type */ + temp = (reg & 0x3F0000) >> 16; + data->pcie_ue_hdr[0] = (uint32_t)(temp << 24); + data->pcie_ue_tgt_trans = PF_ADDR_DMA; + /* Get the req id */ + temp = (reg & 0xFFFF); + data->pcie_ue_hdr[1] = (uint32_t)(temp << 16); + data->pcie_ue_tgt_bdf = temp; + } + + if (nvlist_lookup_uint64(erpt, "mmu-tfar", ®) == 0) { + fmd_hdl_debug(hdl, "tfar 0x%llx\n", reg); + /* Get the address */ + data->pcie_ue_hdr[2] = reg; + data->pcie_ue_hdr[3] = 0; + data->pcie_ue_tgt_addr = reg; + } + + fmd_hdl_debug(hdl, "HEADER 0 0x%x\n", data->pcie_ue_hdr[0]); + fmd_hdl_debug(hdl, "HEADER 1 0x%x\n", data->pcie_ue_hdr[1]); + fmd_hdl_debug(hdl, "HEADER 2 0x%x\n", data->pcie_ue_hdr[2]); + fmd_hdl_debug(hdl, "HEADER 3 0x%x\n", data->pcie_ue_hdr[3]); + + return (1); +} + +void +fab_xlate_fire_erpts(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class) +{ + fab_data_t data = {0}; + + fmd_hdl_debug(hdl, "Fire RC ereport received: %s\n", class); + + fab_fire_to_data(hdl, nvl, &data); + + if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.pec.*")) { + if (! fab_xlate_fire_ce(hdl, &data, nvl, class) && + ! fab_xlate_fire_ue(hdl, &data, nvl, class)) + (void) fab_xlate_fire_oe(hdl, &data, nvl, class); + } else if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.dmc.*") || + fmd_nvl_class_match(hdl, nvl, "ereport.io.n2.dmu.*")) + (void) fab_xlate_fire_dmc(hdl, &data, nvl, class); + + fab_xlate_pcie_erpts(hdl, &data); +} diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fx_subr.c b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_subr.c new file mode 100644 index 0000000000..c88afe982f --- /dev/null +++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_subr.c @@ -0,0 +1,837 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +#include <strings.h> +#include <fm/topo_hc.h> +#include <sys/fm/util.h> +#include <libxml/xpath.h> +#include <libxml/parser.h> +#include <libxml/xpathInternals.h> +#include <libxml/tree.h> + +#include "fabric-xlate.h" + +#define HAS_PROP(node, name) xmlHasProp(node, (const xmlChar *)name) +#define GET_PROP(node, name) ((char *)xmlGetProp(node, (const xmlChar *)name)) +#define FREE_PROP(prop) xmlFree((xmlChar *)prop) + +extern xmlXPathContextPtr fab_xpathCtx; + +/* ARGSUSED */ +int +fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt, + boolean_t isRC) +{ + uint64_t *now; + uint64_t ena; + uint_t nelem; + nvlist_t *detector, *new_detector; + char rcpath[255]; + int err = 0; + + /* Grab the tod, ena and detector(FMRI) */ + err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem); + err |= nvlist_lookup_uint64(nvl, "ena", &ena); + err |= nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector); + if (err) + return (err); + + /* Make a copy of the detector */ + err = nvlist_dup(detector, &new_detector, NV_UNIQUE_NAME); + if (err) + return (err); + + /* Copy the tod and ena to erpt */ + (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena); + (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem); + + /* + * Create the correct ROOT FMRI from PCIe leaf fabric ereports. Used + * only by fab_prep_fake_rc_erpt. See the fab_pciex_fake_rc_erpt_tbl + * comments for more information. + */ + if (isRC && fab_get_rcpath(hdl, nvl, rcpath)) { + /* Create the correct PCIe RC new_detector aka FMRI */ + (void) nvlist_remove(new_detector, FM_FMRI_DEV_PATH, + DATA_TYPE_STRING); + (void) nvlist_add_string(new_detector, FM_FMRI_DEV_PATH, + rcpath); + } + + /* Copy the FMRI to erpt */ + (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, new_detector); + + nvlist_free(new_detector); + return (err); +} + +void +fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, const char *class, + boolean_t isPrimary) +{ + nvlist_t *nvl = data->nvl; + nvlist_t *erpt; + char *fmri = NULL; + uint32_t tgt_trans; + uint64_t tgt_addr; + uint16_t tgt_bdf; + + if (isPrimary) { + tgt_trans = data->pcie_ue_tgt_trans; + tgt_addr = data->pcie_ue_tgt_addr; + tgt_bdf = data->pcie_ue_tgt_bdf; + } else { + tgt_trans = data->pcie_sue_tgt_trans; + tgt_addr = data->pcie_sue_tgt_addr; + tgt_bdf = data->pcie_sue_tgt_bdf; + } + + fmd_hdl_debug(hdl, "Sending Target Ereport: " + "type 0x%x addr 0x%llx fltbdf 0x%x\n", + tgt_trans, tgt_addr, tgt_bdf); + + if (!tgt_trans) + return; + + if ((tgt_trans == PF_ADDR_PIO) && tgt_addr) + fmri = fab_find_addr(hdl, nvl, tgt_addr); + else if ((tgt_trans == PF_ADDR_CFG || (tgt_trans == PF_ADDR_DMA)) && + tgt_bdf) + fmri = fab_find_bdf(hdl, nvl, tgt_bdf); + + if (fmri) { + uint64_t *now; + uint64_t ena; + uint_t nelem; + nvlist_t *detector; + int err = 0; + + /* Allocate space for new erpt */ + if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) + goto done; + + /* Generate the target ereport class */ + (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", + PCI_ERROR_SUBCLASS, class); + (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); + + /* Grab the tod, ena and detector(FMRI) */ + err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem); + err |= nvlist_lookup_uint64(nvl, "ena", &ena); + + /* Copy the tod and ena to erpt */ + (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena); + (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem); + + /* Create the correct FMRI */ + if (nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0) { + nvlist_free(erpt); + goto done; + } + (void) nvlist_add_uint8(detector, FM_VERSION, + FM_DEV_SCHEME_VERSION); + (void) nvlist_add_string(detector, FM_FMRI_SCHEME, + FM_FMRI_SCHEME_DEV); + (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, fmri); + (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, detector); + nvlist_free(detector); + + /* Add the address payload */ + (void) nvlist_add_uint64(erpt, PCI_PA, tgt_addr); + + fmd_hdl_debug(hdl, "Sending target ereport: %s 0x%x\n", + fab_buf, tgt_addr); + fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); + if (fmd_xprt_error(hdl, fab_fmd_xprt)) + goto done; + fmd_hdl_strfree(hdl, fmri); + } else { + fmd_hdl_debug(hdl, + "Cannot find Target FMRI addr:0x%llx bdf 0x%x\n", + tgt_addr, tgt_bdf); + } + + return; +done: + if (fmri) + xmlFree(fmri); + fmd_hdl_debug(hdl, "Failed to send Target PCI ereport\n"); +} + +void +fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl) +{ + fab_erpt_tbl_t *erpt_tbl, *entry; + nvlist_t *erpt; + uint32_t reg; + + erpt_tbl = tbl->erpt_tbl; + if (tbl->reg_size == 16) { + reg = (uint32_t)*((uint16_t *) + ((uint32_t)data + tbl->reg_offset)); + } else { + reg = *((uint32_t *)((uint32_t)data + tbl->reg_offset)); + } + + for (entry = erpt_tbl; entry->err_class; entry++) { + if (!(reg & entry->reg_bit)) + continue; + + if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) + goto done; + if (tbl->fab_prep(hdl, data, erpt, entry) != 0) { + fmd_hdl_debug(hdl, "Prepping ereport failed: " + "class = %s\n", entry->err_class); + nvlist_free(erpt); + continue; + } + + fmd_hdl_debug(hdl, "Sending ereport: %s 0x%x\n", fab_buf, reg); + fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); + if (fmd_xprt_error(hdl, fab_fmd_xprt)) { + fmd_hdl_debug(hdl, "Failed to send PCI ereport\n"); + return; + } + } + + return; +done: + fmd_hdl_debug(hdl, "Failed to send PCI ereport\n"); +} + +char * +fab_xpath_query(fmd_hdl_t *hdl, const char *query) +{ + xmlXPathObjectPtr xpathObj; + xmlNodeSetPtr nodes; + char *temp, *res; + + fmd_hdl_debug(hdl, "xpathObj query %s\n", query); + + xpathObj = xmlXPathEvalExpression((const xmlChar *)query, + fab_xpathCtx); + + if (xpathObj == NULL) + return (NULL); + + fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, + xpathObj->type); + nodes = xpathObj->nodesetval; + + if (nodes) { + temp = (char *)xmlNodeGetContent(nodes->nodeTab[0]); + fmd_hdl_debug(hdl, "query result: %s\n", temp); + res = fmd_hdl_strdup(hdl, temp, FMD_SLEEP); + xmlFree(temp); + xmlXPathFreeObject(xpathObj); + return (res); + } + xmlXPathFreeObject(xpathObj); + return (NULL); +} + +#define FAB_HC2DEV_QUERY_SIZE_MIN 160 +#define FAB_HC2DEV_QUERY_SIZE(sz) \ + ((sz + FAB_HC2DEV_QUERY_SIZE_MIN) * sizeof (char)) + +/* + * hc_path is in form of "/motherboard=0/hostbridge=0/pciexrc=0" + */ +boolean_t +fab_hc2dev(fmd_hdl_t *hdl, const char *hc_path, char **dev_path) +{ + char *query; + uint_t len = FAB_HC2DEV_QUERY_SIZE_MIN + strlen(hc_path); + + query = fmd_hdl_alloc(hdl, len, FMD_SLEEP); + (void) snprintf(query, len, "//propval[@name='resource' and contains(" + "substring(@value, string-length(@value) - %d + 1), '%s')]" + "/parent::*/following-sibling::*/propval[@name='dev']/@value", + strlen(hc_path) + 1, hc_path); + + *dev_path = fab_xpath_query(hdl, query); + + fmd_hdl_free(hdl, query, len); + + return (*dev_path != NULL); +} + +static boolean_t +fab_hc_path(fmd_hdl_t *hdl, nvlist_t *detector, char **hcpath, size_t *lenp) +{ + char c, *name, *id, *buf; + uint_t i, size; + nvlist_t **hcl; + size_t len = 0, buf_size = 0; + + if (nvlist_lookup_nvlist_array(detector, FM_FMRI_HC_LIST, &hcl, + &size) != 0) + return (B_FALSE); + + for (i = 0; i < size; i++) { + if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0) + return (B_FALSE); + if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &id) != 0) + return (B_FALSE); + buf_size += snprintf(&c, 1, "/%s=%s", name, id); + } + + buf_size++; + buf = fmd_hdl_alloc(hdl, buf_size, FMD_SLEEP); + + for (i = 0; i < size; i++) { + (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name); + (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &id); + len += snprintf(buf + len, buf_size - len, "/%s=%s", name, id); + } + + *hcpath = buf; + *lenp = buf_size; + + return (B_TRUE); +} + +boolean_t +fab_hc2dev_nvl(fmd_hdl_t *hdl, nvlist_t *detector, char **dev_path) +{ + char *hcl; + size_t len; + + if (! fab_hc_path(hdl, detector, &hcl, &len)) + return (B_FALSE); + + (void) fab_hc2dev(hdl, hcl, dev_path); + + fmd_hdl_free(hdl, hcl, len); + + return (*dev_path != NULL); +} + +boolean_t +fab_get_hcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char **hcpath, size_t *len) +{ + nvlist_t *detector; + char *scheme; + + if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0 || + nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0 || + ! STRCMP(scheme, FM_FMRI_SCHEME_HC)) + return (B_FALSE); + + return (fab_hc_path(hdl, detector, hcpath, len)); +} + +char * +fab_find_rppath_by_df(fmd_hdl_t *hdl, nvlist_t *nvl, uint8_t df) +{ + char query[500]; + char str[10]; + char *hcpath; + size_t len; + + (void) snprintf(str, sizeof (str), "%0hhx", df); + + /* + * get the string form of the hc detector, eg + * /chassis=0/motherboard=0/hostbridge=0 + */ + if (!fab_get_hcpath(hdl, nvl, &hcpath, &len)) + return (NULL); + + /* + * Explanation of the XSL XPATH Query + * Line 1: Look at all nodes with the node name "propval" + * Line 2: See if the "BDF" of the node matches DF + * Line 3-4: See if the the node is pciexrc + * Line 5-6: See if the "ASRU" contains root complex + * Line 7-8: Go up one level and get prop value of io/dev + */ + (void) snprintf(query, sizeof (query), "//propval[" + "@name='BDF' and contains(substring(@value, " + "string-length(@value) - 1), '%s')]" + "/parent::*/parent::*/propgroup[@name='pci']/propval" + "[@name='extended-capabilities' and @value='%s']" + "/parent::*/parent::*/propgroup[@name='protocol']" + "/propval[@name='resource' and contains(@value, '%s')]" + "/parent::*/parent::*/propgroup[@name='io']" + "/propval[@name='dev']/@value", str, PCIEX_ROOT, hcpath); + + fmd_hdl_free(hdl, hcpath, len); + + return (fab_xpath_query(hdl, query)); +} + +char * +fab_find_rppath_by_devbdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf) +{ + xmlXPathObjectPtr xpathObj; + xmlNodeSetPtr nodes; + xmlNodePtr devNode; + char *retval, *temp; + char query[500]; + int i, size, bus, dev, fn; + char *hcpath; + size_t len; + + if (bdf != (uint16_t)-1) { + bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT; + dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT; + fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT; + } + + /* + * get the string form of the hc detector, eg + * /chassis=0/motherboard=0/hostbridge=0 + */ + if (!fab_get_hcpath(hdl, nvl, &hcpath, &len)) + goto fail; + + /* + * Explanation of the XSL XPATH Query + * Line 1: Look at all nodes with the node name "propval" + * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF + * Line 4-5: See if the "value" of the node ends with correct PCI BDF + * Line 6: Go up one level to the parent of the current node + * Line 7: See if child node contains "ASRU" with the same PCIe Root + * Line 8: Go up see all the ancestors + */ + (void) snprintf(query, sizeof (query), "//propval[" + "contains(substring(@value, string-length(@value) - 34), " + "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or " + "contains(substring(@value, string-length(@value) - 28), " + "'pcibus=%d/pcidev=%d/pcifn=%d')" + "]/parent::" + "*/propval[@name='resource' and contains(@value, '%s')]" + "/ancestor::*", + bus, dev, fn, bus, dev, fn, hcpath); + + fmd_hdl_free(hdl, hcpath, len); + + fmd_hdl_debug(hdl, "xpathObj query %s\n", query); + + xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx); + + if (xpathObj == NULL) + goto fail; + + nodes = xpathObj->nodesetval; + size = (nodes) ? nodes->nodeNr : 0; + + fmd_hdl_debug(hdl, "xpathObj 0x%p type %d size %d\n", + xpathObj, xpathObj->type, size); + + for (i = 0; i < size; i++) { + devNode = nodes->nodeTab[i]; + if (STRCMP(devNode->name, "range") && + HAS_PROP(devNode, "name")) { + char *tprop = GET_PROP(devNode, "name"); + + /* find "range name='pciexrc'" in ancestors */ + if (STRCMP(tprop, PCIEX_ROOT)) { + /* go down to the pciexrc instance node */ + FREE_PROP(tprop); + devNode = nodes->nodeTab[i+1]; + goto found; + } + FREE_PROP(tprop); + } + } + goto fail; + +found: + /* Traverse down the xml tree to find the right propgroup */ + for (devNode = devNode->children; devNode; devNode = devNode->next) { + if (STRCMP(devNode->name, "propgroup")) { + char *tprop = GET_PROP(devNode, "name"); + + if (STRCMP(tprop, "io")) { + FREE_PROP(tprop); + goto propgroup; + } + FREE_PROP(tprop); + } + } + goto fail; + +propgroup: + /* Retrive the "dev" propval and return */ + for (devNode = devNode->children; devNode; devNode = devNode->next) { + if (STRCMP(devNode->name, "propval")) { + char *tprop = GET_PROP(devNode, "name"); + + if (STRCMP(tprop, "dev")) { + temp = GET_PROP(devNode, "value"); + retval = fmd_hdl_strdup(hdl, temp, FMD_SLEEP); + fmd_hdl_debug(hdl, "RP Path: %s\n", retval); + xmlFree(temp); + xmlXPathFreeObject(xpathObj); + } + FREE_PROP(tprop); + + return (retval); + } + } +fail: + if (xpathObj != NULL) + xmlXPathFreeObject(xpathObj); + return (NULL); +} + +/* ARGSUSED */ +boolean_t +fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath) +{ + nvlist_t *detector; + char *path, *scheme; + + if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0) + goto fail; + if (nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0) + goto fail; + + if (STRCMP(scheme, FM_FMRI_SCHEME_DEV)) { + if (nvlist_lookup_string(detector, FM_FMRI_DEV_PATH, + &path) != 0) + goto fail; + (void) strncpy(rcpath, path, FM_MAX_CLASS); + } else if (STRCMP(scheme, FM_FMRI_SCHEME_HC)) { + /* + * This should only occur for ereports that come from the RC + * itself. In this case convert HC scheme to dev path. + */ + if (fab_hc2dev_nvl(hdl, detector, &path)) { + (void) strncpy(rcpath, path, FM_MAX_CLASS); + fmd_hdl_strfree(hdl, path); + } else { + goto fail; + } + } else { + return (B_FALSE); + } + + /* + * Extract the RC path by taking the first device in the dev path + * + * /pci@0,0/pci8086,3605@2/pci8086,3500@0/pci8086,3514@1/pci8086,105e@0 + * - to - + * /pci@0,0 + */ + path = strchr(rcpath + 1, '/'); + if (path) + path[0] = '\0'; + + return (B_TRUE); +fail: + return (B_FALSE); +} + +char * +fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf) +{ + char *retval; + char query[500]; + int bus, dev, fn; + char rcpath[255]; + + if (bdf != (uint16_t)-1) { + bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT; + dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT; + fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT; + } + + if (!fab_get_rcpath(hdl, nvl, rcpath)) + goto fail; + + /* + * Explanation of the XSL XPATH Query + * Line 1: Look at all nodes with the node name "propval" + * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF + * Line 4-5: See if the "value" of the node ends with correct PCI BDF + * Line 6: Go up one level to the parent of the current node + * Line 7: See if child node contains "ASRU" with the same PCIe Root + * Line 8: Traverse up the parent and the other siblings and look for + * the io "propgroup" and get the value of the dev "propval" + */ + (void) snprintf(query, sizeof (query), "//propval[" + "contains(substring(@value, string-length(@value) - 34), " + "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or " + "contains(substring(@value, string-length(@value) - 28), " + "'pcibus=%d/pcidev=%d/pcifn=%d')" + "]/parent::" + "*/propval[@name='ASRU' and contains(@value, '%s')]" + "/parent::*/following-sibling::*[@name='io']/propval[@name='dev']/" + "@value", bus, dev, fn, bus, dev, fn, rcpath); + + retval = fab_xpath_query(hdl, query); + if (retval) { + fmd_hdl_debug(hdl, "BDF Dev Path: %s\n", retval); + return (retval); + } +fail: + return (NULL); +} + +char * +fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr) +{ + xmlXPathObjectPtr xpathObj; + xmlNodeSetPtr nodes; + xmlNodePtr devNode; + char *retval, *temp; + char query[500]; + int size, i, j; + uint32_t prop[50]; + char *token; + pci_regspec_t *assign_p; + uint64_t low, hi; + char rcpath[255]; + + if (!fab_get_rcpath(hdl, nvl, rcpath)) + goto fail; + + (void) snprintf(query, sizeof (query), "//propval[" + "@name='ASRU' and contains(@value, '%s')]/" + "parent::*/following-sibling::*[@name='pci']/" + "propval[@name='assigned-addresses']", rcpath); + + fmd_hdl_debug(hdl, "xpathObj query %s\n", query); + + xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx); + + if (xpathObj == NULL) + goto fail; + + fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type); + + nodes = xpathObj->nodesetval; + size = (nodes) ? nodes->nodeNr : 0; + + /* Decode the list of assigned addresses xml nodes for each device */ + for (i = 0; i < size; i++) { + char *tprop; + + devNode = nodes->nodeTab[i]; + if (!HAS_PROP(devNode, "value")) + continue; + + /* Convert "string" assigned-addresses to pci_regspec_t */ + j = 0; + tprop = GET_PROP(devNode, "value"); + for (token = strtok(tprop, " "); token; + token = strtok(NULL, " ")) { + prop[j++] = strtoul(token, (char **)NULL, 16); + } + prop[j] = (uint32_t)-1; + FREE_PROP(tprop); + + /* Check if address belongs to this device */ + for (assign_p = (pci_regspec_t *)prop; + assign_p->pci_phys_hi != (uint_t)-1; assign_p++) { + low = assign_p->pci_phys_low; + hi = low + assign_p->pci_size_low; + if ((addr < hi) && (addr >= low)) { + fmd_hdl_debug(hdl, "Found Address\n"); + goto found; + } + } + } + goto fail; + +found: + /* Traverse up the xml tree and back down to find the right propgroup */ + for (devNode = devNode->parent->parent->children; + devNode; devNode = devNode->next) { + char *tprop; + + tprop = GET_PROP(devNode, "name"); + if (STRCMP(devNode->name, "propgroup") && + STRCMP(tprop, "io")) { + FREE_PROP(tprop); + goto propgroup; + } + FREE_PROP(tprop); + } + goto fail; + +propgroup: + /* Retrive the "dev" propval and return */ + for (devNode = devNode->children; devNode; devNode = devNode->next) { + char *tprop; + + tprop = GET_PROP(devNode, "name"); + if (STRCMP(devNode->name, "propval") && + STRCMP(tprop, "dev")) { + FREE_PROP(tprop); + temp = GET_PROP(devNode, "value"); + retval = fmd_hdl_strdup(hdl, temp, FMD_SLEEP); + fmd_hdl_debug(hdl, "Addr Dev Path: %s\n", retval); + xmlFree(temp); + xmlXPathFreeObject(xpathObj); + return (retval); + } + FREE_PROP(tprop); + } +fail: + if (xpathObj != NULL) + xmlXPathFreeObject(xpathObj); + return (NULL); +} + +void +fab_pr(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl) +{ + nvpair_t *nvp; + + for (nvp = nvlist_next_nvpair(nvl, NULL); + nvp != NULL; + nvp = nvlist_next_nvpair(nvl, nvp)) { + + data_type_t type = nvpair_type(nvp); + const char *name = nvpair_name(nvp); + + boolean_t b; + uint8_t i8; + uint16_t i16; + uint32_t i32; + uint64_t i64; + char *str; + nvlist_t *cnv; + + nvlist_t **nvlarr; + uint_t arrsize; + int arri; + + + if (STRCMP(name, FM_CLASS)) + continue; /* already printed by caller */ + + fmd_hdl_debug(hdl, " %s=", name); + + switch (type) { + case DATA_TYPE_BOOLEAN: + fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN 1"); + break; + + case DATA_TYPE_BOOLEAN_VALUE: + (void) nvpair_value_boolean_value(nvp, &b); + fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN_VALUE %d", + b ? "1" : "0"); + break; + + case DATA_TYPE_BYTE: + (void) nvpair_value_byte(nvp, &i8); + fmd_hdl_debug(hdl, "DATA_TYPE_BYTE 0x%x", i8); + break; + + case DATA_TYPE_INT8: + (void) nvpair_value_int8(nvp, (void *)&i8); + fmd_hdl_debug(hdl, "DATA_TYPE_INT8 0x%x", i8); + break; + + case DATA_TYPE_UINT8: + (void) nvpair_value_uint8(nvp, &i8); + fmd_hdl_debug(hdl, "DATA_TYPE_UINT8 0x%x", i8); + break; + + case DATA_TYPE_INT16: + (void) nvpair_value_int16(nvp, (void *)&i16); + fmd_hdl_debug(hdl, "DATA_TYPE_INT16 0x%x", i16); + break; + + case DATA_TYPE_UINT16: + (void) nvpair_value_uint16(nvp, &i16); + fmd_hdl_debug(hdl, "DATA_TYPE_UINT16 0x%x", i16); + break; + + case DATA_TYPE_INT32: + (void) nvpair_value_int32(nvp, (void *)&i32); + fmd_hdl_debug(hdl, "DATA_TYPE_INT32 0x%x", i32); + break; + + case DATA_TYPE_UINT32: + (void) nvpair_value_uint32(nvp, &i32); + fmd_hdl_debug(hdl, "DATA_TYPE_UINT32 0x%x", i32); + break; + + case DATA_TYPE_INT64: + (void) nvpair_value_int64(nvp, (void *)&i64); + fmd_hdl_debug(hdl, "DATA_TYPE_INT64 0x%llx", + (u_longlong_t)i64); + break; + + case DATA_TYPE_UINT64: + (void) nvpair_value_uint64(nvp, &i64); + fmd_hdl_debug(hdl, "DATA_TYPE_UINT64 0x%llx", + (u_longlong_t)i64); + break; + + case DATA_TYPE_HRTIME: + (void) nvpair_value_hrtime(nvp, (void *)&i64); + fmd_hdl_debug(hdl, "DATA_TYPE_HRTIME 0x%llx", + (u_longlong_t)i64); + break; + + case DATA_TYPE_STRING: + (void) nvpair_value_string(nvp, &str); + fmd_hdl_debug(hdl, "DATA_TYPE_STRING \"%s\"", + str ? str : "<NULL>"); + break; + + case DATA_TYPE_NVLIST: + fmd_hdl_debug(hdl, "["); + (void) nvpair_value_nvlist(nvp, &cnv); + fab_pr(hdl, NULL, cnv); + fmd_hdl_debug(hdl, " ]"); + break; + + case DATA_TYPE_BOOLEAN_ARRAY: + case DATA_TYPE_BYTE_ARRAY: + case DATA_TYPE_INT8_ARRAY: + case DATA_TYPE_UINT8_ARRAY: + case DATA_TYPE_INT16_ARRAY: + case DATA_TYPE_UINT16_ARRAY: + case DATA_TYPE_INT32_ARRAY: + case DATA_TYPE_UINT32_ARRAY: + case DATA_TYPE_INT64_ARRAY: + case DATA_TYPE_UINT64_ARRAY: + case DATA_TYPE_STRING_ARRAY: + fmd_hdl_debug(hdl, "[...]"); + break; + case DATA_TYPE_NVLIST_ARRAY: + arrsize = 0; + (void) nvpair_value_nvlist_array(nvp, &nvlarr, + &arrsize); + + for (arri = 0; arri < arrsize; arri++) { + fab_pr(hdl, ep, nvlarr[arri]); + } + + break; + case DATA_TYPE_UNKNOWN: + fmd_hdl_debug(hdl, "<unknown>"); + break; + } + } +} diff --git a/usr/src/cmd/mdb/common/modules/crypto/impl.c b/usr/src/cmd/mdb/common/modules/crypto/impl.c index 52d20d2509..69afb4ecc1 100644 --- a/usr/src/cmd/mdb/common/modules/crypto/impl.c +++ b/usr/src/cmd/mdb/common/modules/crypto/impl.c @@ -175,11 +175,13 @@ kcf_provider_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) mdb_printf("pd_provider_list:\t%p\n", desc.pd_provider_list); mdb_printf("pd_resume_cv:\t\t%hd\n", desc.pd_resume_cv._opaque); - mdb_printf("pd_flags:\t\t%s %s %s %s %s\n", + mdb_printf("pd_flags:\t\t%s %s %s %s %s %s\n", (desc.pd_flags & CRYPTO_HIDE_PROVIDER) ? "CRYPTO_HIDE_PROVIDER" : " ", (desc.pd_flags & CRYPTO_HASH_NO_UPDATE) ? "CRYPTO_HASH_NO_UPDATE" : " ", + (desc.pd_flags & CRYPTO_HMAC_NO_UPDATE) ? + "CRYPTO_HMAC_NO_UPDATE" : " ", (desc.pd_flags & CRYPTO_SYNCHRONOUS) ? "CRYPTO_SYNCHRONOUS" : " ", (desc.pd_flags & KCF_LPROV_MEMBER) ? @@ -188,6 +190,8 @@ kcf_provider_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) "KCF_PROV_RESTRICTED" : " "); if (desc.pd_flags & CRYPTO_HASH_NO_UPDATE) mdb_printf("pd_hash_limit:\t\t%u\n", desc.pd_hash_limit); + if (desc.pd_flags & CRYPTO_HMAC_NO_UPDATE) + mdb_printf("pd_hmac_limit:\t\t%u\n", desc.pd_hmac_limit); mdb_printf("pd_kstat:\t\t%p\n", desc.pd_kstat); |