示例#1
0
static int xen_smp_intr_init(unsigned int cpu)
{
	int rc;
	const char *resched_name, *callfunc_name, *debug_name;

	resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
	rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
				    cpu,
				    xen_reschedule_interrupt,
				    IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
				    resched_name,
				    NULL);
	if (rc < 0)
		goto fail;
	per_cpu(resched_irq, cpu) = rc;

	callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu);
	rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR,
				    cpu,
				    xen_call_function_interrupt,
				    IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
				    callfunc_name,
				    NULL);
	if (rc < 0)
		goto fail;
	per_cpu(callfunc_irq, cpu) = rc;

	debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
	rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt,
				     IRQF_DISABLED | IRQF_PERCPU | IRQF_NOBALANCING,
				     debug_name, NULL);
	if (rc < 0)
		goto fail;
	per_cpu(debug_irq, cpu) = rc;

	callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu);
	rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR,
				    cpu,
				    xen_call_function_single_interrupt,
				    IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
				    callfunc_name,
				    NULL);
	if (rc < 0)
		goto fail;
	per_cpu(callfuncsingle_irq, cpu) = rc;

	return 0;

 fail:
	if (per_cpu(resched_irq, cpu) >= 0)
		unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
	if (per_cpu(callfunc_irq, cpu) >= 0)
		unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
	if (per_cpu(debug_irq, cpu) >= 0)
		unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL);
	if (per_cpu(callfuncsingle_irq, cpu) >= 0)
		unbind_from_irqhandler(per_cpu(callfuncsingle_irq, cpu), NULL);

	return rc;
}
示例#2
0
int xen_smp_intr_init_pv(unsigned int cpu)
{
	int rc;
	char *callfunc_name, *pmu_name;

	callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
	rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
				    cpu,
				    xen_irq_work_interrupt,
				    IRQF_PERCPU|IRQF_NOBALANCING,
				    callfunc_name,
				    NULL);
	if (rc < 0)
		goto fail;
	per_cpu(xen_irq_work, cpu).irq = rc;
	per_cpu(xen_irq_work, cpu).name = callfunc_name;

	if (is_xen_pmu(cpu)) {
		pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu);
		rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu,
					     xen_pmu_irq_handler,
					     IRQF_PERCPU|IRQF_NOBALANCING,
					     pmu_name, NULL);
		if (rc < 0)
			goto fail;
		per_cpu(xen_pmu_irq, cpu).irq = rc;
		per_cpu(xen_pmu_irq, cpu).name = pmu_name;
	}

	return 0;

 fail:
	xen_smp_intr_free_pv(cpu);
	return rc;
}
示例#3
0
void xen_init_lock_cpu(int cpu)
{
	int irq;
	char *name;

	if (!xen_pvspin)
		return;

	WARN(per_cpu(lock_kicker_irq, cpu) >= 0, "spinlock on CPU%d exists on IRQ%d!\n",
	     cpu, per_cpu(lock_kicker_irq, cpu));

	name = kasprintf(GFP_KERNEL, "spinlock%d", cpu);
	irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR,
				     cpu,
				     dummy_handler,
				     IRQF_PERCPU|IRQF_NOBALANCING,
				     name,
				     NULL);

	if (irq >= 0) {
		disable_irq(irq); /* make sure it's never delivered */
		per_cpu(lock_kicker_irq, cpu) = irq;
		per_cpu(irq_name, cpu) = name;
	}

	printk("cpu %d spinlock event irq %d\n", cpu, irq);
}
示例#4
0
static int
xen_smp_intr_init(unsigned int cpu)
{
	int rc;
	unsigned int irq;
	
	per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1;

	sprintf(resched_name[cpu], "resched%u", cpu);
	rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR,
				    cpu,
				    resched_name[cpu],
				    smp_reschedule_interrupt,
	    INTR_TYPE_TTY, &irq);

	printf("[XEN] IPI cpu=%d irq=%d vector=RESCHEDULE_VECTOR (%d)\n",
	    cpu, irq, RESCHEDULE_VECTOR);
	
	per_cpu(resched_irq, cpu) = irq;

	sprintf(callfunc_name[cpu], "callfunc%u", cpu);
	rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR,
				    cpu,
				    callfunc_name[cpu],
				    smp_call_function_interrupt,
	    INTR_TYPE_TTY, &irq);
	if (rc < 0)
		goto fail;
	per_cpu(callfunc_irq, cpu) = irq;

	printf("[XEN] IPI cpu=%d irq=%d vector=CALL_FUNCTION_VECTOR (%d)\n",
	    cpu, irq, CALL_FUNCTION_VECTOR);

	
	if ((cpu != 0) && ((rc = ap_cpu_initclocks(cpu)) != 0))
		goto fail;

	return 0;

 fail:
	if (per_cpu(resched_irq, cpu) >= 0)
		unbind_from_irqhandler(per_cpu(resched_irq, cpu));
	if (per_cpu(callfunc_irq, cpu) >= 0)
		unbind_from_irqhandler(per_cpu(callfunc_irq, cpu));
	return rc;
}
示例#5
0
/*
 * This is xen version percpu irq registration, which needs bind
 * to xen specific evtchn sub-system. One trick here is that xen
 * evtchn binding interface depends on kmalloc because related
 * port needs to be freed at device/cpu down. So we cache the
 * registration on BSP before slab is ready and then deal them
 * at later point. For rest instances happening after slab ready,
 * we hook them to xen evtchn immediately.
 *
 * FIXME: MCA is not supported by far, and thus "nomca" boot param is
 * required.
 */
