[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] The attached patch apic.patch updates xen/arch/x86/apic.c so that it is based on linux 2.6.10 code. A few changes made to linux required reworking functions in other files as well so I held off on those changes. For example, setup_APIC_timer(void *) changed to setup_APIC_timer(unsigned int). The change has no real bearing on the Xen code -- it's just a question of how close to linux one wants to be. However, that change goes with a change to smp_call_function which would affect quite a few other files/functions so I left it as is. Most of the other changes are trivial.



ChangeSet 1.1308, 2005/04/16 00:40:59+01:00, iap10@xxxxxxxxxxxxxxxxxxxxx

        The attached patch apic.patch updates xen/arch/x86/apic.c so that it is 
based on linux 2.6.10 code.  A few changes made to linux required reworking 
functions in other files as well so I held off on those changes.  For example, 
setup_APIC_timer(void *) changed to setup_APIC_timer(unsigned int).  The change 
has no real bearing on the Xen code -- it's just a question of how close to 
linux one wants to be.  However, that change goes with a change to 
smp_call_function which would affect quite a few other files/functions so I 
left it as is.  Most of the other changes are trivial.
        xen/ac_timer.h was included but not needed by apic.c so I removed it 
from the list of #includes.
        
        The new apic.c includes two new files: asm/io_ports.h and 
asm/mach_apic.h.  Patches to create those files are included as well.



 arch/x86/apic.c             |  372 +++++++++++++++++++++++++++++++-------------
 include/asm-x86/io_ports.h  |   30 +++
 include/asm-x86/mach_apic.h |   32 +++
 3 files changed, 327 insertions(+), 107 deletions(-)


diff -Nru a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       2005-04-18 21:03:10 -04:00
+++ b/xen/arch/x86/apic.c       2005-04-18 21:03:10 -04:00
@@ -1,4 +1,6 @@
 /*
+ *      based on linux-2.6.10/arch/i386/kernel/apic.c
+ *
  *  Local APIC handling, local APIC timers
  *
  *  (c) 1999, 2000 Ingo Molnar <mingo@xxxxxxxxxx>
@@ -10,11 +12,11 @@
  *                  for testing these extensively.
  *     Maciej W. Rozycki       :       Various updates and fixes.
  *     Mikael Pettersson       :       Power Management for UP-APIC.
+ *    Pavel Machek and
+ *    Mikael Pettersson    :    PM converted to driver model.
  */
 
-
 #include <xen/config.h>
-#include <xen/ac_timer.h>
 #include <xen/perfc.h>
 #include <xen/errno.h>
 #include <xen/init.h>
@@ -32,7 +34,8 @@
 #include <asm/hardirq.h>
 #include <asm/apic.h>
 #include <asm/io_apic.h>
-
+#include <asm/mach_apic.h>
+#include <asm/io_ports.h>
 
 /* Using APIC to generate smp_local_timer_interrupt? */
 int using_apic_timer = 0;
@@ -80,6 +83,16 @@
         apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
     }
 
+#if 0
+/* lets not touch this if we didn't frob it */
+#ifdef CONFIG_X86_MCE_P4THERMAL
+    if (maxlvt >= 5) {
+        v = apic_read(APIC_LVTTHMR);
+        apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED);
+    }
+#endif
+#endif
+
     /*
      * Clean APIC state for other OSs:
      */
@@ -90,9 +103,17 @@
         apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
     if (maxlvt >= 4)
         apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
+
+#if 0
+#ifdef CONFIG_X86_MCE_P4THERMAL
+    if (maxlvt >= 5)
+        apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
+#endif
+#endif 
+
     v = GET_APIC_VERSION(apic_read(APIC_LVR));
     if (APIC_INTEGRATED(v)) {  /* !82489DX */
-        if (maxlvt > 3)
+        if (maxlvt > 3)        /* Due to Pentium errata 3AP and 11AP. */
             apic_write(APIC_ESR, 0);
         apic_read(APIC_ESR);
     }
@@ -113,6 +134,9 @@
         outb(0x70, 0x22);
         outb(0x01, 0x23);
     }
+#if 0
+    enable_apic_mode();
+#endif
 }
 
 void disconnect_bsp_APIC(void)
@@ -193,12 +217,6 @@
      */
     reg0 = apic_read(APIC_ID);
     Dprintk("Getting ID: %x\n", reg0);
-    apic_write(APIC_ID, reg0 ^ APIC_ID_MASK);
-    reg1 = apic_read(APIC_ID);
-    Dprintk("Getting ID: %x\n", reg1);
-    apic_write(APIC_ID, reg0);
-    if (reg1 != (reg0 ^ APIC_ID_MASK))
-        return 0;
 
     /*
      * The next two are just to see if we have sane values.
@@ -215,6 +233,10 @@
 
 void __init sync_Arb_IDs(void)
 {
+    /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
+    unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
+    if (ver >= 0x14)    /* P4 or higher */
+        return;
     /*
      * Wait for idle.
      */
@@ -240,15 +262,17 @@
 {
 }
 
-static unsigned long calculate_ldr(unsigned long old)
-{
-    unsigned long id = 1UL << smp_processor_id();
-    return (old & ~APIC_LDR_MASK)|SET_APIC_LOGICAL_ID(id);
-}
-
 void __init setup_local_APIC (void)
 {
-    unsigned long value, ver, maxlvt;
+    unsigned long oldvalue, value, ver, maxlvt;
+
+    /* Pound the ESR really hard over the head with a big hammer - mbligh */
+    if (esr_disable) {
+        apic_write(APIC_ESR, 0);
+        apic_write(APIC_ESR, 0);
+        apic_write(APIC_ESR, 0);
+        apic_write(APIC_ESR, 0);
+    }
 
     value = apic_read(APIC_LVR);
     ver = GET_APIC_VERSION(value);
@@ -256,8 +280,10 @@
     if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
         __error_in_apic_c();
 
-    /* Double-check wether this APIC is really registered. */
-    if (!test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map))
+    /*
+     * Double-check whether this APIC is really registered.
+     */
+    if (!apic_id_registered())
         BUG();
 
     /*
@@ -265,19 +291,7 @@
      * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
      * document number 292116).  So here it goes...
      */
-
-    /*
-     * In clustered apic mode, the firmware does this for us 
-     * Put the APIC into flat delivery mode.
-     * Must be "all ones" explicitly for 82489DX.
-     */
-    apic_write_around(APIC_DFR, APIC_DFR_FLAT);
-
-    /*
-     * Set up the logical destination ID.
-     */
-    value = apic_read(APIC_LDR);
-    apic_write_around(APIC_LDR, calculate_ldr(value));
+    init_apic_ldr();
 
     /*
      * Set Task Priority to 'accept all'. We never change this
@@ -297,10 +311,35 @@
      */
     value |= APIC_SPIV_APIC_ENABLED;
 
+    /*
+     * Some unknown Intel IO/APIC (or APIC) errata is biting us with
+     * certain networking cards. If high frequency interrupts are
+     * happening on a particular IOAPIC pin, plus the IOAPIC routing
+     * entry is masked/unmasked at a high rate as well then sooner or
+     * later IOAPIC line gets 'stuck', no more interrupts are received
+     * from the device. If focus CPU is disabled then the hang goes
+     * away, oh well :-(
+     *
+     * [ This bug can be reproduced easily with a level-triggered
+     *   PCI Ne2000 networking cards and PII/PIII processors, dual
+     *   BX chipset. ]
+     */
+    /*
+     * Actually disabling the focus CPU check just makes the hang less
+     * frequent as it makes the interrupt distributon model be more
+     * like LRU than MRU (the short-term load is more even across CPUs).
+     * See also the comment in end_level_ioapic_irq().  --macro
+     */
+#if 1
     /* Enable focus processor (bit==0) */
     value &= ~APIC_SPIV_FOCUS_DISABLED;
-
-    /* Set spurious IRQ vector */
+#else
+    /* Disable focus processor (bit==1) */
+    value |= APIC_SPIV_FOCUS_DISABLED;
+#endif
+    /*
+     * Set spurious IRQ vector
+     */
     value |= SPURIOUS_APIC_VECTOR;
     apic_write_around(APIC_SPIV, value);
 
@@ -315,7 +354,7 @@
      * TODO: set up through-local-APIC from through-I/O-APIC? --macro
      */
     value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
-    if (!smp_processor_id()) { 
+    if (!smp_processor_id() && (pic_mode || !value)) {
         value = APIC_DM_EXTINT;
         printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
     } else {
@@ -335,33 +374,43 @@
         value |= APIC_LVT_LEVEL_TRIGGER;
     apic_write_around(APIC_LVT1, value);
 
-    if (APIC_INTEGRATED(ver)) {     /* !82489DX */
+    if (APIC_INTEGRATED(ver) && !esr_disable) {        /* !82489DX */
         maxlvt = get_maxlvt();
         if (maxlvt > 3)     /* Due to the Pentium erratum 3AP. */
             apic_write(APIC_ESR, 0);
-        value = apic_read(APIC_ESR);
-        printk("ESR value before enabling vector: %08lx\n", value);
+        oldvalue = apic_read(APIC_ESR);
 
-        value = ERROR_APIC_VECTOR;      /* enables sending errors */
+        value = ERROR_APIC_VECTOR;      // enables sending errors
         apic_write_around(APIC_LVTERR, value);
-        /* spec says clear errors after enabling vector. */
+        /*
+         * spec says clear errors after enabling vector.
+         */
         if (maxlvt > 3)
             apic_write(APIC_ESR, 0);
         value = apic_read(APIC_ESR);
-        printk("ESR value after enabling vector: %08lx\n", value);
+        if (value != oldvalue)
+            printk("ESR value before enabling vector: 0x%08lx "
+                "after: 0x%08lx\n", oldvalue, value);
     } else {
+        if (esr_disable)    
+            /* 
+             * Something untraceble is creating bad interrupts on 
+             * secondary quads ... for the moment, just leave the
+             * ESR disabled - we can't do anything useful with the
+             * errors anyway - mbligh
+             */
+            printk("Leaving ESR disabled.\n");
+        else 
         printk("No ESR for 82489DX.\n");
     }
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.