- I/O APIC signal handling rewritten ("backported" from qemu)

- don't flood the logfile if APIC EOI has no effect
- fixed a warning in the APIC code
- TODO: fix IRQ 0 handling, implement ExtINT
This commit is contained in:
Volker Ruppert 2006-01-01 11:33:06 +00:00
parent ff7f41541f
commit 97e1f39d8f
4 changed files with 49 additions and 64 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: apic.cc,v 1.70 2005-12-26 19:42:09 sshwarts Exp $
// $Id: apic.cc,v 1.71 2006-01-01 11:33:06 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -645,7 +645,7 @@ void bx_local_apic_c::receive_EOI(Bit32u value)
BX_DEBUG(("%s: Wrote 0x%x to EOI", cpu->name, value));
int vec = highest_priority_int (isr);
if (vec < 0) {
BX_INFO(("EOI written without any bit in ISR"));
BX_DEBUG(("EOI written without any bit in ISR"));
} else {
if (vec != (int) spurious_vector) {
BX_DEBUG(("%s: local apic received EOI, hopefully for vector 0x%02x", cpu->name, vec));
@ -818,7 +818,7 @@ void bx_local_apic_c::service_local_apic(void)
// shadow_error_status |= APIC_ERR_TX_ACCEPT_ERR;
return;
}
if ((first_irr & 0xf0) <= (task_priority & 0xf0)) {
if ((first_irr & 0xf0) <= (int)(task_priority & 0xf0)) {
BX_DEBUG(("local apic (%s): not delivering int%02X because task_priority is %X", cpu->name, first_irr, task_priority));
return;
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: ioapic.cc,v 1.21 2005-12-31 14:46:21 vruppert Exp $
// $Id: ioapic.cc,v 1.22 2006-01-01 11:33:06 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
#include <stdio.h>
@ -133,42 +133,28 @@ void bx_ioapic_c::write(Bit32u address, Bit32u *value, unsigned len)
}
}
void bx_ioapic_c::raise_irq(unsigned num, unsigned from)
void bx_ioapic_c::set_irq_level(Bit8u int_in, bx_bool level)
{
unsigned vector;
if (from == BX_IOAPIC_INT_FROM_ISA) {
if ((num == 0) || (num == 2) || (num == 13)) return;
}
vector = num;
BX_DEBUG(("IOAPIC: received vector %d", vector));
if (vector <= BX_APIC_LAST_VECTOR) {
Bit32u bit = 1<<vector;
if ((irr & bit) == 0) {
irr |= bit;
service_ioapic ();
BX_DEBUG(("set_irq_level(): INTIN%d: level=%d", int_in, level));
if (int_in < BX_IOAPIC_NUM_PINS) {
Bit32u bit = 1<<int_in;
bx_io_redirect_entry_t *entry = ioredtbl + int_in;
entry->parse_value();
if (entry->trig_mode) {
// level triggered
if (level) {
irr |= bit;
service_ioapic ();
} else {
irr &= ~bit;
}
} else {
// edge triggered
if (level) {
irr |= bit;
service_ioapic ();
}
}
} else {
BX_PANIC(("IOAPIC: vector %d out of range", vector));
}
}
void bx_ioapic_c::lower_irq (unsigned num, unsigned from)
{
unsigned vector;
if (from == BX_IOAPIC_INT_FROM_ISA) {
if ((num == 0) || (num == 2) || (num == 13)) return;
}
BX_DEBUG(("IOAPIC: interrupt %d went away", num));
vector = num;
if (vector <= BX_APIC_LAST_VECTOR) {
Bit32u bit = 1<<vector;
if ((irr & bit) != 0) {
irr &= ~bit;
}
} else {
BX_PANIC(("IOAPIC: vector %d out of range", vector));
}
}
@ -178,22 +164,27 @@ void bx_ioapic_c::service_ioapic ()
// look in IRR and deliver any interrupts that are not masked.
BX_DEBUG(("IOAPIC: servicing"));
for (unsigned bit=0; bit < BX_IOAPIC_NUM_PINS; bit++) {
if (irr & (1<<bit)) {
Bit32u mask = 1<<bit;
if (irr & mask) {
bx_io_redirect_entry_t *entry = ioredtbl + bit;
entry->parse_value();
if (! entry->masked) {
// clear irr bit and deliver
bx_bool done = deliver (entry->dest, entry->dest_mode, entry->delivery_mode, entry->vector, entry->polarity, entry->trig_mode);
if (done) {
irr &= ~(1<<bit);
entry->delivery_status = 0;
stuck = 0;
} else {
entry->delivery_status = 1;
stuck++;
if (stuck > 5)
BX_INFO(("vector %#x stuck?\n", entry->vector));
}
// clear irr bit and deliver
if (entry->delivery_mode == 7) {
BX_PANIC(("ExtINT not implemented yet"));
}
bx_bool done = deliver (entry->dest, entry->dest_mode, entry->delivery_mode, entry->vector, entry->polarity, entry->trig_mode);
if (done) {
if (! entry->trig_mode)
irr &= ~mask;
entry->delivery_status = 0;
stuck = 0;
} else {
entry->delivery_status = 1;
stuck++;
if (stuck > 5)
BX_INFO(("vector %#x stuck?\n", entry->vector));
}
}
}
}

View File

@ -1,15 +1,10 @@
/////////////////////////////////////////////////////////////////////////
// $Id: ioapic.h,v 1.12 2005-12-31 14:46:21 vruppert Exp $
// $Id: ioapic.h,v 1.13 2006-01-01 11:33:06 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
extern class bx_ioapic_c bx_ioapic;
#define BX_IOAPIC_NUM_PINS (0x18)
#define BX_IOAPIC_INT_FROM_ISA 0
#define BX_IOAPIC_INT_FROM_PIC 1
#define BX_IOAPIC_INT_FROM_PCI 2
#define BX_IOAPIC_INT_FROM_MB 3
#define BX_IOAPIC_INT_FROM_SMI 4
// use the same version as 82093 IOAPIC (0x00170011)
#define BX_IOAPIC_VERSION_ID (((BX_IOAPIC_NUM_PINS - 1) << 16) | 0x11)
@ -56,8 +51,7 @@ public:
virtual void reset (unsigned type);
virtual void read_aligned(Bit32u address, Bit32u *data, unsigned len);
virtual void write(Bit32u address, Bit32u *value, unsigned len);
void raise_irq(unsigned num, unsigned from);
void lower_irq(unsigned num, unsigned from);
void set_irq_level(Bit8u int_in, bx_bool level);
void service_ioapic ();
virtual bx_apic_type_t get_type () { return APIC_TYPE_IOAPIC; }
};

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: pic.cc,v 1.37 2005-12-31 14:46:21 vruppert Exp $
// $Id: pic.cc,v 1.38 2006-01-01 11:33:06 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 MandrakeSoft S.A.
@ -618,8 +618,8 @@ bx_pic_c::lower_irq(unsigned irq_no)
{
#if BX_SUPPORT_APIC
// forward this function call to the ioapic too
if (DEV_ioapic_present()) {
bx_devices.ioapic->lower_irq(irq_no, BX_IOAPIC_INT_FROM_ISA);
if (DEV_ioapic_present() && (irq_no != 0) && (irq_no != 2)) {
bx_devices.ioapic->set_irq_level(irq_no, 0);
}
#endif
@ -648,8 +648,8 @@ bx_pic_c::raise_irq(unsigned irq_no)
{
#if BX_SUPPORT_APIC
// forward this function call to the ioapic too
if (DEV_ioapic_present()) {
bx_devices.ioapic->raise_irq(irq_no, BX_IOAPIC_INT_FROM_ISA);
if (DEV_ioapic_present() && (irq_no != 0) && (irq_no != 2)) {
bx_devices.ioapic->set_irq_level(irq_no, 1);
}
#endif