xref: /illumos-gate/usr/src/uts/i86pc/cpu/amd_opteron/ao.h (revision 22e4c3ac)
17aec1d6eScindi /*
27aec1d6eScindi  * CDDL HEADER START
37aec1d6eScindi  *
47aec1d6eScindi  * The contents of this file are subject to the terms of the
5a307a255Sgavinm  * Common Development and Distribution License (the "License").
6a307a255Sgavinm  * You may not use this file except in compliance with the License.
77aec1d6eScindi  *
87aec1d6eScindi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97aec1d6eScindi  * or http://www.opensolaris.org/os/licensing.
107aec1d6eScindi  * See the License for the specific language governing permissions
117aec1d6eScindi  * and limitations under the License.
127aec1d6eScindi  *
137aec1d6eScindi  * When distributing Covered Code, include this CDDL HEADER in each
147aec1d6eScindi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157aec1d6eScindi  * If applicable, add the following below this CDDL HEADER, with the
167aec1d6eScindi  * fields enclosed by brackets "[]" replaced with your own identifying
177aec1d6eScindi  * information: Portions Copyright [yyyy] [name of copyright owner]
187aec1d6eScindi  *
197aec1d6eScindi  * CDDL HEADER END
207aec1d6eScindi  */
217aec1d6eScindi 
227aec1d6eScindi /*
23c84b7bbeSAdrian Frost  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
247aec1d6eScindi  */
257aec1d6eScindi 
267aec1d6eScindi #ifndef _AO_H
277aec1d6eScindi #define	_AO_H
287aec1d6eScindi 
297aec1d6eScindi #include <sys/types.h>
307aec1d6eScindi #include <sys/mc.h>
317aec1d6eScindi #include <sys/mca_amd.h>
324156fc34Sgavinm #include <sys/mc_amd.h>
3320c794b3Sgavinm #include <sys/cpu_module_ms_impl.h>
347aec1d6eScindi #include <sys/nvpair.h>
357aec1d6eScindi #include <sys/cyclic.h>
367aec1d6eScindi #include <sys/errorq.h>
377aec1d6eScindi #include <sys/kobj.h>
387aec1d6eScindi #include <sys/fm/util.h>
397aec1d6eScindi 
407aec1d6eScindi #ifdef __cplusplus
417aec1d6eScindi extern "C" {
427aec1d6eScindi #endif
437aec1d6eScindi 
4420c794b3Sgavinm #define	AO_MAX_CHIPS		8
457aec1d6eScindi 
4620c794b3Sgavinm #define	AO_MCA_MAX_ERRORS	10
477aec1d6eScindi 
4820c794b3Sgavinm typedef struct ao_ms_data ao_ms_data_t;
497aec1d6eScindi 
507aec1d6eScindi /*
517aec1d6eScindi  * Rather than using torturous conditionals, we match errors using a table of
527aec1d6eScindi  * ao_error_disp_t's.  The members in the ao_error_disp_t are matched against
537aec1d6eScindi  * the value of MCi_STATUS, with a successful match indicating that the given
547aec1d6eScindi  * error occurred.
557aec1d6eScindi  *
567aec1d6eScindi  * While aed_stat_code will match most of the status code bits, a few of the
577aec1d6eScindi  * status code fields are either/or, and are treated separately so as to
587aec1d6eScindi  * minimize the number of ao_error_disp_t structures that must be created.
597aec1d6eScindi  * For example, the dc.tag_par error can have r4 values drd or dwr.  Rather
607aec1d6eScindi  * than creating two ao_error_disp_t's, we use the separate aed_stat_r4_bits
617aec1d6eScindi  * field to indicate both AO_MCA_R4_BIT_DRD and AO_MCA_R4_BIT_DWD.  As the
627aec1d6eScindi  * matching r4 values are drawn from aed_stat_r4_bits, we don't use the r4
637aec1d6eScindi  * bits in aed_stat_code for matching.  Similar reasoning lies behind the
647aec1d6eScindi  * creation of the pp and ii fields.
657aec1d6eScindi  */
66a307a255Sgavinm #define	AO_AED_PANIC_NEVER	0x00
67a307a255Sgavinm #define	AO_AED_PANIC_IFMCE	0x01
68a307a255Sgavinm #define	AO_AED_PANIC_ALWAYS	0x80
697aec1d6eScindi 
7020c794b3Sgavinm /*
7120c794b3Sgavinm  * The AO_AED_F_* flags tell us how to interpret aspects of the error
7220c794b3Sgavinm  * telemetry, such as which bits of the captured address are valid for
7320c794b3Sgavinm  * this error.
7420c794b3Sgavinm  */
7520c794b3Sgavinm 					/* MCi_ADDR ... */
7620c794b3Sgavinm #define	AO_AED_F_LINEAR		0x01	/* is a linear address */
7720c794b3Sgavinm #define	AO_AED_F_PHYSICAL	0x02	/* is a physical address */
7820c794b3Sgavinm #define	AO_AED_F_PAGEALIGNED	0x04	/* aligns to page size */
7920c794b3Sgavinm #define	AO_AED_F_L2SETWAY	0x08	/* 3:0 = way, 15/14/13/12:6 = set */
804156fc34Sgavinm 
814156fc34Sgavinm #define	AO_AED_FLAGS_ADDRTYPE	(AO_AED_F_LINEAR | AO_AED_F_PHYSICAL | \
824156fc34Sgavinm     AO_AED_F_PAGEALIGNED | AO_AED_F_L2SETWAY)
837aec1d6eScindi 
8420c794b3Sgavinm /*
8520c794b3Sgavinm  * The AO_AED_ET_* flags group individual error dispositions into
8620c794b3Sgavinm  * error types.  This is used to nominate additional telemetry beyond the
8720c794b3Sgavinm  * architectural bank registers to capture for this error type.
8820c794b3Sgavinm  */
8920c794b3Sgavinm #define	AO_AED_ET_MEMECC		0x0001	/* Main memory ECC error */
9020c794b3Sgavinm 
917aec1d6eScindi typedef struct ao_error_disp {
927aec1d6eScindi 	const char *aed_class;		/* ereport class for use if match */
937aec1d6eScindi 	uint64_t aed_ereport_members;	/* ereport contents flags if match */
947aec1d6eScindi 	uint64_t aed_stat_mask;		/* status msr bits for match */
957aec1d6eScindi 	uint64_t aed_stat_mask_res;	/* status mask result for match */
967aec1d6eScindi 	uint16_t aed_stat_code;		/* status code for match */
977aec1d6eScindi 	uint8_t aed_stat_extcode;	/* extended status code for match */
987aec1d6eScindi 	uint8_t aed_stat_pp_bits:4;	/* AO_MCA_PP_BIT_* for pp matching */
997aec1d6eScindi 	uint8_t aed_stat_ii_bits:4;	/* AO_MCA_II_BIT_* for ii matching */
1007aec1d6eScindi 	uint16_t aed_stat_r4_bits;	/* AO_MCA_R4_BIT_* for r4 matching */
1014156fc34Sgavinm 	uint8_t aed_addrvalid_hi;	/* most significant valid addr bit */
1024156fc34Sgavinm 	uint8_t aed_addrvalid_lo;	/* least significant valid addr bit */
1037aec1d6eScindi 	uint8_t aed_panic_when;		/* extra conditions for panic */
10420c794b3Sgavinm 	uint16_t aed_flags;		/* AO_AED_F_* */
10520c794b3Sgavinm 	uint16_t aed_errtype;		/* AO_AED_ET_* */
1067aec1d6eScindi } ao_error_disp_t;
1077aec1d6eScindi 
1087aec1d6eScindi /*
10920c794b3Sgavinm  * We store non-architectutal config as inherited from the BIOS to assist
11020c794b3Sgavinm  * in troubleshooting.
1117aec1d6eScindi  */
11220c794b3Sgavinm struct ao_bios_cfg {
11320c794b3Sgavinm 	uint64_t *bcfg_bank_mask;
11420c794b3Sgavinm };
1157aec1d6eScindi 
1167aec1d6eScindi /*
1177aec1d6eScindi  * The master data structure used to hold MCA-related state.
1187aec1d6eScindi  */
11920c794b3Sgavinm typedef struct ao_ms_mca {
12020c794b3Sgavinm 	struct ao_bios_cfg ao_mca_bios_cfg;
1217aec1d6eScindi 	kmutex_t ao_mca_poll_lock;	/* keep pollers from colliding */
1227aec1d6eScindi 	uint_t ao_mca_flags;		/* AO_MCA_F_* */
12320c794b3Sgavinm } ao_ms_mca_t;
1247aec1d6eScindi 
1258a40a695Sgavinm /*
12620c794b3Sgavinm  * Per-chip shared state
1278a40a695Sgavinm  */
1288a40a695Sgavinm struct ao_chipshared {
129*22e4c3acSKeith M Wesolowski 	x86_chiprev_t aos_chiprev;
1308a40a695Sgavinm 	volatile ulong_t aos_cfgonce;	/* Config performed once per chip */
13120c794b3Sgavinm 	hrtime_t aos_nb_poll_timestamp;
13220c794b3Sgavinm 	cmi_hdl_t aos_nb_poll_owner;
13320c794b3Sgavinm 	uint64_t aos_bcfg_nb_misc;	/* BIOS value of MC4_MISC MSR */
1348a40a695Sgavinm 	uint32_t aos_bcfg_nb_cfg;	/* BIOS value of NB MCA Config */
1358a40a695Sgavinm 	uint32_t aos_bcfg_nb_sparectl;	/* BIOS value of Online Spare Control */
136bb86c342Sgavinm 	uint32_t aos_bcfg_dcfg_lo;	/* BIOS value of DRAM Config Low */
137bb86c342Sgavinm 	uint32_t aos_bcfg_dcfg_hi;	/* BIOS value of DRAM Config High */
13820c794b3Sgavinm 	uint32_t aos_bcfg_scrubctl;	/* BIOS value of scrub control */
1398a40a695Sgavinm };
1408a40a695Sgavinm 
14120c794b3Sgavinm /* Bit numbers for once-per-chip operations policed by cms_once */
1428a40a695Sgavinm enum ao_cfgonce_bitnum {
143bb86c342Sgavinm 	AO_CFGONCE_NBMCA,
14420c794b3Sgavinm 	AO_CFGONCE_NBCFG,
145bb86c342Sgavinm 	AO_CFGONCE_DRAMCFG
1468a40a695Sgavinm };
1478a40a695Sgavinm 
1487aec1d6eScindi /*
14920c794b3Sgavinm  * Per-CPU model-specific state
1507aec1d6eScindi  */
15120c794b3Sgavinm struct ao_ms_data {
15220c794b3Sgavinm 	cmi_hdl_t ao_ms_hdl;
15320c794b3Sgavinm 	ao_ms_mca_t ao_ms_mca;
15420c794b3Sgavinm 	struct ao_chipshared *ao_ms_shared;
15520c794b3Sgavinm 	uint64_t ao_ms_hwcr_val;
1567aec1d6eScindi };
1577aec1d6eScindi 
1587aec1d6eScindi #ifdef _KERNEL
1597aec1d6eScindi 
1607aec1d6eScindi struct regs;
1617aec1d6eScindi 
16220c794b3Sgavinm /*
16320c794b3Sgavinm  * Our cms_ops operations and function prototypes for all non-NULL members.
16420c794b3Sgavinm  */
16520c794b3Sgavinm extern const cms_ops_t _cms_ops;
16620c794b3Sgavinm 
16720c794b3Sgavinm extern int ao_ms_init(cmi_hdl_t, void **);
16820c794b3Sgavinm extern void ao_ms_post_startup(cmi_hdl_t);
16920c794b3Sgavinm extern void ao_ms_post_mpstartup(cmi_hdl_t);
17020c794b3Sgavinm extern uint64_t ao_ms_mcgctl_val(cmi_hdl_t, int, uint64_t);
17120c794b3Sgavinm extern boolean_t ao_ms_bankctl_skipinit(cmi_hdl_t, int);
17220c794b3Sgavinm extern uint64_t ao_ms_bankctl_val(cmi_hdl_t, int, uint64_t);
17320c794b3Sgavinm extern void ao_ms_mca_init(cmi_hdl_t, int);
17420c794b3Sgavinm extern uint64_t ao_ms_poll_ownermask(cmi_hdl_t, hrtime_t);
17520c794b3Sgavinm extern uint32_t ao_ms_error_action(cmi_hdl_t, int, int, uint64_t,
17620c794b3Sgavinm     uint64_t, uint64_t, void *);
177c84b7bbeSAdrian Frost extern cms_cookie_t ao_ms_disp_match(cmi_hdl_t, int, int, uint64_t, uint64_t,
17820c794b3Sgavinm     uint64_t, void *);
17920c794b3Sgavinm extern void ao_ms_ereport_class(cmi_hdl_t, cms_cookie_t, const char **,
18020c794b3Sgavinm     const char **);
18120c794b3Sgavinm extern boolean_t ao_ms_ereport_includestack(cmi_hdl_t, cms_cookie_t);
18220c794b3Sgavinm extern void ao_ms_ereport_add_logout(cmi_hdl_t, nvlist_t *,
18320c794b3Sgavinm     nv_alloc_t *, int, uint64_t, uint64_t, uint64_t, void *, void *);
18420c794b3Sgavinm extern cms_errno_t ao_ms_msrinject(cmi_hdl_t, uint_t, uint64_t);
1857aec1d6eScindi 
18620c794b3Sgavinm /*
18720c794b3Sgavinm  * Local functions
18820c794b3Sgavinm  */
1898031591dSSrihari Venkatesan extern void ao_procnode_scrubber_enable(cmi_hdl_t, ao_ms_data_t *);
1907aec1d6eScindi extern void ao_pcicfg_write(uint_t, uint_t, uint_t, uint32_t);
1917aec1d6eScindi extern uint32_t ao_pcicfg_read(uint_t, uint_t, uint_t);
19220c794b3Sgavinm extern void ao_bankstatus_prewrite(cmi_hdl_t, ao_ms_data_t *);
19320c794b3Sgavinm extern void ao_bankstatus_postwrite(cmi_hdl_t, ao_ms_data_t *);
1948a40a695Sgavinm 
1957aec1d6eScindi #endif /* _KERNEL */
1967aec1d6eScindi 
1977aec1d6eScindi #ifdef __cplusplus
1987aec1d6eScindi }
1997aec1d6eScindi #endif
2007aec1d6eScindi 
2017aec1d6eScindi #endif /* _AO_H */
202