Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / arch / x86 / kernel / cpu / mcheck / mce.c
index c614bd4..769363c 100644 (file)
@@ -118,8 +118,10 @@ void mce_setup(struct mce *m)
        m->time = get_seconds();
        m->cpuvendor = boot_cpu_data.x86_vendor;
        m->cpuid = cpuid_eax(1);
+#ifndef CONFIG_XEN
        m->socketid = cpu_data(m->extcpu).phys_proc_id;
        m->apicid = cpu_data(m->extcpu).initial_apicid;
+#endif
        rdmsrl(MSR_IA32_MCG_CAP, m->mcgcap);
 }
 
@@ -191,7 +193,7 @@ static void drain_mcelog_buffer(void)
 {
        unsigned int next, i, prev = 0;
 
-       next = rcu_dereference_check_mce(mcelog.next);
+       next = ACCESS_ONCE(mcelog.next);
 
        do {
                struct mce *m;
@@ -266,9 +268,14 @@ static void print_mce(struct mce *m)
         * Note this output is parsed by external tools and old fields
         * should not be changed.
         */
+#ifndef CONFIG_XEN
        pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x microcode %x\n",
                m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid,
                cpu_data(m->extcpu).microcode);
+#else
+       pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
+               m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid);
+#endif
 
        /*
         * Print out human-readable details about the MCE error,
@@ -945,9 +952,10 @@ struct mce_info {
        atomic_t                inuse;
        struct task_struct      *t;
        __u64                   paddr;
+       int                     restartable;
 } mce_info[MCE_INFO_MAX];
 
-static void mce_save_info(__u64 addr)
+static void mce_save_info(__u64 addr, int c)
 {
        struct mce_info *mi;
 
@@ -955,6 +963,7 @@ static void mce_save_info(__u64 addr)
                if (atomic_cmpxchg(&mi->inuse, 0, 1) == 0) {
                        mi->t = current;
                        mi->paddr = addr;
+                       mi->restartable = c;
                        return;
                }
        }
@@ -1130,7 +1139,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
                        mce_panic("Fatal machine check on current CPU", &m, msg);
                if (worst == MCE_AR_SEVERITY) {
                        /* schedule action before return to userland */
-                       mce_save_info(m.addr);
+                       mce_save_info(m.addr, m.mcgstatus & MCG_STATUS_RIPV);
                        set_thread_flag(TIF_MCE_NOTIFY);
                } else if (kill_it) {
                        force_sig(SIGBUS, current);
@@ -1179,7 +1188,13 @@ void mce_notify_process(void)
 
        pr_err("Uncorrected hardware memory error in user-access at %llx",
                 mi->paddr);
-       if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0) {
+       /*
+        * We must call memory_failure() here even if the current process is
+        * doomed. We still need to mark the page as poisoned and alert any
+        * other users of the page.
+        */
+       if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0 ||
+                          mi->restartable == 0) {
                pr_err("Memory error not recovered");
                force_sig(SIGBUS, current);
        }
@@ -1228,8 +1243,15 @@ void mce_log_therm_throt_event(__u64 status)
  * Periodic polling timer for "silent" machine check errors.  If the
  * poller finds an MCE, poll 2x faster.  When the poller finds no more
  * errors, poll 2x slower (up to check_interval seconds).
+ *
+ * We will disable polling in DOM0 since all CMCI/Polling
+ * mechanism will be done in XEN for Intel CPUs
  */
+#if defined (CONFIG_X86_XEN_MCE)
+static int check_interval = 0; /* disable polling */
+#else
 static int check_interval = 5 * 60; /* 5 minutes */
+#endif
 
 static DEFINE_PER_CPU(int, mce_next_interval); /* in jiffies */
 static DEFINE_PER_CPU(struct timer_list, mce_timer);
@@ -1402,6 +1424,7 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 
        /* This should be disabled by the BIOS, but isn't always */
        if (c->x86_vendor == X86_VENDOR_AMD) {
+#ifndef CONFIG_XEN
                if (c->x86 == 15 && banks > 4) {
                        /*
                         * disable GART TBL walk error reporting, which
@@ -1410,6 +1433,7 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
                         */
                        clear_bit(10, (unsigned long *)&mce_banks[4].ctl);
                }
+#endif
                if (c->x86 <= 17 && mce_bootlog < 0) {
                        /*
                         * Lots of broken BIOS around that don't clear them
@@ -1482,6 +1506,7 @@ static int __cpuinit __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c)
 
 static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
 {
+#ifndef CONFIG_X86_64_XEN
        switch (c->x86_vendor) {
        case X86_VENDOR_INTEL:
                mce_intel_feature_init(c);
@@ -1492,6 +1517,7 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
        default:
                break;
        }
+#endif
 }
 
 static void __mcheck_cpu_init_timer(void)
@@ -2280,6 +2306,16 @@ static __init int mcheck_init_device(void)
        /* register character device /dev/mcelog */
        misc_register(&mce_chrdev_device);
 
+#ifdef CONFIG_X86_XEN_MCE
+       if (is_initial_xendomain()) {
+               /* Register vIRQ handler for MCE LOG processing */
+               extern int bind_virq_for_mce(void);
+
+               printk(KERN_DEBUG "MCE: bind virq for DOM0 logging\n");
+               bind_virq_for_mce();
+       }
+#endif
+
        return err;
 }
 device_initcall(mcheck_init_device);