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