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 2009 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 FREE_PROP(prop) xmlFree((xmlChar *)prop) 449 #define STRCMP(s1, s2) (strcmp((const char *)s1, (const char *)s2) == 0) 450 451 #define FAB_LOOKUP(sz, name, field) \ 452 (void) nvlist_lookup_uint ## sz(nvl, name, field) 453 /* ARGSUSED */ 454 static void 455 fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) { 456 data->nvl = nvl; 457 458 /* Generic PCI device information */ 459 FAB_LOOKUP(16, "bdf", &data->bdf); 460 FAB_LOOKUP(16, "device_id", &data->device_id); 461 FAB_LOOKUP(16, "vendor_id", &data->vendor_id); 462 FAB_LOOKUP(8, "rev_id", &data->rev_id); 463 FAB_LOOKUP(16, "dev_type", &data->dev_type); 464 FAB_LOOKUP(16, "pcie_off", &data->pcie_off); 465 FAB_LOOKUP(16, "pcix_off", &data->pcix_off); 466 FAB_LOOKUP(16, "aer_off", &data->aer_off); 467 FAB_LOOKUP(16, "ecc_ver", &data->ecc_ver); 468 469 /* Misc ereport information */ 470 FAB_LOOKUP(32, "remainder", &data->remainder); 471 FAB_LOOKUP(32, "severity", &data->severity); 472 473 /* PCI registers */ 474 FAB_LOOKUP(16, "pci_status", &data->pci_err_status); 475 FAB_LOOKUP(16, "pci_command", &data->pci_cfg_comm); 476 477 /* PCI bridge registers */ 478 FAB_LOOKUP(16, "pci_bdg_sec_status", &data->pci_bdg_sec_stat); 479 FAB_LOOKUP(16, "pci_bdg_ctrl", &data->pci_bdg_ctrl); 480 481 /* PCIx registers */ 482 FAB_LOOKUP(32, "pcix_status", &data->pcix_status); 483 FAB_LOOKUP(16, "pcix_command", &data->pcix_command); 484 485 /* PCIx ECC Registers */ 486 FAB_LOOKUP(16, "pcix_ecc_control_0", &data->pcix_ecc_control_0); 487 FAB_LOOKUP(16, "pcix_ecc_status_0", &data->pcix_ecc_status_0); 488 FAB_LOOKUP(32, "pcix_ecc_fst_addr_0", &data->pcix_ecc_fst_addr_0); 489 FAB_LOOKUP(32, "pcix_ecc_sec_addr_0", &data->pcix_ecc_sec_addr_0); 490 FAB_LOOKUP(32, "pcix_ecc_attr_0", &data->pcix_ecc_attr_0); 491 492 /* PCIx ECC Bridge Registers */ 493 FAB_LOOKUP(16, "pcix_ecc_control_1", &data->pcix_ecc_control_1); 494 FAB_LOOKUP(16, "pcix_ecc_status_1", &data->pcix_ecc_status_1); 495 FAB_LOOKUP(32, "pcix_ecc_fst_addr_1", &data->pcix_ecc_fst_addr_1); 496 FAB_LOOKUP(32, "pcix_ecc_sec_addr_1", &data->pcix_ecc_sec_addr_1); 497 FAB_LOOKUP(32, "pcix_ecc_attr_1", &data->pcix_ecc_attr_1); 498 499 /* PCIx Bridge */ 500 FAB_LOOKUP(32, "pcix_bdg_status", &data->pcix_bdg_stat); 501 FAB_LOOKUP(16, "pcix_bdg_sec_status", &data->pcix_bdg_sec_stat); 502 503 /* PCIe registers */ 504 FAB_LOOKUP(16, "pcie_status", &data->pcie_err_status); 505 FAB_LOOKUP(16, "pcie_command", &data->pcie_err_ctl); 506 FAB_LOOKUP(32, "pcie_dev_cap", &data->pcie_dev_cap); 507 508 /* PCIe AER registers */ 509 FAB_LOOKUP(32, "pcie_adv_ctl", &data->pcie_adv_ctl); 510 FAB_LOOKUP(32, "pcie_ue_status", &data->pcie_ue_status); 511 FAB_LOOKUP(32, "pcie_ue_mask", &data->pcie_ue_mask); 512 FAB_LOOKUP(32, "pcie_ue_sev", &data->pcie_ue_sev); 513 FAB_LOOKUP(32, "pcie_ue_hdr0", &data->pcie_ue_hdr[0]); 514 FAB_LOOKUP(32, "pcie_ue_hdr1", &data->pcie_ue_hdr[1]); 515 FAB_LOOKUP(32, "pcie_ue_hdr2", &data->pcie_ue_hdr[2]); 516 FAB_LOOKUP(32, "pcie_ue_hdr3", &data->pcie_ue_hdr[3]); 517 FAB_LOOKUP(32, "pcie_ce_status", &data->pcie_ce_status); 518 FAB_LOOKUP(32, "pcie_ce_mask", &data->pcie_ce_mask); 519 FAB_LOOKUP(32, "pcie_ue_tgt_trans", &data->pcie_ue_tgt_trans); 520 FAB_LOOKUP(64, "pcie_ue_tgt_addr", &data->pcie_ue_tgt_addr); 521 FAB_LOOKUP(16, "pcie_ue_tgt_bdf", &data->pcie_ue_tgt_bdf); 522 523 /* PCIe BDG AER registers */ 524 FAB_LOOKUP(32, "pcie_sue_adv_ctl", &data->pcie_sue_ctl); 525 FAB_LOOKUP(32, "pcie_sue_status", &data->pcie_sue_status); 526 FAB_LOOKUP(32, "pcie_sue_mask", &data->pcie_sue_mask); 527 FAB_LOOKUP(32, "pcie_sue_sev", &data->pcie_sue_sev); 528 FAB_LOOKUP(32, "pcie_sue_hdr0", &data->pcie_sue_hdr[0]); 529 FAB_LOOKUP(32, "pcie_sue_hdr1", &data->pcie_sue_hdr[1]); 530 FAB_LOOKUP(32, "pcie_sue_hdr2", &data->pcie_sue_hdr[2]); 531 FAB_LOOKUP(32, "pcie_sue_hdr3", &data->pcie_sue_hdr[3]); 532 FAB_LOOKUP(32, "pcie_sue_tgt_trans", &data->pcie_sue_tgt_trans); 533 FAB_LOOKUP(64, "pcie_sue_tgt_addr", &data->pcie_sue_tgt_addr); 534 FAB_LOOKUP(16, "pcie_sue_tgt_bdf", &data->pcie_sue_tgt_bdf); 535 536 /* PCIe RP registers */ 537 FAB_LOOKUP(32, "pcie_rp_status", &data->pcie_rp_status); 538 FAB_LOOKUP(16, "pcie_rp_control", &data->pcie_rp_ctl); 539 540 /* PCIe RP AER registers */ 541 FAB_LOOKUP(32, "pcie_adv_rp_status", &data->pcie_rp_err_status); 542 FAB_LOOKUP(32, "pcie_adv_rp_command", &data->pcie_rp_err_cmd); 543 FAB_LOOKUP(16, "pcie_adv_rp_ce_src_id", &data->pcie_rp_ce_src_id); 544 FAB_LOOKUP(16, "pcie_adv_rp_ue_src_id", &data->pcie_rp_ue_src_id); 545 546 /* 547 * If the system has a PCIe complaint RP with AER, turn off translating 548 * fake RP ereports. 549 */ 550 if (fab_xlate_fake_rp && 551 (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) && 552 data->aer_off) 553 fab_xlate_fake_rp = B_FALSE; 554 } 555 556 /* ARGSUSED */ 557 static void 558 fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) { 559 data->nvl = nvl; 560 561 /* Always Root Complex */ 562 data->dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT; 563 564 data->pcie_ue_sev = (PCIE_AER_UCE_DLP | PCIE_AER_UCE_SD | 565 PCIE_AER_UCE_FCP | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP); 566 } 567 568 /* ARGSUSED */ 569 static int 570 fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt, 571 boolean_t isRC) { 572 uint64_t *now; 573 uint64_t ena; 574 uint_t nelem; 575 nvlist_t *detector, *new_detector; 576 char rcpath[255]; 577 int err = 0; 578 579 /* Grab the tod, ena and detector(FMRI) */ 580 err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem); 581 err |= nvlist_lookup_uint64(nvl, "ena", &ena); 582 err |= nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector); 583 if (err) 584 return (err); 585 586 /* Make a copy of the detector */ 587 err = nvlist_dup(detector, &new_detector, NV_UNIQUE_NAME); 588 if (err) 589 return (err); 590 591 /* Copy the tod and ena to erpt */ 592 (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena); 593 (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem); 594 595 /* 596 * Create the correct ROOT FMRI from PCIe leaf fabric ereports. Used 597 * only by fab_prep_fake_rc_erpt. See the fab_pciex_fake_rc_erpt_tbl 598 * comments for more information. 599 */ 600 if (isRC && fab_get_rcpath(hdl, nvl, rcpath)) { 601 /* Create the correct PCIe RC new_detector aka FMRI */ 602 (void) nvlist_remove(new_detector, FM_FMRI_DEV_PATH, 603 DATA_TYPE_STRING); 604 (void) nvlist_add_string(new_detector, FM_FMRI_DEV_PATH, 605 rcpath); 606 } 607 608 /* Copy the FMRI to erpt */ 609 (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, new_detector); 610 611 nvlist_free(new_detector); 612 return (err); 613 } 614 615 static void 616 fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, const char *class, 617 boolean_t isPrimary) 618 { 619 nvlist_t *nvl = data->nvl; 620 nvlist_t *erpt; 621 char *fmri = NULL; 622 uint32_t tgt_trans; 623 uint64_t tgt_addr; 624 uint16_t tgt_bdf; 625 626 if (isPrimary) { 627 tgt_trans = data->pcie_ue_tgt_trans; 628 tgt_addr = data->pcie_ue_tgt_addr; 629 tgt_bdf = data->pcie_ue_tgt_bdf; 630 } else { 631 tgt_trans = data->pcie_sue_tgt_trans; 632 tgt_addr = data->pcie_sue_tgt_addr; 633 tgt_bdf = data->pcie_sue_tgt_bdf; 634 } 635 636 fmd_hdl_debug(hdl, "Sending Target Ereport: " 637 "type 0x%x addr 0x%llx fltbdf 0x%x\n", 638 tgt_trans, tgt_addr, tgt_bdf); 639 640 if (!tgt_trans) 641 return; 642 643 if ((tgt_trans == PF_ADDR_PIO) && tgt_addr) 644 fmri = fab_find_addr(hdl, nvl, tgt_addr); 645 else if ((tgt_trans == PF_ADDR_CFG) && tgt_bdf) 646 fmri = fab_find_bdf(hdl, nvl, tgt_bdf); 647 648 if (fmri) { 649 uint64_t *now; 650 uint64_t ena; 651 uint_t nelem; 652 nvlist_t *detector; 653 int err = 0; 654 655 /* Allocate space for new erpt */ 656 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 657 goto done; 658 659 /* Generate the target ereport class */ 660 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 661 PCI_ERROR_SUBCLASS, class); 662 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 663 664 /* Grab the tod, ena and detector(FMRI) */ 665 err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem); 666 err |= nvlist_lookup_uint64(nvl, "ena", &ena); 667 668 /* Copy the tod and ena to erpt */ 669 (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena); 670 (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem); 671 672 /* Create the correct FMRI */ 673 if (nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0) { 674 nvlist_free(erpt); 675 goto done; 676 } 677 (void) nvlist_add_uint8(detector, FM_VERSION, 678 FM_DEV_SCHEME_VERSION); 679 (void) nvlist_add_string(detector, FM_FMRI_SCHEME, 680 FM_FMRI_SCHEME_DEV); 681 (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, fmri); 682 (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, detector); 683 nvlist_free(detector); 684 685 /* Add the address payload */ 686 (void) nvlist_add_uint64(erpt, PCI_PA, tgt_addr); 687 688 fmd_hdl_debug(hdl, "Sending target ereport: %s 0x%x\n", 689 fab_buf, tgt_addr); 690 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 691 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 692 goto done; 693 xmlFree(fmri); 694 } else { 695 fmd_hdl_debug(hdl, "Cannot find Target FMRI addr:0x%llx", 696 tgt_addr); 697 } 698 699 return; 700 done: 701 if (fmri) 702 xmlFree(fmri); 703 fmd_hdl_debug(hdl, "Failed to send Target PCI ereport\n"); 704 } 705 706 static void 707 fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl) 708 { 709 fab_erpt_tbl_t *erpt_tbl, *entry; 710 nvlist_t *erpt; 711 uint32_t reg; 712 713 erpt_tbl = tbl->erpt_tbl; 714 if (tbl->reg_size == 16) { 715 reg = (uint32_t)*((uint16_t *) 716 ((uint32_t)data + tbl->reg_offset)); 717 } else { 718 reg = *((uint32_t *)((uint32_t)data + tbl->reg_offset)); 719 } 720 721 for (entry = erpt_tbl; entry->err_class; entry++) { 722 if (!(reg & entry->reg_bit)) 723 continue; 724 725 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 726 goto done; 727 if (tbl->fab_prep(hdl, data, erpt, entry) != 0) { 728 fmd_hdl_debug(hdl, "Prepping ereport failed\n"); 729 nvlist_free(erpt); 730 continue; 731 } 732 733 fmd_hdl_debug(hdl, "Sending ereport: %s 0x%x\n", fab_buf, reg); 734 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 735 if (fmd_xprt_error(hdl, fab_fmd_xprt)) { 736 fmd_hdl_debug(hdl, "Failed to send PCI ereport\n"); 737 return; 738 } 739 } 740 741 return; 742 done: 743 fmd_hdl_debug(hdl, "Failed to send PCI ereport\n"); 744 } 745 746 static int 747 fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 748 fab_erpt_tbl_t *tbl) 749 { 750 const char *class = tbl->err_class; 751 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 752 753 /* Generate an ereport for this error bit. */ 754 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 755 PCI_ERROR_SUBCLASS, class); 756 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 757 758 (void) nvlist_add_uint16(erpt, PCI_CONFIG_STATUS, data->pci_err_status); 759 (void) nvlist_add_uint16(erpt, PCI_CONFIG_COMMAND, data->pci_cfg_comm); 760 761 return (err); 762 } 763 764 static int 765 fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 766 fab_erpt_tbl_t *tbl) 767 { 768 const char *class = tbl->err_class; 769 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 770 771 /* Generate an ereport for this error bit. */ 772 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s-%s", 773 PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, class); 774 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 775 776 (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, 777 data->pci_bdg_sec_stat); 778 (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); 779 780 return (err); 781 } 782 783 static int 784 fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 785 fab_erpt_tbl_t *tbl) 786 { 787 const char *class = tbl->err_class; 788 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 789 790 /* Generate an ereport for this error bit. */ 791 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 792 PCI_ERROR_SUBCLASS, class); 793 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 794 795 (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, 796 data->pci_bdg_sec_stat); 797 (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); 798 799 return (err); 800 } 801 802 803 static int 804 fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 805 fab_erpt_tbl_t *tbl) 806 { 807 const char *class = tbl->err_class; 808 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 809 810 /* Generate an ereport for this error bit. */ 811 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 812 PCIEX_ERROR_SUBCLASS, class); 813 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 814 815 (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 816 (void) nvlist_add_uint32(erpt, PCIEX_CE_STATUS_REG, 817 data->pcie_ce_status); 818 819 return (err); 820 } 821 822 static int 823 fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 824 fab_erpt_tbl_t *tbl) 825 { 826 const char *class = tbl->err_class; 827 uint32_t first_err = 1 << (data->pcie_adv_ctl & 828 PCIE_AER_CTL_FST_ERR_PTR_MASK); 829 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 830 831 /* Generate an ereport for this error bit. */ 832 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 833 PCIEX_ERROR_SUBCLASS, class); 834 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 835 836 (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 837 (void) nvlist_add_uint32(erpt, PCIEX_UE_STATUS_REG, 838 data->pcie_ue_status); 839 (void) nvlist_add_uint32(erpt, PCIEX_UE_SEV_REG, data->pcie_ue_sev); 840 (void) nvlist_add_uint32(erpt, PCIEX_ADV_CTL, data->pcie_adv_ctl); 841 842 fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); 843 844 if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_bdf) { 845 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 846 data->pcie_ue_tgt_bdf); 847 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 848 } else { 849 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); 850 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); 851 } 852 853 if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_trans) { 854 if (tbl->tgt_class) 855 fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_TRUE); 856 } 857 858 return (err); 859 } 860 861 static int 862 fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 863 fab_erpt_tbl_t *tbl) 864 { 865 const char *class = tbl->err_class; 866 uint32_t first_err = 1 << (data->pcie_sue_ctl & 867 PCIE_AER_SCTL_FST_ERR_PTR_MASK); 868 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 869 870 /* Generate an ereport for this error bit. */ 871 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 872 PCIEX_ERROR_SUBCLASS, class); 873 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 874 875 (void) nvlist_add_uint32(erpt, PCIEX_SEC_UE_STATUS, 876 data->pcie_sue_status); 877 878 fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); 879 880 if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_bdf) { 881 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 882 data->pcie_sue_tgt_bdf); 883 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 884 } else { 885 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); 886 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); 887 } 888 889 if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_trans) { 890 if (tbl->tgt_class) 891 fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_FALSE); 892 } 893 894 return (err); 895 } 896 897 static int 898 fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 899 fab_erpt_tbl_t *tbl) 900 { 901 const char *class = tbl->err_class; 902 int err = 0; 903 904 /* Only send if this is not a bridge */ 905 if (!data->pcix_status || data->pcix_bdg_sec_stat) 906 return (1); 907 908 err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 909 910 /* Generate an ereport for this error bit. */ 911 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 912 PCIX_ERROR_SUBCLASS, class); 913 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 914 915 (void) nvlist_add_uint8(erpt, PCIX_COMMAND, data->pcix_command); 916 (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 917 918 return (err); 919 } 920 921 static void 922 fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) 923 { 924 nvlist_t *erpt; 925 int ecc_phase = (data->pcix_ecc_status_0 & PCI_PCIX_ECC_PHASE) >> 0x4; 926 int ecc_corr = data->pcix_ecc_status_0 & PCI_PCIX_ECC_CORR; 927 int sec_ue = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_UE; 928 int sec_ce = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_CE; 929 uint32_t ctlstat = (data->pcix_ecc_control_0 << 16) | 930 data->pcix_ecc_status_0; 931 932 switch (ecc_phase) { 933 case PCI_PCIX_ECC_PHASE_NOERR: 934 break; 935 case PCI_PCIX_ECC_PHASE_FADDR: 936 case PCI_PCIX_ECC_PHASE_SADDR: 937 (void) snprintf(fab_buf, FM_MAX_CLASS, 938 "%s.%s", PCIX_ERROR_SUBCLASS, 939 ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR); 940 break; 941 case PCI_PCIX_ECC_PHASE_ATTR: 942 (void) snprintf(fab_buf, FM_MAX_CLASS, 943 "%s.%s", PCIX_ERROR_SUBCLASS, 944 ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); 945 break; 946 case PCI_PCIX_ECC_PHASE_DATA32: 947 case PCI_PCIX_ECC_PHASE_DATA64: 948 (void) snprintf(fab_buf, FM_MAX_CLASS, 949 "%s.%s", PCIX_ERROR_SUBCLASS, 950 ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); 951 break; 952 } 953 954 if (ecc_phase) { 955 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 956 goto done; 957 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 958 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 959 (void) nvlist_add_uint16(erpt, PCIX_COMMAND, 960 data->pcix_command); 961 (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 962 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 963 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 964 data->pcix_ecc_attr_0); 965 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 966 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 967 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 968 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 969 } 970 971 if (sec_ce || sec_ue) { 972 (void) snprintf(fab_buf, FM_MAX_CLASS, 973 "%s.%s", PCIX_ERROR_SUBCLASS, 974 sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); 975 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 976 goto done; 977 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 978 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 979 (void) nvlist_add_uint16(erpt, PCIX_COMMAND, 980 data->pcix_command); 981 (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 982 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 983 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 984 data->pcix_ecc_attr_0); 985 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 986 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 987 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 988 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 989 } 990 991 return; 992 done: 993 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 994 } 995 996 static int 997 fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 998 fab_erpt_tbl_t *tbl) 999 { 1000 const char *class = tbl->err_class; 1001 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1002 1003 /* Generate an ereport for this error bit. */ 1004 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s%s", 1005 PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, class); 1006 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1007 1008 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 1009 data->pcix_bdg_sec_stat); 1010 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); 1011 1012 return (err); 1013 } 1014 1015 static int 1016 fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1017 fab_erpt_tbl_t *tbl) 1018 { 1019 const char *class = tbl->err_class; 1020 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1021 1022 /* Generate an ereport for this error bit. */ 1023 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 1024 PCIX_ERROR_SUBCLASS, class); 1025 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1026 1027 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 1028 data->pcix_bdg_sec_stat); 1029 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); 1030 1031 return (err); 1032 } 1033 1034 static void 1035 fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) 1036 { 1037 nvlist_t *erpt; 1038 int ecc_phase = (data->pcix_ecc_status_1 & PCI_PCIX_ECC_PHASE) >> 0x4; 1039 int ecc_corr = data->pcix_ecc_status_1 & PCI_PCIX_ECC_CORR; 1040 int sec_ue = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_UE; 1041 int sec_ce = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_CE; 1042 uint32_t ctlstat = (data->pcix_ecc_control_1 << 16) | 1043 data->pcix_ecc_status_1; 1044 1045 switch (ecc_phase) { 1046 case PCI_PCIX_ECC_PHASE_NOERR: 1047 break; 1048 case PCI_PCIX_ECC_PHASE_FADDR: 1049 case PCI_PCIX_ECC_PHASE_SADDR: 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_ADDR : PCIX_ECC_UE_ADDR); 1053 break; 1054 case PCI_PCIX_ECC_PHASE_ATTR: 1055 (void) snprintf(fab_buf, FM_MAX_CLASS, 1056 "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 1057 ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); 1058 break; 1059 case PCI_PCIX_ECC_PHASE_DATA32: 1060 case PCI_PCIX_ECC_PHASE_DATA64: 1061 (void) snprintf(fab_buf, FM_MAX_CLASS, 1062 "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 1063 ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); 1064 break; 1065 } 1066 if (ecc_phase) { 1067 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 1068 goto done; 1069 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1070 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1071 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 1072 data->pcix_bdg_sec_stat); 1073 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, 1074 data->pcix_bdg_stat); 1075 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 1076 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 1077 data->pcix_ecc_attr_1); 1078 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 1079 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 1080 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 1081 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 1082 } 1083 1084 if (sec_ce || sec_ue) { 1085 (void) snprintf(fab_buf, FM_MAX_CLASS, 1086 "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 1087 sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); 1088 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 1089 goto done; 1090 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1091 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1092 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 1093 data->pcix_bdg_sec_stat); 1094 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, 1095 data->pcix_bdg_stat); 1096 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 1097 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 1098 data->pcix_ecc_attr_1); 1099 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 1100 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 1101 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 1102 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 1103 } 1104 return; 1105 done: 1106 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 1107 } 1108 1109 static int 1110 fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1111 fab_erpt_tbl_t *tbl) 1112 { 1113 const char *class = tbl->err_class; 1114 int err = 0; 1115 1116 /* Don't send this for PCI device, Root Ports, or PCIe with AER */ 1117 if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || 1118 (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || 1119 data->aer_off) 1120 return (1); 1121 1122 err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1123 1124 /* Generate an ereport for this error bit. */ 1125 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 1126 PCIEX_ERROR_SUBCLASS, class); 1127 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1128 1129 (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 1130 1131 return (err); 1132 } 1133 1134 static int 1135 fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1136 fab_erpt_tbl_t *tbl) 1137 { 1138 const char *class = tbl->err_class; 1139 uint32_t status = data->pcie_rp_err_status; 1140 int err = 0; 1141 int isFE = 0, isNFE = 0; 1142 1143 fmd_hdl_debug(hdl, "XLATE RP Error Class %s", class); 1144 1145 if (!data->aer_off) 1146 return (-1); 1147 1148 /* Only send a FE Msg if the 1st UE error is FE */ 1149 if (STRCMP(class, PCIEX_RC_FE_MSG)) 1150 if (!(status & PCIE_AER_RE_STS_FIRST_UC_FATAL)) 1151 return (-1); 1152 else 1153 isFE = 1; 1154 1155 /* Only send a NFE Msg is the 1st UE error is NFE */ 1156 if (STRCMP(class, PCIEX_RC_NFE_MSG)) 1157 if (status & PCIE_AER_RE_STS_FIRST_UC_FATAL) 1158 return (-1); 1159 else 1160 isNFE = 1; 1161 1162 fmd_hdl_debug(hdl, "XLATE RP Error"); 1163 1164 err |= fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1165 1166 /* Generate an ereport for this error bit. */ 1167 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 1168 PCIEX_ERROR_SUBCLASS, class); 1169 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1170 1171 (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, status); 1172 if ((isFE || isNFE) && data->pcie_rp_ue_src_id) { 1173 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 1174 data->pcie_rp_ue_src_id); 1175 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 1176 } 1177 if (STRCMP(class, PCIEX_RC_CE_MSG) && data->pcie_rp_ce_src_id) { 1178 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 1179 data->pcie_rp_ce_src_id); 1180 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 1181 } 1182 1183 return (err); 1184 } 1185 1186 static int 1187 fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1188 fab_erpt_tbl_t *tbl) 1189 { 1190 const char *class = tbl->err_class; 1191 uint32_t rc_err_sts = 0; 1192 int err = 0; 1193 1194 /* 1195 * Don't send this for PCI device or Root Ports. Only send it on 1196 * systems with non-compliant RPs. 1197 */ 1198 if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || 1199 (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || 1200 (!fab_xlate_fake_rp)) 1201 return (-1); 1202 1203 err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_TRUE); 1204 1205 /* Generate an ereport for this error bit. */ 1206 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 1207 PCIEX_ERROR_SUBCLASS, class); 1208 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1209 1210 /* Send PCIe RC Ereports */ 1211 if (data->pcie_err_status & PCIE_DEVSTS_CE_DETECTED) { 1212 rc_err_sts |= PCIE_AER_RE_STS_CE_RCVD; 1213 } 1214 1215 /* NFE/FE src id takes precedence over CE src id */ 1216 if (data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) { 1217 rc_err_sts |= PCIE_AER_RE_STS_NFE_MSGS_RCVD; 1218 rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; 1219 } 1220 if (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED) { 1221 rc_err_sts |= PCIE_AER_RE_STS_FE_MSGS_RCVD; 1222 rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; 1223 } 1224 if ((data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) && 1225 (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED)) { 1226 rc_err_sts |= PCIE_AER_RE_STS_FIRST_UC_FATAL; 1227 rc_err_sts |= PCIE_AER_RE_STS_MUL_FE_NFE_RCVD; 1228 } 1229 1230 (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, rc_err_sts); 1231 1232 if (!(rc_err_sts & PCIE_AER_RE_STS_MUL_FE_NFE_RCVD)) { 1233 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, data->bdf); 1234 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 1235 } 1236 1237 return (err); 1238 } 1239 1240 static int 1241 fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1242 const char *class) 1243 { 1244 fab_fire_tbl_t *entry; 1245 uint64_t reg; 1246 1247 for (entry = fab_fire_pec_ce_tbl; entry->err_class; entry++) { 1248 if (STRCMP(class, entry->err_class)) 1249 goto send; 1250 } 1251 1252 return (0); 1253 1254 send: 1255 fmd_hdl_debug(hdl, "Translate Fire CE %s\n", class); 1256 1257 /* Fill in the device status register */ 1258 data->pcie_err_status = PCIE_DEVSTS_CE_DETECTED; 1259 1260 /* Fill in the AER CE register */ 1261 if (nvlist_lookup_uint64(erpt, "tlu-cess", ®) == 0) { 1262 data->pcie_ce_status = (uint32_t)reg | (uint32_t)(reg >> 32); 1263 } 1264 1265 return (1); 1266 } 1267 1268 static int 1269 fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1270 const char *class) 1271 { 1272 fab_fire_tbl_t *entry; 1273 uint64_t reg; 1274 uint32_t temp; 1275 pcie_tlp_hdr_t *hdr; 1276 1277 for (entry = fab_fire_pec_ue_tbl; entry->err_class; entry++) { 1278 if (STRCMP(class, entry->err_class)) 1279 goto send; 1280 } 1281 1282 return (0); 1283 1284 send: 1285 fmd_hdl_debug(hdl, "Translate Fire UE %s\n", class); 1286 1287 /* Fill in PCI Status Register */ 1288 data->pci_err_status = entry->pci_err_sts; 1289 data->pci_bdg_sec_stat = entry->pci_bdg_sts; 1290 1291 /* Fill in the device status register */ 1292 if (entry->fire_bit & data->pcie_ue_sev) 1293 data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; 1294 else 1295 data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; 1296 1297 if (entry->fire_bit == PCIE_AER_UCE_UR) 1298 data->pcie_err_status |= PCIE_DEVSTS_UR_DETECTED; 1299 1300 /* Fill in the AER UE register */ 1301 if (nvlist_lookup_uint64(erpt, "tlu-uess", ®) == 0) { 1302 data->pcie_ue_status = (uint32_t)reg | (uint32_t)(reg >> 32); 1303 } 1304 1305 /* Fill in the AER Control register */ 1306 if ((reg & (uint64_t)entry->fire_bit) && 1307 nvlist_lookup_boolean(erpt, "primary")) { 1308 temp = entry->fire_bit; 1309 for (data->pcie_adv_ctl = (uint32_t)-1; temp; 1310 data->pcie_adv_ctl++) 1311 temp = temp >> 1; 1312 } 1313 1314 /* If CTO create target information */ 1315 if (entry->fire_bit == PCIE_AER_UCE_TO && 1316 nvlist_lookup_boolean(erpt, "primary")) { 1317 if (nvlist_lookup_uint64(erpt, "tlu-tueh1l", ®) == 0) { 1318 data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); 1319 data->pcie_ue_hdr[1] = (uint32_t)(reg); 1320 } 1321 if (nvlist_lookup_uint64(erpt, "tlu-tueh2l", ®) == 0) { 1322 data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); 1323 data->pcie_ue_hdr[3] = (uint32_t)(reg); 1324 } 1325 1326 hdr = (pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]); 1327 switch (hdr->type) { 1328 case PCIE_TLP_TYPE_IO: 1329 case PCIE_TLP_TYPE_MEM: 1330 case PCIE_TLP_TYPE_MEMLK: 1331 data->pcie_ue_tgt_trans = PF_ADDR_PIO; 1332 if (hdr->fmt & 0x1) { 1333 data->pcie_ue_tgt_addr = reg; 1334 } else { 1335 data->pcie_ue_tgt_addr = data->pcie_ue_hdr[2]; 1336 } 1337 break; 1338 case PCIE_TLP_TYPE_CFG0: 1339 case PCIE_TLP_TYPE_CFG1: 1340 data->pcie_ue_tgt_trans = PF_ADDR_CFG; 1341 data->pcie_ue_tgt_bdf = data->pcie_ue_hdr[2] >> 16; 1342 break; 1343 } 1344 } 1345 1346 /* Fill in the AER Header registers */ 1347 if (nvlist_lookup_uint64(erpt, "tlu-rueh1l", ®) == 0) { 1348 data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); 1349 data->pcie_ue_hdr[1] = (uint32_t)(reg); 1350 } 1351 if (nvlist_lookup_uint64(erpt, "tlu-rueh2l", ®) == 0) { 1352 data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); 1353 data->pcie_ue_hdr[3] = (uint32_t)(reg); 1354 } 1355 1356 return (1); 1357 } 1358 1359 static int 1360 fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1361 const char *class) 1362 { 1363 fab_fire_tbl_t *entry; 1364 uint64_t reg; 1365 1366 for (entry = fab_fire_pec_oe_tbl; entry->err_class; entry++) { 1367 if (STRCMP(class, entry->err_class)) 1368 goto send; 1369 } 1370 1371 return (0); 1372 1373 send: 1374 fmd_hdl_debug(hdl, "Translate Fire OE %s\n", class); 1375 1376 /* Fill in PCI Status Register */ 1377 if (entry->fire_bit) { 1378 data->pci_err_status = entry->pci_err_sts; 1379 data->pci_bdg_sec_stat = entry->pci_bdg_sts; 1380 } else { 1381 if (nvlist_lookup_uint64(erpt, "tlu-roeeh1l", ®) == 0) { 1382 data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); 1383 data->pcie_ue_hdr[1] = (uint32_t)(reg); 1384 } 1385 if (nvlist_lookup_uint64(erpt, "tlu-roeeh2l", ®) == 0) { 1386 data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); 1387 data->pcie_ue_hdr[3] = (uint32_t)(reg); 1388 } 1389 1390 if (((pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]))->type == 1391 PCIE_TLP_TYPE_CPL) { 1392 pcie_cpl_t *cpl = (pcie_cpl_t *)&data->pcie_ue_hdr[1]; 1393 switch (cpl->status) { 1394 case PCIE_CPL_STS_UR: 1395 data->pci_err_status = 0; 1396 data->pci_bdg_sec_stat = PCI_STAT_R_MAST_AB | 1397 PCI_STAT_S_SYSERR; 1398 break; 1399 case PCIE_CPL_STS_CA: 1400 data->pci_err_status = 0; 1401 data->pci_bdg_sec_stat = PCI_STAT_R_TARG_AB | 1402 PCI_STAT_S_SYSERR; 1403 break; 1404 } 1405 } 1406 } 1407 1408 /* Fill in the device status register */ 1409 if (entry->fire_bit & data->pcie_ue_sev) 1410 data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; 1411 else 1412 data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; 1413 1414 /* Fill in the AER UE register */ 1415 data->pcie_ue_status = entry->fire_bit; 1416 1417 return (1); 1418 } 1419 1420 static int 1421 fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1422 const char *class) 1423 { 1424 fab_fire_tbl_t *entry; 1425 uint64_t reg; 1426 uint32_t temp; 1427 1428 for (entry = fab_fire_dmc_tbl; entry->err_class; entry++) { 1429 fmd_hdl_debug(hdl, "Matching %s\n", entry->err_class); 1430 if (STRCMP(class, entry->err_class) && 1431 nvlist_lookup_boolean(erpt, "primary")) 1432 goto send; 1433 } 1434 1435 return (0); 1436 1437 send: 1438 fmd_hdl_debug(hdl, "Translate Fire DMC %s\n", class); 1439 1440 /* Fill in PCI Status Register */ 1441 data->pci_err_status = entry->pci_err_sts; 1442 data->pci_bdg_sec_stat = entry->pci_bdg_sts; 1443 1444 /* Fill in the device status register */ 1445 data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; 1446 1447 /* Fill in the AER UE register */ 1448 data->pcie_ue_status = entry->fire_bit; 1449 1450 /* Fill in the AER Control register */ 1451 temp = entry->fire_bit; 1452 for (data->pcie_adv_ctl = (uint32_t)-1; temp; data->pcie_adv_ctl++) 1453 temp = temp >> 1; 1454 1455 /* Fill in the AER Header registers */ 1456 if (nvlist_lookup_uint64(erpt, "mmu-tfsr", ®) == 0) { 1457 fmd_hdl_debug(hdl, "tfsr 0x%llx\n", reg); 1458 /* Get the trans type */ 1459 temp = (reg & 0x3F0000) >> 16; 1460 data->pcie_ue_hdr[0] = (uint32_t)(temp << 24); 1461 data->pcie_ue_tgt_trans = PF_ADDR_DMA; 1462 /* Get the req id */ 1463 temp = (reg & 0xFFFF); 1464 data->pcie_ue_hdr[1] = (uint32_t)(temp << 16); 1465 data->pcie_ue_tgt_bdf = temp; 1466 } 1467 1468 if (nvlist_lookup_uint64(erpt, "mmu-tfar", ®) == 0) { 1469 fmd_hdl_debug(hdl, "tfar 0x%llx\n", reg); 1470 /* Get the address */ 1471 data->pcie_ue_hdr[2] = reg; 1472 data->pcie_ue_hdr[3] = 0; 1473 data->pcie_ue_tgt_addr = reg; 1474 } 1475 1476 fmd_hdl_debug(hdl, "HEADER 0 0x%x\n", data->pcie_ue_hdr[0]); 1477 fmd_hdl_debug(hdl, "HEADER 1 0x%x\n", data->pcie_ue_hdr[1]); 1478 fmd_hdl_debug(hdl, "HEADER 2 0x%x\n", data->pcie_ue_hdr[2]); 1479 fmd_hdl_debug(hdl, "HEADER 3 0x%x\n", data->pcie_ue_hdr[3]); 1480 1481 return (1); 1482 } 1483 1484 static void 1485 fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data) 1486 { 1487 fab_err_tbl_t *tbl; 1488 1489 fmd_hdl_debug(hdl, "Sending Ereports Now"); 1490 1491 /* Go through the error logs and send the relavant reports */ 1492 for (tbl = fab_master_err_tbl; tbl->erpt_tbl; tbl++) { 1493 fab_send_erpt(hdl, data, tbl); 1494 } 1495 1496 /* Send PCI-X ECC Ereports */ 1497 fab_send_pcix_ecc_erpt(hdl, data); 1498 fab_send_pcix_bdg_ecc_erpt(hdl, data); 1499 } 1500 1501 static void 1502 fab_xlate_fire_erpts(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *nvl, 1503 const char *class) 1504 { 1505 if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.pec.*")) { 1506 if (fab_xlate_fire_ce(hdl, data, nvl, class)) 1507 return; 1508 1509 if (fab_xlate_fire_ue(hdl, data, nvl, class)) 1510 return; 1511 1512 if (fab_xlate_fire_oe(hdl, data, nvl, class)) 1513 return; 1514 } else if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.dmc.*") || 1515 fmd_nvl_class_match(hdl, nvl, "ereport.io.n2.dmu.*")) { 1516 if (fab_xlate_fire_dmc(hdl, data, nvl, class)) 1517 return; 1518 } 1519 } 1520 1521 static void 1522 fab_update_topo(fmd_hdl_t *hdl) 1523 { 1524 topo_hdl_t *thp = NULL; 1525 FILE *fp; 1526 int err = 0; 1527 1528 if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL) { 1529 fmd_hdl_debug(hdl, "Failed to hold topo\n"); 1530 } 1531 1532 fp = fopen(XMLTOPOFILE, "w"); 1533 1534 if (topo_xml_print(thp, fp, FM_FMRI_SCHEME_HC, &err) < 0) { 1535 fmd_hdl_debug(hdl, "Failed to get XML topo\n"); 1536 } 1537 1538 (void) fclose(fp); 1539 1540 fmd_hdl_topo_rele(hdl, thp); 1541 1542 if (fab_xpathCtx) 1543 xmlXPathFreeContext(fab_xpathCtx); 1544 if (fab_doc) 1545 xmlFreeDoc(fab_doc); 1546 1547 /* Load xml document */ 1548 fab_doc = xmlParseFile(XMLTOPOFILE); 1549 1550 /* Init xpath */ 1551 fab_xpathCtx = xmlXPathNewContext(fab_doc); 1552 1553 fab_valid_topo = 1; 1554 } 1555 1556 #define FAB_HC2DEV_QUERY_SIZE_MIN 160 1557 #define FAB_HC2DEV_QUERY_SIZE(sz) \ 1558 ((sz + FAB_HC2DEV_QUERY_SIZE_MIN) * sizeof (char)) 1559 1560 static boolean_t 1561 fab_hc2dev(fmd_hdl_t *hdl, nvlist_t *detector, char **dev_path, 1562 uint_t *dev_path_size) { 1563 xmlXPathObjectPtr xpathObj; 1564 xmlNodeSetPtr nodes; 1565 char *query, *query_end, *temp; 1566 uint_t i, size; 1567 size_t query_size = 0; 1568 nvlist_t **hcl; 1569 1570 if (nvlist_lookup_nvlist_array(detector, FM_FMRI_HC_LIST, &hcl, 1571 &size) != 0) 1572 goto fail; 1573 1574 for (i = 0; i < size; i++) { 1575 if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &temp) != 0) 1576 goto fail; 1577 query_size += strlen(temp); 1578 if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &temp) != 0) 1579 goto fail; 1580 query_size += strlen(temp); 1581 /* Adjust for '=' and '/' later */ 1582 query_size += 2; 1583 } 1584 1585 query = fmd_hdl_alloc(hdl, FAB_HC2DEV_QUERY_SIZE(query_size), 1586 FMD_SLEEP); 1587 (void) sprintf(query, "//propval[@name='resource' and " 1588 "contains(substring(@value, string-length(@value) - %d), '", 1589 query_size); 1590 1591 query_end = query; 1592 query_end += strlen(query); 1593 1594 for (i = 0; i < size; i++) { 1595 (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &temp); 1596 (void) snprintf(query_end, query_size, "%s=", temp); 1597 query_end += strlen(temp) + 1; 1598 (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &temp); 1599 (void) snprintf(query_end, query_size, "%s", temp); 1600 query_end += strlen(temp); 1601 if (i != (size - 1)) { 1602 (void) sprintf(query_end++, "/"); 1603 } 1604 } 1605 1606 (void) sprintf(query_end, "')]/parent::*/following-sibling::*/" 1607 "propval[@name='dev']/@value"); 1608 1609 fmd_hdl_debug(hdl, "xpathObj query %s\n", query); 1610 1611 xpathObj = xmlXPathEvalExpression((const xmlChar *)query, 1612 fab_xpathCtx); 1613 fmd_hdl_free(hdl, query, FAB_HC2DEV_QUERY_SIZE(query_size)); 1614 1615 if (xpathObj == NULL) 1616 goto fail; 1617 1618 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, 1619 xpathObj->type); 1620 nodes = xpathObj->nodesetval; 1621 1622 if (nodes) { 1623 temp = (char *)xmlNodeGetContent(nodes->nodeTab[0]); 1624 fmd_hdl_debug(hdl, "HC Dev Path: %s\n", temp); 1625 *dev_path_size = strlen(temp) + 1; 1626 *dev_path = fmd_hdl_alloc(hdl, *dev_path_size, FMD_SLEEP); 1627 (void) strlcpy(*dev_path, (char *)temp, *dev_path_size); 1628 xmlFree(temp); 1629 xmlXPathFreeObject(xpathObj); 1630 return (B_TRUE); 1631 } 1632 xmlXPathFreeObject(xpathObj); 1633 fail: 1634 return (B_FALSE); 1635 } 1636 1637 /* ARGSUSED */ 1638 static boolean_t 1639 fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath) { 1640 nvlist_t *detector; 1641 char *path, *scheme; 1642 uint_t size; 1643 1644 if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0) 1645 goto fail; 1646 if (nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0) 1647 goto fail; 1648 1649 if (STRCMP(scheme, FM_FMRI_SCHEME_DEV)) { 1650 if (nvlist_lookup_string(detector, FM_FMRI_DEV_PATH, 1651 &path) != 0) 1652 goto fail; 1653 (void) strncpy(rcpath, path, FM_MAX_CLASS); 1654 } else if (STRCMP(scheme, FM_FMRI_SCHEME_HC)) { 1655 /* 1656 * This should only occur for ereports that come from the RC 1657 * itself. In this case convert HC scheme to dev path. 1658 */ 1659 if (fab_hc2dev(hdl, detector, &path, &size)) { 1660 (void) strncpy(rcpath, path, FM_MAX_CLASS); 1661 fmd_hdl_free(hdl, path, size); 1662 } else { 1663 goto fail; 1664 } 1665 } else { 1666 return (B_FALSE); 1667 } 1668 1669 /* 1670 * Extract the RC path by taking the first device in the dev path 1671 * 1672 * /pci@0,0/pci8086,3605@2/pci8086,3500@0/pci8086,3514@1/pci8086,105e@0 1673 * - to - 1674 * /pci@0,0 1675 */ 1676 path = strchr(rcpath + 1, '/'); 1677 if (path) 1678 path[0] = '\0'; 1679 1680 return (B_TRUE); 1681 fail: 1682 return (B_FALSE); 1683 } 1684 1685 static char * 1686 fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf) { 1687 xmlXPathObjectPtr xpathObj; 1688 xmlNodeSetPtr nodes; 1689 xmlChar *retval; 1690 char query[500]; 1691 int bus, dev, fn; 1692 char rcpath[255]; 1693 1694 if (bdf != (uint16_t)-1) { 1695 bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT; 1696 dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT; 1697 fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT; 1698 } 1699 1700 if (!fab_get_rcpath(hdl, nvl, rcpath)) 1701 goto fail; 1702 1703 /* 1704 * Explanation of the XSL XPATH Query 1705 * Line 1: Look at all nodes with the node name "propval" 1706 * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF 1707 * Line 4-5: See if the "value" of the node ends with correct PCI BDF 1708 * Line 6: Go up one level to the parent of the current node 1709 * Line 7: See if child node contains "ASRU" with the same PCIe Root 1710 * Line 8: Traverse up the parent and the other siblings and look for 1711 * the io "propgroup" and get the value of the dev "propval" 1712 */ 1713 (void) snprintf(query, sizeof (query), "//propval[" 1714 "contains(substring(@value, string-length(@value) - 34), " 1715 "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or " 1716 "contains(substring(@value, string-length(@value) - 28), " 1717 "'pcibus=%d/pcidev=%d/pcifn=%d')" 1718 "]/parent::" 1719 "*/propval[@name='ASRU' and contains(@value, '%s')]" 1720 "/parent::*/following-sibling::*[@name='io']/propval[@name='dev']/" 1721 "@value", bus, dev, fn, bus, dev, fn, rcpath); 1722 1723 fmd_hdl_debug(hdl, "xpathObj query %s\n", query); 1724 1725 xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx); 1726 1727 if (xpathObj == NULL) 1728 goto fail; 1729 1730 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type); 1731 1732 nodes = xpathObj->nodesetval; 1733 if (nodes) { 1734 retval = xmlNodeGetContent(nodes->nodeTab[0]); 1735 fmd_hdl_debug(hdl, "BDF Dev Path: %s\n", retval); 1736 xmlXPathFreeObject(xpathObj); 1737 return ((char *)retval); 1738 } 1739 fail: 1740 return (NULL); 1741 } 1742 1743 static char * 1744 fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr) { 1745 xmlXPathObjectPtr xpathObj; 1746 xmlNodeSetPtr nodes; 1747 xmlNodePtr devNode; 1748 char *retval; 1749 char query[500]; 1750 int size, i, j; 1751 uint32_t prop[50]; 1752 char *token; 1753 pci_regspec_t *assign_p; 1754 uint64_t low, hi; 1755 char rcpath[255]; 1756 1757 if (!fab_get_rcpath(hdl, nvl, rcpath)) 1758 goto fail; 1759 1760 (void) snprintf(query, sizeof (query), "//propval[" 1761 "@name='ASRU' and contains(@value, '%s')]/" 1762 "parent::*/following-sibling::*[@name='pci']/" 1763 "propval[@name='assigned-addresses']", rcpath); 1764 1765 fmd_hdl_debug(hdl, "xpathObj query %s\n", query); 1766 1767 xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx); 1768 1769 if (xpathObj == NULL) 1770 goto fail; 1771 1772 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type); 1773 1774 nodes = xpathObj->nodesetval; 1775 size = (nodes) ? nodes->nodeNr : 0; 1776 1777 /* Decode the list of assigned addresses xml nodes for each device */ 1778 for (i = 0; i < size; i++) { 1779 char *tprop; 1780 1781 devNode = nodes->nodeTab[i]; 1782 if (!HAS_PROP(devNode, "value")) 1783 continue; 1784 1785 /* Convert "string" assigned-addresses to pci_regspec_t */ 1786 j = 0; 1787 tprop = GET_PROP(devNode, "value"); 1788 for (token = strtok(tprop, " "); token; 1789 token = strtok(NULL, " ")) { 1790 prop[j++] = strtoul(token, (char **)NULL, 16); 1791 } 1792 prop[j] = (uint32_t)-1; 1793 FREE_PROP(tprop); 1794 1795 /* Check if address belongs to this device */ 1796 for (assign_p = (pci_regspec_t *)prop; 1797 assign_p->pci_phys_hi != (uint_t)-1; assign_p++) { 1798 low = assign_p->pci_phys_low; 1799 hi = low + assign_p->pci_size_low; 1800 if ((addr < hi) && (addr >= low)) { 1801 fmd_hdl_debug(hdl, "Found Address\n"); 1802 goto found; 1803 } 1804 } 1805 } 1806 goto fail; 1807 1808 found: 1809 /* Traverse up the xml tree and back down to find the right propgroup */ 1810 for (devNode = devNode->parent->parent->children; 1811 devNode; devNode = devNode->next) { 1812 char *tprop; 1813 1814 tprop = GET_PROP(devNode, "name"); 1815 if (STRCMP(devNode->name, "propgroup") && 1816 STRCMP(tprop, "io")) { 1817 FREE_PROP(tprop); 1818 goto propgroup; 1819 } 1820 FREE_PROP(tprop); 1821 } 1822 goto fail; 1823 1824 propgroup: 1825 /* Retrive the "dev" propval and return */ 1826 for (devNode = devNode->children; devNode; devNode = devNode->next) { 1827 char *tprop; 1828 1829 tprop = GET_PROP(devNode, "name"); 1830 if (STRCMP(devNode->name, "propval") && 1831 STRCMP(tprop, "dev")) { 1832 FREE_PROP(tprop); 1833 retval = GET_PROP(devNode, "value"); 1834 fmd_hdl_debug(hdl, "Addr Dev Path: %s\n", retval); 1835 xmlXPathFreeObject(xpathObj); 1836 return (retval); 1837 } 1838 FREE_PROP(tprop); 1839 } 1840 fail: 1841 if (xpathObj != NULL) 1842 xmlXPathFreeObject(xpathObj); 1843 return (NULL); 1844 } 1845 1846 static void 1847 fab_pr(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl) { 1848 nvpair_t *nvp; 1849 1850 for (nvp = nvlist_next_nvpair(nvl, NULL); 1851 nvp != NULL; 1852 nvp = nvlist_next_nvpair(nvl, nvp)) { 1853 1854 data_type_t type = nvpair_type(nvp); 1855 const char *name = nvpair_name(nvp); 1856 1857 boolean_t b; 1858 uint8_t i8; 1859 uint16_t i16; 1860 uint32_t i32; 1861 uint64_t i64; 1862 char *str; 1863 nvlist_t *cnv; 1864 1865 nvlist_t **nvlarr; 1866 uint_t arrsize; 1867 int arri; 1868 1869 1870 if (STRCMP(name, FM_CLASS)) 1871 continue; /* already printed by caller */ 1872 1873 fmd_hdl_debug(hdl, " %s=", name); 1874 1875 switch (type) { 1876 case DATA_TYPE_BOOLEAN: 1877 fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN 1"); 1878 break; 1879 1880 case DATA_TYPE_BOOLEAN_VALUE: 1881 (void) nvpair_value_boolean_value(nvp, &b); 1882 fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN_VALUE %d", 1883 b ? "1" : "0"); 1884 break; 1885 1886 case DATA_TYPE_BYTE: 1887 (void) nvpair_value_byte(nvp, &i8); 1888 fmd_hdl_debug(hdl, "DATA_TYPE_BYTE 0x%x", i8); 1889 break; 1890 1891 case DATA_TYPE_INT8: 1892 (void) nvpair_value_int8(nvp, (void *)&i8); 1893 fmd_hdl_debug(hdl, "DATA_TYPE_INT8 0x%x", i8); 1894 break; 1895 1896 case DATA_TYPE_UINT8: 1897 (void) nvpair_value_uint8(nvp, &i8); 1898 fmd_hdl_debug(hdl, "DATA_TYPE_UINT8 0x%x", i8); 1899 break; 1900 1901 case DATA_TYPE_INT16: 1902 (void) nvpair_value_int16(nvp, (void *)&i16); 1903 fmd_hdl_debug(hdl, "DATA_TYPE_INT16 0x%x", i16); 1904 break; 1905 1906 case DATA_TYPE_UINT16: 1907 (void) nvpair_value_uint16(nvp, &i16); 1908 fmd_hdl_debug(hdl, "DATA_TYPE_UINT16 0x%x", i16); 1909 break; 1910 1911 case DATA_TYPE_INT32: 1912 (void) nvpair_value_int32(nvp, (void *)&i32); 1913 fmd_hdl_debug(hdl, "DATA_TYPE_INT32 0x%x", i32); 1914 break; 1915 1916 case DATA_TYPE_UINT32: 1917 (void) nvpair_value_uint32(nvp, &i32); 1918 fmd_hdl_debug(hdl, "DATA_TYPE_UINT32 0x%x", i32); 1919 break; 1920 1921 case DATA_TYPE_INT64: 1922 (void) nvpair_value_int64(nvp, (void *)&i64); 1923 fmd_hdl_debug(hdl, "DATA_TYPE_INT64 0x%llx", 1924 (u_longlong_t)i64); 1925 break; 1926 1927 case DATA_TYPE_UINT64: 1928 (void) nvpair_value_uint64(nvp, &i64); 1929 fmd_hdl_debug(hdl, "DATA_TYPE_UINT64 0x%llx", 1930 (u_longlong_t)i64); 1931 break; 1932 1933 case DATA_TYPE_HRTIME: 1934 (void) nvpair_value_hrtime(nvp, (void *)&i64); 1935 fmd_hdl_debug(hdl, "DATA_TYPE_HRTIME 0x%llx", 1936 (u_longlong_t)i64); 1937 break; 1938 1939 case DATA_TYPE_STRING: 1940 (void) nvpair_value_string(nvp, &str); 1941 fmd_hdl_debug(hdl, "DATA_TYPE_STRING \"%s\"", 1942 str ? str : "<NULL>"); 1943 break; 1944 1945 case DATA_TYPE_NVLIST: 1946 fmd_hdl_debug(hdl, "["); 1947 (void) nvpair_value_nvlist(nvp, &cnv); 1948 fab_pr(hdl, NULL, cnv); 1949 fmd_hdl_debug(hdl, " ]"); 1950 break; 1951 1952 case DATA_TYPE_BOOLEAN_ARRAY: 1953 case DATA_TYPE_BYTE_ARRAY: 1954 case DATA_TYPE_INT8_ARRAY: 1955 case DATA_TYPE_UINT8_ARRAY: 1956 case DATA_TYPE_INT16_ARRAY: 1957 case DATA_TYPE_UINT16_ARRAY: 1958 case DATA_TYPE_INT32_ARRAY: 1959 case DATA_TYPE_UINT32_ARRAY: 1960 case DATA_TYPE_INT64_ARRAY: 1961 case DATA_TYPE_UINT64_ARRAY: 1962 case DATA_TYPE_STRING_ARRAY: 1963 fmd_hdl_debug(hdl, "[...]"); 1964 break; 1965 case DATA_TYPE_NVLIST_ARRAY: 1966 arrsize = 0; 1967 (void) nvpair_value_nvlist_array(nvp, &nvlarr, 1968 &arrsize); 1969 1970 for (arri = 0; arri < arrsize; arri++) { 1971 fab_pr(hdl, ep, nvlarr[arri]); 1972 } 1973 1974 break; 1975 case DATA_TYPE_UNKNOWN: 1976 fmd_hdl_debug(hdl, "<unknown>"); 1977 break; 1978 } 1979 } 1980 } 1981 1982 /*ARGSUSED*/ 1983 static void 1984 fab_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class) 1985 { 1986 fab_data_t fab_data = {0}; 1987 1988 if (!fab_valid_topo) 1989 fab_update_topo(hdl); 1990 1991 if (fmd_nvl_class_match(hdl, nvl, "ereport.io.pci.fabric")) { 1992 fmd_hdl_debug(hdl, "PCI ereport received: %s\n", class); 1993 fab_pci_fabric_to_data(hdl, nvl, &fab_data); 1994 fab_xlate_pcie_erpts(hdl, &fab_data); 1995 } else { 1996 fab_pr(hdl, ep, nvl); 1997 fmd_hdl_debug(hdl, "Fire RC ereport received: %s\n", class); 1998 fab_fire_to_data(hdl, nvl, &fab_data); 1999 fab_xlate_fire_erpts(hdl, &fab_data, nvl, class); 2000 fab_xlate_pcie_erpts(hdl, &fab_data); 2001 } 2002 } 2003 2004 /* ARGSUSED */ 2005 static void 2006 fab_topo(fmd_hdl_t *hdl, topo_hdl_t *topo) 2007 { 2008 fab_valid_topo = 0; 2009 } 2010 2011 static const fmd_hdl_ops_t fmd_ops = { 2012 fab_recv, /* fmdo_recv */ 2013 NULL, /* fmdo_timeout */ 2014 NULL, /* fmdo_close */ 2015 NULL, /* fmdo_stats */ 2016 NULL, /* fmdo_gc */ 2017 NULL, /* fmdo_send */ 2018 fab_topo, /* fmdo_topo */ 2019 }; 2020 2021 static const fmd_hdl_info_t fmd_info = { 2022 "Fabric Ereport Translater", "1.0", &fmd_ops, NULL 2023 }; 2024 2025 #define REG_OFF(reg) ((uint32_t)(uint32_t)&fab_data.reg - (uint32_t)&fab_data) 2026 #define SET_TBL(n, err, reg, sz) \ 2027 fab_master_err_tbl[n].erpt_tbl = fab_ ## err ## _erpt_tbl; \ 2028 fab_master_err_tbl[n].reg_offset = REG_OFF(reg); \ 2029 fab_master_err_tbl[n].reg_size = sz; \ 2030 fab_master_err_tbl[n].fab_prep = fab_prep_ ## err ## _erpt; 2031 2032 void 2033 _fmd_init(fmd_hdl_t *hdl) 2034 { 2035 fab_data_t fab_data; 2036 2037 if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) 2038 return; 2039 2040 /* Init libxml */ 2041 xmlInitParser(); 2042 2043 fab_fmd_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL); 2044 fmd_hdl_debug(hdl, "Fabric Translater Started\n"); 2045 2046 /* Setup the master error table */ 2047 fab_master_err_tbl = (fab_err_tbl_t *)calloc(13, 2048 sizeof (fab_err_tbl_t)); 2049 2050 SET_TBL(0, pci, pci_err_status, 16); 2051 SET_TBL(1, pci_bdg, pci_bdg_sec_stat, 16); 2052 SET_TBL(2, pci_bdg_ctl, pci_bdg_ctrl, 16); 2053 SET_TBL(3, pcie_ce, pcie_ce_status, 32); 2054 SET_TBL(4, pcie_ue, pcie_ue_status, 32); 2055 SET_TBL(5, pcie_sue, pcie_sue_status, 32); 2056 SET_TBL(6, pcix, pcix_status, 32); 2057 SET_TBL(7, pcix_bdg_sec, pcix_bdg_sec_stat, 16); 2058 SET_TBL(8, pcix_bdg, pcix_bdg_stat, 32); 2059 SET_TBL(9, pcie_nadv, pcie_err_status, 16); 2060 SET_TBL(10, pcie_rc, pcie_rp_err_status, 32); 2061 SET_TBL(11, pcie_fake_rc, pcie_err_status, 16); 2062 } 2063 2064 void 2065 _fmd_fini(fmd_hdl_t *hdl) 2066 { 2067 /* Fini xpath */ 2068 if (fab_xpathCtx) 2069 xmlXPathFreeContext(fab_xpathCtx); 2070 /* Free xml document */ 2071 if (fab_doc) 2072 xmlFreeDoc(fab_doc); 2073 /* Fini libxml */ 2074 xmlCleanupParser(); 2075 2076 fmd_xprt_close(hdl, fab_fmd_xprt); 2077 } 2078