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 47*85738508SVuong Nguyen int nb_check_validlog = 1; 48*85738508SVuong Nguyen 4920c794b3Sgavinm static uint32_t uerrcnt[2]; 505f28a827Saf static uint32_t cerrcnta[2][2]; 515f28a827Saf static uint32_t cerrcntb[2][2]; 525f28a827Saf static uint32_t cerrcntc[2][2]; 535f28a827Saf static uint32_t cerrcntd[2][2]; 5420c794b3Sgavinm static nb_logout_t nb_log; 5520c794b3Sgavinm 5620c794b3Sgavinm struct mch_error_code { 5720c794b3Sgavinm int intel_error_list; /* error number in Chipset Error List */ 5820c794b3Sgavinm uint32_t emask; /* mask for machine check */ 5920c794b3Sgavinm uint32_t error_bit; /* error bit in fault register */ 6020c794b3Sgavinm }; 6120c794b3Sgavinm 6220c794b3Sgavinm static struct mch_error_code fat_fbd_error_code[] = { 6320c794b3Sgavinm { 23, EMASK_FBD_M23, ERR_FAT_FBD_M23 }, 6420c794b3Sgavinm { 3, EMASK_FBD_M3, ERR_FAT_FBD_M3 }, 6520c794b3Sgavinm { 2, EMASK_FBD_M2, ERR_FAT_FBD_M2 }, 6620c794b3Sgavinm { 1, EMASK_FBD_M1, ERR_FAT_FBD_M1 } 6720c794b3Sgavinm }; 6820c794b3Sgavinm 6920c794b3Sgavinm static int 7020c794b3Sgavinm intel_fat_fbd_err(uint32_t fat_fbd) 7120c794b3Sgavinm { 7220c794b3Sgavinm int rt = -1; 7320c794b3Sgavinm int nerr = 0; 7420c794b3Sgavinm uint32_t emask_fbd = 0; 7520c794b3Sgavinm int i; 7620c794b3Sgavinm int sz; 7720c794b3Sgavinm 7820c794b3Sgavinm sz = sizeof (fat_fbd_error_code) / sizeof (struct mch_error_code); 7920c794b3Sgavinm 8020c794b3Sgavinm for (i = 0; i < sz; i++) { 8120c794b3Sgavinm if (fat_fbd & fat_fbd_error_code[i].error_bit) { 8220c794b3Sgavinm rt = fat_fbd_error_code[i].intel_error_list; 8320c794b3Sgavinm emask_fbd |= fat_fbd_error_code[i].emask; 8420c794b3Sgavinm nerr++; 8520c794b3Sgavinm } 8620c794b3Sgavinm } 8720c794b3Sgavinm 8820c794b3Sgavinm if (emask_fbd) 8920c794b3Sgavinm nb_fbd_mask_mc(emask_fbd); 9020c794b3Sgavinm if (nerr > 1) 9120c794b3Sgavinm rt = -1; 9220c794b3Sgavinm return (rt); 9320c794b3Sgavinm } 9420c794b3Sgavinm 9520c794b3Sgavinm static char * 9620c794b3Sgavinm fat_memory_error(const nb_regs_t *rp, void *data) 9720c794b3Sgavinm { 9820c794b3Sgavinm int channel; 9920c794b3Sgavinm uint32_t ferr_fat_fbd, nrecmemb; 1005f28a827Saf uint32_t nrecmema; 10120c794b3Sgavinm char *intr = "nb.unknown"; 10220c794b3Sgavinm nb_mem_scatchpad_t *sp = &((nb_scatchpad_t *)data)->ms; 10320c794b3Sgavinm 10420c794b3Sgavinm ferr_fat_fbd = rp->nb.fat_fbd_regs.ferr_fat_fbd; 1056cb1ca52Saf if ((ferr_fat_fbd & ERR_FAT_FBD_MASK) == 0) { 1066cb1ca52Saf sp->intel_error_list = 1076cb1ca52Saf intel_fat_fbd_err(rp->nb.fat_fbd_regs.nerr_fat_fbd); 1086cb1ca52Saf sp->branch = -1; 1096cb1ca52Saf sp->channel = -1; 1106cb1ca52Saf sp->rank = -1; 1116cb1ca52Saf sp->dimm = -1; 1126cb1ca52Saf sp->bank = -1; 1136cb1ca52Saf sp->cas = -1; 1146cb1ca52Saf sp->ras = -1; 1156cb1ca52Saf sp->pa = -1LL; 1166cb1ca52Saf sp->offset = -1; 1176cb1ca52Saf return (intr); 1186cb1ca52Saf } 11920c794b3Sgavinm sp->intel_error_list = intel_fat_fbd_err(ferr_fat_fbd); 12020c794b3Sgavinm channel = (ferr_fat_fbd >> 28) & 3; 12120c794b3Sgavinm sp->branch = channel >> 1; 12220c794b3Sgavinm sp->channel = channel; 12320c794b3Sgavinm if ((ferr_fat_fbd & (ERR_FAT_FBD_M2|ERR_FAT_FBD_M1)) != 0) { 12420c794b3Sgavinm if ((ferr_fat_fbd & ERR_FAT_FBD_M1) != 0) 12520c794b3Sgavinm intr = "nb.fbd.alert"; /* Alert on FB-DIMM M1 */ 12620c794b3Sgavinm else 12720c794b3Sgavinm intr = "nb.fbd.crc"; /* CRC error FB_DIMM M2 */ 12820c794b3Sgavinm nrecmema = rp->nb.fat_fbd_regs.nrecmema; 12920c794b3Sgavinm nrecmemb = rp->nb.fat_fbd_regs.nrecmemb; 13020c794b3Sgavinm sp->rank = (nrecmema >> 8) & RANK_MASK; 13120c794b3Sgavinm sp->dimm = sp->rank >> 1; 13220c794b3Sgavinm sp->bank = (nrecmema >> 12) & BANK_MASK; 13320c794b3Sgavinm sp->cas = (nrecmemb >> 16) & CAS_MASK; 13420c794b3Sgavinm sp->ras = nrecmemb & RAS_MASK; 13520c794b3Sgavinm sp->pa = dimm_getphys(sp->branch, sp->rank, sp->bank, sp->ras, 13620c794b3Sgavinm sp->cas); 13720c794b3Sgavinm sp->offset = dimm_getoffset(sp->branch, sp->rank, sp->bank, 13820c794b3Sgavinm sp->ras, sp->cas); 13920c794b3Sgavinm } else { 14020c794b3Sgavinm if ((ferr_fat_fbd & ERR_FAT_FBD_M3) != 0) 14120c794b3Sgavinm intr = "nb.fbd.otf"; /* thermal temp > Tmid M3 */ 14220c794b3Sgavinm else if ((ferr_fat_fbd & ERR_FAT_FBD_M23) != 0) { 14320c794b3Sgavinm intr = "nb.fbd.reset_timeout"; 14420c794b3Sgavinm sp->channel = -1; 14520c794b3Sgavinm } 14620c794b3Sgavinm sp->rank = -1; 14720c794b3Sgavinm sp->dimm = -1; 14820c794b3Sgavinm sp->bank = -1; 14920c794b3Sgavinm sp->cas = -1; 15020c794b3Sgavinm sp->ras = -1; 15120c794b3Sgavinm sp->pa = -1LL; 15220c794b3Sgavinm sp->offset = -1; 15320c794b3Sgavinm } 15420c794b3Sgavinm return (intr); 15520c794b3Sgavinm } 15620c794b3Sgavinm 15720c794b3Sgavinm 15820c794b3Sgavinm static struct mch_error_code nf_fbd_error_code[] = { 1595f28a827Saf { 29, EMASK_FBD_M29, ERR_NF_FBD_M29 }, 16020c794b3Sgavinm { 28, EMASK_FBD_M28, ERR_NF_FBD_M28 }, 16120c794b3Sgavinm { 27, EMASK_FBD_M27, ERR_NF_FBD_M27 }, 16220c794b3Sgavinm { 26, EMASK_FBD_M26, ERR_NF_FBD_M26 }, 16320c794b3Sgavinm { 25, EMASK_FBD_M25, ERR_NF_FBD_M25 }, 1645f28a827Saf { 24, EMASK_FBD_M24, ERR_NF_FBD_M24 }, 16520c794b3Sgavinm { 22, EMASK_FBD_M22, ERR_NF_FBD_M22 }, 16620c794b3Sgavinm { 21, EMASK_FBD_M21, ERR_NF_FBD_M21 }, 16720c794b3Sgavinm { 20, EMASK_FBD_M20, ERR_NF_FBD_M20 }, 16820c794b3Sgavinm { 19, EMASK_FBD_M19, ERR_NF_FBD_M19 }, 16920c794b3Sgavinm { 18, EMASK_FBD_M18, ERR_NF_FBD_M18 }, 17020c794b3Sgavinm { 17, EMASK_FBD_M17, ERR_NF_FBD_M17 }, 1715f28a827Saf { 16, EMASK_FBD_M16, ERR_NF_FBD_M16 }, 17220c794b3Sgavinm { 15, EMASK_FBD_M15, ERR_NF_FBD_M15 }, 17320c794b3Sgavinm { 14, EMASK_FBD_M14, ERR_NF_FBD_M14 }, 17420c794b3Sgavinm { 13, EMASK_FBD_M13, ERR_NF_FBD_M13 }, 17520c794b3Sgavinm { 12, EMASK_FBD_M12, ERR_NF_FBD_M12 }, 17620c794b3Sgavinm { 11, EMASK_FBD_M11, ERR_NF_FBD_M11 }, 17720c794b3Sgavinm { 10, EMASK_FBD_M10, ERR_NF_FBD_M10 }, 17820c794b3Sgavinm { 9, EMASK_FBD_M9, ERR_NF_FBD_M9 }, 17920c794b3Sgavinm { 8, EMASK_FBD_M8, ERR_NF_FBD_M8 }, 18020c794b3Sgavinm { 7, EMASK_FBD_M7, ERR_NF_FBD_M7 }, 18120c794b3Sgavinm { 6, EMASK_FBD_M6, ERR_NF_FBD_M6 }, 18220c794b3Sgavinm { 5, EMASK_FBD_M5, ERR_NF_FBD_M5 }, 18320c794b3Sgavinm { 4, EMASK_FBD_M4, ERR_NF_FBD_M4 } 18420c794b3Sgavinm }; 18520c794b3Sgavinm 18620c794b3Sgavinm static int 18720c794b3Sgavinm intel_nf_fbd_err(uint32_t nf_fbd) 18820c794b3Sgavinm { 18920c794b3Sgavinm int rt = -1; 19020c794b3Sgavinm int nerr = 0; 19120c794b3Sgavinm uint32_t emask_fbd = 0; 19220c794b3Sgavinm int i; 19320c794b3Sgavinm int sz; 19420c794b3Sgavinm 19520c794b3Sgavinm sz = sizeof (nf_fbd_error_code) / sizeof (struct mch_error_code); 19620c794b3Sgavinm 19720c794b3Sgavinm for (i = 0; i < sz; i++) { 19820c794b3Sgavinm if (nf_fbd & nf_fbd_error_code[i].error_bit) { 19920c794b3Sgavinm rt = nf_fbd_error_code[i].intel_error_list; 20020c794b3Sgavinm emask_fbd |= nf_fbd_error_code[i].emask; 20120c794b3Sgavinm nerr++; 20220c794b3Sgavinm } 20320c794b3Sgavinm } 20420c794b3Sgavinm if (emask_fbd) 20520c794b3Sgavinm nb_fbd_mask_mc(emask_fbd); 20620c794b3Sgavinm if (nerr > 1) 20720c794b3Sgavinm rt = -1; 20820c794b3Sgavinm return (rt); 20920c794b3Sgavinm } 21020c794b3Sgavinm 21120c794b3Sgavinm static char * 21220c794b3Sgavinm nf_memory_error(const nb_regs_t *rp, void *data) 21320c794b3Sgavinm { 21420c794b3Sgavinm uint32_t ferr_nf_fbd, recmemb, redmemb; 2155f28a827Saf uint32_t recmema; 21620c794b3Sgavinm int branch, channel, ecc_locator; 21720c794b3Sgavinm char *intr = "nb.unknown"; 21820c794b3Sgavinm nb_mem_scatchpad_t *sp = &((nb_scatchpad_t *)data)->ms; 21920c794b3Sgavinm 22020c794b3Sgavinm sp->rank = -1; 22120c794b3Sgavinm sp->dimm = -1; 22220c794b3Sgavinm sp->bank = -1; 22320c794b3Sgavinm sp->cas = -1; 22420c794b3Sgavinm sp->ras = -1LL; 22520c794b3Sgavinm sp->pa = -1LL; 22620c794b3Sgavinm sp->offset = -1; 2276cb1ca52Saf ferr_nf_fbd = rp->nb.nf_fbd_regs.ferr_nf_fbd; 2286cb1ca52Saf if ((ferr_nf_fbd & ERR_NF_FBD_MASK) == 0) { 2296cb1ca52Saf sp->branch = -1; 2306cb1ca52Saf sp->channel = -1; 2316cb1ca52Saf sp->intel_error_list = 2326cb1ca52Saf intel_nf_fbd_err(rp->nb.nf_fbd_regs.nerr_nf_fbd); 2336cb1ca52Saf return (intr); 2346cb1ca52Saf } 2356cb1ca52Saf sp->intel_error_list = intel_nf_fbd_err(ferr_nf_fbd); 2366cb1ca52Saf channel = (ferr_nf_fbd >> ERR_FBD_CH_SHIFT) & 3; 2376cb1ca52Saf branch = channel >> 1; 2386cb1ca52Saf sp->branch = branch; 2396cb1ca52Saf sp->channel = channel; 24020c794b3Sgavinm if (ferr_nf_fbd & ERR_NF_FBD_MASK) { 24120c794b3Sgavinm if (ferr_nf_fbd & ERR_NF_FBD_ECC_UE) { 24220c794b3Sgavinm /* 24320c794b3Sgavinm * uncorrectable ECC M4 - M12 24420c794b3Sgavinm * we can only isolate to pair of dimms 24520c794b3Sgavinm * for single dimm configuration let eversholt 24620c794b3Sgavinm * sort it out with out needing a special rule 24720c794b3Sgavinm */ 24820c794b3Sgavinm sp->channel = -1; 24920c794b3Sgavinm recmema = rp->nb.nf_fbd_regs.recmema; 25020c794b3Sgavinm recmemb = rp->nb.nf_fbd_regs.recmemb; 25120c794b3Sgavinm sp->rank = (recmema >> 8) & RANK_MASK; 25220c794b3Sgavinm sp->bank = (recmema >> 12) & BANK_MASK; 25320c794b3Sgavinm sp->cas = (recmemb >> 16) & CAS_MASK; 25420c794b3Sgavinm sp->ras = recmemb & RAS_MASK; 25520c794b3Sgavinm intr = "nb.mem_ue"; 25620c794b3Sgavinm } else if (ferr_nf_fbd & ERR_NF_FBD_M13) { 25720c794b3Sgavinm /* 25820c794b3Sgavinm * write error M13 25920c794b3Sgavinm * we can only isolate to pair of dimms 26020c794b3Sgavinm */ 26120c794b3Sgavinm sp->channel = -1; 26220c794b3Sgavinm if (nb_mode != NB_MEMORY_MIRROR) { 26320c794b3Sgavinm recmema = rp->nb.nf_fbd_regs.recmema; 26420c794b3Sgavinm sp->rank = (recmema >> 8) & RANK_MASK; 26520c794b3Sgavinm sp->bank = (recmema >> 12) & BANK_MASK; 26620c794b3Sgavinm sp->cas = (recmemb >> 16) & CAS_MASK; 26720c794b3Sgavinm sp->ras = recmemb & RAS_MASK; 26820c794b3Sgavinm } 26920c794b3Sgavinm intr = "nb.fbd.ma"; /* memory alert */ 27020c794b3Sgavinm } else if (ferr_nf_fbd & ERR_NF_FBD_MA) { /* M14, M15 and M21 */ 27120c794b3Sgavinm intr = "nb.fbd.ch"; /* FBD on channel */ 27220c794b3Sgavinm } else if ((ferr_nf_fbd & ERR_NF_FBD_ECC_CE) != 0) { 27320c794b3Sgavinm /* correctable ECC M17-M20 */ 27420c794b3Sgavinm recmema = rp->nb.nf_fbd_regs.recmema; 27520c794b3Sgavinm recmemb = rp->nb.nf_fbd_regs.recmemb; 27620c794b3Sgavinm sp->rank = (recmema >> 8) & RANK_MASK; 27720c794b3Sgavinm redmemb = rp->nb.nf_fbd_regs.redmemb; 27820c794b3Sgavinm ecc_locator = redmemb & 0x3ffff; 27920c794b3Sgavinm if (ecc_locator & 0x1ff) 28020c794b3Sgavinm sp->channel = branch << 1; 28120c794b3Sgavinm else if (ecc_locator & 0x3fe00) 28220c794b3Sgavinm sp->channel = (branch << 1) + 1; 28320c794b3Sgavinm sp->dimm = sp->rank >> 1; 28420c794b3Sgavinm sp->bank = (recmema >> 12) & BANK_MASK; 28520c794b3Sgavinm sp->cas = (recmemb >> 16) & CAS_MASK; 28620c794b3Sgavinm sp->ras = recmemb & RAS_MASK; 28720c794b3Sgavinm intr = "nb.mem_ce"; 28820c794b3Sgavinm } else if ((ferr_nf_fbd & ERR_NF_FBD_SPARE) != 0) { 28920c794b3Sgavinm /* spare dimm M27, M28 */ 29020c794b3Sgavinm intr = "nb.mem_ds"; 29120c794b3Sgavinm sp->channel = -1; 29220c794b3Sgavinm if (rp->nb.nf_fbd_regs.spcps & SPCPS_SPARE_DEPLOYED) { 29320c794b3Sgavinm sp->rank = 29420c794b3Sgavinm SPCPS_FAILED_RANK(rp->nb.nf_fbd_regs.spcps); 29520c794b3Sgavinm nb_used_spare_rank(sp->branch, sp->rank); 29620c794b3Sgavinm nb_config_gen++; 29720c794b3Sgavinm } 2985f28a827Saf } else if ((ferr_nf_fbd & ERR_NF_FBD_M22) != 0) { 2995f28a827Saf intr = "nb.spd"; /* SPD protocol */ 30020c794b3Sgavinm } 30120c794b3Sgavinm } 30220c794b3Sgavinm if (sp->ras != -1) { 30320c794b3Sgavinm sp->pa = dimm_getphys(sp->branch, sp->rank, sp->bank, sp->ras, 30420c794b3Sgavinm sp->cas); 30520c794b3Sgavinm sp->offset = dimm_getoffset(sp->branch, sp->rank, sp->bank, 30620c794b3Sgavinm sp->ras, sp->cas); 30720c794b3Sgavinm } 30820c794b3Sgavinm return (intr); 30920c794b3Sgavinm } 31020c794b3Sgavinm 311*85738508SVuong Nguyen static struct mch_error_code nf_mem_error_code[] = { 312*85738508SVuong Nguyen { 21, EMASK_MEM_M21, ERR_NF_MEM_M21 }, 313*85738508SVuong Nguyen { 20, EMASK_MEM_M20, ERR_NF_MEM_M20 }, 314*85738508SVuong Nguyen { 18, EMASK_MEM_M18, ERR_NF_MEM_M18 }, 315*85738508SVuong Nguyen { 16, EMASK_MEM_M16, ERR_NF_MEM_M16 }, 316*85738508SVuong Nguyen { 15, EMASK_MEM_M15, ERR_NF_MEM_M15 }, 317*85738508SVuong Nguyen { 14, EMASK_MEM_M14, ERR_NF_MEM_M14 }, 318*85738508SVuong Nguyen { 12, EMASK_MEM_M12, ERR_NF_MEM_M12 }, 319*85738508SVuong Nguyen { 11, EMASK_MEM_M11, ERR_NF_MEM_M11 }, 320*85738508SVuong Nguyen { 10, EMASK_MEM_M10, ERR_NF_MEM_M10 }, 321*85738508SVuong Nguyen { 6, EMASK_MEM_M6, ERR_NF_MEM_M6 }, 322*85738508SVuong Nguyen { 5, EMASK_MEM_M5, ERR_NF_MEM_M5 }, 323*85738508SVuong Nguyen { 4, EMASK_MEM_M4, ERR_NF_MEM_M4 }, 324*85738508SVuong Nguyen { 1, EMASK_MEM_M1, ERR_NF_MEM_M1 } 325*85738508SVuong Nguyen }; 326*85738508SVuong Nguyen 327*85738508SVuong Nguyen static int 328*85738508SVuong Nguyen intel_nf_mem_err(uint32_t nf_mem) 329*85738508SVuong Nguyen { 330*85738508SVuong Nguyen int rt = -1; 331*85738508SVuong Nguyen int nerr = 0; 332*85738508SVuong Nguyen uint32_t emask_mem = 0; 333*85738508SVuong Nguyen int i; 334*85738508SVuong Nguyen int sz; 335*85738508SVuong Nguyen 336*85738508SVuong Nguyen sz = sizeof (nf_mem_error_code) / sizeof (struct mch_error_code); 337*85738508SVuong Nguyen 338*85738508SVuong Nguyen for (i = 0; i < sz; i++) { 339*85738508SVuong Nguyen if (nf_mem & nf_mem_error_code[i].error_bit) { 340*85738508SVuong Nguyen rt = nf_mem_error_code[i].intel_error_list; 341*85738508SVuong Nguyen emask_mem |= nf_mem_error_code[i].emask; 342*85738508SVuong Nguyen nerr++; 343*85738508SVuong Nguyen } 344*85738508SVuong Nguyen } 345*85738508SVuong Nguyen if (emask_mem) 346*85738508SVuong Nguyen nb_mem_mask_mc(emask_mem); 347*85738508SVuong Nguyen if (nerr > 1) 348*85738508SVuong Nguyen rt = -1; 349*85738508SVuong Nguyen return (rt); 350*85738508SVuong Nguyen } 351*85738508SVuong Nguyen 352*85738508SVuong Nguyen static char * 353*85738508SVuong Nguyen nf_mem_error(const nb_regs_t *rp, void *data) 354*85738508SVuong Nguyen { 355*85738508SVuong Nguyen uint32_t ferr_nf_mem, recmema, recmemb; 356*85738508SVuong Nguyen uint32_t nrecmema, nrecmemb, validlog; 357*85738508SVuong Nguyen int channel; 358*85738508SVuong Nguyen char *intr = "nb.unknown"; 359*85738508SVuong Nguyen nb_mem_scatchpad_t *sp = &((nb_scatchpad_t *)data)->ms; 360*85738508SVuong Nguyen 361*85738508SVuong Nguyen sp->rank = -1; 362*85738508SVuong Nguyen sp->dimm = -1; 363*85738508SVuong Nguyen sp->bank = -1; 364*85738508SVuong Nguyen sp->cas = -1; 365*85738508SVuong Nguyen sp->ras = -1LL; 366*85738508SVuong Nguyen sp->pa = -1LL; 367*85738508SVuong Nguyen sp->offset = -1; 368*85738508SVuong Nguyen ferr_nf_mem = rp->nb.nf_mem_regs.ferr_nf_mem; 369*85738508SVuong Nguyen if ((ferr_nf_mem & ERR_NF_MEM_MASK) == 0) { 370*85738508SVuong Nguyen /* no first error found */ 371*85738508SVuong Nguyen sp->branch = -1; 372*85738508SVuong Nguyen sp->channel = -1; 373*85738508SVuong Nguyen sp->intel_error_list = 374*85738508SVuong Nguyen intel_nf_mem_err(rp->nb.nf_mem_regs.nerr_nf_mem); 375*85738508SVuong Nguyen return (intr); 376*85738508SVuong Nguyen } 377*85738508SVuong Nguyen sp->intel_error_list = intel_nf_mem_err(ferr_nf_mem); 378*85738508SVuong Nguyen 379*85738508SVuong Nguyen channel = (ferr_nf_mem >> ERR_MEM_CH_SHIFT) & 0x1; 380*85738508SVuong Nguyen sp->branch = channel; 381*85738508SVuong Nguyen sp->channel = -1; 382*85738508SVuong Nguyen if (ferr_nf_mem & ERR_NF_MEM_MASK) { 383*85738508SVuong Nguyen if (ferr_nf_mem & ERR_NF_MEM_ECC_UE) { 384*85738508SVuong Nguyen /* 385*85738508SVuong Nguyen * uncorrectable ECC M1,M4-M6,M10-M12 386*85738508SVuong Nguyen * There is only channel per branch 387*85738508SVuong Nguyen * Invalidate the channel number so the mem ereport 388*85738508SVuong Nguyen * has the same detector with existing 5000 ereports. 389*85738508SVuong Nguyen * so we can leverage the existing Everhsolt rule. 390*85738508SVuong Nguyen */ 391*85738508SVuong Nguyen validlog = rp->nb.nf_mem_regs.validlog; 392*85738508SVuong Nguyen if (ferr_nf_mem & ERR_NF_MEM_M1) { 393*85738508SVuong Nguyen nrecmema = rp->nb.nf_mem_regs.nrecmema; 394*85738508SVuong Nguyen nrecmemb = rp->nb.nf_mem_regs.nrecmemb; 395*85738508SVuong Nguyen /* check if the nrecmem log is valid */ 396*85738508SVuong Nguyen if (validlog & 0x1 || nb_check_validlog == 0) { 397*85738508SVuong Nguyen sp->rank = (nrecmema >> 8) & RANK_MASK; 398*85738508SVuong Nguyen sp->bank = (nrecmema >> 12) & BANK_MASK; 399*85738508SVuong Nguyen sp->cas = (nrecmemb >> 16) & CAS_MASK; 400*85738508SVuong Nguyen sp->ras = nrecmemb & RAS_MASK; 401*85738508SVuong Nguyen } 402*85738508SVuong Nguyen } else { 403*85738508SVuong Nguyen recmema = rp->nb.nf_mem_regs.recmema; 404*85738508SVuong Nguyen recmemb = rp->nb.nf_mem_regs.recmemb; 405*85738508SVuong Nguyen /* check if the recmem log is valid */ 406*85738508SVuong Nguyen if (validlog & 0x2 || nb_check_validlog == 0) { 407*85738508SVuong Nguyen sp->rank = (recmema >> 8) & RANK_MASK; 408*85738508SVuong Nguyen sp->bank = (recmema >> 12) & BANK_MASK; 409*85738508SVuong Nguyen sp->cas = (recmemb >> 16) & CAS_MASK; 410*85738508SVuong Nguyen sp->ras = recmemb & RAS_MASK; 411*85738508SVuong Nguyen } 412*85738508SVuong Nguyen } 413*85738508SVuong Nguyen intr = "nb.ddr2_mem_ue"; 414*85738508SVuong Nguyen } else if ((ferr_nf_mem & ERR_NF_MEM_ECC_CE) != 0) { 415*85738508SVuong Nguyen /* correctable ECC M14-M16 */ 416*85738508SVuong Nguyen recmema = rp->nb.nf_mem_regs.recmema; 417*85738508SVuong Nguyen recmemb = rp->nb.nf_mem_regs.recmemb; 418*85738508SVuong Nguyen validlog = rp->nb.nf_mem_regs.validlog; 419*85738508SVuong Nguyen /* check if the recmem log is valid */ 420*85738508SVuong Nguyen if (validlog & 0x2 || nb_check_validlog == 0) { 421*85738508SVuong Nguyen sp->channel = channel; 422*85738508SVuong Nguyen sp->rank = (recmema >> 8) & RANK_MASK; 423*85738508SVuong Nguyen sp->dimm = nb_rank2dimm(sp->channel, sp->rank); 424*85738508SVuong Nguyen sp->bank = (recmema >> 12) & BANK_MASK; 425*85738508SVuong Nguyen sp->cas = (recmemb >> 16) & CAS_MASK; 426*85738508SVuong Nguyen sp->ras = recmemb & RAS_MASK; 427*85738508SVuong Nguyen } 428*85738508SVuong Nguyen intr = "nb.ddr2_mem_ce"; 429*85738508SVuong Nguyen } else if ((ferr_nf_mem & ERR_NF_MEM_SPARE) != 0) { 430*85738508SVuong Nguyen /* spare dimm M20, M21 */ 431*85738508SVuong Nguyen intr = "nb.ddr2_mem_ds"; 432*85738508SVuong Nguyen 433*85738508SVuong Nguyen /* 434*85738508SVuong Nguyen * The channel can be valid here. 435*85738508SVuong Nguyen * However, there is only one channel per branch and 436*85738508SVuong Nguyen * to leverage the eversolt rules of other chipsets, 437*85738508SVuong Nguyen * the channel is ignored and let the rule find it out 438*85738508SVuong Nguyen * from the topology. 439*85738508SVuong Nguyen */ 440*85738508SVuong Nguyen if (rp->nb.nf_mem_regs.spcps & SPCPS_SPARE_DEPLOYED) { 441*85738508SVuong Nguyen sp->rank = 442*85738508SVuong Nguyen SPCPS_FAILED_RANK(rp->nb.nf_mem_regs.spcps); 443*85738508SVuong Nguyen nb_used_spare_rank(sp->branch, sp->rank); 444*85738508SVuong Nguyen nb_config_gen++; 445*85738508SVuong Nguyen } 446*85738508SVuong Nguyen } else if ((ferr_nf_mem & ERR_NF_MEM_M18) != 0) { 447*85738508SVuong Nguyen sp->channel = channel; 448*85738508SVuong Nguyen intr = "nb.ddr2_spd"; /* SPD protocol */ 449*85738508SVuong Nguyen 450*85738508SVuong Nguyen } 451*85738508SVuong Nguyen } 452*85738508SVuong Nguyen if (sp->ras != -1) { 453*85738508SVuong Nguyen sp->pa = dimm_getphys(sp->branch, sp->rank, sp->bank, sp->ras, 454*85738508SVuong Nguyen sp->cas); 455*85738508SVuong Nguyen sp->offset = dimm_getoffset(sp->branch, sp->rank, sp->bank, 456*85738508SVuong Nguyen sp->ras, sp->cas); 457*85738508SVuong Nguyen } 458*85738508SVuong Nguyen return (intr); 459*85738508SVuong Nguyen } 460*85738508SVuong Nguyen 46120c794b3Sgavinm static struct mch_error_code fat_int_error_code[] = { 4625f28a827Saf { 14, EMASK_INT_B14, ERR_FAT_INT_B14 }, 4635f28a827Saf { 12, EMASK_INT_B12, ERR_FAT_INT_B12 }, 4645f28a827Saf { 25, EMASK_INT_B25, ERR_FAT_INT_B25 }, 4655f28a827Saf { 23, EMASK_INT_B23, ERR_FAT_INT_B23 }, 4665f28a827Saf { 21, EMASK_INT_B21, ERR_FAT_INT_B21 }, 4676cb1ca52Saf { 7, EMASK_INT_B7, ERR_FAT_INT_B7 }, 46820c794b3Sgavinm { 4, EMASK_INT_B4, ERR_FAT_INT_B4 }, 46920c794b3Sgavinm { 3, EMASK_INT_B3, ERR_FAT_INT_B3 }, 47020c794b3Sgavinm { 2, EMASK_INT_B2, ERR_FAT_INT_B2 }, 47120c794b3Sgavinm { 1, EMASK_INT_B1, ERR_FAT_INT_B1 } 47220c794b3Sgavinm }; 47320c794b3Sgavinm 47420c794b3Sgavinm static struct mch_error_code nf_int_error_code[] = { 4755f28a827Saf { 27, 0, ERR_NF_INT_B27 }, 4765f28a827Saf { 24, 0, ERR_NF_INT_B24 }, 4775f28a827Saf { 22, EMASK_INT_B22, ERR_NF_INT_B22 }, 4785f28a827Saf { 20, EMASK_INT_B20, ERR_NF_INT_B20 }, 4795f28a827Saf { 19, EMASK_INT_B19, ERR_NF_INT_B19 }, 4805f28a827Saf { 18, 0, ERR_NF_INT_B18 }, 4815f28a827Saf { 17, 0, ERR_NF_INT_B17 }, 4825f28a827Saf { 16, 0, ERR_NF_INT_B16 }, 4835f28a827Saf { 11, EMASK_INT_B11, ERR_NF_INT_B11 }, 4845f28a827Saf { 10, EMASK_INT_B10, ERR_NF_INT_B10 }, 4855f28a827Saf { 9, EMASK_INT_B9, ERR_NF_INT_B9 }, 4866cb1ca52Saf { 8, EMASK_INT_B8, ERR_NF_INT_B8 }, 48720c794b3Sgavinm { 6, EMASK_INT_B6, ERR_NF_INT_B6 }, 48820c794b3Sgavinm { 5, EMASK_INT_B5, ERR_NF_INT_B5 } 48920c794b3Sgavinm }; 49020c794b3Sgavinm 49120c794b3Sgavinm static int 4925f28a827Saf intel_int_err(uint16_t err_fat_int, uint16_t err_nf_int) 49320c794b3Sgavinm { 49420c794b3Sgavinm int rt = -1; 49520c794b3Sgavinm int nerr = 0; 4965f28a827Saf uint32_t emask_int = 0; 49720c794b3Sgavinm int i; 49820c794b3Sgavinm int sz; 49920c794b3Sgavinm 50020c794b3Sgavinm sz = sizeof (fat_int_error_code) / sizeof (struct mch_error_code); 50120c794b3Sgavinm 50220c794b3Sgavinm for (i = 0; i < sz; i++) { 5036cb1ca52Saf if (err_fat_int & fat_int_error_code[i].error_bit) { 50420c794b3Sgavinm rt = fat_int_error_code[i].intel_error_list; 50520c794b3Sgavinm emask_int |= fat_int_error_code[i].emask; 50620c794b3Sgavinm nerr++; 50720c794b3Sgavinm } 50820c794b3Sgavinm } 50920c794b3Sgavinm 5105f28a827Saf if (nb_chipset == INTEL_NB_5400 && 5115f28a827Saf (err_nf_int & NERR_NF_5400_INT_B26) != 0) { 5125f28a827Saf err_nf_int &= ~NERR_NF_5400_INT_B26; 5135f28a827Saf rt = 26; 5145f28a827Saf nerr++; 5155f28a827Saf } 5165f28a827Saf 5179ff4cbe7SAdrian Frost if (rt) 5189ff4cbe7SAdrian Frost err_nf_int &= ~ERR_NF_INT_B18; 5199ff4cbe7SAdrian Frost 52020c794b3Sgavinm sz = sizeof (nf_int_error_code) / sizeof (struct mch_error_code); 52120c794b3Sgavinm 52220c794b3Sgavinm for (i = 0; i < sz; i++) { 5236cb1ca52Saf if (err_nf_int & nf_int_error_code[i].error_bit) { 52420c794b3Sgavinm rt = nf_int_error_code[i].intel_error_list; 52520c794b3Sgavinm emask_int |= nf_int_error_code[i].emask; 52620c794b3Sgavinm nerr++; 52720c794b3Sgavinm } 52820c794b3Sgavinm } 52920c794b3Sgavinm 53020c794b3Sgavinm if (emask_int) 53120c794b3Sgavinm nb_int_mask_mc(emask_int); 53220c794b3Sgavinm if (nerr > 1) 53320c794b3Sgavinm rt = -1; 53420c794b3Sgavinm return (rt); 53520c794b3Sgavinm } 53620c794b3Sgavinm 5379ff4cbe7SAdrian Frost static int 5380ad0f0b2SAdrian Frost log_int_err(nb_regs_t *rp, int willpanic, int *interpose) 53920c794b3Sgavinm { 54020c794b3Sgavinm int t = 0; 5419ff4cbe7SAdrian Frost int rt = 0; 54220c794b3Sgavinm 54320c794b3Sgavinm rp->flag = NB_REG_LOG_INT; 54420c794b3Sgavinm rp->nb.int_regs.ferr_fat_int = FERR_FAT_INT_RD(interpose); 54520c794b3Sgavinm rp->nb.int_regs.ferr_nf_int = FERR_NF_INT_RD(&t); 54620c794b3Sgavinm *interpose |= t; 54720c794b3Sgavinm rp->nb.int_regs.nerr_fat_int = NERR_FAT_INT_RD(&t); 54820c794b3Sgavinm *interpose |= t; 54920c794b3Sgavinm rp->nb.int_regs.nerr_nf_int = NERR_NF_INT_RD(&t); 55020c794b3Sgavinm *interpose |= t; 55120c794b3Sgavinm rp->nb.int_regs.nrecint = NRECINT_RD(); 55220c794b3Sgavinm rp->nb.int_regs.recint = RECINT_RD(); 55320c794b3Sgavinm rp->nb.int_regs.nrecsf = NRECSF_RD(); 55420c794b3Sgavinm rp->nb.int_regs.recsf = RECSF_RD(); 55520c794b3Sgavinm 5560ad0f0b2SAdrian Frost if (!willpanic) { 5570ad0f0b2SAdrian Frost if (rp->nb.int_regs.ferr_fat_int || *interpose) 5580ad0f0b2SAdrian Frost FERR_FAT_INT_WR(rp->nb.int_regs.ferr_fat_int); 5590ad0f0b2SAdrian Frost if (rp->nb.int_regs.ferr_nf_int || *interpose) 5600ad0f0b2SAdrian Frost FERR_NF_INT_WR(rp->nb.int_regs.ferr_nf_int); 5610ad0f0b2SAdrian Frost if (rp->nb.int_regs.nerr_fat_int) 5620ad0f0b2SAdrian Frost NERR_FAT_INT_WR(rp->nb.int_regs.nerr_fat_int); 5630ad0f0b2SAdrian Frost if (rp->nb.int_regs.nerr_nf_int) 5640ad0f0b2SAdrian Frost NERR_NF_INT_WR(rp->nb.int_regs.nerr_nf_int); 5650ad0f0b2SAdrian Frost /* 5660ad0f0b2SAdrian Frost * if interpose write read-only registers to clear from pcii 5670ad0f0b2SAdrian Frost * cache 5680ad0f0b2SAdrian Frost */ 5690ad0f0b2SAdrian Frost if (*interpose) { 5700ad0f0b2SAdrian Frost NRECINT_WR(); 5710ad0f0b2SAdrian Frost RECINT_WR(); 5720ad0f0b2SAdrian Frost NRECSF_WR(); 5730ad0f0b2SAdrian Frost RECSF_WR(); 5740ad0f0b2SAdrian Frost } 57520c794b3Sgavinm } 5769ff4cbe7SAdrian Frost if (rp->nb.int_regs.ferr_fat_int == 0 && 5779ff4cbe7SAdrian Frost rp->nb.int_regs.nerr_fat_int == 0 && 5789ff4cbe7SAdrian Frost (rp->nb.int_regs.ferr_nf_int == ERR_NF_INT_B18 || 5799ff4cbe7SAdrian Frost (rp->nb.int_regs.ferr_nf_int == 0 && 5809ff4cbe7SAdrian Frost rp->nb.int_regs.nerr_nf_int == ERR_NF_INT_B18))) { 5819ff4cbe7SAdrian Frost rt = 1; 5829ff4cbe7SAdrian Frost } 5839ff4cbe7SAdrian Frost return (rt); 58420c794b3Sgavinm } 58520c794b3Sgavinm 5865f28a827Saf static void 5870ad0f0b2SAdrian Frost log_thermal_err(nb_regs_t *rp, int willpanic, int *interpose) 5885f28a827Saf { 5895f28a827Saf int t = 0; 5905f28a827Saf 5915f28a827Saf rp->flag = NB_REG_LOG_THR; 5925f28a827Saf rp->nb.thr_regs.ferr_fat_thr = FERR_FAT_THR_RD(interpose); 5935f28a827Saf rp->nb.thr_regs.nerr_fat_thr = NERR_FAT_THR_RD(&t); 5945f28a827Saf *interpose |= t; 5955f28a827Saf rp->nb.thr_regs.ferr_nf_thr = FERR_NF_THR_RD(&t); 5965f28a827Saf *interpose |= t; 5975f28a827Saf rp->nb.thr_regs.nerr_nf_thr = NERR_NF_THR_RD(&t); 5985f28a827Saf *interpose |= t; 5995f28a827Saf rp->nb.thr_regs.ctsts = CTSTS_RD(); 6005f28a827Saf rp->nb.thr_regs.thrtsts = THRTSTS_RD(); 6015f28a827Saf 6020ad0f0b2SAdrian Frost if (!willpanic) { 6030ad0f0b2SAdrian Frost if (rp->nb.thr_regs.ferr_fat_thr || *interpose) 6040ad0f0b2SAdrian Frost FERR_FAT_THR_WR(rp->nb.thr_regs.ferr_fat_thr); 6050ad0f0b2SAdrian Frost if (rp->nb.thr_regs.nerr_fat_thr || *interpose) 6060ad0f0b2SAdrian Frost NERR_FAT_THR_WR(rp->nb.thr_regs.nerr_fat_thr); 6070ad0f0b2SAdrian Frost if (rp->nb.thr_regs.ferr_nf_thr || *interpose) 6080ad0f0b2SAdrian Frost FERR_NF_THR_WR(rp->nb.thr_regs.ferr_nf_thr); 6090ad0f0b2SAdrian Frost if (rp->nb.thr_regs.nerr_nf_thr || *interpose) 6100ad0f0b2SAdrian Frost NERR_NF_THR_WR(rp->nb.thr_regs.nerr_nf_thr); 6110ad0f0b2SAdrian Frost 6120ad0f0b2SAdrian Frost if (*interpose) { 6130ad0f0b2SAdrian Frost CTSTS_WR(rp->nb.thr_regs.ctsts); 6140ad0f0b2SAdrian Frost THRTSTS_WR(rp->nb.thr_regs.thrtsts); 6150ad0f0b2SAdrian Frost } 6165f28a827Saf } 6175f28a827Saf } 6185f28a827Saf 61920c794b3Sgavinm static void 62020c794b3Sgavinm log_dma_err(nb_regs_t *rp, int *interpose) 62120c794b3Sgavinm { 62220c794b3Sgavinm rp->flag = NB_REG_LOG_DMA; 62320c794b3Sgavinm 62420c794b3Sgavinm rp->nb.dma_regs.pcists = PCISTS_RD(interpose); 62520c794b3Sgavinm rp->nb.dma_regs.pexdevsts = PCIDEVSTS_RD(); 62620c794b3Sgavinm } 62720c794b3Sgavinm 6286cb1ca52Saf static struct mch_error_code fat_fsb_error_code[] = { 6296cb1ca52Saf { 9, EMASK_FSB_F9, ERR_FAT_FSB_F9 }, 6306cb1ca52Saf { 2, EMASK_FSB_F2, ERR_FAT_FSB_F2 }, 6316cb1ca52Saf { 1, EMASK_FSB_F1, ERR_FAT_FSB_F1 } 6326cb1ca52Saf }; 6336cb1ca52Saf 6346cb1ca52Saf static struct mch_error_code nf_fsb_error_code[] = { 6356cb1ca52Saf { 8, EMASK_FSB_F8, ERR_NF_FSB_F8 }, 6366cb1ca52Saf { 7, EMASK_FSB_F7, ERR_NF_FSB_F7 }, 6376cb1ca52Saf { 6, EMASK_FSB_F6, ERR_NF_FSB_F6 } 6386cb1ca52Saf }; 6396cb1ca52Saf 64020c794b3Sgavinm static int 6416cb1ca52Saf intel_fsb_err(int fsb, uint8_t err_fat_fsb, uint8_t err_nf_fsb) 64220c794b3Sgavinm { 64320c794b3Sgavinm int rt = -1; 64420c794b3Sgavinm int nerr = 0; 64520c794b3Sgavinm uint16_t emask_fsb = 0; 6466cb1ca52Saf int i; 6476cb1ca52Saf int sz; 64820c794b3Sgavinm 6496cb1ca52Saf sz = sizeof (fat_fsb_error_code) / sizeof (struct mch_error_code); 6506cb1ca52Saf 6516cb1ca52Saf for (i = 0; i < sz; i++) { 6526cb1ca52Saf if (err_fat_fsb & fat_fsb_error_code[i].error_bit) { 6536cb1ca52Saf rt = fat_fsb_error_code[i].intel_error_list; 6546cb1ca52Saf emask_fsb |= fat_fsb_error_code[i].emask; 6556cb1ca52Saf nerr++; 6566cb1ca52Saf } 65720c794b3Sgavinm } 6586cb1ca52Saf 6596cb1ca52Saf sz = sizeof (nf_fsb_error_code) / sizeof (struct mch_error_code); 6606cb1ca52Saf 6616cb1ca52Saf for (i = 0; i < sz; i++) { 6626cb1ca52Saf if (err_nf_fsb & nf_fsb_error_code[i].error_bit) { 6636cb1ca52Saf rt = nf_fsb_error_code[i].intel_error_list; 6646cb1ca52Saf emask_fsb |= nf_fsb_error_code[i].emask; 6656cb1ca52Saf nerr++; 6666cb1ca52Saf } 66720c794b3Sgavinm } 6686cb1ca52Saf 66920c794b3Sgavinm if (emask_fsb) 67020c794b3Sgavinm nb_fsb_mask_mc(fsb, emask_fsb); 67120c794b3Sgavinm if (nerr > 1) 67220c794b3Sgavinm rt = -1; 67320c794b3Sgavinm return (rt); 67420c794b3Sgavinm } 67520c794b3Sgavinm 67620c794b3Sgavinm static void 6770ad0f0b2SAdrian Frost log_fsb_err(uint64_t ferr, nb_regs_t *rp, int willpanic, int *interpose) 67820c794b3Sgavinm { 67920c794b3Sgavinm uint8_t fsb; 68020c794b3Sgavinm int t = 0; 68120c794b3Sgavinm 68220c794b3Sgavinm fsb = GE_FERR_FSB(ferr); 68320c794b3Sgavinm rp->flag = NB_REG_LOG_FSB; 68420c794b3Sgavinm 68520c794b3Sgavinm rp->nb.fsb_regs.fsb = fsb; 68620c794b3Sgavinm rp->nb.fsb_regs.ferr_fat_fsb = FERR_FAT_FSB_RD(fsb, interpose); 68720c794b3Sgavinm rp->nb.fsb_regs.ferr_nf_fsb = FERR_NF_FSB_RD(fsb, &t); 68820c794b3Sgavinm *interpose |= t; 68920c794b3Sgavinm rp->nb.fsb_regs.nerr_fat_fsb = NERR_FAT_FSB_RD(fsb, &t); 69020c794b3Sgavinm *interpose |= t; 69120c794b3Sgavinm rp->nb.fsb_regs.nerr_nf_fsb = NERR_NF_FSB_RD(fsb, &t); 69220c794b3Sgavinm *interpose |= t; 69320c794b3Sgavinm rp->nb.fsb_regs.nrecfsb = NRECFSB_RD(fsb); 69420c794b3Sgavinm rp->nb.fsb_regs.nrecfsb_addr = NRECADDR_RD(fsb); 69520c794b3Sgavinm rp->nb.fsb_regs.recfsb = RECFSB_RD(fsb); 6960ad0f0b2SAdrian Frost if (!willpanic) { 6972d532312SVuong Nguyen /* Clear the fatal/non-fatal first/next FSB errors */ 6980ad0f0b2SAdrian Frost if (rp->nb.fsb_regs.ferr_fat_fsb || *interpose) 6990ad0f0b2SAdrian Frost FERR_FAT_FSB_WR(fsb, rp->nb.fsb_regs.ferr_fat_fsb); 7000ad0f0b2SAdrian Frost if (rp->nb.fsb_regs.ferr_nf_fsb || *interpose) 7010ad0f0b2SAdrian Frost FERR_NF_FSB_WR(fsb, rp->nb.fsb_regs.ferr_nf_fsb); 7022d532312SVuong Nguyen if (rp->nb.fsb_regs.nerr_fat_fsb || *interpose) 7032d532312SVuong Nguyen NERR_FAT_FSB_WR(fsb, rp->nb.fsb_regs.nerr_fat_fsb); 7042d532312SVuong Nguyen if (rp->nb.fsb_regs.nerr_nf_fsb || *interpose) 7052d532312SVuong Nguyen NERR_NF_FSB_WR(fsb, rp->nb.fsb_regs.nerr_nf_fsb); 7062d532312SVuong Nguyen 7070ad0f0b2SAdrian Frost /* 7080ad0f0b2SAdrian Frost * if interpose write read-only registers to clear from pcii 7090ad0f0b2SAdrian Frost * cache 7100ad0f0b2SAdrian Frost */ 7110ad0f0b2SAdrian Frost if (*interpose) { 7120ad0f0b2SAdrian Frost NRECFSB_WR(fsb); 7130ad0f0b2SAdrian Frost NRECADDR_WR(fsb); 7140ad0f0b2SAdrian Frost RECFSB_WR(fsb); 7150ad0f0b2SAdrian Frost } 71620c794b3Sgavinm } 71720c794b3Sgavinm } 71820c794b3Sgavinm 71920c794b3Sgavinm static struct mch_error_code fat_pex_error_code[] = { 72020c794b3Sgavinm { 19, EMASK_UNCOR_PEX_IO19, PEX_FAT_IO19 }, 72120c794b3Sgavinm { 18, EMASK_UNCOR_PEX_IO18, PEX_FAT_IO18 }, 72220c794b3Sgavinm { 10, EMASK_UNCOR_PEX_IO10, PEX_FAT_IO10 }, 72320c794b3Sgavinm { 9, EMASK_UNCOR_PEX_IO9, PEX_FAT_IO9 }, 72420c794b3Sgavinm { 8, EMASK_UNCOR_PEX_IO8, PEX_FAT_IO8 }, 72520c794b3Sgavinm { 7, EMASK_UNCOR_PEX_IO7, PEX_FAT_IO7 }, 72620c794b3Sgavinm { 6, EMASK_UNCOR_PEX_IO6, PEX_FAT_IO6 }, 72720c794b3Sgavinm { 5, EMASK_UNCOR_PEX_IO5, PEX_FAT_IO5 }, 72820c794b3Sgavinm { 4, EMASK_UNCOR_PEX_IO4, PEX_FAT_IO4 }, 72920c794b3Sgavinm { 3, EMASK_UNCOR_PEX_IO3, PEX_FAT_IO3 }, 73020c794b3Sgavinm { 2, EMASK_UNCOR_PEX_IO2, PEX_FAT_IO2 }, 73120c794b3Sgavinm { 0, EMASK_UNCOR_PEX_IO0, PEX_FAT_IO0 } 73220c794b3Sgavinm }; 73320c794b3Sgavinm 7345f28a827Saf static struct mch_error_code fat_unit_pex_5400_error_code[] = { 7355f28a827Saf { 32, EMASK_UNIT_PEX_IO32, PEX_5400_FAT_IO32 }, 7365f28a827Saf { 31, EMASK_UNIT_PEX_IO31, PEX_5400_FAT_IO31 }, 7375f28a827Saf { 30, EMASK_UNIT_PEX_IO30, PEX_5400_FAT_IO30 }, 7385f28a827Saf { 29, EMASK_UNIT_PEX_IO29, PEX_5400_FAT_IO29 }, 7395f28a827Saf { 27, EMASK_UNIT_PEX_IO27, PEX_5400_FAT_IO27 }, 7405f28a827Saf { 26, EMASK_UNIT_PEX_IO26, PEX_5400_FAT_IO26 }, 7415f28a827Saf { 25, EMASK_UNIT_PEX_IO25, PEX_5400_FAT_IO25 }, 7425f28a827Saf { 24, EMASK_UNIT_PEX_IO24, PEX_5400_FAT_IO24 }, 7435f28a827Saf { 23, EMASK_UNIT_PEX_IO23, PEX_5400_FAT_IO23 }, 7445f28a827Saf { 22, EMASK_UNIT_PEX_IO22, PEX_5400_FAT_IO22 }, 7455f28a827Saf }; 7465f28a827Saf 7475f28a827Saf static struct mch_error_code fat_pex_5400_error_code[] = { 7485f28a827Saf { 19, EMASK_UNCOR_PEX_IO19, PEX_5400_FAT_IO19 }, 7495f28a827Saf { 18, EMASK_UNCOR_PEX_IO18, PEX_5400_FAT_IO18 }, 7505f28a827Saf { 10, EMASK_UNCOR_PEX_IO10, PEX_5400_FAT_IO10 }, 7515f28a827Saf { 9, EMASK_UNCOR_PEX_IO9, PEX_5400_FAT_IO9 }, 7525f28a827Saf { 8, EMASK_UNCOR_PEX_IO8, PEX_5400_FAT_IO8 }, 7535f28a827Saf { 7, EMASK_UNCOR_PEX_IO7, PEX_5400_FAT_IO7 }, 7545f28a827Saf { 6, EMASK_UNCOR_PEX_IO6, PEX_5400_FAT_IO6 }, 7555f28a827Saf { 5, EMASK_UNCOR_PEX_IO5, PEX_5400_FAT_IO5 }, 7565f28a827Saf { 4, EMASK_UNCOR_PEX_IO4, PEX_5400_FAT_IO4 }, 7575f28a827Saf { 2, EMASK_UNCOR_PEX_IO2, PEX_5400_FAT_IO2 }, 7585f28a827Saf { 0, EMASK_UNCOR_PEX_IO0, PEX_5400_FAT_IO0 } 7595f28a827Saf }; 7605f28a827Saf 7615f28a827Saf static struct mch_error_code fat_rp_5400_error_code[] = { 7625f28a827Saf { 1, EMASK_RP_PEX_IO1, PEX_5400_FAT_IO1 } 7635f28a827Saf }; 7645f28a827Saf 76520c794b3Sgavinm static struct mch_error_code fat_rp_error_code[] = { 76620c794b3Sgavinm { 1, EMASK_RP_PEX_IO1, PEX_FAT_IO1 } 76720c794b3Sgavinm }; 76820c794b3Sgavinm 76920c794b3Sgavinm static struct mch_error_code uncor_pex_error_code[] = { 77020c794b3Sgavinm { 19, EMASK_UNCOR_PEX_IO19, PEX_NF_IO19 }, 77120c794b3Sgavinm { 9, EMASK_UNCOR_PEX_IO9, PEX_NF_IO9 }, 77220c794b3Sgavinm { 8, EMASK_UNCOR_PEX_IO8, PEX_NF_IO8 }, 77320c794b3Sgavinm { 7, EMASK_UNCOR_PEX_IO7, PEX_NF_IO7 }, 77420c794b3Sgavinm { 6, EMASK_UNCOR_PEX_IO6, PEX_NF_IO6 }, 77520c794b3Sgavinm { 5, EMASK_UNCOR_PEX_IO5, PEX_NF_IO5 }, 77620c794b3Sgavinm { 4, EMASK_UNCOR_PEX_IO4, PEX_NF_IO4 }, 77720c794b3Sgavinm { 3, EMASK_UNCOR_PEX_IO3, PEX_NF_IO3 }, 77820c794b3Sgavinm { 0, EMASK_UNCOR_PEX_IO0, PEX_NF_IO0 } 77920c794b3Sgavinm }; 78020c794b3Sgavinm 7815f28a827Saf static struct mch_error_code uncor_pex_5400_error_code[] = { 7825f28a827Saf { 33, EMASK_UNIT_PEX_IO33, PEX_5400_NF_IO33 }, 7835f28a827Saf { 32, EMASK_UNIT_PEX_IO32, PEX_5400_NF_IO32 }, 7845f28a827Saf { 31, EMASK_UNIT_PEX_IO31, PEX_5400_NF_IO31 }, 7855f28a827Saf { 30, EMASK_UNIT_PEX_IO30, PEX_5400_NF_IO30 }, 7865f28a827Saf { 29, EMASK_UNIT_PEX_IO29, PEX_5400_NF_IO29 }, 7875f28a827Saf { 28, EMASK_UNIT_PEX_IO28, PEX_5400_NF_IO28 }, 7885f28a827Saf { 27, EMASK_UNIT_PEX_IO27, PEX_5400_NF_IO27 }, 7895f28a827Saf { 26, EMASK_UNIT_PEX_IO26, PEX_5400_NF_IO26 }, 7905f28a827Saf { 25, EMASK_UNIT_PEX_IO25, PEX_5400_NF_IO25 }, 7915f28a827Saf { 24, EMASK_UNIT_PEX_IO24, PEX_5400_NF_IO24 }, 7925f28a827Saf { 23, EMASK_UNIT_PEX_IO23, PEX_5400_NF_IO23 }, 7935f28a827Saf }; 7945f28a827Saf 79520c794b3Sgavinm static struct mch_error_code cor_pex_error_code[] = { 7965f28a827Saf { 20, EMASK_COR_PEX_IO20, PEX_5400_NF_IO20 }, 79720c794b3Sgavinm { 16, EMASK_COR_PEX_IO16, PEX_NF_IO16 }, 79820c794b3Sgavinm { 15, EMASK_COR_PEX_IO15, PEX_NF_IO15 }, 79920c794b3Sgavinm { 14, EMASK_COR_PEX_IO14, PEX_NF_IO14 }, 80020c794b3Sgavinm { 13, EMASK_COR_PEX_IO13, PEX_NF_IO13 }, 80120c794b3Sgavinm { 12, EMASK_COR_PEX_IO12, PEX_NF_IO12 }, 80220c794b3Sgavinm { 10, 0, PEX_NF_IO10 }, 80320c794b3Sgavinm { 2, 0, PEX_NF_IO2 } 80420c794b3Sgavinm }; 80520c794b3Sgavinm 8065f28a827Saf static struct mch_error_code rp_pex_5400_error_code[] = { 8075f28a827Saf { 17, EMASK_RP_PEX_IO17, PEX_5400_NF_IO17 }, 8085f28a827Saf { 11, EMASK_RP_PEX_IO11, PEX_5400_NF_IO11 } 8095f28a827Saf }; 8105f28a827Saf 8115f28a827Saf static struct mch_error_code cor_pex_5400_error_code1[] = { 8125f28a827Saf { 19, EMASK_UNCOR_PEX_IO19, PEX_5400_NF_IO19 }, 8135f28a827Saf { 10, EMASK_UNCOR_PEX_IO10, PEX_5400_NF_IO10 }, 8145f28a827Saf { 9, EMASK_UNCOR_PEX_IO9, PEX_5400_NF_IO9 }, 8155f28a827Saf { 8, EMASK_UNCOR_PEX_IO8, PEX_5400_NF_IO8 }, 8165f28a827Saf { 7, EMASK_UNCOR_PEX_IO7, PEX_5400_NF_IO7 }, 8175f28a827Saf { 6, EMASK_UNCOR_PEX_IO6, PEX_5400_NF_IO6 }, 8185f28a827Saf { 5, EMASK_UNCOR_PEX_IO5, PEX_5400_NF_IO5 }, 8195f28a827Saf { 4, EMASK_UNCOR_PEX_IO4, PEX_5400_NF_IO4 }, 8205f28a827Saf { 2, EMASK_UNCOR_PEX_IO2, PEX_5400_NF_IO2 }, 8215f28a827Saf { 0, EMASK_UNCOR_PEX_IO0, PEX_5400_NF_IO0 } 8225f28a827Saf }; 8235f28a827Saf 8245f28a827Saf static struct mch_error_code cor_pex_5400_error_code2[] = { 8255f28a827Saf { 20, EMASK_COR_PEX_IO20, PEX_5400_NF_IO20 }, 8265f28a827Saf { 16, EMASK_COR_PEX_IO16, PEX_5400_NF_IO16 }, 8275f28a827Saf { 15, EMASK_COR_PEX_IO15, PEX_5400_NF_IO15 }, 8285f28a827Saf { 14, EMASK_COR_PEX_IO14, PEX_5400_NF_IO14 }, 8295f28a827Saf { 13, EMASK_COR_PEX_IO13, PEX_5400_NF_IO13 }, 8305f28a827Saf { 12, EMASK_COR_PEX_IO12, PEX_5400_NF_IO12 } 8315f28a827Saf }; 8325f28a827Saf 8335f28a827Saf static struct mch_error_code cor_pex_5400_error_code3[] = { 8345f28a827Saf { 33, EMASK_UNIT_PEX_IO33, PEX_5400_NF_IO33 }, 8355f28a827Saf { 32, EMASK_UNIT_PEX_IO32, PEX_5400_NF_IO32 }, 8365f28a827Saf { 31, EMASK_UNIT_PEX_IO31, PEX_5400_NF_IO31 }, 8375f28a827Saf { 30, EMASK_UNIT_PEX_IO30, PEX_5400_NF_IO30 }, 8385f28a827Saf { 29, EMASK_UNIT_PEX_IO29, PEX_5400_NF_IO29 }, 8395f28a827Saf { 28, EMASK_UNIT_PEX_IO28, PEX_5400_NF_IO28 }, 8405f28a827Saf { 27, EMASK_UNIT_PEX_IO27, PEX_5400_NF_IO27 }, 8415f28a827Saf { 26, EMASK_UNIT_PEX_IO26, PEX_5400_NF_IO26 }, 8425f28a827Saf { 25, EMASK_UNIT_PEX_IO25, PEX_5400_NF_IO25 }, 8435f28a827Saf { 24, EMASK_UNIT_PEX_IO24, PEX_5400_NF_IO24 }, 8445f28a827Saf { 23, EMASK_UNIT_PEX_IO23, PEX_5400_NF_IO23 } 8455f28a827Saf }; 8465f28a827Saf 84720c794b3Sgavinm static struct mch_error_code rp_pex_error_code[] = { 84820c794b3Sgavinm { 17, EMASK_RP_PEX_IO17, PEX_NF_IO17 }, 84920c794b3Sgavinm { 11, EMASK_RP_PEX_IO11, PEX_NF_IO11 }, 85020c794b3Sgavinm }; 85120c794b3Sgavinm 85220c794b3Sgavinm static int 85320c794b3Sgavinm intel_pex_err(uint32_t pex_fat, uint32_t pex_nf_cor) 85420c794b3Sgavinm { 85520c794b3Sgavinm int rt = -1; 85620c794b3Sgavinm int nerr = 0; 85720c794b3Sgavinm int i; 85820c794b3Sgavinm int sz; 85920c794b3Sgavinm 86020c794b3Sgavinm sz = sizeof (fat_pex_error_code) / sizeof (struct mch_error_code); 86120c794b3Sgavinm 86220c794b3Sgavinm for (i = 0; i < sz; i++) { 86320c794b3Sgavinm if (pex_fat & fat_pex_error_code[i].error_bit) { 86420c794b3Sgavinm rt = fat_pex_error_code[i].intel_error_list; 86520c794b3Sgavinm nerr++; 86620c794b3Sgavinm } 86720c794b3Sgavinm } 86820c794b3Sgavinm sz = sizeof (fat_rp_error_code) / sizeof (struct mch_error_code); 86920c794b3Sgavinm 87020c794b3Sgavinm for (i = 0; i < sz; i++) { 87120c794b3Sgavinm if (pex_fat & fat_rp_error_code[i].error_bit) { 87220c794b3Sgavinm rt = fat_rp_error_code[i].intel_error_list; 87320c794b3Sgavinm nerr++; 87420c794b3Sgavinm } 87520c794b3Sgavinm } 87620c794b3Sgavinm sz = sizeof (uncor_pex_error_code) / sizeof (struct mch_error_code); 87720c794b3Sgavinm 87820c794b3Sgavinm for (i = 0; i < sz; i++) { 87920c794b3Sgavinm if (pex_nf_cor & uncor_pex_error_code[i].error_bit) { 88020c794b3Sgavinm rt = uncor_pex_error_code[i].intel_error_list; 88120c794b3Sgavinm nerr++; 88220c794b3Sgavinm } 88320c794b3Sgavinm } 88420c794b3Sgavinm 88520c794b3Sgavinm sz = sizeof (cor_pex_error_code) / sizeof (struct mch_error_code); 88620c794b3Sgavinm 88720c794b3Sgavinm for (i = 0; i < sz; i++) { 88820c794b3Sgavinm if (pex_nf_cor & cor_pex_error_code[i].error_bit) { 88920c794b3Sgavinm rt = cor_pex_error_code[i].intel_error_list; 89020c794b3Sgavinm nerr++; 89120c794b3Sgavinm } 89220c794b3Sgavinm } 89320c794b3Sgavinm sz = sizeof (rp_pex_error_code) / sizeof (struct mch_error_code); 89420c794b3Sgavinm 89520c794b3Sgavinm for (i = 0; i < sz; i++) { 89620c794b3Sgavinm if (pex_nf_cor & rp_pex_error_code[i].error_bit) { 89720c794b3Sgavinm rt = rp_pex_error_code[i].intel_error_list; 89820c794b3Sgavinm nerr++; 89920c794b3Sgavinm } 90020c794b3Sgavinm } 90120c794b3Sgavinm 90220c794b3Sgavinm if (nerr > 1) 90320c794b3Sgavinm rt = -1; 90420c794b3Sgavinm return (rt); 90520c794b3Sgavinm } 9065f28a827Saf 9075f28a827Saf static struct mch_error_code fat_thr_error_code[] = { 9085f28a827Saf { 2, EMASK_THR_F2, ERR_FAT_THR_F2 }, 9095f28a827Saf { 1, EMASK_THR_F1, ERR_FAT_THR_F1 } 9105f28a827Saf }; 9115f28a827Saf 9125f28a827Saf static struct mch_error_code nf_thr_error_code[] = { 9135f28a827Saf { 5, EMASK_THR_F5, ERR_NF_THR_F5 }, 9145f28a827Saf { 4, EMASK_THR_F4, ERR_NF_THR_F4 }, 9155f28a827Saf { 3, EMASK_THR_F3, ERR_NF_THR_F3 } 9165f28a827Saf }; 9175f28a827Saf 9185f28a827Saf static int 9195f28a827Saf intel_thr_err(uint8_t err_fat_thr, uint8_t err_nf_thr) 9205f28a827Saf { 9215f28a827Saf int rt = -1; 9225f28a827Saf int nerr = 0; 9235f28a827Saf uint16_t emask_thr = 0; 9245f28a827Saf int i; 9255f28a827Saf int sz; 9265f28a827Saf 9275f28a827Saf sz = sizeof (fat_thr_error_code) / sizeof (struct mch_error_code); 9285f28a827Saf 9295f28a827Saf for (i = 0; i < sz; i++) { 9305f28a827Saf if (err_fat_thr & fat_thr_error_code[i].error_bit) { 9315f28a827Saf rt = fat_thr_error_code[i].intel_error_list; 9325f28a827Saf emask_thr |= fat_thr_error_code[i].emask; 9335f28a827Saf nerr++; 9345f28a827Saf } 9355f28a827Saf } 9365f28a827Saf 9375f28a827Saf sz = sizeof (nf_thr_error_code) / sizeof (struct mch_error_code); 9385f28a827Saf 9395f28a827Saf for (i = 0; i < sz; i++) { 9405f28a827Saf if (err_nf_thr & nf_thr_error_code[i].error_bit) { 9415f28a827Saf rt = nf_thr_error_code[i].intel_error_list; 9425f28a827Saf emask_thr |= nf_thr_error_code[i].emask; 9435f28a827Saf nerr++; 9445f28a827Saf } 9455f28a827Saf } 9465f28a827Saf 9475f28a827Saf if (emask_thr) 9485f28a827Saf nb_thr_mask_mc(emask_thr); 9495f28a827Saf if (nerr > 1) 9505f28a827Saf rt = -1; 9515f28a827Saf return (rt); 9525f28a827Saf } 9535f28a827Saf 9545f28a827Saf static int 9555f28a827Saf intel_pex_5400_err(uint32_t pex_fat, uint32_t pex_nf_cor) 9565f28a827Saf { 9575f28a827Saf int rt = -1; 9585f28a827Saf int nerr = 0; 9595f28a827Saf int i; 9605f28a827Saf int sz; 9615f28a827Saf 9625f28a827Saf sz = sizeof (fat_pex_5400_error_code) / sizeof (struct mch_error_code); 9635f28a827Saf 9645f28a827Saf for (i = 0; i < sz; i++) { 9655f28a827Saf if (pex_fat & fat_pex_5400_error_code[i].error_bit) { 9665f28a827Saf rt = fat_pex_5400_error_code[i].intel_error_list; 9675f28a827Saf nerr++; 9685f28a827Saf } 9695f28a827Saf } 9705f28a827Saf sz = sizeof (fat_rp_5400_error_code) / sizeof (struct mch_error_code); 9715f28a827Saf 9725f28a827Saf for (i = 0; i < sz; i++) { 9735f28a827Saf if (pex_fat & fat_rp_5400_error_code[i].error_bit) { 9745f28a827Saf rt = fat_rp_5400_error_code[i].intel_error_list; 9755f28a827Saf nerr++; 9765f28a827Saf } 9775f28a827Saf } 9785f28a827Saf sz = sizeof (fat_unit_pex_5400_error_code) / 9795f28a827Saf sizeof (struct mch_error_code); 9805f28a827Saf 9815f28a827Saf for (i = 0; i < sz; i++) { 9825f28a827Saf if (pex_fat & 9835f28a827Saf fat_unit_pex_5400_error_code[i].error_bit) { 9845f28a827Saf rt = fat_unit_pex_5400_error_code[i].intel_error_list; 9855f28a827Saf nerr++; 9865f28a827Saf } 9875f28a827Saf } 9885f28a827Saf sz = sizeof (uncor_pex_5400_error_code) / 9895f28a827Saf sizeof (struct mch_error_code); 9905f28a827Saf 9915f28a827Saf for (i = 0; i < sz; i++) { 9925f28a827Saf if (pex_fat & uncor_pex_5400_error_code[i].error_bit) { 9935f28a827Saf rt = uncor_pex_5400_error_code[i].intel_error_list; 9945f28a827Saf nerr++; 9955f28a827Saf } 9965f28a827Saf } 9975f28a827Saf 9985f28a827Saf sz = sizeof (rp_pex_5400_error_code) / sizeof (struct mch_error_code); 9995f28a827Saf 10005f28a827Saf for (i = 0; i < sz; i++) { 10015f28a827Saf if (pex_nf_cor & rp_pex_5400_error_code[i].error_bit) { 10025f28a827Saf rt = rp_pex_5400_error_code[i].intel_error_list; 10035f28a827Saf nerr++; 10045f28a827Saf } 10055f28a827Saf } 10065f28a827Saf 10075f28a827Saf sz = sizeof (cor_pex_5400_error_code1) / sizeof (struct mch_error_code); 10085f28a827Saf 10095f28a827Saf for (i = 0; i < sz; i++) { 10105f28a827Saf if (pex_nf_cor & cor_pex_5400_error_code1[i].error_bit) { 10115f28a827Saf rt = cor_pex_5400_error_code1[i].intel_error_list; 10125f28a827Saf nerr++; 10135f28a827Saf } 10145f28a827Saf } 10155f28a827Saf 10165f28a827Saf sz = sizeof (cor_pex_5400_error_code2) / sizeof (struct mch_error_code); 10175f28a827Saf 10185f28a827Saf for (i = 0; i < sz; i++) { 10195f28a827Saf if (pex_nf_cor & cor_pex_5400_error_code2[i].error_bit) { 10205f28a827Saf rt = cor_pex_5400_error_code2[i].intel_error_list; 10215f28a827Saf nerr++; 10225f28a827Saf } 10235f28a827Saf } 10245f28a827Saf 10255f28a827Saf sz = sizeof (cor_pex_5400_error_code3) / sizeof (struct mch_error_code); 10265f28a827Saf 10275f28a827Saf for (i = 0; i < sz; i++) { 10285f28a827Saf if (pex_nf_cor & cor_pex_5400_error_code3[i].error_bit) { 10295f28a827Saf rt = cor_pex_5400_error_code3[i].intel_error_list; 10305f28a827Saf nerr++; 10315f28a827Saf } 10325f28a827Saf } 10335f28a827Saf 10345f28a827Saf if (nerr > 1) 10355f28a827Saf rt = -1; 10365f28a827Saf return (rt); 10375f28a827Saf } 10385f28a827Saf 103920c794b3Sgavinm static void 10400ad0f0b2SAdrian Frost log_pex_err(uint64_t ferr, nb_regs_t *rp, int willpanic, int *interpose) 104120c794b3Sgavinm { 104220c794b3Sgavinm uint8_t pex = (uint8_t)-1; 104320c794b3Sgavinm int t = 0; 104420c794b3Sgavinm 104520c794b3Sgavinm rp->flag = NB_REG_LOG_PEX; 104620c794b3Sgavinm pex = GE_ERR_PEX(ferr); 104720c794b3Sgavinm 104820c794b3Sgavinm rp->nb.pex_regs.pex = pex; 104920c794b3Sgavinm rp->nb.pex_regs.pex_fat_ferr = PEX_FAT_FERR_RD(pex, interpose); 105020c794b3Sgavinm rp->nb.pex_regs.pex_fat_nerr = PEX_FAT_NERR_RD(pex, &t); 105120c794b3Sgavinm *interpose |= t; 105220c794b3Sgavinm rp->nb.pex_regs.pex_nf_corr_ferr = PEX_NF_FERR_RD(pex, &t); 105320c794b3Sgavinm *interpose |= t; 105420c794b3Sgavinm rp->nb.pex_regs.pex_nf_corr_nerr = PEX_NF_NERR_RD(pex, &t); 105520c794b3Sgavinm *interpose |= t; 105620c794b3Sgavinm rp->nb.pex_regs.uncerrsev = UNCERRSEV_RD(pex); 105720c794b3Sgavinm rp->nb.pex_regs.rperrsts = RPERRSTS_RD(pex); 105820c794b3Sgavinm rp->nb.pex_regs.rperrsid = RPERRSID_RD(pex); 105920c794b3Sgavinm if (pex != (uint8_t)-1) 106020c794b3Sgavinm rp->nb.pex_regs.uncerrsts = UNCERRSTS_RD(pex); 106120c794b3Sgavinm else 106220c794b3Sgavinm rp->nb.pex_regs.uncerrsts = 0; 106320c794b3Sgavinm rp->nb.pex_regs.aerrcapctrl = AERRCAPCTRL_RD(pex); 106420c794b3Sgavinm rp->nb.pex_regs.corerrsts = CORERRSTS_RD(pex); 106520c794b3Sgavinm rp->nb.pex_regs.pexdevsts = PEXDEVSTS_RD(pex); 106620c794b3Sgavinm 10670ad0f0b2SAdrian Frost if (!willpanic) { 10680ad0f0b2SAdrian Frost if (rp->nb.pex_regs.pex_fat_ferr || *interpose) 10690ad0f0b2SAdrian Frost PEX_FAT_FERR_WR(pex, rp->nb.pex_regs.pex_fat_ferr); 10700ad0f0b2SAdrian Frost if (rp->nb.pex_regs.pex_fat_nerr) 10710ad0f0b2SAdrian Frost PEX_FAT_NERR_WR(pex, rp->nb.pex_regs.pex_fat_nerr); 10720ad0f0b2SAdrian Frost if (rp->nb.pex_regs.pex_nf_corr_ferr || *interpose) 10730ad0f0b2SAdrian Frost PEX_NF_FERR_WR(pex, rp->nb.pex_regs.pex_nf_corr_ferr); 10740ad0f0b2SAdrian Frost if (rp->nb.pex_regs.pex_nf_corr_nerr) 10750ad0f0b2SAdrian Frost PEX_NF_NERR_WR(pex, rp->nb.pex_regs.pex_nf_corr_nerr); 10760ad0f0b2SAdrian Frost if (*interpose) 10770ad0f0b2SAdrian Frost UNCERRSTS_WR(pex, rp->nb.pex_regs.uncerrsts); 10780ad0f0b2SAdrian Frost if (*interpose) 10790ad0f0b2SAdrian Frost RPERRSTS_WR(pex, rp->nb.pex_regs.rperrsts); 10800ad0f0b2SAdrian Frost if (*interpose) 10810ad0f0b2SAdrian Frost PEXDEVSTS_WR(pex, 0); 10820ad0f0b2SAdrian Frost } 108320c794b3Sgavinm } 108420c794b3Sgavinm 108520c794b3Sgavinm static void 10860ad0f0b2SAdrian Frost log_fat_fbd_err(nb_regs_t *rp, int willpanic, int *interpose) 108720c794b3Sgavinm { 108820c794b3Sgavinm int channel, branch; 108920c794b3Sgavinm int t = 0; 109020c794b3Sgavinm 109120c794b3Sgavinm rp->flag = NB_REG_LOG_FAT_FBD; 109220c794b3Sgavinm rp->nb.fat_fbd_regs.ferr_fat_fbd = FERR_FAT_FBD_RD(interpose); 109320c794b3Sgavinm channel = (rp->nb.fat_fbd_regs.ferr_fat_fbd >> 28) & 3; 109420c794b3Sgavinm branch = channel >> 1; 109520c794b3Sgavinm rp->nb.fat_fbd_regs.nerr_fat_fbd = NERR_FAT_FBD_RD(&t); 109620c794b3Sgavinm *interpose |= t; 10975f28a827Saf rp->nb.fat_fbd_regs.nrecmema = NRECMEMA_RD(branch); 10985f28a827Saf rp->nb.fat_fbd_regs.nrecmemb = NRECMEMB_RD(branch); 10995f28a827Saf rp->nb.fat_fbd_regs.nrecfglog = NRECFGLOG_RD(branch); 11005f28a827Saf rp->nb.fat_fbd_regs.nrecfbda = NRECFBDA_RD(branch); 11015f28a827Saf rp->nb.fat_fbd_regs.nrecfbdb = NRECFBDB_RD(branch); 11025f28a827Saf rp->nb.fat_fbd_regs.nrecfbdc = NRECFBDC_RD(branch); 11035f28a827Saf rp->nb.fat_fbd_regs.nrecfbdd = NRECFBDD_RD(branch); 11045f28a827Saf rp->nb.fat_fbd_regs.nrecfbde = NRECFBDE_RD(branch); 11055f28a827Saf rp->nb.fat_fbd_regs.nrecfbdf = NRECFBDF_RD(branch); 110620c794b3Sgavinm rp->nb.fat_fbd_regs.spcps = SPCPS_RD(branch); 110720c794b3Sgavinm rp->nb.fat_fbd_regs.spcpc = SPCPC_RD(branch); 110820c794b3Sgavinm rp->nb.fat_fbd_regs.uerrcnt = UERRCNT_RD(branch); 110920c794b3Sgavinm rp->nb.fat_fbd_regs.uerrcnt_last = uerrcnt[branch]; 111020c794b3Sgavinm uerrcnt[branch] = rp->nb.fat_fbd_regs.uerrcnt; 111120c794b3Sgavinm rp->nb.fat_fbd_regs.badrama = BADRAMA_RD(branch); 111220c794b3Sgavinm rp->nb.fat_fbd_regs.badramb = BADRAMB_RD(branch); 111320c794b3Sgavinm rp->nb.fat_fbd_regs.badcnt = BADCNT_RD(branch); 11140ad0f0b2SAdrian Frost if (!willpanic) { 11150ad0f0b2SAdrian Frost if (rp->nb.fat_fbd_regs.ferr_fat_fbd || *interpose) 11160ad0f0b2SAdrian Frost FERR_FAT_FBD_WR(rp->nb.fat_fbd_regs.ferr_fat_fbd); 11170ad0f0b2SAdrian Frost if (rp->nb.fat_fbd_regs.nerr_fat_fbd) 11180ad0f0b2SAdrian Frost NERR_FAT_FBD_WR(rp->nb.fat_fbd_regs.nerr_fat_fbd); 11190ad0f0b2SAdrian Frost /* 11200ad0f0b2SAdrian Frost * if interpose write read-only registers to clear from pcii 11210ad0f0b2SAdrian Frost * cache 11220ad0f0b2SAdrian Frost */ 11230ad0f0b2SAdrian Frost if (*interpose) { 11240ad0f0b2SAdrian Frost NRECMEMA_WR(branch); 11250ad0f0b2SAdrian Frost NRECMEMB_WR(branch); 11260ad0f0b2SAdrian Frost NRECFGLOG_WR(branch); 11270ad0f0b2SAdrian Frost NRECFBDA_WR(branch); 11280ad0f0b2SAdrian Frost NRECFBDB_WR(branch); 11290ad0f0b2SAdrian Frost NRECFBDC_WR(branch); 11300ad0f0b2SAdrian Frost NRECFBDD_WR(branch); 11310ad0f0b2SAdrian Frost NRECFBDE_WR(branch); 11320ad0f0b2SAdrian Frost NRECFBDF_WR(branch); 11330ad0f0b2SAdrian Frost } 113420c794b3Sgavinm } 113520c794b3Sgavinm } 113620c794b3Sgavinm 113720c794b3Sgavinm static void 11380ad0f0b2SAdrian Frost log_nf_fbd_err(nb_regs_t *rp, int willpanic, int *interpose) 113920c794b3Sgavinm { 114020c794b3Sgavinm int channel, branch; 114120c794b3Sgavinm int t = 0; 114220c794b3Sgavinm 114320c794b3Sgavinm rp->flag = NB_REG_LOG_NF_FBD; 114420c794b3Sgavinm rp->nb.nf_fbd_regs.ferr_nf_fbd = FERR_NF_FBD_RD(interpose); 114520c794b3Sgavinm channel = (rp->nb.nf_fbd_regs.ferr_nf_fbd >> 28) & 3; 114620c794b3Sgavinm branch = channel >> 1; 114720c794b3Sgavinm rp->nb.nf_fbd_regs.nerr_nf_fbd = NERR_NF_FBD_RD(&t); 114820c794b3Sgavinm *interpose |= t; 114920c794b3Sgavinm rp->nb.nf_fbd_regs.redmemb = REDMEMB_RD(); 11505f28a827Saf rp->nb.nf_fbd_regs.recmema = RECMEMA_RD(branch); 11515f28a827Saf rp->nb.nf_fbd_regs.recmemb = RECMEMB_RD(branch); 11525f28a827Saf rp->nb.nf_fbd_regs.recfglog = RECFGLOG_RD(branch); 11535f28a827Saf rp->nb.nf_fbd_regs.recfbda = RECFBDA_RD(branch); 11545f28a827Saf rp->nb.nf_fbd_regs.recfbdb = RECFBDB_RD(branch); 11555f28a827Saf rp->nb.nf_fbd_regs.recfbdc = RECFBDC_RD(branch); 11565f28a827Saf rp->nb.nf_fbd_regs.recfbdd = RECFBDD_RD(branch); 11575f28a827Saf rp->nb.nf_fbd_regs.recfbde = RECFBDE_RD(branch); 11585f28a827Saf rp->nb.nf_fbd_regs.recfbdf = RECFBDF_RD(branch); 115920c794b3Sgavinm rp->nb.nf_fbd_regs.spcps = SPCPS_RD(branch); 116020c794b3Sgavinm rp->nb.nf_fbd_regs.spcpc = SPCPC_RD(branch); 11615f28a827Saf if (nb_chipset == INTEL_NB_7300 || nb_chipset == INTEL_NB_5400) { 11625f28a827Saf rp->nb.nf_fbd_regs.cerrcnta = CERRCNTA_RD(branch, channel); 11635f28a827Saf rp->nb.nf_fbd_regs.cerrcntb = CERRCNTB_RD(branch, channel); 11645f28a827Saf rp->nb.nf_fbd_regs.cerrcntc = CERRCNTC_RD(branch, channel); 11655f28a827Saf rp->nb.nf_fbd_regs.cerrcntd = CERRCNTD_RD(branch, channel); 11665f28a827Saf } else { 11675f28a827Saf rp->nb.nf_fbd_regs.cerrcnta = CERRCNT_RD(branch); 11685f28a827Saf rp->nb.nf_fbd_regs.cerrcntb = 0; 11695f28a827Saf rp->nb.nf_fbd_regs.cerrcntc = 0; 11705f28a827Saf rp->nb.nf_fbd_regs.cerrcntd = 0; 11715f28a827Saf } 11725f28a827Saf rp->nb.nf_fbd_regs.cerrcnta_last = cerrcnta[branch][channel & 1]; 11735f28a827Saf rp->nb.nf_fbd_regs.cerrcntb_last = cerrcntb[branch][channel & 1]; 11745f28a827Saf rp->nb.nf_fbd_regs.cerrcntc_last = cerrcntc[branch][channel & 1]; 11755f28a827Saf rp->nb.nf_fbd_regs.cerrcntd_last = cerrcntd[branch][channel & 1]; 11765f28a827Saf cerrcnta[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcnta; 11775f28a827Saf cerrcntb[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcntb; 11785f28a827Saf cerrcntc[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcntc; 11795f28a827Saf cerrcntd[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcntd; 118020c794b3Sgavinm rp->nb.nf_fbd_regs.badrama = BADRAMA_RD(branch); 118120c794b3Sgavinm rp->nb.nf_fbd_regs.badramb = BADRAMB_RD(branch); 118220c794b3Sgavinm rp->nb.nf_fbd_regs.badcnt = BADCNT_RD(branch); 11830ad0f0b2SAdrian Frost if (!willpanic) { 11840ad0f0b2SAdrian Frost if (rp->nb.nf_fbd_regs.ferr_nf_fbd || *interpose) 11850ad0f0b2SAdrian Frost FERR_NF_FBD_WR(rp->nb.nf_fbd_regs.ferr_nf_fbd); 11860ad0f0b2SAdrian Frost if (rp->nb.nf_fbd_regs.nerr_nf_fbd) 11870ad0f0b2SAdrian Frost NERR_NF_FBD_WR(rp->nb.nf_fbd_regs.nerr_nf_fbd); 11880ad0f0b2SAdrian Frost /* 11890ad0f0b2SAdrian Frost * if interpose write read-only registers to clear from pcii 11900ad0f0b2SAdrian Frost * cache 11910ad0f0b2SAdrian Frost */ 11920ad0f0b2SAdrian Frost if (*interpose) { 11930ad0f0b2SAdrian Frost RECMEMA_WR(branch); 11940ad0f0b2SAdrian Frost RECMEMB_WR(branch); 11950ad0f0b2SAdrian Frost RECFGLOG_WR(branch); 11960ad0f0b2SAdrian Frost RECFBDA_WR(branch); 11970ad0f0b2SAdrian Frost RECFBDB_WR(branch); 11980ad0f0b2SAdrian Frost RECFBDC_WR(branch); 11990ad0f0b2SAdrian Frost RECFBDD_WR(branch); 12000ad0f0b2SAdrian Frost RECFBDE_WR(branch); 12010ad0f0b2SAdrian Frost RECFBDF_WR(branch); 12020ad0f0b2SAdrian Frost SPCPS_WR(branch); 12030ad0f0b2SAdrian Frost } 120420c794b3Sgavinm } 120520c794b3Sgavinm } 120620c794b3Sgavinm 1207*85738508SVuong Nguyen static void 1208*85738508SVuong Nguyen log_nf_mem_err(nb_regs_t *rp, int willpanic, int *interpose) 1209*85738508SVuong Nguyen { 1210*85738508SVuong Nguyen int channel, branch; 1211*85738508SVuong Nguyen int t = 0; 1212*85738508SVuong Nguyen 1213*85738508SVuong Nguyen rp->flag = NB_REG_LOG_NF_MEM; 1214*85738508SVuong Nguyen 1215*85738508SVuong Nguyen /* Memmory err registers */ 1216*85738508SVuong Nguyen rp->nb.nf_mem_regs.ferr_nf_mem = FERR_NF_MEM_RD(interpose); 1217*85738508SVuong Nguyen channel = (rp->nb.nf_mem_regs.ferr_nf_mem >> 28) & 0x1; 1218*85738508SVuong Nguyen branch = channel; 1219*85738508SVuong Nguyen rp->nb.nf_mem_regs.nerr_nf_mem = NERR_NF_MEM_RD(&t); 1220*85738508SVuong Nguyen *interpose |= t; 1221*85738508SVuong Nguyen rp->nb.nf_mem_regs.redmema = MEM_REDMEMA_RD(branch); 1222*85738508SVuong Nguyen rp->nb.nf_mem_regs.redmemb = MEM_REDMEMB_RD(branch); 1223*85738508SVuong Nguyen rp->nb.nf_mem_regs.recmema = MEM_RECMEMA_RD(branch); 1224*85738508SVuong Nguyen rp->nb.nf_mem_regs.recmemb = MEM_RECMEMB_RD(branch); 1225*85738508SVuong Nguyen rp->nb.nf_mem_regs.nrecmema = MEM_NRECMEMA_RD(branch); 1226*85738508SVuong Nguyen rp->nb.nf_mem_regs.nrecmemb = MEM_NRECMEMB_RD(branch); 1227*85738508SVuong Nguyen 1228*85738508SVuong Nguyen /* spare rank */ 1229*85738508SVuong Nguyen rp->nb.nf_mem_regs.spcps = SPCPS_RD(branch); 1230*85738508SVuong Nguyen rp->nb.nf_mem_regs.spcpc = SPCPC_RD(branch); 1231*85738508SVuong Nguyen 1232*85738508SVuong Nguyen /* RAS registers */ 1233*85738508SVuong Nguyen rp->nb.nf_mem_regs.cerrcnt = MEM_CERRCNT_RD(branch); 1234*85738508SVuong Nguyen rp->nb.nf_mem_regs.cerrcnt_ext = (uint32_t)MEM_CERRCNT_EXT_RD(branch); 1235*85738508SVuong Nguyen rp->nb.nf_mem_regs.cerrcnt_last = cerrcnta[branch][channel & 1]; 1236*85738508SVuong Nguyen rp->nb.nf_mem_regs.cerrcnt_ext_last = cerrcntb[branch][channel & 1]; 1237*85738508SVuong Nguyen cerrcnta[branch][channel & 1] = rp->nb.nf_mem_regs.cerrcnt; 1238*85738508SVuong Nguyen cerrcntb[branch][channel & 1] = rp->nb.nf_mem_regs.cerrcnt_ext; 1239*85738508SVuong Nguyen rp->nb.nf_mem_regs.badram = BADRAMA_RD(branch); 1240*85738508SVuong Nguyen rp->nb.nf_mem_regs.badcnt = BADCNT_RD(branch); 1241*85738508SVuong Nguyen rp->nb.nf_mem_regs.validlog = VALIDLOG_RD(branch); 1242*85738508SVuong Nguyen 1243*85738508SVuong Nguyen if (!willpanic) { 1244*85738508SVuong Nguyen if (rp->nb.nf_mem_regs.ferr_nf_mem || *interpose) 1245*85738508SVuong Nguyen FERR_NF_MEM_WR(rp->nb.nf_mem_regs.ferr_nf_mem); 1246*85738508SVuong Nguyen if (rp->nb.nf_mem_regs.nerr_nf_mem) 1247*85738508SVuong Nguyen NERR_NF_MEM_WR(rp->nb.nf_mem_regs.nerr_nf_mem); 1248*85738508SVuong Nguyen /* 1249*85738508SVuong Nguyen * if interpose, write read-only registers to clear from pci 1250*85738508SVuong Nguyen * cache 1251*85738508SVuong Nguyen */ 1252*85738508SVuong Nguyen if (*interpose) { 1253*85738508SVuong Nguyen MEM_NRECMEMA_WR(branch); 1254*85738508SVuong Nguyen MEM_NRECMEMB_WR(branch); 1255*85738508SVuong Nguyen MEM_REDMEMA_WR(branch); 1256*85738508SVuong Nguyen MEM_REDMEMB_WR(branch); 1257*85738508SVuong Nguyen MEM_RECMEMA_WR(branch); 1258*85738508SVuong Nguyen MEM_RECMEMB_WR(branch); 1259*85738508SVuong Nguyen SPCPS_WR(branch); 1260*85738508SVuong Nguyen } 1261*85738508SVuong Nguyen } 1262*85738508SVuong Nguyen } 1263*85738508SVuong Nguyen 126420c794b3Sgavinm static void 126520c794b3Sgavinm log_ferr(uint64_t ferr, uint32_t *nerrp, nb_logout_t *log, int willpanic) 126620c794b3Sgavinm { 126720c794b3Sgavinm nb_regs_t *rp = &log->nb_regs; 126820c794b3Sgavinm uint32_t nerr = *nerrp; 126920c794b3Sgavinm int interpose = 0; 12709ff4cbe7SAdrian Frost int spurious = 0; 127120c794b3Sgavinm 127220c794b3Sgavinm log->acl_timestamp = gethrtime_waitfree(); 127320c794b3Sgavinm if ((ferr & (GE_PCIEX_FATAL | GE_PCIEX_NF)) != 0) { 12740ad0f0b2SAdrian Frost log_pex_err(ferr, rp, willpanic, &interpose); 127520c794b3Sgavinm *nerrp = nerr & ~(GE_PCIEX_FATAL | GE_PCIEX_NF); 127620c794b3Sgavinm } else if ((ferr & GE_FBD_FATAL) != 0) { 12770ad0f0b2SAdrian Frost log_fat_fbd_err(rp, willpanic, &interpose); 127820c794b3Sgavinm *nerrp = nerr & ~GE_NERR_FBD_FATAL; 127920c794b3Sgavinm } else if ((ferr & GE_FBD_NF) != 0) { 12800ad0f0b2SAdrian Frost log_nf_fbd_err(rp, willpanic, &interpose); 128120c794b3Sgavinm *nerrp = nerr & ~GE_NERR_FBD_NF; 1282*85738508SVuong Nguyen } else if ((ferr & GE_MEM_NF) != 0) { 1283*85738508SVuong Nguyen log_nf_mem_err(rp, willpanic, &interpose); 1284*85738508SVuong Nguyen *nerrp = nerr & ~GE_NERR_MEM_NF; 128520c794b3Sgavinm } else if ((ferr & (GE_FERR_FSB_FATAL | GE_FERR_FSB_NF)) != 0) { 12860ad0f0b2SAdrian Frost log_fsb_err(ferr, rp, willpanic, &interpose); 128720c794b3Sgavinm *nerrp = nerr & ~(GE_NERR_FSB_FATAL | GE_NERR_FSB_NF); 128820c794b3Sgavinm } else if ((ferr & (GE_DMA_FATAL | GE_DMA_NF)) != 0) { 128920c794b3Sgavinm log_dma_err(rp, &interpose); 129020c794b3Sgavinm *nerrp = nerr & ~(GE_DMA_FATAL | GE_DMA_NF); 129120c794b3Sgavinm } else if ((ferr & (GE_INT_FATAL | GE_INT_NF)) != 0) { 12920ad0f0b2SAdrian Frost spurious = log_int_err(rp, willpanic, &interpose); 129320c794b3Sgavinm *nerrp = nerr & ~(GE_INT_FATAL | GE_INT_NF); 12945f28a827Saf } else if (nb_chipset == INTEL_NB_5400 && 12955f28a827Saf (ferr & (GE_FERR_THERMAL_FATAL | GE_FERR_THERMAL_NF)) != 0) { 12960ad0f0b2SAdrian Frost log_thermal_err(rp, willpanic, &interpose); 12975f28a827Saf *nerrp = nerr & ~(GE_FERR_THERMAL_FATAL | GE_FERR_THERMAL_NF); 129820c794b3Sgavinm } 129920c794b3Sgavinm if (interpose) 130020c794b3Sgavinm log->type = "inject"; 130120c794b3Sgavinm else 130220c794b3Sgavinm log->type = "error"; 13039ff4cbe7SAdrian Frost if (!spurious) { 13049ff4cbe7SAdrian Frost errorq_dispatch(nb_queue, log, sizeof (nb_logout_t), 13059ff4cbe7SAdrian Frost willpanic ? ERRORQ_SYNC : ERRORQ_ASYNC); 13069ff4cbe7SAdrian Frost } 130720c794b3Sgavinm } 130820c794b3Sgavinm 130920c794b3Sgavinm static void 131020c794b3Sgavinm log_nerr(uint32_t *errp, nb_logout_t *log, int willpanic) 131120c794b3Sgavinm { 131220c794b3Sgavinm uint32_t err; 131320c794b3Sgavinm nb_regs_t *rp = &log->nb_regs; 131420c794b3Sgavinm int interpose = 0; 13159ff4cbe7SAdrian Frost int spurious = 0; 131620c794b3Sgavinm 131720c794b3Sgavinm err = *errp; 131820c794b3Sgavinm log->acl_timestamp = gethrtime_waitfree(); 131920c794b3Sgavinm if ((err & (GE_PCIEX_FATAL | GE_PCIEX_NF)) != 0) { 13200ad0f0b2SAdrian Frost log_pex_err(err, rp, willpanic, &interpose); 132120c794b3Sgavinm *errp = err & ~(GE_PCIEX_FATAL | GE_PCIEX_NF); 132220c794b3Sgavinm } else if ((err & GE_NERR_FBD_FATAL) != 0) { 13230ad0f0b2SAdrian Frost log_fat_fbd_err(rp, willpanic, &interpose); 132420c794b3Sgavinm *errp = err & ~GE_NERR_FBD_FATAL; 132520c794b3Sgavinm } else if ((err & GE_NERR_FBD_NF) != 0) { 13260ad0f0b2SAdrian Frost log_nf_fbd_err(rp, willpanic, &interpose); 132720c794b3Sgavinm *errp = err & ~GE_NERR_FBD_NF; 1328*85738508SVuong Nguyen } else if ((err & GE_NERR_MEM_NF) != 0) { 1329*85738508SVuong Nguyen log_nf_mem_err(rp, willpanic, &interpose); 1330*85738508SVuong Nguyen *errp = err & ~GE_NERR_MEM_NF; 133120c794b3Sgavinm } else if ((err & (GE_NERR_FSB_FATAL | GE_NERR_FSB_NF)) != 0) { 13320ad0f0b2SAdrian Frost log_fsb_err(GE_NERR_TO_FERR_FSB(err), rp, willpanic, 13330ad0f0b2SAdrian Frost &interpose); 133420c794b3Sgavinm *errp = err & ~(GE_NERR_FSB_FATAL | GE_NERR_FSB_NF); 133520c794b3Sgavinm } else if ((err & (GE_DMA_FATAL | GE_DMA_NF)) != 0) { 133620c794b3Sgavinm log_dma_err(rp, &interpose); 133720c794b3Sgavinm *errp = err & ~(GE_DMA_FATAL | GE_DMA_NF); 133820c794b3Sgavinm } else if ((err & (GE_INT_FATAL | GE_INT_NF)) != 0) { 13390ad0f0b2SAdrian Frost spurious = log_int_err(rp, willpanic, &interpose); 134020c794b3Sgavinm *errp = err & ~(GE_INT_FATAL | GE_INT_NF); 134120c794b3Sgavinm } 134220c794b3Sgavinm if (interpose) 134320c794b3Sgavinm log->type = "inject"; 134420c794b3Sgavinm else 134520c794b3Sgavinm log->type = "error"; 13469ff4cbe7SAdrian Frost if (!spurious) { 13479ff4cbe7SAdrian Frost errorq_dispatch(nb_queue, log, sizeof (nb_logout_t), 13489ff4cbe7SAdrian Frost willpanic ? ERRORQ_SYNC : ERRORQ_ASYNC); 13499ff4cbe7SAdrian Frost } 135020c794b3Sgavinm } 135120c794b3Sgavinm 135220c794b3Sgavinm /*ARGSUSED*/ 135320c794b3Sgavinm void 135420c794b3Sgavinm nb_error_trap(cmi_hdl_t hdl, boolean_t ismc, boolean_t willpanic) 135520c794b3Sgavinm { 135620c794b3Sgavinm uint64_t ferr; 135720c794b3Sgavinm uint32_t nerr, err; 135820c794b3Sgavinm int nmc = 0; 135920c794b3Sgavinm int i; 136020c794b3Sgavinm 136120c794b3Sgavinm if (mutex_tryenter(&nb_mutex) == 0) 136220c794b3Sgavinm return; 136320c794b3Sgavinm 136420c794b3Sgavinm nerr = NERR_GLOBAL_RD(); 136520c794b3Sgavinm err = nerr; 136620c794b3Sgavinm for (i = 0; i < NB_MAX_ERRORS; i++) { 136720c794b3Sgavinm ferr = FERR_GLOBAL_RD(); 136820c794b3Sgavinm nb_log.nb_regs.chipset = nb_chipset; 136920c794b3Sgavinm nb_log.nb_regs.ferr = ferr; 137020c794b3Sgavinm nb_log.nb_regs.nerr = nerr; 137120c794b3Sgavinm if (ferr) { 137220c794b3Sgavinm log_ferr(ferr, &err, &nb_log, willpanic); 137320c794b3Sgavinm FERR_GLOBAL_WR(ferr); 137420c794b3Sgavinm nmc++; 137520c794b3Sgavinm } else if (err) { 137620c794b3Sgavinm log_nerr(&err, &nb_log, willpanic); 137720c794b3Sgavinm nmc++; 137820c794b3Sgavinm } 137920c794b3Sgavinm } 138020c794b3Sgavinm if (nerr) { 138120c794b3Sgavinm NERR_GLOBAL_WR(nerr); 138220c794b3Sgavinm } 138320c794b3Sgavinm if (nmc == 0 && nb_mask_mc_set) 138420c794b3Sgavinm nb_mask_mc_reset(); 138520c794b3Sgavinm mutex_exit(&nb_mutex); 138620c794b3Sgavinm } 138720c794b3Sgavinm 138820c794b3Sgavinm static void 138920c794b3Sgavinm nb_fsb_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 139020c794b3Sgavinm nb_scatchpad_t *data) 139120c794b3Sgavinm { 139220c794b3Sgavinm int intel_error_list; 139320c794b3Sgavinm char buf[32]; 139420c794b3Sgavinm 139520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FSB, 139620c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.fsb, NULL); 139720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_FSB, 139820c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.ferr_fat_fsb, NULL); 139920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_FSB, 140020c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.nerr_fat_fsb, NULL); 140120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_FSB, 140220c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.ferr_nf_fsb, NULL); 140320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_FSB, 140420c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.nerr_nf_fsb, NULL); 140520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFSB, 140620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fsb_regs.nrecfsb, NULL); 140720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFSB_ADDR, 140820c794b3Sgavinm DATA_TYPE_UINT64, nb_regs->nb.fsb_regs.nrecfsb_addr, NULL); 140920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFSB, 141020c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fsb_regs.recfsb, NULL); 141120c794b3Sgavinm intel_error_list = data->intel_error_list; 141220c794b3Sgavinm if (intel_error_list >= 0) 141320c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "F%d", intel_error_list); 141420c794b3Sgavinm else 141520c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 141620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 141720c794b3Sgavinm DATA_TYPE_STRING, buf, NULL); 141820c794b3Sgavinm } 141920c794b3Sgavinm 142020c794b3Sgavinm static void 142120c794b3Sgavinm nb_pex_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 142220c794b3Sgavinm nb_scatchpad_t *data) 142320c794b3Sgavinm { 142420c794b3Sgavinm int intel_error_list; 142520c794b3Sgavinm char buf[32]; 142620c794b3Sgavinm 142720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX, 142820c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.pex_regs.pex, NULL); 142920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_FAT_FERR, 143020c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_fat_ferr, NULL); 143120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_FAT_NERR, 143220c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_fat_nerr, NULL); 143320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_NF_CORR_FERR, 143420c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_nf_corr_ferr, NULL); 143520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_NF_CORR_NERR, 143620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_nf_corr_nerr, NULL); 143720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UNCERRSEV, 143820c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.uncerrsev, NULL); 143920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RPERRSTS, 144020c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.rperrsts, NULL); 144120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RPERRSID, 144220c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.rperrsid, NULL); 144320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UNCERRSTS, 144420c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.uncerrsts, NULL); 144520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_AERRCAPCTRL, 144620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.aerrcapctrl, NULL); 144720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CORERRSTS, 144820c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.pex_regs.corerrsts, NULL); 144920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEXDEVSTS, 145020c794b3Sgavinm DATA_TYPE_UINT16, nb_regs->nb.pex_regs.pexdevsts, NULL); 145120c794b3Sgavinm intel_error_list = data->intel_error_list; 145220c794b3Sgavinm if (intel_error_list >= 0) 145320c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "IO%d", intel_error_list); 145420c794b3Sgavinm else 145520c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 145620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 145720c794b3Sgavinm DATA_TYPE_STRING, buf, NULL); 145820c794b3Sgavinm } 145920c794b3Sgavinm 146020c794b3Sgavinm static void 146120c794b3Sgavinm nb_int_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 146220c794b3Sgavinm nb_scatchpad_t *data) 146320c794b3Sgavinm { 146420c794b3Sgavinm int intel_error_list; 146520c794b3Sgavinm char buf[32]; 146620c794b3Sgavinm 146720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_INT, 14685f28a827Saf DATA_TYPE_UINT16, nb_regs->nb.int_regs.ferr_fat_int, NULL); 146920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_INT, 14705f28a827Saf DATA_TYPE_UINT16, nb_regs->nb.int_regs.ferr_nf_int, NULL); 147120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_INT, 14725f28a827Saf DATA_TYPE_UINT16, nb_regs->nb.int_regs.nerr_fat_int, NULL); 147320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_INT, 14745f28a827Saf DATA_TYPE_UINT16, nb_regs->nb.int_regs.nerr_nf_int, NULL); 147520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECINT, 147620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.int_regs.nrecint, NULL); 147720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECINT, 147820c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.int_regs.recint, NULL); 147920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECSF, 148020c794b3Sgavinm DATA_TYPE_UINT64, nb_regs->nb.int_regs.nrecsf, NULL); 148120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECSF, 148220c794b3Sgavinm DATA_TYPE_UINT64, nb_regs->nb.int_regs.recsf, NULL); 148320c794b3Sgavinm intel_error_list = data->intel_error_list; 148420c794b3Sgavinm if (intel_error_list >= 0) 148520c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "B%d", intel_error_list); 148620c794b3Sgavinm else 148720c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 148820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 148920c794b3Sgavinm DATA_TYPE_STRING, buf, NULL); 149020c794b3Sgavinm } 149120c794b3Sgavinm 149220c794b3Sgavinm static void 149320c794b3Sgavinm nb_fat_fbd_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 149420c794b3Sgavinm nb_scatchpad_t *data) 149520c794b3Sgavinm { 149620c794b3Sgavinm nb_mem_scatchpad_t *sp; 149720c794b3Sgavinm char buf[32]; 149820c794b3Sgavinm 149920c794b3Sgavinm sp = &((nb_scatchpad_t *)data)->ms; 150020c794b3Sgavinm 150120c794b3Sgavinm if (sp->ras != -1) { 150220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK, 150320c794b3Sgavinm DATA_TYPE_INT32, sp->bank, NULL); 150420c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CAS, 150520c794b3Sgavinm DATA_TYPE_INT32, sp->cas, NULL); 150620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RAS, 150720c794b3Sgavinm DATA_TYPE_INT32, sp->ras, NULL); 150820c794b3Sgavinm if (sp->offset != -1LL) { 150920c794b3Sgavinm fm_payload_set(payload, FM_FMRI_MEM_OFFSET, 151020c794b3Sgavinm DATA_TYPE_UINT64, sp->offset, NULL); 151120c794b3Sgavinm } 151220c794b3Sgavinm if (sp->pa != -1LL) { 151320c794b3Sgavinm fm_payload_set(payload, FM_FMRI_MEM_PHYSADDR, 151420c794b3Sgavinm DATA_TYPE_UINT64, sp->pa, NULL); 151520c794b3Sgavinm } 151620c794b3Sgavinm } 151720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_FBD, 151820c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.ferr_fat_fbd, NULL); 151920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_FBD, 152020c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nerr_fat_fbd, NULL); 152120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECMEMA, 15225f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecmema, NULL); 152320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECMEMB, 152420c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecmemb, NULL); 152520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFGLOG, 152620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfglog, NULL); 152720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDA, 152820c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbda, NULL); 152920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDB, 153020c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdb, NULL); 153120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDC, 153220c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdc, NULL); 153320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDD, 153420c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdd, NULL); 153520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDE, 153620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbde, NULL); 15375de8e333Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDF, 15385de8e333Saf DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdf, NULL); 153920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPS, 154020c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.fat_fbd_regs.spcps, NULL); 154120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPC, 154220c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.spcpc, NULL); 154320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UERRCNT, 154420c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.uerrcnt, NULL); 154520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UERRCNT_LAST, 154620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.uerrcnt_last, NULL); 154720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMA, 154820c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.badrama, NULL); 154920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMB, 155020c794b3Sgavinm DATA_TYPE_UINT16, nb_regs->nb.fat_fbd_regs.badramb, NULL); 155120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADCNT, 155220c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.badcnt, NULL); 155320c794b3Sgavinm 155420c794b3Sgavinm if (sp->intel_error_list >= 0) 155520c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "M%d", sp->intel_error_list); 155620c794b3Sgavinm else 155720c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 155820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 155920c794b3Sgavinm DATA_TYPE_STRING, buf, NULL); 156020c794b3Sgavinm } 156120c794b3Sgavinm 156220c794b3Sgavinm static void 156320c794b3Sgavinm nb_nf_fbd_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 156420c794b3Sgavinm nb_scatchpad_t *data) 156520c794b3Sgavinm { 156620c794b3Sgavinm nb_mem_scatchpad_t *sp; 156720c794b3Sgavinm char buf[32]; 156820c794b3Sgavinm 156920c794b3Sgavinm sp = &((nb_scatchpad_t *)data)->ms; 157020c794b3Sgavinm 157120c794b3Sgavinm if (sp->dimm == -1 && sp->rank != -1) { 157220c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RANK, 157320c794b3Sgavinm DATA_TYPE_INT32, sp->rank, NULL); 157420c794b3Sgavinm } 157520c794b3Sgavinm if (sp->ras != -1) { 157620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK, 157720c794b3Sgavinm DATA_TYPE_INT32, sp->bank, NULL); 157820c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CAS, 157920c794b3Sgavinm DATA_TYPE_INT32, sp->cas, NULL); 158020c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RAS, 158120c794b3Sgavinm DATA_TYPE_INT32, sp->ras, NULL); 158220c794b3Sgavinm if (sp->offset != -1LL) { 158320c794b3Sgavinm fm_payload_set(payload, FM_FMRI_MEM_OFFSET, 158420c794b3Sgavinm DATA_TYPE_UINT64, sp->offset, NULL); 158520c794b3Sgavinm } 158620c794b3Sgavinm if (sp->pa != -1LL) { 158720c794b3Sgavinm fm_payload_set(payload, FM_FMRI_MEM_PHYSADDR, 158820c794b3Sgavinm DATA_TYPE_UINT64, sp->pa, NULL); 158920c794b3Sgavinm } 159020c794b3Sgavinm } 159120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_FBD, 159220c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.ferr_nf_fbd, NULL); 159320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_FBD, 159420c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.nerr_nf_fbd, NULL); 159520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECMEMA, 15965f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recmema, NULL); 159720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECMEMB, 159820c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recmemb, NULL); 159920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFGLOG, 160020c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfglog, NULL); 160120c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDA, 160220c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbda, NULL); 160320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDB, 160420c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdb, NULL); 160520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDC, 160620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdc, NULL); 160720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDD, 160820c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdd, NULL); 160920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDE, 161020c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbde, NULL); 16115de8e333Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDF, 16125de8e333Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdf, NULL); 161320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPS, 161420c794b3Sgavinm DATA_TYPE_UINT8, nb_regs->nb.nf_fbd_regs.spcps, NULL); 161520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPC, 161620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.spcpc, NULL); 16175f28a827Saf if (nb_chipset == INTEL_NB_7300 || nb_chipset == INTEL_NB_5400) { 16185f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTA, 16195f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta, NULL); 16205f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTB, 16215f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntb, NULL); 16225f28a827Saf if (nb_chipset == INTEL_NB_7300) { 16235f28a827Saf fm_payload_set(payload, 16245f28a827Saf FM_EREPORT_PAYLOAD_NAME_CERRCNTC, 16255f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntc, 16265f28a827Saf NULL); 16275f28a827Saf fm_payload_set(payload, 16285f28a827Saf FM_EREPORT_PAYLOAD_NAME_CERRCNTD, 16295f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntd, 16305f28a827Saf NULL); 16315f28a827Saf } 16325f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTA_LAST, 16335f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta_last, 16345f28a827Saf NULL); 16355f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTB_LAST, 16365f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntb_last, 16375f28a827Saf NULL); 16385f28a827Saf if (nb_chipset == INTEL_NB_7300) { 16395f28a827Saf fm_payload_set(payload, 16405f28a827Saf FM_EREPORT_PAYLOAD_NAME_CERRCNTC_LAST, 16415f28a827Saf DATA_TYPE_UINT32, 16425f28a827Saf nb_regs->nb.nf_fbd_regs.cerrcntc_last, NULL); 16435f28a827Saf fm_payload_set(payload, 16445f28a827Saf FM_EREPORT_PAYLOAD_NAME_CERRCNTD_LAST, 16455f28a827Saf DATA_TYPE_UINT32, 16465f28a827Saf nb_regs->nb.nf_fbd_regs.cerrcntd_last, NULL); 16475f28a827Saf } 16485f28a827Saf } else { 16495f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT, 16505f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta, NULL); 16515f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT_LAST, 16525f28a827Saf DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta_last, 16535f28a827Saf NULL); 16545f28a827Saf } 165520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMA, 165620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.badrama, NULL); 165720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMB, 165820c794b3Sgavinm DATA_TYPE_UINT16, nb_regs->nb.nf_fbd_regs.badramb, NULL); 165920c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADCNT, 166020c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.badcnt, NULL); 166120c794b3Sgavinm 166220c794b3Sgavinm if (sp->intel_error_list >= 0) 166320c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "M%d", sp->intel_error_list); 166420c794b3Sgavinm else 166520c794b3Sgavinm (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 166620c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 166720c794b3Sgavinm DATA_TYPE_STRING, buf, NULL); 166820c794b3Sgavinm } 166920c794b3Sgavinm 1670*85738508SVuong Nguyen static void 1671*85738508SVuong Nguyen nb_nf_mem_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 1672*85738508SVuong Nguyen nb_scatchpad_t *data) 1673*85738508SVuong Nguyen { 1674*85738508SVuong Nguyen nb_mem_scatchpad_t *sp; 1675*85738508SVuong Nguyen char buf[32]; 1676*85738508SVuong Nguyen 1677*85738508SVuong Nguyen sp = &((nb_scatchpad_t *)data)->ms; 1678*85738508SVuong Nguyen 1679*85738508SVuong Nguyen if (sp->dimm == -1 && sp->rank != -1) { 1680*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RANK, 1681*85738508SVuong Nguyen DATA_TYPE_INT32, sp->rank, NULL); 1682*85738508SVuong Nguyen } 1683*85738508SVuong Nguyen if (sp->ras != -1) { 1684*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK, 1685*85738508SVuong Nguyen DATA_TYPE_INT32, sp->bank, NULL); 1686*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CAS, 1687*85738508SVuong Nguyen DATA_TYPE_INT32, sp->cas, NULL); 1688*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RAS, 1689*85738508SVuong Nguyen DATA_TYPE_INT32, sp->ras, NULL); 1690*85738508SVuong Nguyen if (sp->offset != -1LL) { 1691*85738508SVuong Nguyen fm_payload_set(payload, FM_FMRI_MEM_OFFSET, 1692*85738508SVuong Nguyen DATA_TYPE_UINT64, sp->offset, NULL); 1693*85738508SVuong Nguyen } 1694*85738508SVuong Nguyen if (sp->pa != -1LL) { 1695*85738508SVuong Nguyen fm_payload_set(payload, FM_FMRI_MEM_PHYSADDR, 1696*85738508SVuong Nguyen DATA_TYPE_UINT64, sp->pa, NULL); 1697*85738508SVuong Nguyen } 1698*85738508SVuong Nguyen } 1699*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_MEM, 1700*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.ferr_nf_mem, NULL); 1701*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_MEM, 1702*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.nerr_nf_mem, NULL); 1703*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECMEMA, 1704*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.recmema, NULL); 1705*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECMEMB, 1706*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.recmemb, NULL); 1707*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_REDMEMA, 1708*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.redmema, NULL); 1709*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_REDMEMB, 1710*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.redmemb, NULL); 1711*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECMEMA, 1712*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.nrecmema, NULL); 1713*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECMEMB, 1714*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.nrecmemb, NULL); 1715*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPS, 1716*85738508SVuong Nguyen DATA_TYPE_UINT8, nb_regs->nb.nf_mem_regs.spcps, NULL); 1717*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPC, 1718*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.spcpc, NULL); 1719*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT, 1720*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.cerrcnt, NULL); 1721*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT_LAST, 1722*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.cerrcnt_last, NULL); 1723*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT_EXT, 1724*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.cerrcnt_ext, NULL); 1725*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT_EXT_LAST, 1726*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.cerrcnt_ext_last, NULL); 1727*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAM, 1728*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.badram, NULL); 1729*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADCNT, 1730*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.badcnt, NULL); 1731*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_VALIDLOG, 1732*85738508SVuong Nguyen DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.validlog, NULL); 1733*85738508SVuong Nguyen 1734*85738508SVuong Nguyen if (sp->intel_error_list >= 0) 1735*85738508SVuong Nguyen (void) snprintf(buf, sizeof (buf), "M%d", sp->intel_error_list); 1736*85738508SVuong Nguyen else 1737*85738508SVuong Nguyen (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 1738*85738508SVuong Nguyen fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 1739*85738508SVuong Nguyen DATA_TYPE_STRING, buf, NULL); 1740*85738508SVuong Nguyen } 1741*85738508SVuong Nguyen 174220c794b3Sgavinm static void 174320c794b3Sgavinm nb_dma_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload) 174420c794b3Sgavinm { 174520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PCISTS, 174620c794b3Sgavinm DATA_TYPE_UINT16, nb_regs->nb.dma_regs.pcists, NULL); 174720c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEXDEVSTS, 174820c794b3Sgavinm DATA_TYPE_UINT16, nb_regs->nb.dma_regs.pexdevsts, NULL); 174920c794b3Sgavinm } 175020c794b3Sgavinm 17515f28a827Saf static void 17525f28a827Saf nb_thr_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload, 17535f28a827Saf nb_scatchpad_t *data) 17545f28a827Saf { 17555f28a827Saf char buf[32]; 17565f28a827Saf 17575f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_THR, 17585f28a827Saf DATA_TYPE_UINT8, nb_regs->nb.thr_regs.ferr_fat_thr, NULL); 17595f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_THR, 17605f28a827Saf DATA_TYPE_UINT8, nb_regs->nb.thr_regs.nerr_fat_thr, NULL); 17615f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_THR, 17625f28a827Saf DATA_TYPE_UINT8, nb_regs->nb.thr_regs.ferr_nf_thr, NULL); 17635f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_THR, 17645f28a827Saf DATA_TYPE_UINT8, nb_regs->nb.thr_regs.nerr_nf_thr, NULL); 17655f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CTSTS, 17665f28a827Saf DATA_TYPE_UINT8, nb_regs->nb.thr_regs.ctsts, NULL); 17675f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_THRTSTS, 17685f28a827Saf DATA_TYPE_UINT16, nb_regs->nb.thr_regs.thrtsts, NULL); 17695f28a827Saf if (data->intel_error_list >= 0) { 17705f28a827Saf (void) snprintf(buf, sizeof (buf), "TH%d", 17715f28a827Saf data->intel_error_list); 17725f28a827Saf } else { 17735f28a827Saf (void) snprintf(buf, sizeof (buf), "Multiple or unknown error"); 17745f28a827Saf } 17755f28a827Saf fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO, 17765f28a827Saf DATA_TYPE_STRING, buf, NULL); 17775f28a827Saf } 17785f28a827Saf 177920c794b3Sgavinm static void 178020c794b3Sgavinm nb_ereport_add_logout(nvlist_t *payload, const nb_logout_t *acl, 178120c794b3Sgavinm nb_scatchpad_t *data) 178220c794b3Sgavinm { 178320c794b3Sgavinm const nb_regs_t *nb_regs = &acl->nb_regs; 178420c794b3Sgavinm 178520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_MC_TYPE, 17866cb1ca52Saf DATA_TYPE_STRING, acl->type, NULL); 178720c794b3Sgavinm switch (nb_regs->flag) { 178820c794b3Sgavinm case NB_REG_LOG_FSB: 178920c794b3Sgavinm nb_fsb_err_payload(nb_regs, payload, data); 179020c794b3Sgavinm break; 179120c794b3Sgavinm case NB_REG_LOG_PEX: 179220c794b3Sgavinm nb_pex_err_payload(nb_regs, payload, data); 179320c794b3Sgavinm break; 179420c794b3Sgavinm case NB_REG_LOG_INT: 179520c794b3Sgavinm nb_int_err_payload(nb_regs, payload, data); 179620c794b3Sgavinm break; 179720c794b3Sgavinm case NB_REG_LOG_FAT_FBD: 179820c794b3Sgavinm nb_fat_fbd_err_payload(nb_regs, payload, data); 179920c794b3Sgavinm break; 180020c794b3Sgavinm case NB_REG_LOG_NF_FBD: 180120c794b3Sgavinm nb_nf_fbd_err_payload(nb_regs, payload, data); 180220c794b3Sgavinm break; 180320c794b3Sgavinm case NB_REG_LOG_DMA: 180420c794b3Sgavinm nb_dma_err_payload(nb_regs, payload); 180520c794b3Sgavinm break; 18065f28a827Saf case NB_REG_LOG_THR: 18075f28a827Saf nb_thr_err_payload(nb_regs, payload, data); 18085f28a827Saf break; 1809*85738508SVuong Nguyen case NB_REG_LOG_NF_MEM: 1810*85738508SVuong Nguyen nb_nf_mem_err_payload(nb_regs, payload, data); 1811*85738508SVuong Nguyen break; 181220c794b3Sgavinm default: 181320c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_GLOBAL, 181420c794b3Sgavinm DATA_TYPE_UINT64, nb_regs->ferr, NULL); 181520c794b3Sgavinm fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_GLOBAL, 181620c794b3Sgavinm DATA_TYPE_UINT32, nb_regs->nerr, NULL); 181720c794b3Sgavinm break; 181820c794b3Sgavinm } 181920c794b3Sgavinm } 182020c794b3Sgavinm 182120c794b3Sgavinm void 182220c794b3Sgavinm nb_fsb_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 182320c794b3Sgavinm nb_scatchpad_t *data) 182420c794b3Sgavinm { 182520c794b3Sgavinm int chip; 182620c794b3Sgavinm 182720c794b3Sgavinm if (nb_chipset == INTEL_NB_7300) 182820c794b3Sgavinm chip = nb_regs->nb.fsb_regs.fsb * 2; 182920c794b3Sgavinm else 183020c794b3Sgavinm chip = nb_regs->nb.fsb_regs.fsb; 183120c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2, 183220c794b3Sgavinm "motherboard", 0, "chip", chip); 183320c794b3Sgavinm 18346cb1ca52Saf if (nb_regs->nb.fsb_regs.ferr_fat_fsb == 0 && 18356cb1ca52Saf nb_regs->nb.fsb_regs.ferr_nf_fsb == 0) { 18366cb1ca52Saf data->intel_error_list = intel_fsb_err(nb_regs->nb.fsb_regs.fsb, 18376cb1ca52Saf nb_regs->nb.fsb_regs.nerr_fat_fsb, 18386cb1ca52Saf nb_regs->nb.fsb_regs.nerr_nf_fsb); 18396cb1ca52Saf } else { 18406cb1ca52Saf data->intel_error_list = intel_fsb_err(nb_regs->nb.fsb_regs.fsb, 18416cb1ca52Saf nb_regs->nb.fsb_regs.ferr_fat_fsb, 18426cb1ca52Saf nb_regs->nb.fsb_regs.ferr_nf_fsb); 18436cb1ca52Saf } 184420c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 184520c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "fsb"); 184620c794b3Sgavinm } 184720c794b3Sgavinm 184820c794b3Sgavinm void 184920c794b3Sgavinm nb_pex_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 185020c794b3Sgavinm nb_scatchpad_t *data) 185120c794b3Sgavinm { 185220c794b3Sgavinm int hostbridge; 185320c794b3Sgavinm 185420c794b3Sgavinm if (nb_regs->nb.pex_regs.pex == 0) { 185520c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 185620c794b3Sgavinm "motherboard", 0); 185720c794b3Sgavinm } else { 185820c794b3Sgavinm hostbridge = nb_regs->nb.pex_regs.pex - 1; 185920c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2, 186020c794b3Sgavinm "motherboard", 0, 186120c794b3Sgavinm "hostbridge", hostbridge); 186220c794b3Sgavinm } 186320c794b3Sgavinm 18646cb1ca52Saf if (nb_regs->nb.pex_regs.pex_fat_ferr == 0 && 18656cb1ca52Saf nb_regs->nb.pex_regs.pex_nf_corr_ferr == 0) { 18665f28a827Saf if (nb_chipset == INTEL_NB_5400) { 18675f28a827Saf data->intel_error_list = 18685f28a827Saf intel_pex_5400_err( 18695f28a827Saf nb_regs->nb.pex_regs.pex_fat_nerr, 18705f28a827Saf nb_regs->nb.pex_regs.pex_nf_corr_nerr); 18715f28a827Saf } else { 18725f28a827Saf data->intel_error_list = 18735f28a827Saf intel_pex_err(nb_regs->nb.pex_regs.pex_fat_nerr, 18745f28a827Saf nb_regs->nb.pex_regs.pex_nf_corr_nerr); 18755f28a827Saf } 18766cb1ca52Saf } else { 18775f28a827Saf if (nb_chipset == INTEL_NB_5400) { 18785f28a827Saf data->intel_error_list = 18795f28a827Saf intel_pex_5400_err( 18805f28a827Saf nb_regs->nb.pex_regs.pex_fat_ferr, 18815f28a827Saf nb_regs->nb.pex_regs.pex_nf_corr_ferr); 18825f28a827Saf } else { 18835f28a827Saf data->intel_error_list = 18845f28a827Saf intel_pex_err(nb_regs->nb.pex_regs.pex_fat_ferr, 18855f28a827Saf nb_regs->nb.pex_regs.pex_nf_corr_ferr); 18865f28a827Saf } 18876cb1ca52Saf } 188820c794b3Sgavinm 188920c794b3Sgavinm if (nb_regs->nb.pex_regs.pex == 0) { 189020c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 189120c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "esi"); 189220c794b3Sgavinm } else { 189320c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 189420c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "pex"); 189520c794b3Sgavinm } 189620c794b3Sgavinm } 189720c794b3Sgavinm 189820c794b3Sgavinm void 189920c794b3Sgavinm nb_int_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 190020c794b3Sgavinm void *data) 190120c794b3Sgavinm { 190220c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 190320c794b3Sgavinm "motherboard", 0); 190420c794b3Sgavinm 19056cb1ca52Saf if (nb_regs->nb.int_regs.ferr_fat_int == 0 && 19066cb1ca52Saf nb_regs->nb.int_regs.ferr_nf_int == 0) { 19076cb1ca52Saf ((nb_scatchpad_t *)data)->intel_error_list = 19086cb1ca52Saf intel_int_err(nb_regs->nb.int_regs.nerr_fat_int, 19096cb1ca52Saf nb_regs->nb.int_regs.nerr_nf_int); 19106cb1ca52Saf } else { 19116cb1ca52Saf ((nb_scatchpad_t *)data)->intel_error_list = 19126cb1ca52Saf intel_int_err(nb_regs->nb.int_regs.ferr_fat_int, 19136cb1ca52Saf nb_regs->nb.int_regs.ferr_nf_int); 19146cb1ca52Saf } 191520c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 191620c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "ie"); 191720c794b3Sgavinm } 191820c794b3Sgavinm 191920c794b3Sgavinm void 192020c794b3Sgavinm nb_fat_fbd_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 192120c794b3Sgavinm void *data) 192220c794b3Sgavinm { 192320c794b3Sgavinm char *intr; 192420c794b3Sgavinm nb_mem_scatchpad_t *sp; 192520c794b3Sgavinm 192620c794b3Sgavinm intr = fat_memory_error(nb_regs, data); 192720c794b3Sgavinm sp = &((nb_scatchpad_t *)data)->ms; 192820c794b3Sgavinm 192920c794b3Sgavinm if (sp->dimm != -1) { 193020c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 5, 193120c794b3Sgavinm "motherboard", 0, 193220c794b3Sgavinm "memory-controller", sp->branch, 193320c794b3Sgavinm "dram-channel", sp->channel, 193420c794b3Sgavinm "dimm", sp->dimm, 193520c794b3Sgavinm "rank", sp->rank); 193620c794b3Sgavinm } else if (sp->channel != -1) { 193720c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 3, 193820c794b3Sgavinm "motherboard", 0, 193920c794b3Sgavinm "memory-controller", sp->branch, 194020c794b3Sgavinm "dram-channel", sp->channel); 19416cb1ca52Saf } else if (sp->branch != -1) { 194220c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2, 194320c794b3Sgavinm "motherboard", 0, 194420c794b3Sgavinm "memory-controller", sp->branch); 19456cb1ca52Saf } else { 19466cb1ca52Saf fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 19476cb1ca52Saf "motherboard", 0); 194820c794b3Sgavinm } 194920c794b3Sgavinm 195020c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s", 195120c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, intr); 195220c794b3Sgavinm } 195320c794b3Sgavinm 195420c794b3Sgavinm void 195520c794b3Sgavinm nb_nf_fbd_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 195620c794b3Sgavinm void *data) 195720c794b3Sgavinm { 195820c794b3Sgavinm char *intr; 195920c794b3Sgavinm nb_mem_scatchpad_t *sp; 196020c794b3Sgavinm 196120c794b3Sgavinm intr = nf_memory_error(nb_regs, data); 196220c794b3Sgavinm sp = &((nb_scatchpad_t *)data)->ms; 196320c794b3Sgavinm 196420c794b3Sgavinm if (sp->dimm != -1) { 196520c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 5, 196620c794b3Sgavinm "motherboard", 0, 196720c794b3Sgavinm "memory-controller", sp->branch, 196820c794b3Sgavinm "dram-channel", sp->channel, 196920c794b3Sgavinm "dimm", sp->dimm, 197020c794b3Sgavinm "rank", sp->rank); 197120c794b3Sgavinm } else if (sp->channel != -1) { 197220c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 3, 197320c794b3Sgavinm "motherboard", 0, 197420c794b3Sgavinm "memory-controller", sp->branch, 197520c794b3Sgavinm "dram-channel", sp->channel); 19766cb1ca52Saf } else if (sp->branch != -1) { 197720c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2, 197820c794b3Sgavinm "motherboard", 0, 197920c794b3Sgavinm "memory-controller", sp->branch); 19806cb1ca52Saf } else { 19816cb1ca52Saf fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 19826cb1ca52Saf "motherboard", 0); 198320c794b3Sgavinm } 198420c794b3Sgavinm 198520c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s", 198620c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, intr); 198720c794b3Sgavinm } 198820c794b3Sgavinm 198920c794b3Sgavinm void 199020c794b3Sgavinm nb_dma_report(char *class, nvlist_t *detector) 199120c794b3Sgavinm { 199220c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 199320c794b3Sgavinm "motherboard", 0); 199420c794b3Sgavinm 199520c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 199620c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "dma"); 199720c794b3Sgavinm } 199820c794b3Sgavinm 19995f28a827Saf void 20005f28a827Saf nb_thr_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 20015f28a827Saf void *data) 20025f28a827Saf { 20035f28a827Saf ((nb_scatchpad_t *)data)->intel_error_list = 20045f28a827Saf intel_thr_err(nb_regs->nb.thr_regs.ferr_fat_thr, 20055f28a827Saf nb_regs->nb.thr_regs.ferr_nf_thr); 20065f28a827Saf fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 20075f28a827Saf "motherboard", 0); 20085f28a827Saf 20095f28a827Saf (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 20105f28a827Saf FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "otf"); 20115f28a827Saf } 20125f28a827Saf 2013*85738508SVuong Nguyen void 2014*85738508SVuong Nguyen nb_nf_mem_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector, 2015*85738508SVuong Nguyen void *data) 2016*85738508SVuong Nguyen { 2017*85738508SVuong Nguyen char *intr; 2018*85738508SVuong Nguyen nb_mem_scatchpad_t *sp; 2019*85738508SVuong Nguyen 2020*85738508SVuong Nguyen intr = nf_mem_error(nb_regs, data); 2021*85738508SVuong Nguyen sp = &((nb_scatchpad_t *)data)->ms; 2022*85738508SVuong Nguyen 2023*85738508SVuong Nguyen if (sp->dimm != -1) { 2024*85738508SVuong Nguyen fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 5, 2025*85738508SVuong Nguyen "motherboard", 0, 2026*85738508SVuong Nguyen "memory-controller", sp->branch, 2027*85738508SVuong Nguyen "dram-channel", sp->channel, 2028*85738508SVuong Nguyen "dimm", sp->dimm, 2029*85738508SVuong Nguyen "rank", sp->rank); 2030*85738508SVuong Nguyen } else if (sp->channel != -1) { 2031*85738508SVuong Nguyen fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 3, 2032*85738508SVuong Nguyen "motherboard", 0, 2033*85738508SVuong Nguyen "memory-controller", sp->branch, 2034*85738508SVuong Nguyen "dram-channel", sp->channel); 2035*85738508SVuong Nguyen } else if (sp->branch != -1) { 2036*85738508SVuong Nguyen fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2, 2037*85738508SVuong Nguyen "motherboard", 0, 2038*85738508SVuong Nguyen "memory-controller", sp->branch); 2039*85738508SVuong Nguyen } else { 2040*85738508SVuong Nguyen fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 2041*85738508SVuong Nguyen "motherboard", 0); 2042*85738508SVuong Nguyen } 2043*85738508SVuong Nguyen 2044*85738508SVuong Nguyen (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s", 2045*85738508SVuong Nguyen FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, intr); 2046*85738508SVuong Nguyen } 2047*85738508SVuong Nguyen 204820c794b3Sgavinm 204920c794b3Sgavinm nvlist_t * 205020c794b3Sgavinm nb_report(const nb_regs_t *nb_regs, char *class, nv_alloc_t *nva, void *scratch) 205120c794b3Sgavinm { 205220c794b3Sgavinm nvlist_t *detector = fm_nvlist_create(nva); 205320c794b3Sgavinm 205420c794b3Sgavinm switch (nb_regs->flag) { 205520c794b3Sgavinm case NB_REG_LOG_FSB: 205620c794b3Sgavinm nb_fsb_report(nb_regs, class, detector, scratch); 205720c794b3Sgavinm break; 205820c794b3Sgavinm case NB_REG_LOG_PEX: 205920c794b3Sgavinm nb_pex_report(nb_regs, class, detector, scratch); 206020c794b3Sgavinm break; 206120c794b3Sgavinm case NB_REG_LOG_INT: 206220c794b3Sgavinm nb_int_report(nb_regs, class, detector, scratch); 206320c794b3Sgavinm break; 206420c794b3Sgavinm case NB_REG_LOG_FAT_FBD: 206520c794b3Sgavinm nb_fat_fbd_report(nb_regs, class, detector, scratch); 206620c794b3Sgavinm break; 206720c794b3Sgavinm case NB_REG_LOG_NF_FBD: 206820c794b3Sgavinm nb_nf_fbd_report(nb_regs, class, detector, scratch); 206920c794b3Sgavinm break; 207020c794b3Sgavinm case NB_REG_LOG_DMA: 207120c794b3Sgavinm nb_dma_report(class, detector); 207220c794b3Sgavinm break; 20735f28a827Saf case NB_REG_LOG_THR: 20745f28a827Saf nb_thr_report(nb_regs, class, detector, scratch); 20755f28a827Saf break; 2076*85738508SVuong Nguyen case NB_REG_LOG_NF_MEM: 2077*85738508SVuong Nguyen nb_nf_mem_report(nb_regs, class, detector, scratch); 2078*85738508SVuong Nguyen break; 207920c794b3Sgavinm default: 208020c794b3Sgavinm fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1, 208120c794b3Sgavinm "motherboard", 0); 208220c794b3Sgavinm 208320c794b3Sgavinm (void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s", 208420c794b3Sgavinm FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "unknown"); 208520c794b3Sgavinm } 208620c794b3Sgavinm return (detector); 208720c794b3Sgavinm } 208820c794b3Sgavinm 208920c794b3Sgavinm /*ARGSUSED*/ 209020c794b3Sgavinm void 209120c794b3Sgavinm nb_drain(void *ignored, const void *data, const errorq_elem_t *eqe) 209220c794b3Sgavinm { 209320c794b3Sgavinm nb_logout_t *acl = (nb_logout_t *)data; 209420c794b3Sgavinm errorq_elem_t *eqep, *scr_eqep; 209520c794b3Sgavinm nvlist_t *ereport, *detector; 209620c794b3Sgavinm nv_alloc_t *nva = NULL; 209720c794b3Sgavinm char buf[FM_MAX_CLASS]; 209820c794b3Sgavinm nb_scatchpad_t nb_scatchpad; 209920c794b3Sgavinm 210020c794b3Sgavinm if (panicstr) { 210120c794b3Sgavinm if ((eqep = errorq_reserve(ereport_errorq)) == NULL) 210220c794b3Sgavinm return; 210320c794b3Sgavinm ereport = errorq_elem_nvl(ereport_errorq, eqep); 210420c794b3Sgavinm /* 210520c794b3Sgavinm * Now try to allocate another element for scratch space and 210620c794b3Sgavinm * use that for further scratch space (eg for constructing 210720c794b3Sgavinm * nvlists to add the main ereport). If we can't reserve 210820c794b3Sgavinm * a scratch element just fallback to working within the 210920c794b3Sgavinm * element we already have, and hope for the best. All this 211020c794b3Sgavinm * is necessary because the fixed buffer nv allocator does 211120c794b3Sgavinm * not reclaim freed space and nvlist construction is 211220c794b3Sgavinm * expensive. 211320c794b3Sgavinm */ 211420c794b3Sgavinm if ((scr_eqep = errorq_reserve(ereport_errorq)) != NULL) 211520c794b3Sgavinm nva = errorq_elem_nva(ereport_errorq, scr_eqep); 211620c794b3Sgavinm else 211720c794b3Sgavinm nva = errorq_elem_nva(ereport_errorq, eqep); 211820c794b3Sgavinm } else { 211920c794b3Sgavinm ereport = fm_nvlist_create(NULL); 212020c794b3Sgavinm } 212120c794b3Sgavinm detector = nb_report(&acl->nb_regs, buf, nva, &nb_scatchpad); 212220c794b3Sgavinm if (detector == NULL) 212320c794b3Sgavinm return; 212420c794b3Sgavinm fm_ereport_set(ereport, FM_EREPORT_VERSION, buf, 212520c794b3Sgavinm fm_ena_generate(acl->acl_timestamp, FM_ENA_FMT1), detector, NULL); 212620c794b3Sgavinm /* 212720c794b3Sgavinm * We're done with 'detector' so reclaim the scratch space. 212820c794b3Sgavinm */ 212920c794b3Sgavinm if (panicstr) { 213020c794b3Sgavinm fm_nvlist_destroy(detector, FM_NVA_RETAIN); 213120c794b3Sgavinm nv_alloc_reset(nva); 213220c794b3Sgavinm } else { 213320c794b3Sgavinm fm_nvlist_destroy(detector, FM_NVA_FREE); 213420c794b3Sgavinm } 213520c794b3Sgavinm 213620c794b3Sgavinm /* 213720c794b3Sgavinm * Encode the error-specific data that was saved in the logout area. 213820c794b3Sgavinm */ 213920c794b3Sgavinm nb_ereport_add_logout(ereport, acl, &nb_scatchpad); 214020c794b3Sgavinm 214120c794b3Sgavinm if (panicstr) { 214220c794b3Sgavinm errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC); 214320c794b3Sgavinm if (scr_eqep) 214420c794b3Sgavinm errorq_cancel(ereport_errorq, scr_eqep); 214520c794b3Sgavinm } else { 214620c794b3Sgavinm (void) fm_ereport_post(ereport, EVCH_TRYHARD); 214720c794b3Sgavinm fm_nvlist_destroy(ereport, FM_NVA_FREE); 214820c794b3Sgavinm } 214920c794b3Sgavinm } 2150