static void
__xen_register_percpu_irq(unsigned int cpu, unsigned int vec,
			struct irqaction *action, int save)
{
	struct irq_desc *desc;
	int irq = 0;

	if (xen_slab_ready) {
		switch (vec) {
		case IA64_TIMER_VECTOR:
			snprintf(per_cpu(xen_timer_name, cpu),
				 sizeof(per_cpu(xen_timer_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu,
				action->handler, action->flags,
				per_cpu(xen_timer_name, cpu), action->dev_id);
			per_cpu(xen_timer_irq, cpu) = irq;
			break;
		case IA64_IPI_RESCHEDULE:
			snprintf(per_cpu(xen_resched_name, cpu),
				 sizeof(per_cpu(xen_resched_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, cpu,
				action->handler, action->flags,
				per_cpu(xen_resched_name, cpu), action->dev_id);
			per_cpu(xen_resched_irq, cpu) = irq;
			break;
		case IA64_IPI_VECTOR:
			snprintf(per_cpu(xen_ipi_name, cpu),
				 sizeof(per_cpu(xen_ipi_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_ipi_to_irqhandler(XEN_IPI_VECTOR, cpu,
				action->handler, action->flags,
				per_cpu(xen_ipi_name, cpu), action->dev_id);
			per_cpu(xen_ipi_irq, cpu) = irq;
			break;
		case IA64_CMC_VECTOR:
			snprintf(per_cpu(xen_cmc_name, cpu),
				 sizeof(per_cpu(xen_cmc_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu,
						action->handler,
						action->flags,
						per_cpu(xen_cmc_name, cpu),
						action->dev_id);
			per_cpu(xen_cmc_irq, cpu) = irq;
			break;
		case IA64_CMCP_VECTOR:
			snprintf(per_cpu(xen_cmcp_name, cpu),
				 sizeof(per_cpu(xen_cmcp_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_ipi_to_irqhandler(XEN_CMCP_VECTOR, cpu,
						action->handler,
						action->flags,
						per_cpu(xen_cmcp_name, cpu),
						action->dev_id);
			per_cpu(xen_cmcp_irq, cpu) = irq;
			break;
		case IA64_CPEP_VECTOR:
			snprintf(per_cpu(xen_cpep_name, cpu),
				 sizeof(per_cpu(xen_cpep_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_ipi_to_irqhandler(XEN_CPEP_VECTOR, cpu,
						action->handler,
						action->flags,
						per_cpu(xen_cpep_name, cpu),
						action->dev_id);
			per_cpu(xen_cpep_irq, cpu) = irq;
			break;
		case IA64_CPE_VECTOR:
		case IA64_MCA_RENDEZ_VECTOR:
		case IA64_PERFMON_VECTOR:
		case IA64_MCA_WAKEUP_VECTOR:
		case IA64_SPURIOUS_INT_VECTOR:
			/* No need to complain, these aren't supported. */
			break;
		default:
			printk(KERN_WARNING "Percpu irq %d is unsupported "
			       "by xen!\n", vec);
			break;
		}
		BUG_ON(irq < 0);

		if (irq > 0) {
			/*
			 * Mark percpu.  Without this, migrate_irqs() will
			 * mark the interrupt for migrations and trigger it
			 * on cpu hotplug.
			 */
			desc = irq_desc + irq;
			desc->status |= IRQ_PER_CPU;
		}
	}

	/* For BSP, we cache registered percpu irqs, and then re-walk
	 * them when initializing APs
	 */
	if (!cpu && save) {
		BUG_ON(saved_irq_cnt == MAX_LATE_IRQ);
		saved_percpu_irqs[saved_irq_cnt].irq = vec;
		saved_percpu_irqs[saved_irq_cnt].action = action;
		saved_irq_cnt++;
		if (!xen_slab_ready)
			late_irq_cnt++;
	}
}
示例#6
0
static void
__xen_register_percpu_irq(unsigned int cpu, unsigned int vec,
			struct irqaction *action, int save)
{
	int irq = 0;

	if (xen_slab_ready) {
		switch (vec) {
		case IA64_TIMER_VECTOR:
			snprintf(per_cpu(xen_timer_name, cpu),
				 sizeof(per_cpu(xen_timer_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu,
				action->handler, action->flags,
				per_cpu(xen_timer_name, cpu), action->dev_id);
			per_cpu(xen_timer_irq, cpu) = irq;
			break;
		case IA64_IPI_RESCHEDULE:
			snprintf(per_cpu(xen_resched_name, cpu),
				 sizeof(per_cpu(xen_resched_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, cpu,
				action->handler, action->flags,
				per_cpu(xen_resched_name, cpu), action->dev_id);
			per_cpu(xen_resched_irq, cpu) = irq;
			break;
		case IA64_IPI_VECTOR:
			snprintf(per_cpu(xen_ipi_name, cpu),
				 sizeof(per_cpu(xen_ipi_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_ipi_to_irqhandler(XEN_IPI_VECTOR, cpu,
				action->handler, action->flags,
				per_cpu(xen_ipi_name, cpu), action->dev_id);
			per_cpu(xen_ipi_irq, cpu) = irq;
			break;
		case IA64_CMC_VECTOR:
			snprintf(per_cpu(xen_cmc_name, cpu),
				 sizeof(per_cpu(xen_cmc_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu,
						action->handler,
						action->flags,
						per_cpu(xen_cmc_name, cpu),
						action->dev_id);
			per_cpu(xen_cmc_irq, cpu) = irq;
			break;
		case IA64_CMCP_VECTOR:
			snprintf(per_cpu(xen_cmcp_name, cpu),
				 sizeof(per_cpu(xen_cmcp_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_ipi_to_irqhandler(XEN_CMCP_VECTOR, cpu,
						action->handler,
						action->flags,
						per_cpu(xen_cmcp_name, cpu),
						action->dev_id);
			per_cpu(xen_cmcp_irq, cpu) = irq;
			break;
		case IA64_CPEP_VECTOR:
			snprintf(per_cpu(xen_cpep_name, cpu),
				 sizeof(per_cpu(xen_cpep_name, cpu)),
				 "%s%d", action->name, cpu);
			irq = bind_ipi_to_irqhandler(XEN_CPEP_VECTOR, cpu,
						action->handler,
						action->flags,
						per_cpu(xen_cpep_name, cpu),
						action->dev_id);
			per_cpu(xen_cpep_irq, cpu) = irq;
			break;
		case IA64_CPE_VECTOR:
		case IA64_MCA_RENDEZ_VECTOR:
		case IA64_PERFMON_VECTOR:
		case IA64_MCA_WAKEUP_VECTOR:
		case IA64_SPURIOUS_INT_VECTOR:
			/*                                              */
			break;
		default:
			printk(KERN_WARNING "Percpu irq %d is unsupported "
			       "by xen!\n", vec);
			break;
		}
		BUG_ON(irq < 0);

		if (irq > 0) {
			/*
                                                     
                                                      
                     
    */
			irq_set_status_flags(irq, IRQ_PER_CPU);
		}
	}

	/*                                                           
                              
  */
	if (!cpu && save) {
		BUG_ON(saved_irq_cnt == MAX_LATE_IRQ);
		saved_percpu_irqs[saved_irq_cnt].irq = vec;
		saved_percpu_irqs[saved_irq_cnt].action = action;
		saved_irq_cnt++;
		if (!xen_slab_ready)
			late_irq_cnt++;
	}
}
示例#7
0
文件: smp.c 项目: garyvan/openwrt-1.6
static int xen_smp_intr_init(unsigned int cpu)
{
	int rc;
	const char *resched_name, *callfunc_name, *debug_name;

	resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
	rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
				    cpu,
				    xen_reschedule_interrupt,
				    IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
				    resched_name,
				    NULL);
	if (rc < 0)
		goto fail;
	per_cpu(xen_resched_irq, cpu) = rc;

	callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu);
	rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR,
				    cpu,
				    xen_call_function_interrupt,
				    IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
				    callfunc_name,
				    NULL);
	if (rc < 0)
		goto fail;
	per_cpu(xen_callfunc_irq, cpu) = rc;

	debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
	rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt,
				     IRQF_DISABLED | IRQF_PERCPU | IRQF_NOBALANCING,
				     debug_name, NULL);
	if (rc < 0)
		goto fail;
	per_cpu(xen_debug_irq, cpu) = rc;

	callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu);
	rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR,
				    cpu,
				    xen_call_function_single_interrupt,
				    IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
				    callfunc_name,
				    NULL);
	if (rc < 0)
		goto fail;
	per_cpu(xen_callfuncsingle_irq, cpu) = rc;

	/*
	 * The IRQ worker on PVHVM goes through the native path and uses the
	 * IPI mechanism.
	 */
	if (xen_hvm_domain())
		return 0;

	callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
	rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
				    cpu,
				    xen_irq_work_interrupt,
				    IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
				    callfunc_name,
				    NULL);
	if (rc < 0)
		goto fail;
	per_cpu(xen_irq_work, cpu) = rc;

	return 0;

 fail:
	if (per_cpu(xen_resched_irq, cpu) >= 0)
		unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL);
	if (per_cpu(xen_callfunc_irq, cpu) >= 0)
		unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
	if (per_cpu(xen_debug_irq, cpu) >= 0)
		unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
	if (per_cpu(xen_callfuncsingle_irq, cpu) >= 0)
		unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu),
				       NULL);
	if (xen_hvm_domain())
		return rc;

	if (per_cpu(xen_irq_work, cpu) >= 0)
		unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);

	return rc;
}