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

[Xen-changelog] Big fixes for the new IO-APIC acknowledging method. The problems



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID b39365343de08af6c76fa3492b2cffb436470b3f
# Parent  4613f42db7806c866e5057f17ad7fa340ccbc7ab
Big fixes for the new IO-APIC acknowledging method. The problems
were:
 1. Some critical Xen interrupts could get blocked behind
    unacknowledged guest interrupts. This is avoided by making
    all Xen-bound interrrupts strictly higher priority.
 2. Interrupts must not only be EOIed on the CPU that received
    them, but also in reverse order when interrupts are nested.
    A whole load of logic has been added to ensure this.

There are two boot parameters relating to all this:
 'ioapic_ack=old' -- use the old IO-APIC ACK method
 'ioapic_ack=new' -- use the new IO-APIC ACK method (default)
 'force_intack'   -- periodically force acknowledgement of
                     interrupts (default is no; useful for debugging)

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 4613f42db780 -r b39365343de0 xen/arch/x86/i8259.c
--- a/xen/arch/x86/i8259.c      Sat Apr 15 14:53:53 2006
+++ b/xen/arch/x86/i8259.c      Sat Apr 15 17:09:52 2006
@@ -318,7 +318,7 @@
      * outb_p - this has to work on a wide range of PC hardware.
      */
     outb_p(0x11, 0x20);     /* ICW1: select 8259A-1 init */
-    outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
+    outb_p(FIRST_LEGACY_VECTOR + 0, 0x21); /* ICW2: 8259A-1 IR0-7 */
     outb_p(0x04, 0x21);     /* 8259A-1 (the master) has a slave on IR2 */
     if (auto_eoi)
         outb_p(0x03, 0x21); /* master does Auto EOI */
@@ -326,7 +326,7 @@
         outb_p(0x01, 0x21); /* master expects normal EOI */
 
     outb_p(0x11, 0xA0);     /* ICW1: select 8259A-2 init */
-    outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
+    outb_p(FIRST_LEGACY_VECTOR + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 */
     outb_p(0x02, 0xA1);     /* 8259A-2 is a slave on master's IR2 */
     outb_p(0x01, 0xA1);     /* (slave's support for AEOI in flat mode
                                is to be investigated) */
diff -r 4613f42db780 -r b39365343de0 xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c    Sat Apr 15 14:53:53 2006
+++ b/xen/arch/x86/io_apic.c    Sat Apr 15 17:09:52 2006
@@ -669,11 +669,11 @@
 }
 
 /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
