direct-io.hg
changeset 9664:b39365343de0
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@xensource.com>
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@xensource.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Sat Apr 15 18:09:52 2006 +0100 (2006-04-15) |
parents | 4613f42db780 |
children | 91da9a1b7196 |
files | xen/arch/x86/i8259.c xen/arch/x86/io_apic.c xen/arch/x86/irq.c xen/arch/x86/smpboot.c xen/drivers/char/ns16550.c xen/drivers/char/serial.c xen/include/asm-x86/irq.h xen/include/asm-x86/mach-default/irq_vectors.h xen/include/xen/serial.h |
line diff
1.1 --- a/xen/arch/x86/i8259.c Sat Apr 15 15:53:53 2006 +0100 1.2 +++ b/xen/arch/x86/i8259.c Sat Apr 15 18:09:52 2006 +0100 1.3 @@ -318,7 +318,7 @@ void __init init_8259A(int auto_eoi) 1.4 * outb_p - this has to work on a wide range of PC hardware. 1.5 */ 1.6 outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */ 1.7 - outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */ 1.8 + outb_p(FIRST_LEGACY_VECTOR + 0, 0x21); /* ICW2: 8259A-1 IR0-7 */ 1.9 outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */ 1.10 if (auto_eoi) 1.11 outb_p(0x03, 0x21); /* master does Auto EOI */ 1.12 @@ -326,7 +326,7 @@ void __init init_8259A(int auto_eoi) 1.13 outb_p(0x01, 0x21); /* master expects normal EOI */ 1.14 1.15 outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */ 1.16 - outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */ 1.17 + outb_p(FIRST_LEGACY_VECTOR + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 */ 1.18 outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */ 1.19 outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode 1.20 is to be investigated) */
2.1 --- a/xen/arch/x86/io_apic.c Sat Apr 15 15:53:53 2006 +0100 2.2 +++ b/xen/arch/x86/io_apic.c Sat Apr 15 18:09:52 2006 +0100 2.3 @@ -669,11 +669,11 @@ static inline int IO_APIC_irq_trigger(in 2.4 } 2.5 2.6 /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ 2.7 -u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 }; 2.8 +u8 irq_vector[NR_IRQ_VECTORS] __read_mostly; 2.9 2.10 int assign_irq_vector(int irq) 2.11 { 2.12 - static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; 2.13 + static int current_vector = FIRST_DYNAMIC_VECTOR, offset = 0; 2.14 2.15 BUG_ON(irq >= NR_IRQ_VECTORS); 2.16 if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) 2.17 @@ -689,11 +689,11 @@ next: 2.18 if (current_vector == 0x80) 2.19 goto next; 2.20 2.21 - if (current_vector >= FIRST_SYSTEM_VECTOR) { 2.22 + if (current_vector > LAST_DYNAMIC_VECTOR) { 2.23 offset++; 2.24 if (!(offset%8)) 2.25 return -ENOSPC; 2.26 - current_vector = FIRST_DEVICE_VECTOR + offset; 2.27 + current_vector = FIRST_DYNAMIC_VECTOR + offset; 2.28 } 2.29 2.30 vector_irq[current_vector] = irq; 2.31 @@ -1333,15 +1333,24 @@ static unsigned int startup_level_ioapic 2.32 return 0; /* don't check for pending */ 2.33 } 2.34 2.35 -static int new_ack; 2.36 -boolean_param("new_ack", new_ack); 2.37 +int ioapic_ack_new = 1; 2.38 +static void setup_ioapic_ack(char *s) 2.39 +{ 2.40 + if ( !strcmp(s, "old") ) 2.41 + ioapic_ack_new = 0; 2.42 + else if ( !strcmp(s, "new") ) 2.43 + ioapic_ack_new = 1; 2.44 + else 2.45 + printk("Unknown ioapic_ack value specified: '%s'\n", s); 2.46 +} 2.47 +custom_param("ioapic_ack", setup_ioapic_ack); 2.48 2.49 static void mask_and_ack_level_ioapic_irq (unsigned int irq) 2.50 { 2.51 unsigned long v; 2.52 int i; 2.53 2.54 - if ( new_ack ) 2.55 + if ( ioapic_ack_new ) 2.56 return; 2.57 2.58 mask_IO_APIC_irq(irq); 2.59 @@ -1384,7 +1393,7 @@ static void end_level_ioapic_irq (unsign 2.60 unsigned long v; 2.61 int i; 2.62 2.63 - if ( !new_ack ) 2.64 + if ( !ioapic_ack_new ) 2.65 { 2.66 unmask_IO_APIC_irq(irq); 2.67 return; 2.68 @@ -1753,7 +1762,7 @@ void __init setup_IO_APIC(void) 2.69 io_apic_irqs = ~PIC_IRQS; 2.70 2.71 printk("ENABLING IO-APIC IRQs\n"); 2.72 - printk(" -> Using %s ACK method\n", new_ack ? "new" : "old"); 2.73 + printk(" -> Using %s ACK method\n", ioapic_ack_new ? "new" : "old"); 2.74 2.75 /* 2.76 * Set up IO-APIC IRQ routing. 2.77 @@ -2015,9 +2024,9 @@ int ioapic_guest_write(unsigned long phy 2.78 return 0; 2.79 } 2.80 2.81 - if ( old_rte.vector >= FIRST_DEVICE_VECTOR ) 2.82 + if ( old_rte.vector >= FIRST_DYNAMIC_VECTOR ) 2.83 old_irq = vector_irq[old_rte.vector]; 2.84 - if ( new_rte.vector >= FIRST_DEVICE_VECTOR ) 2.85 + if ( new_rte.vector >= FIRST_DYNAMIC_VECTOR ) 2.86 new_irq = vector_irq[new_rte.vector]; 2.87 2.88 if ( (old_irq != new_irq) && (old_irq != -1) && IO_APIC_IRQ(old_irq) )
3.1 --- a/xen/arch/x86/irq.c Sat Apr 15 15:53:53 2006 +0100 3.2 +++ b/xen/arch/x86/irq.c Sat Apr 15 18:09:52 2006 +0100 3.3 @@ -149,31 +149,49 @@ typedef struct { 3.4 u8 in_flight; 3.5 u8 shareable; 3.6 u8 ack_type; 3.7 -#define ACKTYPE_NONE 0 /* Final ACK is not required */ 3.8 -#define ACKTYPE_SINGLE 1 /* Final ACK on any CPU */ 3.9 -#define ACKTYPE_MULTI 2 /* Final ACK on the CPU that was interrupted */ 3.10 - cpumask_t cpu_ack_map; 3.11 +#define ACKTYPE_NONE 0 /* No final acknowledgement is required */ 3.12 +#define ACKTYPE_UNMASK 1 /* Unmask PIC hardware (from any CPU) */ 3.13 +#define ACKTYPE_LAPIC_EOI 2 /* EOI on the CPU that was interrupted */ 3.14 + cpumask_t cpu_eoi_map; /* CPUs that need to EOI this interrupt */ 3.15 struct domain *guest[IRQ_MAX_GUESTS]; 3.16 } irq_guest_action_t; 3.17 3.18 +/* 3.19 + * Stack of interrupts awaiting EOI on each CPU. These must be popped in 3.20 + * order, as only the current highest-priority pending irq can be EOIed. 3.21 + */ 3.22 +static struct { 3.23 + u8 vector; 3.24 + u8 ready_to_end; 3.25 +} pending_lapic_eoi[NR_CPUS][NR_VECTORS] __cacheline_aligned; 3.26 +#define pending_lapic_eoi_sp(cpu) (pending_lapic_eoi[cpu][NR_VECTORS-1].vector) 3.27 + 3.28 static void __do_IRQ_guest(int vector) 3.29 { 3.30 unsigned int irq = vector_to_irq(vector); 3.31 irq_desc_t *desc = &irq_desc[vector]; 3.32 irq_guest_action_t *action = (irq_guest_action_t *)desc->action; 3.33 struct domain *d; 3.34 - int i; 3.35 + int i, sp, cpu = smp_processor_id(); 3.36 3.37 if ( unlikely(action->nr_guests == 0) ) 3.38 { 3.39 - /* An interrupt may slip through while freeing an ACKTYPE_MULTI irq. */ 3.40 - ASSERT(action->ack_type == ACKTYPE_MULTI); 3.41 + /* An interrupt may slip through while freeing a LAPIC_EOI irq. */ 3.42 + ASSERT(action->ack_type == ACKTYPE_LAPIC_EOI); 3.43 desc->handler->end(vector); 3.44 return; 3.45 } 3.46 3.47 - if ( action->ack_type == ACKTYPE_MULTI ) 3.48 - cpu_set(smp_processor_id(), action->cpu_ack_map); 3.49 + if ( action->ack_type == ACKTYPE_LAPIC_EOI ) 3.50 + { 3.51 + sp = pending_lapic_eoi_sp(cpu); 3.52 + ASSERT((sp == 0) || (pending_lapic_eoi[cpu][sp-1].vector < vector)); 3.53 + ASSERT(sp < (NR_VECTORS-1)); 3.54 + pending_lapic_eoi[cpu][sp].vector = vector; 3.55 + pending_lapic_eoi[cpu][sp].ready_to_end = 0; 3.56 + pending_lapic_eoi_sp(cpu) = sp+1; 3.57 + cpu_set(cpu, action->cpu_eoi_map); 3.58 + } 3.59 3.60 for ( i = 0; i < action->nr_guests; i++ ) 3.61 { 3.62 @@ -190,20 +208,49 @@ static void end_guest_irq(void *data) 3.63 irq_desc_t *desc = data; 3.64 irq_guest_action_t *action = (irq_guest_action_t *)desc->action; 3.65 unsigned long flags; 3.66 + int vector, sp, cpu = smp_processor_id(); 3.67 + 3.68 + vector = desc - irq_desc; 3.69 3.70 spin_lock_irqsave(&desc->lock, flags); 3.71 + 3.72 if ( (desc->status & IRQ_GUEST) && 3.73 (action->in_flight == 0) && 3.74 - test_and_clear_bit(smp_processor_id(), &action->cpu_ack_map) ) 3.75 - desc->handler->end(desc - irq_desc); 3.76 - spin_unlock_irqrestore(&desc->lock, flags); 3.77 + test_and_clear_bit(cpu, &action->cpu_eoi_map) ) 3.78 + { 3.79 + sp = pending_lapic_eoi_sp(cpu); 3.80 + do { 3.81 + ASSERT(sp > 0); 3.82 + } while ( pending_lapic_eoi[cpu][--sp].vector != vector ); 3.83 + ASSERT(!pending_lapic_eoi[cpu][sp].ready_to_end); 3.84 + pending_lapic_eoi[cpu][sp].ready_to_end = 1; 3.85 + } 3.86 + 3.87 + for ( ; ; ) 3.88 + { 3.89 + sp = pending_lapic_eoi_sp(cpu); 3.90 + if ( (sp == 0) || !pending_lapic_eoi[cpu][sp-1].ready_to_end ) 3.91 + { 3.92 + spin_unlock_irqrestore(&desc->lock, flags); 3.93 + return; 3.94 + } 3.95 + if ( pending_lapic_eoi[cpu][sp-1].vector != vector ) 3.96 + { 3.97 + spin_unlock(&desc->lock); 3.98 + vector = pending_lapic_eoi[cpu][sp-1].vector; 3.99 + desc = &irq_desc[vector]; 3.100 + spin_lock(&desc->lock); 3.101 + } 3.102 + desc->handler->end(vector); 3.103 + pending_lapic_eoi_sp(cpu) = sp-1; 3.104 + } 3.105 } 3.106 3.107 int pirq_guest_unmask(struct domain *d) 3.108 { 3.109 irq_desc_t *desc; 3.110 irq_guest_action_t *action; 3.111 - cpumask_t cpu_ack_map = CPU_MASK_NONE; 3.112 + cpumask_t cpu_eoi_map = CPU_MASK_NONE; 3.113 unsigned int pirq, cpu = smp_processor_id(); 3.114 shared_info_t *s = d->shared_info; 3.115 3.116 @@ -221,24 +268,27 @@ int pirq_guest_unmask(struct domain *d) 3.117 ASSERT(action->ack_type != ACKTYPE_NONE); 3.118 if ( --action->in_flight == 0 ) 3.119 { 3.120 - if ( (action->ack_type == ACKTYPE_SINGLE) || 3.121 - test_and_clear_bit(cpu, &action->cpu_ack_map) ) 3.122 + if ( action->ack_type == ACKTYPE_UNMASK ) 3.123 desc->handler->end(irq_to_vector(pirq)); 3.124 - cpu_ack_map = action->cpu_ack_map; 3.125 + cpu_eoi_map = action->cpu_eoi_map; 3.126 } 3.127 } 3.128 spin_unlock_irq(&desc->lock); 3.129 3.130 - if ( !cpus_empty(cpu_ack_map) ) 3.131 + if ( __test_and_clear_bit(cpu, &cpu_eoi_map) ) 3.132 + end_guest_irq(desc); 3.133 + 3.134 + if ( !cpus_empty(cpu_eoi_map) ) 3.135 { 3.136 - on_selected_cpus(cpu_ack_map, end_guest_irq, desc, 1, 0); 3.137 - cpu_ack_map = CPU_MASK_NONE; 3.138 + on_selected_cpus(cpu_eoi_map, end_guest_irq, desc, 1, 0); 3.139 + cpu_eoi_map = CPU_MASK_NONE; 3.140 } 3.141 } 3.142 3.143 return 0; 3.144 } 3.145 3.146 +extern int ioapic_ack_new; 3.147 int pirq_acktype(int irq) 3.148 { 3.149 irq_desc_t *desc; 3.150 @@ -259,14 +309,17 @@ int pirq_acktype(int irq) 3.151 3.152 /* Legacy PIC interrupts can be acknowledged from any CPU. */ 3.153 if ( !strcmp(desc->handler->typename, "XT-PIC") ) 3.154 - return ACKTYPE_SINGLE; 3.155 + return ACKTYPE_UNMASK; 3.156 3.157 /* 3.158 - * By default assume that an interrupt must be finally acknowledged on 3.159 - * the CPU on which it was received. This is true for level-triggered 3.160 - * IO-APIC interrupts, for example, where we tickle the LAPIC to EOI. 3.161 + * Level-triggered IO-APIC interrupts need to be acknowledged on the CPU 3.162 + * on which they were received. This is because we tickle the LAPIC to EOI. 3.163 */ 3.164 - return ACKTYPE_MULTI; 3.165 + if ( !strcmp(desc->handler->typename, "IO-APIC-level") ) 3.166 + return ioapic_ack_new ? ACKTYPE_LAPIC_EOI : ACKTYPE_UNMASK; 3.167 + 3.168 + BUG(); 3.169 + return 0; 3.170 } 3.171 3.172 int pirq_guest_bind(struct vcpu *v, int irq, int will_share) 3.173 @@ -313,7 +366,7 @@ int pirq_guest_bind(struct vcpu *v, int 3.174 action->in_flight = 0; 3.175 action->shareable = will_share; 3.176 action->ack_type = pirq_acktype(irq); 3.177 - action->cpu_ack_map = CPU_MASK_NONE; 3.178 + action->cpu_eoi_map = CPU_MASK_NONE; 3.179 3.180 desc->depth = 0; 3.181 desc->status |= IRQ_GUEST; 3.182 @@ -352,7 +405,7 @@ int pirq_guest_unbind(struct domain *d, 3.183 unsigned int vector = irq_to_vector(irq); 3.184 irq_desc_t *desc = &irq_desc[vector]; 3.185 irq_guest_action_t *action; 3.186 - cpumask_t cpu_ack_map; 3.187 + cpumask_t cpu_eoi_map; 3.188 unsigned long flags; 3.189 int i; 3.190 3.191 @@ -370,30 +423,30 @@ int pirq_guest_unbind(struct domain *d, 3.192 3.193 switch ( action->ack_type ) 3.194 { 3.195 - case ACKTYPE_SINGLE: 3.196 + case ACKTYPE_UNMASK: 3.197 if ( test_and_clear_bit(irq, &d->pirq_mask) && 3.198 (--action->in_flight == 0) ) 3.199 desc->handler->end(vector); 3.200 break; 3.201 - case ACKTYPE_MULTI: 3.202 + case ACKTYPE_LAPIC_EOI: 3.203 if ( test_and_clear_bit(irq, &d->pirq_mask) ) 3.204 --action->in_flight; 3.205 while ( action->in_flight == 0 ) 3.206 { 3.207 /* We cannot release guest info until all pending ACKs are done. */ 3.208 - cpu_ack_map = action->cpu_ack_map; 3.209 - if ( cpus_empty(cpu_ack_map) ) 3.210 + cpu_eoi_map = action->cpu_eoi_map; 3.211 + if ( cpus_empty(cpu_eoi_map) ) 3.212 break; 3.213 3.214 /* We cannot hold the lock while interrupting other CPUs. */ 3.215 spin_unlock_irqrestore(&desc->lock, flags); 3.216 - on_selected_cpus(cpu_ack_map, end_guest_irq, desc, 1, 1); 3.217 + on_selected_cpus(cpu_eoi_map, end_guest_irq, desc, 1, 1); 3.218 spin_lock_irqsave(&desc->lock, flags); 3.219 3.220 /* The world can change while we do not hold the lock. */ 3.221 if ( !(desc->status & IRQ_GUEST) ) 3.222 goto out; 3.223 - if ( (action->ack_type != ACKTYPE_MULTI) || 3.224 + if ( (action->ack_type != ACKTYPE_LAPIC_EOI) || 3.225 (action->nr_guests != 0) ) 3.226 break; 3.227 } 3.228 @@ -406,7 +459,7 @@ int pirq_guest_unbind(struct domain *d, 3.229 goto out; 3.230 3.231 BUG_ON(action->in_flight != 0); 3.232 - BUG_ON(!cpus_empty(action->cpu_ack_map)); 3.233 + BUG_ON(!cpus_empty(action->cpu_eoi_map)); 3.234 3.235 desc->action = NULL; 3.236 xfree(action); 3.237 @@ -487,3 +540,61 @@ static int __init setup_dump_irqs(void) 3.238 return 0; 3.239 } 3.240 __initcall(setup_dump_irqs); 3.241 + 3.242 +static struct timer end_irq_timer[NR_CPUS]; 3.243 + 3.244 +static void end_irq_timeout(void *unused) 3.245 +{ 3.246 + irq_desc_t *desc; 3.247 + irq_guest_action_t *action; 3.248 + cpumask_t cpu_eoi_map; 3.249 + unsigned int cpu = smp_processor_id(); 3.250 + int sp, vector, i; 3.251 + 3.252 + local_irq_disable(); 3.253 + 3.254 + if ( (sp = pending_lapic_eoi_sp(cpu)) == 0 ) 3.255 + { 3.256 + local_irq_enable(); 3.257 + return; 3.258 + } 3.259 + 3.260 + vector = pending_lapic_eoi[cpu][sp-1].vector; 3.261 + ASSERT(!pending_lapic_eoi[cpu][sp-1].ready_to_end); 3.262 + 3.263 + desc = &irq_desc[vector]; 3.264 + spin_lock(&desc->lock); 3.265 + action = (irq_guest_action_t *)desc->action; 3.266 + ASSERT(action->ack_type == ACKTYPE_LAPIC_EOI); 3.267 + ASSERT(desc->status & IRQ_GUEST); 3.268 + for ( i = 0; i < action->nr_guests; i++ ) 3.269 + clear_bit(vector_to_irq(vector), &action->guest[i]->pirq_mask); 3.270 + action->in_flight = 0; 3.271 + cpu_eoi_map = action->cpu_eoi_map; 3.272 + spin_unlock(&desc->lock); 3.273 + 3.274 + local_irq_enable(); 3.275 + 3.276 + if ( !cpus_empty(cpu_eoi_map) ) 3.277 + on_selected_cpus(cpu_eoi_map, end_guest_irq, desc, 1, 0); 3.278 + 3.279 + set_timer(&end_irq_timer[cpu], NOW() + MILLISECS(1000)); 3.280 +} 3.281 + 3.282 +static void __init __setup_irq_timeout(void *unused) 3.283 +{ 3.284 + int cpu = smp_processor_id(); 3.285 + init_timer(&end_irq_timer[cpu], end_irq_timeout, NULL, cpu); 3.286 + set_timer(&end_irq_timer[cpu], NOW() + MILLISECS(1000)); 3.287 +} 3.288 + 3.289 +static int force_intack; 3.290 +boolean_param("force_intack", force_intack); 3.291 + 3.292 +static int __init setup_irq_timeout(void) 3.293 +{ 3.294 + if ( force_intack ) 3.295 + on_each_cpu(__setup_irq_timeout, NULL, 1, 1); 3.296 + return 0; 3.297 +} 3.298 +__initcall(setup_irq_timeout);
4.1 --- a/xen/arch/x86/smpboot.c Sat Apr 15 15:53:53 2006 +0100 4.2 +++ b/xen/arch/x86/smpboot.c Sat Apr 15 18:09:52 2006 +0100 4.3 @@ -41,6 +41,7 @@ 4.4 #include <xen/irq.h> 4.5 #include <xen/delay.h> 4.6 #include <xen/softirq.h> 4.7 +#include <xen/serial.h> 4.8 #include <asm/current.h> 4.9 #include <asm/mc146818rtc.h> 4.10 #include <asm/desc.h> 4.11 @@ -1231,12 +1232,25 @@ void __init smp_cpus_done(unsigned int m 4.12 4.13 void __init smp_intr_init(void) 4.14 { 4.15 + int irq, seridx; 4.16 + 4.17 /* 4.18 * IRQ0 must be given a fixed assignment and initialized, 4.19 * because it's used before the IO-APIC is set up. 4.20 */ 4.21 - irq_vector[0] = FIRST_DEVICE_VECTOR; 4.22 - vector_irq[FIRST_DEVICE_VECTOR] = 0; 4.23 + irq_vector[0] = FIRST_HIPRIORITY_VECTOR; 4.24 + vector_irq[FIRST_HIPRIORITY_VECTOR] = 0; 4.25 + 4.26 + /* 4.27 + * Also ensure serial interrupts are high priority. We do not 4.28 + * want them to be blocked by unacknowledged guest-bound interrupts. 4.29 + */ 4.30 + for (seridx = 0; seridx < 2; seridx++) { 4.31 + if ((irq = serial_irq(seridx)) < 0) 4.32 + continue; 4.33 + irq_vector[irq] = FIRST_HIPRIORITY_VECTOR + seridx + 1; 4.34 + vector_irq[FIRST_HIPRIORITY_VECTOR + seridx + 1] = irq; 4.35 + } 4.36 4.37 /* IPI for event checking. */ 4.38 set_intr_gate(EVENT_CHECK_VECTOR, event_check_interrupt);
5.1 --- a/xen/drivers/char/ns16550.c Sat Apr 15 15:53:53 2006 +0100 5.2 +++ b/xen/drivers/char/ns16550.c Sat Apr 15 18:09:52 2006 +0100 5.3 @@ -260,13 +260,20 @@ static void ns16550_endboot(struct seria 5.4 #define ns16550_endboot NULL 5.5 #endif 5.6 5.7 +static int ns16550_irq(struct serial_port *port) 5.8 +{ 5.9 + struct ns16550 *uart = port->uart; 5.10 + return ((uart->irq > 0) ? uart->irq : -1); 5.11 +} 5.12 + 5.13 static struct uart_driver ns16550_driver = { 5.14 .init_preirq = ns16550_init_preirq, 5.15 .init_postirq = ns16550_init_postirq, 5.16 .endboot = ns16550_endboot, 5.17 .tx_empty = ns16550_tx_empty, 5.18 .putc = ns16550_putc, 5.19 - .getc = ns16550_getc 5.20 + .getc = ns16550_getc, 5.21 + .irq = ns16550_irq 5.22 }; 5.23 5.24 static int parse_parity_char(int c)
6.1 --- a/xen/drivers/char/serial.c Sat Apr 15 15:53:53 2006 +0100 6.2 +++ b/xen/drivers/char/serial.c Sat Apr 15 18:09:52 2006 +0100 6.3 @@ -372,6 +372,15 @@ void serial_endboot(void) 6.4 com[i].driver->endboot(&com[i]); 6.5 } 6.6 6.7 +int serial_irq(int idx) 6.8 +{ 6.9 + if ( (idx >= 0) && (idx < ARRAY_SIZE(com)) && 6.10 + com[idx].driver && com[idx].driver->irq ) 6.11 + return com[idx].driver->irq(&com[idx]); 6.12 + 6.13 + return -1; 6.14 +} 6.15 + 6.16 void serial_register_uart(int idx, struct uart_driver *driver, void *uart) 6.17 { 6.18 /* Store UART-specific info. */
7.1 --- a/xen/include/asm-x86/irq.h Sat Apr 15 15:53:53 2006 +0100 7.2 +++ b/xen/include/asm-x86/irq.h Sat Apr 15 18:09:52 2006 +0100 7.3 @@ -11,8 +11,8 @@ 7.4 #define IO_APIC_IRQ(irq) (((irq) >= 16) || ((1<<(irq)) & io_apic_irqs)) 7.5 #define IO_APIC_VECTOR(irq) (irq_vector[irq]) 7.6 7.7 -#define LEGACY_VECTOR(irq) ((irq) + FIRST_EXTERNAL_VECTOR) 7.8 -#define LEGACY_IRQ_FROM_VECTOR(vec) ((vec) - FIRST_EXTERNAL_VECTOR) 7.9 +#define LEGACY_VECTOR(irq) ((irq) + FIRST_LEGACY_VECTOR) 7.10 +#define LEGACY_IRQ_FROM_VECTOR(vec) ((vec) - FIRST_LEGACY_VECTOR) 7.11 7.12 #define irq_to_vector(irq) \ 7.13 (IO_APIC_IRQ(irq) ? IO_APIC_VECTOR(irq) : LEGACY_VECTOR(irq))
8.1 --- a/xen/include/asm-x86/mach-default/irq_vectors.h Sat Apr 15 15:53:53 2006 +0100 8.2 +++ b/xen/include/asm-x86/mach-default/irq_vectors.h Sat Apr 15 18:09:52 2006 +0100 8.3 @@ -1,96 +1,36 @@ 8.4 -/* 8.5 - * This file should contain #defines for all of the interrupt vector 8.6 - * numbers used by this architecture. 8.7 - * 8.8 - * In addition, there are some standard defines: 8.9 - * 8.10 - * FIRST_EXTERNAL_VECTOR: 8.11 - * The first free place for external interrupts 8.12 - * 8.13 - * SYSCALL_VECTOR: 8.14 - * The IRQ vector a syscall makes the user to kernel transition 8.15 - * under. 8.16 - * 8.17 - * TIMER_IRQ: 8.18 - * The IRQ number the timer interrupt comes in at. 8.19 - * 8.20 - * NR_IRQS: 8.21 - * The total number of interrupt vectors (including all the 8.22 - * architecture specific interrupts) needed. 8.23 - * 8.24 - */ 8.25 #ifndef _ASM_IRQ_VECTORS_H 8.26 #define _ASM_IRQ_VECTORS_H 8.27 8.28 -/* 8.29 - * IDT vectors usable for external interrupt sources start 8.30 - * at 0x20: 8.31 - */ 8.32 -#define FIRST_EXTERNAL_VECTOR 0x20 8.33 - 8.34 -#define HYPERCALL_VECTOR 0x82 8.35 - 8.36 -/* 8.37 - * Vectors 0x20-0x2f are used for ISA interrupts. 8.38 - */ 8.39 - 8.40 -/* 8.41 - * Special IRQ vectors used by the SMP architecture, 0xf0-0xff 8.42 - * 8.43 - * some of the following vectors are 'rare', they are merged 8.44 - * into a single vector (CALL_FUNCTION_VECTOR) to save vector space. 8.45 - * TLB, reschedule and local APIC vectors are performance-critical. 8.46 - * 8.47 - * Vectors 0xf0-0xfa are free (reserved for future Linux use). 8.48 - */ 8.49 +/* Processor-initiated interrupts are all high priority. */ 8.50 #define SPURIOUS_APIC_VECTOR 0xff 8.51 #define ERROR_APIC_VECTOR 0xfe 8.52 #define INVALIDATE_TLB_VECTOR 0xfd 8.53 #define EVENT_CHECK_VECTOR 0xfc 8.54 #define CALL_FUNCTION_VECTOR 0xfb 8.55 - 8.56 -#define THERMAL_APIC_VECTOR 0xf0 8.57 -/* 8.58 - * Local APIC timer IRQ vector is on a different priority level, 8.59 - * to work around the 'lost local interrupt if more than 2 IRQ 8.60 - * sources per level' errata. 8.61 - */ 8.62 -#define LOCAL_TIMER_VECTOR 0xef 8.63 - 8.64 -/* 8.65 - * First APIC vector available to drivers: (vectors 0x30-0xee) 8.66 - * we start at 0x31 to spread out vectors evenly between priority 8.67 - * levels. (0x80 is the syscall vector) 8.68 - */ 8.69 -#define FIRST_DEVICE_VECTOR 0x31 8.70 -#define FIRST_SYSTEM_VECTOR 0xef 8.71 - 8.72 -#define TIMER_IRQ 0 8.73 +#define THERMAL_APIC_VECTOR 0xfa 8.74 +#define LOCAL_TIMER_VECTOR 0xf9 8.75 8.76 /* 8.77 - * 16 8259A IRQ's, 208 potential APIC interrupt sources. 8.78 - * Right now the APIC is mostly only used for SMP. 8.79 - * 256 vectors is an architectural limit. (we can have 8.80 - * more than 256 devices theoretically, but they will 8.81 - * have to use shared interrupts) 8.82 - * Since vectors 0x00-0x1f are used/reserved for the CPU, 8.83 - * the usable vector space is 0x20-0xff (224 vectors) 8.84 + * High-priority dynamically-allocated vectors. For interrupts that 8.85 + * must be higher priority than any guest-bound interrupt. 8.86 */ 8.87 +#define FIRST_HIPRIORITY_VECTOR 0xf0 8.88 +#define LAST_HIPRIORITY_VECTOR 0xf8 8.89 8.90 -/* 8.91 - * The maximum number of vectors supported by i386 processors 8.92 - * is limited to 256. For processors other than i386, NR_VECTORS 8.93 - * should be changed accordingly. 8.94 - */ 8.95 +/* Legacy PIC uses vectors 0xe0-0xef. */ 8.96 +#define FIRST_LEGACY_VECTOR 0xe0 8.97 +#define LAST_LEGACY_VECTOR 0xef 8.98 + 8.99 +#define HYPERCALL_VECTOR 0x82 8.100 + 8.101 +/* Dynamically-allocated vectors available to any driver. */ 8.102 +#define FIRST_DYNAMIC_VECTOR 0x20 8.103 +#define LAST_DYNAMIC_VECTOR 0xdf 8.104 + 8.105 #define NR_VECTORS 256 8.106 8.107 -#include "irq_vectors_limits.h" 8.108 - 8.109 -#define FPU_IRQ 13 8.110 - 8.111 -#define FIRST_VM86_IRQ 3 8.112 -#define LAST_VM86_IRQ 15 8.113 -#define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15) 8.114 - 8.115 +/* Limited by number of trap vectors. */ 8.116 +#define NR_IRQS NR_VECTORS 8.117 +#define NR_IRQ_VECTORS NR_IRQS 8.118 8.119 #endif /* _ASM_IRQ_VECTORS_H */
9.1 --- a/xen/include/asm-x86/mach-default/irq_vectors_limits.h Sat Apr 15 15:53:53 2006 +0100 9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 9.3 @@ -1,8 +0,0 @@ 9.4 -#ifndef _ASM_IRQ_VECTORS_LIMITS_H 9.5 -#define _ASM_IRQ_VECTORS_LIMITS_H 9.6 - 9.7 -/* Limited by number of trap vectors. */ 9.8 -#define NR_IRQS FIRST_SYSTEM_VECTOR 9.9 -#define NR_IRQ_VECTORS NR_IRQS 9.10 - 9.11 -#endif /* _ASM_IRQ_VECTORS_LIMITS_H */
10.1 --- a/xen/include/xen/serial.h Sat Apr 15 15:53:53 2006 +0100 10.2 +++ b/xen/include/xen/serial.h Sat Apr 15 18:09:52 2006 +0100 10.3 @@ -57,6 +57,8 @@ struct uart_driver { 10.4 void (*putc)(struct serial_port *, char); 10.5 /* Get a character from the serial line: returns 0 if none available. */ 10.6 int (*getc)(struct serial_port *, char *); 10.7 + /* Get IRQ number for this port's serial line: returns -1 if none. */ 10.8 + int (*irq)(struct serial_port *); 10.9 }; 10.10 10.11 /* 'Serial handles' are composed from the following fields. */ 10.12 @@ -99,6 +101,9 @@ void serial_end_sync(int handle); 10.13 /* Return number of bytes headroom in transmit buffer. */ 10.14 int serial_tx_space(int handle); 10.15 10.16 +/* Return irq number for specified serial port (identified by index). */ 10.17 +int serial_irq(int idx); 10.18 + 10.19 /* 10.20 * Initialisation and helper functions for uart drivers. 10.21 */