- adds an important behavior of local APICs that was missing before.

An INIT interrupt with Trigger mode=Level and Level=Deassert tells
  all the APICs to set their arbitration ID.  It does NOT do a normal
  init, as bochs was doing before.
This commit is contained in:
Bryce Denney 2002-03-24 01:08:24 +00:00
parent fb97571bc9
commit e6e4bca1f6

View File

@ -0,0 +1,129 @@
? Makefile
? .apic.cc.swp
? stSVOcJq
? apic-works.cc
? .cpu.h.swp
Index: apic.cc
===================================================================
RCS file: /cvsroot/bochs/bochs/cpu/apic.cc,v
retrieving revision 1.8
diff -u -r1.8 apic.cc
--- apic.cc 3 Oct 2001 13:10:37 -0000 1.8
+++ apic.cc 24 Mar 2002 01:04:36 -0000
@@ -22,6 +22,13 @@
{
}
+void
+bx_generic_apic_c::set_arb_id (int new_arb_id)
+{
+ // politely ignore it. This gets sent to every APIC, regardless of its
+ // type.
+}
+
// init is called during RESET and when an INIT message is delivered.
void bx_generic_apic_c::init ()
{
@@ -185,6 +191,10 @@
break;
case 5: // INIT
{
+ // NOTE: special behavior of local apics is handled in
+ // bx_local_apic_c::deliver.
+
+ // normal INIT. initialize the local apics in the delivery mask.
for (int bit=0; bit<APIC_MAX_ID; bit++) {
if (deliver_bitmask & (1<<bit))
apic_index[bit]->init ();
@@ -221,6 +231,33 @@
return true;
}
+Boolean
+bx_local_apic_c::deliver (Bit8u dest, Bit8u dest_mode, Bit8u delivery_mode, Bit8u vector, Bit8u polarity, Bit8u trig_mode)
+{
+ // In this function, implement only the behavior that is specific to
+ // the local apic. For general behavior of all apics, just send it to
+ // the base class.
+ if (delivery_mode == 5)
+ {
+ int trig_mode = (icr_low >> 15) & 1;
+ int level = (icr_low >> 14) & 1;
+ if (level == 0 && trig_mode == 1) {
+ // special mode in local apic. See "INIT Level Deassert" in the
+ // Intel Soft. Devel. Guide Vol 3, page 7-34. This magic code
+ // causes all APICs (regardless of dest address) to set their
+ // arbitration ID to their APIC ID.
+ BX_INFO (("INIT with Level&Deassert: synchronize arbitration IDs"));
+ for (int bit=0; bit<APIC_MAX_ID; bit++) {
+ if (apic_index[bit])
+ apic_index[bit]->set_arb_id (apic_index[bit]->get_id ());
+ }
+ return true;
+ }
+ }
+ // not any special case behavior, just use generic apic code.
+ return bx_generic_apic_c::deliver (dest, dest_mode, delivery_mode, vector, polarity, trig_mode);
+}
+
bx_local_apic_c::bx_local_apic_c(BX_CPU_C *mycpu)
: bx_generic_apic_c ()
{
@@ -230,6 +267,13 @@
}
void
+bx_local_apic_c::set_arb_id (int new_arb_id)
+{
+ BX_DEBUG (("set arbitration ID to %d", new_arb_id));
+ arb_id = new_arb_id;
+}
+
+void
bx_local_apic_c::hwreset ()
{
/* same as INIT but also sets arbitration ID and APIC ID */
@@ -338,9 +382,11 @@
break;
case 0xd0: // logical destination
log_dest = (*data >> 24) & 0xff;
+ BX_DEBUG (("set logical destination to %02x", log_dest));
break;
case 0xe0: // destination format
dest_format = (*data >> 28) & 0xf;
+ BX_DEBUG (("set destination format to %02x", dest_format));
break;
case 0xf0: // spurious interrupt vector
spurious_vec = (spurious_vec & 0x0f) | (*data & 0x3f0);
Index: cpu.h
===================================================================
RCS file: /cvsroot/bochs/bochs/cpu/cpu.h,v
retrieving revision 1.15
diff -u -r1.15 cpu.h
--- cpu.h 3 Oct 2001 19:53:48 -0000 1.15
+++ cpu.h 24 Mar 2002 01:04:39 -0000
@@ -548,9 +548,10 @@
virtual void trigger_irq (unsigned num, unsigned from);
virtual void untrigger_irq (unsigned num, unsigned from);
virtual Bit32u get_delivery_bitmask (Bit8u dest, Bit8u dest_mode);
- Boolean deliver (Bit8u destination, Bit8u dest_mode, Bit8u delivery_mode, Bit8u vector, Bit8u polarity, Bit8u trig_mode);
+ virtual Boolean deliver (Bit8u destination, Bit8u dest_mode, Bit8u delivery_mode, Bit8u vector, Bit8u polarity, Bit8u trig_mode);
virtual Boolean match_logical_addr (Bit8u address);
virtual bx_apic_type_t get_type ();
+ virtual void set_arb_id (int newid); // only implemented on local apics
};
class bx_local_apic_c : public bx_generic_apic_c {
@@ -612,10 +613,12 @@
virtual Boolean is_local_apic () { return true; }
virtual bx_apic_type_t get_type () { return APIC_TYPE_LOCAL_APIC; }
virtual Bit32u get_delivery_bitmask (Bit8u dest, Bit8u dest_mode);
+ virtual Boolean deliver (Bit8u destination, Bit8u dest_mode, Bit8u delivery_mode, Bit8u vector, Bit8u polarity, Bit8u trig_mode);
Bit8u get_ppr ();
Bit8u get_apr ();
void periodic (Bit32u usec_delta);
void set_divide_configuration (Bit32u value);
+ virtual void set_arb_id (int newid);
};
#define APIC_MAX_ID 16