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 | 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 | 171 | APICState *s = env->apic_state; |
172 | 172 | uint32_t lvt = s->lvt[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 | 221 | #define foreach_apic(apic, deliver_bitmask, code) \ |
201 | 222 | {\ |
202 | 223 | int __i, __j, __mask;\ | ... | ... |
hw/pc.c
... | ... | @@ -119,11 +119,9 @@ static void pic_irq_request(void *opaque, int irq, int level) |
119 | 119 | CPUState *env = first_cpu; |
120 | 120 | |
121 | 121 | if (env->apic_state) { |
122 | - if (!level) | |
123 | - return; | |
124 | 122 | while (env) { |
125 | 123 | if (apic_accept_pic_intr(env)) |
126 | - apic_local_deliver(env, APIC_LINT0); | |
124 | + apic_deliver_pic_intr(env, level); | |
127 | 125 | env = env->next_cpu; |
128 | 126 | } |
129 | 127 | } else { | ... | ... |
hw/pc.h
... | ... | @@ -40,11 +40,9 @@ void irq_info(void); |
40 | 40 | /* APIC */ |
41 | 41 | typedef struct IOAPICState IOAPICState; |
42 | 42 | |
43 | -#define APIC_LINT0 3 | |
44 | - | |
45 | 43 | int apic_init(CPUState *env); |
46 | 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 | 46 | int apic_get_interrupt(CPUState *env); |
49 | 47 | IOAPICState *ioapic_init(void); |
50 | 48 | void ioapic_set_irq(void *opaque, int vector, int level); | ... | ... |