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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Native MCA polling. We establish an ommipresent cyclic to fire on all 29 * online cpus to check their MCA state and log any valid errors for 30 * diagnosis. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/cyclic.h> 35 #include <sys/x86_archext.h> 36 #include <sys/mca_x86.h> 37 38 #include "gcpu.h" 39 40 hrtime_t gcpu_mca_poll_interval = NANOSEC * 10ULL; /* tuneable */ 41 static cyclic_id_t gcpu_mca_poll_cycid; 42 static int gcpu_mca_poll_inits; 43 44 /* 45 * Return nonzero of the given handle should poll the MCH. We stick with 46 * the same handle as before unless the timestamp has not been updated 47 * for a while. There is no need to keep a hold on the mch_poll_owner 48 * handle. 49 */ 50 51 static kmutex_t mch_poll_lock; 52 static hrtime_t mch_poll_timestamp; 53 static cmi_hdl_t mch_poll_owner; 54 55 static int 56 mch_pollowner(cmi_hdl_t hdl) 57 { 58 hrtime_t now = gethrtime_waitfree(); 59 int dopoll = 0; 60 61 mutex_enter(&mch_poll_lock); 62 if (now - mch_poll_timestamp > 2 * gcpu_mca_poll_interval || 63 mch_poll_timestamp == 0) { 64 mch_poll_owner = hdl; 65 dopoll = 1; 66 } else if (mch_poll_owner == hdl) { 67 dopoll = 1; 68 } 69 70 if (dopoll) 71 mch_poll_timestamp = now; 72 73 mutex_exit(&mch_poll_lock); 74 return (dopoll); 75 } 76 77 78 static void 79 gcpu_ntv_mca_poll(cmi_hdl_t hdl, int what) 80 { 81 gcpu_data_t *gcpu = cmi_hdl_getcmidata(hdl); 82 gcpu_mca_t *mca = &gcpu->gcpu_mca; 83 gcpu_mce_status_t mce; 84 int willpanic; 85 uint64_t bankmask; 86 87 ASSERT(MUTEX_HELD(&gcpu->gcpu_shared->gcpus_poll_lock)); 88 89 /* Enable CMCI in first poll if is supported */ 90 if (cmi_enable_cmci && (!mca->gcpu_mca_first_poll_cmci_enabled)) { 91 int i; 92 uint64_t ctl2; 93 94 for (i = 0; i < mca->gcpu_mca_nbanks; i++) { 95 if (mca->gcpu_bank_cmci[i].cmci_cap) { 96 (void) cmi_hdl_rdmsr(hdl, IA32_MSR_MC_CTL2(i), 97 &ctl2); 98 ctl2 |= MSR_MC_CTL2_EN; 99 (void) cmi_hdl_wrmsr(hdl, IA32_MSR_MC_CTL2(i), 100 ctl2); 101 mca->gcpu_bank_cmci[i].cmci_enabled = 1; 102 } 103 } 104 mca->gcpu_mca_first_poll_cmci_enabled = 1; 105 } 106 107 if (mca->gcpu_mca_flags & GCPU_MCA_F_UNFAULTING) { 108 int i; 109 110 mca->gcpu_mca_flags &= ~GCPU_MCA_F_UNFAULTING; 111 gcpu_poll_trace(&gcpu->gcpu_mca.gcpu_polltrace, 112 GCPU_MPT_WHAT_UNFAULTING, 0); 113 114 /* 115 * On the first cyclic poll after unfaulting a CPU we 116 * clear the status registers; see gcpu_faulted_exit 117 * for details. We don't do this if the poll was 118 * initiated manually (presumably from some injection 119 * activity). 120 */ 121 if (what == GCPU_MPT_WHAT_CYC_ERR) { 122 for (i = 0; i < mca->gcpu_mca_nbanks; i++) { 123 (void) cmi_hdl_wrmsr(hdl, 124 IA32_MSR_MC(i, STATUS), 0ULL); 125 } 126 return; 127 } 128 } 129 130 /* 131 * Logout errors of the MCA banks of this cpu. 132 */ 133 if (what == GCPU_MPT_WHAT_CMCI_ERR) { 134 /* 135 * for CMCI, all banks should be scanned for log out 136 */ 137 bankmask = -1ULL; 138 } else { 139 bankmask = cms_poll_ownermask(hdl, gcpu_mca_poll_interval); 140 } 141 gcpu_mca_logout(hdl, NULL, bankmask, &mce, B_TRUE, what); 142 143 if (mce.mce_nerr != 0) 144 gcpu_poll_trace(&gcpu->gcpu_mca.gcpu_polltrace, what, 145 mce.mce_nerr); 146 147 mca->gcpu_mca_lastpoll = gethrtime_waitfree(); 148 149 willpanic = mce.mce_disp & CMI_ERRDISP_FORCEFATAL && cmi_panic_on_ue(); 150 151 if (what != GCPU_MPT_WHAT_CMCI_ERR) { 152 /* 153 * Call to the memory-controller driver which may report some 154 * errors not visible under the MCA (for off-chip NB). 155 * Since there is typically a single MCH we arrange that 156 * just one cpu perform this task at each cyclic fire. 157 */ 158 if (mch_pollowner(hdl)) 159 cmi_mc_logout(hdl, 0, willpanic); 160 } 161 162 /* 163 * In the common case any polled error is considered non-fatal, 164 * even if it indicates PCC or UC etc. The only condition on which 165 * we will panic for a polled error is if model-specific support 166 * forces the error to be terminal regardless of how it is 167 * encountered. 168 */ 169 if (willpanic) { 170 #ifdef DEBUG 171 cmn_err(CE_WARN, "MCA Poll: %u errors, disp=0x%llx, " 172 "%u PCC (%u ok), " 173 "%u UC (%u ok, %u poisoned), " 174 "%u forcefatal, %u ignored", 175 mce.mce_nerr, (u_longlong_t)mce.mce_disp, 176 mce.mce_npcc, mce.mce_npcc_ok, 177 mce.mce_nuc, mce.mce_nuc_ok, mce.mce_nuc_poisoned, 178 mce.mce_forcefatal, mce.mce_ignored); 179 180 #endif 181 fm_panic("Unrecoverable Machine-Check Exception (Polled)"); 182 } 183 } 184 185 /* 186 * See gcpu_mca_trap for an explanation of why preemption is disabled here. 187 * Note that we disable preemption and then contend for an adaptive mutex - 188 * we could block during the mutex operation, but once we return with the 189 * mutex held we nust perform no operation that can block and we cannot 190 * be preempted so we will stay on cpu for the duration. The disabling 191 * of preemption also means we cannot migrate cpus once we have returned 192 * with the mutex held - cyclic invocations can't migrate, anyway, but 193 * others could if they have failed to bind before this point. 194 */ 195 static void 196 gcpu_ntv_mca_poll_wrapper(cmi_hdl_t hdl, int what) 197 { 198 gcpu_data_t *gcpu; 199 200 if (hdl == NULL || (gcpu = cmi_hdl_getcmidata(hdl)) == NULL || 201 gcpu->gcpu_mca.gcpu_mca_lgsz == 0) 202 return; 203 204 kpreempt_disable(); 205 mutex_enter(&gcpu->gcpu_shared->gcpus_poll_lock); 206 gcpu_ntv_mca_poll(hdl, what); 207 mutex_exit(&gcpu->gcpu_shared->gcpus_poll_lock); 208 kpreempt_enable(); 209 } 210 211 static void 212 gcpu_ntv_mca_poll_cyclic(void *arg) 213 { 214 gcpu_ntv_mca_poll_wrapper((cmi_hdl_t)arg, GCPU_MPT_WHAT_CYC_ERR); 215 } 216 217 /*ARGSUSED*/ 218 static void 219 gcpu_ntv_mca_poll_online(void *arg, cpu_t *cp, cyc_handler_t *cyh, 220 cyc_time_t *cyt) 221 { 222 cmi_hdl_t hdl; 223 224 /* 225 * Lookup and hold a handle for this cpu (any hold released in 226 * our offline function). If we chose not to initialize a handle 227 * for this cpu back at cmi_init time then this lookup will return 228 * NULL, so the cyh_func we appoint must be prepared for that. 229 */ 230 hdl = cmi_hdl_lookup(CMI_HDL_NATIVE, cmi_ntv_hwchipid(cp), 231 cmi_ntv_hwcoreid(cp), cmi_ntv_hwstrandid(cp)); 232 233 cyt->cyt_when = 0; 234 cyt->cyt_interval = gcpu_mca_poll_interval; 235 cyh->cyh_func = gcpu_ntv_mca_poll_cyclic; 236 cyh->cyh_arg = (void *)hdl; 237 cyh->cyh_level = CY_LOW_LEVEL; 238 } 239 240 /*ARGSUSED*/ 241 static void 242 gcpu_ntv_mca_poll_offline(void *arg, cpu_t *cpu, void *cyh_arg) 243 { 244 cmi_hdl_t hdl = (cmi_hdl_t)cyh_arg; 245 246 if (hdl != NULL) 247 cmi_hdl_rele(hdl); 248 } 249 250 static void 251 gcpu_ntv_mca_poll_start(void) 252 { 253 cyc_omni_handler_t cyo; 254 255 if (gcpu_mca_poll_interval == 0 || gcpu_mca_poll_inits == 0) 256 return; 257 258 cyo.cyo_online = gcpu_ntv_mca_poll_online; 259 cyo.cyo_offline = gcpu_ntv_mca_poll_offline; 260 cyo.cyo_arg = NULL; 261 262 mutex_enter(&cpu_lock); 263 gcpu_mca_poll_cycid = cyclic_add_omni(&cyo); 264 mutex_exit(&cpu_lock); 265 } 266 267 /* 268 * gcpu_mca_poll_init is called from gcpu_mca_init for each cpu handle 269 * that we initialize for. It should prepare for polling by allocating 270 * control structures and the like, but must not kick polling off yet. 271 */ 272 273 void 274 gcpu_mca_poll_init(cmi_hdl_t hdl) 275 { 276 gcpu_data_t *gcpu = cmi_hdl_getcmidata(hdl); 277 gcpu_poll_trace_ctl_t *ptc = &gcpu->gcpu_mca.gcpu_polltrace; 278 279 ASSERT(cmi_hdl_class(hdl) == CMI_HDL_NATIVE); 280 281 gcpu_poll_trace_init(ptc); 282 283 gcpu_mca_poll_inits++; 284 } 285 286 void 287 gcpu_mca_poll_start(cmi_hdl_t hdl) 288 { 289 ASSERT(cmi_hdl_class(hdl) == CMI_HDL_NATIVE); 290 gcpu_ntv_mca_poll_start(); 291 } 292 293 void 294 gcpu_hdl_poke(cmi_hdl_t hdl) 295 { 296 ASSERT(cmi_hdl_class(hdl) == CMI_HDL_NATIVE); 297 gcpu_ntv_mca_poll_wrapper(hdl, GCPU_MPT_WHAT_POKE_ERR); 298 } 299 300 void 301 gcpu_cmci_trap(cmi_hdl_t hdl) 302 { 303 gcpu_ntv_mca_poll_wrapper(hdl, GCPU_MPT_WHAT_CMCI_ERR); 304 } 305