xref: /illumos-gate/usr/src/uts/i86pc/cpu/amd_opteron/ao.h (revision 20c794b3)
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 #ifndef _AO_H
28 #define	_AO_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <sys/types.h>
33 #include <sys/mc.h>
34 #include <sys/mca_amd.h>
35 #include <sys/mc_amd.h>
36 #include <sys/cpu_module_ms_impl.h>
37 #include <sys/nvpair.h>
38 #include <sys/cyclic.h>
39 #include <sys/errorq.h>
40 #include <sys/kobj.h>
41 #include <sys/fm/util.h>
42 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 
47 #define	AO_MAX_CHIPS		8
48 
49 #define	AO_MCA_MAX_ERRORS	10
50 
51 typedef struct ao_ms_data ao_ms_data_t;
52 
53 /*
54  * Rather than using torturous conditionals, we match errors using a table of
55  * ao_error_disp_t's.  The members in the ao_error_disp_t are matched against
56  * the value of MCi_STATUS, with a successful match indicating that the given
57  * error occurred.
58  *
59  * While aed_stat_code will match most of the status code bits, a few of the
60  * status code fields are either/or, and are treated separately so as to
61  * minimize the number of ao_error_disp_t structures that must be created.
62  * For example, the dc.tag_par error can have r4 values drd or dwr.  Rather
63  * than creating two ao_error_disp_t's, we use the separate aed_stat_r4_bits
64  * field to indicate both AO_MCA_R4_BIT_DRD and AO_MCA_R4_BIT_DWD.  As the
65  * matching r4 values are drawn from aed_stat_r4_bits, we don't use the r4
66  * bits in aed_stat_code for matching.  Similar reasoning lies behind the
67  * creation of the pp and ii fields.
68  */
69 #define	AO_AED_PANIC_NEVER	0x00
70 #define	AO_AED_PANIC_IFMCE	0x01
71 #define	AO_AED_PANIC_ALWAYS	0x80
72 
73 /*
74  * The AO_AED_F_* flags tell us how to interpret aspects of the error
75  * telemetry, such as which bits of the captured address are valid for
76  * this error.
77  */
78 					/* MCi_ADDR ... */
79 #define	AO_AED_F_LINEAR		0x01	/* is a linear address */
80 #define	AO_AED_F_PHYSICAL	0x02	/* is a physical address */
81 #define	AO_AED_F_PAGEALIGNED	0x04	/* aligns to page size */
82 #define	AO_AED_F_L2SETWAY	0x08	/* 3:0 = way, 15/14/13/12:6 = set */
83 
84 #define	AO_AED_FLAGS_ADDRTYPE	(AO_AED_F_LINEAR | AO_AED_F_PHYSICAL | \
85     AO_AED_F_PAGEALIGNED | AO_AED_F_L2SETWAY)
86 
87 /*
88  * The AO_AED_ET_* flags group individual error dispositions into
89  * error types.  This is used to nominate additional telemetry beyond the
90  * architectural bank registers to capture for this error type.
91  */
92 #define	AO_AED_ET_MEMECC		0x0001	/* Main memory ECC error */
93 
94 typedef struct ao_error_disp {
95 	const char *aed_class;		/* ereport class for use if match */
96 	uint64_t aed_ereport_members;	/* ereport contents flags if match */
97 	uint64_t aed_stat_mask;		/* status msr bits for match */
98 	uint64_t aed_stat_mask_res;	/* status mask result for match */
99 	uint16_t aed_stat_code;		/* status code for match */
100 	uint8_t aed_stat_extcode;	/* extended status code for match */
101 	uint8_t aed_stat_pp_bits:4;	/* AO_MCA_PP_BIT_* for pp matching */
102 	uint8_t aed_stat_ii_bits:4;	/* AO_MCA_II_BIT_* for ii matching */
103 	uint16_t aed_stat_r4_bits;	/* AO_MCA_R4_BIT_* for r4 matching */
104 	uint8_t aed_addrvalid_hi;	/* most significant valid addr bit */
105 	uint8_t aed_addrvalid_lo;	/* least significant valid addr bit */
106 	uint8_t aed_panic_when;		/* extra conditions for panic */
107 	uint16_t aed_flags;		/* AO_AED_F_* */
108 	uint16_t aed_errtype;		/* AO_AED_ET_* */
109 } ao_error_disp_t;
110 
111 /*
112  * We store non-architectutal config as inherited from the BIOS to assist
113  * in troubleshooting.
114  */
115 struct ao_bios_cfg {
116 	uint64_t *bcfg_bank_mask;
117 };
118 
119 /*
120  * The master data structure used to hold MCA-related state.
121  */
122 typedef struct ao_ms_mca {
123 	struct ao_bios_cfg ao_mca_bios_cfg;
124 	kmutex_t ao_mca_poll_lock;	/* keep pollers from colliding */
125 	uint_t ao_mca_flags;		/* AO_MCA_F_* */
126 } ao_ms_mca_t;
127 
128 /*
129  * Per-chip shared state
130  */
131 struct ao_chipshared {
132 	uint32_t aos_chiprev;
133 	volatile ulong_t aos_cfgonce;	/* Config performed once per chip */
134 	hrtime_t aos_nb_poll_timestamp;
135 	cmi_hdl_t aos_nb_poll_owner;
136 	uint64_t aos_bcfg_nb_misc;	/* BIOS value of MC4_MISC MSR */
137 	uint32_t aos_bcfg_nb_cfg;	/* BIOS value of NB MCA Config */
138 	uint32_t aos_bcfg_nb_sparectl;	/* BIOS value of Online Spare Control */
139 	uint32_t aos_bcfg_dcfg_lo;	/* BIOS value of DRAM Config Low */
140 	uint32_t aos_bcfg_dcfg_hi;	/* BIOS value of DRAM Config High */
141 	uint32_t aos_bcfg_scrubctl;	/* BIOS value of scrub control */
142 };
143 
144 /* Bit numbers for once-per-chip operations policed by cms_once */
145 enum ao_cfgonce_bitnum {
146 	AO_CFGONCE_NBMCA,
147 	AO_CFGONCE_NBCFG,
148 	AO_CFGONCE_DRAMCFG
149 };
150 
151 /*
152  * Per-CPU model-specific state
153  */
154 struct ao_ms_data {
155 	cmi_hdl_t ao_ms_hdl;
156 	ao_ms_mca_t ao_ms_mca;
157 	struct ao_chipshared *ao_ms_shared;
158 	uint64_t ao_ms_hwcr_val;
159 };
160 
161 #ifdef _KERNEL
162 
163 struct regs;
164 
165 /*
166  * Our cms_ops operations and function prototypes for all non-NULL members.
167  */
168 extern const cms_ops_t _cms_ops;
169 
170 extern int ao_ms_init(cmi_hdl_t, void **);
171 extern void ao_ms_post_startup(cmi_hdl_t);
172 extern void ao_ms_post_mpstartup(cmi_hdl_t);
173 extern uint64_t ao_ms_mcgctl_val(cmi_hdl_t, int, uint64_t);
174 extern boolean_t ao_ms_bankctl_skipinit(cmi_hdl_t, int);
175 extern uint64_t ao_ms_bankctl_val(cmi_hdl_t, int, uint64_t);
176 extern void ao_ms_mca_init(cmi_hdl_t, int);
177 extern uint64_t ao_ms_poll_ownermask(cmi_hdl_t, hrtime_t);
178 extern uint32_t ao_ms_error_action(cmi_hdl_t, int, int, uint64_t,
179     uint64_t, uint64_t, void *);
180 extern cms_cookie_t ao_ms_disp_match(cmi_hdl_t, int, uint64_t, uint64_t,
181     uint64_t, void *);
182 extern void ao_ms_ereport_class(cmi_hdl_t, cms_cookie_t, const char **,
183     const char **);
184 extern boolean_t ao_ms_ereport_includestack(cmi_hdl_t, cms_cookie_t);
185 extern void ao_ms_ereport_add_logout(cmi_hdl_t, nvlist_t *,
186     nv_alloc_t *, int, uint64_t, uint64_t, uint64_t, void *, void *);
187 extern cms_errno_t ao_ms_msrinject(cmi_hdl_t, uint_t, uint64_t);
188 
189 /*
190  * Local functions
191  */
192 extern void ao_chip_scrubber_enable(cmi_hdl_t, ao_ms_data_t *);
193 extern void ao_pcicfg_write(uint_t, uint_t, uint_t, uint32_t);
194 extern uint32_t ao_pcicfg_read(uint_t, uint_t, uint_t);
195 extern void ao_bankstatus_prewrite(cmi_hdl_t, ao_ms_data_t *);
196 extern void ao_bankstatus_postwrite(cmi_hdl_t, ao_ms_data_t *);
197 
198 #endif /* _KERNEL */
199 
200 #ifdef __cplusplus
201 }
202 #endif
203 
204 #endif /* _AO_H */
205