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

[Xen-changelog] [xen-unstable] x86: enable directed EOI



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1258959499 0
# Node ID 522ae754787d678ad64fcad7ee951bdce4fe28ce
# Parent  3ca45272ff2cf8382d324d2ef767f1fe9e3022e3
x86: enable directed EOI

This patch enables directed EOI on latest processor. With this, the
broadcast of EOI would be suppressed upon LAPIC EOI, so VMM is
required to perform a directed EOI to the IOxAPIC generating the
interrupt by writting to its EOI register.(Pls. refer SDM 3A 10.5.5)

This is useful for ioapic_ack_old to avoid the spurious interrupt
storm, which is the reason why ioapic_ack_new is used.

Signed-Off-By: Zhai Edwin <edwin.zhai@xxxxxxxxx>
---
 xen/arch/x86/apic.c           |   25 +++++++++++++++++++++++++
 xen/arch/x86/io_apic.c        |   35 +++++++++++++++++++++++++++++++++--
 xen/include/asm-x86/apic.h    |    1 +
 xen/include/asm-x86/apicdef.h |    2 ++
 xen/include/asm-x86/io_apic.h |    5 +++++
 5 files changed, 66 insertions(+), 2 deletions(-)

diff -r 3ca45272ff2c -r 522ae754787d xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       Mon Nov 23 06:56:01 2009 +0000
+++ b/xen/arch/x86/apic.c       Mon Nov 23 06:58:19 2009 +0000
@@ -68,6 +68,7 @@ int apic_verbosity;
 int apic_verbosity;
 
 int x2apic_enabled __read_mostly = 0;
+int directed_eoi_enabled __read_mostly = 0;
 
 /*
  * The following vectors are part of the Linux architecture, there
@@ -348,6 +349,7 @@ void disable_local_APIC(void)
     }
 }
 
+extern int ioapic_ack_new;
 /*
  * This is to verify that we're looking at a real local APIC.
  * Check these against your board if the CPUs aren't getting
@@ -386,6 +388,18 @@ int __init verify_local_APIC(void)
     reg1 = get_maxlvt();
     if (reg1 < 0x02 || reg1 == 0xff)
         return 0;
+
+    /*
+     * Detecting directed EOI on BSP:
+     * If having directed EOI support in lapic, force to use ioapic_ack_old,
+     * and enable the directed EOI for intr handling.
+     */
+    if ( reg0 & APIC_LVR_DIRECTED_EOI )
+    {
+        ioapic_ack_new = 0;
+        directed_eoi_enabled = 1;
+        printk("Enabled directed EOI with ioapic_ack_old on!\n");
+    }
 
     /*
      * The ID register is read/write in a real APIC.
@@ -575,6 +589,17 @@ void __devinit setup_local_APIC(void)
      * Set spurious IRQ vector
      */
     value |= SPURIOUS_APIC_VECTOR;
