Commit 1a7de94aa40729b4d7ed8f37c642304866232f40
1 parent
b614106a
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 <jan.kiszka@siemens.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5041 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
24 additions
and
7 deletions
hw/apic.c
| @@ -166,7 +166,7 @@ static inline void reset_bit(uint32_t *tab, int index) | @@ -166,7 +166,7 @@ static inline void reset_bit(uint32_t *tab, int index) | ||
| 166 | tab[i] &= ~mask; | 166 | tab[i] &= ~mask; |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | -void apic_local_deliver(CPUState *env, int vector) | 169 | +static void apic_local_deliver(CPUState *env, int vector) |
| 170 | { | 170 | { |
| 171 | APICState *s = env->apic_state; | 171 | APICState *s = env->apic_state; |
| 172 | uint32_t lvt = s->lvt[vector]; | 172 | uint32_t lvt = s->lvt[vector]; |
| @@ -197,6 +197,27 @@ void apic_local_deliver(CPUState *env, int vector) | @@ -197,6 +197,27 @@ void apic_local_deliver(CPUState *env, int vector) | ||
| 197 | } | 197 | } |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | +void apic_deliver_pic_intr(CPUState *env, int level) | ||
| 201 | +{ | ||
| 202 | + if (level) | ||
| 203 | + apic_local_deliver(env, APIC_LVT_LINT0); | ||
| 204 | + else { | ||
| 205 | + APICState *s = env->apic_state; | ||
| 206 | + uint32_t lvt = s->lvt[APIC_LVT_LINT0]; | ||
| 207 | + | ||
| 208 | + switch ((lvt >> 8) & 7) { | ||
| 209 | + case APIC_DM_FIXED: | ||
| 210 | + if (!(lvt & APIC_LVT_LEVEL_TRIGGER)) | ||
| 211 | + break; | ||
| 212 | + reset_bit(s->irr, lvt & 0xff); | ||
| 213 | + /* fall through */ | ||
| 214 | + case APIC_DM_EXTINT: | ||
| 215 | + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); | ||
| 216 | + break; | ||
| 217 | + } | ||
| 218 | + } | ||
| 219 | +} | ||
| 220 | + | ||
| 200 | #define foreach_apic(apic, deliver_bitmask, code) \ | 221 | #define foreach_apic(apic, deliver_bitmask, code) \ |
| 201 | {\ | 222 | {\ |
| 202 | int __i, __j, __mask;\ | 223 | int __i, __j, __mask;\ |
hw/pc.c
| @@ -119,11 +119,9 @@ static void pic_irq_request(void *opaque, int irq, int level) | @@ -119,11 +119,9 @@ static void pic_irq_request(void *opaque, int irq, int level) | ||
| 119 | CPUState *env = first_cpu; | 119 | CPUState *env = first_cpu; |
| 120 | 120 | ||
| 121 | if (env->apic_state) { | 121 | if (env->apic_state) { |
| 122 | - if (!level) | ||
| 123 | - return; | ||
| 124 | while (env) { | 122 | while (env) { |
| 125 | if (apic_accept_pic_intr(env)) | 123 | if (apic_accept_pic_intr(env)) |
| 126 | - apic_local_deliver(env, APIC_LINT0); | 124 | + apic_deliver_pic_intr(env, level); |
| 127 | env = env->next_cpu; | 125 | env = env->next_cpu; |
| 128 | } | 126 | } |
| 129 | } else { | 127 | } else { |
hw/pc.h
| @@ -40,11 +40,9 @@ void irq_info(void); | @@ -40,11 +40,9 @@ void irq_info(void); | ||
| 40 | /* APIC */ | 40 | /* APIC */ |
| 41 | typedef struct IOAPICState IOAPICState; | 41 | typedef struct IOAPICState IOAPICState; |
| 42 | 42 | ||
| 43 | -#define APIC_LINT0 3 | ||
| 44 | - | ||
| 45 | int apic_init(CPUState *env); | 43 | int apic_init(CPUState *env); |
| 46 | int apic_accept_pic_intr(CPUState *env); | 44 | int apic_accept_pic_intr(CPUState *env); |
| 47 | -void apic_local_deliver(CPUState *env, int vector); | 45 | +void apic_deliver_pic_intr(CPUState *env, int level); |
| 48 | int apic_get_interrupt(CPUState *env); | 46 | int apic_get_interrupt(CPUState *env); |
| 49 | IOAPICState *ioapic_init(void); | 47 | IOAPICState *ioapic_init(void); |
| 50 | void ioapic_set_irq(void *opaque, int vector, int level); | 48 | void ioapic_set_irq(void *opaque, int vector, int level); |