[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |