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 2007 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/pghw.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/mc_amd.h>
48 #include <sys/psw.h>
49 #include <sys/ddi.h>
50 #include <sys/sunddi.h>
51 #include <sys/sdt.h>
52 #include <sys/fm/util.h>
53 #include <sys/fm/protocol.h>
54 #include <sys/fm/cpu/AMD.h>
55 #include <sys/acpi/acpi.h>
56 #include <sys/acpi/acpi_pci.h>
57 #include <sys/acpica.h>
58 
59 #include "ao.h"
60 #include "ao_mca_disp.h"
61 
62 #define	AO_REVS_FG (X86_CHIPREV_AMD_F_REV_F | X86_CHIPREV_AMD_F_REV_G)
63 
64 errorq_t *ao_mca_queue;			/* machine-check ereport queue */
65 int ao_mca_stack_flag = 0;		/* record stack trace in ereports */
66 int ao_mca_smi_disable = 1;		/* attempt to disable SMI polling */
67 
68 ao_bank_regs_t ao_bank_regs[AMD_MCA_BANK_COUNT] = {
69 	{ AMD_MSR_DC_STATUS, AMD_MSR_DC_ADDR, AMD_MSR_DC_MISC },
70 	{ AMD_MSR_IC_STATUS, AMD_MSR_IC_ADDR, AMD_MSR_IC_MISC },
71 	{ AMD_MSR_BU_STATUS, AMD_MSR_BU_ADDR, AMD_MSR_BU_MISC },
72 	{ AMD_MSR_LS_STATUS, AMD_MSR_LS_ADDR, AMD_MSR_LS_MISC },
73 	{ AMD_MSR_NB_STATUS, AMD_MSR_NB_ADDR, AMD_MSR_NB_MISC }
74 };
75 
76 struct ao_ctl_init {
77 	uint32_t ctl_revmask;	/* rev(s) to which this applies */
78 	uint64_t ctl_bits;	/* mca ctl reg bitmask to set */
79 };
80 
81 /*
82  * Additional NB MCA ctl initialization for revs F and G
83  */
84 static const struct ao_ctl_init ao_nb_ctl_init[] = {
85 	{ AO_REVS_FG, AMD_NB_CTL_INIT_REV_FG },
86 	{ X86_CHIPREV_UNKNOWN, 0 }
87 };
88 
89 typedef struct ao_bank_cfg {
90 	uint_t bank_ctl;
91 	uint_t bank_ctl_mask;
92 	uint64_t bank_ctl_init_cmn;			/* Common init value */
93 	const struct ao_ctl_init *bank_ctl_init_extra;	/* Extra for each rev */
94 	void (*bank_misc_initfunc)(ao_data_t *, uint32_t);
95 	uint_t bank_status;
96 	uint_t bank_addr;
97 } ao_bank_cfg_t;
98 
99 static void nb_mcamisc_init(ao_data_t *, uint32_t);
100 
101 static const ao_bank_cfg_t ao_bank_cfgs[] = {
102 	{ AMD_MSR_DC_CTL, AMD_MSR_DC_MASK, AMD_DC_CTL_INIT_CMN,
103 	    NULL, NULL, AMD_MSR_DC_STATUS, AMD_MSR_DC_ADDR },
104 	{ AMD_MSR_IC_CTL, AMD_MSR_IC_MASK, AMD_IC_CTL_INIT_CMN,
105 	    NULL, NULL, AMD_MSR_IC_STATUS, AMD_MSR_IC_ADDR },
106 	{ AMD_MSR_BU_CTL, AMD_MSR_BU_MASK, AMD_BU_CTL_INIT_CMN,
107 	    NULL, NULL, AMD_MSR_BU_STATUS, AMD_MSR_BU_ADDR },
108 	{ AMD_MSR_LS_CTL, AMD_MSR_LS_MASK, AMD_LS_CTL_INIT_CMN,
109 	    NULL, NULL, AMD_MSR_LS_STATUS, AMD_MSR_LS_ADDR },
110 	{ AMD_MSR_NB_CTL, AMD_MSR_NB_MASK, AMD_NB_CTL_INIT_CMN,
111 	    &ao_nb_ctl_init[0], nb_mcamisc_init,
112 	    AMD_MSR_NB_STATUS, AMD_MSR_NB_ADDR }
113 };
114 
115 static const ao_error_disp_t ao_disp_unknown = {
116 	FM_EREPORT_CPU_AMD_UNKNOWN,
117 	FM_EREPORT_PAYLOAD_FLAGS_CPU_AMD_UNKNOWN
118 };
119 
120 /*
121  * This is quite awful but necessary to work around x86 system vendor's view of
122  * the world.  Other operating systems (you know who you are) don't understand
123  * Opteron-specific error handling, so BIOS and system vendors often hide these
124  * conditions from them by using SMI polling to copy out any errors from the
125  * machine-check registers.  When Solaris runs on a system with this feature,
126  * we want to disable the SMI polling so we can use FMA instead.  Sadly, there
127  * isn't even a standard self-describing way to express the whole situation,
128  * so we have to resort to hard-coded values.  This should all be changed to
129  * be a self-describing vendor-specific SMBIOS structure in the future.
130  */
131 static const struct ao_smi_disable {
132 	const char *asd_sys_vendor;	/* SMB_TYPE_SYSTEM vendor prefix */
133 	const char *asd_sys_product;	/* SMB_TYPE_SYSTEM product prefix */
134 	const char *asd_bios_vendor;	/* SMB_TYPE_BIOS vendor prefix */
135 	uint8_t asd_code;		/* output code for SMI disable */
136 } ao_smi_disable[] = {
137 	{ "Sun Microsystems", "Galaxy12",
138 	    "American Megatrends", 0x59 },
139 	{ "Sun Microsystems", "Sun Fire X4100 Server",
140 	    "American Megatrends", 0x59 },
141 	{ "Sun Microsystems", "Sun Fire X4200 Server",
142 	    "American Megatrends", 0x59 },
143 	{ NULL, NULL, NULL, 0 }
144 };
145 
146 static int
147 ao_disp_match_r4(uint16_t ref, uint8_t r4)
148 {
149 	static const uint16_t ao_r4_map[] = {
150 		AO_MCA_R4_BIT_GEN,	/* AMD_ERRCODE_R4_GEN */
151 		AO_MCA_R4_BIT_RD,	/* AMD_ERRCODE_R4_RD */
152 		AO_MCA_R4_BIT_WR,	/* AMD_ERRCODE_R4_WR */
153 		AO_MCA_R4_BIT_DRD,	/* AMD_ERRCODE_R4_DRD */
154 		AO_MCA_R4_BIT_DWR,	/* AMD_ERRCODE_R4_DWR */
155 		AO_MCA_R4_BIT_IRD,	/* AMD_ERRCODE_R4_IRD */
156 		AO_MCA_R4_BIT_PREFETCH,	/* AMD_ERRCODE_R4_PREFETCH */
157 		AO_MCA_R4_BIT_EVICT,	/* AMD_ERRCODE_R4_EVICT */
158 		AO_MCA_R4_BIT_SNOOP	/* AMD_ERRCODE_R4_SNOOP */
159 	};
160 
161 	ASSERT(r4 < sizeof (ao_r4_map) / sizeof (uint16_t));
162 
163 	return ((ref & ao_r4_map[r4]) != 0);
164 }
165 
166 static int
167 ao_disp_match_pp(uint8_t ref, uint8_t pp)
168 {
169 	static const uint8_t ao_pp_map[] = {
170 		AO_MCA_PP_BIT_SRC,	/* AMD_ERRCODE_PP_SRC */
171 		AO_MCA_PP_BIT_RSP,	/* AMD_ERRCODE_PP_RSP */
172 		AO_MCA_PP_BIT_OBS,	/* AMD_ERRCODE_PP_OBS */
173 		AO_MCA_PP_BIT_GEN	/* AMD_ERRCODE_PP_GEN */
174 	};
175 
176 	ASSERT(pp < sizeof (ao_pp_map) / sizeof (uint8_t));
177 
178 	return ((ref & ao_pp_map[pp]) != 0);
179 }
180 
181 static int
182 ao_disp_match_ii(uint8_t ref, uint8_t ii)
183 {
184 	static const uint8_t ao_ii_map[] = {
185 		AO_MCA_II_BIT_MEM,	/* AMD_ERRCODE_II_MEM */
186 		0,
187 		AO_MCA_II_BIT_IO,	/* AMD_ERRCODE_II_IO */
188 		AO_MCA_II_BIT_GEN	/* AMD_ERRCODE_II_GEN */
189 	};
190 
191 	ASSERT(ii < sizeof (ao_ii_map) / sizeof (uint8_t));
192 
193 	return ((ref & ao_ii_map[ii]) != 0);
194 }
195 
196 static uint8_t
197 bit_strip(uint16_t *codep, uint16_t mask, uint16_t shift)
198 {
199 	uint8_t val = (*codep & mask) >> shift;
200 	*codep &= ~mask;
201 	return (val);
202 }
203 
204 #define	BIT_STRIP(codep, name) \
205 	bit_strip(codep, AMD_ERRCODE_##name##_MASK, AMD_ERRCODE_##name##_SHIFT)
206 
207 static int
208 ao_disp_match_one(const ao_error_disp_t *aed, uint64_t status, uint32_t rev,
209     int bankno)
210 {
211 	uint16_t code = status & AMD_ERRCODE_MASK;
212 	uint8_t extcode = (status & AMD_ERREXT_MASK) >> AMD_ERREXT_SHIFT;
213 	uint64_t stat_mask = aed->aed_stat_mask;
214 	uint64_t stat_mask_res = aed->aed_stat_mask_res;
215 
216 	/*
217 	 * If the bank's status register indicates overflow, then we can no
218 	 * longer rely on the value of CECC: our experience with actual fault
219 	 * injection has shown that multiple CE's overwriting each other shows
220 	 * AMD_BANK_STAT_CECC and AMD_BANK_STAT_UECC both set to zero.  This
221 	 * should be clarified in a future BKDG or by the Revision Guide.
222 	 * This behaviour is fixed in revision F.
223 	 */
224 	if (bankno == AMD_MCA_BANK_NB &&
225 	    !X86_CHIPREV_ATLEAST(rev, X86_CHIPREV_AMD_F_REV_F) &&
226 	    status & AMD_BANK_STAT_OVER) {
227 		stat_mask &= ~AMD_BANK_STAT_CECC;
228 		stat_mask_res &= ~AMD_BANK_STAT_CECC;
229 	}
230 
231 	if ((status & stat_mask) != stat_mask_res)
232 		return (0);
233 
234 	/*
235 	 * r4 and pp bits are stored separately, so we mask off and compare them
236 	 * for the code types that use them.  Once we've taken the r4 and pp
237 	 * bits out of the equation, we can directly compare the resulting code
238 	 * with the one stored in the ao_error_disp_t.
239 	 */
240 	if (AMD_ERRCODE_ISMEM(code)) {
241 		uint8_t r4 = BIT_STRIP(&code, R4);
242 
243 		if (!ao_disp_match_r4(aed->aed_stat_r4_bits, r4))
244 			return (0);
245 
246 	} else if (AMD_ERRCODE_ISBUS(code)) {
247 		uint8_t r4 = BIT_STRIP(&code, R4);
248 		uint8_t pp = BIT_STRIP(&code, PP);
249 		uint8_t ii = BIT_STRIP(&code, II);
250 
251 		if (!ao_disp_match_r4(aed->aed_stat_r4_bits, r4) ||
252 		    !ao_disp_match_pp(aed->aed_stat_pp_bits, pp) ||
253 		    !ao_disp_match_ii(aed->aed_stat_ii_bits, ii))
254 			return (0);
255 	}
256 
257 	return (code == aed->aed_stat_code && extcode == aed->aed_stat_extcode);
258 }
259 
260 static const ao_error_disp_t *
261 ao_disp_match(uint_t bankno, uint64_t status, uint32_t rev)
262 {
263 	const ao_error_disp_t *aed;
264 
265 	for (aed = ao_error_disp[bankno]; aed->aed_stat_mask != 0; aed++) {
266 		if (ao_disp_match_one(aed, status, rev, bankno))
267 			return (aed);
268 	}
269 
270 	return (&ao_disp_unknown);
271 }
272 
273 void
274 ao_pcicfg_write(uint_t chipid, uint_t func, uint_t reg, uint32_t val)
275 {
276 	ASSERT(chipid + 24 <= 31);
277 	ASSERT((func & 7) == func);
278 	ASSERT((reg & 3) == 0 && reg < 256);
279 
280 	pci_mech1_putl(0, chipid + 24, func, reg, val);
281 }
282 
283 uint32_t
284 ao_pcicfg_read(uint_t chipid, uint_t func, uint_t reg)
285 {
286 	ASSERT(chipid + 24 <= 31);
287 	ASSERT((func & 7) == func);
288 	ASSERT((reg & 3) == 0 && reg < 256);
289 
290 	return (pci_mech1_getl(0, chipid + 24, func, reg));
291 }
292 
293 /*
294  * ao_chip_once returns 1 if the caller should perform the operation for
295  * this chip, or 0 if some other core has already performed the operation.
296  */
297 
298 int
299 ao_chip_once(ao_data_t *ao, enum ao_cfgonce_bitnum what)
300 {
301 	return (atomic_set_long_excl(&ao->ao_shared->aos_cfgonce, what) == 0 ?
302 	    1 : 0);
303 }
304 
305 /*
306  * Setup individual bank detectors after stashing their bios settings.
307  * The 'donb' argument indicates whether this core should configured
308  * the shared NorthBridhe MSRs.
309  */
310 static void
311 ao_bank_cfg(ao_data_t *ao, uint32_t rev, int donb)
312 {
313 	ao_mca_t *mca = &ao->ao_mca;
314 	struct ao_chipshared *aos = ao->ao_shared;
315 	ao_bios_cfg_t *bcfg = &mca->ao_mca_bios_cfg;
316 	const ao_bank_cfg_t *bankcfg = ao_bank_cfgs;
317 	const struct ao_ctl_init *extrap;
318 	uint64_t mcictl;
319 	int i;
320 
321 	for (i = 0; i < AMD_MCA_BANK_COUNT; i++, bankcfg++) {
322 		if (i == AMD_MCA_BANK_NB && donb == 0) {
323 			bcfg->bcfg_bank_ctl[i] = 0xbaddcafe;
324 			bcfg->bcfg_bank_mask[i] = 0xbaddcafe;
325 			continue;
326 		} else  if (i == AMD_MCA_BANK_NB) {
327 			aos->aos_bcfg_nb_ctl = rdmsr(bankcfg->bank_ctl);
328 			aos->aos_bcfg_nb_mask = rdmsr(bankcfg->bank_ctl_mask);
329 		} else {
330 			bcfg->bcfg_bank_ctl[i] = rdmsr(bankcfg->bank_ctl);
331 			bcfg->bcfg_bank_mask[i] = rdmsr(bankcfg->bank_ctl_mask);
332 		}
333 
334 		/* Initialize MCi_CTL register for this bank */
335 		mcictl = bankcfg->bank_ctl_init_cmn;
336 		if ((extrap = bankcfg->bank_ctl_init_extra) != NULL) {
337 			while (extrap->ctl_revmask != X86_CHIPREV_UNKNOWN) {
338 				if (X86_CHIPREV_MATCH(rev, extrap->ctl_revmask))
339 					mcictl |= extrap->ctl_bits;
340 				extrap++;
341 			}
342 		}
343 		wrmsr(bankcfg->bank_ctl, mcictl);
344 
345 		/* Initialize the MCi_MISC register for this bank */
346 		if (bankcfg->bank_misc_initfunc != NULL)
347 			(bankcfg->bank_misc_initfunc)(ao, rev);
348 	}
349 }
350 
351 /*
352  * This knob exists in case any platform has a problem with our default
353  * policy of disabling any interrupt registered in the NB MC4_MISC
354  * register.  Setting this may cause Solaris and external entities
355  * who also have an interest in this register to argue over available
356  * telemetry (so setting it is generally not recommended).
357  */
358 int ao_nb_cfg_mc4misc_noseize = 0;
359 
360 /*
361  * The BIOS may have setup to receive SMI on counter overflow.  It may also
362  * have locked various fields or made them read-only.  We will clear any
363  * SMI request and leave the register locked.  We will also clear the
364  * counter and enable counting - while we don't use the counter it is nice
365  * to have it enabled for verification and debug work.
366  */
367 static void
368 nb_mcamisc_init(ao_data_t *ao, uint32_t rev)
369 {
370 	uint64_t hwcr, oldhwcr;
371 	uint64_t val;
372 	int locked;
373 
374 	if (!X86_CHIPREV_MATCH(rev, AO_REVS_FG))
375 		return;
376 
377 	ao->ao_shared->aos_bcfg_nb_misc = val = rdmsr(AMD_MSR_NB_MISC);
378 
379 	if (ao_nb_cfg_mc4misc_noseize)
380 		return;		/* stash BIOS value, but no changes */
381 
382 	locked = val & AMD_NB_MISC_LOCKED;
383 
384 	/*
385 	 * The Valid bit tells us whether the CtrP bit is defined; if it
386 	 * is the CtrP bit tells us whether an ErrCount field is present.
387 	 * If not then there is nothing for us to do.
388 	 */
389 	if (!(val & AMD_NB_MISC_VALID) || !(val & AMD_NB_MISC_CTRP))
390 		return;
391 
392 	if (locked) {
393 		oldhwcr = rdmsr(MSR_AMD_HWCR);
394 		hwcr = oldhwcr | AMD_HWCR_MCI_STATUS_WREN;
395 		wrmsr(MSR_AMD_HWCR, hwcr);
396 	}
397 
398 	val |= AMD_NB_MISC_CNTEN;		/* enable ECC error counting */
399 	val &= ~AMD_NB_MISC_ERRCOUNT_MASK;	/* clear ErrCount */
400 	val &= ~AMD_NB_MISC_OVRFLW;		/* clear Ovrflw */
401 	val &= ~AMD_NB_MISC_INTTYPE_MASK;	/* no interrupt on overflow */
402 	val |= AMD_NB_MISC_LOCKED;
403 
404 	wrmsr(AMD_MSR_NB_MISC, val);
405 
406 	if (locked)
407 		wrmsr(MSR_AMD_HWCR, oldhwcr);
408 }
409 
410 /*
411  * NorthBridge (NB) MCA Configuration.
412  *
413  * We add and remove bits from the BIOS-configured value, rather than
414  * writing an absolute value.  The variables ao_nb_cfg_{add,remove}_cmn and
415  * ap_nb_cfg_{add,remove}_revFG are available for modification via kmdb
416  * and /etc/system.  The revision-specific adds and removes are applied
417  * after the common changes, and one write is made to the config register.
418  * These are not intended for watchdog configuration via these variables -
419  * use the watchdog policy below.
420  */
421 
422 /*
423  * Bits to be added to the NB configuration register - all revs.
424  */
425 uint32_t ao_nb_cfg_add_cmn = AMD_NB_CFG_ADD_CMN;
426 
427 /*
428  * Bits to be cleared from the NB configuration register - all revs.
429  */
430 uint32_t ao_nb_cfg_remove_cmn = AMD_NB_CFG_REMOVE_CMN;
431 
432 /*
433  * Bits to be added to the NB configuration register - revs F and G.
434  */
435 uint32_t ao_nb_cfg_add_revFG = AMD_NB_CFG_ADD_REV_FG;
436 
437 /*
438  * Bits to be cleared from the NB configuration register - revs F and G.
439  */
440 uint32_t ao_nb_cfg_remove_revFG = AMD_NB_CFG_REMOVE_REV_FG;
441 
442 struct ao_nb_cfg {
443 	uint32_t cfg_revmask;
444 	uint32_t *cfg_add_p;
445 	uint32_t *cfg_remove_p;
446 };
447 
448 static const struct ao_nb_cfg ao_cfg_extra[] = {
449 	{ AO_REVS_FG, &ao_nb_cfg_add_revFG, &ao_nb_cfg_remove_revFG },
450 	{ X86_CHIPREV_UNKNOWN, NULL, NULL }
451 };
452 
453 /*
454  * Bits to be used if we configure the NorthBridge (NB) Watchdog.  The watchdog
455  * triggers a machine check exception when no response to an NB system access
456  * occurs within a specified time interval.
457  */
458 uint32_t ao_nb_cfg_wdog =
459     AMD_NB_CFG_WDOGTMRCNTSEL_4095 |
460     AMD_NB_CFG_WDOGTMRBASESEL_1MS;
461 
462 /*
463  * The default watchdog policy is to enable it (at the above rate) if it
464  * is disabled;  if it is enabled then we leave it enabled at the rate
465  * chosen by the BIOS.
466  */
467 enum {
468 	AO_NB_WDOG_LEAVEALONE,		/* Don't touch watchdog config */
469 	AO_NB_WDOG_DISABLE,		/* Always disable watchdog */
470 	AO_NB_WDOG_ENABLE_IF_DISABLED,	/* If disabled, enable at our rate */
471 	AO_NB_WDOG_ENABLE_FORCE_RATE	/* Enable and set our rate */
472 } ao_nb_watchdog_policy = AO_NB_WDOG_ENABLE_IF_DISABLED;
473 
474 static void
475 ao_nb_cfg(ao_data_t *ao, uint32_t rev)
476 {
477 	const struct ao_nb_cfg *nbcp = &ao_cfg_extra[0];
478 	uint_t chipid = pg_plat_hw_instance_id(CPU, PGHW_CHIP);
479 	uint32_t val;
480 
481 	/*
482 	 * Read the NorthBridge (NB) configuration register in PCI space,
483 	 * modify the settings accordingly, and store the new value back.
484 	 */
485 	ao->ao_shared->aos_bcfg_nb_cfg = val =
486 	    ao_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_NBCFG);
487 
488 	switch (ao_nb_watchdog_policy) {
489 	case AO_NB_WDOG_LEAVEALONE:
490 		break;
491 
492 	case AO_NB_WDOG_DISABLE:
493 		val &= ~AMD_NB_CFG_WDOGTMRBASESEL_MASK;
494 		val &= ~AMD_NB_CFG_WDOGTMRCNTSEL_MASK;
495 		val |= AMD_NB_CFG_WDOGTMRDIS;
496 		break;
497 
498 	default:
499 		cmn_err(CE_NOTE, "ao_nb_watchdog_policy=%d unrecognised, "
500 		    "using default policy", ao_nb_watchdog_policy);
501 		/*FALLTHRU*/
502 
503 	case AO_NB_WDOG_ENABLE_IF_DISABLED:
504 		if (val & AMD_NB_CFG_WDOGTMRDIS)
505 			break;	/* if enabled leave rate intact */
506 		/*FALLTHRU*/
507 
508 	case AO_NB_WDOG_ENABLE_FORCE_RATE:
509 		val &= ~AMD_NB_CFG_WDOGTMRBASESEL_MASK;
510 		val &= ~AMD_NB_CFG_WDOGTMRCNTSEL_MASK;
511 		val &= ~AMD_NB_CFG_WDOGTMRDIS;
512 		val |= ao_nb_cfg_wdog;
513 		break;
514 	}
515 
516 	/*
517 	 * Now apply bit adds and removes, first those common to all revs
518 	 * and then the revision-specific ones.
519 	 */
520 	val &= ~ao_nb_cfg_remove_cmn;
521 	val |= ao_nb_cfg_add_cmn;
522 
523 	while (nbcp->cfg_revmask != X86_CHIPREV_UNKNOWN) {
524 		if (X86_CHIPREV_MATCH(rev, nbcp->cfg_revmask)) {
525 			val &= ~(*nbcp->cfg_remove_p);
526 			val |= *nbcp->cfg_add_p;
527 		}
528 		nbcp++;
529 	}
530 
531 	ao_pcicfg_write(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_NBCFG, val);
532 }
533 
534 static void
535 ao_dram_cfg(ao_data_t *ao, uint32_t rev)
536 {
537 	uint_t chipid = pg_plat_hw_instance_id(CPU, PGHW_CHIP);
538 	union mcreg_dramcfg_lo dcfglo;
539 
540 	ao->ao_shared->aos_bcfg_dcfg_lo = MCREG_VAL32(&dcfglo) =
541 	    ao_pcicfg_read(chipid, MC_FUNC_DRAMCTL, MC_DC_REG_DRAMCFGLO);
542 	ao->ao_shared->aos_bcfg_dcfg_hi =
543 	    ao_pcicfg_read(chipid, MC_FUNC_DRAMCTL, MC_DC_REG_DRAMCFGHI);
544 
545 #ifdef OPTERON_ERRATUM_172
546 	if (X86_CHIPREV_MATCH(rev, AO_REVS_FG) &&
547 	    MCREG_FIELD_revFG(&dcfglo, ParEn)) {
548 		MCREG_FIELD_revFG(&dcfglo, ParEn) = 0;
549 		ao_pcicfg_write(chipid, MC_FUNC_DRAMCTL, MC_DC_REG_DRAMCFGLO,
550 		    MCREG_VAL32(&dcfglo));
551 	}
552 #endif
553 }
554 
555 /*
556  * This knob exists in case any platform has a problem with our default
557  * policy of disabling any interrupt registered in the online spare
558  * control register.  Setting this may cause Solaris and external entities
559  * who also have an interest in this register to argue over available
560  * telemetry (so setting it is generally not recommended).
561  */
562 int ao_nb_cfg_sparectl_noseize = 0;
563 
564 /*
565  * Setup the online spare control register (revs F and G).  We disable
566  * any interrupt registered by the BIOS and zero all error counts.
567  */
568 static void
569 ao_sparectl_cfg(ao_data_t *ao)
570 {
571 	uint_t chipid = pg_plat_hw_instance_id(CPU, PGHW_CHIP);
572 	union mcreg_sparectl sparectl;
573 	int chan, cs;
574 
575 	ao->ao_shared->aos_bcfg_nb_sparectl = MCREG_VAL32(&sparectl) =
576 	    ao_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL);
577 
578 	if (ao_nb_cfg_sparectl_noseize)
579 		return;	/* stash BIOS value, but no changes */
580 
581 	/*
582 	 * If the BIOS has requested SMI interrupt type for ECC count
583 	 * overflow for a chip-select or channel force those off.
584 	 */
585 	MCREG_FIELD_revFG(&sparectl, EccErrInt) = 0;
586 	MCREG_FIELD_revFG(&sparectl, SwapDoneInt) = 0;
587 
588 	/* Enable writing to the EccErrCnt field */
589 	MCREG_FIELD_revFG(&sparectl, EccErrCntWrEn) = 1;
590 
591 	/* First write, preparing for writes to EccErrCnt */
592 	ao_pcicfg_write(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL,
593 	    MCREG_VAL32(&sparectl));
594 
595 	/*
596 	 * Zero EccErrCnt and write this back to all chan/cs combinations.
597 	 */
598 	MCREG_FIELD_revFG(&sparectl, EccErrCnt) = 0;
599 	for (chan = 0; chan < MC_CHIP_NDRAMCHAN; chan++) {
600 		MCREG_FIELD_revFG(&sparectl, EccErrCntDramChan) = chan;
601 
602 		for (cs = 0; cs < MC_CHIP_NCS; cs++) {
603 			MCREG_FIELD_revFG(&sparectl, EccErrCntDramCs) = cs;
604 			ao_pcicfg_write(chipid, MC_FUNC_MISCCTL,
605 			    MC_CTL_REG_SPARECTL, MCREG_VAL32(&sparectl));
606 		}
607 	}
608 }
609 
610 /*
611  * Capture the machine-check exception state into our per-CPU logout area, and
612  * dispatch a copy of the logout area to our error queue for ereport creation.
613  * If 'rp' is non-NULL, we're being called from trap context; otherwise we're
614  * being polled or poked by the injector.  We return the number of errors
615  * found through 'np', and a boolean indicating whether the error is fatal.
616  * The caller is expected to call fm_panic() if we return fatal (non-zero).
617  */
618 int
619 ao_mca_logout(ao_cpu_logout_t *acl, struct regs *rp, int *np, int skipnb,
620     uint32_t rev)
621 {
622 	uint64_t mcg_status = rdmsr(IA32_MSR_MCG_STATUS);
623 	int i, fatal = 0, n = 0;
624 
625 	acl->acl_timestamp = gethrtime_waitfree();
626 	acl->acl_mcg_status = mcg_status;
627 	acl->acl_ip = rp ? rp->r_pc : 0;
628 	acl->acl_flags = 0;
629 
630 	/*
631 	 * Iterate over the banks of machine-check registers, read the address
632 	 * and status registers into the logout area, and clear status as we go.
633 	 * Also read the MCi_MISC register if MCi_STATUS.MISCV indicates that
634 	 * there is valid info there (as it will in revisions F and G for
635 	 * NorthBridge ECC errors).
636 	 */
637 	for (i = 0; i < AMD_MCA_BANK_COUNT; i++) {
638 		ao_bank_logout_t *abl = &acl->acl_banks[i];
639 
640 		if (i == AMD_MCA_BANK_NB && skipnb) {
641 			abl->abl_status = 0;
642 			continue;
643 		}
644 
645 		abl->abl_addr = rdmsr(ao_bank_regs[i].abr_addr);
646 		abl->abl_status = rdmsr(ao_bank_regs[i].abr_status);
647 
648 		if (abl->abl_status & AMD_BANK_STAT_MISCV)
649 			abl->abl_misc = rdmsr(ao_bank_regs[i].abr_misc);
650 		else
651 			abl->abl_misc = 0;
652 
653 		if (abl->abl_status & AMD_BANK_STAT_VALID)
654 			wrmsr(ao_bank_regs[i].abr_status, 0);
655 	}
656 
657 	if (rp == NULL || !USERMODE(rp->r_cs))
658 		acl->acl_flags |= AO_ACL_F_PRIV;
659 
660 	if (ao_mca_stack_flag)
661 		acl->acl_stackdepth = getpcstack(acl->acl_stack, FM_STK_DEPTH);
662 	else
663 		acl->acl_stackdepth = 0;
664 
665 	/*
666 	 * Clear MCG_STATUS, indicating that machine-check trap processing is
667 	 * complete.  Once we do this, another machine-check trap can occur
668 	 * (if another occurs up to this point then the system will reset).
669 	 */
670 	if (mcg_status & MCG_STATUS_MCIP)
671 		wrmsr(IA32_MSR_MCG_STATUS, 0);
672 
673 	/*
674 	 * If we took a machine-check trap, then the error is fatal if the
675 	 * return instruction pointer is not valid in the global register.
676 	 */
677 	if (rp != NULL && !(acl->acl_mcg_status & MCG_STATUS_RIPV))
678 		fatal++;
679 
680 	/*
681 	 * Now iterate over the saved logout area, determining whether the
682 	 * error that we saw is fatal or not based upon our dispositions
683 	 * and the hardware's indicators of whether or not we can resume.
684 	 */
685 	for (i = 0; i < AMD_MCA_BANK_COUNT; i++) {
686 		ao_bank_logout_t *abl = &acl->acl_banks[i];
687 		const ao_error_disp_t *aed;
688 		uint8_t when;
689 
690 		if (!(abl->abl_status & AMD_BANK_STAT_VALID))
691 			continue;
692 
693 		aed = ao_disp_match(i, abl->abl_status, rev);
694 		if ((when = aed->aed_panic_when) != AO_AED_PANIC_NEVER) {
695 			if ((when & AO_AED_PANIC_ALWAYS) ||
696 			    ((when & AO_AED_PANIC_IFMCE) && rp != NULL)) {
697 					fatal++;
698 			}
699 		}
700 
701 		/*
702 		 * If we are taking a machine-check exception and our context
703 		 * is corrupt, then we must die.
704 		 */
705 		if (rp != NULL && abl->abl_status & AMD_BANK_STAT_PCC)
706 			fatal++;
707 
708 		/*
709 		 * The overflow bit is set if the bank detects an error but
710 		 * the valid bit of its status register is already set
711 		 * (software has not yet read and cleared it).  Enabled
712 		 * (for mc# reporting) errors overwrite disabled errors,
713 		 * uncorrectable errors overwrite correctable errors,
714 		 * uncorrectable errors are not overwritten.
715 		 *
716 		 * For the NB detector bank the overflow bit will not be
717 		 * set for repeated correctable errors on revisions D and
718 		 * earlier; it will be set on revisions E and later.
719 		 * On revision E, however, the CorrECC bit does appear
720 		 * to clear in these circumstances.  Since we can enable
721 		 * machine-check exception on NB correctables we need to
722 		 * be careful here; we never enable mc# for correctable from
723 		 * other banks.
724 		 *
725 		 * Our solution will be to declare a machine-check exception
726 		 * fatal if the overflow bit is set except in the case of
727 		 * revision F on the NB detector bank for which CorrECC
728 		 * is indicated.  Machine-check exception for NB correctables
729 		 * on rev E is explicitly not supported.
730 		 */
731 		if (rp != NULL && abl->abl_status & AMD_BANK_STAT_OVER &&
732 		    !(i == AMD_MCA_BANK_NB &&
733 		    X86_CHIPREV_ATLEAST(rev, X86_CHIPREV_AMD_F_REV_F) &&
734 		    abl->abl_status & AMD_BANK_STAT_CECC))
735 			fatal++;
736 
737 		/*
738 		 * If we are taking a machine-check exception and we don't
739 		 * recognize the error case at all, then assume it's fatal.
740 		 * This will need to change if we eventually use the Opteron
741 		 * Rev E exception mechanism for detecting correctable errors.
742 		 */
743 		if (rp != NULL && aed == &ao_disp_unknown)
744 			fatal++;
745 
746 		abl->abl_addr_type = aed->aed_flags & AO_AED_FLAGS_ADDRTYPE;
747 		abl->abl_addr_valid_hi = aed->aed_addrvalid_hi;
748 		abl->abl_addr_valid_lo = aed->aed_addrvalid_lo;
749 		n++;
750 	}
751 
752 	if (n > 0) {
753 		errorq_dispatch(ao_mca_queue, acl, sizeof (ao_cpu_logout_t),
754 		    fatal && cmi_panic_on_uncorrectable_error ?
755 		    ERRORQ_SYNC : ERRORQ_ASYNC);
756 	}
757 
758 	if (np != NULL)
759 		*np = n; /* return number of errors found to caller */
760 
761 	return (fatal != 0);
762 }
763 
764 static uint_t
765 ao_ereport_synd(ao_data_t *ao, const ao_bank_logout_t *abl, uint_t *typep,
766     int is_nb)
767 {
768 	if (is_nb) {
769 		if (ao->ao_shared->aos_bcfg_nb_cfg & AMD_NB_CFG_CHIPKILLECCEN) {
770 			*typep = AMD_SYNDTYPE_CHIPKILL;
771 			return (AMD_NB_STAT_CKSYND(abl->abl_status));
772 		} else {
773 			*typep = AMD_SYNDTYPE_ECC;
774 			return (AMD_BANK_SYND(abl->abl_status));
775 		}
776 	} else {
777 		*typep = AMD_SYNDTYPE_ECC;
778 		return (AMD_BANK_SYND(abl->abl_status));
779 	}
780 }
781 
782 static void
783 ao_ereport_create_resource_elem(nvlist_t **nvlp, nv_alloc_t *nva,
784     mc_unum_t *unump, int dimmnum)
785 {
786 	nvlist_t *snvl;
787 	*nvlp = fm_nvlist_create(nva);		/* freed by caller */
788 
789 	snvl = fm_nvlist_create(nva);
790 
791 	(void) nvlist_add_uint64(snvl, FM_FMRI_HC_SPECIFIC_OFFSET,
792 	    unump->unum_offset);
793 
794 	fm_fmri_hc_set(*nvlp, FM_HC_SCHEME_VERSION, NULL, snvl, 5,
795 	    "motherboard", unump->unum_board,
796 	    "chip", unump->unum_chip,
797 	    "memory-controller", unump->unum_mc,
798 	    "dimm", unump->unum_dimms[dimmnum],
799 	    "rank", unump->unum_rank);
800 
801 	fm_nvlist_destroy(snvl, nva ? FM_NVA_RETAIN : FM_NVA_FREE);
802 }
803 
804 static void
805 ao_ereport_add_resource(nvlist_t *payload, nv_alloc_t *nva, mc_unum_t *unump)
806 {
807 
808 	nvlist_t *elems[MC_UNUM_NDIMM];
809 	int nelems = 0;
810 	int i;
811 
812 	for (i = 0; i < MC_UNUM_NDIMM; i++) {
813 		if (unump->unum_dimms[i] == MC_INVALNUM)
814 			break;
815 		ao_ereport_create_resource_elem(&elems[nelems++], nva,
816 		    unump, i);
817 	}
818 
819 	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RESOURCE,
820 	    DATA_TYPE_NVLIST_ARRAY, nelems, elems, NULL);
821 
822 	for (i = 0; i < nelems; i++)
823 		fm_nvlist_destroy(elems[i], nva ? FM_NVA_RETAIN : FM_NVA_FREE);
824 }
825 
826 static void
827 ao_ereport_add_logout(ao_data_t *ao, nvlist_t *payload, nv_alloc_t *nva,
828     const ao_cpu_logout_t *acl, uint_t bankno, const ao_error_disp_t *aed)
829 {
830 	uint64_t members = aed->aed_ereport_members;
831 	const ao_bank_logout_t *abl = &acl->acl_banks[bankno];
832 	uint_t synd, syndtype;
833 
834 	synd = ao_ereport_synd(ao, abl, &syndtype, bankno == AMD_MCA_BANK_NB);
835 
836 	if (members & FM_EREPORT_PAYLOAD_FLAG_BANK_STAT) {
837 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK_STAT,
838 		    DATA_TYPE_UINT64, abl->abl_status, NULL);
839 	}
840 
841 	if (members & FM_EREPORT_PAYLOAD_FLAG_BANK_NUM) {
842 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK_NUM,
843 		    DATA_TYPE_UINT8, bankno, NULL);
844 	}
845 
846 	if (members & FM_EREPORT_PAYLOAD_FLAG_ADDR) {
847 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ADDR,
848 		    DATA_TYPE_UINT64, abl->abl_addr, NULL);
849 	}
850 
851 	if (members & FM_EREPORT_PAYLOAD_FLAG_ADDR_VALID) {
852 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ADDR_VALID,
853 		    DATA_TYPE_BOOLEAN_VALUE, (abl->abl_status &
854 		    AMD_BANK_STAT_ADDRV) ? B_TRUE : B_FALSE, NULL);
855 	}
856 
857 	if (members & FM_EREPORT_PAYLOAD_FLAG_BANK_MISC) {
858 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK_MISC,
859 		    DATA_TYPE_UINT64, abl->abl_misc, NULL);
860 	}
861 
862 	if (members & FM_EREPORT_PAYLOAD_FLAG_SYND) {
863 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SYND,
864 		    DATA_TYPE_UINT16, synd, NULL);
865 	}
866 
867 	if (members & FM_EREPORT_PAYLOAD_FLAG_SYND_TYPE) {
868 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SYND_TYPE,
869 		    DATA_TYPE_STRING, (syndtype == AMD_SYNDTYPE_CHIPKILL ?
870 		    "C" : "E"), NULL);
871 	}
872 
873 	if (members & FM_EREPORT_PAYLOAD_FLAG_IP) {
874 		uint64_t ip = (acl->acl_mcg_status & MCG_STATUS_EIPV) ?
875 		    acl->acl_ip : 0;
876 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_IP,
877 		    DATA_TYPE_UINT64, ip, NULL);
878 	}
879 
880 	if (members & FM_EREPORT_PAYLOAD_FLAG_PRIV) {
881 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PRIV,
882 		    DATA_TYPE_BOOLEAN_VALUE, (acl->acl_flags & AO_ACL_F_PRIV) ?
883 		    B_TRUE : B_FALSE, NULL);
884 	}
885 
886 	if (members & FM_EREPORT_PAYLOAD_FLAG_RESOURCE) {
887 		mc_unum_t unum;
888 		int addrvalid = 0;
889 
890 		if (abl->abl_addr_type & AO_AED_F_PHYSICAL) {
891 			addrvalid = (members & FM_EREPORT_PAYLOAD_FLAG_ADDR) &&
892 			    (members & FM_EREPORT_PAYLOAD_FLAG_ADDR_VALID) &&
893 			    (abl->abl_status & AMD_BANK_STAT_ADDRV);
894 		}
895 
896 		if (addrvalid && ao_mc_patounum(ao, abl->abl_addr,
897 		    abl->abl_addr_valid_hi, abl->abl_addr_valid_lo,
898 		    synd, syndtype, &unum))
899 			ao_ereport_add_resource(payload, nva, &unum);
900 	}
901 
902 	if (ao_mca_stack_flag && members & FM_EREPORT_PAYLOAD_FLAG_STACK) {
903 		fm_payload_stack_add(payload, acl->acl_stack,
904 		    acl->acl_stackdepth);
905 	}
906 }
907 
908 static void
909 ao_ereport_post(const ao_cpu_logout_t *acl,
910     int bankno, const ao_error_disp_t *aed)
911 {
912 	ao_data_t *ao = acl->acl_ao;
913 	errorq_elem_t *eqep, *scr_eqep;
914 	nvlist_t *ereport, *detector;
915 	nv_alloc_t *nva = NULL;
916 	char buf[FM_MAX_CLASS];
917 
918 	if (panicstr) {
919 		if ((eqep = errorq_reserve(ereport_errorq)) == NULL)
920 			return;
921 		ereport = errorq_elem_nvl(ereport_errorq, eqep);
922 
923 		/*
924 		 * Now try to allocate another element for scratch space and
925 		 * use that for further scratch space (eg for constructing
926 		 * nvlists to add the main ereport).  If we can't reserve
927 		 * a scratch element just fallback to working within the
928 		 * element we already have, and hope for the best.  All this
929 		 * is necessary because the fixed buffer nv allocator does
930 		 * not reclaim freed space and nvlist construction is
931 		 * expensive.
932 		 */
933 		if ((scr_eqep = errorq_reserve(ereport_errorq)) != NULL)
934 			nva = errorq_elem_nva(ereport_errorq, scr_eqep);
935 		else
936 			nva = errorq_elem_nva(ereport_errorq, eqep);
937 	} else {
938 		ereport = fm_nvlist_create(NULL);
939 	}
940 
941 	/*
942 	 * Create the "hc" scheme detector FMRI identifying this cpu
943 	 */
944 	detector = ao_fmri_create(ao, nva);
945 
946 	/*
947 	 * Encode all the common data into the ereport.
948 	 */
949 	(void) snprintf(buf, FM_MAX_CLASS, "%s.%s.%s",
950 	    FM_ERROR_CPU, "amd", aed->aed_class);
951 
952 	fm_ereport_set(ereport, FM_EREPORT_VERSION, buf,
953 	    fm_ena_generate_cpu(acl->acl_timestamp, ao->ao_cpu->cpu_id,
954 	    FM_ENA_FMT1), detector, NULL);
955 
956 	/*
957 	 * We're done with 'detector' so reclaim the scratch space.
958 	 */
959 	if (panicstr) {
960 		fm_nvlist_destroy(detector, FM_NVA_RETAIN);
961 		nv_alloc_reset(nva);
962 	} else {
963 		fm_nvlist_destroy(detector, FM_NVA_FREE);
964 	}
965 
966 	/*
967 	 * Encode the error-specific data that was saved in the logout area.
968 	 */
969 	ao_ereport_add_logout(ao, ereport, nva, acl, bankno, aed);
970 
971 	if (panicstr) {
972 		errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
973 		if (scr_eqep)
974 			errorq_cancel(ereport_errorq, scr_eqep);
975 	} else {
976 		(void) fm_ereport_post(ereport, EVCH_TRYHARD);
977 		fm_nvlist_destroy(ereport, FM_NVA_FREE);
978 	}
979 }
980 
981 /*ARGSUSED*/
982 void
983 ao_mca_drain(void *ignored, const void *data, const errorq_elem_t *eqe)
984 {
985 	const ao_cpu_logout_t *acl = data;
986 	uint32_t rev = acl->acl_ao->ao_shared->aos_chiprev;
987 	int i;
988 
989 	for (i = 0; i < AMD_MCA_BANK_COUNT; i++) {
990 		const ao_bank_logout_t *abl = &acl->acl_banks[i];
991 		const ao_error_disp_t *aed;
992 
993 		if (abl->abl_status & AMD_BANK_STAT_VALID) {
994 			aed = ao_disp_match(i, abl->abl_status, rev);
995 			ao_ereport_post(acl, i, aed);
996 		}
997 	}
998 }
999 
1000 /*
1001  * Machine check interrupt handler - we jump here from mcetrap.
1002  *
1003  * A sibling core may attempt to poll the NorthBridge during the
1004  * time we are performing the logout.  So we coordinate NB access
1005  * of all cores of the same chip via a per-chip lock.  If the lock
1006  * is held on a sibling core then we spin for it here; if the
1007  * lock is held by the thread we have interrupted then we do
1008  * not acquire the lock but can proceed safe in the knowledge that
1009  * the lock owner can't actually perform any NB accesses.  This
1010  * requires that threads that take the aos_nb_poll_lock do not
1011  * block and that they disable preemption while they hold the lock.
1012  * It also requires that the lock be adaptive since mutex_owner does
1013  * not work for spin locks.
1014  */
1015 static int ao_mca_path1, ao_mca_path2;
1016 int
1017 ao_mca_trap(void *data, struct regs *rp)
1018 {
1019 	ao_data_t *ao = data;
1020 	ao_mca_t *mca = &ao->ao_mca;
1021 	ao_cpu_logout_t *acl = &mca->ao_mca_logout[AO_MCA_LOGOUT_EXCEPTION];
1022 	kmutex_t *nblock = NULL;
1023 	int tooklock = 0;
1024 	int rv;
1025 
1026 	if (ao->ao_shared != NULL)
1027 		nblock = &ao->ao_shared->aos_nb_poll_lock;
1028 
1029 	if (nblock && !mutex_owned(nblock)) {
1030 		/*
1031 		 * The mutex is not owned by the thread we have interrupted
1032 		 * (since the holder may not block or be preempted once the
1033 		 * lock is acquired).  We will spin for this adaptive lock.
1034 		 */
1035 		++ao_mca_path1;
1036 		while (!mutex_tryenter(nblock)) {
1037 			while (mutex_owner(nblock) != NULL)
1038 				;
1039 		}
1040 		tooklock = 1;
1041 	} else {
1042 		++ao_mca_path2;
1043 	}
1044 
1045 	rv = ao_mca_logout(acl, rp, NULL, 0, ao->ao_shared->aos_chiprev);
1046 
1047 	if (tooklock)
1048 		mutex_exit(&ao->ao_shared->aos_nb_poll_lock);
1049 
1050 	return (rv);
1051 }
1052 
1053 /*ARGSUSED*/
1054 int
1055 ao_mca_inject(void *data, cmi_mca_regs_t *regs, uint_t nregs)
1056 {
1057 	uint64_t hwcr, oldhwcr;
1058 	int i;
1059 
1060 	oldhwcr = rdmsr(MSR_AMD_HWCR);
1061 	hwcr = oldhwcr | AMD_HWCR_MCI_STATUS_WREN;
1062 	wrmsr(MSR_AMD_HWCR, hwcr);
1063 
1064 	for (i = 0; i < nregs; i++)
1065 		wrmsr(regs[i].cmr_msrnum, regs[i].cmr_msrval);
1066 
1067 	wrmsr(MSR_AMD_HWCR, oldhwcr);
1068 	return (0);
1069 }
1070 
1071 void
1072 ao_mca_init(void *data)
1073 {
1074 	ao_data_t *ao = data;
1075 	ao_mca_t *mca = &ao->ao_mca;
1076 	uint64_t cap = rdmsr(IA32_MSR_MCG_CAP);
1077 	uint32_t rev;
1078 	int donb, dodcfg;
1079 	int i;
1080 
1081 	/*
1082 	 * cmi_mca_init is only called during cpu startup if features include
1083 	 * X86_MCA (defined as both MCA and MCE support indicated by CPUID).
1084 	 * Furthermore, our ao_init function returns ENOTSUP if features
1085 	 * lacked X86_MCA, IA32_MSR_MCG_CAP lacks MCG_CAP_CTL_P, or the
1086 	 * cpu has an unexpected number of detector banks.
1087 	 */
1088 	ASSERT(x86_feature & X86_MCA);
1089 	ASSERT(cap & MCG_CAP_CTL_P);
1090 	ASSERT((cap & MCG_CAP_COUNT_MASK) == AMD_MCA_BANK_COUNT);
1091 
1092 	/*
1093 	 * Configure the logout areas.  We preset every logout area's acl_ao
1094 	 * pointer to refer back to our per-CPU state for errorq drain usage.
1095 	 */
1096 	for (i = 0; i < AO_MCA_LOGOUT_NUM; i++)
1097 		mca->ao_mca_logout[i].acl_ao = ao;
1098 
1099 	/* LINTED: logical expression always true */
1100 	ASSERT(sizeof (ao_bank_cfgs) / sizeof (ao_bank_cfg_t) ==
1101 	    AMD_MCA_BANK_COUNT);
1102 
1103 	rev = ao->ao_shared->aos_chiprev = cpuid_getchiprev(ao->ao_cpu);
1104 
1105 	/*
1106 	 * Must this core perform NB MCA or DRAM configuration?  This must be
1107 	 * done by just one core.
1108 	 */
1109 	donb = ao_chip_once(ao, AO_CFGONCE_NBMCA);
1110 	dodcfg = ao_chip_once(ao, AO_CFGONCE_DRAMCFG);
1111 
1112 	/*
1113 	 * Initialize poller data, but don't start polling yet.
1114 	 */
1115 	ao_mca_poll_init(ao, donb);
1116 
1117 	/*
1118 	 * Configure the bank MCi_CTL register to nominate which error
1119 	 * types for each bank will produce a machine-check (we'll poll
1120 	 * for others).  Correctable error types mentioned in these MCi_CTL
1121 	 * settings won't actually produce an exception unless an additional
1122 	 * (and undocumented) bit is set elsewhere - the poller must still
1123 	 * handle these.
1124 	 */
1125 	ao_bank_cfg(ao, rev, donb);
1126 
1127 	/*
1128 	 * Modify the MCA NB Configuration and Dram Configuration Registers.
1129 	 */
1130 	if (donb)
1131 		ao_nb_cfg(ao, rev);
1132 	if (dodcfg)
1133 		ao_dram_cfg(ao, rev);
1134 
1135 	/*
1136 	 * Setup the Online Spare Control Register
1137 	 */
1138 	if (donb && X86_CHIPREV_MATCH(rev, AO_REVS_FG)) {
1139 		ao_sparectl_cfg(ao);
1140 	}
1141 
1142 	/*
1143 	 * Enable all error reporting banks (icache, dcache, ...).  This
1144 	 * enables error detection, as opposed to error reporting above.
1145 	 */
1146 	wrmsr(IA32_MSR_MCG_CTL, AMD_MCG_EN_ALL);
1147 
1148 	/*
1149 	 * Throw away all existing bank state.  We do this because some BIOSes,
1150 	 * perhaps during POST, do things to the machine that cause MCA state
1151 	 * to be updated.  If we interpret this state as an actual error, we
1152 	 * may end up indicting something that's not actually broken.
1153 	 */
1154 	for (i = 0; i < AMD_MCA_BANK_COUNT; i++) {
1155 		if (!donb)
1156 			continue;
1157 
1158 		wrmsr(ao_bank_cfgs[i].bank_status, 0ULL);
1159 	}
1160 
1161 	wrmsr(IA32_MSR_MCG_STATUS, 0ULL);
1162 	membar_producer();
1163 
1164 	setcr4(getcr4() | CR4_MCE); /* enable #mc exceptions */
1165 }
1166 
1167 /*
1168  * Note that although this cpu module is loaded before the PSMs are
1169  * loaded (and hence before acpica is loaded), this function is
1170  * called from post_startup(), after PSMs are initialized and acpica
1171  * is loaded.
1172  */
1173 static int
1174 ao_acpi_find_smicmd(int *asd_port)
1175 {
1176 	FADT_DESCRIPTOR *fadt = NULL;
1177 
1178 	/*
1179 	 * AcpiGetFirmwareTable works even if ACPI is disabled, so a failure
1180 	 * here means we weren't able to retreive a pointer to the FADT.
1181 	 */
1182 	if (AcpiGetFirmwareTable(FADT_SIG, 1, ACPI_LOGICAL_ADDRESSING,
1183 	    (ACPI_TABLE_HEADER **)&fadt) != AE_OK)
1184 		return (-1);
1185 
1186 	ASSERT(fadt != NULL);
1187 
1188 	*asd_port = fadt->SmiCmd;
1189 	return (0);
1190 }
1191 
1192 /*ARGSUSED*/
1193 void
1194 ao_mca_post_init(void *data)
1195 {
1196 	const struct ao_smi_disable *asd;
1197 	id_t id;
1198 	int rv = -1, asd_port;
1199 
1200 	smbios_system_t sy;
1201 	smbios_bios_t sb;
1202 	smbios_info_t si;
1203 
1204 	/*
1205 	 * Fetch the System and BIOS vendor strings from SMBIOS and see if they
1206 	 * match a value in our table.  If so, disable SMI error polling.  This
1207 	 * is grotesque and should be replaced by self-describing vendor-
1208 	 * specific SMBIOS data or a specification enhancement instead.
1209 	 */
1210 	if (ao_mca_smi_disable && ksmbios != NULL &&
1211 	    smbios_info_bios(ksmbios, &sb) != SMB_ERR &&
1212 	    (id = smbios_info_system(ksmbios, &sy)) != SMB_ERR &&
1213 	    smbios_info_common(ksmbios, id, &si) != SMB_ERR) {
1214 
1215 		for (asd = ao_smi_disable; asd->asd_sys_vendor != NULL; asd++) {
1216 			if (strncmp(asd->asd_sys_vendor, si.smbi_manufacturer,
1217 			    strlen(asd->asd_sys_vendor)) != 0 ||
1218 			    strncmp(asd->asd_sys_product, si.smbi_product,
1219 			    strlen(asd->asd_sys_product)) != 0 ||
1220 			    strncmp(asd->asd_bios_vendor, sb.smbb_vendor,
1221 			    strlen(asd->asd_bios_vendor)) != 0)
1222 				continue;
1223 
1224 			/*
1225 			 * Look for the SMI_CMD port in the ACPI FADT,
1226 			 * if the port is 0, this platform doesn't support
1227 			 * SMM, so there is no SMI error polling to disable.
1228 			 */
1229 			if ((rv = ao_acpi_find_smicmd(&asd_port)) == 0 &&
1230 			    asd_port != 0) {
1231 				cmn_err(CE_CONT, "?SMI polling disabled in "
1232 				    "favor of Solaris Fault Management for "
1233 				    "AMD Processors\n");
1234 
1235 				outb(asd_port, asd->asd_code);
1236 
1237 			} else if (rv < 0) {
1238 				cmn_err(CE_CONT, "?Solaris Fault Management "
1239 				    "for AMD Processors could not disable SMI "
1240 				    "polling because an error occurred while "
1241 				    "trying to determine the SMI command port "
1242 				    "from the ACPI FADT table\n");
1243 			}
1244 			break;
1245 		}
1246 	}
1247 
1248 	ao_mca_poll_start();
1249 }
1250 
1251 /*
1252  * Called after a CPU has been marked with CPU_FAULTED.  Not called on the
1253  * faulted CPU.  cpu_lock is held.
1254  */
1255 /*ARGSUSED*/
1256 void
1257 ao_faulted_enter(void *data)
1258 {
1259 	/*
1260 	 * Nothing to do here.  We'd like to turn off the faulted CPU's
1261 	 * correctable error detectors, but that can only be done by the
1262 	 * faulted CPU itself.  cpu_get_state() will now return P_FAULTED,
1263 	 * allowing the poller to skip this CPU until it is re-enabled.
1264 	 */
1265 }
1266 
1267 /*
1268  * Called after the CPU_FAULTED bit has been cleared from a previously-faulted
1269  * CPU.  Not called on the faulted CPU.  cpu_lock is held.
1270  */
1271 void
1272 ao_faulted_exit(void *data)
1273 {
1274 	ao_data_t *ao = data;
1275 
1276 	/*
1277 	 * We'd like to clear the faulted CPU's MCi_STATUS registers so as to
1278 	 * avoid generating ereports for errors which occurred while the CPU was
1279 	 * officially faulted.  Unfortunately, those registers can only be
1280 	 * cleared by the CPU itself, so we can't do it here.
1281 	 *
1282 	 * We're going to set the UNFAULTING bit on the formerly-faulted CPU's
1283 	 * MCA state.  This will tell the poller that the MCi_STATUS registers
1284 	 * can't yet be trusted.  The poller, which is the first thing we
1285 	 * control that'll execute on that CPU, will clear the registers, and
1286 	 * will then clear the bit.
1287 	 */
1288 
1289 	ao->ao_mca.ao_mca_flags |= AO_MCA_F_UNFAULTING;
1290 }
1291