if ( already_pending )
return;
- vgic_vcpu_inject_irq(v, v->domain->arch.evtchn_irq);
+ vgic_inject_irq(v->domain, v, v->domain->arch.evtchn_irq, true);
}
/* The ARM spec declares that even if local irqs are masked in
* the CPSR register, an irq should wake up a cpu from WFI anyway.
* For this reason we need to check for irqs that need delivery,
* ignoring the CPSR register, *after* calling SCHEDOP_block to
- * avoid races with vgic_vcpu_inject_irq.
+ * avoid races with vgic_inject_irq.
*/
void vcpu_block_unless_event_pending(struct vcpu *v)
{
if ( vcpu_id >= d->max_vcpus )
return;
- vgic_vcpu_inject_irq(d->vcpu[vcpu_id], virq);
+ vgic_inject_irq(d, d->vcpu[vcpu_id], virq, true);
}
/*
* The irq cannot be a PPI, we only support delivery of SPIs to
* guests.
*/
- vgic_vcpu_inject_spi(info->d, info->virq);
+ vgic_inject_irq(info->d, NULL, info->virq, true);
goto out_no_end;
}
current->arch.virt_timer.ctl = READ_SYSREG32(CNTV_CTL_EL0);
WRITE_SYSREG32(current->arch.virt_timer.ctl | CNTx_CTL_MASK, CNTV_CTL_EL0);
- vgic_vcpu_inject_irq(current, current->arch.virt_timer.irq);
+ vgic_inject_irq(current->domain, current, current->arch.virt_timer.irq, true);
}
/*
vgic_remove_irq_from_queues(old, p);
irq_set_affinity(p->desc, cpumask_of(new->processor));
spin_unlock_irqrestore(&old->arch.vgic.lock, flags);
- vgic_vcpu_inject_irq(new, irq);
+ vgic_inject_irq(new->domain, new, irq, true);
return true;
}
/* if the IRQ is in a GICH_LR register, set GIC_IRQ_GUEST_MIGRATING
sgir, target->list);
continue;
}
- vgic_vcpu_inject_irq(d->vcpu[vcpuid], virq);
+ vgic_inject_irq(d, d->vcpu[vcpuid], virq, true);
}
break;
case SGI_TARGET_OTHERS:
{
if ( i != current->vcpu_id && d->vcpu[i] != NULL &&
is_vcpu_online(d->vcpu[i]) )
- vgic_vcpu_inject_irq(d->vcpu[i], virq);
+ vgic_inject_irq(d, d->vcpu[i], virq, true);
}
break;
case SGI_TARGET_SELF:
perfc_incr(vgic_sgi_self);
- vgic_vcpu_inject_irq(d->vcpu[current->vcpu_id], virq);
+ vgic_inject_irq(d, current, virq, true);
break;
default:
gprintk(XENLOG_WARNING,
gic_remove_from_lr_pending(v, p);
}
-void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq)
+void vgic_inject_irq(struct domain *d, struct vcpu *v, unsigned int virq,
+ bool level)
{
uint8_t priority;
struct pending_irq *iter, *n;
unsigned long flags;
bool running;
+ /*
+ * For edge triggered interrupts we always ignore a "falling edge".
+ * For level triggered interrupts we shouldn't, but do anyways.
+ */
+ if ( !level )
+ return;
+
+ if ( !v )
+ {
+ /* The IRQ needs to be an SPI if no vCPU is specified. */
+ ASSERT(virq >= 32 && virq <= vgic_num_irqs(d));
+
+ v = vgic_get_target_vcpu(d->vcpu[0], virq);
+ };
+
spin_lock_irqsave(&v->arch.vgic.lock, flags);
n = irq_to_pending(v, virq);
perfc_incr(vgic_cross_cpu_intr_inject);
smp_send_event_check_mask(cpumask_of(v->processor));
}
-}
-
-void vgic_vcpu_inject_spi(struct domain *d, unsigned int virq)
-{
- struct vcpu *v;
-
- /* the IRQ needs to be an SPI */
- ASSERT(virq >= 32 && virq <= vgic_num_irqs(d));
- v = vgic_get_target_vcpu(d->vcpu[0], virq);
- vgic_vcpu_inject_irq(v, virq);
+ return;
}
void arch_evtchn_inject(struct vcpu *v)
{
- vgic_vcpu_inject_irq(v, v->domain->arch.evtchn_irq);
+ vgic_inject_irq(v->domain, v, v->domain->arch.evtchn_irq, true);
}
bool vgic_evtchn_irq_pending(struct vcpu *v)
* status bit has been set since the last time.
*/
if ( uartmis & ~vpl011->shadow_uartmis )
- vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI);
+ vgic_inject_irq(d, NULL, GUEST_VPL011_SPI, true);
vpl011->shadow_uartmis = uartmis;
}
if ( !(t->ctl & CNTx_CTL_MASK) )
{
perfc_incr(vtimer_phys_inject);
- vgic_vcpu_inject_irq(t->v, t->irq);
+ vgic_inject_irq(t->v->domain, t->v, t->irq, true);
}
else
perfc_incr(vtimer_phys_masked);
{
struct vtimer *t = data;
t->ctl |= CNTx_CTL_MASK;
- vgic_vcpu_inject_irq(t->v, t->irq);
+ vgic_inject_irq(t->v->domain, t->v, t->irq, true);
perfc_incr(vtimer_virt_inject);
}
extern void domain_vgic_free(struct domain *d);
extern int vcpu_vgic_init(struct vcpu *v);
extern struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned int virq);
-extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq);
-extern void vgic_vcpu_inject_spi(struct domain *d, unsigned int virq);
+extern void vgic_inject_irq(struct domain *d, struct vcpu *v, unsigned int virq,
+ bool level);
extern void vgic_remove_irq_from_queues(struct vcpu *v, struct pending_irq *p);
extern void gic_remove_from_lr_pending(struct vcpu *v, struct pending_irq *p);
extern void vgic_clear_pending_irqs(struct vcpu *v);