Commit 0fbfbb59 authored by Gleb Natapov's avatar Gleb Natapov Committed by Anthony Liguori
Browse files

correctly check ppr priority during interrupt injection]



TPR blocks all interrupts in a priority class, so simple "less or
equal" check is not enough.

Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
Reviewed-by: default avatarJan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parent ed94592b
Loading
Loading
Loading
Loading
+30 −12
Original line number Diff line number Diff line
@@ -372,20 +372,37 @@ static int apic_get_arb_pri(APICState *s)
    return 0;
}

/* signal the CPU if an irq is pending */
static void apic_update_irq(APICState *s)

/*
 * <0 - low prio interrupt,
 * 0  - no interrupt,
 * >0 - interrupt number
 */
static int apic_irq_pending(APICState *s)
{
    int irrv, ppr;
    if (!(s->spurious_vec & APIC_SV_ENABLE))
        return;
    irrv = get_highest_priority_int(s->irr);
    if (irrv < 0)
        return;
    if (irrv < 0) {
        return 0;
    }
    ppr = apic_get_ppr(s);
    if (ppr && (irrv & 0xf0) <= (ppr & 0xf0))
    if (ppr && (irrv & 0xf0) <= (ppr & 0xf0)) {
        return -1;
    }

    return irrv;
}

/* signal the CPU if an irq is pending */
static void apic_update_irq(APICState *s)
{
    if (!(s->spurious_vec & APIC_SV_ENABLE)) {
        return;
    }
    if (apic_irq_pending(s) > 0) {
        cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
    }
}

void apic_reset_irq_delivered(void)
{
@@ -590,12 +607,13 @@ int apic_get_interrupt(DeviceState *d)
    if (!(s->spurious_vec & APIC_SV_ENABLE))
        return -1;

    /* XXX: spurious IRQ handling */
    intno = get_highest_priority_int(s->irr);
    if (intno < 0)
    intno = apic_irq_pending(s);

    if (intno == 0) {
        return -1;
    if (s->tpr && intno <= s->tpr)
    } else if (intno < 0) {
        return s->spurious_vec & 0xff;
    }
    reset_bit(s->irr, intno);
    set_bit(s->isr, intno);
    apic_update_irq(s);