+u8 irq_vector[NR_IRQ_VECTORS] __read_mostly;
 
 int assign_irq_vector(int irq)
 {
-    static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
+    static int current_vector = FIRST_DYNAMIC_VECTOR, offset = 0;
 
     BUG_ON(irq >= NR_IRQ_VECTORS);
     if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
@@ -689,11 +689,11 @@
     if (current_vector == 0x80)
         goto next;
 
-    if (current_vector >= FIRST_SYSTEM_VECTOR) {
+    if (current_vector > LAST_DYNAMIC_VECTOR) {
         offset++;
         if (!(offset%8))
             return -ENOSPC;
-        current_vector = FIRST_DEVICE_VECTOR + offset;
+        current_vector = FIRST_DYNAMIC_VECTOR + offset;
     }
 
     vector_irq[current_vector] = irq;
@@ -1333,15 +1333,24 @@
     return 0; /* don't check for pending */
 }
 
-static int new_ack;
-boolean_param("new_ack", new_ack);
+int ioapic_ack_new = 1;
+static void setup_ioapic_ack(char *s)
+{
+    if ( !strcmp(s, "old") )
+        ioapic_ack_new = 0;
+    else if ( !strcmp(s, "new") )
+        ioapic_ack_new = 1;
+    else
+        printk("Unknown ioapic_ack value specified: '%s'\n", s);
+}
+custom_param("ioapic_ack", setup_ioapic_ack);
 
 static void mask_and_ack_level_ioapic_irq (unsigned int irq)
 {
     unsigned long v;
     int i;
 
-    if ( new_ack )
+    if ( ioapic_ack_new )
         return;
 
     mask_IO_APIC_irq(irq);
@@ -1384,7 +1393,7 @@
     unsigned long v;
     int i;
 
-    if ( !new_ack )
+    if ( !ioapic_ack_new )
     {
         unmask_IO_APIC_irq(irq);
         return;
@@ -1753,7 +1762,7 @@
         io_apic_irqs = ~PIC_IRQS;
 
     printk("ENABLING IO-APIC IRQs\n");
-    printk(" -> Using %s ACK method\n", new_ack ? "new" : "old");
+    printk(" -> Using %s ACK method\n", ioapic_ack_new ? "new" : "old");
 
     /*
      * Set up IO-APIC IRQ routing.
@@ -2015,9 +2024,9 @@
         return 0;
     }
 
-    if ( old_rte.vector >= FIRST_DEVICE_VECTOR )
+    if ( old_rte.vector >= FIRST_DYNAMIC_VECTOR )
         old_irq = vector_irq[old_rte.vector];
-    if ( new_rte.vector >= FIRST_DEVICE_VECTOR )
+    if ( new_rte.vector >= FIRST_DYNAMIC_VECTOR )
         new_irq = vector_irq[new_rte.vector];
 
     if ( (old_irq != new_irq) && (old_irq != -1) && IO_APIC_IRQ(old_irq) )
diff -r 4613f42db780 -r b39365343de0 xen/arch/x86/irq.c
--- a/xen/arch/x86/irq.c        Sat Apr 15 14:53:53 2006
+++ b/xen/arch/x86/irq.c        Sat Apr 15 17:09:52 2006
@@ -149,12 +149,22 @@
     u8 in_flight;
     u8 shareable;
     u8 ack_type;
-#define ACKTYPE_NONE   0 /* Final ACK is not required */
-#define ACKTYPE_SINGLE 1 /* Final ACK on any CPU */
-#define ACKTYPE_MULTI  2 /* Final ACK on the CPU that was interrupted */
-    cpumask_t cpu_ack_map;
+#define ACKTYPE_NONE   0     /* No final acknowledgement is required */
+#define ACKTYPE_UNMASK 1     /* Unmask PIC hardware (from any CPU)   */
+#define ACKTYPE_LAPIC_EOI  2 /* EOI on the CPU that was interrupted  */
+    cpumask_t cpu_eoi_map;   /* CPUs that need to EOI this interrupt */
     struct domain *guest[IRQ_MAX_GUESTS];
 } irq_guest_action_t;
+
+/*
+ * Stack of interrupts awaiting EOI on each CPU. These must be popped in
+ * order, as only the current highest-priority pending irq can be EOIed.
+ */
+static struct {
+    u8 vector;
+    u8 ready_to_end;
+} pending_lapic_eoi[NR_CPUS][NR_VECTORS] __cacheline_aligned;
+#define pending_lapic_eoi_sp(cpu) (pending_lapic_eoi[cpu][NR_VECTORS-1].vector)
 
 static void __do_IRQ_guest(int vector)
 {
@@ -162,18 +172,26 @@
     irq_desc_t         *desc = &irq_desc[vector];
     irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
     struct domain      *d;
-    int                 i;
+    int                 i, sp, cpu = smp_processor_id();
 
     if ( unlikely(action->nr_guests == 0) )
     {
-        /* An interrupt may slip through while freeing an ACKTYPE_MULTI irq. */
-        ASSERT(action->ack_type == ACKTYPE_MULTI);
+        /* An interrupt may slip through while freeing a LAPIC_EOI irq. */
+        ASSERT(action->ack_type == ACKTYPE_LAPIC_EOI);
         desc->handler->end(vector);
         return;
     }
 
-    if ( action->ack_type == ACKTYPE_MULTI )
-        cpu_set(smp_processor_id(), action->cpu_ack_map);
+    if ( action->ack_type == ACKTYPE_LAPIC_EOI )
+    {
+        sp = pending_lapic_eoi_sp(cpu);
+        ASSERT((sp == 0) || (pending_lapic_eoi[cpu][sp-1].vector < vector));
+        ASSERT(sp < (NR_VECTORS-1));
+        pending_lapic_eoi[cpu][sp].vector = vector;
+        pending_lapic_eoi[cpu][sp].ready_to_end = 0;
+        pending_lapic_eoi_sp(cpu) = sp+1;
+        cpu_set(cpu, action->cpu_eoi_map);
+    }
 
     for ( i = 0; i < action->nr_guests; i++ )
     {
@@ -190,20 +208,49 @@
     irq_desc_t         *desc = data;
     irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
     unsigned long       flags;
+    int                 vector, sp, cpu = smp_processor_id();
+
+    vector = desc - irq_desc;
 
     spin_lock_irqsave(&desc->lock, flags);
+
     if ( (desc->status & IRQ_GUEST) &&
          (action->in_flight == 0) &&
-         test_and_clear_bit(smp_processor_id(), &action->cpu_ack_map) )
-        desc->handler->end(desc - irq_desc);
-    spin_unlock_irqrestore(&desc->lock, flags);    
+         test_and_clear_bit(cpu, &action->cpu_eoi_map) )
+    {
+        sp = pending_lapic_eoi_sp(cpu);
+        do {
+            ASSERT(sp > 0);
+        } while ( pending_lapic_eoi[cpu][--sp].vector != vector );
+        ASSERT(!pending_lapic_eoi[cpu][sp].ready_to_end);
+        pending_lapic_eoi[cpu][sp].ready_to_end = 1;
+    }
+
+    for ( ; ; )
+    {
+        sp = pending_lapic_eoi_sp(cpu);
+        if ( (sp == 0) || !pending_lapic_eoi[cpu][sp-1].ready_to_end )
+        {
+            spin_unlock_irqrestore(&desc->lock, flags);    
+            return;
+        }
+        if ( pending_lapic_eoi[cpu][sp-1].vector != vector )
+        {
+            spin_unlock(&desc->lock);
+            vector = pending_lapic_eoi[cpu][sp-1].vector;
+            desc = &irq_desc[vector];
+            spin_lock(&desc->lock);
+        }
+        desc->handler->end(vector);
+        pending_lapic_eoi_sp(cpu) = sp-1;
+    }
 }
 
 int pirq_guest_unmask(struct domain *d)
 {
     irq_desc_t         *desc;
     irq_guest_action_t *action;
-    cpumask_t           cpu_ack_map = CPU_MASK_NONE;
+    cpumask_t           cpu_eoi_map = CPU_MASK_NONE;
     unsigned int        pirq, cpu = smp_processor_id();
     shared_info_t      *s = d->shared_info;
 
@@ -221,24 +268,27 @@
             ASSERT(action->ack_type != ACKTYPE_NONE);
             if ( --action->in_flight == 0 )
             {
-                if ( (action->ack_type == ACKTYPE_SINGLE) ||
-                     test_and_clear_bit(cpu, &action->cpu_ack_map) )
+                if ( action->ack_type == ACKTYPE_UNMASK )
                     desc->handler->end(irq_to_vector(pirq));
-                cpu_ack_map = action->cpu_ack_map;
+                cpu_eoi_map = action->cpu_eoi_map;
             }
         }
         spin_unlock_irq(&desc->lock);
 
-        if ( !cpus_empty(cpu_ack_map) )
-        {
-            on_selected_cpus(cpu_ack_map, end_guest_irq, desc, 1, 0);
-            cpu_ack_map = CPU_MASK_NONE;
+        if ( __test_and_clear_bit(cpu, &cpu_eoi_map) )
+            end_guest_irq(desc);
+
+        if ( !cpus_empty(cpu_eoi_map) )
+        {
+            on_selected_cpus(cpu_eoi_map, end_guest_irq, desc, 1, 0);
+            cpu_eoi_map = CPU_MASK_NONE;
         }
     }
 
     return 0;
 }
 
+extern int ioapic_ack_new;
 int pirq_acktype(int irq)
 {
     irq_desc_t  *desc;
@@ -259,14 +309,17 @@
 
     /* Legacy PIC interrupts can be acknowledged from any CPU. */
     if ( !strcmp(desc->handler->typename, "XT-PIC") )
-        return ACKTYPE_SINGLE;
+        return ACKTYPE_UNMASK;
 
     /*
-     * By default assume that an interrupt must be finally acknowledged on
-     * the CPU on which it was received. This is true for level-triggered
-     * IO-APIC interrupts, for example, where we tickle the LAPIC to EOI.
+     * Level-triggered IO-APIC interrupts need to be acknowledged on the CPU
+     * on which they were received. This is because we tickle the LAPIC to EOI.
      */
-    return ACKTYPE_MULTI;
+    if ( !strcmp(desc->handler->typename, "IO-APIC-level") )
+        return ioapic_ack_new ? ACKTYPE_LAPIC_EOI : ACKTYPE_UNMASK;
+
+    BUG();
+    return 0;
 }
 
 int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
@@ -313,7 +366,7 @@
         action->in_flight   = 0;
         action->shareable   = will_share;
         action->ack_type    = pirq_acktype(irq);
-        action->cpu_ack_map = CPU_MASK_NONE;
+        action->cpu_eoi_map = CPU_MASK_NONE;
 
         desc->depth = 0;
         desc->status |= IRQ_GUEST;
@@ -352,7 +405,7 @@
     unsigned int        vector = irq_to_vector(irq);
     irq_desc_t         *desc = &irq_desc[vector];
     irq_guest_action_t *action;
-    cpumask_t           cpu_ack_map;
+    cpumask_t           cpu_eoi_map;
     unsigned long       flags;
     int                 i;
 
@@ -370,30 +423,30 @@
 
     switch ( action->ack_type )
     {
-    case ACKTYPE_SINGLE:
+    case ACKTYPE_UNMASK:
         if ( test_and_clear_bit(irq, &d->pirq_mask) &&
              (--action->in_flight == 0) )
             desc->handler->end(vector);
         break;
-    case ACKTYPE_MULTI:
+    case ACKTYPE_LAPIC_EOI:
         if ( test_and_clear_bit(irq, &d->pirq_mask) )
             --action->in_flight;
         while ( action->in_flight == 0 )
         {
             /* We cannot release guest info until all pending ACKs are done. */
-            cpu_ack_map = action->cpu_ack_map;
-            if ( cpus_empty(cpu_ack_map) )
+            cpu_eoi_map = action->cpu_eoi_map;
+            if ( cpus_empty(cpu_eoi_map) )
                 break;
 
             /* We cannot hold the lock while interrupting other CPUs. */
             spin_unlock_irqrestore(&desc->lock, flags);    
-            on_selected_cpus(cpu_ack_map, end_guest_irq, desc, 1, 1);
+            on_selected_cpus(cpu_eoi_map, end_guest_irq, desc, 1, 1);
             spin_lock_irqsave(&desc->lock, flags);
 
             /* The world can change while we do not hold the lock. */
             if ( !(desc->status & IRQ_GUEST) )
                 goto out;
-            if ( (action->ack_type != ACKTYPE_MULTI) ||
+            if ( (action->ack_type != ACKTYPE_LAPIC_EOI) ||
                  (action->nr_guests != 0) )
                 break;
         }
@@ -406,7 +459,7 @@
         goto out;
 
     BUG_ON(action->in_flight != 0);
-    BUG_ON(!cpus_empty(action->cpu_ack_map));
+    BUG_ON(!cpus_empty(action->cpu_eoi_map));
 
     desc->action = NULL;
     xfree(action);
@@ -487,3 +540,61 @@
     return 0;
 }
 __initcall(setup_dump_irqs);
+
+static struct timer end_irq_timer[NR_CPUS];
+
+static void end_irq_timeout(void *unused)
+{
+    irq_desc_t         *desc;
+    irq_guest_action_t *action;
+    cpumask_t           cpu_eoi_map;
+    unsigned int        cpu = smp_processor_id();
+    int                 sp, vector, i;
+
+    local_irq_disable();
+
+    if ( (sp = pending_lapic_eoi_sp(cpu)) == 0 )
+    {
+        local_irq_enable();
+        return;
+    }
+
+    vector = pending_lapic_eoi[cpu][sp-1].vector;
+    ASSERT(!pending_lapic_eoi[cpu][sp-1].ready_to_end);
+
+    desc = &irq_desc[vector];
+    spin_lock(&desc->lock);
+    action = (irq_guest_action_t *)desc->action;
+    ASSERT(action->ack_type == ACKTYPE_LAPIC_EOI);
+    ASSERT(desc->status & IRQ_GUEST);
+    for ( i = 0; i < action->nr_guests; i++ )
+        clear_bit(vector_to_irq(vector), &action->guest[i]->pirq_mask);
+    action->in_flight = 0;
+    cpu_eoi_map = action->cpu_eoi_map;
+    spin_unlock(&desc->lock);
+
+    local_irq_enable();
+
+    if ( !cpus_empty(cpu_eoi_map) )
+        on_selected_cpus(cpu_eoi_map, end_guest_irq, desc, 1, 0);
+
+    set_timer(&end_irq_timer[cpu], NOW() + MILLISECS(1000));
+}
+
+static void __init __setup_irq_timeout(void *unused)
+{
+    int cpu = smp_processor_id();
+    init_timer(&end_irq_timer[cpu], end_irq_timeout, NULL, cpu);
+    set_timer(&end_irq_timer[cpu], NOW() + MILLISECS(1000));
+}
+
+static int force_intack;
+boolean_param("force_intack", force_intack);
+
+static int __init setup_irq_timeout(void)
+{
+    if ( force_intack )
+        on_each_cpu(__setup_irq_timeout, NULL, 1, 1);
+    return 0;
+}
+__initcall(setup_irq_timeout);
diff -r 4613f42db780 -r b39365343de0 xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c    Sat Apr 15 14:53:53 2006
+++ b/xen/arch/x86/smpboot.c    Sat Apr 15 17:09:52 2006
@@ -41,6 +41,7 @@
 #include <xen/irq.h>
 #include <xen/delay.h>
 #include <xen/softirq.h>
+#include <xen/serial.h>
 #include <asm/current.h>
 #include <asm/mc146818rtc.h>
 #include <asm/desc.h>
@@ -1231,12 +1232,25 @@
 
 void __init smp_intr_init(void)
 {
+       int irq, seridx;
+
        /*
         * IRQ0 must be given a fixed assignment and initialized,
         * because it's used before the IO-APIC is set up.
         */
-       irq_vector[0] = FIRST_DEVICE_VECTOR;
-       vector_irq[FIRST_DEVICE_VECTOR] = 0;
+       irq_vector[0] = FIRST_HIPRIORITY_VECTOR;
+       vector_irq[FIRST_HIPRIORITY_VECTOR] = 0;
+
+       /*
+        * Also ensure serial interrupts are high priority. We do not
+        * want them to be blocked by unacknowledged guest-bound interrupts.
+        */
+       for (seridx = 0; seridx < 2; seridx++) {
+               if ((irq = serial_irq(seridx)) < 0)
+                       continue;
+               irq_vector[irq] = FIRST_HIPRIORITY_VECTOR + seridx + 1;
+               vector_irq[FIRST_HIPRIORITY_VECTOR + seridx + 1] = irq;
+       }
 
        /* IPI for event checking. */
        set_intr_gate(EVENT_CHECK_VECTOR, event_check_interrupt);
diff -r 4613f42db780 -r b39365343de0 xen/drivers/char/ns16550.c
--- a/xen/drivers/char/ns16550.c        Sat Apr 15 14:53:53 2006
+++ b/xen/drivers/char/ns16550.c        Sat Apr 15 17:09:52 2006
@@ -260,13 +260,20 @@
 #define ns16550_endboot NULL
 #endif
 
+static int ns16550_irq(struct serial_port *port)
+{
+    struct ns16550 *uart = port->uart;
+    return ((uart->irq > 0) ? uart->irq : -1);
+}
+
 static struct uart_driver ns16550_driver = {
     .init_preirq  = ns16550_init_preirq,
     .init_postirq = ns16550_init_postirq,
     .endboot      = ns16550_endboot,
     .tx_empty     = ns16550_tx_empty,
     .putc         = ns16550_putc,
-    .getc         = ns16550_getc
+    .getc         = ns16550_getc,
+    .irq          = ns16550_irq
 };
 
 static int parse_parity_char(int c)
diff -r 4613f42db780 -r b39365343de0 xen/drivers/char/serial.c
--- a/xen/drivers/char/serial.c Sat Apr 15 14:53:53 2006
+++ b/xen/drivers/char/serial.c Sat Apr 15 17:09:52 2006
@@ -372,6 +372,15 @@
             com[i].driver->endboot(&com[i]);
 }
 
+int serial_irq(int idx)
+{
+    if ( (idx >= 0) && (idx < ARRAY_SIZE(com)) &&
+         com[idx].driver && com[idx].driver->irq )
+        return com[idx].driver->irq(&com[idx]);
+
+    return -1;
+}
+
 void serial_register_uart(int idx, struct uart_driver *driver, void *uart)
 {
     /* Store UART-specific info. */
diff -r 4613f42db780 -r b39365343de0 xen/include/asm-x86/irq.h
--- a/xen/include/asm-x86/irq.h Sat Apr 15 14:53:53 2006
+++ b/xen/include/asm-x86/irq.h Sat Apr 15 17:09:52 2006
@@ -11,8 +11,8 @@
 #define IO_APIC_IRQ(irq)    (((irq) >= 16) || ((1<<(irq)) & io_apic_irqs))
 #define IO_APIC_VECTOR(irq) (irq_vector[irq])
 
-#define LEGACY_VECTOR(irq)          ((irq) + FIRST_EXTERNAL_VECTOR)
-#define LEGACY_IRQ_FROM_VECTOR(vec) ((vec) - FIRST_EXTERNAL_VECTOR)
+#define LEGACY_VECTOR(irq)          ((irq) + FIRST_LEGACY_VECTOR)
+#define LEGACY_IRQ_FROM_VECTOR(vec) ((vec) - FIRST_LEGACY_VECTOR)
 
 #define irq_to_vector(irq)  \
     (IO_APIC_IRQ(irq) ? IO_APIC_VECTOR(irq) : LEGACY_VECTOR(irq))
diff -r 4613f42db780 -r b39365343de0 
xen/include/asm-x86/mach-default/irq_vectors.h
--- a/xen/include/asm-x86/mach-default/irq_vectors.h    Sat Apr 15 14:53:53 2006
+++ b/xen/include/asm-x86/mach-default/irq_vectors.h    Sat Apr 15 17:09:52 2006
@@ -1,96 +1,36 @@
-/*
- * This file should contain #defines for all of the interrupt vector
- * numbers used by this architecture.
- *
- * In addition, there are some standard defines:
- *
- *     FIRST_EXTERNAL_VECTOR:
- *             The first free place for external interrupts
- *
- *     SYSCALL_VECTOR:
- *             The IRQ vector a syscall makes the user to kernel transition
- *             under.
- *
- *     TIMER_IRQ:
- *             The IRQ number the timer interrupt comes in at.
- *
- *     NR_IRQS:
- *             The total number of interrupt vectors (including all the
- *             architecture specific interrupts) needed.
- *
- */                    
 #ifndef _ASM_IRQ_VECTORS_H
 #define _ASM_IRQ_VECTORS_H
 
-/*
- * IDT vectors usable for external interrupt sources start
- * at 0x20:
- */
-#define FIRST_EXTERNAL_VECTOR  0x20
-
-#define HYPERCALL_VECTOR       0x82
-
-/*
- * Vectors 0x20-0x2f are used for ISA interrupts.
- */
-
-/*
- * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
- *
- *  some of the following vectors are 'rare', they are merged
- *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
- *  TLB, reschedule and local APIC vectors are performance-critical.
- *
- *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
- */
+/* Processor-initiated interrupts are all high priority. */
 #define SPURIOUS_APIC_VECTOR   0xff
 #define ERROR_APIC_VECTOR      0xfe
 #define INVALIDATE_TLB_VECTOR  0xfd
 #define EVENT_CHECK_VECTOR     0xfc
 #define CALL_FUNCTION_VECTOR   0xfb
-
-#define THERMAL_APIC_VECTOR    0xf0
-/*
- * Local APIC timer IRQ vector is on a different priority level,
- * to work around the 'lost local interrupt if more than 2 IRQ
- * sources per level' errata.
- */
-#define LOCAL_TIMER_VECTOR     0xef
+#define THERMAL_APIC_VECTOR    0xfa
+#define LOCAL_TIMER_VECTOR     0xf9
 
 /*
- * First APIC vector available to drivers: (vectors 0x30-0xee)
- * we start at 0x31 to spread out vectors evenly between priority
- * levels. (0x80 is the syscall vector)
+ * High-priority dynamically-allocated vectors. For interrupts that
+ * must be higher priority than any guest-bound interrupt.
  */
-#define FIRST_DEVICE_VECTOR    0x31
-#define FIRST_SYSTEM_VECTOR    0xef
+#define FIRST_HIPRIORITY_VECTOR        0xf0
+#define LAST_HIPRIORITY_VECTOR  0xf8
 
-#define TIMER_IRQ 0
+/* Legacy PIC uses vectors 0xe0-0xef. */
+#define FIRST_LEGACY_VECTOR    0xe0
+#define LAST_LEGACY_VECTOR      0xef
 
-/*
- * 16 8259A IRQ's, 208 potential APIC interrupt sources.
- * Right now the APIC is mostly only used for SMP.
- * 256 vectors is an architectural limit. (we can have
- * more than 256 devices theoretically, but they will
- * have to use shared interrupts)
- * Since vectors 0x00-0x1f are used/reserved for the CPU,
- * the usable vector space is 0x20-0xff (224 vectors)
- */
+#define HYPERCALL_VECTOR       0x82
 
-/*
- * The maximum number of vectors supported by i386 processors
- * is limited to 256. For processors other than i386, NR_VECTORS
- * should be changed accordingly.
- */
+/* Dynamically-allocated vectors available to any driver. */
+#define FIRST_DYNAMIC_VECTOR   0x20
+#define LAST_DYNAMIC_VECTOR    0xdf
+
 #define NR_VECTORS 256
 
-#include "irq_vectors_limits.h"
-
-#define FPU_IRQ                        13
-
-#define        FIRST_VM86_IRQ          3
-#define LAST_VM86_IRQ          15
-#define invalid_vm86_irq(irq)  ((irq) < 3 || (irq) > 15)
-
+/* Limited by number of trap vectors. */
+#define NR_IRQS        NR_VECTORS
+#define NR_IRQ_VECTORS NR_IRQS
 
 #endif /* _ASM_IRQ_VECTORS_H */
diff -r 4613f42db780 -r b39365343de0 xen/include/xen/serial.h
--- a/xen/include/xen/serial.h  Sat Apr 15 14:53:53 2006
+++ b/xen/include/xen/serial.h  Sat Apr 15 17:09:52 2006
@@ -57,6 +57,8 @@
     void (*putc)(struct serial_port *, char);
     /* Get a character from the serial line: returns 0 if none available. */
     int  (*getc)(struct serial_port *, char *);
+    /* Get IRQ number for this port's serial line: returns -1 if none. */
+    int  (*irq)(struct serial_port *);
 };
 
 /* 'Serial handles' are composed from the following fields. */
@@ -99,6 +101,9 @@
 /* Return number of bytes headroom in transmit buffer. */
 int serial_tx_space(int handle);
 
+/* Return irq number for specified serial port (identified by index). */
+int serial_irq(int idx);
+
 /*
  * Initialisation and helper functions for uart drivers.
  */
diff -r 4613f42db780 -r b39365343de0 
xen/include/asm-x86/mach-default/irq_vectors_limits.h
--- a/xen/include/asm-x86/mach-default/irq_vectors_limits.h     Sat Apr 15 
14:53:53 2006
+++ /dev/null   Sat Apr 15 17:09:52 2006
@@ -1,8 +0,0 @@
-#ifndef _ASM_IRQ_VECTORS_LIMITS_H
-#define _ASM_IRQ_VECTORS_LIMITS_H
-
-/* Limited by number of trap vectors. */
-#define NR_IRQS        FIRST_SYSTEM_VECTOR
-#define NR_IRQ_VECTORS NR_IRQS
-
-#endif /* _ASM_IRQ_VECTORS_LIMITS_H */

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