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; }
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; }
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); }
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; }
/* * 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++; } }
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++; } }
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; }