예제 #1
0
int __init bind_virq_for_mce(void)
{
	int ret;
	xen_mc_t mc_op;

	g_mi = kmalloc(sizeof(*g_mi), GFP_KERNEL);
	if (!g_mi)
		return -ENOMEM;

	/* fetch physical CPU count */
	mc_op.cmd = XEN_MC_physcpuinfo;
	mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
	set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, NULL);
	ret = HYPERVISOR_mca(&mc_op);
	if (ret) {
		printk(KERN_ERR "MCE: Failed to get physical CPU count\n");
		kfree(g_mi);
		return ret;
	}

	/* fetch CPU physical info for later reference */
	ncpus = mc_op.u.mc_physcpuinfo.ncpus;
	g_physinfo = kmalloc(sizeof(*g_physinfo) * ncpus, GFP_KERNEL);
	if (!g_physinfo) {
		kfree(g_mi);
		return -ENOMEM;
	}
	set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, g_physinfo);
	ret = HYPERVISOR_mca(&mc_op);
	if (ret) {
		printk(KERN_ERR "MCE: Failed to get physical CPUs' info\n");
		kfree(g_mi);
		kfree(g_physinfo);
		return ret;
	}

	ret  = bind_virq_to_irqhandler(VIRQ_MCA, 0, 
		mce_dom0_interrupt, 0, "mce", NULL);

	if (ret < 0) {
		printk(KERN_ERR "MCE: Failed to bind vIRQ for Dom0\n");
		kfree(g_mi);
		kfree(g_physinfo);
		return ret;
	}

	/* Log the machine checks left over from the previous reset. */
	mce_dom0_interrupt(VIRQ_MCA, NULL);

	return 0;
}
예제 #2
0
파일: mcelog.c 프로젝트: 383530895/linux
static int 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;
	mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
	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;
	}

	return 0;
}
예제 #3
0
파일: mcelog.c 프로젝트: 383530895/linux
static int mc_queue_handle(uint32_t flags)
{
	struct xen_mc mc_op;
	int ret = 0;

	mc_op.cmd = XEN_MC_fetch;
	mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
	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;
}
예제 #4
0
int
xen_get_mc_physcpuinfo(xen_mc_logical_cpu_t *log_cpus, uint_t *ncpus)
{
	xen_mc_t xmc;
	struct xen_mc_physcpuinfo *cpi = &xmc.u.mc_physcpuinfo;

	cpi->ncpus = *ncpus;
	/*LINTED: constant in conditional context*/
	set_xen_guest_handle(cpi->info, log_cpus);

	if (HYPERVISOR_mca(XEN_MC_physcpuinfo, &xmc) != 0)
		return (-1);

	*ncpus = cpi->ncpus;
	return (0);
}
예제 #5
0
static irqreturn_t mce_dom0_interrupt(int irq, void *dev_id)
{
	xen_mc_t mc_op;
	int result = 0;

	printk(KERN_DEBUG "MCE_DOM0_LOG: enter dom0 mce vIRQ handler\n");
	mc_op.cmd = XEN_MC_fetch;
	mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
	set_xen_guest_handle(mc_op.u.mc_fetch.data, g_mi);
urgent:
	mc_op.u.mc_fetch.flags = XEN_MC_URGENT;
	result = HYPERVISOR_mca(&mc_op);
	if (result || mc_op.u.mc_fetch.flags & XEN_MC_NODATA ||
			mc_op.u.mc_fetch.flags & XEN_MC_FETCHFAILED)
	{
		printk(KERN_DEBUG "MCE_DOM0_LOG: No more urgent data\n");
		goto nonurgent;
	}
	else
	{
		result = convert_log(g_mi);
		if (result) {
			printk(KERN_ERR "MCE_DOM0_LOG: Log conversion failed\n");
			goto end;
		}
		/* After fetching the telem from DOM0, we need to dec the telem's
		 * refcnt and release the entry. The telem is reserved and inc
		 * refcnt when filling the telem.
		 */
		mc_op.u.mc_fetch.flags = XEN_MC_URGENT | XEN_MC_ACK;
		result = HYPERVISOR_mca(&mc_op);

		goto urgent;
	}
nonurgent:
	mc_op.u.mc_fetch.flags = XEN_MC_NONURGENT;
	result = HYPERVISOR_mca(&mc_op);
	if (result || mc_op.u.mc_fetch.flags & XEN_MC_NODATA ||
			mc_op.u.mc_fetch.flags & XEN_MC_FETCHFAILED)
	{
		printk(KERN_DEBUG "MCE_DOM0_LOG: No more nonurgent data\n");
		goto end;
	}
	else
	{
		result = convert_log(g_mi);
		if (result) {
			printk(KERN_ERR "MCE_DOM0_LOG: Log conversion failed\n");
			goto end;
		}
		/* After fetching the telem from DOM0, we need to dec the telem's
		 * refcnt and release the entry. The telem is reserved and inc
		 * refcnt when filling the telem.
		 */
		mc_op.u.mc_fetch.flags = XEN_MC_NONURGENT | XEN_MC_ACK;
		result = HYPERVISOR_mca(&mc_op);

		goto nonurgent;
	}
end:
	return IRQ_HANDLED;
}