xref: /illumos-gate/usr/src/uts/i86pc/cpu/generic_cpu/gcpu_poll_ntv.c (revision e4b86885570d77af552e9cf94f142f4d744fb8c8)
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