for (i = 0; i < ncpus; i++) if (g_physinfo[i].mc_apicid == m.apicid) break; if (unlikely(i == ncpus)) {
pr_warn("Failed to match cpu with apicid %d\n", m.apicid); return -ENODEV;
}
if (mic->type == MC_TYPE_BANK) {
mc_bank = (struct mcinfo_bank *)mic;
m.misc = mc_bank->mc_misc;
m.status = mc_bank->mc_status;
m.addr = mc_bank->mc_addr;
m.tsc = mc_bank->mc_tsc;
m.bank = mc_bank->mc_bank;
m.finished = 1; /*log this record*/
xen_mce_log(&m);
}
mic = x86_mcinfo_next(mic);
} while (1);
return0;
}
staticint mc_queue_handle(uint32_t flags)
{ struct xen_mc mc_op; int ret = 0;
mc_op.cmd = XEN_MC_fetch;
set_xen_guest_handle(mc_op.u.mc_fetch.data, &g_mi); do {
mc_op.u.mc_fetch.flags = flags;
ret = HYPERVISOR_mca(&mc_op); if (ret) {
pr_err("Failed to fetch %surgent error log\n",
flags == XEN_MC_URGENT ? "" : "non"); break;
}
if (mc_op.u.mc_fetch.flags & XEN_MC_NODATA ||
mc_op.u.mc_fetch.flags & XEN_MC_FETCHFAILED) break; else {
ret = convert_log(&g_mi); if (ret)
pr_warn("Failed to convert this error log, continue acking it anyway\n");
mc_op.u.mc_fetch.flags = flags | XEN_MC_ACK;
ret = HYPERVISOR_mca(&mc_op); if (ret) {
pr_err("Failed to ack previous error log\n"); break;
}
}
} while (1);
return ret;
}
/* virq handler for machine check error info*/ staticvoid xen_mce_work_fn(struct work_struct *work)
{ int err;
staticint bind_virq_for_mce(void)
{ int ret; struct xen_mc mc_op;
memset(&mc_op, 0, sizeof(struct xen_mc));
/* Fetch physical CPU Numbers */
mc_op.cmd = XEN_MC_physcpuinfo;
set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, g_physinfo);
ret = HYPERVISOR_mca(&mc_op); if (ret) {
pr_err("Failed to get CPU numbers\n"); return ret;
}
/* Fetch each CPU Physical Info for later reference*/
ncpus = mc_op.u.mc_physcpuinfo.ncpus;
g_physinfo = kcalloc(ncpus, sizeof(struct mcinfo_logical_cpu),
GFP_KERNEL); if (!g_physinfo) return -ENOMEM;
set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, g_physinfo);
ret = HYPERVISOR_mca(&mc_op); if (ret) {
pr_err("Failed to get CPU info\n");
kfree(g_physinfo); return ret;
}
ret = bind_virq_to_irqhandler(VIRQ_MCA, 0,
xen_mce_interrupt, 0, "mce", NULL); if (ret < 0) {
pr_err("Failed to bind virq\n");
kfree(g_physinfo); return ret;
}
return0;
}
staticint __init xen_late_init_mcelog(void)
{ int ret;
/* Only DOM0 is responsible for MCE logging */ if (!xen_initial_domain()) return -ENODEV;
/* register character device /dev/mcelog for xen mcelog */
ret = misc_register(&xen_mce_chrdev_device); if (ret) return ret;
ret = bind_virq_for_mce(); if (ret) goto deregister;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.