コード例 #1
0
ファイル: vpl011.c プロジェクト: fdario/xen
static void vpl011_update_interrupt_status(struct domain *d)
{
    struct vpl011 *vpl011 = &d->arch.vpl011;
    uint32_t uartmis = vpl011->uartris & vpl011->uartimsc;

    /*
     * This function is expected to be called with the lock taken.
     */
    ASSERT(spin_is_locked(&vpl011->lock));

    /*
     * TODO: PL011 interrupts are level triggered which means
     * that interrupt needs to be set/clear instead of being
     * injected. However, currently vGIC does not handle level
     * triggered interrupts properly. This function needs to be
     * revisited once vGIC starts handling level triggered
     * interrupts.
     */

    /*
     * Raise an interrupt only if any additional interrupt
     * status bit has been set since the last time.
     */
    if ( uartmis & ~vpl011->shadow_uartmis )
        vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI);

    vpl011->shadow_uartmis = uartmis;
}
コード例 #2
0
ファイル: irq.c プロジェクト: doniexun/xen
/* Dispatch an interrupt */
void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq)
{
    struct irq_desc *desc = irq_to_desc(irq);

    perfc_incr(irqs);

    ASSERT(irq >= 16); /* SGIs do not come down this path */

    if (irq < 32)
        perfc_incr(ppis);
    else
        perfc_incr(spis);

    /* TODO: this_cpu(irq_count)++; */

    irq_enter();

    spin_lock(&desc->lock);
    desc->handler->ack(desc);

    if ( !desc->action )
    {
        printk("Unknown %s %#3.3x\n",
               is_fiq ? "FIQ" : "IRQ", irq);
        goto out;
    }

    if ( test_bit(_IRQ_GUEST, &desc->status) )
    {
        struct irq_guest *info = irq_get_guest_info(desc);

        perfc_incr(guest_irqs);
        desc->handler->end(desc);

        set_bit(_IRQ_INPROGRESS, &desc->status);

        /*
         * The irq cannot be a PPI, we only support delivery of SPIs to
         * guests.
	 */
        vgic_vcpu_inject_spi(info->d, info->virq);
        goto out_no_end;
    }

    set_bit(_IRQ_PENDING, &desc->status);

    /*
     * Since we set PENDING, if another processor is handling a different
     * instance of this same irq, the other processor will take care of it.
     */
    if ( test_bit(_IRQ_DISABLED, &desc->status) ||
         test_bit(_IRQ_INPROGRESS, &desc->status) )
        goto out;

    set_bit(_IRQ_INPROGRESS, &desc->status);

    while ( test_bit(_IRQ_PENDING, &desc->status) )
    {
        struct irqaction *action;

        clear_bit(_IRQ_PENDING, &desc->status);
        action = desc->action;

        spin_unlock_irq(&desc->lock);

        do
        {
            action->handler(irq, action->dev_id, regs);
            action = action->next;
        } while ( action );

        spin_lock_irq(&desc->lock);
    }

    clear_bit(_IRQ_INPROGRESS, &desc->status);

out:
    desc->handler->end(desc);
out_no_end:
    spin_unlock(&desc->lock);
    irq_exit();
}