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
This commit is contained in:
aurel32 2008-08-21 03:14:52 +00:00
parent b614106a17
commit 1a7de94aa4
3 changed files with 24 additions and 7 deletions

View File

@ -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;\

View File

@ -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 {

View File

@ -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);