From 1a7de94aa40729b4d7ed8f37c642304866232f40 Mon Sep 17 00:00:00 2001 From: aurel32 Date: Thu, 21 Aug 2008 03:14:52 +0000 Subject: [PATCH] De-assert PIC IRQs properly at APIC level [ Taking latest isapc changes into account. ] Ensure that PIC-delivered IRQs are properly de-asserted in case the APIC is in EXTINT or FIXED mode (with level-triggering selected) on LINT0. Fixes EFI-BIOS boot issues. This patch also cleans up a bit the interface between PIC and APIC, making apic_local_deliver private again. Signed-off-by: Jan Kiszka Signed-off-by: Aurelien Jarno git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5041 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/apic.c | 23 ++++++++++++++++++++++- hw/pc.c | 4 +--- hw/pc.h | 4 +--- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/hw/apic.c b/hw/apic.c index cfaa1db778..43d748cabd 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -166,7 +166,7 @@ static inline void reset_bit(uint32_t *tab, int index) tab[i] &= ~mask; } -void apic_local_deliver(CPUState *env, int vector) +static void apic_local_deliver(CPUState *env, int vector) { APICState *s = env->apic_state; uint32_t lvt = s->lvt[vector]; @@ -197,6 +197,27 @@ void apic_local_deliver(CPUState *env, int vector) } } +void apic_deliver_pic_intr(CPUState *env, int level) +{ + if (level) + apic_local_deliver(env, APIC_LVT_LINT0); + else { + APICState *s = env->apic_state; + uint32_t lvt = s->lvt[APIC_LVT_LINT0]; + + switch ((lvt >> 8) & 7) { + case APIC_DM_FIXED: + if (!(lvt & APIC_LVT_LEVEL_TRIGGER)) + break; + reset_bit(s->irr, lvt & 0xff); + /* fall through */ + case APIC_DM_EXTINT: + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); + break; + } + } +} + #define foreach_apic(apic, deliver_bitmask, code) \ {\ int __i, __j, __mask;\ diff --git a/hw/pc.c b/hw/pc.c index 08e0fb6cae..880e57f233 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -119,11 +119,9 @@ static void pic_irq_request(void *opaque, int irq, int level) CPUState *env = first_cpu; if (env->apic_state) { - if (!level) - return; while (env) { if (apic_accept_pic_intr(env)) - apic_local_deliver(env, APIC_LINT0); + apic_deliver_pic_intr(env, level); env = env->next_cpu; } } else { diff --git a/hw/pc.h b/hw/pc.h index acbb9fc82f..28628491dc 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -40,11 +40,9 @@ void irq_info(void); /* APIC */ typedef struct IOAPICState IOAPICState; -#define APIC_LINT0 3 - int apic_init(CPUState *env); int apic_accept_pic_intr(CPUState *env); -void apic_local_deliver(CPUState *env, int vector); +void apic_deliver_pic_intr(CPUState *env, int level); int apic_get_interrupt(CPUState *env); IOAPICState *ioapic_init(void); void ioapic_set_irq(void *opaque, int vector, int level);