From e6e4bca1f6b36283c3877d7453d42d97da5b3926 Mon Sep 17 00:00:00 2001 From: Bryce Denney Date: Sun, 24 Mar 2002 01:08:24 +0000 Subject: [PATCH] - 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. --- bochs/patches/patch.smp-sync-arb-ids | 129 +++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 bochs/patches/patch.smp-sync-arb-ids diff --git a/bochs/patches/patch.smp-sync-arb-ids b/bochs/patches/patch.smp-sync-arb-ids new file mode 100644 index 000000000..eed69dc2d --- /dev/null +++ b/bochs/patches/patch.smp-sync-arb-ids @@ -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; bitinit (); +@@ -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; bitset_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