Since machine checks and CMCIs can happen before Dom0 even gets constructed, the handlers of these events have to avoid de-referencing respective pointers without checking. Signed-off-by: Jan Beulich --- 2010-02-09.orig/xen/arch/x86/cpu/mcheck/amd_nonfatal.c 2010-01-13 18:58:11.000000000 +0100 +++ 2010-02-09/xen/arch/x86/cpu/mcheck/amd_nonfatal.c 2010-02-16 12:08:51.000000000 +0100 @@ -84,12 +84,9 @@ static void mce_amd_checkregs(void *info { mctelem_cookie_t mctc; struct mca_summary bs; - unsigned int event_enabled; mctc = mcheck_mca_logout(MCA_POLLER, mca_allbanks, &bs, NULL); - event_enabled = guest_enabled_event(dom0->vcpu[0], VIRQ_MCA); - if (bs.errcnt && mctc != NULL) { static uint64_t dumpcount = 0; @@ -101,7 +98,7 @@ static void mce_amd_checkregs(void *info * a simple-minded attempt to avoid spamming the console * for corrected errors in early startup. */ - if (event_enabled) { + if (dom0_vmce_enabled()) { mctelem_commit(mctc); send_guest_global_virq(dom0, VIRQ_MCA); } else if (++dumpcount >= 10) { @@ -136,7 +133,7 @@ static void mce_amd_work_fn(void *data) on_each_cpu(mce_amd_checkregs, data, 1); if (adjust > 0) { - if (!guest_enabled_event(dom0->vcpu[0], VIRQ_MCA) ) { + if (!dom0_vmce_enabled()) { /* Dom0 did not enable VIRQ_MCA, so Xen is reporting. */ printk("MCE: polling routine found correctable error. " " Use mcelog to parse above error output.\n"); --- 2010-02-09.orig/xen/arch/x86/cpu/mcheck/mce.c 2010-02-09 09:00:50.000000000 +0100 +++ 2010-02-09/xen/arch/x86/cpu/mcheck/mce.c 2010-02-16 12:17:29.000000000 +0100 @@ -414,7 +414,7 @@ void mcheck_cmn_handler(struct cpu_user_ * as terminal for any context. */ ctx_xen = SEG_PL(regs->cs) == 0; - ctx_dom0 = !ctx_xen && (domid == dom0->domain_id); + ctx_dom0 = !ctx_xen && (domid == 0); ctx_domU = !ctx_xen && !ctx_dom0; xen_state_lost = bs.uc != 0 || (ctx_xen && (bs.pcc || !ripv)) || @@ -463,7 +463,8 @@ void mcheck_cmn_handler(struct cpu_user_ * XXFM Could add some Solaris dom0 contract kill here? */ if (dom0_state_lost) { - if (guest_has_trap_callback(dom0, 0, TRAP_machine_check)) { + if (dom0 && dom0->max_vcpus && dom0->vcpu[0] && + guest_has_trap_callback(dom0, 0, TRAP_machine_check)) { dom_state = DOM0_TRAP; send_guest_trap(dom0, 0, TRAP_machine_check); /* XXFM case of return with !ripv ??? */ @@ -532,7 +533,7 @@ cmn_handler_done: if (bs.errcnt) { /* Not panicing, so forward telemetry to dom0 now if it * is interested. */ - if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) { + if (dom0_vmce_enabled()) { if (mctc != NULL) mctelem_commit(mctc); send_guest_global_virq(dom0, VIRQ_MCA); --- 2010-02-09.orig/xen/arch/x86/cpu/mcheck/mce.h 2010-02-03 16:15:15.000000000 +0100 +++ 2010-02-09/xen/arch/x86/cpu/mcheck/mce.h 2010-02-16 12:32:26.000000000 +0100 @@ -55,6 +55,8 @@ void mc_panic(char *s); void x86_mc_get_cpu_info(unsigned, uint32_t *, uint16_t *, uint16_t *, uint32_t *, uint32_t *, uint32_t *, uint32_t *); +#define dom0_vmce_enabled() (dom0 && dom0->max_vcpus && dom0->vcpu[0] \ + && guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) /* Register a handler for machine check exceptions. */ typedef void (*x86_mce_vector_t)(struct cpu_user_regs *, long); --- 2010-02-09.orig/xen/arch/x86/cpu/mcheck/mce_intel.c 2010-02-09 09:16:49.000000000 +0100 +++ 2010-02-09/xen/arch/x86/cpu/mcheck/mce_intel.c 2010-02-16 12:11:40.000000000 +0100 @@ -518,7 +518,7 @@ static void mce_softirq(void) } /* Step2: Send Log to DOM0 through vIRQ */ - if (dom0 && guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) { + if (dom0_vmce_enabled()) { mce_printk(MCE_VERBOSE, "MCE: send MCE# to DOM0 through virq\n"); send_guest_global_virq(dom0, VIRQ_MCA); } @@ -863,7 +863,7 @@ static void cmci_discover(void) MCA_CMCI_HANDLER, __get_cpu_var(mce_banks_owned), &bs, NULL); if (bs.errcnt && mctc != NULL) { - if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) { + if (dom0_vmce_enabled()) { mctelem_commit(mctc); send_guest_global_virq(dom0, VIRQ_MCA); } else { @@ -978,7 +978,7 @@ fastcall void smp_cmci_interrupt(struct MCA_CMCI_HANDLER, __get_cpu_var(mce_banks_owned), &bs, NULL); if (bs.errcnt && mctc != NULL) { - if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) { + if (dom0_vmce_enabled()) { mctelem_commit(mctc); mce_printk(MCE_VERBOSE, "CMCI: send CMCI to DOM0 through virq\n"); send_guest_global_virq(dom0, VIRQ_MCA); --- 2010-02-09.orig/xen/arch/x86/cpu/mcheck/non-fatal.c 2010-01-13 18:58:11.000000000 +0100 +++ 2010-02-09/xen/arch/x86/cpu/mcheck/non-fatal.c 2010-02-16 12:09:10.000000000 +0100 @@ -53,7 +53,7 @@ static void mce_checkregs (void *info) * for corrected errors in early startup. */ - if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) { + if (dom0_vmce_enabled()) { mctelem_commit(mctc); send_guest_global_virq(dom0, VIRQ_MCA); } else if (++dumpcount >= 10) {