*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/sched.h>
ISOLATE_NONE
} isolate_status_t;
+typedef enum {
+ MCA_NOT_RECOVERED = 0,
+ MCA_RECOVERED = 1
+} recovery_status_t;
+
/*
* This pool keeps pointers to the section part of SAL error record
*/
int max_idx; /* Maximum index of section pointer list pool */
} slidx_pool;
+static int
+fatal_mca(const char *fmt, ...)
+{
+ va_list args;
+ char buf[256];
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ ia64_mca_printk(KERN_ALERT "MCA: %s\n", buf);
+
+ return MCA_NOT_RECOVERED;
+}
+
+static int
+mca_recovered(const char *fmt, ...)
+{
+ va_list args;
+ char buf[256];
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ ia64_mca_printk(KERN_INFO "MCA: %s\n", buf);
+
+ return MCA_RECOVERED;
+}
+
/**
* mca_page_isolate - isolate a poisoned page in order not to use it later
* @paddr: poisoned memory location
void
mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr)
{
+ ia64_mlogbuf_dump();
printk(KERN_ERR "OS_MCA: process [cpu %d, pid: %d, uid: %d, "
"iip: %p, psr: 0x%lx,paddr: 0x%lx](%s) encounters MCA.\n",
raw_smp_processor_id(), current->pid, current->uid,
/* Is target address valid? */
if (!pbci->tv)
- return 0;
+ return fatal_mca("target address not valid");
/*
* cpu read or memory-mapped io read
/* Is minstate valid? */
if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate))
- return 0;
+ return fatal_mca("minstate not valid");
psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
psr2 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_xpsr);
psr2->bn = 1;
psr2->i = 0;
- return 1;
+ return mca_recovered("user memory corruption. "
+ "kill affected process - recovered.");
}
}
- return 0;
+ return fatal_mca("kernel context not recovered, iip 0x%lx\n",
+ pmsa->pmsa_iip);
}
/**
* The machine check is corrected.
*/
if (psp->cm == 1)
- return 1;
+ return mca_recovered("machine check is already corrected.");
/*
* The error was not contained. Software must be reset.
*/
if (psp->us || psp->ci == 0)
- return 0;
+ return fatal_mca("error not contained");
/*
* The cache check and bus check bits have four possible states
* 1 1 Memory error, attempt recovery
*/
if (psp->bc == 0 || pbci == NULL)
- return 0;
+ return fatal_mca("No bus check");
/*
* Sorry, we cannot handle so many.
*/
if (peidx_bus_check_num(peidx) > 1)
- return 0;
+ return fatal_mca("Too many bus checks");
/*
* Well, here is only one bus error.
*/
- if (pbci->ib || pbci->cc)
- return 0;
+ if (pbci->ib)
+ return fatal_mca("Internal Bus error");
+ if (pbci->cc)
+ return fatal_mca("Cache-cache error");
if (pbci->eb && pbci->bsi > 0)
- return 0;
+ return fatal_mca("External bus check fatal status");
/*
* This is a local MCA and estimated as recoverble external bus error.
/*
* On account of strange SAL error record, we cannot recover.
*/
- return 0;
+ return fatal_mca("Strange SAL record");
}
/**
/* Now, OS can recover when there is one processor error section */
if (n_proc_err > 1)
- return 0;
- else if (n_proc_err == 0) {
- /* Weird SAL record ... We need not to recover */
-
- return 1;
- }
+ return fatal_mca("Too Many Errors");
+ else if (n_proc_err == 0)
+ /* Weird SAL record ... We can't do anything */
+ return fatal_mca("Weird SAL record");
/* Make index of processor error section */
mca_make_peidx((sal_log_processor_info_t*)
/* Check whether MCA is global or not */
if (is_mca_global(&peidx, &pbci, sos))
- return 0;
+ return fatal_mca("global MCA");
/* Try to recover a processor error */
return recover_from_processor_error(platform_err, &slidx, &peidx,