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