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.
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.
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]
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
29 #include <sys/types.h>
31 #include <sys/mca_amd.h>
32 #include <sys/mc_amd.h>
33 #include <sys/cpu_module_ms_impl.h>
34 #include <sys/nvpair.h>
35 #include <sys/cyclic.h>
36 #include <sys/errorq.h>
38 #include <sys/fm/util.h>
44 #define AO_MAX_CHIPS 8
46 #define AO_MCA_MAX_ERRORS 10
48 typedef struct ao_ms_data ao_ms_data_t
;
51 * Rather than using torturous conditionals, we match errors using a table of
52 * ao_error_disp_t's. The members in the ao_error_disp_t are matched against
53 * the value of MCi_STATUS, with a successful match indicating that the given
56 * While aed_stat_code will match most of the status code bits, a few of the
57 * status code fields are either/or, and are treated separately so as to
58 * minimize the number of ao_error_disp_t structures that must be created.
59 * For example, the dc.tag_par error can have r4 values drd or dwr. Rather
60 * than creating two ao_error_disp_t's, we use the separate aed_stat_r4_bits
61 * field to indicate both AO_MCA_R4_BIT_DRD and AO_MCA_R4_BIT_DWD. As the
62 * matching r4 values are drawn from aed_stat_r4_bits, we don't use the r4
63 * bits in aed_stat_code for matching. Similar reasoning lies behind the
64 * creation of the pp and ii fields.
66 #define AO_AED_PANIC_NEVER 0x00
67 #define AO_AED_PANIC_IFMCE 0x01
68 #define AO_AED_PANIC_ALWAYS 0x80
71 * The AO_AED_F_* flags tell us how to interpret aspects of the error
72 * telemetry, such as which bits of the captured address are valid for
76 #define AO_AED_F_LINEAR 0x01 /* is a linear address */
77 #define AO_AED_F_PHYSICAL 0x02 /* is a physical address */
78 #define AO_AED_F_PAGEALIGNED 0x04 /* aligns to page size */
79 #define AO_AED_F_L2SETWAY 0x08 /* 3:0 = way, 15/14/13/12:6 = set */
81 #define AO_AED_FLAGS_ADDRTYPE (AO_AED_F_LINEAR | AO_AED_F_PHYSICAL | \
82 AO_AED_F_PAGEALIGNED | AO_AED_F_L2SETWAY)
85 * The AO_AED_ET_* flags group individual error dispositions into
86 * error types. This is used to nominate additional telemetry beyond the
87 * architectural bank registers to capture for this error type.
89 #define AO_AED_ET_MEMECC 0x0001 /* Main memory ECC error */
91 typedef struct ao_error_disp
{
92 const char *aed_class
; /* ereport class for use if match */
93 uint64_t aed_ereport_members
; /* ereport contents flags if match */
94 uint64_t aed_stat_mask
; /* status msr bits for match */
95 uint64_t aed_stat_mask_res
; /* status mask result for match */
96 uint16_t aed_stat_code
; /* status code for match */
97 uint8_t aed_stat_extcode
; /* extended status code for match */
98 uint8_t aed_stat_pp_bits
:4; /* AO_MCA_PP_BIT_* for pp matching */
99 uint8_t aed_stat_ii_bits
:4; /* AO_MCA_II_BIT_* for ii matching */
100 uint16_t aed_stat_r4_bits
; /* AO_MCA_R4_BIT_* for r4 matching */
101 uint8_t aed_addrvalid_hi
; /* most significant valid addr bit */
102 uint8_t aed_addrvalid_lo
; /* least significant valid addr bit */
103 uint8_t aed_panic_when
; /* extra conditions for panic */
104 uint16_t aed_flags
; /* AO_AED_F_* */
105 uint16_t aed_errtype
; /* AO_AED_ET_* */
109 * We store non-architectutal config as inherited from the BIOS to assist
110 * in troubleshooting.
113 uint64_t *bcfg_bank_mask
;
117 * The master data structure used to hold MCA-related state.
119 typedef struct ao_ms_mca
{
120 struct ao_bios_cfg ao_mca_bios_cfg
;
121 kmutex_t ao_mca_poll_lock
; /* keep pollers from colliding */
122 uint_t ao_mca_flags
; /* AO_MCA_F_* */
126 * Per-chip shared state
128 struct ao_chipshared
{
129 uint32_t aos_chiprev
;
130 volatile ulong_t aos_cfgonce
; /* Config performed once per chip */
131 hrtime_t aos_nb_poll_timestamp
;
132 cmi_hdl_t aos_nb_poll_owner
;
133 uint64_t aos_bcfg_nb_misc
; /* BIOS value of MC4_MISC MSR */
134 uint32_t aos_bcfg_nb_cfg
; /* BIOS value of NB MCA Config */
135 uint32_t aos_bcfg_nb_sparectl
; /* BIOS value of Online Spare Control */
136 uint32_t aos_bcfg_dcfg_lo
; /* BIOS value of DRAM Config Low */
137 uint32_t aos_bcfg_dcfg_hi
; /* BIOS value of DRAM Config High */
138 uint32_t aos_bcfg_scrubctl
; /* BIOS value of scrub control */
141 /* Bit numbers for once-per-chip operations policed by cms_once */
142 enum ao_cfgonce_bitnum
{
149 * Per-CPU model-specific state
153 ao_ms_mca_t ao_ms_mca
;
154 struct ao_chipshared
*ao_ms_shared
;
155 uint64_t ao_ms_hwcr_val
;
163 * Our cms_ops operations and function prototypes for all non-NULL members.
165 extern const cms_ops_t _cms_ops
;
167 extern int ao_ms_init(cmi_hdl_t
, void **);
168 extern void ao_ms_post_startup(cmi_hdl_t
);
169 extern void ao_ms_post_mpstartup(cmi_hdl_t
);
170 extern uint64_t ao_ms_mcgctl_val(cmi_hdl_t
, int, uint64_t);
171 extern boolean_t
ao_ms_bankctl_skipinit(cmi_hdl_t
, int);
172 extern uint64_t ao_ms_bankctl_val(cmi_hdl_t
, int, uint64_t);
173 extern void ao_ms_mca_init(cmi_hdl_t
, int);
174 extern uint64_t ao_ms_poll_ownermask(cmi_hdl_t
, hrtime_t
);
175 extern uint32_t ao_ms_error_action(cmi_hdl_t
, int, int, uint64_t,
176 uint64_t, uint64_t, void *);
177 extern cms_cookie_t
ao_ms_disp_match(cmi_hdl_t
, int, int, uint64_t, uint64_t,
179 extern void ao_ms_ereport_class(cmi_hdl_t
, cms_cookie_t
, const char **,
181 extern boolean_t
ao_ms_ereport_includestack(cmi_hdl_t
, cms_cookie_t
);
182 extern void ao_ms_ereport_add_logout(cmi_hdl_t
, nvlist_t
*,
183 nv_alloc_t
*, int, uint64_t, uint64_t, uint64_t, void *, void *);
184 extern cms_errno_t
ao_ms_msrinject(cmi_hdl_t
, uint_t
, uint64_t);
189 extern void ao_procnode_scrubber_enable(cmi_hdl_t
, ao_ms_data_t
*);
190 extern void ao_pcicfg_write(uint_t
, uint_t
, uint_t
, uint32_t);
191 extern uint32_t ao_pcicfg_read(uint_t
, uint_t
, uint_t
);
192 extern void ao_bankstatus_prewrite(cmi_hdl_t
, ao_ms_data_t
*);
193 extern void ao_bankstatus_postwrite(cmi_hdl_t
, ao_ms_data_t
*);