mce.c (36df96f8acaf51992177645eb2d781f766ce97dc) mce.c (b5ff4211a8294be2ddbaf963fa3666fa042292a8)
1/*
2 * Machine check exception handling.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *

--- 17 unchanged lines hidden (view full) ---

26#include <linux/ptrace.h>
27#include <linux/percpu.h>
28#include <linux/export.h>
29#include <asm/mce.h>
30
31static DEFINE_PER_CPU(int, mce_nest_count);
32static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event);
33
1/*
2 * Machine check exception handling.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *

--- 17 unchanged lines hidden (view full) ---

26#include <linux/ptrace.h>
27#include <linux/percpu.h>
28#include <linux/export.h>
29#include <asm/mce.h>
30
31static DEFINE_PER_CPU(int, mce_nest_count);
32static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event);
33
34/* Queue for delayed MCE events. */
35static DEFINE_PER_CPU(int, mce_queue_count);
36static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event_queue);
37
34static void mce_set_error_info(struct machine_check_event *mce,
35 struct mce_error_info *mce_err)
36{
37 mce->error_type = mce_err->error_type;
38 switch (mce_err->error_type) {
39 case MCE_ERROR_TYPE_UE:
40 mce->u.ue_error.ue_error_type = mce_err->u.ue_error_type;
41 break;

--- 115 unchanged lines hidden (view full) ---

157
158 return ret;
159}
160
161void release_mce_event(void)
162{
163 get_mce_event(NULL, true);
164}
38static void mce_set_error_info(struct machine_check_event *mce,
39 struct mce_error_info *mce_err)
40{
41 mce->error_type = mce_err->error_type;
42 switch (mce_err->error_type) {
43 case MCE_ERROR_TYPE_UE:
44 mce->u.ue_error.ue_error_type = mce_err->u.ue_error_type;
45 break;

--- 115 unchanged lines hidden (view full) ---

161
162 return ret;
163}
164
165void release_mce_event(void)
166{
167 get_mce_event(NULL, true);
168}
169
170/*
171 * Queue up the MCE event which then can be handled later.
172 */
173void machine_check_queue_event(void)
174{
175 int index;
176 struct machine_check_event evt;
177
178 if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
179 return;
180
181 index = __get_cpu_var(mce_queue_count)++;
182 /* If queue is full, just return for now. */
183 if (index >= MAX_MC_EVT) {
184 __get_cpu_var(mce_queue_count)--;
185 return;
186 }
187 __get_cpu_var(mce_event_queue[index]) = evt;
188}
189
190/*
191 * process pending MCE event from the mce event queue. This function will be
192 * called during syscall exit.
193 */
194void machine_check_process_queued_event(void)
195{
196 int index;
197
198 preempt_disable();
199 /*
200 * For now just print it to console.
201 * TODO: log this error event to FSP or nvram.
202 */
203 while (__get_cpu_var(mce_queue_count) > 0) {
204 index = __get_cpu_var(mce_queue_count) - 1;
205 machine_check_print_event_info(
206 &__get_cpu_var(mce_event_queue[index]));
207 __get_cpu_var(mce_queue_count)--;
208 }
209 preempt_enable();
210}
211
212void machine_check_print_event_info(struct machine_check_event *evt)
213{
214 const char *level, *sevstr, *subtype;
215 static const char *mc_ue_types[] = {
216 "Indeterminate",
217 "Instruction fetch",
218 "Page table walk ifetch",
219 "Load/Store",
220 "Page table walk Load/Store",
221 };
222 static const char *mc_slb_types[] = {
223 "Indeterminate",
224 "Parity",
225 "Multihit",
226 };
227 static const char *mc_erat_types[] = {
228 "Indeterminate",
229 "Parity",
230 "Multihit",
231 };
232 static const char *mc_tlb_types[] = {
233 "Indeterminate",
234 "Parity",
235 "Multihit",
236 };
237
238 /* Print things out */
239 if (evt->version != MCE_V1) {
240 pr_err("Machine Check Exception, Unknown event version %d !\n",
241 evt->version);
242 return;
243 }
244 switch (evt->severity) {
245 case MCE_SEV_NO_ERROR:
246 level = KERN_INFO;
247 sevstr = "Harmless";
248 break;
249 case MCE_SEV_WARNING:
250 level = KERN_WARNING;
251 sevstr = "";
252 break;
253 case MCE_SEV_ERROR_SYNC:
254 level = KERN_ERR;
255 sevstr = "Severe";
256 break;
257 case MCE_SEV_FATAL:
258 default:
259 level = KERN_ERR;
260 sevstr = "Fatal";
261 break;
262 }
263
264 printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
265 evt->disposition == MCE_DISPOSITION_RECOVERED ?
266 "Recovered" : "[Not recovered");
267 printk("%s Initiator: %s\n", level,
268 evt->initiator == MCE_INITIATOR_CPU ? "CPU" : "Unknown");
269 switch (evt->error_type) {
270 case MCE_ERROR_TYPE_UE:
271 subtype = evt->u.ue_error.ue_error_type <
272 ARRAY_SIZE(mc_ue_types) ?
273 mc_ue_types[evt->u.ue_error.ue_error_type]
274 : "Unknown";
275 printk("%s Error type: UE [%s]\n", level, subtype);
276 if (evt->u.ue_error.effective_address_provided)
277 printk("%s Effective address: %016llx\n",
278 level, evt->u.ue_error.effective_address);
279 if (evt->u.ue_error.physical_address_provided)
280 printk("%s Physial address: %016llx\n",
281 level, evt->u.ue_error.physical_address);
282 break;
283 case MCE_ERROR_TYPE_SLB:
284 subtype = evt->u.slb_error.slb_error_type <
285 ARRAY_SIZE(mc_slb_types) ?
286 mc_slb_types[evt->u.slb_error.slb_error_type]
287 : "Unknown";
288 printk("%s Error type: SLB [%s]\n", level, subtype);
289 if (evt->u.slb_error.effective_address_provided)
290 printk("%s Effective address: %016llx\n",
291 level, evt->u.slb_error.effective_address);
292 break;
293 case MCE_ERROR_TYPE_ERAT:
294 subtype = evt->u.erat_error.erat_error_type <
295 ARRAY_SIZE(mc_erat_types) ?
296 mc_erat_types[evt->u.erat_error.erat_error_type]
297 : "Unknown";
298 printk("%s Error type: ERAT [%s]\n", level, subtype);
299 if (evt->u.erat_error.effective_address_provided)
300 printk("%s Effective address: %016llx\n",
301 level, evt->u.erat_error.effective_address);
302 break;
303 case MCE_ERROR_TYPE_TLB:
304 subtype = evt->u.tlb_error.tlb_error_type <
305 ARRAY_SIZE(mc_tlb_types) ?
306 mc_tlb_types[evt->u.tlb_error.tlb_error_type]
307 : "Unknown";
308 printk("%s Error type: TLB [%s]\n", level, subtype);
309 if (evt->u.tlb_error.effective_address_provided)
310 printk("%s Effective address: %016llx\n",
311 level, evt->u.tlb_error.effective_address);
312 break;
313 default:
314 case MCE_ERROR_TYPE_UNKNOWN:
315 printk("%s Error type: Unknown\n", level);
316 break;
317 }
318}