- 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:
parent
fb97571bc9
commit
e6e4bca1f6
129
bochs/patches/patch.smp-sync-arb-ids
Normal file
129
bochs/patches/patch.smp-sync-arb-ids
Normal 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
|
Loading…
Reference in New Issue
Block a user