+
+    /*
+     * Enable directed EOI
+     */
+    if ( directed_eoi_enabled )
+    {
+        value |= APIC_SPIV_DIRECTED_EOI;
+        apic_printk(APIC_VERBOSE, "Suppress EOI broadcast on CPU#%d\n",
+                    smp_processor_id());
+    }
+
     apic_write_around(APIC_SPIV, value);
 
     /*
diff -r 3ca45272ff2c -r 522ae754787d xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c    Mon Nov 23 06:56:01 2009 +0000
+++ b/xen/arch/x86/io_apic.c    Mon Nov 23 06:58:19 2009 +0000
@@ -194,6 +194,30 @@ static void unmask_IO_APIC_irq (unsigned
 
     spin_lock_irqsave(&ioapic_lock, flags);
     __unmask_IO_APIC_irq(irq);
+    spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+static void __eoi_IO_APIC_irq(unsigned int irq)
+{
+    struct irq_pin_list *entry = irq_2_pin + irq;
+    unsigned int pin, vector = IO_APIC_VECTOR(irq);
+
+    for (;;) {
+        pin = entry->pin;
+        if (pin == -1)
+            break;
+        io_apic_eoi(entry->apic, vector);
+        if (!entry->next)
+            break;
+        entry = irq_2_pin + entry->next;
+    }
+}
+
+static void eoi_IO_APIC_irq(unsigned int irq)
+{
+    unsigned long flags;
+    spin_lock_irqsave(&ioapic_lock, flags);
+    __eoi_IO_APIC_irq(irq);
     spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
@@ -1464,7 +1488,8 @@ static void mask_and_ack_level_ioapic_ir
     if ( ioapic_ack_new )
         return;
 
-    mask_IO_APIC_irq(irq);
+    if ( !directed_eoi_enabled )
+        mask_IO_APIC_irq(irq);
 
 /*
  * It appears there is an erratum which affects at least version 0x11
@@ -1511,8 +1536,14 @@ static void end_level_ioapic_irq (unsign
 
     if ( !ioapic_ack_new )
     {
-        if ( !(irq_desc[irq].status & IRQ_DISABLED) )
+        if ( irq_desc[irq].status & IRQ_DISABLED )
+            return;
+
+        if ( directed_eoi_enabled )
+            eoi_IO_APIC_irq(irq);
+        else
             unmask_IO_APIC_irq(irq);
+
         return;
     }
 
diff -r 3ca45272ff2c -r 522ae754787d xen/include/asm-x86/apic.h
--- a/xen/include/asm-x86/apic.h        Mon Nov 23 06:56:01 2009 +0000
+++ b/xen/include/asm-x86/apic.h        Mon Nov 23 06:58:19 2009 +0000
@@ -23,6 +23,7 @@
 
 extern int apic_verbosity;
 extern int x2apic_enabled;
+extern int directed_eoi_enabled;
 
 extern void enable_x2apic(void);
 
diff -r 3ca45272ff2c -r 522ae754787d xen/include/asm-x86/apicdef.h
--- a/xen/include/asm-x86/apicdef.h     Mon Nov 23 06:56:01 2009 +0000
+++ b/xen/include/asm-x86/apicdef.h     Mon Nov 23 06:58:19 2009 +0000
@@ -16,6 +16,7 @@
 #define                        SET_xAPIC_ID(x)         (((x)<<24))
 #define                APIC_LVR        0x30
 #define                        APIC_LVR_MASK           0xFF00FF
+#define                        APIC_LVR_DIRECTED_EOI   (1 << 24)
 #define                        GET_APIC_VERSION(x)     ((x)&0xFF)
 #define                        GET_APIC_MAXLVT(x)      (((x)>>16)&0xFF)
 #define                        APIC_INTEGRATED(x)      ((x)&0xF0)
@@ -39,6 +40,7 @@
 #define                APIC_SPIV       0xF0
 #define                        APIC_SPIV_FOCUS_DISABLED        (1<<9)
 #define                        APIC_SPIV_APIC_ENABLED          (1<<8)
+#define                        APIC_SPIV_DIRECTED_EOI          (1<<12)
 #define                APIC_ISR        0x100
 #define         APIC_ISR_NR     0x8     /* Number of 32 bit ISR registers. */
 #define                APIC_TMR        0x180
diff -r 3ca45272ff2c -r 522ae754787d xen/include/asm-x86/io_apic.h
--- a/xen/include/asm-x86/io_apic.h     Mon Nov 23 06:56:01 2009 +0000
+++ b/xen/include/asm-x86/io_apic.h     Mon Nov 23 06:58:19 2009 +0000
@@ -147,6 +147,11 @@ static inline void io_apic_write(unsigne
        *(IO_APIC_BASE(apic)+4) = value;
 }
 
+static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
+{
+       *(IO_APIC_BASE(apic)+16) = vector;
+}
+
 /*
  * Re-write a value: to be used for read-modify-write
  * cycles where the read already set up the index register.

_______________________________________________
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®.