xref: /illumos-gate/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c (revision 1a220b56b93ff1dc80855691548503117af4cc10)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/regset.h>
31 #include <sys/privregs.h>
32 #include <sys/pci_impl.h>
33 #include <sys/cpuvar.h>
34 #include <sys/x86_archext.h>
35 #include <sys/cmn_err.h>
36 #include <sys/systm.h>
37 #include <sys/sysmacros.h>
38 #include <sys/chip.h>
39 #include <sys/cyclic.h>
40 #include <sys/cpu_module_impl.h>
41 #include <sys/pci_cfgspace_impl.h>
42 #include <sys/sysevent.h>
43 #include <sys/smbios.h>
44 #include <sys/mca_x86.h>
45 #include <sys/mca_amd.h>
46 #include <sys/mc.h>
47 #include <sys/psw.h>
48 #include <sys/ddi.h>
49 #include <sys/sunddi.h>
50 #include <sys/sdt.h>
51 #include <sys/fm/util.h>
52 #include <sys/fm/protocol.h>
53 #include <sys/fm/cpu/AMD.h>
54 #include <sys/acpi/acpi.h>
55 #include <sys/acpi/acpi_pci.h>
56 #include <sys/acpica.h>
57 
58 #include "ao.h"
59 #include "ao_mca_disp.h"
60 
61 errorq_t *ao_mca_queue;			/* machine-check ereport queue */
62 int ao_mca_stack_flag = 0;		/* record stack trace in ereports */
63 int ao_mca_smi_disable = 1;		/* attempt to disable SMI polling */
64 
65 ao_bank_regs_t ao_bank_regs[AMD_MCA_BANK_COUNT] = {
66 	{ AMD_MSR_DC_STATUS, AMD_MSR_DC_ADDR },
67 	{ AMD_MSR_IC_STATUS, AMD_MSR_IC_ADDR },
68 	{ AMD_MSR_BU_STATUS, AMD_MSR_BU_ADDR },
69 	{ AMD_MSR_LS_STATUS, AMD_MSR_LS_ADDR },
70 	{ AMD_MSR_NB_STATUS, AMD_MSR_NB_ADDR }
71 };
72 
73 typedef struct ao_bank_cfg {
74 	uint_t bank_ctl;
75 	uint_t bank_ctl_mask;
76 	uint64_t bank_ctl_init;
77 	uint_t bank_status;
78 	uint_t bank_addr;
79 } ao_bank_cfg_t;
80 
81 static const ao_bank_cfg_t ao_bank_cfgs[] = {
82 	{ AMD_MSR_DC_CTL, AMD_MSR_DC_MASK, AMD_DC_CTL_INIT, AMD_MSR_DC_STATUS,
83 	    AMD_MSR_DC_ADDR },
84 	{ AMD_MSR_IC_CTL, AMD_MSR_IC_MASK, AMD_IC_CTL_INIT, AMD_MSR_IC_STATUS,
85 	    AMD_MSR_IC_ADDR },
86 	{ AMD_MSR_BU_CTL, AMD_MSR_BU_MASK, AMD_BU_CTL_INIT, AMD_MSR_BU_STATUS,
87 	    AMD_MSR_BU_ADDR },
88 	{ AMD_MSR_LS_CTL, AMD_MSR_LS_MASK, AMD_LS_CTL_INIT, AMD_MSR_LS_STATUS,
89 	    AMD_MSR_LS_ADDR },
90 	{ AMD_MSR_NB_CTL, AMD_MSR_NB_MASK, AMD_NB_CTL_INIT, AMD_MSR_NB_STATUS,
91 	    AMD_MSR_NB_ADDR }
92 };
93 
94 static const ao_error_disp_t ao_disp_unknown = {
95 	FM_EREPORT_CPU_AMD_UNKNOWN,
96 	FM_EREPORT_PAYLOAD_FLAGS_CPU_AMD_UNKNOWN
97 };
98 
99 /*
100  * This is quite awful but necessary to work around x86 system vendor's view of
101  * the world.  Other operating systems (you know who you are) don't understand
102  * Opteron-specific error handling, so BIOS and system vendors often hide these
103  * conditions from them by using SMI polling to copy out any errors from the
104  * machine-check registers.  When Solaris runs on a system with this feature,
105  * we want to disable the SMI polling so we can use FMA instead.  Sadly, there
106  * isn't even a standard self-describing way to express the whole situation,
107  * so we have to resort to hard-coded values.  This should all be changed to
108  * be a self-describing vendor-specific SMBIOS structure in the future.
109  */
110 static const struct ao_smi_disable {
111 	const char *asd_sys_vendor;	/* SMB_TYPE_SYSTEM vendor prefix */
112 	const char *asd_bios_vendor;	/* SMB_TYPE_BIOS vendor prefix */
113 	uint8_t asd_code;		/* output code for SMI disable */
114 } ao_smi_disable[] = {
115 	{ "Sun Microsystems", "American Megatrends", 0x59 },
116 	{ NULL, NULL, 0 }
117 };
118 
119 static int
120 ao_disp_match_r4(uint16_t ref, uint8_t r4)
121 {
122 	static const uint16_t ao_r4_map[] = {
123 		AO_MCA_R4_BIT_GEN,	/* AMD_ERRCODE_R4_GEN */
124 		AO_MCA_R4_BIT_RD,	/* AMD_ERRCODE_R4_RD */
125 		AO_MCA_R4_BIT_WR,	/* AMD_ERRCODE_R4_WR */
126 		AO_MCA_R4_BIT_DRD,	/* AMD_ERRCODE_R4_DRD */
127 		AO_MCA_R4_BIT_DWR,	/* AMD_ERRCODE_R4_DWR */
128 		AO_MCA_R4_BIT_IRD,	/* AMD_ERRCODE_R4_IRD */
129 		AO_MCA_R4_BIT_PREFETCH,	/* AMD_ERRCODE_R4_PREFETCH */
130 		AO_MCA_R4_BIT_EVICT,	/* AMD_ERRCODE_R4_EVICT */
131 		AO_MCA_R4_BIT_SNOOP	/* AMD_ERRCODE_R4_SNOOP */
132 	};
133 
134 	ASSERT(r4 < sizeof (ao_r4_map) / sizeof (uint16_t));
135 
136 	return ((ref & ao_r4_map[r4]) != 0);
137 }
138 
139 static int
140 ao_disp_match_pp(uint8_t ref, uint8_t pp)
141 {
142 	static const uint8_t ao_pp_map[] = {
143 		AO_MCA_PP_BIT_SRC,	/* AMD_ERRCODE_PP_SRC */
144 		AO_MCA_PP_BIT_RSP,	/* AMD_ERRCODE_PP_RSP */
145 		AO_MCA_PP_BIT_OBS,	/* AMD_ERRCODE_PP_OBS */
146 		AO_MCA_PP_BIT_GEN	/* AMD_ERRCODE_PP_GEN */
147 	};
148 
149 	ASSERT(pp < sizeof (ao_pp_map) / sizeof (uint8_t));
150 
151 	return ((ref & ao_pp_map[pp]) != 0);
152 }
153 
154 static int
155 ao_disp_match_ii(uint8_t ref, uint8_t ii)
156 {
157 	static const uint8_t ao_ii_map[] = {
158 		AO_MCA_II_BIT_MEM,	/* AMD_ERRCODE_II_MEM */
159 		0,
160 		AO_MCA_II_BIT_IO,	/* AMD_ERRCODE_II_IO */
161 		AO_MCA_II_BIT_GEN	/* AMD_ERRCODE_II_GEN */
162 	};
163 
164 	ASSERT(ii < sizeof (ao_ii_map) / sizeof (uint8_t));
165 
166 	return ((ref & ao_ii_map[ii]) != 0);
167 }
168 
169 static uint8_t
170 bit_strip(uint16_t *codep, uint16_t mask, uint16_t shift)
171 {
172 	uint8_t val = (*codep & mask) >> shift;
173 	*codep &= ~mask;
174 	return (val);
175 }
176 
177 #define	BIT_STRIP(codep, name) \
178 	bit_strip(codep, AMD_ERRCODE_##name##_MASK, AMD_ERRCODE_##name##_SHIFT)
179 
180 static int
181 ao_disp_match_one(const ao_error_disp_t *aed, uint64_t status)
182 {
183 	uint16_t code = status & AMD_ERRCODE_MASK;
184 	uint8_t extcode = (status & AMD_ERREXT_MASK) >> AMD_ERREXT_SHIFT;
185 	uint64_t stat_mask = aed->aed_stat_mask;
186 	uint64_t stat_mask_res = aed->aed_stat_mask_res;
187 
188 	/*
189 	 * If the bank's status register indicates overflow, then we can no
190 	 * longer rely on the value of CECC: our experience with actual fault
191 	 * injection has shown that multiple CE's overwriting each other shows
192 	 * AMD_BANK_STAT_CECC and AMD_BANK_STAT_UECC both set to zero.  This
193 	 * should be clarified in a future BKDG or by the Revision Guide.
194 	 */
195 	if (status & AMD_BANK_STAT_OVER) {
196 		stat_mask &= ~AMD_BANK_STAT_CECC;
197 		stat_mask_res &= ~AMD_BANK_STAT_CECC;
198 	}
199 
200 	if ((status & stat_mask) != stat_mask_res)
201 		return (0);
202 
203 	/*
204 	 * r4 and pp bits are stored separately, so we mask off and compare them
205 	 * for the code types that use them.  Once we've taken the r4 and pp
206 	 * bits out of the equation, we can directly compare the resulting code
207 	 * with the one stored in the ao_error_disp_t.
208 	 */
209 	if (AMD_ERRCODE_ISMEM(code)) {
210 		uint8_t r4 = BIT_STRIP(&code, R4);
211 
212 		if (!ao_disp_match_r4(aed->aed_stat_r4_bits, r4))
213 			return (0);
214 
215 	} else if (AMD_ERRCODE_ISBUS(code)) {
216 		uint8_t r4 = BIT_STRIP(&code, R4);
217 		uint8_t pp = BIT_STRIP(&code, PP);
218 		uint8_t ii = BIT_STRIP(&code, II);
219 
220 		if (!ao_disp_match_r4(aed->aed_stat_r4_bits, r4) ||
221 		    !ao_disp_match_pp(aed->aed_stat_pp_bits, pp) ||
222 		    !ao_disp_match_ii(aed->aed_stat_ii_bits, ii))
223 			return (0);
224 	}
225 
226 	return (code == aed->aed_stat_code && extcode == aed->aed_stat_extcode);
227 }
228 
229 static const ao_error_disp_t *
230 ao_disp_match(uint_t bankno, uint64_t status)
231 {
232 	const ao_error_disp_t *aed;
233 
234 	for (aed = ao_error_disp[bankno]; aed->aed_stat_mask != 0; aed++) {
235 		if (ao_disp_match_one(aed, status))
236 			return (aed);
237 	}
238 
239 	return (&ao_disp_unknown);
240 }
241 
242 void
243 ao_pcicfg_write(uint_t chipid, uint_t func, uint_t reg, uint32_t val)
244 {
245 	ASSERT(chipid + 24 <= 31);
246 	ASSERT((func & 7) == func);
247 	ASSERT((reg & 3) == 0 && reg < 256);
248 
249 	pci_mech1_putl(0, chipid + 24, func, reg, val);
250 }
251 
252 uint32_t
253 ao_pcicfg_read(uint_t chipid, uint_t func, uint_t reg)
254 {
255 	ASSERT(chipid + 24 <= 31);
256 	ASSERT((func & 7) == func);
257 	ASSERT((reg & 3) == 0 && reg < 256);
258 
259 	return (pci_mech1_getl(0, chipid + 24, func, reg));
260 }
261 
262 /*
263  * Setup individual bank detectors after stashing their bios settings.
264  */
265 static void
266 ao_bank_cfg(ao_mca_t *mca)
267 {
268 	ao_bios_cfg_t *bioscfg = &mca->ao_mca_bios_cfg;
269 	const ao_bank_cfg_t *bankcfg = ao_bank_cfgs;
270 	int i;
271 
272 	for (i = 0; i < AMD_MCA_BANK_COUNT; i++, bankcfg++) {
273 		bioscfg->bcfg_bank_ctl[i] = rdmsr(bankcfg->bank_ctl);
274 		bioscfg->bcfg_bank_mask[i] = rdmsr(bankcfg->bank_ctl_mask);
275 		wrmsr(bankcfg->bank_ctl, bankcfg->bank_ctl_init);
276 	}
277 }
278 
279 /*
280  * Bits to be added to the NorthBridge (NB) configuration register.
281  * See BKDG 3.29 Section 3.6.4.2 for more information.
282  */
283 uint32_t ao_nb_cfg_add =
284     AMD_NB_CFG_NBMCATOMSTCPUEN |
285     AMD_NB_CFG_DISPCICFGCPUERRRSP |
286     AMD_NB_CFG_SYNCONUCECCEN |
287     AMD_NB_CFG_CPUECCERREN;
288 
289 /*
290  * Bits to be cleared from the NorthBridge (NB) configuration register.
291  * See BKDG 3.29 Section 3.6.4.2 for more information.
292  */
293 uint32_t ao_nb_cfg_remove =
294     AMD_NB_CFG_IORDDATERREN |
295     AMD_NB_CFG_SYNCONANYERREN |
296     AMD_NB_CFG_SYNCONWDOGEN |
297     AMD_NB_CFG_IOERRDIS |
298     AMD_NB_CFG_IOMSTABORTDIS |
299     AMD_NB_CFG_SYNCPKTPROPDIS |
300     AMD_NB_CFG_SYNCPKTGENDIS;
301 
302 /*
303  * Bits to be used if we configure the NorthBridge (NB) Watchdog.  The watchdog
304  * triggers a machine check exception when no response to an NB system access
305  * occurs within a specified time interval.  If the BIOS (i.e. platform design)
306  * has enabled the watchdog, we leave its rate alone.  If the BIOS has not
307  * enabled the watchdog, we enable it and set the rate to one specified below.
308  * To disable the watchdog, add the AMD_NB_CFG_WDOGTMRDIS bit to ao_nb_cfg_add.
309  */
310 uint32_t ao_nb_cfg_wdog =
311     AMD_NB_CFG_WDOGTMRCNTSEL_4095 |
312     AMD_NB_CFG_WDOGTMRBASESEL_1MS;
313 
314 static void
315 ao_nb_cfg(ao_mca_t *mca)
316 {
317 	uint_t chipid = chip_plat_get_chipid(CPU);
318 	uint32_t val;
319 
320 	if (chip_plat_get_clogid(CPU) != 0)
321 		return; /* only configure NB once per CPU */
322 
323 	/*
324 	 * Read the NorthBridge (NB) configuration register in PCI space,
325 	 * modify the settings accordingly, and store the new value back.
326 	 */
327 	mca->ao_mca_bios_cfg.bcfg_nb_cfg = val =
328 	    ao_pcicfg_read(chipid, AMD_NB_FUNC, AMD_NB_REG_CFG);
329 
330 	/*
331 	 * If the watchdog was disabled, enable it according to the policy
332 	 * described above.  Then apply the ao_nb_cfg_[add|remove] masks.
333 	 */
334 	if (val & AMD_NB_CFG_WDOGTMRDIS) {
335 		val &= ~AMD_NB_CFG_WDOGTMRBASESEL_MASK;
336 		val &= ~AMD_NB_CFG_WDOGTMRCNTSEL_MASK;
337 		val &= ~AMD_NB_CFG_WDOGTMRDIS;
338 		val |= ao_nb_cfg_wdog;
339 	}
340 
341 	val &= ~ao_nb_cfg_remove;
342 	val |= ao_nb_cfg_add;
343 
344 	ao_pcicfg_write(chipid, AMD_NB_FUNC, AMD_NB_REG_CFG, val);
345 }
346 
347 /*
348  * Capture the machine-check exception state into our per-CPU logout area, and
349  * dispatch a copy of the logout area to our error queue for ereport creation.
350  * If 'rp' is non-NULL, we're being called from trap context; otherwise we're
351  * being polled or poked by the injector.  We return the number of errors
352  * found through 'np', and a boolean indicating whether the error is fatal.
353  * The caller is expected to call fm_panic() if we return fatal (non-zero).
354  */
355 int
356 ao_mca_logout(ao_cpu_logout_t *acl, struct regs *rp, int *np)
357 {
358 	int i, fatal = 0, n = 0;
359 
360 	acl->acl_timestamp = gethrtime_waitfree();
361 	acl->acl_mcg_status = rdmsr(IA32_MSR_MCG_STATUS);
362 	acl->acl_ip = rp ? rp->r_pc : 0;
363 	acl->acl_flags = 0;
364 
365 	/*
366 	 * Iterate over the banks of machine-check registers, read the address
367 	 * and status registers into the logout area, and clear them as we go.
368 	 */
369 	for (i = 0; i < AMD_MCA_BANK_COUNT; i++) {
370 		ao_bank_logout_t *abl = &acl->acl_banks[i];
371 
372 		abl->abl_addr = rdmsr(ao_bank_regs[i].abr_addr);
373 		abl->abl_status = rdmsr(ao_bank_regs[i].abr_status);
374 
375 		if (abl->abl_status & AMD_BANK_STAT_VALID)
376 			wrmsr(ao_bank_regs[i].abr_status, 0);
377 	}
378 
379 	if (rp == NULL || !USERMODE(rp->r_cs))
380 		acl->acl_flags |= AO_ACL_F_PRIV;
381 
382 	if (ao_mca_stack_flag)
383 		acl->acl_stackdepth = getpcstack(acl->acl_stack, FM_STK_DEPTH);
384 	else
385 		acl->acl_stackdepth = 0;
386 
387 	/*
388 	 * Clear MCG_STATUS, indicating that machine-check trap processing is
389 	 * complete.  Once we do this, another machine-check trap can occur.
390 	 */
391 	wrmsr(IA32_MSR_MCG_STATUS, 0);
392 
393 	/*
394 	 * If we took a machine-check trap, then the error is fatal if the
395 	 * return instruction pointer is not valid in the global register.
396 	 */
397 	if (rp != NULL && !(acl->acl_mcg_status & MCG_STATUS_RIPV))
398 		fatal++;
399 
400 	/*
401 	 * Now iterate over the saved logout area, determining whether the
402 	 * error that we saw is fatal or not based upon our dispositions
403 	 * and the hardware's indicators of whether or not we can resume.
404 	 */
405 	for (i = 0; i < AMD_MCA_BANK_COUNT; i++) {
406 		ao_bank_logout_t *abl = &acl->acl_banks[i];
407 		const ao_error_disp_t *aed;
408 		uint8_t when;
409 
410 		if (!(abl->abl_status & AMD_BANK_STAT_VALID))
411 			continue;
412 
413 		aed = ao_disp_match(i, abl->abl_status);
414 		if ((when = aed->aed_panic_when) != AO_AED_PANIC_NEVER) {
415 			if ((when & AO_AED_PANIC_ALWAYS) ||
416 			    ((when & AO_AED_PANIC_IFMCE) && rp != NULL)) {
417 					fatal++;
418 			}
419 		}
420 
421 		/*
422 		 * If we are taking a machine-check exception and the overflow
423 		 * bit is set or our context is corrupt, then we must die.
424 		 * NOTE: This code assumes that if the overflow bit is set and
425 		 * we didn't take a #mc exception (i.e. the poller found it),
426 		 * then multiple correctable errors overwrote each other.
427 		 * This will need to change if we eventually use the Opteron
428 		 * Rev E exception mechanism for detecting correctable errors.
429 		 */
430 		if (rp != NULL && (abl->abl_status &
431 		    (AMD_BANK_STAT_OVER | AMD_BANK_STAT_PCC)))
432 			fatal++;
433 
434 		/*
435 		 * If we are taking a machine-check exception and we don't
436 		 * recognize the error case at all, then assume it's fatal.
437 		 * This will need to change if we eventually use the Opteron
438 		 * Rev E exception mechanism for detecting correctable errors.
439 		 */
440 		if (rp != NULL && aed == &ao_disp_unknown)
441 			fatal++;
442 
443 		n++;
444 	}
445 
446 	if (n > 0) {
447 		errorq_dispatch(ao_mca_queue, acl, sizeof (ao_cpu_logout_t),
448 		    fatal && cmi_panic_on_uncorrectable_error ?
449 		    ERRORQ_SYNC : ERRORQ_ASYNC);
450 	}
451 
452 	if (np != NULL)
453 		*np = n; /* return number of errors found to caller */
454 
455 	return (fatal != 0);
456 }
457 
458 static uint_t
459 ao_ereport_synd(ao_mca_t *mca,
460     const ao_bank_logout_t *abl, uint_t *typep, int is_nb)
461 {
462 	if (is_nb) {
463 		if ((mca->ao_mca_bios_cfg.bcfg_nb_cfg &
464 		    AMD_NB_CFG_CHIPKILLECCEN) != 0) {
465 			*typep = AMD_SYNDTYPE_CHIPKILL;
466 			return (AMD_NB_STAT_CKSYND(abl->abl_status));
467 		} else {
468 			*typep = AMD_SYNDTYPE_ECC;
469 			return (AMD_BANK_SYND(abl->abl_status));
470 		}
471 	} else {
472 		*typep = AMD_SYNDTYPE_ECC;
473 		return (AMD_BANK_SYND(abl->abl_status));
474 	}
475 }
476 
477 static void
478 ao_ereport_create_resource_elem(nvlist_t **nvlp, nv_alloc_t *nva,
479     mc_unum_t *unump, int dimmnum)
480 {
481 	nvlist_t *snvl;
482 	*nvlp = fm_nvlist_create(nva);		/* freed by caller */
483 
484 	snvl = fm_nvlist_create(nva);
485 
486 	(void) nvlist_add_uint64(snvl, FM_FMRI_HC_SPECIFIC_OFFSET,
487 	    unump->unum_offset);
488 
489 	fm_fmri_hc_set(*nvlp, FM_HC_SCHEME_VERSION, NULL, snvl, 4,
490 	    "motherboard", unump->unum_board,
491 	    "chip", unump->unum_chip,
492 	    "memory-controller", unump->unum_mc,
493 	    "dimm", unump->unum_dimms[dimmnum]);
494 
495 	fm_nvlist_destroy(snvl, nva ? FM_NVA_RETAIN : FM_NVA_FREE);
496 }
497 
498 static void
499 ao_ereport_add_resource(nvlist_t *payload, nv_alloc_t *nva, mc_unum_t *unump)
500 {
501 
502 	nvlist_t *elems[MC_UNUM_NDIMM];
503 	int nelems = 0;
504 	int i;
505 
506 	for (i = 0; i < MC_UNUM_NDIMM; i++) {
507 		if (unump->unum_dimms[i] == -1)
508 			break;
509 		ao_ereport_create_resource_elem(&elems[nelems++], nva,
510 		    unump, i);
511 	}
512 
513 	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RESOURCE,
514 	    DATA_TYPE_NVLIST_ARRAY, nelems, elems, NULL);
515 
516 	for (i = 0; i < nelems; i++)
517 		fm_nvlist_destroy(elems[i], nva ? FM_NVA_RETAIN : FM_NVA_FREE);
518 }
519 
520 static void
521 ao_ereport_add_logout(ao_data_t *ao, nvlist_t *payload, nv_alloc_t *nva,
522     const ao_cpu_logout_t *acl, uint_t bankno, const ao_error_disp_t *aed)
523 {
524 	uint64_t members = aed->aed_ereport_members;
525 	ao_mca_t *mca = &ao->ao_mca;
526 	const ao_bank_logout_t *abl = &acl->acl_banks[bankno];
527 	uint_t synd, syndtype;
528 
529 	synd = ao_ereport_synd(mca, abl, &syndtype, bankno == AMD_MCA_BANK_NB);
530 
531 	if (members & FM_EREPORT_PAYLOAD_FLAG_BANK_STAT) {
532 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK_STAT,
533 		    DATA_TYPE_UINT64, abl->abl_status, NULL);
534 	}
535 
536 	if (members & FM_EREPORT_PAYLOAD_FLAG_BANK_NUM) {
537 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK_NUM,
538 		    DATA_TYPE_UINT8, bankno, NULL);
539 	}
540 
541 	if (members & FM_EREPORT_PAYLOAD_FLAG_ADDR) {
542 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ADDR,
543 		    DATA_TYPE_UINT64, abl->abl_addr, NULL);
544 	}
545 
546 	if (members & FM_EREPORT_PAYLOAD_FLAG_ADDR_VALID) {
547 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ADDR_VALID,
548 		    DATA_TYPE_BOOLEAN_VALUE, (abl->abl_status &
549 		    AMD_BANK_STAT_ADDRV) ? B_TRUE : B_FALSE, NULL);
550 	}
551 
552 	if (members & FM_EREPORT_PAYLOAD_FLAG_SYND) {
553 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SYND,
554 		    DATA_TYPE_UINT16, synd, NULL);
555 	}
556 
557 	if (members & FM_EREPORT_PAYLOAD_FLAG_SYND_TYPE) {
558 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SYND_TYPE,
559 		    DATA_TYPE_STRING, (syndtype == AMD_SYNDTYPE_CHIPKILL ?
560 		    "C" : "E"), NULL);
561 	}
562 
563 	if (members & FM_EREPORT_PAYLOAD_FLAG_IP) {
564 		uint64_t ip = (acl->acl_mcg_status & MCG_STATUS_EIPV) ?
565 		    acl->acl_ip : 0;
566 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_IP,
567 		    DATA_TYPE_UINT64, ip, NULL);
568 	}
569 
570 	if (members & FM_EREPORT_PAYLOAD_FLAG_PRIV) {
571 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PRIV,
572 		    DATA_TYPE_BOOLEAN_VALUE, (acl->acl_flags & AO_ACL_F_PRIV) ?
573 		    B_TRUE : B_FALSE, NULL);
574 	}
575 
576 	if (members & FM_EREPORT_PAYLOAD_FLAG_RESOURCE) {
577 		mc_unum_t unum;
578 		int addrvalid;
579 
580 		addrvalid = (members & FM_EREPORT_PAYLOAD_FLAG_ADDR) &&
581 		    (members & FM_EREPORT_PAYLOAD_FLAG_ADDR_VALID) &&
582 		    (abl->abl_status & AMD_BANK_STAT_ADDRV);
583 
584 		if (addrvalid && ao_mc_patounum(ao, abl->abl_addr, synd,
585 		    syndtype, &unum))
586 			ao_ereport_add_resource(payload, nva, &unum);
587 	}
588 
589 	if (ao_mca_stack_flag && members & FM_EREPORT_PAYLOAD_FLAG_STACK) {
590 		fm_payload_stack_add(payload, acl->acl_stack,
591 		    acl->acl_stackdepth);
592 	}
593 }
594 
595 static void
596 ao_ereport_post(const ao_cpu_logout_t *acl,
597     int bankno, const ao_error_disp_t *aed)
598 {
599 	ao_data_t *ao = acl->acl_ao;
600 	errorq_elem_t *eqep, *scr_eqep;
601 	nvlist_t *ereport, *detector;
602 	nv_alloc_t *nva = NULL;
603 	char buf[FM_MAX_CLASS];
604 
605 	if (panicstr) {
606 		if ((eqep = errorq_reserve(ereport_errorq)) == NULL)
607 			return;
608 		ereport = errorq_elem_nvl(ereport_errorq, eqep);
609 
610 		/*
611 		 * Now try to allocate another element for scratch space and
612 		 * use that for further scratch space (eg for constructing
613 		 * nvlists to add the main ereport).  If we can't reserve
614 		 * a scratch element just fallback to working within the
615 		 * element we already have, and hope for the best.  All this
616 		 * is necessary because the fixed buffer nv allocator does
617 		 * not reclaim freed space and nvlist construction is
618 		 * expensive.
619 		 */
620 		if ((scr_eqep = errorq_reserve(ereport_errorq)) != NULL)
621 			nva = errorq_elem_nva(ereport_errorq, scr_eqep);
622 		else
623 			nva = errorq_elem_nva(ereport_errorq, eqep);
624 	} else {
625 		ereport = fm_nvlist_create(NULL);
626 	}
627 
628 	/*
629 	 * Create the scheme "cpu" FMRI
630 	 */
631 	detector = ao_fmri_create(ao, nva);
632 
633 	/*
634 	 * Encode all the common data into the ereport.
635 	 */
636 	(void) snprintf(buf, FM_MAX_CLASS, "%s.%s.%s",
637 	    FM_ERROR_CPU, "amd", aed->aed_class);
638 
639 	fm_ereport_set(ereport, FM_EREPORT_VERSION, buf,
640 	    fm_ena_generate_cpu(acl->acl_timestamp, ao->ao_cpu->cpu_id,
641 	    FM_ENA_FMT1), detector, NULL);
642 
643 	/*
644 	 * We're done with 'detector' so reclaim the scratch space.
645 	 */
646 	if (panicstr) {
647 		fm_nvlist_destroy(detector, FM_NVA_RETAIN);
648 		nv_alloc_reset(nva);
649 	} else {
650 		fm_nvlist_destroy(detector, FM_NVA_FREE);
651 	}
652 
653 	/*
654 	 * Encode the error-specific data that was saved in the logout area.
655 	 */
656 	ao_ereport_add_logout(ao, ereport, nva, acl, bankno, aed);
657 
658 	if (panicstr) {
659 		errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
660 		if (scr_eqep)
661 			errorq_cancel(ereport_errorq, scr_eqep);
662 	} else {
663 		(void) fm_ereport_post(ereport, EVCH_TRYHARD);
664 		fm_nvlist_destroy(ereport, FM_NVA_FREE);
665 	}
666 }
667 
668 /*ARGSUSED*/
669 void
670 ao_mca_drain(void *ignored, const void *data, const errorq_elem_t *eqe)
671 {
672 	const ao_cpu_logout_t *acl = data;
673 	int i;
674 
675 	for (i = 0; i < AMD_MCA_BANK_COUNT; i++) {
676 		const ao_bank_logout_t *abl = &acl->acl_banks[i];
677 		const ao_error_disp_t *aed;
678 
679 		if (abl->abl_status & AMD_BANK_STAT_VALID) {
680 			aed = ao_disp_match(i, abl->abl_status);
681 			ao_ereport_post(acl, i, aed);
682 		}
683 	}
684 }
685 
686 int
687 ao_mca_trap(void *data, struct regs *rp)
688 {
689 	ao_data_t *ao = data;
690 	ao_mca_t *mca = &ao->ao_mca;
691 	ao_cpu_logout_t *acl = &mca->ao_mca_logout[AO_MCA_LOGOUT_EXCEPTION];
692 	return (ao_mca_logout(acl, rp, NULL));
693 }
694 
695 /*ARGSUSED*/
696 int
697 ao_mca_inject(void *data, cmi_mca_regs_t *regs, uint_t nregs)
698 {
699 	uint64_t hwcr, oldhwcr;
700 	int i;
701 
702 	oldhwcr = rdmsr(MSR_AMD_HWCR);
703 	hwcr = oldhwcr | AMD_HWCR_MCI_STATUS_WREN;
704 	wrmsr(MSR_AMD_HWCR, hwcr);
705 
706 	for (i = 0; i < nregs; i++)
707 		wrmsr(regs[i].cmr_msrnum, regs[i].cmr_msrval);
708 
709 	wrmsr(MSR_AMD_HWCR, oldhwcr);
710 	return (0);
711 }
712 
713 void
714 ao_mca_init(void *data)
715 {
716 	ao_data_t *ao = data;
717 	ao_mca_t *mca = &ao->ao_mca;
718 	uint64_t cap;
719 	int i;
720 
721 	ao_mca_poll_init(mca);
722 
723 	ASSERT(x86_feature & X86_MCA);
724 	cap = rdmsr(IA32_MSR_MCG_CAP);
725 	ASSERT(cap & MCG_CAP_CTL_P);
726 
727 	/*
728 	 * If the hardware's bank count is different than what we expect, then
729 	 * we're running on some Opteron variant that we don't understand yet.
730 	 */
731 	if ((cap & MCG_CAP_COUNT_MASK) != AMD_MCA_BANK_COUNT) {
732 		cmn_err(CE_WARN, "CPU %d has %llu MCA banks; expected %u: "
733 		    "disabling MCA on this CPU", ao->ao_cpu->cpu_id,
734 		    (u_longlong_t)cap & MCG_CAP_COUNT_MASK, AMD_MCA_BANK_COUNT);
735 		return;
736 	}
737 
738 	/*
739 	 * Configure the logout areas.  We preset every logout area's acl_ao
740 	 * pointer to refer back to our per-CPU state for errorq drain usage.
741 	 */
742 	for (i = 0; i < AO_MCA_LOGOUT_NUM; i++)
743 		mca->ao_mca_logout[i].acl_ao = ao;
744 
745 	ao_bank_cfg(mca);
746 	ao_nb_cfg(mca);
747 
748 	wrmsr(IA32_MSR_MCG_CTL, AMD_MCG_EN_ALL);
749 
750 	/*
751 	 * Throw away all existing bank state.  We do this because some BIOSes,
752 	 * perhaps during POST, do things to the machine that cause MCA state
753 	 * to be updated.  If we interpret this state as an actual error, we
754 	 * may end up indicting something that's not actually broken.
755 	 */
756 	for (i = 0; i < sizeof (ao_bank_cfgs) / sizeof (ao_bank_cfg_t); i++)
757 		wrmsr(ao_bank_cfgs[i].bank_status, 0ULL);
758 
759 	wrmsr(IA32_MSR_MCG_STATUS, 0ULL);
760 	membar_producer();
761 
762 	setcr4(getcr4() | CR4_MCE); /* enable #mc exceptions */
763 }
764 
765 /*
766  * Note that although this cpu module is loaded before the PSMs are
767  * loaded (and hence before acpica is loaded), this function is
768  * called from post_startup(), after PSMs are initialized and acpica
769  * is loaded.
770  */
771 static int
772 ao_acpi_find_smicmd(int *asd_port)
773 {
774 	FADT_DESCRIPTOR *fadt = NULL;
775 
776 	/*
777 	 * AcpiGetFirmwareTable works even if ACPI is disabled, so a failure
778 	 * here means we weren't able to retreive a pointer to the FADT.
779 	 */
780 	if (AcpiGetFirmwareTable(FADT_SIG, 1, ACPI_LOGICAL_ADDRESSING,
781 	    (ACPI_TABLE_HEADER **)&fadt) != AE_OK)
782 		return (-1);
783 
784 	ASSERT(fadt != NULL);
785 
786 	*asd_port = fadt->SmiCmd;
787 	return (0);
788 }
789 
790 /*ARGSUSED*/
791 void
792 ao_mca_post_init(void *data)
793 {
794 	const struct ao_smi_disable *asd;
795 	id_t id;
796 	int rv = -1, asd_port;
797 
798 	smbios_system_t sy;
799 	smbios_bios_t sb;
800 	smbios_info_t si;
801 
802 	/*
803 	 * Fetch the System and BIOS vendor strings from SMBIOS and see if they
804 	 * match a value in our table.  If so, disable SMI error polling.  This
805 	 * is grotesque and should be replaced by self-describing vendor-
806 	 * specific SMBIOS data or a specification enhancement instead.
807 	 */
808 	if (ao_mca_smi_disable && ksmbios != NULL &&
809 	    smbios_info_bios(ksmbios, &sb) != SMB_ERR &&
810 	    (id = smbios_info_system(ksmbios, &sy)) != SMB_ERR &&
811 	    smbios_info_common(ksmbios, id, &si) != SMB_ERR) {
812 
813 		for (asd = ao_smi_disable; asd->asd_sys_vendor != NULL; asd++) {
814 			if (strncmp(asd->asd_sys_vendor, si.smbi_manufacturer,
815 			    strlen(asd->asd_sys_vendor)) != 0 ||
816 			    strncmp(asd->asd_bios_vendor, sb.smbb_vendor,
817 			    strlen(asd->asd_bios_vendor)) != 0)
818 				continue;
819 
820 			/*
821 			 * Look for the SMI_CMD port in the ACPI FADT,
822 			 * if the port is 0, this platform doesn't support
823 			 * SMM, so there is no SMI error polling to disable.
824 			 */
825 			if ((rv = ao_acpi_find_smicmd(&asd_port)) == 0 &&
826 			    asd_port != 0) {
827 				cmn_err(CE_CONT, "?SMI polling disabled in "
828 				    "favor of Solaris Fault Management for "
829 				    "AMD Processors\n");
830 
831 				outb(asd_port, asd->asd_code);
832 
833 			} else if (rv < 0) {
834 				cmn_err(CE_CONT, "?Solaris Fault Management "
835 				    "for AMD Processors could not disable SMI "
836 				    "polling because an error occurred while "
837 				    "trying to determine the SMI command port "
838 				    "from the ACPI FADT table\n");
839 			}
840 			break;
841 		}
842 	}
843 
844 	ao_mca_poll_start();
845 }
846 
847 /*
848  * Called after a CPU has been marked with CPU_FAULTED.  Not called on the
849  * faulted CPU.  cpu_lock is held.
850  */
851 /*ARGSUSED*/
852 void
853 ao_faulted_enter(void *data)
854 {
855 	/*
856 	 * Nothing to do here.  We'd like to turn off the faulted CPU's
857 	 * correctable error detectors, but that can only be done by the
858 	 * faulted CPU itself.  cpu_get_state() will now return P_FAULTED,
859 	 * allowing the poller to skip this CPU until it is re-enabled.
860 	 */
861 }
862 
863 /*
864  * Called after the CPU_FAULTED bit has been cleared from a previously-faulted
865  * CPU.  Not called on the faulted CPU.  cpu_lock is held.
866  */
867 void
868 ao_faulted_exit(void *data)
869 {
870 	ao_data_t *ao = data;
871 
872 	/*
873 	 * We'd like to clear the faulted CPU's MCi_STATUS registers so as to
874 	 * avoid generating ereports for errors which occurred while the CPU was
875 	 * officially faulted.  Unfortunately, those registers can only be
876 	 * cleared by the CPU itself, so we can't do it here.
877 	 *
878 	 * We're going to set the UNFAULTING bit on the formerly-faulted CPU's
879 	 * MCA state.  This will tell the poller that the MCi_STATUS registers
880 	 * can't yet be trusted.  The poller, which is the first thing we
881 	 * control that'll execute on that CPU, will clear the registers, and
882 	 * will then clear the bit.
883 	 */
884 
885 	ao->ao_mca.ao_mca_flags |= AO_MCA_F_UNFAULTING;
886 }
887