diff --git a/hw/apic.c b/hw/apic.c index d8f56c8b7..8289eef5b 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -23,6 +23,7 @@ #include "host-utils.h" #include "sysbus.h" #include "trace.h" +#include "pc.h" /* APIC Local Vector Table */ #define APIC_LVT_TIMER 0 @@ -399,6 +400,9 @@ static void apic_update_irq(APICState *s) } if (apic_irq_pending(s) > 0) { cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD); + } else if (apic_accept_pic_intr(&s->busdev.qdev) && + pic_get_output(isa_pic)) { + apic_deliver_pic_intr(&s->busdev.qdev, 1); } } diff --git a/hw/i8259.c b/hw/i8259.c index e5323ffa4..60061236f 100644 --- a/hw/i8259.c +++ b/hw/i8259.c @@ -146,8 +146,7 @@ static int pic_get_irq(PicState *s) /* raise irq to CPU if necessary. must be called every time the active irq may change */ -/* XXX: should not export it, but it is needed for an APIC kludge */ -void pic_update_irq(PicState2 *s) +static void pic_update_irq(PicState2 *s) { int irq2, irq; @@ -174,14 +173,9 @@ void pic_update_irq(PicState2 *s) printf("pic: cpu_interrupt\n"); #endif qemu_irq_raise(s->parent_irq); - } - -/* all targets should do this rather than acking the IRQ in the cpu */ -#if defined(TARGET_MIPS) || defined(TARGET_PPC) || defined(TARGET_ALPHA) - else { + } else { qemu_irq_lower(s->parent_irq); } -#endif } #ifdef DEBUG_IRQ_LATENCY @@ -441,6 +435,11 @@ uint32_t pic_intack_read(PicState2 *s) return ret; } +int pic_get_output(PicState2 *s) +{ + return (pic_get_irq(&s->pics[0]) >= 0); +} + static void elcr_ioport_write(void *opaque, target_phys_addr_t addr, uint64_t val, unsigned size) { diff --git a/hw/pc.c b/hw/pc.c index 9b68695cf..f0802b709 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -155,9 +155,6 @@ int cpu_get_pic_interrupt(CPUState *env) intno = apic_get_interrupt(env->apic_state); if (intno >= 0) { - /* set irq request if a PIC irq is still pending */ - /* XXX: improve that */ - pic_update_irq(isa_pic); return intno; } /* read the irq from the PIC */ diff --git a/hw/pc.h b/hw/pc.h index 72f8c7c97..d133dc055 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -66,7 +66,7 @@ void pic_set_irq(int irq, int level); void pic_set_irq_new(void *opaque, int irq, int level); qemu_irq *i8259_init(qemu_irq parent_irq); int pic_read_irq(PicState2 *s); -void pic_update_irq(PicState2 *s); +int pic_get_output(PicState2 *s); uint32_t pic_intack_read(PicState2 *s); void pic_info(Monitor *mon); void irq_info(Monitor *mon);