Commit 1a7de94aa40729b4d7ed8f37c642304866232f40

Authored by aurel32
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;\
@@ -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 {
@@ -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);