1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #include <assert.h> 27 #include <stddef.h> 28 #include <errno.h> 29 #include <strings.h> 30 #include <fm/fmd_api.h> 31 #include <fm/libtopo.h> 32 #include <sys/fm/util.h> 33 #include <sys/fm/protocol.h> 34 #include <sys/fm/io/pci.h> 35 #include <sys/fm/io/sun4_fire.h> 36 #include <sys/pci.h> 37 #include <sys/pcie.h> 38 #include <sys/nvpair.h> 39 #include <sys/nvpair_impl.h> 40 41 #include <libxml/xpath.h> 42 #include <libxml/parser.h> 43 #include <libxml/xpathInternals.h> 44 #include <libxml/tree.h> 45 46 /* PCI-E config space data for error handling and fabric ereports */ 47 typedef struct fab_data { 48 /* Original ereport NVL */ 49 nvlist_t *nvl; 50 51 /* Device Information */ 52 uint16_t bdf; 53 uint16_t device_id; 54 uint16_t vendor_id; 55 uint8_t rev_id; 56 uint16_t dev_type; 57 uint16_t pcie_off; 58 uint16_t pcix_off; 59 uint16_t aer_off; 60 uint16_t ecc_ver; 61 62 /* Ereport Information */ 63 uint32_t remainder; 64 uint32_t severity; 65 66 /* Error Registers */ 67 uint16_t pci_err_status; /* pci status register */ 68 uint16_t pci_cfg_comm; /* pci command register */ 69 70 uint16_t pci_bdg_sec_stat; /* PCI secondary status reg */ 71 uint16_t pci_bdg_ctrl; /* PCI bridge control reg */ 72 73 uint16_t pcix_command; /* pcix command register */ 74 uint32_t pcix_status; /* pcix status register */ 75 76 uint16_t pcix_bdg_sec_stat; /* pcix bridge secondary status reg */ 77 uint32_t pcix_bdg_stat; /* pcix bridge status reg */ 78 79 uint16_t pcix_ecc_control_0; /* pcix ecc control status reg */ 80 uint16_t pcix_ecc_status_0; /* pcix ecc control status reg */ 81 uint32_t pcix_ecc_fst_addr_0; /* pcix ecc first address reg */ 82 uint32_t pcix_ecc_sec_addr_0; /* pcix ecc second address reg */ 83 uint32_t pcix_ecc_attr_0; /* pcix ecc attributes reg */ 84 uint16_t pcix_ecc_control_1; /* pcix ecc control status reg */ 85 uint16_t pcix_ecc_status_1; /* pcix ecc control status reg */ 86 uint32_t pcix_ecc_fst_addr_1; /* pcix ecc first address reg */ 87 uint32_t pcix_ecc_sec_addr_1; /* pcix ecc second address reg */ 88 uint32_t pcix_ecc_attr_1; /* pcix ecc attributes reg */ 89 90 uint16_t pcie_err_status; /* pcie device status register */ 91 uint16_t pcie_err_ctl; /* pcie error control register */ 92 uint32_t pcie_dev_cap; /* pcie device capabilities register */ 93 94 uint32_t pcie_adv_ctl; /* pcie advanced control reg */ 95 uint32_t pcie_ue_status; /* pcie ue error status reg */ 96 uint32_t pcie_ue_mask; /* pcie ue error mask reg */ 97 uint32_t pcie_ue_sev; /* pcie ue error severity reg */ 98 uint32_t pcie_ue_hdr[4]; /* pcie ue header log */ 99 uint32_t pcie_ce_status; /* pcie ce error status reg */ 100 uint32_t pcie_ce_mask; /* pcie ce error mask reg */ 101 uint32_t pcie_ue_tgt_trans; /* Fault trans type from AER Logs */ 102 uint64_t pcie_ue_tgt_addr; /* Fault addr from AER Logs */ 103 pcie_req_id_t pcie_ue_tgt_bdf; /* Fault bdf from SAER Logs */ 104 105 uint32_t pcie_sue_ctl; /* pcie bridge secondary ue control */ 106 uint32_t pcie_sue_status; /* pcie bridge secondary ue status */ 107 uint32_t pcie_sue_mask; /* pcie bridge secondary ue mask */ 108 uint32_t pcie_sue_sev; /* pcie bridge secondary ue severity */ 109 uint32_t pcie_sue_hdr[4]; /* pcie bridge secondary ue hdr log */ 110 uint32_t pcie_sue_tgt_trans; /* Fault trans type from AER Logs */ 111 uint64_t pcie_sue_tgt_addr; /* Fault addr from AER Logs */ 112 pcie_req_id_t pcie_sue_tgt_bdf; /* Fault bdf from SAER Logs */ 113 114 uint32_t pcie_rp_status; /* root complex status register */ 115 uint16_t pcie_rp_ctl; /* root complex control register */ 116 uint32_t pcie_rp_err_status; /* pcie root complex error status reg */ 117 uint32_t pcie_rp_err_cmd; /* pcie root complex error cmd reg */ 118 uint16_t pcie_rp_ce_src_id; /* pcie root complex ce sourpe id */ 119 uint16_t pcie_rp_ue_src_id; /* pcie root complex ue sourpe id */ 120 } fab_data_t; 121 122 /* 123 * These values are used for the xxx_tgt_trans value in fab_data_t. They are 124 * originally set in pcie_fault.c and originally defined in pcie_impl.h. 125 */ 126 #define PF_ADDR_DMA (1 << 0) 127 #define PF_ADDR_PIO (1 << 1) 128 #define PF_ADDR_CFG (1 << 2) 129 130 typedef struct fab_erpt_tbl { 131 const char *err_class; /* Final Ereport Class */ 132 uint32_t reg_bit; /* Error Bit Mask */ 133 /* Pointer to function that prepares the ereport body */ 134 const char *tgt_class; /* Target Ereport Class */ 135 } fab_erpt_tbl_t; 136 137 typedef struct fab_err_tbl { 138 fab_erpt_tbl_t *erpt_tbl; /* ereport table */ 139 uint32_t reg_offset; /* sts reg for ereport table offset */ 140 uint32_t reg_size; /* size of the status register */ 141 /* Pointer to function that prepares the ereport body */ 142 int (*fab_prep)(fmd_hdl_t *, fab_data_t *, nvlist_t *, 143 fab_erpt_tbl_t *); 144 } fab_err_tbl_t; 145 146 typedef struct fab_fire_tbl { 147 const char *err_class; 148 uint32_t fire_bit; /* Fire error bit */ 149 uint16_t pci_err_sts; /* Equivalent PCI Error Status */ 150 uint16_t pci_bdg_sts; /* Equivalent PCI Bridge Status */ 151 } fab_fire_tbl_t; 152 153 /* Static FM Topo XML Format and XML XPath Context */ 154 static xmlDocPtr fab_doc = NULL; 155 static xmlXPathContextPtr fab_xpathCtx = NULL; 156 static int fab_valid_topo = 0; 157 #define XMLTOPOFILE "/tmp/fab-xlate-topo.xml" 158 159 /* Functions that convert ereports to a common C data structure */ 160 static void fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, 161 fab_data_t *data); 162 static void fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data); 163 164 /* Common functions for sending translated ereports */ 165 static int fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt, 166 boolean_t isRC); 167 static boolean_t fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath); 168 static char *fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr); 169 static char *fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf); 170 static void fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, 171 const char *class, boolean_t isPrimary); 172 static void fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl); 173 174 /* 175 * Common functions for converting pci.fabric classes of 176 * ereports 177 */ 178 static int fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, 179 nvlist_t *erpt, fab_erpt_tbl_t *table); 180 static int fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, 181 nvlist_t *erpt, fab_erpt_tbl_t *table); 182 static int fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, 183 nvlist_t *erpt, fab_erpt_tbl_t *table); 184 static int fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, 185 nvlist_t *erpt, fab_erpt_tbl_t *table); 186 static int fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, 187 nvlist_t *erpt, fab_erpt_tbl_t *table); 188 static int fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, 189 nvlist_t *erpt, fab_erpt_tbl_t *table); 190 static int fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, 191 nvlist_t *erpt, fab_erpt_tbl_t *table); 192 static int fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, 193 nvlist_t *erpt, fab_erpt_tbl_t *table); 194 static void fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data); 195 static int fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, 196 nvlist_t *erpt, fab_erpt_tbl_t *table); 197 static void fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data); 198 static int fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, 199 nvlist_t *erpt, fab_erpt_tbl_t *table); 200 static int fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, 201 nvlist_t *erpt, fab_erpt_tbl_t *table); 202 203 /* Functions for converting fire specific error registers */ 204 static int fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 205 const char *class); 206 static int fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 207 const char *class); 208 static int fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 209 const char *class); 210 static int fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 211 const char *class); 212 213 /* Main functions for converting "fabric" ereports */ 214 static void fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data); 215 static void fab_xlate_fire_erpts(fmd_hdl_t *hdl, fab_data_t *data, 216 nvlist_t *nvl, const char *class); 217 218 /* 219 * Translation tables for converting "fabric" error bits into "pci" ereports. 220 * <Ereport Class Name>, <Error Bit Mask>, <Preparation Function> 221 */ 222 223 /* MACRO for table entries with no TGT ereports */ 224 #define NT(class, bit, prep) class, bit, prep, NULL 225 /* Translate Fabric ereports to ereport.io.pci.* */ 226 static fab_erpt_tbl_t fab_pci_erpt_tbl[] = { 227 PCI_DET_PERR, PCI_STAT_PERROR, NULL, 228 PCI_MDPE, PCI_STAT_S_PERROR, NULL, 229 PCI_SIG_SERR, PCI_STAT_S_SYSERR, NULL, 230 PCI_MA, PCI_STAT_R_MAST_AB, NULL, 231 PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL, 232 PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, 233 NULL, NULL, NULL 234 }; 235 236 /* Translate Fabric ereports to ereport.io.pci.sec-* */ 237 static fab_erpt_tbl_t fab_pci_bdg_erpt_tbl[] = { 238 PCI_DET_PERR, PCI_STAT_PERROR, NULL, 239 PCI_MDPE, PCI_STAT_S_PERROR, NULL, 240 PCI_REC_SERR, PCI_STAT_S_SYSERR, NULL, 241 #ifdef sparc 242 PCI_MA, PCI_STAT_R_MAST_AB, NULL, 243 #endif 244 PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL, 245 PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, 246 NULL, NULL, NULL, NULL, 247 }; 248 249 250 /* Translate Fabric ereports to ereport.io.pci.dto */ 251 static fab_erpt_tbl_t fab_pci_bdg_ctl_erpt_tbl[] = { 252 PCI_DTO, PCI_BCNF_BCNTRL_DTO_STAT, NULL, 253 NULL, NULL, NULL 254 }; 255 256 /* Translate Fabric ereports to ereport.io.pciex.* */ 257 static fab_erpt_tbl_t fab_pcie_ce_erpt_tbl[] = { 258 PCIEX_RE, PCIE_AER_CE_RECEIVER_ERR, NULL, 259 PCIEX_RNR, PCIE_AER_CE_REPLAY_ROLLOVER, NULL, 260 PCIEX_RTO, PCIE_AER_CE_REPLAY_TO, NULL, 261 PCIEX_BDP, PCIE_AER_CE_BAD_DLLP, NULL, 262 PCIEX_BTP, PCIE_AER_CE_BAD_TLP, NULL, 263 PCIEX_ANFE, PCIE_AER_CE_AD_NFE, NULL, 264 NULL, NULL, NULL 265 }; 266 267 /* Translate Fabric ereports to ereport.io.pciex.* */ 268 static fab_erpt_tbl_t fab_pcie_ue_erpt_tbl[] = { 269 PCIEX_TE, PCIE_AER_UCE_TRAINING, NULL, 270 PCIEX_DLP, PCIE_AER_UCE_DLP, NULL, 271 PCIEX_SD, PCIE_AER_UCE_SD, NULL, 272 PCIEX_ROF, PCIE_AER_UCE_RO, NULL, 273 PCIEX_FCP, PCIE_AER_UCE_FCP, NULL, 274 PCIEX_MFP, PCIE_AER_UCE_MTLP, NULL, 275 PCIEX_CTO, PCIE_AER_UCE_TO, PCI_TARG_MA, 276 PCIEX_UC, PCIE_AER_UCE_UC, NULL, 277 PCIEX_ECRC, PCIE_AER_UCE_ECRC, NULL, 278 PCIEX_CA, PCIE_AER_UCE_CA, PCI_TARG_REC_TA, 279 #ifdef sparc 280 PCIEX_UR, PCIE_AER_UCE_UR, PCI_TARG_MA, 281 #endif 282 PCIEX_POIS, PCIE_AER_UCE_PTLP, PCI_TARG_MDPE, 283 NULL, NULL, NULL 284 }; 285 286 /* Translate Fabric ereports to ereport.io.pciex.* */ 287 static fab_erpt_tbl_t fab_pcie_sue_erpt_tbl[] = { 288 PCIEX_S_TA_SC, PCIE_AER_SUCE_TA_ON_SC, PCI_TARG_REC_TA, 289 PCIEX_S_MA_SC, PCIE_AER_SUCE_MA_ON_SC, PCI_TARG_MA, 290 PCIEX_S_RTA, PCIE_AER_SUCE_RCVD_TA, PCI_TARG_REC_TA, 291 #ifdef sparc 292 PCIEX_S_RMA, PCIE_AER_SUCE_RCVD_MA, PCI_TARG_MA, 293 #endif 294 PCIEX_S_USC, PCIE_AER_SUCE_USC_ERR, NULL, 295 PCIEX_S_USCMD, PCIE_AER_SUCE_USC_MSG_DATA_ERR, PCI_TARG_REC_TA, 296 PCIEX_S_UDE, PCIE_AER_SUCE_UC_DATA_ERR, PCI_TARG_MDPE, 297 PCIEX_S_UAT, PCIE_AER_SUCE_UC_ATTR_ERR, PCI_TARG_MDPE, 298 PCIEX_S_UADR, PCIE_AER_SUCE_UC_ADDR_ERR, PCI_TARG_MDPE, 299 PCIEX_S_TEX, PCIE_AER_SUCE_TIMER_EXPIRED, NULL, 300 PCIEX_S_PERR, PCIE_AER_SUCE_PERR_ASSERT, PCI_TARG_MDPE, 301 PCIEX_S_SERR, PCIE_AER_SUCE_SERR_ASSERT, NULL, 302 PCIEX_INTERR, PCIE_AER_SUCE_INTERNAL_ERR, NULL, 303 NULL, NULL, NULL 304 }; 305 306 /* Translate Fabric ereports to ereport.io.pcix.* */ 307 static fab_erpt_tbl_t fab_pcix_erpt_tbl[] = { 308 PCIX_SPL_DIS, PCI_PCIX_SPL_DSCD, NULL, 309 PCIX_UNEX_SPL, PCI_PCIX_UNEX_SPL, NULL, 310 PCIX_RX_SPL_MSG, PCI_PCIX_RX_SPL_MSG, NULL, 311 NULL, NULL, NULL 312 }; 313 static fab_erpt_tbl_t *fab_pcix_bdg_erpt_tbl = fab_pcix_erpt_tbl; 314 315 /* Translate Fabric ereports to ereport.io.pcix.sec-* */ 316 static fab_erpt_tbl_t fab_pcix_bdg_sec_erpt_tbl[] = { 317 PCIX_SPL_DIS, PCI_PCIX_BSS_SPL_DSCD, NULL, 318 PCIX_UNEX_SPL, PCI_PCIX_BSS_UNEX_SPL, NULL, 319 PCIX_BSS_SPL_OR, PCI_PCIX_BSS_SPL_OR, NULL, 320 PCIX_BSS_SPL_DLY, PCI_PCIX_BSS_SPL_DLY, NULL, 321 NULL, NULL, NULL 322 }; 323 324 /* Translate Fabric ereports to ereport.io.pciex.* */ 325 static fab_erpt_tbl_t fab_pcie_nadv_erpt_tbl[] = { 326 #ifdef sparc 327 PCIEX_UR, PCIE_DEVSTS_UR_DETECTED, NULL, 328 #endif 329 PCIEX_FAT, PCIE_DEVSTS_FE_DETECTED, NULL, 330 PCIEX_NONFAT, PCIE_DEVSTS_NFE_DETECTED, NULL, 331 PCIEX_CORR, PCIE_DEVSTS_CE_DETECTED, NULL, 332 NULL, NULL, NULL 333 }; 334 335 /* Translate Fabric ereports to ereport.io.pciex.* */ 336 static fab_erpt_tbl_t fab_pcie_rc_erpt_tbl[] = { 337 PCIEX_RC_FE_MSG, PCIE_AER_RE_STS_FE_MSGS_RCVD, NULL, 338 PCIEX_RC_NFE_MSG, PCIE_AER_RE_STS_NFE_MSGS_RCVD, NULL, 339 PCIEX_RC_CE_MSG, PCIE_AER_RE_STS_CE_RCVD, NULL, 340 PCIEX_RC_MCE_MSG, PCIE_AER_RE_STS_MUL_CE_RCVD, NULL, 341 PCIEX_RC_MUE_MSG, PCIE_AER_RE_STS_MUL_FE_NFE_RCVD, NULL, 342 NULL, NULL, NULL 343 }; 344 345 /* 346 * Translate Fabric ereports to pseudo ereport.io.pciex.* RC Fabric Messages. 347 * If the RP is not a PCIe compliant RP or does not support AER, rely on the 348 * leaf fabric ereport to help create a xxx_MSG ereport coming from the RC. 349 */ 350 static fab_erpt_tbl_t fab_pcie_fake_rc_erpt_tbl[] = { 351 PCIEX_RC_FE_MSG, PCIE_DEVSTS_FE_DETECTED, NULL, 352 PCIEX_RC_NFE_MSG, PCIE_DEVSTS_NFE_DETECTED, NULL, 353 PCIEX_RC_CE_MSG, PCIE_DEVSTS_CE_DETECTED, NULL, 354 NULL, NULL, NULL, 355 }; 356 357 static fab_err_tbl_t *fab_master_err_tbl; 358 359 /* 360 * Translation tables for converting fire error bits into "pci" ereports. 361 * <Fire Bit> 362 * <pci ereport Class> 363 * <pci error status reg> 364 * <pci bridge status reg> 365 * <pci target class> 366 */ 367 #define FAB_FIRE_PEC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_PEC_ ## fb 368 #define FAB_FIRE_DMC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_DMC_ ## fb 369 #define FAB_N2_DMU_BIT(fb) "ereport.io.n2.dmu." fb 370 #define FAB_OB_PEC_BIT(fb) "ereport.io." PCIEX_OBERON "." FIRE_PEC_ ## fb 371 372 #define FAB_FIRE_UE(fb, bit, sts, bdg) \ 373 FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg 374 #define FAB_OB_UE(fb, bit, sts, bdg) \ 375 FAB_OB_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg 376 static fab_fire_tbl_t fab_fire_pec_ue_tbl[] = { 377 FAB_FIRE_UE(UR, UR, PCI_STAT_S_SYSERR, 0), 378 FAB_FIRE_UE(UC, UC, PCI_STAT_S_SYSERR, 0), 379 FAB_OB_UE(ECRC, ECRC, PCI_STAT_S_SYSERR, 0), 380 FAB_FIRE_UE(CTO, TO, PCI_STAT_S_SYSERR, 0), 381 FAB_FIRE_UE(ROF, RO, PCI_STAT_S_SYSERR, 0), 382 FAB_FIRE_UE(MFP, MTLP, PCI_STAT_S_SYSERR, 0), 383 FAB_FIRE_UE(PP, PTLP, PCI_STAT_S_PERROR, 384 (PCI_STAT_S_SYSERR | PCI_STAT_PERROR)), 385 FAB_FIRE_UE(FCP, FCP, PCI_STAT_S_SYSERR, 0), 386 FAB_FIRE_UE(DLP, DLP, PCI_STAT_S_SYSERR, 0), 387 FAB_FIRE_UE(TE, TRAINING, PCI_STAT_S_SYSERR, 0), 388 FAB_FIRE_UE(CA, CA, PCI_STAT_S_TARG_AB, 389 PCI_STAT_S_TARG_AB), 390 NULL, NULL, NULL, 391 }; 392 393 #define FAB_FIRE_CE(fb, bit) \ 394 FAB_FIRE_PEC_BIT(fb), PCIE_AER_CE_ ## bit, 0, 0 395 static fab_fire_tbl_t fab_fire_pec_ce_tbl[] = { 396 FAB_FIRE_CE(RTO, REPLAY_TO), 397 FAB_FIRE_CE(RNR, REPLAY_ROLLOVER), 398 FAB_FIRE_CE(BDP, BAD_DLLP), 399 FAB_FIRE_CE(BTP, BAD_TLP), 400 FAB_FIRE_CE(RE, RECEIVER_ERR), 401 NULL, NULL, NULL, 402 }; 403 404 /* 405 * WUC/RUC will need to be special cased for the target ereports, because you 406 * need to decode the tlp log. 407 */ 408 #define FAB_FIRE_WUCRUC(fb) \ 409 FAB_FIRE_PEC_BIT(fb), 0, 0, (PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR) 410 #define FAB_FIRE_OE(fb, bit) \ 411 FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0 412 #define FAB_OB_OE(fb, bit) \ 413 FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0 414 static fab_fire_tbl_t fab_fire_pec_oe_tbl[] = { 415 FAB_FIRE_WUCRUC(WUC), 416 FAB_FIRE_WUCRUC(RUC), 417 FAB_FIRE_OE(ERU, DLP), 418 FAB_FIRE_OE(ERO, DLP), 419 FAB_FIRE_OE(EMP, DLP), 420 FAB_FIRE_OE(EPE, DLP), 421 NULL, NULL, NULL, 422 }; 423 424 #define FAB_FIRE_DMC(fb) \ 425 FAB_FIRE_DMC_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB 426 #define FAB_N2_DMU(fb) \ 427 FAB_N2_DMU_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB 428 static fab_fire_tbl_t fab_fire_dmc_tbl[] = { 429 FAB_FIRE_DMC(BYP_ERR), 430 FAB_FIRE_DMC(BYP_OOR), 431 FAB_FIRE_DMC(TRN_OOR), 432 FAB_FIRE_DMC(TTE_INV), 433 FAB_FIRE_DMC(TTE_PRT), 434 FAB_N2_DMU("iotsbdesc_inv"), 435 FAB_N2_DMU("sun4v_adj_va_uf"), 436 FAB_N2_DMU("sun4v_inv_pg_sz"), 437 FAB_N2_DMU("sun4v_key_err"), 438 FAB_N2_DMU("sun4v_va_oor"), 439 NULL, NULL, NULL 440 }; 441 442 static fmd_xprt_t *fab_fmd_xprt = NULL; /* FMD transport layer handle */ 443 static char fab_buf[FM_MAX_CLASS]; 444 static boolean_t fab_xlate_fake_rp = B_TRUE; 445 446 #define HAS_PROP(node, name) xmlHasProp(node, (const xmlChar *)name) 447 #define GET_PROP(node, name) ((char *)xmlGetProp(node, (const xmlChar *)name)) 448 #define STRCMP(s1, s2) (strcmp((const char *)s1, (const char *)s2) == 0) 449 450 #define FAB_LOOKUP(sz, name, field) \ 451 (void) nvlist_lookup_uint ## sz(nvl, name, field) 452 /* ARGSUSED */ 453 static void 454 fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) { 455 data->nvl = nvl; 456 457 /* Generic PCI device information */ 458 FAB_LOOKUP(16, "bdf", &data->bdf); 459 FAB_LOOKUP(16, "device_id", &data->device_id); 460 FAB_LOOKUP(16, "vendor_id", &data->vendor_id); 461 FAB_LOOKUP(8, "rev_id", &data->rev_id); 462 FAB_LOOKUP(16, "dev_type", &data->dev_type); 463 FAB_LOOKUP(16, "pcie_off", &data->pcie_off); 464 FAB_LOOKUP(16, "pcix_off", &data->pcix_off); 465 FAB_LOOKUP(16, "aer_off", &data->aer_off); 466 FAB_LOOKUP(16, "ecc_ver", &data->ecc_ver); 467 468 /* Misc ereport information */ 469 FAB_LOOKUP(32, "remainder", &data->remainder); 470 FAB_LOOKUP(32, "severity", &data->severity); 471 472 /* PCI registers */ 473 FAB_LOOKUP(16, "pci_status", &data->pci_err_status); 474 FAB_LOOKUP(16, "pci_command", &data->pci_cfg_comm); 475 476 /* PCI bridge registers */ 477 FAB_LOOKUP(16, "pci_bdg_sec_status", &data->pci_bdg_sec_stat); 478 FAB_LOOKUP(16, "pci_bdg_ctrl", &data->pci_bdg_ctrl); 479 480 /* PCIx registers */ 481 FAB_LOOKUP(32, "pcix_status", &data->pcix_status); 482 FAB_LOOKUP(16, "pcix_command", &data->pcix_command); 483 484 /* PCIx ECC Registers */ 485 FAB_LOOKUP(16, "pcix_ecc_control_0", &data->pcix_ecc_control_0); 486 FAB_LOOKUP(16, "pcix_ecc_status_0", &data->pcix_ecc_status_0); 487 FAB_LOOKUP(32, "pcix_ecc_fst_addr_0", &data->pcix_ecc_fst_addr_0); 488 FAB_LOOKUP(32, "pcix_ecc_sec_addr_0", &data->pcix_ecc_sec_addr_0); 489 FAB_LOOKUP(32, "pcix_ecc_attr_0", &data->pcix_ecc_attr_0); 490 491 /* PCIx ECC Bridge Registers */ 492 FAB_LOOKUP(16, "pcix_ecc_control_1", &data->pcix_ecc_control_1); 493 FAB_LOOKUP(16, "pcix_ecc_status_1", &data->pcix_ecc_status_1); 494 FAB_LOOKUP(32, "pcix_ecc_fst_addr_1", &data->pcix_ecc_fst_addr_1); 495 FAB_LOOKUP(32, "pcix_ecc_sec_addr_1", &data->pcix_ecc_sec_addr_1); 496 FAB_LOOKUP(32, "pcix_ecc_attr_1", &data->pcix_ecc_attr_1); 497 498 /* PCIx Bridge */ 499 FAB_LOOKUP(32, "pcix_bdg_status", &data->pcix_bdg_stat); 500 FAB_LOOKUP(16, "pcix_bdg_sec_status", &data->pcix_bdg_sec_stat); 501 502 /* PCIe registers */ 503 FAB_LOOKUP(16, "pcie_status", &data->pcie_err_status); 504 FAB_LOOKUP(16, "pcie_command", &data->pcie_err_ctl); 505 FAB_LOOKUP(32, "pcie_dev_cap", &data->pcie_dev_cap); 506 507 /* PCIe AER registers */ 508 FAB_LOOKUP(32, "pcie_adv_ctl", &data->pcie_adv_ctl); 509 FAB_LOOKUP(32, "pcie_ue_status", &data->pcie_ue_status); 510 FAB_LOOKUP(32, "pcie_ue_mask", &data->pcie_ue_mask); 511 FAB_LOOKUP(32, "pcie_ue_sev", &data->pcie_ue_sev); 512 FAB_LOOKUP(32, "pcie_ue_hdr0", &data->pcie_ue_hdr[0]); 513 FAB_LOOKUP(32, "pcie_ue_hdr1", &data->pcie_ue_hdr[1]); 514 FAB_LOOKUP(32, "pcie_ue_hdr2", &data->pcie_ue_hdr[2]); 515 FAB_LOOKUP(32, "pcie_ue_hdr3", &data->pcie_ue_hdr[3]); 516 FAB_LOOKUP(32, "pcie_ce_status", &data->pcie_ce_status); 517 FAB_LOOKUP(32, "pcie_ce_mask", &data->pcie_ce_mask); 518 FAB_LOOKUP(32, "pcie_ue_tgt_trans", &data->pcie_ue_tgt_trans); 519 FAB_LOOKUP(64, "pcie_ue_tgt_addr", &data->pcie_ue_tgt_addr); 520 FAB_LOOKUP(16, "pcie_ue_tgt_bdf", &data->pcie_ue_tgt_bdf); 521 522 /* PCIe BDG AER registers */ 523 FAB_LOOKUP(32, "pcie_sue_adv_ctl", &data->pcie_sue_ctl); 524 FAB_LOOKUP(32, "pcie_sue_status", &data->pcie_sue_status); 525 FAB_LOOKUP(32, "pcie_sue_mask", &data->pcie_sue_mask); 526 FAB_LOOKUP(32, "pcie_sue_sev", &data->pcie_sue_sev); 527 FAB_LOOKUP(32, "pcie_sue_hdr0", &data->pcie_sue_hdr[0]); 528 FAB_LOOKUP(32, "pcie_sue_hdr1", &data->pcie_sue_hdr[1]); 529 FAB_LOOKUP(32, "pcie_sue_hdr2", &data->pcie_sue_hdr[2]); 530 FAB_LOOKUP(32, "pcie_sue_hdr3", &data->pcie_sue_hdr[3]); 531 FAB_LOOKUP(32, "pcie_sue_tgt_trans", &data->pcie_sue_tgt_trans); 532 FAB_LOOKUP(64, "pcie_sue_tgt_addr", &data->pcie_sue_tgt_addr); 533 FAB_LOOKUP(16, "pcie_sue_tgt_bdf", &data->pcie_sue_tgt_bdf); 534 535 /* PCIe RP registers */ 536 FAB_LOOKUP(32, "pcie_rp_status", &data->pcie_rp_status); 537 FAB_LOOKUP(16, "pcie_rp_control", &data->pcie_rp_ctl); 538 539 /* PCIe RP AER registers */ 540 FAB_LOOKUP(32, "pcie_adv_rp_status", &data->pcie_rp_err_status); 541 FAB_LOOKUP(32, "pcie_adv_rp_command", &data->pcie_rp_err_cmd); 542 FAB_LOOKUP(16, "pcie_adv_rp_ce_src_id", &data->pcie_rp_ce_src_id); 543 FAB_LOOKUP(16, "pcie_adv_rp_ue_src_id", &data->pcie_rp_ue_src_id); 544 545 /* 546 * If the system has a PCIe complaint RP with AER, turn off translating 547 * fake RP ereports. 548 */ 549 if (fab_xlate_fake_rp && 550 (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) && 551 data->aer_off) 552 fab_xlate_fake_rp = B_FALSE; 553 } 554 555 /* ARGSUSED */ 556 static void 557 fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) { 558 data->nvl = nvl; 559 560 /* Always Root Complex */ 561 data->dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT; 562 563 data->pcie_ue_sev = (PCIE_AER_UCE_DLP | PCIE_AER_UCE_SD | 564 PCIE_AER_UCE_FCP | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP); 565 } 566 567 /* ARGSUSED */ 568 static int 569 fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt, 570 boolean_t isRC) { 571 uint64_t *now; 572 uint64_t ena; 573 uint_t nelem; 574 nvlist_t *detector, *new_detector; 575 char rcpath[255]; 576 int err = 0; 577 578 /* Grab the tod, ena and detector(FMRI) */ 579 err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem); 580 err |= nvlist_lookup_uint64(nvl, "ena", &ena); 581 err |= nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector); 582 if (err) 583 return (err); 584 585 /* Make a copy of the detector */ 586 err = nvlist_dup(detector, &new_detector, NV_UNIQUE_NAME); 587 if (err) 588 return (err); 589 590 /* Copy the tod and ena to erpt */ 591 (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena); 592 (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem); 593 594 /* 595 * Create the correct ROOT FMRI from PCIe leaf fabric ereports. Used 596 * only by fab_prep_fake_rc_erpt. See the fab_pciex_fake_rc_erpt_tbl 597 * comments for more information. 598 */ 599 if (isRC && fab_get_rcpath(hdl, nvl, rcpath)) { 600 /* Create the correct PCIe RC new_detector aka FMRI */ 601 (void) nvlist_remove(new_detector, FM_FMRI_DEV_PATH, 602 DATA_TYPE_STRING); 603 (void) nvlist_add_string(new_detector, FM_FMRI_DEV_PATH, 604 rcpath); 605 } 606 607 /* Copy the FMRI to erpt */ 608 (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, new_detector); 609 610 nvlist_free(new_detector); 611 return (err); 612 } 613 614 static void 615 fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, const char *class, 616 boolean_t isPrimary) 617 { 618 nvlist_t *nvl = data->nvl; 619 nvlist_t *erpt; 620 char *fmri = NULL; 621 uint32_t tgt_trans; 622 uint64_t tgt_addr; 623 uint16_t tgt_bdf; 624 625 if (isPrimary) { 626 tgt_trans = data->pcie_ue_tgt_trans; 627 tgt_addr = data->pcie_ue_tgt_addr; 628 tgt_bdf = data->pcie_ue_tgt_bdf; 629 } else { 630 tgt_trans = data->pcie_sue_tgt_trans; 631 tgt_addr = data->pcie_sue_tgt_addr; 632 tgt_bdf = data->pcie_sue_tgt_bdf; 633 } 634 635 fmd_hdl_debug(hdl, "Sending Target Ereport: " 636 "type 0x%x addr 0x%llx fltbdf 0x%x\n", 637 tgt_trans, tgt_addr, tgt_bdf); 638 639 if (!tgt_trans) 640 return; 641 642 if ((tgt_trans == PF_ADDR_PIO) && tgt_addr) 643 fmri = fab_find_addr(hdl, nvl, tgt_addr); 644 else if ((tgt_trans == PF_ADDR_CFG) && tgt_bdf) 645 fmri = fab_find_bdf(hdl, nvl, tgt_bdf); 646 647 if (fmri) { 648 uint64_t *now; 649 uint64_t ena; 650 uint_t nelem; 651 nvlist_t *detector; 652 int err = 0; 653 654 /* Allocate space for new erpt */ 655 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 656 goto done; 657 658 /* Generate the target ereport class */ 659 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 660 PCI_ERROR_SUBCLASS, class); 661 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 662 663 /* Grab the tod, ena and detector(FMRI) */ 664 err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem); 665 err |= nvlist_lookup_uint64(nvl, "ena", &ena); 666 667 /* Copy the tod and ena to erpt */ 668 (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena); 669 (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem); 670 671 /* Create the correct FMRI */ 672 if (nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0) { 673 nvlist_free(erpt); 674 goto done; 675 } 676 (void) nvlist_add_string(detector, FM_VERSION, 677 FM_DEV_SCHEME_VERSION); 678 (void) nvlist_add_string(detector, FM_FMRI_SCHEME, 679 FM_FMRI_SCHEME_DEV); 680 (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, fmri); 681 (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, detector); 682 683 /* Add the address payload */ 684 (void) nvlist_add_uint64(erpt, PCI_PA, tgt_addr); 685 686 fmd_hdl_debug(hdl, "Sending target ereport: %s 0x%x\n", 687 fab_buf, tgt_addr); 688 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 689 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 690 goto done; 691 } else { 692 fmd_hdl_debug(hdl, "Cannot find Target FMRI addr:0x%llx", 693 tgt_addr); 694 } 695 696 return; 697 done: 698 fmd_hdl_debug(hdl, "Failed to send Target PCI ereport\n"); 699 } 700 701 static void 702 fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl) 703 { 704 fab_erpt_tbl_t *erpt_tbl, *entry; 705 nvlist_t *erpt; 706 uint32_t reg; 707 708 erpt_tbl = tbl->erpt_tbl; 709 if (tbl->reg_size == 16) { 710 reg = (uint32_t)*((uint16_t *) 711 ((uint32_t)data + tbl->reg_offset)); 712 } else { 713 reg = *((uint32_t *)((uint32_t)data + tbl->reg_offset)); 714 } 715 716 for (entry = erpt_tbl; entry->err_class; entry++) { 717 if (!(reg & entry->reg_bit)) 718 continue; 719 720 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 721 goto done; 722 if (tbl->fab_prep(hdl, data, erpt, entry) != 0) { 723 fmd_hdl_debug(hdl, "Prepping ereport failed\n"); 724 nvlist_free(erpt); 725 continue; 726 } 727 728 fmd_hdl_debug(hdl, "Sending ereport: %s 0x%x\n", fab_buf, reg); 729 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 730 if (fmd_xprt_error(hdl, fab_fmd_xprt)) { 731 fmd_hdl_debug(hdl, "Failed to send PCI ereport\n"); 732 return; 733 } 734 } 735 736 return; 737 done: 738 fmd_hdl_debug(hdl, "Failed to send PCI ereport\n"); 739 } 740 741 static int 742 fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 743 fab_erpt_tbl_t *tbl) 744 { 745 const char *class = tbl->err_class; 746 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 747 748 /* Generate an ereport for this error bit. */ 749 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 750 PCI_ERROR_SUBCLASS, class); 751 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 752 753 (void) nvlist_add_uint16(erpt, PCI_CONFIG_STATUS, data->pci_err_status); 754 (void) nvlist_add_uint16(erpt, PCI_CONFIG_COMMAND, data->pci_cfg_comm); 755 756 return (err); 757 } 758 759 static int 760 fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 761 fab_erpt_tbl_t *tbl) 762 { 763 const char *class = tbl->err_class; 764 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 765 766 /* Generate an ereport for this error bit. */ 767 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s-%s", 768 PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, class); 769 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 770 771 (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, 772 data->pci_bdg_sec_stat); 773 (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); 774 775 return (err); 776 } 777 778 static int 779 fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 780 fab_erpt_tbl_t *tbl) 781 { 782 const char *class = tbl->err_class; 783 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 784 785 /* Generate an ereport for this error bit. */ 786 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 787 PCI_ERROR_SUBCLASS, class); 788 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 789 790 (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, 791 data->pci_bdg_sec_stat); 792 (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); 793 794 return (err); 795 } 796 797 798 static int 799 fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 800 fab_erpt_tbl_t *tbl) 801 { 802 const char *class = tbl->err_class; 803 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 804 805 /* Generate an ereport for this error bit. */ 806 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 807 PCIEX_ERROR_SUBCLASS, class); 808 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 809 810 (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 811 (void) nvlist_add_uint32(erpt, PCIEX_CE_STATUS_REG, 812 data->pcie_ce_status); 813 814 return (err); 815 } 816 817 static int 818 fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 819 fab_erpt_tbl_t *tbl) 820 { 821 const char *class = tbl->err_class; 822 uint32_t first_err = 1 << (data->pcie_adv_ctl & 823 PCIE_AER_CTL_FST_ERR_PTR_MASK); 824 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 825 826 /* Generate an ereport for this error bit. */ 827 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 828 PCIEX_ERROR_SUBCLASS, class); 829 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 830 831 (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 832 (void) nvlist_add_uint32(erpt, PCIEX_UE_STATUS_REG, 833 data->pcie_ue_status); 834 (void) nvlist_add_uint32(erpt, PCIEX_UE_SEV_REG, data->pcie_ue_sev); 835 (void) nvlist_add_uint32(erpt, PCIEX_ADV_CTL, data->pcie_adv_ctl); 836 837 fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); 838 839 if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_bdf) { 840 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 841 data->pcie_ue_tgt_bdf); 842 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 843 } else { 844 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); 845 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); 846 } 847 848 if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_trans) { 849 if (tbl->tgt_class) 850 fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_TRUE); 851 } 852 853 return (err); 854 } 855 856 static int 857 fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 858 fab_erpt_tbl_t *tbl) 859 { 860 const char *class = tbl->err_class; 861 uint32_t first_err = 1 << (data->pcie_sue_ctl & 862 PCIE_AER_SCTL_FST_ERR_PTR_MASK); 863 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 864 865 /* Generate an ereport for this error bit. */ 866 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 867 PCIEX_ERROR_SUBCLASS, class); 868 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 869 870 (void) nvlist_add_uint32(erpt, PCIEX_SEC_UE_STATUS, 871 data->pcie_sue_status); 872 873 fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); 874 875 if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_bdf) { 876 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 877 data->pcie_sue_tgt_bdf); 878 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 879 } else { 880 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); 881 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); 882 } 883 884 if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_trans) { 885 if (tbl->tgt_class) 886 fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_FALSE); 887 } 888 889 return (err); 890 } 891 892 static int 893 fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 894 fab_erpt_tbl_t *tbl) 895 { 896 const char *class = tbl->err_class; 897 int err = 0; 898 899 /* Only send if this is not a bridge */ 900 if (!data->pcix_status || data->pcix_bdg_sec_stat) 901 return (1); 902 903 err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 904 905 /* Generate an ereport for this error bit. */ 906 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 907 PCIX_ERROR_SUBCLASS, class); 908 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 909 910 (void) nvlist_add_uint8(erpt, PCIX_COMMAND, data->pcix_command); 911 (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 912 913 return (err); 914 } 915 916 static void 917 fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) 918 { 919 nvlist_t *erpt; 920 int ecc_phase = (data->pcix_ecc_status_0 & PCI_PCIX_ECC_PHASE) >> 0x4; 921 int ecc_corr = data->pcix_ecc_status_0 & PCI_PCIX_ECC_CORR; 922 int sec_ue = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_UE; 923 int sec_ce = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_CE; 924 uint32_t ctlstat = (data->pcix_ecc_control_0 << 16) | 925 data->pcix_ecc_status_0; 926 927 switch (ecc_phase) { 928 case PCI_PCIX_ECC_PHASE_NOERR: 929 break; 930 case PCI_PCIX_ECC_PHASE_FADDR: 931 case PCI_PCIX_ECC_PHASE_SADDR: 932 (void) snprintf(fab_buf, FM_MAX_CLASS, 933 "%s.%s", PCIX_ERROR_SUBCLASS, 934 ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR); 935 break; 936 case PCI_PCIX_ECC_PHASE_ATTR: 937 (void) snprintf(fab_buf, FM_MAX_CLASS, 938 "%s.%s", PCIX_ERROR_SUBCLASS, 939 ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); 940 break; 941 case PCI_PCIX_ECC_PHASE_DATA32: 942 case PCI_PCIX_ECC_PHASE_DATA64: 943 (void) snprintf(fab_buf, FM_MAX_CLASS, 944 "%s.%s", PCIX_ERROR_SUBCLASS, 945 ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); 946 break; 947 } 948 949 if (ecc_phase) { 950 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 951 goto done; 952 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 953 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 954 (void) nvlist_add_uint16(erpt, PCIX_COMMAND, 955 data->pcix_command); 956 (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 957 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 958 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 959 data->pcix_ecc_attr_0); 960 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 961 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 962 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 963 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 964 } 965 966 if (sec_ce || sec_ue) { 967 (void) snprintf(fab_buf, FM_MAX_CLASS, 968 "%s.%s", PCIX_ERROR_SUBCLASS, 969 sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); 970 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 971 goto done; 972 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 973 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 974 (void) nvlist_add_uint16(erpt, PCIX_COMMAND, 975 data->pcix_command); 976 (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 977 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 978 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 979 data->pcix_ecc_attr_0); 980 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 981 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 982 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 983 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 984 } 985 986 return; 987 done: 988 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 989 } 990 991 static int 992 fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 993 fab_erpt_tbl_t *tbl) 994 { 995 const char *class = tbl->err_class; 996 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 997 998 /* Generate an ereport for this error bit. */ 999 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s%s", 1000 PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, class); 1001 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1002 1003 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 1004 data->pcix_bdg_sec_stat); 1005 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); 1006 1007 return (err); 1008 } 1009 1010 static int 1011 fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1012 fab_erpt_tbl_t *tbl) 1013 { 1014 const char *class = tbl->err_class; 1015 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1016 1017 /* Generate an ereport for this error bit. */ 1018 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 1019 PCIX_ERROR_SUBCLASS, class); 1020 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1021 1022 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 1023 data->pcix_bdg_sec_stat); 1024 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); 1025 1026 return (err); 1027 } 1028 1029 static void 1030 fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) 1031 { 1032 nvlist_t *erpt; 1033 int ecc_phase = (data->pcix_ecc_status_1 & PCI_PCIX_ECC_PHASE) >> 0x4; 1034 int ecc_corr = data->pcix_ecc_status_1 & PCI_PCIX_ECC_CORR; 1035 int sec_ue = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_UE; 1036 int sec_ce = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_CE; 1037 uint32_t ctlstat = (data->pcix_ecc_control_1 << 16) | 1038 data->pcix_ecc_status_1; 1039 1040 switch (ecc_phase) { 1041 case PCI_PCIX_ECC_PHASE_NOERR: 1042 break; 1043 case PCI_PCIX_ECC_PHASE_FADDR: 1044 case PCI_PCIX_ECC_PHASE_SADDR: 1045 (void) snprintf(fab_buf, FM_MAX_CLASS, 1046 "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 1047 ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR); 1048 break; 1049 case PCI_PCIX_ECC_PHASE_ATTR: 1050 (void) snprintf(fab_buf, FM_MAX_CLASS, 1051 "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 1052 ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); 1053 break; 1054 case PCI_PCIX_ECC_PHASE_DATA32: 1055 case PCI_PCIX_ECC_PHASE_DATA64: 1056 (void) snprintf(fab_buf, FM_MAX_CLASS, 1057 "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 1058 ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); 1059 break; 1060 } 1061 if (ecc_phase) { 1062 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 1063 goto done; 1064 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1065 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1066 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 1067 data->pcix_bdg_sec_stat); 1068 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, 1069 data->pcix_bdg_stat); 1070 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 1071 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 1072 data->pcix_ecc_attr_1); 1073 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 1074 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 1075 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 1076 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 1077 } 1078 1079 if (sec_ce || sec_ue) { 1080 (void) snprintf(fab_buf, FM_MAX_CLASS, 1081 "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 1082 sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); 1083 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 1084 goto done; 1085 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1086 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1087 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 1088 data->pcix_bdg_sec_stat); 1089 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, 1090 data->pcix_bdg_stat); 1091 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 1092 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 1093 data->pcix_ecc_attr_1); 1094 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 1095 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 1096 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 1097 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 1098 } 1099 return; 1100 done: 1101 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 1102 } 1103 1104 static int 1105 fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1106 fab_erpt_tbl_t *tbl) 1107 { 1108 const char *class = tbl->err_class; 1109 int err = 0; 1110 1111 /* Don't send this for PCI device, Root Ports, or PCIe with AER */ 1112 if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || 1113 (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || 1114 data->aer_off) 1115 return (1); 1116 1117 err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1118 1119 /* Generate an ereport for this error bit. */ 1120 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 1121 PCIEX_ERROR_SUBCLASS, class); 1122 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1123 1124 (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 1125 1126 return (err); 1127 } 1128 1129 static int 1130 fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1131 fab_erpt_tbl_t *tbl) 1132 { 1133 const char *class = tbl->err_class; 1134 uint32_t status = data->pcie_rp_err_status; 1135 int err = 0; 1136 int isFE = 0, isNFE = 0; 1137 1138 fmd_hdl_debug(hdl, "XLATE RP Error Class %s", class); 1139 1140 if (!data->aer_off) 1141 return (-1); 1142 1143 /* Only send a FE Msg if the 1st UE error is FE */ 1144 if (STRCMP(class, PCIEX_RC_FE_MSG)) 1145 if (!(status & PCIE_AER_RE_STS_FIRST_UC_FATAL)) 1146 return (-1); 1147 else 1148 isFE = 1; 1149 1150 /* Only send a NFE Msg is the 1st UE error is NFE */ 1151 if (STRCMP(class, PCIEX_RC_NFE_MSG)) 1152 if (status & PCIE_AER_RE_STS_FIRST_UC_FATAL) 1153 return (-1); 1154 else 1155 isNFE = 1; 1156 1157 fmd_hdl_debug(hdl, "XLATE RP Error"); 1158 1159 err |= fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1160 1161 /* Generate an ereport for this error bit. */ 1162 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 1163 PCIEX_ERROR_SUBCLASS, class); 1164 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1165 1166 (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, status); 1167 if ((isFE || isNFE) && data->pcie_rp_ue_src_id) { 1168 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 1169 data->pcie_rp_ue_src_id); 1170 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 1171 } 1172 if (STRCMP(class, PCIEX_RC_CE_MSG) && data->pcie_rp_ce_src_id) { 1173 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 1174 data->pcie_rp_ce_src_id); 1175 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 1176 } 1177 1178 return (err); 1179 } 1180 1181 static int 1182 fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1183 fab_erpt_tbl_t *tbl) 1184 { 1185 const char *class = tbl->err_class; 1186 uint32_t rc_err_sts = 0; 1187 int err = 0; 1188 1189 /* 1190 * Don't send this for PCI device or Root Ports. Only send it on 1191 * systems with non-compliant RPs. 1192 */ 1193 if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || 1194 (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || 1195 (!fab_xlate_fake_rp)) 1196 return (-1); 1197 1198 err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_TRUE); 1199 1200 /* Generate an ereport for this error bit. */ 1201 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 1202 PCIEX_ERROR_SUBCLASS, class); 1203 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1204 1205 /* Send PCIe RC Ereports */ 1206 if (data->pcie_err_status & PCIE_DEVSTS_CE_DETECTED) { 1207 rc_err_sts |= PCIE_AER_RE_STS_CE_RCVD; 1208 } 1209 1210 /* NFE/FE src id takes precedence over CE src id */ 1211 if (data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) { 1212 rc_err_sts |= PCIE_AER_RE_STS_NFE_MSGS_RCVD; 1213 rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; 1214 } 1215 if (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED) { 1216 rc_err_sts |= PCIE_AER_RE_STS_FE_MSGS_RCVD; 1217 rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; 1218 } 1219 if ((data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) && 1220 (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED)) { 1221 rc_err_sts |= PCIE_AER_RE_STS_FIRST_UC_FATAL; 1222 rc_err_sts |= PCIE_AER_RE_STS_MUL_FE_NFE_RCVD; 1223 } 1224 1225 (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, rc_err_sts); 1226 1227 if (!(rc_err_sts & PCIE_AER_RE_STS_MUL_FE_NFE_RCVD)) { 1228 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, data->bdf); 1229 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 1230 } 1231 1232 return (err); 1233 } 1234 1235 static int 1236 fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1237 const char *class) 1238 { 1239 fab_fire_tbl_t *entry; 1240 uint64_t reg; 1241 1242 for (entry = fab_fire_pec_ce_tbl; entry->err_class; entry++) { 1243 if (STRCMP(class, entry->err_class)) 1244 goto send; 1245 } 1246 1247 return (0); 1248 1249 send: 1250 fmd_hdl_debug(hdl, "Translate Fire CE %s\n", class); 1251 1252 /* Fill in the device status register */ 1253 data->pcie_err_status = PCIE_DEVSTS_CE_DETECTED; 1254 1255 /* Fill in the AER CE register */ 1256 if (nvlist_lookup_uint64(erpt, "tlu-cess", ®) == 0) { 1257 data->pcie_ce_status = (uint32_t)reg | (uint32_t)(reg >> 32); 1258 } 1259 1260 return (1); 1261 } 1262 1263 static int 1264 fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1265 const char *class) 1266 { 1267 fab_fire_tbl_t *entry; 1268 uint64_t reg; 1269 uint32_t temp; 1270 pcie_tlp_hdr_t *hdr; 1271 1272 for (entry = fab_fire_pec_ue_tbl; entry->err_class; entry++) { 1273 if (STRCMP(class, entry->err_class)) 1274 goto send; 1275 } 1276 1277 return (0); 1278 1279 send: 1280 fmd_hdl_debug(hdl, "Translate Fire UE %s\n", class); 1281 1282 /* Fill in PCI Status Register */ 1283 data->pci_err_status = entry->pci_err_sts; 1284 data->pci_bdg_sec_stat = entry->pci_bdg_sts; 1285 1286 /* Fill in the device status register */ 1287 if (entry->fire_bit & data->pcie_ue_sev) 1288 data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; 1289 else 1290 data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; 1291 1292 if (entry->fire_bit == PCIE_AER_UCE_UR) 1293 data->pcie_err_status |= PCIE_DEVSTS_UR_DETECTED; 1294 1295 /* Fill in the AER UE register */ 1296 if (nvlist_lookup_uint64(erpt, "tlu-uess", ®) == 0) { 1297 data->pcie_ue_status = (uint32_t)reg | (uint32_t)(reg >> 32); 1298 } 1299 1300 /* Fill in the AER Control register */ 1301 if ((reg & (uint64_t)entry->fire_bit) && 1302 nvlist_lookup_boolean(erpt, "primary")) { 1303 temp = entry->fire_bit; 1304 for (data->pcie_adv_ctl = (uint32_t)-1; temp; 1305 data->pcie_adv_ctl++) 1306 temp = temp >> 1; 1307 } 1308 1309 /* If CTO create target information */ 1310 if (entry->fire_bit == PCIE_AER_UCE_TO && 1311 nvlist_lookup_boolean(erpt, "primary")) { 1312 if (nvlist_lookup_uint64(erpt, "tlu-tueh1l", ®) == 0) { 1313 data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); 1314 data->pcie_ue_hdr[1] = (uint32_t)(reg); 1315 } 1316 if (nvlist_lookup_uint64(erpt, "tlu-tueh2l", ®) == 0) { 1317 data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); 1318 data->pcie_ue_hdr[3] = (uint32_t)(reg); 1319 } 1320 1321 hdr = (pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]); 1322 switch (hdr->type) { 1323 case PCIE_TLP_TYPE_IO: 1324 case PCIE_TLP_TYPE_MEM: 1325 case PCIE_TLP_TYPE_MEMLK: 1326 data->pcie_ue_tgt_trans = PF_ADDR_PIO; 1327 if (hdr->fmt & 0x1) { 1328 data->pcie_ue_tgt_addr = reg; 1329 } else { 1330 data->pcie_ue_tgt_addr = data->pcie_ue_hdr[2]; 1331 } 1332 break; 1333 case PCIE_TLP_TYPE_CFG0: 1334 case PCIE_TLP_TYPE_CFG1: 1335 data->pcie_ue_tgt_trans = PF_ADDR_CFG; 1336 data->pcie_ue_tgt_bdf = data->pcie_ue_hdr[2] >> 16; 1337 break; 1338 } 1339 } 1340 1341 /* Fill in the AER Header registers */ 1342 if (nvlist_lookup_uint64(erpt, "tlu-rueh1l", ®) == 0) { 1343 data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); 1344 data->pcie_ue_hdr[1] = (uint32_t)(reg); 1345 } 1346 if (nvlist_lookup_uint64(erpt, "tlu-rueh2l", ®) == 0) { 1347 data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); 1348 data->pcie_ue_hdr[3] = (uint32_t)(reg); 1349 } 1350 1351 return (1); 1352 } 1353 1354 static int 1355 fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1356 const char *class) 1357 { 1358 fab_fire_tbl_t *entry; 1359 uint64_t reg; 1360 1361 for (entry = fab_fire_pec_oe_tbl; entry->err_class; entry++) { 1362 if (STRCMP(class, entry->err_class)) 1363 goto send; 1364 } 1365 1366 return (0); 1367 1368 send: 1369 fmd_hdl_debug(hdl, "Translate Fire OE %s\n", class); 1370 1371 /* Fill in PCI Status Register */ 1372 if (entry->fire_bit) { 1373 data->pci_err_status = entry->pci_err_sts; 1374 data->pci_bdg_sec_stat = entry->pci_bdg_sts; 1375 } else { 1376 if (nvlist_lookup_uint64(erpt, "tlu-roeeh1l", ®) == 0) { 1377 data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); 1378 data->pcie_ue_hdr[1] = (uint32_t)(reg); 1379 } 1380 if (nvlist_lookup_uint64(erpt, "tlu-roeeh2l", ®) == 0) { 1381 data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); 1382 data->pcie_ue_hdr[3] = (uint32_t)(reg); 1383 } 1384 1385 if (((pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]))->type == 1386 PCIE_TLP_TYPE_CPL) { 1387 pcie_cpl_t *cpl = (pcie_cpl_t *)&data->pcie_ue_hdr[1]; 1388 switch (cpl->status) { 1389 case PCIE_CPL_STS_UR: 1390 data->pci_err_status = 0; 1391 data->pci_bdg_sec_stat = PCI_STAT_R_MAST_AB | 1392 PCI_STAT_S_SYSERR; 1393 break; 1394 case PCIE_CPL_STS_CA: 1395 data->pci_err_status = 0; 1396 data->pci_bdg_sec_stat = PCI_STAT_R_TARG_AB | 1397 PCI_STAT_S_SYSERR; 1398 break; 1399 } 1400 } 1401 } 1402 1403 /* Fill in the device status register */ 1404 if (entry->fire_bit & data->pcie_ue_sev) 1405 data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; 1406 else 1407 data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; 1408 1409 /* Fill in the AER UE register */ 1410 data->pcie_ue_status = entry->fire_bit; 1411 1412 return (1); 1413 } 1414 1415 static int 1416 fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1417 const char *class) 1418 { 1419 fab_fire_tbl_t *entry; 1420 uint64_t reg; 1421 uint32_t temp; 1422 1423 for (entry = fab_fire_dmc_tbl; entry->err_class; entry++) { 1424 fmd_hdl_debug(hdl, "Matching %s\n", entry->err_class); 1425 if (STRCMP(class, entry->err_class) && 1426 nvlist_lookup_boolean(erpt, "primary")) 1427 goto send; 1428 } 1429 1430 return (0); 1431 1432 send: 1433 fmd_hdl_debug(hdl, "Translate Fire DMC %s\n", class); 1434 1435 /* Fill in PCI Status Register */ 1436 data->pci_err_status = entry->pci_err_sts; 1437 data->pci_bdg_sec_stat = entry->pci_bdg_sts; 1438 1439 /* Fill in the device status register */ 1440 data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; 1441 1442 /* Fill in the AER UE register */ 1443 data->pcie_ue_status = entry->fire_bit; 1444 1445 /* Fill in the AER Control register */ 1446 temp = entry->fire_bit; 1447 for (data->pcie_adv_ctl = (uint32_t)-1; temp; data->pcie_adv_ctl++) 1448 temp = temp >> 1; 1449 1450 /* Fill in the AER Header registers */ 1451 if (nvlist_lookup_uint64(erpt, "mmu-tfsr", ®) == 0) { 1452 fmd_hdl_debug(hdl, "tfsr 0x%llx\n", reg); 1453 /* Get the trans type */ 1454 temp = (reg & 0x3F0000) >> 16; 1455 data->pcie_ue_hdr[0] = (uint32_t)(temp << 24); 1456 data->pcie_ue_tgt_trans = PF_ADDR_DMA; 1457 /* Get the req id */ 1458 temp = (reg & 0xFFFF); 1459 data->pcie_ue_hdr[1] = (uint32_t)(temp << 16); 1460 data->pcie_ue_tgt_bdf = temp; 1461 } 1462 1463 if (nvlist_lookup_uint64(erpt, "mmu-tfar", ®) == 0) { 1464 fmd_hdl_debug(hdl, "tfar 0x%llx\n", reg); 1465 /* Get the address */ 1466 data->pcie_ue_hdr[2] = reg; 1467 data->pcie_ue_hdr[3] = 0; 1468 data->pcie_ue_tgt_addr = reg; 1469 } 1470 1471 fmd_hdl_debug(hdl, "HEADER 0 0x%x\n", data->pcie_ue_hdr[0]); 1472 fmd_hdl_debug(hdl, "HEADER 1 0x%x\n", data->pcie_ue_hdr[1]); 1473 fmd_hdl_debug(hdl, "HEADER 2 0x%x\n", data->pcie_ue_hdr[2]); 1474 fmd_hdl_debug(hdl, "HEADER 3 0x%x\n", data->pcie_ue_hdr[3]); 1475 1476 return (1); 1477 } 1478 1479 static void 1480 fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data) 1481 { 1482 fab_err_tbl_t *tbl; 1483 1484 fmd_hdl_debug(hdl, "Sending Ereports Now"); 1485 1486 /* Go through the error logs and send the relavant reports */ 1487 for (tbl = fab_master_err_tbl; tbl->erpt_tbl; tbl++) { 1488 fab_send_erpt(hdl, data, tbl); 1489 } 1490 1491 /* Send PCI-X ECC Ereports */ 1492 fab_send_pcix_ecc_erpt(hdl, data); 1493 fab_send_pcix_bdg_ecc_erpt(hdl, data); 1494 } 1495 1496 static void 1497 fab_xlate_fire_erpts(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *nvl, 1498 const char *class) 1499 { 1500 if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.pec.*")) { 1501 if (fab_xlate_fire_ce(hdl, data, nvl, class)) 1502 return; 1503 1504 if (fab_xlate_fire_ue(hdl, data, nvl, class)) 1505 return; 1506 1507 if (fab_xlate_fire_oe(hdl, data, nvl, class)) 1508 return; 1509 } else if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.dmc.*") || 1510 fmd_nvl_class_match(hdl, nvl, "ereport.io.n2.dmu.*")) { 1511 if (fab_xlate_fire_dmc(hdl, data, nvl, class)) 1512 return; 1513 } 1514 } 1515 1516 static void 1517 fab_update_topo(fmd_hdl_t *hdl) 1518 { 1519 topo_hdl_t *thp = NULL; 1520 FILE *fp; 1521 int err = 0; 1522 1523 if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL) { 1524 fmd_hdl_debug(hdl, "Failed to hold topo\n"); 1525 } 1526 1527 fp = fopen(XMLTOPOFILE, "w"); 1528 1529 if (topo_xml_print(thp, fp, FM_FMRI_SCHEME_HC, &err) < 0) { 1530 fmd_hdl_debug(hdl, "Failed to get XML topo\n"); 1531 } 1532 1533 (void) fclose(fp); 1534 1535 fmd_hdl_topo_rele(hdl, thp); 1536 1537 if (fab_xpathCtx) 1538 xmlXPathFreeContext(fab_xpathCtx); 1539 if (fab_doc) 1540 xmlFreeDoc(fab_doc); 1541 1542 /* Load xml document */ 1543 fab_doc = xmlParseFile(XMLTOPOFILE); 1544 1545 /* Init xpath */ 1546 fab_xpathCtx = xmlXPathNewContext(fab_doc); 1547 1548 fab_valid_topo = 1; 1549 } 1550 1551 #define FAB_HC2DEV_QUERY_SIZE_MIN 160 1552 #define FAB_HC2DEV_QUERY_SIZE(sz) \ 1553 ((sz + FAB_HC2DEV_QUERY_SIZE_MIN) * sizeof (char)) 1554 1555 static boolean_t 1556 fab_hc2dev(fmd_hdl_t *hdl, nvlist_t *detector, char **dev_path, 1557 uint_t *dev_path_size) { 1558 xmlXPathObjectPtr xpathObj; 1559 xmlNodeSetPtr nodes; 1560 char *query, *query_end, *temp; 1561 uint_t i, size; 1562 size_t query_size = 0; 1563 nvlist_t **hcl; 1564 1565 if (nvlist_lookup_nvlist_array(detector, FM_FMRI_HC_LIST, &hcl, 1566 &size) != 0) 1567 goto fail; 1568 1569 for (i = 0; i < size; i++) { 1570 if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &temp) != 0) 1571 goto fail; 1572 query_size += strlen(temp); 1573 if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &temp) != 0) 1574 goto fail; 1575 query_size += strlen(temp); 1576 /* Adjust for '=' and '/' later */ 1577 query_size += 2; 1578 } 1579 1580 query = fmd_hdl_alloc(hdl, FAB_HC2DEV_QUERY_SIZE(query_size), 1581 FMD_SLEEP); 1582 (void) sprintf(query, "//propval[@name='resource' and " 1583 "contains(substring(@value, string-length(@value) - %d), '", 1584 query_size); 1585 1586 query_end = query; 1587 query_end += strlen(query); 1588 1589 for (i = 0; i < size; i++) { 1590 (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &temp); 1591 (void) snprintf(query_end, query_size, "%s=", temp); 1592 query_end += strlen(temp) + 1; 1593 (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &temp); 1594 (void) snprintf(query_end, query_size, "%s", temp); 1595 query_end += strlen(temp); 1596 if (i != (size - 1)) { 1597 (void) sprintf(query_end++, "/"); 1598 } 1599 } 1600 1601 (void) sprintf(query_end, "')]/parent::*/following-sibling::*/" 1602 "propval[@name='dev']/@value"); 1603 1604 fmd_hdl_debug(hdl, "xpathObj query %s\n", query); 1605 1606 xpathObj = xmlXPathEvalExpression((const xmlChar *)query, 1607 fab_xpathCtx); 1608 fmd_hdl_free(hdl, query, FAB_HC2DEV_QUERY_SIZE(query_size)); 1609 1610 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, 1611 xpathObj->type); 1612 nodes = xpathObj->nodesetval; 1613 1614 if (nodes) { 1615 temp = (char *)xmlNodeGetContent(nodes->nodeTab[0]); 1616 fmd_hdl_debug(hdl, "HC Dev Path: %s\n", temp); 1617 *dev_path_size = strlen(temp) + 1; 1618 *dev_path = fmd_hdl_alloc(hdl, *dev_path_size, FMD_SLEEP); 1619 (void) strcpy(*dev_path, 1620 (char *)xmlNodeGetContent(nodes->nodeTab[0])); 1621 return (B_TRUE); 1622 } 1623 fail: 1624 return (B_FALSE); 1625 } 1626 1627 /* ARGSUSED */ 1628 static boolean_t 1629 fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath) { 1630 nvlist_t *detector; 1631 char *path, *scheme; 1632 uint_t size; 1633 1634 if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0) 1635 goto fail; 1636 if (nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0) 1637 goto fail; 1638 1639 if (STRCMP(scheme, FM_FMRI_SCHEME_DEV)) { 1640 if (nvlist_lookup_string(detector, FM_FMRI_DEV_PATH, 1641 &path) != 0) 1642 goto fail; 1643 (void) strncpy(rcpath, path, FM_MAX_CLASS); 1644 } else if (STRCMP(scheme, FM_FMRI_SCHEME_HC)) { 1645 /* 1646 * This should only occur for ereports that come from the RC 1647 * itself. In this case convert HC scheme to dev path. 1648 */ 1649 if (fab_hc2dev(hdl, detector, &path, &size)) { 1650 (void) strncpy(rcpath, path, FM_MAX_CLASS); 1651 fmd_hdl_free(hdl, path, size); 1652 } else { 1653 goto fail; 1654 } 1655 } else { 1656 return (B_FALSE); 1657 } 1658 1659 /* 1660 * Extract the RC path by taking the first device in the dev path 1661 * 1662 * /pci@0,0/pci8086,3605@2/pci8086,3500@0/pci8086,3514@1/pci8086,105e@0 1663 * - to - 1664 * /pci@0,0 1665 */ 1666 path = strchr(rcpath + 1, '/'); 1667 if (path) 1668 path[0] = '\0'; 1669 1670 return (B_TRUE); 1671 fail: 1672 return (B_FALSE); 1673 } 1674 1675 static char * 1676 fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf) { 1677 xmlXPathObjectPtr xpathObj; 1678 xmlNodeSetPtr nodes; 1679 char query[500]; 1680 int bus, dev, fn; 1681 char rcpath[255]; 1682 1683 if (bdf != (uint16_t)-1) { 1684 bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT; 1685 dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT; 1686 fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT; 1687 } 1688 1689 if (!fab_get_rcpath(hdl, nvl, rcpath)) 1690 goto fail; 1691 1692 /* 1693 * Explanation of the XSL XPATH Query 1694 * Line 1: Look at all nodes with the node name "propval" 1695 * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF 1696 * Line 4-5: See if the "value" of the node ends with correct PCI BDF 1697 * Line 6: Go up one level to the parent of the current node 1698 * Line 7: See if child node contains "ASRU" with the same PCIe Root 1699 * Line 8: Traverse up the parent and the other siblings and look for 1700 * the io "propgroup" and get the value of the dev "propval" 1701 */ 1702 (void) snprintf(query, sizeof (query), "//propval[" 1703 "contains(substring(@value, string-length(@value) - 34), " 1704 "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or " 1705 "contains(substring(@value, string-length(@value) - 28), " 1706 "'pcibus=%d/pcidev=%d/pcifn=%d')" 1707 "]/parent::" 1708 "*/propval[@name='ASRU' and contains(@value, '%s')]" 1709 "/parent::*/following-sibling::*[@name='io']/propval[@name='dev']/" 1710 "@value", bus, dev, fn, bus, dev, fn, rcpath); 1711 1712 fmd_hdl_debug(hdl, "xpathObj query %s\n", query); 1713 1714 xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx); 1715 1716 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type); 1717 1718 nodes = xpathObj->nodesetval; 1719 if (nodes) { 1720 fmd_hdl_debug(hdl, "BDF Dev Path: %s\n", 1721 xmlNodeGetContent(nodes->nodeTab[0])); 1722 return ((char *)xmlNodeGetContent(nodes->nodeTab[0])); 1723 } 1724 fail: 1725 return (NULL); 1726 } 1727 1728 static char * 1729 fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr) { 1730 xmlXPathObjectPtr xpathObj; 1731 xmlNodeSetPtr nodes; 1732 xmlNodePtr devNode; 1733 char query[500]; 1734 int size, i, j; 1735 uint32_t prop[50]; 1736 char *token; 1737 pci_regspec_t *assign_p; 1738 uint64_t low, hi; 1739 char rcpath[255]; 1740 1741 if (!fab_get_rcpath(hdl, nvl, rcpath)) 1742 goto fail; 1743 1744 (void) snprintf(query, sizeof (query), "//propval[" 1745 "@name='ASRU' and contains(@value, '%s')]/" 1746 "parent::*/following-sibling::*[@name='pci']/" 1747 "propval[@name='assigned-addresses']", rcpath); 1748 1749 fmd_hdl_debug(hdl, "xpathObj query %s\n", query); 1750 1751 xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx); 1752 1753 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type); 1754 1755 nodes = xpathObj->nodesetval; 1756 size = (nodes) ? nodes->nodeNr : 0; 1757 1758 /* Decode the list of assigned addresses xml nodes for each device */ 1759 for (i = 0; i < size; i++) { 1760 devNode = nodes->nodeTab[i]; 1761 if (!HAS_PROP(devNode, "value")) 1762 continue; 1763 1764 /* Convert "string" assigned-addresses to pci_regspec_t */ 1765 j = 0; 1766 for (token = strtok(GET_PROP(devNode, "value"), " "); token; 1767 token = strtok(NULL, " ")) { 1768 prop[j++] = strtoul(token, (char **)NULL, 16); 1769 } 1770 prop[j] = (uint32_t)-1; 1771 1772 /* Check if address belongs to this device */ 1773 for (assign_p = (pci_regspec_t *)prop; 1774 assign_p->pci_phys_hi != (uint_t)-1; assign_p++) { 1775 low = assign_p->pci_phys_low; 1776 hi = low + assign_p->pci_size_low; 1777 if ((addr < hi) && (addr >= low)) { 1778 fmd_hdl_debug(hdl, "Found Address\n"); 1779 goto found; 1780 } 1781 } 1782 } 1783 goto fail; 1784 1785 found: 1786 /* Traverse up the xml tree and back down to find the right propgroup */ 1787 for (devNode = devNode->parent->parent->children; 1788 devNode; devNode = devNode->next) { 1789 if (STRCMP(devNode->name, "propgroup") && 1790 STRCMP(GET_PROP(devNode, "name"), "io")) 1791 goto propgroup; 1792 } 1793 goto fail; 1794 1795 propgroup: 1796 /* Retrive the "dev" propval and return */ 1797 for (devNode = devNode->children; devNode; devNode = devNode->next) { 1798 if (STRCMP(devNode->name, "propval") && 1799 STRCMP(GET_PROP(devNode, "name"), "dev")) { 1800 fmd_hdl_debug(hdl, "Addr Dev Path: %s\n", 1801 GET_PROP(devNode, "value")); 1802 return (GET_PROP(devNode, "value")); 1803 } 1804 } 1805 fail: 1806 return (NULL); 1807 } 1808 1809 static void 1810 fab_pr(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl) { 1811 nvpair_t *nvp; 1812 1813 for (nvp = nvlist_next_nvpair(nvl, NULL); 1814 nvp != NULL; 1815 nvp = nvlist_next_nvpair(nvl, nvp)) { 1816 1817 data_type_t type = nvpair_type(nvp); 1818 const char *name = nvpair_name(nvp); 1819 1820 boolean_t b; 1821 uint8_t i8; 1822 uint16_t i16; 1823 uint32_t i32; 1824 uint64_t i64; 1825 char *str; 1826 nvlist_t *cnv; 1827 1828 nvlist_t **nvlarr; 1829 uint_t arrsize; 1830 int arri; 1831 1832 1833 if (STRCMP(name, FM_CLASS)) 1834 continue; /* already printed by caller */ 1835 1836 fmd_hdl_debug(hdl, " %s=", name); 1837 1838 switch (type) { 1839 case DATA_TYPE_BOOLEAN: 1840 fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN 1"); 1841 break; 1842 1843 case DATA_TYPE_BOOLEAN_VALUE: 1844 (void) nvpair_value_boolean_value(nvp, &b); 1845 fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN_VALUE %d", 1846 b ? "1" : "0"); 1847 break; 1848 1849 case DATA_TYPE_BYTE: 1850 (void) nvpair_value_byte(nvp, &i8); 1851 fmd_hdl_debug(hdl, "DATA_TYPE_BYTE 0x%x", i8); 1852 break; 1853 1854 case DATA_TYPE_INT8: 1855 (void) nvpair_value_int8(nvp, (void *)&i8); 1856 fmd_hdl_debug(hdl, "DATA_TYPE_INT8 0x%x", i8); 1857 break; 1858 1859 case DATA_TYPE_UINT8: 1860 (void) nvpair_value_uint8(nvp, &i8); 1861 fmd_hdl_debug(hdl, "DATA_TYPE_UINT8 0x%x", i8); 1862 break; 1863 1864 case DATA_TYPE_INT16: 1865 (void) nvpair_value_int16(nvp, (void *)&i16); 1866 fmd_hdl_debug(hdl, "DATA_TYPE_INT16 0x%x", i16); 1867 break; 1868 1869 case DATA_TYPE_UINT16: 1870 (void) nvpair_value_uint16(nvp, &i16); 1871 fmd_hdl_debug(hdl, "DATA_TYPE_UINT16 0x%x", i16); 1872 break; 1873 1874 case DATA_TYPE_INT32: 1875 (void) nvpair_value_int32(nvp, (void *)&i32); 1876 fmd_hdl_debug(hdl, "DATA_TYPE_INT32 0x%x", i32); 1877 break; 1878 1879 case DATA_TYPE_UINT32: 1880 (void) nvpair_value_uint32(nvp, &i32); 1881 fmd_hdl_debug(hdl, "DATA_TYPE_UINT32 0x%x", i32); 1882 break; 1883 1884 case DATA_TYPE_INT64: 1885 (void) nvpair_value_int64(nvp, (void *)&i64); 1886 fmd_hdl_debug(hdl, "DATA_TYPE_INT64 0x%llx", 1887 (u_longlong_t)i64); 1888 break; 1889 1890 case DATA_TYPE_UINT64: 1891 (void) nvpair_value_uint64(nvp, &i64); 1892 fmd_hdl_debug(hdl, "DATA_TYPE_UINT64 0x%llx", 1893 (u_longlong_t)i64); 1894 break; 1895 1896 case DATA_TYPE_HRTIME: 1897 (void) nvpair_value_hrtime(nvp, (void *)&i64); 1898 fmd_hdl_debug(hdl, "DATA_TYPE_HRTIME 0x%llx", 1899 (u_longlong_t)i64); 1900 break; 1901 1902 case DATA_TYPE_STRING: 1903 (void) nvpair_value_string(nvp, &str); 1904 fmd_hdl_debug(hdl, "DATA_TYPE_STRING \"%s\"", 1905 str ? str : "<NULL>"); 1906 break; 1907 1908 case DATA_TYPE_NVLIST: 1909 fmd_hdl_debug(hdl, "["); 1910 (void) nvpair_value_nvlist(nvp, &cnv); 1911 fab_pr(hdl, NULL, cnv); 1912 fmd_hdl_debug(hdl, " ]"); 1913 break; 1914 1915 case DATA_TYPE_BOOLEAN_ARRAY: 1916 case DATA_TYPE_BYTE_ARRAY: 1917 case DATA_TYPE_INT8_ARRAY: 1918 case DATA_TYPE_UINT8_ARRAY: 1919 case DATA_TYPE_INT16_ARRAY: 1920 case DATA_TYPE_UINT16_ARRAY: 1921 case DATA_TYPE_INT32_ARRAY: 1922 case DATA_TYPE_UINT32_ARRAY: 1923 case DATA_TYPE_INT64_ARRAY: 1924 case DATA_TYPE_UINT64_ARRAY: 1925 case DATA_TYPE_STRING_ARRAY: 1926 fmd_hdl_debug(hdl, "[...]"); 1927 break; 1928 case DATA_TYPE_NVLIST_ARRAY: 1929 arrsize = 0; 1930 (void) nvpair_value_nvlist_array(nvp, &nvlarr, 1931 &arrsize); 1932 1933 for (arri = 0; arri < arrsize; arri++) { 1934 fab_pr(hdl, ep, nvlarr[arri]); 1935 } 1936 1937 break; 1938 case DATA_TYPE_UNKNOWN: 1939 fmd_hdl_debug(hdl, "<unknown>"); 1940 break; 1941 } 1942 } 1943 } 1944 1945 /*ARGSUSED*/ 1946 static void 1947 fab_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class) 1948 { 1949 fab_data_t fab_data = {0}; 1950 1951 if (!fab_valid_topo) 1952 fab_update_topo(hdl); 1953 1954 if (fmd_nvl_class_match(hdl, nvl, "ereport.io.pci.fabric")) { 1955 fmd_hdl_debug(hdl, "PCI ereport received: %s\n", class); 1956 fab_pci_fabric_to_data(hdl, nvl, &fab_data); 1957 fab_xlate_pcie_erpts(hdl, &fab_data); 1958 } else { 1959 fab_pr(hdl, ep, nvl); 1960 fmd_hdl_debug(hdl, "Fire RC ereport received: %s\n", class); 1961 fab_fire_to_data(hdl, nvl, &fab_data); 1962 fab_xlate_fire_erpts(hdl, &fab_data, nvl, class); 1963 fab_xlate_pcie_erpts(hdl, &fab_data); 1964 } 1965 } 1966 1967 /* ARGSUSED */ 1968 static void 1969 fab_topo(fmd_hdl_t *hdl, topo_hdl_t *topo) 1970 { 1971 fab_valid_topo = 0; 1972 } 1973 1974 static const fmd_hdl_ops_t fmd_ops = { 1975 fab_recv, /* fmdo_recv */ 1976 NULL, /* fmdo_timeout */ 1977 NULL, /* fmdo_close */ 1978 NULL, /* fmdo_stats */ 1979 NULL, /* fmdo_gc */ 1980 NULL, /* fmdo_send */ 1981 fab_topo, /* fmdo_topo */ 1982 }; 1983 1984 static const fmd_hdl_info_t fmd_info = { 1985 "Fabric Ereport Translater", "1.0", &fmd_ops, NULL 1986 }; 1987 1988 #define REG_OFF(reg) ((uint32_t)(uint32_t)&fab_data.reg - (uint32_t)&fab_data) 1989 #define SET_TBL(n, err, reg, sz) \ 1990 fab_master_err_tbl[n].erpt_tbl = fab_ ## err ## _erpt_tbl; \ 1991 fab_master_err_tbl[n].reg_offset = REG_OFF(reg); \ 1992 fab_master_err_tbl[n].reg_size = sz; \ 1993 fab_master_err_tbl[n].fab_prep = fab_prep_ ## err ## _erpt; 1994 1995 void 1996 _fmd_init(fmd_hdl_t *hdl) 1997 { 1998 fab_data_t fab_data; 1999 2000 if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) 2001 return; 2002 2003 /* Init libxml */ 2004 xmlInitParser(); 2005 2006 fab_fmd_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL); 2007 fmd_hdl_debug(hdl, "Fabric Translater Started\n"); 2008 2009 /* Setup the master error table */ 2010 fab_master_err_tbl = (fab_err_tbl_t *)calloc(13, 2011 sizeof (fab_err_tbl_t)); 2012 2013 SET_TBL(0, pci, pci_err_status, 16); 2014 SET_TBL(1, pci_bdg, pci_bdg_sec_stat, 16); 2015 SET_TBL(2, pci_bdg_ctl, pci_bdg_ctrl, 16); 2016 SET_TBL(3, pcie_ce, pcie_ce_status, 32); 2017 SET_TBL(4, pcie_ue, pcie_ue_status, 32); 2018 SET_TBL(5, pcie_sue, pcie_sue_status, 32); 2019 SET_TBL(6, pcix, pcix_status, 32); 2020 SET_TBL(7, pcix_bdg_sec, pcix_bdg_sec_stat, 16); 2021 SET_TBL(8, pcix_bdg, pcix_bdg_stat, 32); 2022 SET_TBL(9, pcie_nadv, pcie_err_status, 16); 2023 SET_TBL(10, pcie_rc, pcie_rp_err_status, 32); 2024 SET_TBL(11, pcie_fake_rc, pcie_err_status, 16); 2025 } 2026 2027 void 2028 _fmd_fini(fmd_hdl_t *hdl) 2029 { 2030 /* Fini xpath */ 2031 if (fab_xpathCtx) 2032 xmlXPathFreeContext(fab_xpathCtx); 2033 /* Free xml document */ 2034 if (fab_doc) 2035 xmlFreeDoc(fab_doc); 2036 /* Fini libxml */ 2037 xmlCleanupParser(); 2038 2039 fmd_xprt_close(hdl, fab_fmd_xprt); 2040 } 2041