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 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;\
... ...
... ... @@ -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 {
... ...
... ... @@ -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);
... ...