120c794b3Sgavinm /* 220c794b3Sgavinm * CDDL HEADER START 320c794b3Sgavinm * 420c794b3Sgavinm * The contents of this file are subject to the terms of the 520c794b3Sgavinm * Common Development and Distribution License (the "License"). 620c794b3Sgavinm * You may not use this file except in compliance with the License. 720c794b3Sgavinm * 820c794b3Sgavinm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 920c794b3Sgavinm * or http://www.opensolaris.org/os/licensing. 1020c794b3Sgavinm * See the License for the specific language governing permissions 1120c794b3Sgavinm * and limitations under the License. 1220c794b3Sgavinm * 1320c794b3Sgavinm * When distributing Covered Code, include this CDDL HEADER in each 1420c794b3Sgavinm * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1520c794b3Sgavinm * If applicable, add the following below this CDDL HEADER, with the 1620c794b3Sgavinm * fields enclosed by brackets "[]" replaced with your own identifying 1720c794b3Sgavinm * information: Portions Copyright [yyyy] [name of copyright owner] 1820c794b3Sgavinm * 1920c794b3Sgavinm * CDDL HEADER END 2020c794b3Sgavinm */ 2120c794b3Sgavinm 2220c794b3Sgavinm /* 239ff4cbe7SAdrian Frost * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2420c794b3Sgavinm * Use is subject to license terms. 2520c794b3Sgavinm */ 2620c794b3Sgavinm 2720c794b3Sgavinm #include <sys/types.h> 2820c794b3Sgavinm #include <sys/cmn_err.h> 2920c794b3Sgavinm #include <sys/errno.h> 3020c794b3Sgavinm #include <sys/log.h> 3120c794b3Sgavinm #include <sys/systm.h> 3220c794b3Sgavinm #include <sys/modctl.h> 3320c794b3Sgavinm #include <sys/errorq.h> 3420c794b3Sgavinm #include <sys/controlregs.h> 3520c794b3Sgavinm #include <sys/fm/util.h> 3620c794b3Sgavinm #include <sys/fm/protocol.h> 3720c794b3Sgavinm #include <sys/sysevent.h> 3820c794b3Sgavinm #include <sys/pghw.h> 3920c794b3Sgavinm #include <sys/cyclic.h> 4020c794b3Sgavinm #include <sys/pci_cfgspace.h> 4120c794b3Sgavinm #include <sys/mc_intel.h> 4220c794b3Sgavinm #include <sys/smbios.h> 4320c794b3Sgavinm #include "nb5000.h" 4420c794b3Sgavinm #include "nb_log.h" 4520c794b3Sgavinm #include "dimm_phys.h" 4620c794b3Sgavinm 4720c794b3Sgavinm static uint32_t uerrcnt[2]; 485f28a827Saf static uint32_t cerrcnta[2][2]; 495f28a827Saf static uint32_t cerrcntb[2][2]; 505f28a827Saf static uint32_t cerrcntc[2][2]; 515f28a827Saf static uint32_t cerrcntd[2][2]; 5220c794b3Sgavinm static nb_logout_t nb_log; 5320c794b3Sgavinm 5420c794b3Sgavinm struct mch_error_code { 5520c794b3Sgavinm int intel_error_list; /* error number in Chipset Error List */ 5620c794b3Sgavinm uint32_t emask; /* mask for machine check */ 5720c794b3Sgavinm uint32_t error_bit; /* error bit in fault register */ 5820c794b3Sgavinm }; 5920c794b3Sgavinm 6020c794b3Sgavinm static struct mch_error_code fat_fbd_error_code[] = { 6120c794b3Sgavinm { 23, EMASK_FBD_M23, ERR_FAT_FBD_M23 }, 6220c794b3Sgavinm { 3, EMASK_FBD_M3, ERR_FAT_FBD_M3 }, 6320c794b3Sgavinm { 2, EMASK_FBD_M2, ERR_FAT_FBD_M2 }, 6420c794b3Sgavinm { 1, EMASK_FBD_M1, ERR_FAT_FBD_M1 } 6520c794b3Sgavinm }; 6620c794b3Sgavinm 6720c794b3Sgavinm static int 6820c794b3Sgavinm intel_fat_fbd_err(uint32_t fat_fbd) 6920c794b3Sgavinm { 7020c794b3Sgavinm int rt = -1; 7120c794b3Sgavinm int nerr = 0; 7220c794b3Sgavinm uint32_t emask_fbd = 0; 7320c794b3Sgavinm int i; 7420c794b3Sgavinm int sz; 7520c794b3Sgavinm 7620c794b3Sgavinm sz = sizeof (fat_fbd_error_code) / sizeof (struct mch_error_code); 7720c794b3Sgavinm 7820c794b3Sgavinm for (i = 0; i < sz; i++) { 7920c794b3Sgavinm if (fat_fbd & fat_fbd_error_code[i].error_bit) { 8020c794b3Sgavinm rt = fat_fbd_error_code[i].intel_error_list; 8120c794b3Sgavinm emask_fbd |= fat_fbd_error_code[i].emask; 8220c794b3Sgavinm nerr++; 8320c794b3Sgavinm } 8420c794b3Sgavinm } 8520c794b3Sgavinm 8620c794b3Sgavinm if (emask_fbd) 8720c794b3Sgavinm nb_fbd_mask_mc(emask_fbd); 8820c794b3Sgavinm if (nerr > 1) 8920c794b3Sgavinm rt = -1; 9020c794b3Sgavinm return (rt); 9120c794b3Sgavinm } 9220c794b3Sgavinm 9320c794b3Sgavinm static char * 9420c794b3Sgavinm fat_memory_error(const nb_regs_t *rp, void *data) 9520c794b3Sgavinm { 9620c794b3Sgavinm int channel; 9720c794b3Sgavinm uint32_t ferr_fat_fbd, nrecmemb; 985f28a827Saf uint32_t nrecmema; 9920c794b3Sgavinm char *intr = "nb.unknown"; 10020c794b3Sgavinm nb_mem_scatchpad_t *sp = &((nb_scatchpad_t *)data)->ms; 10120c794b3Sgavinm 10220c794b3Sgavinm ferr_fat_fbd = rp->nb.fat_fbd_regs.ferr_fat_fbd; 1036cb1ca52Saf if ((ferr_fat_fbd & ERR_FAT_FBD_MASK) == 0) { 1046cb1ca52Saf sp->intel_error_list = 1056cb1ca52Saf intel_fat_fbd_err(rp->nb.fat_fbd_regs.nerr_fat_fbd); 1066cb1ca52Saf sp->branch = -1; 1076cb1ca52Saf sp->channel = -1; 1086cb1ca52Saf sp->rank = -1; 1096cb1ca52Saf sp->dimm = -1; 1106cb1ca52Saf sp->bank = -1; 1116cb1ca52Saf sp->cas = -1; 1126cb1ca52Saf sp->ras = -1; 1136cb1ca52Saf sp->pa = -1LL; 1146cb1ca52Saf sp->offset = -1; 1156cb1ca52Saf return (intr); 1166cb1ca52Saf } 11720c794b3Sgavinm sp->intel_error_list = intel_fat_fbd_err(ferr_fat_fbd); 11820c794b3Sgavinm channel = (ferr_fat_fbd >> 28) & 3; 11920c794b3Sgavinm sp->branch = channel >> 1; 12020c794b3Sgavinm sp->channel = channel; 12120c794b3Sgavinm if ((ferr_fat_fbd & (ERR_FAT_FBD_M2|ERR_FAT_FBD_M1)) != 0) { 12220c794b3Sgavinm if ((ferr_fat_fbd & ERR_FAT_FBD_M1) != 0) 12320c794b3Sgavinm intr = "nb.fbd.alert"; /* Alert on FB-DIMM M1 */ 12420c794b3Sgavinm else 12520c794b3Sgavinm intr = "nb.fbd.crc"; /* CRC error FB_DIMM M2 */ 12620c794b3Sgavinm nrecmema = rp->nb.fat_fbd_regs.nrecmema; 12720c794b3Sgavinm nrecmemb = rp->nb.fat_fbd_regs.nrecmemb; 12820c794b3Sgavinm sp->rank = (nrecmema >> 8) & RANK_MASK; 12920c794b3Sgavinm sp->dimm = sp->rank >> 1; 13020c794b3Sgavinm sp->bank = (nrecmema >> 12) & BANK_MASK; 13120c794b3Sgavinm sp->cas = (nrecmemb >> 16) & CAS_MASK; 13220c794b3Sgavinm sp->ras = nrecmemb & RAS_MASK; 13320c794b3Sgavinm sp->pa = dimm_getphys(sp->branch, sp->rank, sp->bank, sp->ras, 13420c794b3Sgavinm sp->cas); 13520c794b3Sgavinm sp->offset = dimm_getoffset(sp->branch, sp->rank, sp->bank, 13620c794b3Sgavinm sp->ras, sp->cas); 13720c794b3Sgavinm } else { 13820c794b3Sgavinm if ((ferr_fat_fbd & ERR_FAT_FBD_M3) != 0) 13920c794b3Sgavinm intr = "nb.fbd.otf"; /* thermal temp > Tmid M3 */ 14020c794b3Sgavinm else if ((ferr_fat_fbd & ERR_FAT_FBD_M23) != 0) { 14120c794b3Sgavinm intr = "nb.fbd.reset_timeout"; 14220c794b3Sgavinm sp->channel = -1; 14320c794b3Sgavinm } 14420c794b3Sgavinm sp->rank = -1; 14520c794b3Sgavinm sp->dimm = -1; 14620c794b3Sgavinm sp->bank = -1; 14720c794b3Sgavinm sp->cas = -1; 14820c794b3Sgavinm sp->ras = -1; 14920c794b3Sgavinm sp->pa = -1LL; 15020c794b3Sgavinm sp->offset = -1; 15120c794b3Sgavinm } 15220c794b3Sgavinm return (intr); 15320c794b3Sgavinm } 15420c794b3Sgavinm 15520c794b3Sgavinm 15620c794b3Sgavinm static struct mch_error_code nf_fbd_error_code[] = { 1575f28a827Saf { 29, EMASK_FBD_M29, ERR_NF_FBD_M29 }, 15820c794b3Sgavinm { 28, EMASK_FBD_M28, ERR_NF_FBD_M28 }, 15920c794b3Sgavinm { 27, EMASK_FBD_M27, ERR_NF_FBD_M27 }, 16020c794b3Sgavinm { 26, EMASK_FBD_M26, ERR_NF_FBD_M26 }, 16120c794b3Sgavinm { 25, EMASK_FBD_M25, ERR_NF_FBD_M25 }, 1625f28a827Saf { 24, EMASK_FBD_M24, ERR_NF_FBD_M24 }, 16320c794b3Sgavinm { 22, EMASK_FBD_M22, ERR_NF_FBD_M22 }, 16420c794b3Sgavinm { 21, EMASK_FBD_M21, ERR_NF_FBD_M21 }, 16520c794b3Sgavinm { 20, EMASK_FBD_M20, ERR_NF_FBD_M20 }, 16620c794b3Sgavinm { 19, EMASK_FBD_M19, ERR_NF_FBD_M19 }, 16720c794b3Sgavinm { 18, EMASK_FBD_M18, ERR_NF_FBD_M18 }, 16820c794b3Sgavinm { 17, EMASK_FBD_M17, ERR_NF_FBD_M17 }, 1695f28a827Saf { 16, EMASK_FBD_M16, ERR_NF_FBD_M16 }, 17020c794b3Sgavinm { 15, EMASK_FBD_M15, ERR_NF_FBD_M15 }, 17120c794b3Sgavinm { 14, EMASK_FBD_M14, ERR_NF_FBD_M14 }, 17220c794b3Sgavinm { 13, EMASK_FBD_M13, ERR_NF_FBD_M13 }, 17320c794b3Sgavinm { 12, EMASK_FBD_M12, ERR_NF_FBD_M12 }, 17420c794b3Sgavinm { 11, EMASK_FBD_M11, ERR_NF_FBD_M11 }, 17520c794b3Sgavinm { 10, EMASK_FBD_M10, ERR_NF_FBD_M10 }, 17620c794b3Sgavinm { 9, EMASK_FBD_M9, ERR_NF_FBD_M9 }, 17720c794b3Sgavinm { 8, EMASK_FBD_M8, ERR_NF_FBD_M8 }, 17820c794b3Sgavinm { 7, EMASK_FBD_M7, ERR_NF_FBD_M7 }, 17920c794b3Sgavinm { 6, EMASK_FBD_M6, ERR_NF_FBD_M6 }, 18020c794b3Sgavinm { 5, EMASK_FBD_M5, ERR_NF_FBD_M5 }, 18120c794b3Sgavinm { 4, EMASK_FBD_M4, ERR_NF_FBD_M4 } 18220c794b3Sgavinm }; 18320c794b3Sgavinm 18420c794b3Sgavinm static int 18520c794b3Sgavinm intel_nf_fbd_err(uint32_t nf_fbd) 18620c794b3Sgavinm { 18720c794b3Sgavinm int rt = -1; 18820c794b3Sgavinm int nerr = 0; 18920c794b3Sgavinm uint32_t emask_fbd = 0; 19020c794b3Sgavinm int i; 19120c794b3Sgavinm int sz; 19220c794b3Sgavinm 19320c794b3Sgavinm sz = sizeof (nf_fbd_error_code) / sizeof (struct mch_error_code); 19420c794b3Sgavinm 19520c794b3Sgavinm for (i = 0; i < sz; i++) { 19620c794b3Sgavinm if (nf_fbd & nf_fbd_error_code[i].error_bit) { 19720c794b3Sgavinm rt = nf_fbd_error_code[i].intel_error_list; 19820c794b3Sgavinm emask_fbd |= nf_fbd_error_code[i].emask; 19920c794b3Sgavinm nerr++; 20020c794b3Sgavinm } 20120c794b3Sgavinm } 20220c794b3Sgavinm if (emask_fbd) 20320c794b3Sgavinm nb_fbd_mask_mc(emask_fbd); 20420c794b3Sgavinm if (nerr > 1) 20520c794b3Sgavinm rt = -1; 20620c794b3Sgavinm return (rt); 20720c794b3Sgavinm } 20820c794b3Sgavinm 20920c794b3Sgavinm static char * 21020c794b3Sgavinm nf_memory_error(const nb_regs_t *rp, void *data) 21120c794b3Sgavinm { 21220c794b3Sgavinm uint32_t ferr_nf_fbd, recmemb, redmemb; 2135f28a827Saf uint32_t recmema; 21420c794b3Sgavinm int branch, channel, ecc_locator; 21520c794b3Sgavinm char *intr = "nb.unknown"; 21620c794b3Sgavinm nb_mem_scatchpad_t *sp = &((nb_scatchpad_t *)data)->ms; 21720c794b3Sgavinm 21820c794b3Sgavinm sp->rank = -1; 21920c794b3Sgavinm sp->dimm = -1; 22020c794b3Sgavinm sp->bank = -1; 22120c794b3Sgavinm sp->cas = -1; 22220c794b3Sgavinm sp->ras = -1LL; 22320c794b3Sgavinm sp->pa = -1LL; 22420c794b3Sgavinm sp->offset = -1; 2256cb1ca52Saf ferr_nf_fbd = rp->nb.nf_fbd_regs.ferr_nf_fbd; 2266cb1ca52Saf if ((ferr_nf_fbd & ERR_NF_FBD_MASK) == 0) { 2276cb1ca52Saf sp->branch = -1; 2286cb1ca52Saf sp->channel = -1; 2296cb1ca52Saf sp->intel_error_list = 2306cb1ca52Saf intel_nf_fbd_err(rp->nb.nf_fbd_regs.nerr_nf_fbd); 2316cb1ca52Saf return (intr); 2326cb1ca52Saf } 2336cb1ca52Saf sp->intel_error_list = intel_nf_fbd_err(ferr_nf_fbd); 2346cb1ca52Saf channel = (ferr_nf_fbd >> ERR_FBD_CH_SHIFT) & 3; 2356cb1ca52Saf branch = channel >> 1; 2366cb1ca52Saf sp->branch = branch; 2376cb1ca52Saf sp->channel = channel; 23820c794b3Sgavinm if (ferr_nf_fbd & ERR_NF_FBD_MASK) { 23920c794b3Sgavinm if (ferr_nf_fbd & ERR_NF_FBD_ECC_UE) { 24020c794b3Sgavinm /* 24120c794b3Sgavinm * uncorrectable ECC M4 - M12 24220c794b3Sgavinm * we can only isolate to pair of dimms 24320c794b3Sgavinm * for single dimm configuration let eversholt 24420c794b3Sgavinm * sort it out with out needing a special rule 24520c794b3Sgavinm */ 24620c794b3Sgavinm sp->channel = -1; 24720c794b3Sgavinm recmema = rp->nb.nf_fbd_regs.recmema; 24820c794b3Sgavinm recmemb = rp->nb.nf_fbd_regs.recmemb; 24920c794b3Sgavinm sp->rank = (recmema >> 8) & RANK_MASK; 25020c794b3Sgavinm sp->bank = (recmema >> 12) & BANK_MASK; 25120c794b3Sgavinm sp->cas = (recmemb >> 16) & CAS_MASK; 25220c794b3Sgavinm sp->ras = recmemb & RAS_MASK; 25320c794b3Sgavinm intr = "nb.mem_ue"; 25420c794b3Sgavinm } else if (ferr_nf_fbd & ERR_NF_FBD_M13) { 25520c794b3Sgavinm /* 25620c794b3Sgavinm * write error M13 25720c794b3Sgavinm * we can only isolate to pair of dimms 25820c794b3Sgavinm */ 25920c794b3Sgavinm sp->channel = -1; 26020c794b3Sgavinm if (nb_mode != NB_MEMORY_MIRROR) { 26120c794b3Sgavinm recmema = rp->nb.nf_fbd_regs.recmema; 26220c794b3Sgavinm sp->rank = (recmema >> 8) & RANK_MASK; 26320c794b3Sgavinm sp->bank = (recmema >> 12) & BANK_MASK; 26420c794b3Sgavinm sp->cas = (recmemb >> 16) & CAS_MASK; 26520c794b3Sgavinm sp->ras = recmemb & RAS_MASK; 26620c794b3Sgavinm } 26720c794b3Sgavinm intr = "nb.fbd.ma"; /* memory alert */ 26820c794b3Sgavinm } else if (ferr_nf_fbd & ERR_NF_FBD_MA) { /* M14, M15 and M21 */ 26920c794b3Sgavinm intr = "nb.fbd.ch"; /* FBD on channel */ 27020c794b3Sgavinm } else if ((ferr_nf_fbd & ERR_NF_FBD_ECC_CE) != 0) { 27120c794b3Sgavinm /* correctable ECC M17-M20 */ 27220c794b3Sgavinm recmema = rp->nb.nf_fbd_regs.recmema; 27320c794b3Sgavinm recmemb = rp->nb.nf_fbd_regs.recmemb; 27420c794b3Sgavinm sp->rank = (recmema >> 8) & RANK_MASK; 27520c794b3Sgavinm redmemb = rp->nb.nf_fbd_regs.redmemb; 27620c794b3Sgavinm ecc_locator = redmemb & 0x3ffff; 27720c794b3Sgavinm if (ecc_locator & 0x1ff) 27820c794b3Sgavinm sp->channel = branch << 1; 27920c794b3Sgavinm else if (ecc_locator & 0x3fe00) 28020c794b3Sgavinm sp->channel = (branch << 1) + 1; 28120c794b3Sgavinm sp->dimm = sp->rank >> 1; 28220c794b3Sgavinm sp->bank = (recmema >> 12) & BANK_MASK; 28320c794b3Sgavinm sp->cas = (recmemb >> 16) & CAS_MASK; 28420c794b3Sgavinm sp->ras = recmemb & RAS_MASK; 28520c794b3Sgavinm intr = "nb.mem_ce"; 28620c794b3Sgavinm } else if ((ferr_nf_fbd & ERR_NF_FBD_SPARE) != 0) { 28720c794b3Sgavinm /* spare dimm M27, M28 */ 28820c794b3Sgavinm intr = "nb.mem_ds"; 28920c794b3Sgavinm sp->channel = -1; 29020c794b3Sgavinm if (rp->nb.nf_fbd_regs.spcps & SPCPS_SPARE_DEPLOYED) { 29120c794b3Sgavinm sp->rank = 29220c794b3Sgavinm SPCPS_FAILED_RANK(rp->nb.nf_fbd_regs.spcps); 29320c794b3Sgavinm nb_used_spare_rank(sp->branch, sp->rank); 29420c794b3Sgavinm nb_config_gen++; 29520c794b3Sgavinm } 2965f28a827Saf } else if ((ferr_nf_fbd & ERR_NF_FBD_M22) != 0) { 2975f28a827Saf intr = "nb.spd"; /* SPD protocol */ 29820c794b3Sgavinm } 29920c794b3Sgavinm } 30020c794b3Sgavinm if (sp->ras != -1) { 30120c794b3Sgavinm sp->pa = dimm_getphys(sp->branch, sp->rank, sp->bank, sp->ras, 30220c794b3Sgavinm sp->cas); 30320c794b3Sgavinm sp->offset = dimm_getoffset(sp->branch, sp->rank, sp->bank, 30420c794b3Sgavinm sp->ras, sp->cas); 30520c794b3Sgavinm } 30620c794b3Sgavinm return (intr); 30720c794b3Sgavinm } 30820c794b3Sgavinm 30920c794b3Sgavinm static struct mch_error_code fat_int_error_code[] = { 3105f28a827Saf { 14, EMASK_INT_B14, ERR_FAT_INT_B14 }, 3115f28a827Saf { 12, EMASK_INT_B12, ERR_FAT_INT_B12 }, 3125f28a827Saf { 25, EMASK_INT_B25, ERR_FAT_INT_B25 }, 3135f28a827Saf { 23, EMASK_INT_B23, ERR_FAT_INT_B23 }, 3145f28a827Saf { 21, EMASK_INT_B21, ERR_FAT_INT_B21 }, 3156cb1ca52Saf { 7, EMASK_INT_B7, ERR_FAT_INT_B7 }, 31620c794b3Sgavinm { 4, EMASK_INT_B4, ERR_FAT_INT_B4 }, 31720c794b3Sgavinm { 3, EMASK_INT_B3, ERR_FAT_INT_B3 }, 31820c794b3Sgavinm { 2, EMASK_INT_B2, ERR_FAT_INT_B2 }, 31920c794b3Sgavinm { 1, EMASK_INT_B1, ERR_FAT_INT_B1 } 32020c794b3Sgavinm }; 32120c794b3Sgavinm 32220c794b3Sgavinm static struct mch_error_code nf_int_error_code[] = { 3235f28a827Saf { 27, 0, ERR_NF_INT_B27 }, 3245f28a827Saf { 24, 0, ERR_NF_INT_B24 }, 3255f28a827Saf { 22, EMASK_INT_B22, ERR_NF_INT_B22 }, 3265f28a827Saf { 20, EMASK_INT_B20, ERR_NF_INT_B20 }, 3275f28a827Saf { 19, EMASK_INT_B19, ERR_NF_INT_B19 }, 3285f28a827Saf { 18, 0, ERR_NF_INT_B18 }, 3295f28a827Saf { 17, 0, ERR_NF_INT_B17 }, 3305f28a827Saf { 16, 0, ERR_NF_INT_B16 }, 3315f28a827Saf { 11, EMASK_INT_B11, ERR_NF_INT_B11 }, 3325f28a827Saf { 10, EMASK_INT_B10, ERR_NF_INT_B10 }, 3335f28a827Saf { 9, EMASK_INT_B9, ERR_NF_INT_B9 }, 3346cb1ca52Saf { 8, EMASK_INT_B8, ERR_NF_INT_B8 }, 33520c794b3Sgavinm { 6, EMASK_INT_B6, ERR_NF_INT_B6 }, 33620c794b3Sgavinm { 5, EMASK_INT_B5, ERR_NF_INT_B5 } 33720c794b3Sgavinm }; 33820c794b3Sgavinm 33920c794b3Sgavinm static int 3405f28a827Saf intel_int_err(uint16_t err_fat_int, uint16_t err_nf_int) 34120c794b3Sgavinm { 34220c794b3Sgavinm int rt = -1; 34320c794b3Sgavinm int nerr = 0; 3445f28a827Saf uint32_t emask_int = 0; 34520c794b3Sgavinm int i; 34620c794b3Sgavinm int sz; 34720c794b3Sgavinm 34820c794b3Sgavinm sz = sizeof (fat_int_error_code) / sizeof (struct mch_error_code); 34920c794b3Sgavinm 35020c794b3Sgavinm for (i = 0; i < sz; i++) { 3516cb1ca52Saf if (err_fat_int & fat_int_error_code[i].error_bit) { 35220c794b3Sgavinm rt = fat_int_error_code[i].intel_error_list; 35320c794b3Sgavinm emask_int |= fat_int_error_code[i].emask; 35420c794b3Sgavinm nerr++; 35520c794b3Sgavinm } 35620c794b3Sgavinm } 35720c794b3Sgavinm 3585f28a827Saf if (nb_chipset == INTEL_NB_5400 && 3595f28a827Saf (err_nf_int & NERR_NF_5400_INT_B26) != 0) { 3605f28a827Saf err_nf_int &= ~NERR_NF_5400_INT_B26; 3615f28a827Saf rt = 26; 3625f28a827Saf nerr++; 3635f28a827Saf } 3645f28a827Saf 3659ff4cbe7SAdrian Frost if (rt) 3669ff4cbe7SAdrian Frost err_nf_int &= ~ERR_NF_INT_B18; 3679ff4cbe7SAdrian Frost 36820c794b3Sgavinm sz = sizeof (nf_int_error_code) / sizeof (struct mch_error_code); 36920c794b3Sgavinm 37020c794b3Sgavinm for (i = 0; i < sz; i++) { 3716cb1ca52Saf if (err_nf_int & nf_int_error_code[i].error_bit) { 37220c794b3Sgavinm rt = nf_int_error_code[i].intel_error_list; 37320c794b3Sgavinm emask_int |= nf_int_error_code[i].emask; 37420c794b3Sgavinm nerr++; 37520c794b3Sgavinm } 37620c794b3Sgavinm } 37720c794b3Sgavinm 37820c794b3Sgavinm if (emask_int) 37920c794b3Sgavinm nb_int_mask_mc(emask_int); 38020c794b3Sgavinm if (nerr > 1) 38120c794b3Sgavinm rt = -1; 38220c794b3Sgavinm return (rt); 38320c794b3Sgavinm } 38420c794b3Sgavinm 3859ff4cbe7SAdrian Frost static int 3860ad0f0b2SAdrian Frost log_int_err(nb_regs_t *rp, int willpanic, int *interpose) 38720c794b3Sgavinm { 38820c794b3Sgavinm int t = 0; 3899ff4cbe7SAdrian Frost int rt = 0; 39020c794b3Sgavinm 39120c794b3Sgavinm rp->flag = NB_REG_LOG_INT; 39220c794b3Sgavinm rp->nb.int_regs.ferr_fat_int = FERR_FAT_INT_RD(interpose); 39320c794b3Sgavinm rp->nb.int_regs.ferr_nf_int = FERR_NF_INT_RD(&t); 39420c794b3Sgavinm *interpose |= t; 39520c794b3Sgavinm rp->nb.int_regs.nerr_fat_int = NERR_FAT_INT_RD(&t); 39620c794b3Sgavinm *interpose |= t; 39720c794b3Sgavinm rp->nb.int_regs.nerr_nf_int = NERR_NF_INT_RD(&t); 39820c794b3Sgavinm *interpose |= t; 39920c794b3Sgavinm rp->nb.int_regs.nrecint = NRECINT_RD(); 40020c794b3Sgavinm rp->nb.int_regs.recint = RECINT_RD(); 40120c794b3Sgavinm rp->nb.int_regs.nrecsf = NRECSF_RD(); 40220c794b3Sgavinm rp->nb.int_regs.recsf = RECSF_RD(); 40320c794b3Sgavinm 4040ad0f0b2SAdrian Frost if (!willpanic) { 4050ad0f0b2SAdrian Frost if (rp->nb.int_regs.ferr_fat_int || *interpose) 4060ad0f0b2SAdrian Frost FERR_FAT_INT_WR(rp->nb.int_regs.ferr_fat_int); 4070ad0f0b2SAdrian Frost if (rp->nb.int_regs.ferr_nf_int || *interpose) 4080ad0f0b2SAdrian Frost FERR_NF_INT_WR(rp->nb.int_regs.ferr_nf_int); 4090ad0f0b2SAdrian Frost if (rp->nb.int_regs.nerr_fat_int) 4100ad0f0b2SAdrian Frost NERR_FAT_INT_WR(rp->nb.int_regs.nerr_fat_int); 4110ad0f0b2SAdrian Frost if (rp->nb.int_regs.nerr_nf_int) 4120ad0f0b2SAdrian Frost NERR_NF_INT_WR(rp->nb.int_regs.nerr_nf_int); 4130ad0f0b2SAdrian Frost /* 4140ad0f0b2SAdrian Frost * if interpose write read-only registers to clear from pcii 4150ad0f0b2SAdrian Frost * cache 4160ad0f0b2SAdrian Frost */ 4170ad0f0b2SAdrian Frost if (*interpose) { 4180ad0f0b2SAdrian Frost NRECINT_WR(); 4190ad0f0b2SAdrian Frost RECINT_WR(); 4200ad0f0b2SAdrian Frost NRECSF_WR(); 4210ad0f0b2SAdrian Frost RECSF_WR(); 4220ad0f0b2SAdrian Frost } 42320c794b3Sgavinm } 4249ff4cbe7SAdrian Frost if (rp->nb.int_regs.ferr_fat_int == 0 && 4259ff4cbe7SAdrian Frost rp->nb.int_regs.nerr_fat_int == 0 && 4269ff4cbe7SAdrian Frost (rp->nb.int_regs.ferr_nf_int == ERR_NF_INT_B18 || 4279ff4cbe7SAdrian Frost (rp->nb.int_regs.ferr_nf_int == 0 && 4289ff4cbe7SAdrian Frost rp->nb.int_regs.nerr_nf_int == ERR_NF_INT_B18))) { 4299ff4cbe7SAdrian Frost rt = 1; 4309ff4cbe7SAdrian Frost } 4319ff4cbe7SAdrian Frost return (rt); 43220c794b3Sgavinm } 43320c794b3Sgavinm 4345f28a827Saf static void 4350ad0f0b2SAdrian Frost log_thermal_err(nb_regs_t *rp, int willpanic, int *interpose) 4365f28a827Saf { 4375f28a827Saf int t = 0; 4385f28a827Saf 4395f28a827Saf rp->flag = NB_REG_LOG_THR; 4405f28a827Saf rp->nb.thr_regs.ferr_fat_thr = FERR_FAT_THR_RD(interpose); 4415f28a827Saf rp->nb.thr_regs.nerr_fat_thr = NERR_FAT_THR_RD(&t); 4425f28a827Saf *interpose |= t; 4435f28a827Saf rp->nb.thr_regs.ferr_nf_thr = FERR_NF_THR_RD(&t); 4445f28a827Saf *interpose |= t; 4455f28a827Saf rp->nb.thr_regs.nerr_nf_thr = NERR_NF_THR_RD(&t); 4465f28a827Saf *interpose |= t; 4475f28a827Saf rp->nb.thr_regs.ctsts = CTSTS_RD(); 4485f28a827Saf rp->nb.thr_regs.thrtsts = THRTSTS_RD(); 4495f28a827Saf 4500ad0f0b2SAdrian Frost if (!willpanic) { 4510ad0f0b2SAdrian Frost if (rp->nb.thr_regs.ferr_fat_thr || *interpose) 4520ad0f0b2SAdrian Frost FERR_FAT_THR_WR(rp->nb.thr_regs.ferr_fat_thr); 4530ad0f0b2SAdrian Frost if (rp->nb.thr_regs.nerr_fat_thr || *interpose) 4540ad0f0b2SAdrian Frost NERR_FAT_THR_WR(rp->nb.thr_regs.nerr_fat_thr); 4550ad0f0b2SAdrian Frost if (rp->nb.thr_regs.ferr_nf_thr || *interpose) 4560ad0f0b2SAdrian Frost FERR_NF_THR_WR(rp->nb.thr_regs.ferr_nf_thr); 4570ad0f0b2SAdrian Frost if (rp->nb.thr_regs.nerr_nf_thr || *interpose) 4580ad0f0b2SAdrian Frost NERR_NF_THR_WR(rp->nb.thr_regs.nerr_nf_thr); 4590ad0f0b2SAdrian Frost 4600ad0f0b2SAdrian Frost if (*interpose) { 4610ad0f0b2SAdrian Frost CTSTS_WR(rp->nb.thr_regs.ctsts); 4620ad0f0b2SAdrian Frost THRTSTS_WR(rp->nb.thr_regs.thrtsts); 4630ad0f0b2SAdrian Frost } 4645f28a827Saf } 4655f28a827Saf } 4665f28a827Saf 46720c794b3Sgavinm static void 46820c794b3Sgavinm log_dma_err(nb_regs_t *rp, int *interpose) 46920c794b3Sgavinm { 47020c794b3Sgavinm rp->flag = NB_REG_LOG_DMA; 47120c794b3Sgavinm 47220c794b3Sgavinm rp->nb.dma_regs.pcists = PCISTS_RD(interpose); 47320c794b3Sgavinm rp->nb.dma_regs.pexdevsts = PCIDEVSTS_RD(); 47420c794b3Sgavinm } 47520c794b3Sgavinm 4766cb1ca52Saf static struct mch_error_code fat_fsb_error_code[] = { 4776cb1ca52Saf { 9, EMASK_FSB_F9, ERR_FAT_FSB_F9 }, 4786cb1ca52Saf { 2, EMASK_FSB_F2, ERR_FAT_FSB_F2 }, 4796cb1ca52Saf { 1, EMASK_FSB_F1, ERR_FAT_FSB_F1 } 4806cb1ca52Saf }; 4816cb1ca52Saf 4826cb1ca52Saf static struct mch_error_code nf_fsb_error_code[] = { 4836cb1ca52Saf { 8, EMASK_FSB_F8, ERR_NF_FSB_F8 }, 4846cb1ca52Saf { 7, EMASK_FSB_F7, ERR_NF_FSB_F7 }, 4856cb1ca52Saf { 6, EMASK_FSB_F6, ERR_NF_FSB_F6 } 4866cb1ca52Saf }; 4876cb1ca52Saf 48820c794b3Sgavinm static int 4896cb1ca52Saf intel_fsb_err(int fsb, uint8_t err_fat_fsb, uint8_t err_nf_fsb) 49020c794b3Sgavinm { 49120c794b3Sgavinm int rt = -1; 49220c794b3Sgavinm int nerr = 0; 49320c794b3Sgavinm uint16_t emask_fsb = 0; 4946cb1ca52Saf int i; 4956cb1ca52Saf int sz; 49620c794b3Sgavinm 4976cb1ca52Saf sz = sizeof (fat_fsb_error_code) / sizeof (struct mch_error_code); 4986cb1ca52Saf 4996cb1ca52Saf for (i = 0; i < sz; i++) { 5006cb1ca52Saf if (err_fat_fsb & fat_fsb_error_code[i].error_bit) { 5016cb1ca52Saf rt = fat_fsb_error_code[i].intel_error_list; 5026cb1ca52Saf emask_fsb |= fat_fsb_error_code[i].emask; 5036cb1ca52Saf nerr++; 5046cb1ca52Saf } 50520c794b3Sgavinm } 5066cb1ca52Saf 5076cb1ca52Saf sz = sizeof (nf_fsb_error_code) / sizeof (struct mch_error_code); 5086cb1ca52Saf 5096cb1ca52Saf for (i = 0; i < sz; i++) { 5106cb1ca52Saf if (err_nf_fsb & nf_fsb_error_code[i].error_bit) { 5116cb1ca52Saf rt = nf_fsb_error_code[i].intel_error_list; 5126cb1ca52Saf emask_fsb |= nf_fsb_error_code[i].emask; 5136cb1ca52Saf nerr++; 5146cb1ca52Saf } 51520c794b3Sgavinm } 5166cb1ca52Saf 51720c794b3Sgavinm if (emask_fsb) 51820c794b3Sgavinm nb_fsb_mask_mc(fsb, emask_fsb); 51920c794b3Sgavinm if (nerr > 1) 52020c794b3Sgavinm rt = -1; 52120c794b3Sgavinm return (rt); 52220c794b3Sgavinm } 52320c794b3Sgavinm 52420c794b3Sgavinm static void 5250ad0f0b2SAdrian Frost log_fsb_err(uint64_t ferr, nb_regs_t *rp, int willpanic, int *interpose) 52620c794b3Sgavinm { 52720c794b3Sgavinm uint8_t fsb; 52820c794b3Sgavinm int t = 0; 52920c794b3Sgavinm 53020c794b3Sgavinm fsb = GE_FERR_FSB(ferr); 53120c794b3Sgavinm rp->flag = NB_REG_LOG_FSB; 53220c794b3Sgavinm 53320c794b3Sgavinm rp->nb.fsb_regs.fsb = fsb; 53420c794b3Sgavinm rp->nb.fsb_regs.ferr_fat_fsb = FERR_FAT_FSB_RD(fsb, interpose); 53520c794b3Sgavinm rp->nb.fsb_regs.ferr_nf_fsb = FERR_NF_FSB_RD(fsb, &t); 53620c794b3Sgavinm *interpose |= t; 53720c794b3Sgavinm rp->nb.fsb_regs.nerr_fat_fsb = NERR_FAT_FSB_RD(fsb, &t); 53820c794b3Sgavinm *interpose |= t; 53920c794b3Sgavinm rp->nb.fsb_regs.nerr_nf_fsb = NERR_NF_FSB_RD(fsb, &t); 54020c794b3Sgavinm *interpose |= t; 54120c794b3Sgavinm rp->nb.fsb_regs.nrecfsb = NRECFSB_RD(fsb); 54220c794b3Sgavinm rp->nb.fsb_regs.nrecfsb_addr = NRECADDR_RD(fsb); 54320c794b3Sgavinm rp->nb.fsb_regs.recfsb = RECFSB_RD(fsb); 5440ad0f0b2SAdrian Frost if (!willpanic) { 545*2d532312SVuong Nguyen /* Clear the fatal/non-fatal first/next FSB errors */ 5460ad0f0b2SAdrian Frost if (rp->nb.fsb_regs.ferr_fat_fsb || *interpose) 5470ad0f0b2SAdrian Frost FERR_FAT_FSB_WR(fsb, rp->nb.fsb_regs.ferr_fat_fsb); 5480ad0f0b2SAdrian Frost if (rp->nb.fsb_regs.ferr_nf_fsb || *interpose) 5490ad0f0b2SAdrian Frost FERR_NF_FSB_WR(fsb, rp->nb.fsb_regs.ferr_nf_fsb); 550*2d532312SVuong Nguyen if (rp->nb.fsb_regs.nerr_fat_fsb || *interpose) 551*2d532312SVuong Nguyen NERR_FAT_FSB_WR(fsb, rp->nb.fsb_regs.nerr_fat_fsb); 552*2d532312SVuong Nguyen if (rp->nb.fsb_regs.nerr_nf_fsb || *interpose) 553*2d532312SVuong Nguyen NERR_NF_FSB_WR(fsb, rp->nb.fsb_regs.nerr_nf_fsb); 554*2d532312SVuong Nguyen 5550ad0f0b2SAdrian Frost /* 5560ad0f0b2SAdrian Frost * if interpose write read-only registers to clear from pcii 5570ad0f0b2SAdrian Frost * cache 5580ad0f0b2SAdrian Frost */ 5590ad0f0b2SAdrian Frost if (*interpose) { 5600ad0f0b2SAdrian Frost NRECFSB_WR(fsb); 5610ad0f0b2SAdrian Frost NRECADDR_WR(fsb); 5620ad0f0b2SAdrian Frost RECFSB_WR(fsb); 5630ad0f0b2SAdrian Frost } 56420c794b3Sgavinm } 56520c794b3Sgavinm } 56620c794b3Sgavinm 56720c794b3Sgavinm static struct mch_error_code fat_pex_error_code[] = { 56820c794b3Sgavinm { 19, EMASK_UNCOR_PEX_IO19, PEX_FAT_IO19 }, 56920c794b3Sgavinm { 18, EMASK_UNCOR_PEX_IO18, PEX_FAT_IO18 }, 57020c794b3Sgavinm { 10, EMASK_UNCOR_PEX_IO10, PEX_FAT_IO10 }, 57120c794b3Sgavinm { 9, EMASK_UNCOR_PEX_IO9, PEX_FAT_IO9 }, 57220c794b3Sgavinm { 8, EMASK_UNCOR_PEX_IO8, PEX_FAT_IO8 }, 57320c794b3Sgavinm { 7, EMASK_UNCOR_PEX_IO7, PEX_FAT_IO7 }, 57420c794b3Sgavinm { 6, EMASK_UNCOR_PEX_IO6, PEX_FAT_IO6 }, 57520c794b3Sgavinm { 5, EMASK_UNCOR_PEX_IO5, PEX_FAT_IO5 }, 57620c794b3Sgavinm { 4, EMASK_UNCOR_PEX_IO4, PEX_FAT_IO4 }, 57720c794b3Sgavinm { 3, EMASK_UNCOR_PEX_IO3, PEX_FAT_IO3 }, 57820c794b3Sgavinm { 2, EMASK_UNCOR_PEX_IO2, PEX_FAT_IO2 }, 57920c794b3Sgavinm { 0, EMASK_UNCOR_PEX_IO0, PEX_FAT_IO0 } 58020c794b3Sgavinm }; 58120c794b3Sgavinm 5825f28a827Saf static struct mch_error_code fat_unit_pex_5400_error_code[] = { 5835f28a827Saf { 32, EMASK_UNIT_PEX_IO32, PEX_5400_FAT_IO32 }, 5845f28a827Saf { 31, EMASK_UNIT_PEX_IO31, PEX_5400_FAT_IO31 }, 5855f28a827Saf { 30, EMASK_UNIT_PEX_IO30, PEX_5400_FAT_IO30 }, 5865f28a827Saf { 29, EMASK_UNIT_PEX_IO29, PEX_5400_FAT_IO29 }, 5875f28a827Saf { 27, EMASK_UNIT_PEX_IO27, PEX_5400_FAT_IO27 }, 5885f28a827Saf { 26, EMASK_UNIT_PEX_IO26, PEX_5400_FAT_IO26 }, 5895f28a827Saf { 25, EMASK_UNIT_PEX_IO25, PEX_5400_FAT_IO25 }, 5905f28a827Saf { 24, EMASK_UNIT_PEX_IO24, PEX_5400_FAT_IO24 }, 5915f28a827Saf { 23, EMASK_UNIT_PEX_IO23, PEX_5400_FAT_IO23 }, 5925f28a827Saf { 22, EMASK_UNIT_PEX_IO22, PEX_5400_FAT_IO22 }, 5935f28a827Saf }; 5945f28a827Saf 5955f28a827Saf static struct mch_error_code fat_pex_5400_error_code[] = { 5965f28a827Saf { 19, EMASK_UNCOR_PEX_IO19, PEX_5400_FAT_IO19 }, 5975f28a827Saf { 18, EMASK_UNCOR_PEX_IO18, PEX_5400_FAT_IO18 }, 5985f28a827Saf { 10, EMASK_UNCOR_PEX_IO10, PEX_5400_FAT_IO10 }, 5995f28a827Saf { 9, EMASK_UNCOR_PEX_IO9, PEX_5400_FAT_IO9 }, 6005f28a827Saf { 8, EMASK_UNCOR_PEX_IO8, PEX_5400_FAT_IO8 }, 6015f28a827Saf { 7, EMASK_UNCOR_PEX_IO7, PEX_5400_FAT_IO7 }, 6025f28a827Saf { 6, EMASK_UNCOR_PEX_IO6, PEX_5400_FAT_IO6 }, 6035f28a827Saf { 5, EMASK_UNCOR_PEX_IO5, PEX_5400_FAT_IO5 }, 6045f28a827Saf { 4, EMASK_UNCOR_PEX_IO4, PEX_5400_FAT_IO4 }, 6055f28a827Saf { 2, EMASK_UNCOR_PEX_IO2, PEX_5400_FAT_IO2 }, 6065f28a827Saf { 0, EMASK_UNCOR_PEX_IO0, PEX_5400_FAT_IO0 } 6075f28a827Saf }; 6085f28a827Saf 6095f28a827Saf static struct mch_error_code fat_rp_5400_error_code[] = { 6105f28a827Saf { 1, EMASK_RP_PEX_IO1, PEX_5400_FAT_IO1 } 6115f28a827Saf }; 6125f28a827Saf 61320c794b3Sgavinm static struct mch_error_code fat_rp_error_code[] = { 61420c794b3Sgavinm { 1, EMASK_RP_PEX_IO1, PEX_FAT_IO1 } 61520c794b3Sgavinm }; 61620c794b3Sgavinm 61720c794b3Sgavinm static struct mch_error_code uncor_pex_error_code[] = { 61820c794b3Sgavinm { 19, EMASK_UNCOR_PEX_IO19, PEX_NF_IO19 }, 61920c794b3Sgavinm { 9, EMASK_UNCOR_PEX_IO9, PEX_NF_IO9 }, 62020c794b3Sgavinm { 8, EMASK_UNCOR_PEX_IO8, PEX_NF_IO8 }, 62120c794b3Sgavinm { 7, EMASK_UNCOR_PEX_IO7, PEX_NF_IO7 }, 62220c794b3Sgavinm { 6, EMASK_UNCOR_PEX_IO6, PEX_NF_IO6 }, 62320c794b3Sgavinm { 5, EMASK_UNCOR_PEX_IO5, PEX_NF_IO5 }, 62420c794b3Sgavinm { 4, EMASK_UNCOR_PEX_IO4, PEX_NF_IO4 }, 62520c794b3Sgavinm { 3, EMASK_UNCOR_PEX_IO3, PEX_NF_IO3 }, 62620c794b3Sgavinm { 0, EMASK_UNCOR_PEX_IO0, PEX_NF_IO0 } 62720c794b3Sgavinm }; 62820c794b3Sgavinm 6295f28a827Saf static struct mch_error_code uncor_pex_5400_error_code[] = { 6305f28a827Saf { 33, EMASK_UNIT_PEX_IO33, PEX_5400_NF_IO33 }, 6315f28a827Saf { 32, EMASK_UNIT_PEX_IO32, PEX_5400_NF_IO32 }, 6325f28a827Saf { 31, EMASK_UNIT_PEX_IO31, PEX_5400_NF_IO31 }, 6335f28a827Saf { 30, EMASK_UNIT_PEX_IO30, PEX_5400_NF_IO30 }, 6345f28a827Saf { 29, EMASK_UNIT_PEX_IO29, PEX_5400_NF_IO29 }, 6355f28a827Saf { 28, EMASK_UNIT_PEX_IO28, PEX_5400_NF_IO28 }, 6365f28a827Saf { 27, EMASK_UNIT_PEX_IO27, PEX_5400_NF_IO27 }, 6375f28a827Saf { 26, EMASK_UNIT_PEX_IO26, PEX_5400_NF_IO26 }, 6385f28a827Saf { 25, EMASK_UNIT_PEX_IO25, PEX_5400_NF_IO25 }, 6395f28a827Saf { 24, EMASK_UNIT_PEX_IO24, PEX_5400_NF_IO24 }, 6405f28a827Saf { 23, EMASK_UNIT_PEX_IO23, PEX_5400_NF_IO23 }, 6415f28a827Saf }; 6425f28a827Saf 64320c794b3Sgavinm static struct mch_error_code cor_pex_error_code[] = { 6445f28a827Saf { 20, EMASK_COR_PEX_IO20, PEX_5400_NF_IO20 }, 64520c794b3Sgavinm { 16, EMASK_COR_PEX_IO16, PEX_NF_IO16 }, 64620c794b3Sgavinm { 15, EMASK_COR_PEX_IO15, PEX_NF_IO15 }, 64720c794b3Sgavinm { 14, EMASK_COR_PEX_IO14, PEX_NF_IO14 }, 64820c794b3Sgavinm { 13, EMASK_COR_PEX_IO13, PEX_NF_IO13 }, 64920c794b3Sgavinm { 12, EMASK_COR_PEX_IO12, PEX_NF_IO12 }, 65020c794b3Sgavinm { 10, 0, PEX_NF_IO10 }, 65120c794b3Sgavinm { 2, 0, PEX_NF_IO2 } 65220c794b3Sgavinm }; 65320c794b3Sgavinm 6545f28a827Saf static struct mch_error_code rp_pex_5400_error_code[] = { 6555f28a827Saf { 17, EMASK_RP_PEX_IO17, PEX_5400_NF_IO17 }, 6565f28a827Saf { 11, EMASK_RP_PEX_IO11, PEX_5400_NF_IO11 } 6575f28a827Saf }; 6585f28a827Saf 6595f28a827Saf static struct mch_error_code cor_pex_5400_error_code1[] = { 6605f28a827Saf { 19, EMASK_UNCOR_PEX_IO19, PEX_5400_NF_IO19 }, 6615f28a827Saf { 10, EMASK_UNCOR_PEX_IO10, PEX_5400_NF_IO10 }, 6625f28a827Saf { 9, EMASK_UNCOR_PEX_IO9, PEX_5400_NF_IO9 }, 6635f28a827Saf { 8, EMASK_UNCOR_PEX_IO8, PEX_5400_NF_IO8 }, 6645f28a827Saf { 7, EMASK_UNCOR_PEX_IO7, PEX_5400_NF_IO7 }, 6655f28a827Saf { 6, EMASK_UNCOR_PEX_IO6, PEX_5400_NF_IO6 }, 6665f28a827Saf { 5, EMASK_UNCOR_PEX_IO5, PEX_5400_NF_IO5 }, 6675f28a827Saf { 4, EMASK_UNCOR_PEX_IO4, PEX_5400_NF_IO4 }, 6685f28a827Saf { 2, EMASK_UNCOR_PEX_IO2, PEX_5400_NF_IO2 }, 6695f28a827Saf { 0, EMASK_UNCOR_PEX_IO0, PEX_5400_NF_IO0 } 6705f28a827Saf }; 6715f28a827Saf 6725f28a827Saf static struct mch_error_code cor_pex_5400_error_code2[] = { 6735f28a827Saf { 20, EMASK_COR_PEX_IO20, PEX_5400_NF_IO20 }, 6745f28a827Saf { 16, EMASK_COR_PEX_IO16, PEX_5400_NF_IO16 }, 6755f28a827Saf { 15, EMASK_COR_PEX_IO15, PEX_5400_NF_IO15 }, 6765f28a827Saf { 14, EMASK_COR_PEX_IO14, PEX_5400_NF_IO14 }, 6775f28a827Saf { 13, EMASK_COR_PEX_IO13, PEX_5400_NF_IO13 }, 6785f28a827Saf { 12, EMASK_COR_PEX_IO12, PEX_5400_NF_IO12 } 6795f28a827Saf }; 6805f28a827Saf 6815f28a827Saf static struct mch_error_code cor_pex_5400_error_code3[] = { 6825f28a827Saf { 33, EMASK_UNIT_PEX_IO33, PEX_5400_NF_IO33 }, 6835f28a827Saf { 32, EMASK_UNIT_PEX_IO32, PEX_5400_NF_IO32 }, 6845f28a827Saf { 31, EMASK_UNIT_PEX_IO31, PEX_5400_NF_IO31 }, 6855f28a827Saf { 30, EMASK_UNIT_PEX_IO30, PEX_5400_NF_IO30 }, 6865f28a827Saf { 29, EMASK_UNIT_PEX_IO29, PEX_5400_NF_IO29 }, 6875f28a827Saf { 28, EMASK_UNIT_PEX_IO28, PEX_5400_NF_IO28 }, 6885f28a827Saf { 27, EMASK_UNIT_PEX_IO27, PEX_5400_NF_IO27 }, 6895f28a827Saf { 26, EMASK_UNIT_PEX_IO26, PEX_5400_NF_IO26 }, 6905f28a827Saf { 25, EMASK_UNIT_PEX_IO25, PEX_5400_NF_IO25 }, 6915f28a827Saf { 24, EMASK_UNIT_PEX_IO24, PEX_5400_NF_IO24 }, 6925f28a827Saf { 23, EMASK_UNIT_PEX_IO23, PEX_5400_NF_IO23 } 6935f28a827Saf }; 6945f28a827Saf 69520c794b3Sgavinm static struct mch_error_code rp_pex_error_code[] = { 69620c794b3Sgavinm { 17, EMASK_RP_PEX_IO17, PEX_NF_IO17 }, 69720c794b3Sgavinm { 11, EMASK_RP_PEX_IO11, PEX_NF_IO11 }, 69820c794b3Sgavinm }; 69920c794b3Sgavinm 70020c794b3Sgavinm static int 70120c794b3Sgavinm intel_pex_err(uint32_t pex_fat, uint32_t pex_nf_cor) 70220c794b3Sgavinm { 70320c794b3Sgavinm int rt = -1; 70420c794b3Sgavinm int nerr = 0; 70520c794b3Sgavinm int i; 70620c794b3Sgavinm int sz; 70720c794b3Sgavinm 70820c794b3Sgavinm sz = sizeof (fat_pex_error_code) / sizeof (struct mch_error_code); 70920c794b3Sgavinm 71020c794b3Sgavinm for (i = 0; i < sz; i++) { 71120c794b3Sgavinm if (pex_fat & fat_pex_error_code[i].error_bit) { 71220c794b3Sgavinm rt = fat_pex_error_code[i].intel_error_list; 71320c794b3Sgavinm nerr++; 71420c794b3Sgavinm } 71520c794b3Sgavinm } 71620c794b3Sgavinm sz = sizeof (fat_rp_error_code) / sizeof (struct mch_error_code); 71720c794b3Sgavinm 71820c794b3Sgavinm for (i = 0; i < sz; i++) { 71920c794b3Sgavinm if (pex_fat & fat_rp_error_code[i].error_bit) { 72020c794b3Sgavinm rt = fat_rp_error_code[i].intel_error_list; 72120c794b3Sgavinm nerr++; 72220c794b3Sgavinm } 72320c794b3Sgavinm } 72420c794b3Sgavinm sz = sizeof (uncor_pex_error_code) / sizeof (struct mch_error_code); 72520c794b3Sgavinm 72620c794b3Sgavinm for (i = 0; i < sz; i++) { 72720c794b3Sgavinm if (pex_nf_cor & uncor_pex_error_code[i].error_bit) { 72820c794b3Sgavinm rt = uncor_pex_error_code[i].intel_error_list; 72920c794b3Sgavinm nerr++; 73020c794b3Sgavinm } 73120c794b3Sgavinm } 73220c794b3Sgavinm 73320c794b3Sgavinm sz = sizeof (cor_pex_error_code) / sizeof (struct mch_error_code); 73420c794b3Sgavinm 73520c794b3Sgavinm for (i = 0; i < sz; i++) { 73620c794b3Sgavinm if (pex_nf_cor & cor_pex_error_code[i].error_bit) { 73720c794b3Sgavinm rt = cor_pex_error_code[i].intel_error_list; 73820c794b3Sgavinm nerr++; 73920c794b3Sgavinm } 74020c794b3Sgavinm } 74120c794b3Sgavinm sz = sizeof (rp_pex_error_code) / sizeof (struct mch_error_code); 74220c794b3Sgavinm 74320c794b3Sgavinm for (i = 0; i < sz; i++) { 74420c794b3Sgavinm if (pex_nf_cor & rp_pex_error_code[i].error_bit) { 74520c794b3Sgavinm rt = rp_pex_error_code[i].intel_error_list; 74620c794b3Sgavinm nerr++; 74720c794b3Sgavinm } 74820c794b3Sgavinm } 74920c794b3Sgavinm 75020c794b3Sgavinm if (nerr > 1) 75120c794b3Sgavinm rt = -1; 75220c794b3Sgavinm return (rt); 75320c794b3Sgavinm } 7545f28a827Saf 7555f28a827Saf static struct mch_error_code fat_thr_error_code[] = { 7565f28a827Saf { 2, EMASK_THR_F2, ERR_FAT_THR_F2 }, 7575f28a827Saf { 1, EMASK_THR_F1, ERR_FAT_THR_F1 } 7585f28a827Saf }; 7595f28a827Saf 7605f28a827Saf static struct mch_error_code nf_thr_error_code[] = { 7615f28a827Saf { 5, EMASK_THR_F5, ERR_NF_THR_F5 }, 7625f28a827Saf { 4, EMASK_THR_F4, ERR_NF_THR_F4 }, 7635f28a827Saf { 3, EMASK_THR_F3, ERR_NF_THR_F3 } 7645f28a827Saf }; 7655f28a827Saf 7665f28a827Saf static int 7675f28a827Saf intel_thr_err(uint8_t err_fat_thr, uint8_t err_nf_thr) 7685f28a827Saf { 7695f28a827Saf int rt = -1; 7705f28a827Saf int nerr = 0; 7715f28a827Saf uint16_t emask_thr = 0; 7725f28a827Saf int i; 7735f28a827Saf int sz; 7745f28a827Saf 7755f28a827Saf sz = sizeof (fat_thr_error_code) / sizeof (struct mch_error_code); 7765f28a827Saf 7775f28a827Saf for (i = 0; i < sz; i++) { 7785f28a827Saf if (err_fat_thr & fat_thr_error_code[i].error_bit) { 7795f28a827Saf rt = fat_thr_error_code[i].intel_error_list; 7805f28a827Saf emask_thr |= fat_thr_error_code[i].emask; 7815f28a827Saf nerr++; 7825f28a827Saf } 7835f28a827Saf } 7845f28a827Saf 7855f28a827Saf sz = sizeof (nf_thr_error_code) / sizeof (struct mch_error_code); 7865f28a827Saf 7875f28a827Saf for (i = 0; i < sz; i++) { 7885f28a827Saf if (err_nf_thr & nf_thr_error_code[i].error_bit) { 7895f28a827Saf rt = nf_thr_error_code[i].intel_error_list; 7905f28a827Saf emask_thr |= nf_thr_error_code[i].emask; 7915f28a827Saf nerr++; 7925f28a827Saf } 7935f28a827Saf } 7945f28a827Saf 7955f28a827Saf if (emask_thr) 7965f28a827Saf nb_thr_mask_mc(emask_thr); 7975f28a827Saf if (nerr > 1) 7985f28a827Saf rt = -1; 7995f28a827Saf return (rt); 8005f28a827Saf } 8015f28a827Saf 8025f28a827Saf static int 8035f28a827Saf intel_pex_5400_err(uint32_t pex_fat, uint32_t pex_nf_cor) 8045f28a827Saf { 8055f28a827Saf int rt = -1; 8065f28a827Saf int nerr = 0; 8075f28a827Saf int i; 8085f28a827Saf int sz; 8095f28a827Saf 8105f28a827Saf sz = sizeof (fat_pex_5400_error_code) / sizeof (struct mch_error_code); 8115f28a827Saf 8125f28a827Saf for (i = 0; i < sz; i++) { 8135f28a827Saf if (pex_fat & fat_pex_5400_error_code[i].error_bit) { 8145f28a827Saf rt = fat_pex_5400_error_code[i].intel_error_list; 8155f28a827Saf nerr++; 8165f28a827Saf } 8175f28a827Saf } 8185f28a827Saf sz = sizeof (fat_rp_5400_error_code) / sizeof (struct mch_error_code); 8195f28a827Saf 8205f28a827Saf for (i = 0; i < sz; i++) { 8215f28a827Saf if (pex_fat & fat_rp_5400_error_code[i].error_bit) { 8225f28a827Saf rt = fat_rp_5400_error_code[i].intel_error_list; 8235f28a827Saf nerr++; 8245f28a827Saf } 8255f28a827Saf } 8265f28a827Saf sz = sizeof (fat_unit_pex_5400_error_code) / 8275f28a827Saf sizeof (struct mch_error_code); 8285f28a827Saf 8295f28a827Saf for (i = 0; i < sz; i++) { 8305f28a827Saf if (pex_fat & 8315f28a827Saf fat_unit_pex_5400_error_code[i].error_bit) { 8325f28a827Saf rt = fat_unit_pex_5400_error_code[i].intel_error_list; 8335f28a827Saf nerr++; 8345f28a827Saf } 8355f28a827Saf } 8365f28a827Saf sz = sizeof (uncor_pex_5400_error_code) / 8375f28a827Saf sizeof (struct mch_error_code); 8385f28a827Saf 8395f28a827Saf for (i = 0; i < sz; i++) { 8405f28a827Saf if (pex_fat & uncor_pex_5400_error_code[i].error_bit) { 8415f28a827Saf rt = uncor_pex_5400_error_code[i].intel_error_list; 8425f28a827Saf nerr++; 8435f28a827Saf } 8445f28a827Saf } 8455f28a827Saf 8465f28a827Saf sz = sizeof (rp_pex_5400_error_code) / sizeof (struct mch_error_code); 8475f28a827Saf 8485f28a827Saf for (i = 0; i < sz; i++) { 8495f28a827Saf if (pex_nf_cor & rp_pex_5400_error_code[i].error_bit) { 8505f28a827Saf rt = rp_pex_5400_error_code[i].intel_error_list; 8515f28a827Saf nerr++; 8525f28a827Saf } 8535f28a827Saf } 8545f28a827Saf 8555f28a827Saf sz = sizeof (cor_pex_5400_error_code1) / sizeof (struct mch_error_code); 8565f28a827Saf 8575f28a827Saf for (i = 0; i < sz; i++) { 8585f28a827Saf if (pex_nf_cor & cor_pex_5400_error_code1[i].error_bit) { 8595f28a827Saf rt = cor_pex_5400_error_code1[i].intel_error_list; 8605f28a827Saf nerr++; 8615f28a827Saf } 8625f28a827Saf } 8635f28a827Saf 8645f28a827Saf sz = sizeof (cor_pex_5400_error_code2) / sizeof (struct mch_error_code); 8655f28a827Saf 8665f28a827Saf for (i = 0; i < sz; i++) { 8675f28a827Saf if (pex_nf_cor & cor_pex_5400_error_code2[i].error_bit) { 8685f28a827Saf rt = cor_pex_5400_error_code2[i].intel_error_list; 8695f28a827Saf nerr++; 8705f28a827Saf } 8715f28a827Saf } 8725f28a827Saf 8735f28a827Saf sz = sizeof (cor_pex_5400_error_code3) / sizeof (struct mch_error_code); 8745f28a827Saf 8755f28a827Saf for (i = 0; i < sz; i++) { 8765f28a827Saf if (pex_nf_cor & cor_pex_5400_error_code3[i].error_bit) { 8775f28a827Saf rt = cor_pex_5400_error_code3[i].intel_error_list; 8785f28a827Saf nerr++; 8795f28a827Saf } 8805f28a827Saf } 8815f28a827Saf 8825f28a827Saf if (nerr > 1) 8835f28a827Saf rt = -1; 8845f28a827Saf return (rt); 8855f28a827Saf } 8865f28a827Saf 88720c794b3Sgavinm static void 8880ad0f0b2SAdrian Frost log_pex_err(uint64_t ferr, nb_regs_t *rp, int willpanic, int *interpose) 88920c794b3Sgavinm { 89020c794b3Sgavinm uint8_t pex = (uint8_t)-1; 89120c794b3Sgavinm int t = 0; 89220c794b3Sgavinm 89320c794b3Sgavinm rp->flag = NB_REG_LOG_PEX; 89420c794b3Sgavinm pex = GE_ERR_PEX(ferr); 89520c794b3Sgavinm 89620c794b3Sgavinm rp->nb.pex_regs.pex = pex; 89720c794b3Sgavinm rp->nb.pex_regs.pex_fat_ferr = PEX_FAT_FERR_RD(pex, interpose); 89820c794b3Sgavinm rp->nb.pex_regs.pex_fat_nerr = PEX_FAT_NERR_RD(pex, &t); 89920c794b3Sgavinm *interpose |= t; 90020c794b3Sgavinm rp->nb.pex_regs.pex_nf_corr_ferr = PEX_NF_FERR_RD(pex, &t); 90120c794b3Sgavinm *interpose |= t; 90220c794b3Sgavinm rp->nb.pex_regs.pex_nf_corr_nerr = PEX_NF_NERR_RD(pex, &t); 90320c794b3Sgavinm *interpose |= t; 90420c794b3Sgavinm rp->nb.pex_regs.uncerrsev = UNCERRSEV_RD(pex); 90520c794b3Sgavinm rp->nb.pex_regs.rperrsts = RPERRSTS_RD(pex); 90620c794b3Sgavinm rp->nb.pex_regs.rperrsid = RPERRSID_RD(pex); 90720c794b3Sgavinm if (pex != (uint8_t)-1) 90820c794b3Sgavinm rp->nb.pex_regs.uncerrsts = UNCERRSTS_RD(pex); 90920c794b3Sgavinm else 91020c794b3Sgavinm rp->nb.pex_regs.uncerrsts = 0; 91120c794b3Sgavinm rp->nb.pex_regs.aerrcapctrl = AERRCAPCTRL_RD(pex); 91220c794b3Sgavinm rp->nb.pex_regs.corerrsts = CORERRSTS_RD(pex); 91320c794b3Sgavinm rp->nb.pex_regs.pexdevsts = PEXDEVSTS_RD(pex); 91420c794b3Sgavinm 9150ad0f0b2SAdrian Frost if (!willpanic) { 9160ad0f0b2SAdrian Frost if (rp->nb.pex_regs.pex_fat_ferr || *interpose) 9170ad0f0b2SAdrian Frost PEX_FAT_FERR_WR(pex, rp->nb.pex_regs.pex_fat_ferr); 9180ad0f0b2SAdrian Frost if (rp->nb.pex_regs.pex_fat_nerr) 9190ad0f0b2SAdrian Frost PEX_FAT_NERR_WR(pex, rp->nb.pex_regs.pex_fat_nerr); 9200ad0f0b2SAdrian Frost if (rp->nb.pex_regs.pex_nf_corr_ferr || *interpose) 9210ad0f0b2SAdrian Frost PEX_NF_FERR_WR(pex, rp->nb.pex_regs.pex_nf_corr_ferr); 9220ad0f0b2SAdrian Frost if (rp->nb.pex_regs.pex_nf_corr_nerr) 9230ad0f0b2SAdrian Frost PEX_NF_NERR_WR(pex, rp->nb.pex_regs.pex_nf_corr_nerr); 9240ad0f0b2SAdrian Frost if (*interpose) 9250ad0f0b2SAdrian Frost UNCERRSTS_WR(pex, rp->nb.pex_regs.uncerrsts); 9260ad0f0b2SAdrian Frost if (*interpose) 9270ad0f0b2SAdrian Frost RPERRSTS_WR(pex, rp->nb.pex_regs.rperrsts); 9280ad0f0b2SAdrian Frost if (*interpose) 9290ad0f0b2SAdrian Frost PEXDEVSTS_WR(pex, 0); 9300ad0f0b2SAdrian Frost } 93120c794b3Sgavinm } 93220c794b3Sgavinm 93320c794b3Sgavinm static void 9340ad0f0b2SAdrian Frost log_fat_fbd_err(nb_regs_t *rp, int willpanic, int *interpose) 93520c794b3Sgavinm { 93620c794b3Sgavinm int channel, branch; 93720c794b3Sgavinm int t = 0; 93820c794b3Sgavinm 93920c794b3Sgavinm rp->flag = NB_REG_LOG_FAT_FBD; 94020c794b3Sgavinm rp->nb.fat_fbd_regs.ferr_fat_fbd = FERR_FAT_FBD_RD(interpose); 94120c794b3Sgavinm channel = (rp->nb.fat_fbd_regs.ferr_fat_fbd >> 28) & 3; 94220c794b3Sgavinm branch = channel >> 1; 94320c794b3Sgavinm rp->nb.fat_fbd_regs.nerr_fat_fbd = NERR_FAT_FBD_RD(&t); 94420c794b3Sgavinm *interpose |= t; 9455f28a827Saf rp->nb.fat_fbd_regs.nrecmema = NRECMEMA_RD(branch); 9465f28a827Saf rp->nb.fat_fbd_regs.nrecmemb = NRECMEMB_RD(branch); 9475f28a827Saf rp->nb.fat_fbd_regs.nrecfglog = NRECFGLOG_RD(branch); 9485f28a827Saf rp->nb.fat_fbd_regs.nrecfbda = NRECFBDA_RD(branch); 9495f28a827Saf rp->nb.fat_fbd_regs.nrecfbdb = NRECFBDB_RD(branch); 9505f28a827Saf rp->nb.fat_fbd_regs.nrecfbdc = NRECFBDC_RD(branch); 9515f28a827Saf rp->nb.fat_fbd_regs.nrecfbdd = NRECFBDD_RD(branch); 9525f28a827Saf rp->nb.fat_fbd_regs.nrecfbde = NRECFBDE_RD(branch); 9535f28a827Saf rp->nb.fat_fbd_regs.nrecfbdf = NRECFBDF_RD(branch); 95420c794b3Sgavinm rp->nb.fat_fbd_regs.spcps = SPCPS_RD(branch); 95520c794b3Sgavinm rp->nb.fat_fbd_regs.spcpc = SPCPC_RD(branch); 95620c794b3Sgavinm rp->nb.fat_fbd_regs.uerrcnt = UERRCNT_RD(branch); 95720c794b3Sgavinm rp->nb.fat_fbd_regs.uerrcnt_last = uerrcnt[branch]; 95820c794b3Sgavinm uerrcnt[branch] = rp->nb.fat_fbd_regs.uerrcnt; 95920c794b3Sgavinm rp->nb.fat_fbd_regs.badrama = BADRAMA_RD(branch); 96020c794b3Sgavinm rp->nb.fat_fbd_regs.badramb = BADRAMB_RD(branch); 96120c794b3Sgavinm rp->nb.fat_fbd_regs.badcnt = BADCNT_RD(branch); 9620ad0f0b2SAdrian Frost if (!willpanic) { 9630ad0f0b2SAdrian Frost if (rp->nb.fat_fbd_regs.ferr_fat_fbd || *interpose) 9640ad0f0b2SAdrian Frost FERR_FAT_FBD_WR(rp->nb.fat_fbd_regs.ferr_fat_fbd); 9650ad0f0b2SAdrian Frost if (rp->nb.fat_fbd_regs.nerr_fat_fbd) 9660ad0f0b2SAdrian Frost NERR_FAT_FBD_WR(rp->nb.fat_fbd_regs.nerr_fat_fbd); 9670ad0f0b2SAdrian Frost /* 9680ad0f0b2SAdrian Frost * if interpose write read-only registers to clear from pcii 9690ad0f0b2SAdrian Frost * cache 9700ad0f0b2SAdrian Frost */ 9710ad0f0b2SAdrian Frost if (*interpose) { 9720ad0f0b2SAdrian Frost NRECMEMA_WR(branch); 9730ad0f0b2SAdrian Frost NRECMEMB_WR(branch); 9740ad0f0b2SAdrian Frost NRECFGLOG_WR(branch); 9750ad0f0b2SAdrian Frost NRECFBDA_WR(branch); 9760ad0f0b2SAdrian Frost NRECFBDB_WR(branch); 9770ad0f0b2SAdrian Frost NRECFBDC_WR(branch); 9780ad0f0b2SAdrian Frost NRECFBDD_WR(branch); 9790ad0f0b2SAdrian Frost NRECFBDE_WR(branch); 9800ad0f0b2SAdrian Frost NRECFBDF_WR(branch); 9810ad0f0b2SAdrian Frost } 98220c794b3Sgavinm } 98320c794b3Sgavinm } 98420c794b3Sgavinm 98520c794b3Sgavinm static void 9860ad0f0b2SAdrian Frost log_nf_fbd_err(nb_regs_t *rp, int willpanic, int *interpose) 98720c794b3Sgavinm { 98820c794b3Sgavinm int channel, branch; 98920c794b3Sgavinm int t = 0; 99020c794b3Sgavinm 99120c794b3Sgavinm rp->flag = NB_REG_LOG_NF_FBD; 99220c794b3Sgavinm rp->nb.nf_fbd_regs.ferr_nf_fbd = FERR_NF_FBD_RD(interpose); 99320c794b3Sgavinm channel = (rp->nb.nf_fbd_regs.ferr_nf_fbd >> 28) & 3; 99420c794b3Sgavinm branch = channel >> 1; 99520c794b3Sgavinm rp->nb.nf_fbd_regs.nerr_nf_fbd = NERR_NF_FBD_RD(&t); 99620c794b3Sgavinm *interpose |= t; 99720c794b3Sgavinm rp->nb.nf_fbd_regs.redmemb = REDMEMB_RD(); 9985f28a827Saf rp->nb.nf_fbd_regs.recmema = RECMEMA_RD(branch); 9995f28a827Saf rp->nb.nf_fbd_regs.recmemb = RECMEMB_RD(branch); 10005f28a827Saf rp->nb.nf_fbd_regs.recfglog = RECFGLOG_RD(branch); 10015f28a827Saf rp->nb.nf_fbd_regs.recfbda = RECFBDA_RD(branch); 10025f28a827Saf rp->nb.nf_fbd_regs.recfbdb = RECFBDB_RD(branch); 10035f28a827Saf rp->nb.nf_fbd_regs.recfbdc = RECFBDC_RD(branch); 10045f28a827Saf rp->nb.nf_fbd_regs.recfbdd = RECFBDD_RD(branch); 10055f28a827Saf rp->nb.nf_fbd_regs.recfbde = RECFBDE_RD(branch); 10065f28a827Saf rp->nb.nf_fbd_regs.recfbdf = RECFBDF_RD(branch); 100720c794b3Sgavinm rp->nb.nf_fbd_regs.spcps = SPCPS_RD(branch); 100820c794b3Sgavinm rp->nb.nf_fbd_regs.spcpc = SPCPC_RD(branch); 10095f28a827Saf if (nb_chipset == INTEL_NB_7300 || nb_chipset == INTEL_NB_5400) { 10105f28a827Saf rp->nb.nf_fbd_regs.cerrcnta = CERRCNTA_RD(branch, channel); 10115f28a827Saf rp->nb.nf_fbd_regs.cerrcntb = CERRCNTB_RD(branch, channel); 10125f28a827Saf rp->nb.nf_fbd_regs.cerrcntc = CERRCNTC_RD(branch, channel); 10135f28a827Saf rp->nb.nf_fbd_regs.cerrcntd = CERRCNTD_RD(branch, channel); 10145f28a827Saf } else { 10155f28a827Saf rp->nb.nf_fbd_regs.cerrcnta = CERRCNT_RD(branch); 10165f28a827Saf rp->nb.nf_fbd_regs.cerrcntb = 0; 10175f28a827Saf rp->nb.nf_fbd_regs.cerrcntc = 0; 10185f28a827Saf rp->nb.nf_fbd_regs.cerrcntd = 0; 10195f28a827Saf } 10205f28a827Saf rp->nb.nf_fbd_regs.cerrcnta_last = cerrcnta[branch][channel & 1]; 10215f28a827Saf rp->nb.nf_fbd_regs.cerrcntb_last = cerrcntb[branch][channel & 1]; 10225f28a827Saf rp->nb.nf_fbd_regs.cerrcntc_last = cerrcntc[branch][channel & 1]; 10235f28a827Saf rp->nb.nf_fbd_regs.cerrcntd_last = cerrcntd[branch][channel & 1]; 10245f28a827Saf cerrcnta[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcnta; 10255f28a827Saf cerrcntb[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcntb; 10265f28a827Saf cerrcntc[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcntc; 10275f28a827Saf cerrcntd[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcntd; 102820c794b3Sgavinm rp->nb.nf_fbd_regs.badrama = BADRAMA_RD(branch); 102920c794b3Sgavinm rp->nb.nf_fbd_regs.badramb = BADRAMB_RD(branch); 103020c794b3Sgavinm rp->nb.nf_fbd_regs.badcnt = BADCNT_RD(branch); 10310ad0f0b2SAdrian Frost if (!willpanic) { 10320ad0f0b2SAdrian Frost if (rp->nb.nf_fbd_regs.ferr_nf_fbd || *interpose) 10330ad0f0b2SAdrian Frost FERR_NF_FBD_WR(rp->nb.nf_fbd_regs.ferr_nf_fbd); 10340ad0f0b2SAdrian Frost if (rp->nb.nf_fbd_regs.nerr_nf_fbd) 10350ad0f0b2SAdrian Frost NERR_NF_FBD_WR(rp->nb.nf_fbd_regs.nerr_nf_fbd); 10360ad0f0b2SAdrian Frost /* 10370ad0f0b2SAdrian Frost * if interpose write read-only registers to clear from pcii 10380ad0f0b2SAdrian Frost * cache 10390ad0f0b2SAdrian Frost */ 10400ad0f0b2SAdrian Frost if (*interpose) { 10410ad0f0b2SAdrian Frost RECMEMA_WR(branch); 10420ad0f0b2SAdrian Frost RECMEMB_WR(branch); 10430ad0f0b2SAdrian Frost RECFGLOG_WR(branch); 10440ad0f0b2SAdrian Frost RECFBDA_WR(branch); 10450ad0f0b2SAdrian Frost RECFBDB_WR(branch); 10460ad0f0b2SAdrian Frost RECFBDC_WR(branch); 10470ad0f0b2SAdrian Frost RECFBDD_WR(branch); 10480ad0f0b2SAdrian Frost RECFBDE_WR(branch); 10490ad0f0b2SAdrian Frost RECFBDF_WR(branch); 10500ad0f0b2SAdrian Frost SPCPS_WR(branch); 10510ad0f0b2SAdrian Frost } 105220c794b3Sgavinm } 105320c794b3Sgavinm } 105420c794b3Sgavinm 105520c794b3Sgavinm static void 105620c794b3Sgavinm log_ferr(uint64_t ferr, uint32_t *nerrp, nb_logout_t *log, int willpanic) 105720c794b3Sgavinm { 105820c794b3Sgavinm nb_regs_t *rp = &log->nb_regs; 105920c794b3Sgavinm uint32_t nerr = *nerrp; 106020c794b3Sgavinm int interpose = 0; 10619ff4cbe7SAdrian Frost int spurious = 0; 106220c794b3Sgavinm 106320c794b3Sgavinm log->acl_timestamp = gethrtime_waitfree(); 106420c794b3Sgavinm if ((ferr & (GE_PCIEX_FATAL | GE_PCIEX_NF)) != 0) { 10650ad0f0b2SAdrian Frost log_pex_err(ferr, rp, willpanic, &interpose); 106620c794b3Sgavinm *nerrp = nerr & ~(GE_PCIEX_FATAL | GE_PCIEX_NF); 106720c794b3Sgavinm } else if ((ferr & GE_FBD_FATAL) != 0) { 10680ad0f0b2SAdrian Frost log_fat_fbd_err(rp, willpanic, &interpose); 106920c794b3Sgavinm *nerrp = nerr & ~GE_NERR_FBD_FATAL; 107020c794b3Sgavinm } else if ((ferr & GE_FBD_NF) != 0) { 10710ad0f0b2SAdrian Frost log_nf_fbd_err(rp, willpanic, &interpose); 107220c794b3Sgavinm *nerrp = nerr & ~GE_NERR_FBD_NF; 107320c794b3Sgavinm } else if ((ferr & (GE_FERR_FSB_FATAL | GE_FERR_FSB_NF)) != 0) { 10740ad0f0b2SAdrian Frost log_fsb_err(ferr, rp, willpanic, &interpose); 107520c794b3Sgavinm *nerrp = nerr & ~(GE_NERR_FSB_FATAL | GE_NERR_FSB_NF); 107620c794b3Sgavinm } else if ((ferr & (GE_DMA_FATAL | GE_DMA_NF)) != 0) { 107720c794b3Sgavinm log_dma_err(rp, &interpose); 107820c794b3Sgavinm *nerrp = nerr & ~(GE_DMA_FATAL | GE_DMA_NF); 107920c794b3Sgavinm } else if ((ferr & (GE_INT_FATAL | GE_INT_NF)) != 0) { 10800ad0f0b2SAdrian Frost spurious = log_int_err(rp, willpanic, &interpose); 108120c794b3Sgavinm *nerrp = nerr & ~(GE_INT_FATAL | GE_INT_NF); 10825f28a827Saf } else if (nb_chipset == INTEL_NB_5400 && 10835f28a827Saf (ferr & (GE_FERR_THERMAL_FATAL | GE_FERR_THERMAL_NF)) != 0) { 10840ad0f0b2SAdrian Frost log_thermal_err(rp, willpanic, &interpose); 10855f28a827Saf *nerrp = nerr & ~(GE_FERR_THERMAL_FATAL | GE_FERR_THERMAL_NF); 108620c794b3Sgavinm } 108720c794b3Sgavinm if (interpose) 108820c794b3Sgavinm log->type = "inject"; 108920c794b3Sgavinm else 109020c794b3Sgavinm log->type = "error"; 10919ff4cbe7SAdrian Frost if (!spurious) { 10929ff4cbe7SAdrian Frost errorq_dispatch(nb_queue, log, sizeof (nb_logout_t), 10939ff4cbe7SAdrian Frost willpanic ? ERRORQ_SYNC : ERRORQ_ASYNC); 10949ff4cbe7SAdrian Frost } 109520c794b3Sgavinm } 109620c794b3Sgavinm 109720c794b3Sgavinm static void 109820c794b3Sgavinm log_nerr(uint32_t *errp, nb_logout_t *log, int willpanic) 109920c794b3Sgavinm { 110020c794b3Sgavinm uint32_t err; 110120c794b3Sgavinm nb_regs_t *rp = &log->nb_regs; 110220c794b3Sgavinm int interpose = 0; 11039ff4cbe7SAdrian Frost int spurious = 0; 110420c794b3Sgavinm 110520c794b3Sgavinm err = *errp; 110620c794b3Sgavinm log->acl_timestamp = gethrtime_waitfree(); 110720c794b3Sgavinm if ((err & (GE_PCIEX_FATAL | GE_PCIEX_NF)) != 0) { 11080ad0f0b2SAdrian Frost log_pex_err(err, rp, willpanic, &interpose); 110920c794b3Sgavinm *errp = err & ~(GE_PCIEX_FATAL | GE_PCIEX_NF); 111020c794b3Sgavinm } else if ((err & GE_NERR_FBD_FATAL) != 0) { 11110ad0f0b2SAdrian Frost log_fat_fbd_err(rp, willpanic, &interpose); 111220c794b3Sgavinm *errp = err & ~GE_NERR_FBD_FATAL; 111320c794b3Sgavinm } else if ((err & GE_NERR_FBD_NF) != 0) { 11140ad0f0b2SAdrian Frost log_nf_fbd_err(rp, willpanic, &interpose); 111520c794b3Sgavinm *errp = err & ~GE_NERR_FBD_NF; 111620c794b3Sgavinm } else if ((err & (GE_NERR_FSB_FATAL | GE_NERR_FSB_NF)) != 0) { 11170ad0f0b2SAdrian Frost log_fsb_err(GE_NERR_TO_FERR_FSB(err), rp, willpanic, 11180ad0f0b2SAdrian Frost &interpose); 111920c794b3Sgavinm *errp = err & ~(GE_NERR_FSB_FATAL | GE_NERR_FSB_NF); 112020c794b3Sgavinm } else if ((err & (GE_DMA_FATAL | GE_DMA_NF)) != 0) { 112120c794b3Sgavinm log_dma_err(rp, &interpose); 112220c794b3Sgavinm *errp = err & ~(GE_DMA_FATAL | GE_DMA_NF); 112320c794b3Sgavinm } else if ((err & (GE_INT_FATAL | GE_INT_NF)) != 0) { 11240ad0f0b2SAdrian Frost spurious = log_int_err(rp, willpanic, &interpose); 112520c794b3Sgavinm *errp = err & ~(GE_INT_FATAL | GE_INT_NF); 112620c794b3Sgavinm } 112720c794b3Sgavinm if (interpose) 112820c794b3Sgavinm log->type = "inject"; 112920c794b3Sgavinm else 113020c794b3Sgavinm log->type = "error"; 11319ff4cbe7SAdrian Frost if (!spurious) { 11329ff4cbe7SAdrian Frost errorq_dispatch(nb_queue, log, sizeof (nb_logout_t), 11339ff4cbe7SAdrian Frost willpanic ? ERRORQ_SYNC : ERRORQ_ASYNC); 11349ff4cbe7SAdrian Frost } 113520c794b3Sgavinm } 113620c794b3Sgavinm 113720c794b3Sgavinm /*ARGSUSED*/ 113820c794b3Sgavinm void 113920c794b3Sgavinm nb_error_trap(cmi_hdl_t hdl, boolean_t ismc, boolean_t willpanic) 114020c794b3Sgavinm { 114120c794b3Sgavinm uint64_t ferr; 114220c794b3Sgavinm uint32_t nerr, err; 114320c794b3Sgavinm int nmc = 0; 114420c794b3Sgavinm int i; 114520c794b3Sgavinm 114620c794b3Sgavinm if (mutex_tryenter(&nb_mutex) == 0) 114720c794b3Sgavinm return; 114820c794b3Sgavinm 114920c794b3Sgavinm nerr = NERR_GLOBAL_RD(); 115020c794b3Sgavinm err = nerr; 115120c794b3Sgavinm for (i = 0; i < NB_MAX_ERRORS; i++) { 115220c794b3Sgavinm ferr = FERR_GLOBAL_RD(); 115320c794b3Sgavinm nb_log.nb_regs.chipset = nb_chipset; 115420c794b3Sgavinm nb_log.nb_regs.ferr = ferr; 115520c794b3Sgavinm nb_log.nb_regs.nerr = nerr; 115620c794b3Sgavinm if (ferr) { 115720c794b3Sgavinm log_ferr(ferr, &err, &nb_log, willpanic); 115820c794b3Sgavinm FERR_GLOBAL_WR(ferr); 115920c794b3Sgavinm nmc++; 116020c794b3Sgavinm } else if (err) { 116120c794b3Sgavinm log_nerr(&err, &nb_log, willpanic); 116220c794b3Sgavinm nmc++; 116320c794b3Sgavinm } 116420c794b3Sgavinm } 116520c794b3Sgavinm if (nerr) { 116620c794b3Sgavinm NERR_GLOBAL_WR(nerr); 116720c794b3Sgavinm } 116820c794b3Sgavinm if (nmc == 0 && nb_mask_mc_set) 116920c794b3Sgavinm nb_mask_mc_reset(); 117020c794b3Sgavinm mutex_exit(&nb_mutex); 117120c794b3Sgavinm } 117220c794b3Sgavinm 117320c794b3Sgavinm static void 117420c794b3Sgavinm nb_fsb_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 117520c794b3Sgavinm nb_scatchpad_t *data) 117620c794b3Sgavinm { 117720c794b3Sgavinm int intel_error_list; 117820c794b3Sgavinm char buf[32]; 117920c794b3Sgavinm 118020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FSB, 118120c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.fsb, NULL); 118220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_FSB, 118320c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.ferr_fat_fsb, NULL); 118420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_FSB, 118520c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.nerr_fat_fsb, NULL); 118620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_FSB, 118720c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.ferr_nf_fsb, NULL); 118820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_FSB, 118920c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.nerr_nf_fsb, NULL); 119020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFSB, 119120c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fsb_regs.nrecfsb, NULL); 119220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFSB_ADDR, 119320c794b3Sgavinm DATA_TYPE_UINT64, nb_regs->nb.fsb_regs.nrecfsb_addr, NULL); 119420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFSB, 119520c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fsb_regs.recfsb, NULL); 119620c794b3Sgavinm intel_error_list = data->intel_error_list; 119720c794b3Sgavinm if (intel_error_list >= 0) 119820c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "F%d", intel_error_list); 119920c794b3Sgavinm else 120020c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 120120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 120220c794b3Sgavinm DATA_TYPE_STRING, buf, NULL); 120320c794b3Sgavinm } 120420c794b3Sgavinm 120520c794b3Sgavinm static void 120620c794b3Sgavinm nb_pex_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 120720c794b3Sgavinm nb_scatchpad_t *data) 120820c794b3Sgavinm { 120920c794b3Sgavinm int intel_error_list; 121020c794b3Sgavinm char buf[32]; 121120c794b3Sgavinm 121220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX, 121320c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.pex_regs.pex, NULL); 121420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_FAT_FERR, 121520c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_fat_ferr, NULL); 121620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_FAT_NERR, 121720c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_fat_nerr, NULL); 121820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_NF_CORR_FERR, 121920c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_nf_corr_ferr, NULL); 122020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_NF_CORR_NERR, 122120c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_nf_corr_nerr, NULL); 122220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UNCERRSEV, 122320c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.uncerrsev, NULL); 122420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RPERRSTS, 122520c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.rperrsts, NULL); 122620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RPERRSID, 122720c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.rperrsid, NULL); 122820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UNCERRSTS, 122920c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.uncerrsts, NULL); 123020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_AERRCAPCTRL, 123120c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.aerrcapctrl, NULL); 123220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CORERRSTS, 123320c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.corerrsts, NULL); 123420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEXDEVSTS, 123520c794b3Sgavinm DATA_TYPE_UINT16, nb_regs->nb.pex_regs.pexdevsts, NULL); 123620c794b3Sgavinm intel_error_list = data->intel_error_list; 123720c794b3Sgavinm if (intel_error_list >= 0) 123820c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "IO%d", intel_error_list); 123920c794b3Sgavinm else 124020c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 124120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 124220c794b3Sgavinm DATA_TYPE_STRING, buf, NULL); 124320c794b3Sgavinm } 124420c794b3Sgavinm 124520c794b3Sgavinm static void 124620c794b3Sgavinm nb_int_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 124720c794b3Sgavinm nb_scatchpad_t *data) 124820c794b3Sgavinm { 124920c794b3Sgavinm int intel_error_list; 125020c794b3Sgavinm char buf[32]; 125120c794b3Sgavinm 125220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_INT, 12535f28a827Saf DATA_TYPE_UINT16, nb_regs->nb.int_regs.ferr_fat_int, NULL); 125420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_INT, 12555f28a827Saf DATA_TYPE_UINT16, nb_regs->nb.int_regs.ferr_nf_int, NULL); 125620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_INT, 12575f28a827Saf DATA_TYPE_UINT16, nb_regs->nb.int_regs.nerr_fat_int, NULL); 125820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_INT, 12595f28a827Saf DATA_TYPE_UINT16, nb_regs->nb.int_regs.nerr_nf_int, NULL); 126020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECINT, 126120c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.int_regs.nrecint, NULL); 126220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECINT, 126320c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.int_regs.recint, NULL); 126420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECSF, 126520c794b3Sgavinm DATA_TYPE_UINT64, nb_regs->nb.int_regs.nrecsf, NULL); 126620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECSF, 126720c794b3Sgavinm DATA_TYPE_UINT64, nb_regs->nb.int_regs.recsf, NULL); 126820c794b3Sgavinm intel_error_list = data->intel_error_list; 126920c794b3Sgavinm if (intel_error_list >= 0) 127020c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "B%d", intel_error_list); 127120c794b3Sgavinm else 127220c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 127320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 127420c794b3Sgavinm DATA_TYPE_STRING, buf, NULL); 127520c794b3Sgavinm } 127620c794b3Sgavinm 127720c794b3Sgavinm static void 127820c794b3Sgavinm nb_fat_fbd_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 127920c794b3Sgavinm nb_scatchpad_t *data) 128020c794b3Sgavinm { 128120c794b3Sgavinm nb_mem_scatchpad_t *sp; 128220c794b3Sgavinm char buf[32]; 128320c794b3Sgavinm 128420c794b3Sgavinm sp = &((nb_scatchpad_t *)data)->ms; 128520c794b3Sgavinm 128620c794b3Sgavinm if (sp->ras != -1) { 128720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK, 128820c794b3Sgavinm DATA_TYPE_INT32, sp->bank, NULL); 128920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CAS, 129020c794b3Sgavinm DATA_TYPE_INT32, sp->cas, NULL); 129120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RAS, 129220c794b3Sgavinm DATA_TYPE_INT32, sp->ras, NULL); 129320c794b3Sgavinm if (sp->offset != -1LL) { 129420c794b3Sgavinm fm_payload_set(payload, FM_FMRI_MEM_OFFSET, 129520c794b3Sgavinm DATA_TYPE_UINT64, sp->offset, NULL); 129620c794b3Sgavinm } 129720c794b3Sgavinm if (sp->pa != -1LL) { 129820c794b3Sgavinm fm_payload_set(payload, FM_FMRI_MEM_PHYSADDR, 129920c794b3Sgavinm DATA_TYPE_UINT64, sp->pa, NULL); 130020c794b3Sgavinm } 130120c794b3Sgavinm } 130220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_FBD, 130320c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.ferr_fat_fbd, NULL); 130420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_FBD, 130520c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nerr_fat_fbd, NULL); 130620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECMEMA, 13075f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecmema, NULL); 130820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECMEMB, 130920c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecmemb, NULL); 131020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFGLOG, 131120c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfglog, NULL); 131220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDA, 131320c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbda, NULL); 131420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDB, 131520c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdb, NULL); 131620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDC, 131720c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdc, NULL); 131820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDD, 131920c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdd, NULL); 132020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDE, 132120c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbde, NULL); 13225de8e333Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDF, 13235de8e333Saf DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdf, NULL); 132420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPS, 132520c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fat_fbd_regs.spcps, NULL); 132620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPC, 132720c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.spcpc, NULL); 132820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UERRCNT, 132920c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.uerrcnt, NULL); 133020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UERRCNT_LAST, 133120c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.uerrcnt_last, NULL); 133220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMA, 133320c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.badrama, NULL); 133420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMB, 133520c794b3Sgavinm DATA_TYPE_UINT16, nb_regs->nb.fat_fbd_regs.badramb, NULL); 133620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADCNT, 133720c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.badcnt, NULL); 133820c794b3Sgavinm 133920c794b3Sgavinm if (sp->intel_error_list >= 0) 134020c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "M%d", sp->intel_error_list); 134120c794b3Sgavinm else 134220c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 134320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 134420c794b3Sgavinm DATA_TYPE_STRING, buf, NULL); 134520c794b3Sgavinm } 134620c794b3Sgavinm 134720c794b3Sgavinm static void 134820c794b3Sgavinm nb_nf_fbd_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 134920c794b3Sgavinm nb_scatchpad_t *data) 135020c794b3Sgavinm { 135120c794b3Sgavinm nb_mem_scatchpad_t *sp; 135220c794b3Sgavinm char buf[32]; 135320c794b3Sgavinm 135420c794b3Sgavinm sp = &((nb_scatchpad_t *)data)->ms; 135520c794b3Sgavinm 135620c794b3Sgavinm if (sp->dimm == -1 && sp->rank != -1) { 135720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RANK, 135820c794b3Sgavinm DATA_TYPE_INT32, sp->rank, NULL); 135920c794b3Sgavinm } 136020c794b3Sgavinm if (sp->ras != -1) { 136120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK, 136220c794b3Sgavinm DATA_TYPE_INT32, sp->bank, NULL); 136320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CAS, 136420c794b3Sgavinm DATA_TYPE_INT32, sp->cas, NULL); 136520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RAS, 136620c794b3Sgavinm DATA_TYPE_INT32, sp->ras, NULL); 136720c794b3Sgavinm if (sp->offset != -1LL) { 136820c794b3Sgavinm fm_payload_set(payload, FM_FMRI_MEM_OFFSET, 136920c794b3Sgavinm DATA_TYPE_UINT64, sp->offset, NULL); 137020c794b3Sgavinm } 137120c794b3Sgavinm if (sp->pa != -1LL) { 137220c794b3Sgavinm fm_payload_set(payload, FM_FMRI_MEM_PHYSADDR, 137320c794b3Sgavinm DATA_TYPE_UINT64, sp->pa, NULL); 137420c794b3Sgavinm } 137520c794b3Sgavinm } 137620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_FBD, 137720c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.ferr_nf_fbd, NULL); 137820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_FBD, 137920c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.nerr_nf_fbd, NULL); 138020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECMEMA, 13815f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recmema, NULL); 138220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECMEMB, 138320c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recmemb, NULL); 138420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFGLOG, 138520c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfglog, NULL); 138620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDA, 138720c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbda, NULL); 138820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDB, 138920c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdb, NULL); 139020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDC, 139120c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdc, NULL); 139220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDD, 139320c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdd, NULL); 139420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDE, 139520c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbde, NULL); 13965de8e333Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDF, 13975de8e333Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdf, NULL); 139820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPS, 139920c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.nf_fbd_regs.spcps, NULL); 140020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPC, 140120c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.spcpc, NULL); 14025f28a827Saf if (nb_chipset == INTEL_NB_7300 || nb_chipset == INTEL_NB_5400) { 14035f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTA, 14045f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta, NULL); 14055f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTB, 14065f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntb, NULL); 14075f28a827Saf if (nb_chipset == INTEL_NB_7300) { 14085f28a827Saf fm_payload_set(payload, 14095f28a827Saf FM_EREPORT_PAYLOAD_NAME_CERRCNTC, 14105f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntc, 14115f28a827Saf NULL); 14125f28a827Saf fm_payload_set(payload, 14135f28a827Saf FM_EREPORT_PAYLOAD_NAME_CERRCNTD, 14145f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntd, 14155f28a827Saf NULL); 14165f28a827Saf } 14175f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTA_LAST, 14185f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta_last, 14195f28a827Saf NULL); 14205f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTB_LAST, 14215f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntb_last, 14225f28a827Saf NULL); 14235f28a827Saf if (nb_chipset == INTEL_NB_7300) { 14245f28a827Saf fm_payload_set(payload, 14255f28a827Saf FM_EREPORT_PAYLOAD_NAME_CERRCNTC_LAST, 14265f28a827Saf DATA_TYPE_UINT32, 14275f28a827Saf nb_regs->nb.nf_fbd_regs.cerrcntc_last, NULL); 14285f28a827Saf fm_payload_set(payload, 14295f28a827Saf FM_EREPORT_PAYLOAD_NAME_CERRCNTD_LAST, 14305f28a827Saf DATA_TYPE_UINT32, 14315f28a827Saf nb_regs->nb.nf_fbd_regs.cerrcntd_last, NULL); 14325f28a827Saf } 14335f28a827Saf } else { 14345f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT, 14355f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta, NULL); 14365f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT_LAST, 14375f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta_last, 14385f28a827Saf NULL); 14395f28a827Saf } 144020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMA, 144120c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.badrama, NULL); 144220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMB, 144320c794b3Sgavinm DATA_TYPE_UINT16, nb_regs->nb.nf_fbd_regs.badramb, NULL); 144420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADCNT, 144520c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.badcnt, NULL); 144620c794b3Sgavinm 144720c794b3Sgavinm if (sp->intel_error_list >= 0) 144820c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "M%d", sp->intel_error_list); 144920c794b3Sgavinm else 145020c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 145120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 145220c794b3Sgavinm DATA_TYPE_STRING, buf, NULL); 145320c794b3Sgavinm } 145420c794b3Sgavinm 145520c794b3Sgavinm static void 145620c794b3Sgavinm nb_dma_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload) 145720c794b3Sgavinm { 145820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PCISTS, 145920c794b3Sgavinm DATA_TYPE_UINT16, nb_regs->nb.dma_regs.pcists, NULL); 146020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEXDEVSTS, 146120c794b3Sgavinm DATA_TYPE_UINT16, nb_regs->nb.dma_regs.pexdevsts, NULL); 146220c794b3Sgavinm } 146320c794b3Sgavinm 14645f28a827Saf static void 14655f28a827Saf nb_thr_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 14665f28a827Saf nb_scatchpad_t *data) 14675f28a827Saf { 14685f28a827Saf char buf[32]; 14695f28a827Saf 14705f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_THR, 14715f28a827Saf DATA_TYPE_UINT8, nb_regs->nb.thr_regs.ferr_fat_thr, NULL); 14725f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_THR, 14735f28a827Saf DATA_TYPE_UINT8, nb_regs->nb.thr_regs.nerr_fat_thr, NULL); 14745f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_THR, 14755f28a827Saf DATA_TYPE_UINT8, nb_regs->nb.thr_regs.ferr_nf_thr, NULL); 14765f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_THR, 14775f28a827Saf DATA_TYPE_UINT8, nb_regs->nb.thr_regs.nerr_nf_thr, NULL); 14785f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CTSTS, 14795f28a827Saf DATA_TYPE_UINT8, nb_regs->nb.thr_regs.ctsts, NULL); 14805f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_THRTSTS, 14815f28a827Saf DATA_TYPE_UINT16, nb_regs->nb.thr_regs.thrtsts, NULL); 14825f28a827Saf if (data->intel_error_list >= 0) { 14835f28a827Saf (void) snprintf(buf, sizeof (buf), "TH%d", 14845f28a827Saf data->intel_error_list); 14855f28a827Saf } else { 14865f28a827Saf (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 14875f28a827Saf } 14885f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 14895f28a827Saf DATA_TYPE_STRING, buf, NULL); 14905f28a827Saf } 14915f28a827Saf 149220c794b3Sgavinm static void 149320c794b3Sgavinm nb_ereport_add_logout(nvlist_t *payload, const nb_logout_t *acl, 149420c794b3Sgavinm nb_scatchpad_t *data) 149520c794b3Sgavinm { 149620c794b3Sgavinm const nb_regs_t *nb_regs = &acl->nb_regs; 149720c794b3Sgavinm 149820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_MC_TYPE, 14996cb1ca52Saf DATA_TYPE_STRING, acl->type, NULL); 150020c794b3Sgavinm switch (nb_regs->flag) { 150120c794b3Sgavinm case NB_REG_LOG_FSB: 150220c794b3Sgavinm nb_fsb_err_payload(nb_regs, payload, data); 150320c794b3Sgavinm break; 150420c794b3Sgavinm case NB_REG_LOG_PEX: 150520c794b3Sgavinm nb_pex_err_payload(nb_regs, payload, data); 150620c794b3Sgavinm break; 150720c794b3Sgavinm case NB_REG_LOG_INT: 150820c794b3Sgavinm nb_int_err_payload(nb_regs, payload, data); 150920c794b3Sgavinm break; 151020c794b3Sgavinm case NB_REG_LOG_FAT_FBD: 151120c794b3Sgavinm nb_fat_fbd_err_payload(nb_regs, payload, data); 151220c794b3Sgavinm break; 151320c794b3Sgavinm case NB_REG_LOG_NF_FBD: 151420c794b3Sgavinm nb_nf_fbd_err_payload(nb_regs, payload, data); 151520c794b3Sgavinm break; 151620c794b3Sgavinm case NB_REG_LOG_DMA: 151720c794b3Sgavinm nb_dma_err_payload(nb_regs, payload); 151820c794b3Sgavinm break; 15195f28a827Saf case NB_REG_LOG_THR: 15205f28a827Saf nb_thr_err_payload(nb_regs, payload, data); 15215f28a827Saf break; 152220c794b3Sgavinm default: 152320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_GLOBAL, 152420c794b3Sgavinm DATA_TYPE_UINT64, nb_regs->ferr, NULL); 152520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_GLOBAL, 152620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nerr, NULL); 152720c794b3Sgavinm break; 152820c794b3Sgavinm } 152920c794b3Sgavinm } 153020c794b3Sgavinm 153120c794b3Sgavinm void 153220c794b3Sgavinm nb_fsb_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 153320c794b3Sgavinm nb_scatchpad_t *data) 153420c794b3Sgavinm { 153520c794b3Sgavinm int chip; 153620c794b3Sgavinm 153720c794b3Sgavinm if (nb_chipset == INTEL_NB_7300) 153820c794b3Sgavinm chip = nb_regs->nb.fsb_regs.fsb * 2; 153920c794b3Sgavinm else 154020c794b3Sgavinm chip = nb_regs->nb.fsb_regs.fsb; 154120c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2, 154220c794b3Sgavinm "motherboard", 0, "chip", chip); 154320c794b3Sgavinm 15446cb1ca52Saf if (nb_regs->nb.fsb_regs.ferr_fat_fsb == 0 && 15456cb1ca52Saf nb_regs->nb.fsb_regs.ferr_nf_fsb == 0) { 15466cb1ca52Saf data->intel_error_list = intel_fsb_err(nb_regs->nb.fsb_regs.fsb, 15476cb1ca52Saf nb_regs->nb.fsb_regs.nerr_fat_fsb, 15486cb1ca52Saf nb_regs->nb.fsb_regs.nerr_nf_fsb); 15496cb1ca52Saf } else { 15506cb1ca52Saf data->intel_error_list = intel_fsb_err(nb_regs->nb.fsb_regs.fsb, 15516cb1ca52Saf nb_regs->nb.fsb_regs.ferr_fat_fsb, 15526cb1ca52Saf nb_regs->nb.fsb_regs.ferr_nf_fsb); 15536cb1ca52Saf } 155420c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 155520c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "fsb"); 155620c794b3Sgavinm } 155720c794b3Sgavinm 155820c794b3Sgavinm void 155920c794b3Sgavinm nb_pex_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 156020c794b3Sgavinm nb_scatchpad_t *data) 156120c794b3Sgavinm { 156220c794b3Sgavinm int hostbridge; 156320c794b3Sgavinm 156420c794b3Sgavinm if (nb_regs->nb.pex_regs.pex == 0) { 156520c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 156620c794b3Sgavinm "motherboard", 0); 156720c794b3Sgavinm } else { 156820c794b3Sgavinm hostbridge = nb_regs->nb.pex_regs.pex - 1; 156920c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2, 157020c794b3Sgavinm "motherboard", 0, 157120c794b3Sgavinm "hostbridge", hostbridge); 157220c794b3Sgavinm } 157320c794b3Sgavinm 15746cb1ca52Saf if (nb_regs->nb.pex_regs.pex_fat_ferr == 0 && 15756cb1ca52Saf nb_regs->nb.pex_regs.pex_nf_corr_ferr == 0) { 15765f28a827Saf if (nb_chipset == INTEL_NB_5400) { 15775f28a827Saf data->intel_error_list = 15785f28a827Saf intel_pex_5400_err( 15795f28a827Saf nb_regs->nb.pex_regs.pex_fat_nerr, 15805f28a827Saf nb_regs->nb.pex_regs.pex_nf_corr_nerr); 15815f28a827Saf } else { 15825f28a827Saf data->intel_error_list = 15835f28a827Saf intel_pex_err(nb_regs->nb.pex_regs.pex_fat_nerr, 15845f28a827Saf nb_regs->nb.pex_regs.pex_nf_corr_nerr); 15855f28a827Saf } 15866cb1ca52Saf } else { 15875f28a827Saf if (nb_chipset == INTEL_NB_5400) { 15885f28a827Saf data->intel_error_list = 15895f28a827Saf intel_pex_5400_err( 15905f28a827Saf nb_regs->nb.pex_regs.pex_fat_ferr, 15915f28a827Saf nb_regs->nb.pex_regs.pex_nf_corr_ferr); 15925f28a827Saf } else { 15935f28a827Saf data->intel_error_list = 15945f28a827Saf intel_pex_err(nb_regs->nb.pex_regs.pex_fat_ferr, 15955f28a827Saf nb_regs->nb.pex_regs.pex_nf_corr_ferr); 15965f28a827Saf } 15976cb1ca52Saf } 159820c794b3Sgavinm 159920c794b3Sgavinm if (nb_regs->nb.pex_regs.pex == 0) { 160020c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 160120c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "esi"); 160220c794b3Sgavinm } else { 160320c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 160420c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "pex"); 160520c794b3Sgavinm } 160620c794b3Sgavinm } 160720c794b3Sgavinm 160820c794b3Sgavinm void 160920c794b3Sgavinm nb_int_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 161020c794b3Sgavinm void *data) 161120c794b3Sgavinm { 161220c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 161320c794b3Sgavinm "motherboard", 0); 161420c794b3Sgavinm 16156cb1ca52Saf if (nb_regs->nb.int_regs.ferr_fat_int == 0 && 16166cb1ca52Saf nb_regs->nb.int_regs.ferr_nf_int == 0) { 16176cb1ca52Saf ((nb_scatchpad_t *)data)->intel_error_list = 16186cb1ca52Saf intel_int_err(nb_regs->nb.int_regs.nerr_fat_int, 16196cb1ca52Saf nb_regs->nb.int_regs.nerr_nf_int); 16206cb1ca52Saf } else { 16216cb1ca52Saf ((nb_scatchpad_t *)data)->intel_error_list = 16226cb1ca52Saf intel_int_err(nb_regs->nb.int_regs.ferr_fat_int, 16236cb1ca52Saf nb_regs->nb.int_regs.ferr_nf_int); 16246cb1ca52Saf } 162520c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 162620c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "ie"); 162720c794b3Sgavinm } 162820c794b3Sgavinm 162920c794b3Sgavinm void 163020c794b3Sgavinm nb_fat_fbd_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 163120c794b3Sgavinm void *data) 163220c794b3Sgavinm { 163320c794b3Sgavinm char *intr; 163420c794b3Sgavinm nb_mem_scatchpad_t *sp; 163520c794b3Sgavinm 163620c794b3Sgavinm intr = fat_memory_error(nb_regs, data); 163720c794b3Sgavinm sp = &((nb_scatchpad_t *)data)->ms; 163820c794b3Sgavinm 163920c794b3Sgavinm if (sp->dimm != -1) { 164020c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 5, 164120c794b3Sgavinm "motherboard", 0, 164220c794b3Sgavinm "memory-controller", sp->branch, 164320c794b3Sgavinm "dram-channel", sp->channel, 164420c794b3Sgavinm "dimm", sp->dimm, 164520c794b3Sgavinm "rank", sp->rank); 164620c794b3Sgavinm } else if (sp->channel != -1) { 164720c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 3, 164820c794b3Sgavinm "motherboard", 0, 164920c794b3Sgavinm "memory-controller", sp->branch, 165020c794b3Sgavinm "dram-channel", sp->channel); 16516cb1ca52Saf } else if (sp->branch != -1) { 165220c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2, 165320c794b3Sgavinm "motherboard", 0, 165420c794b3Sgavinm "memory-controller", sp->branch); 16556cb1ca52Saf } else { 16566cb1ca52Saf fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 16576cb1ca52Saf "motherboard", 0); 165820c794b3Sgavinm } 165920c794b3Sgavinm 166020c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s", 166120c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, intr); 166220c794b3Sgavinm } 166320c794b3Sgavinm 166420c794b3Sgavinm void 166520c794b3Sgavinm nb_nf_fbd_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 166620c794b3Sgavinm void *data) 166720c794b3Sgavinm { 166820c794b3Sgavinm char *intr; 166920c794b3Sgavinm nb_mem_scatchpad_t *sp; 167020c794b3Sgavinm 167120c794b3Sgavinm intr = nf_memory_error(nb_regs, data); 167220c794b3Sgavinm sp = &((nb_scatchpad_t *)data)->ms; 167320c794b3Sgavinm 167420c794b3Sgavinm if (sp->dimm != -1) { 167520c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 5, 167620c794b3Sgavinm "motherboard", 0, 167720c794b3Sgavinm "memory-controller", sp->branch, 167820c794b3Sgavinm "dram-channel", sp->channel, 167920c794b3Sgavinm "dimm", sp->dimm, 168020c794b3Sgavinm "rank", sp->rank); 168120c794b3Sgavinm } else if (sp->channel != -1) { 168220c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 3, 168320c794b3Sgavinm "motherboard", 0, 168420c794b3Sgavinm "memory-controller", sp->branch, 168520c794b3Sgavinm "dram-channel", sp->channel); 16866cb1ca52Saf } else if (sp->branch != -1) { 168720c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2, 168820c794b3Sgavinm "motherboard", 0, 168920c794b3Sgavinm "memory-controller", sp->branch); 16906cb1ca52Saf } else { 16916cb1ca52Saf fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 16926cb1ca52Saf "motherboard", 0); 169320c794b3Sgavinm } 169420c794b3Sgavinm 169520c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s", 169620c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, intr); 169720c794b3Sgavinm } 169820c794b3Sgavinm 169920c794b3Sgavinm void 170020c794b3Sgavinm nb_dma_report(char *class, nvlist_t *detector) 170120c794b3Sgavinm { 170220c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 170320c794b3Sgavinm "motherboard", 0); 170420c794b3Sgavinm 170520c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 170620c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "dma"); 170720c794b3Sgavinm } 170820c794b3Sgavinm 17095f28a827Saf void 17105f28a827Saf nb_thr_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 17115f28a827Saf void *data) 17125f28a827Saf { 17135f28a827Saf ((nb_scatchpad_t *)data)->intel_error_list = 17145f28a827Saf intel_thr_err(nb_regs->nb.thr_regs.ferr_fat_thr, 17155f28a827Saf nb_regs->nb.thr_regs.ferr_nf_thr); 17165f28a827Saf fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 17175f28a827Saf "motherboard", 0); 17185f28a827Saf 17195f28a827Saf (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 17205f28a827Saf FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "otf"); 17215f28a827Saf } 17225f28a827Saf 172320c794b3Sgavinm 172420c794b3Sgavinm nvlist_t * 172520c794b3Sgavinm nb_report(const nb_regs_t *nb_regs, char *class, nv_alloc_t *nva, void *scratch) 172620c794b3Sgavinm { 172720c794b3Sgavinm nvlist_t *detector = fm_nvlist_create(nva); 172820c794b3Sgavinm 172920c794b3Sgavinm switch (nb_regs->flag) { 173020c794b3Sgavinm case NB_REG_LOG_FSB: 173120c794b3Sgavinm nb_fsb_report(nb_regs, class, detector, scratch); 173220c794b3Sgavinm break; 173320c794b3Sgavinm case NB_REG_LOG_PEX: 173420c794b3Sgavinm nb_pex_report(nb_regs, class, detector, scratch); 173520c794b3Sgavinm break; 173620c794b3Sgavinm case NB_REG_LOG_INT: 173720c794b3Sgavinm nb_int_report(nb_regs, class, detector, scratch); 173820c794b3Sgavinm break; 173920c794b3Sgavinm case NB_REG_LOG_FAT_FBD: 174020c794b3Sgavinm nb_fat_fbd_report(nb_regs, class, detector, scratch); 174120c794b3Sgavinm break; 174220c794b3Sgavinm case NB_REG_LOG_NF_FBD: 174320c794b3Sgavinm nb_nf_fbd_report(nb_regs, class, detector, scratch); 174420c794b3Sgavinm break; 174520c794b3Sgavinm case NB_REG_LOG_DMA: 174620c794b3Sgavinm nb_dma_report(class, detector); 174720c794b3Sgavinm break; 17485f28a827Saf case NB_REG_LOG_THR: 17495f28a827Saf nb_thr_report(nb_regs, class, detector, scratch); 17505f28a827Saf break; 175120c794b3Sgavinm default: 175220c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 175320c794b3Sgavinm "motherboard", 0); 175420c794b3Sgavinm 175520c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 175620c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "unknown"); 175720c794b3Sgavinm } 175820c794b3Sgavinm return (detector); 175920c794b3Sgavinm } 176020c794b3Sgavinm 176120c794b3Sgavinm /*ARGSUSED*/ 176220c794b3Sgavinm void 176320c794b3Sgavinm nb_drain(void *ignored, const void *data, const errorq_elem_t *eqe) 176420c794b3Sgavinm { 176520c794b3Sgavinm nb_logout_t *acl = (nb_logout_t *)data; 176620c794b3Sgavinm errorq_elem_t *eqep, *scr_eqep; 176720c794b3Sgavinm nvlist_t *ereport, *detector; 176820c794b3Sgavinm nv_alloc_t *nva = NULL; 176920c794b3Sgavinm char buf[FM_MAX_CLASS]; 177020c794b3Sgavinm nb_scatchpad_t nb_scatchpad; 177120c794b3Sgavinm 177220c794b3Sgavinm if (panicstr) { 177320c794b3Sgavinm if ((eqep = errorq_reserve(ereport_errorq)) == NULL) 177420c794b3Sgavinm return; 177520c794b3Sgavinm ereport = errorq_elem_nvl(ereport_errorq, eqep); 177620c794b3Sgavinm /* 177720c794b3Sgavinm * Now try to allocate another element for scratch space and 177820c794b3Sgavinm * use that for further scratch space (eg for constructing 177920c794b3Sgavinm * nvlists to add the main ereport). If we can't reserve 178020c794b3Sgavinm * a scratch element just fallback to working within the 178120c794b3Sgavinm * element we already have, and hope for the best. All this 178220c794b3Sgavinm * is necessary because the fixed buffer nv allocator does 178320c794b3Sgavinm * not reclaim freed space and nvlist construction is 178420c794b3Sgavinm * expensive. 178520c794b3Sgavinm */ 178620c794b3Sgavinm if ((scr_eqep = errorq_reserve(ereport_errorq)) != NULL) 178720c794b3Sgavinm nva = errorq_elem_nva(ereport_errorq, scr_eqep); 178820c794b3Sgavinm else 178920c794b3Sgavinm nva = errorq_elem_nva(ereport_errorq, eqep); 179020c794b3Sgavinm } else { 179120c794b3Sgavinm ereport = fm_nvlist_create(NULL); 179220c794b3Sgavinm } 179320c794b3Sgavinm detector = nb_report(&acl->nb_regs, buf, nva, &nb_scatchpad); 179420c794b3Sgavinm if (detector == NULL) 179520c794b3Sgavinm return; 179620c794b3Sgavinm fm_ereport_set(ereport, FM_EREPORT_VERSION, buf, 179720c794b3Sgavinm fm_ena_generate(acl->acl_timestamp, FM_ENA_FMT1), detector, NULL); 179820c794b3Sgavinm /* 179920c794b3Sgavinm * We're done with 'detector' so reclaim the scratch space. 180020c794b3Sgavinm */ 180120c794b3Sgavinm if (panicstr) { 180220c794b3Sgavinm fm_nvlist_destroy(detector, FM_NVA_RETAIN); 180320c794b3Sgavinm nv_alloc_reset(nva); 180420c794b3Sgavinm } else { 180520c794b3Sgavinm fm_nvlist_destroy(detector, FM_NVA_FREE); 180620c794b3Sgavinm } 180720c794b3Sgavinm 180820c794b3Sgavinm /* 180920c794b3Sgavinm * Encode the error-specific data that was saved in the logout area. 181020c794b3Sgavinm */ 181120c794b3Sgavinm nb_ereport_add_logout(ereport, acl, &nb_scatchpad); 181220c794b3Sgavinm 181320c794b3Sgavinm if (panicstr) { 181420c794b3Sgavinm errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC); 181520c794b3Sgavinm if (scr_eqep) 181620c794b3Sgavinm errorq_cancel(ereport_errorq, scr_eqep); 181720c794b3Sgavinm } else { 181820c794b3Sgavinm (void) fm_ereport_post(ereport, EVCH_TRYHARD); 181920c794b3Sgavinm fm_nvlist_destroy(ereport, FM_NVA_FREE); 182020c794b3Sgavinm } 182120c794b3Sgavinm } 1822