ia64/xen-unstable

view xen/arch/x86/irq.c @ 16409:00fec8212ae6

Remove unused smpboot.h header file.
Signed-off-by: Keir Fraser <keir.fraser@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Nov 21 09:45:22 2007 +0000 (2007-11-21)
parents 45548c83daef
children af33f2054f47
line source
1 /******************************************************************************
2 * arch/x86/irq.c
3 *
4 * Portions of this file are:
5 * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
6 */
8 #include <xen/config.h>
9 #include <xen/init.h>
10 #include <xen/errno.h>
11 #include <xen/event.h>
12 #include <xen/irq.h>
13 #include <xen/perfc.h>
14 #include <xen/sched.h>
15 #include <xen/keyhandler.h>
16 #include <xen/compat.h>
17 #include <asm/current.h>
18 #include <asm/iommu.h>
20 /* opt_noirqbalance: If true, software IRQ balancing/affinity is disabled. */
21 int opt_noirqbalance = 0;
22 boolean_param("noirqbalance", opt_noirqbalance);
24 irq_desc_t irq_desc[NR_IRQS];
26 static void __do_IRQ_guest(int vector);
28 void no_action(int cpl, void *dev_id, struct cpu_user_regs *regs) { }
30 static void enable_none(unsigned int vector) { }
31 static unsigned int startup_none(unsigned int vector) { return 0; }
32 static void disable_none(unsigned int vector) { }
33 static void ack_none(unsigned int vector)
34 {
35 ack_bad_irq(vector);
36 }
38 #define shutdown_none disable_none
39 #define end_none enable_none
41 struct hw_interrupt_type no_irq_type = {
42 "none",
43 startup_none,
44 shutdown_none,
45 enable_none,
46 disable_none,
47 ack_none,
48 end_none
49 };
51 atomic_t irq_err_count;
53 asmlinkage void do_IRQ(struct cpu_user_regs *regs)
54 {
55 unsigned int vector = regs->entry_vector;
56 irq_desc_t *desc = &irq_desc[vector];
57 struct irqaction *action;
59 perfc_incr(irqs);
61 spin_lock(&desc->lock);
62 desc->handler->ack(vector);
64 if ( likely(desc->status & IRQ_GUEST) )
65 {
66 __do_IRQ_guest(vector);
67 spin_unlock(&desc->lock);
68 return;
69 }
71 desc->status &= ~IRQ_REPLAY;
72 desc->status |= IRQ_PENDING;
74 /*
75 * Since we set PENDING, if another processor is handling a different
76 * instance of this same irq, the other processor will take care of it.
77 */
78 if ( desc->status & (IRQ_DISABLED | IRQ_INPROGRESS) )
79 goto out;
81 desc->status |= IRQ_INPROGRESS;
83 action = desc->action;
84 while ( desc->status & IRQ_PENDING )
85 {
86 desc->status &= ~IRQ_PENDING;
87 irq_enter();
88 spin_unlock_irq(&desc->lock);
89 action->handler(vector_to_irq(vector), action->dev_id, regs);
90 spin_lock_irq(&desc->lock);
91 irq_exit();
92 }
94 desc->status &= ~IRQ_INPROGRESS;
96 out:
97 desc->handler->end(vector);
98 spin_unlock(&desc->lock);
99 }
101 int request_irq(unsigned int irq,
102 void (*handler)(int, void *, struct cpu_user_regs *),
103 unsigned long irqflags, const char * devname, void *dev_id)
104 {
105 struct irqaction * action;
106 int retval;
108 /*
109 * Sanity-check: shared interrupts must pass in a real dev-ID,
110 * otherwise we'll have trouble later trying to figure out
111 * which interrupt is which (messes up the interrupt freeing
112 * logic etc).
113 */
114 if (irq >= NR_IRQS)
115 return -EINVAL;
116 if (!handler)
117 return -EINVAL;
119 action = xmalloc(struct irqaction);
120 if (!action)
121 return -ENOMEM;
123 action->handler = handler;
124 action->name = devname;
125 action->dev_id = dev_id;
127 retval = setup_irq(irq, action);
128 if (retval)
129 xfree(action);
131 return retval;
132 }
134 void free_irq(unsigned int irq)
135 {
136 unsigned int vector = irq_to_vector(irq);
137 irq_desc_t *desc = &irq_desc[vector];
138 unsigned long flags;
140 spin_lock_irqsave(&desc->lock,flags);
141 desc->action = NULL;
142 desc->depth = 1;
143 desc->status |= IRQ_DISABLED;
144 desc->handler->shutdown(irq);
145 spin_unlock_irqrestore(&desc->lock,flags);
147 /* Wait to make sure it's not being used on another CPU */
148 do { smp_mb(); } while ( desc->status & IRQ_INPROGRESS );
149 }
151 int setup_irq(unsigned int irq, struct irqaction *new)
152 {
153 unsigned int vector = irq_to_vector(irq);
154 irq_desc_t *desc = &irq_desc[vector];
155 unsigned long flags;
157 spin_lock_irqsave(&desc->lock,flags);
159 if ( desc->action != NULL )
160 {
161 spin_unlock_irqrestore(&desc->lock,flags);
162 return -EBUSY;
163 }
165 desc->action = new;
166 desc->depth = 0;
167 desc->status &= ~IRQ_DISABLED;
168 desc->handler->startup(vector);
170 spin_unlock_irqrestore(&desc->lock,flags);
172 return 0;
173 }
176 /*
177 * HANDLING OF GUEST-BOUND PHYSICAL IRQS
178 */
180 #define IRQ_MAX_GUESTS 7
181 typedef struct {
182 u8 nr_guests;
183 u8 in_flight;
184 u8 shareable;
185 u8 ack_type;
186 #define ACKTYPE_NONE 0 /* No final acknowledgement is required */
187 #define ACKTYPE_UNMASK 1 /* Unmask PIC hardware (from any CPU) */
188 #define ACKTYPE_EOI 2 /* EOI on the CPU that was interrupted */
189 cpumask_t cpu_eoi_map; /* CPUs that need to EOI this interrupt */
190 struct domain *guest[IRQ_MAX_GUESTS];
191 } irq_guest_action_t;
193 /*
194 * Stack of interrupts awaiting EOI on each CPU. These must be popped in
195 * order, as only the current highest-priority pending irq can be EOIed.
196 */
197 struct pending_eoi {
198 u8 vector; /* Vector awaiting EOI */
199 u8 ready; /* Ready for EOI now? */
200 };
201 static DEFINE_PER_CPU(struct pending_eoi, pending_eoi[NR_VECTORS]);
202 #define pending_eoi_sp(p) ((p)[NR_VECTORS-1].vector)
204 static void __do_IRQ_guest(int vector)
205 {
206 unsigned int irq = vector_to_irq(vector);
207 irq_desc_t *desc = &irq_desc[vector];
208 irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
209 struct domain *d;
210 int i, sp;
211 struct pending_eoi *peoi = this_cpu(pending_eoi);
213 if ( unlikely(action->nr_guests == 0) )
214 {
215 /* An interrupt may slip through while freeing an ACKTYPE_EOI irq. */
216 ASSERT(action->ack_type == ACKTYPE_EOI);
217 ASSERT(desc->status & IRQ_DISABLED);
218 desc->handler->end(vector);
219 return;
220 }
222 if ( action->ack_type == ACKTYPE_EOI )
223 {
224 sp = pending_eoi_sp(peoi);
225 ASSERT((sp == 0) || (peoi[sp-1].vector < vector));
226 ASSERT(sp < (NR_VECTORS-1));
227 peoi[sp].vector = vector;
228 peoi[sp].ready = 0;
229 pending_eoi_sp(peoi) = sp+1;
230 cpu_set(smp_processor_id(), action->cpu_eoi_map);
231 }
233 for ( i = 0; i < action->nr_guests; i++ )
234 {
235 d = action->guest[i];
236 if ( (action->ack_type != ACKTYPE_NONE) &&
237 !test_and_set_bit(irq, d->pirq_mask) )
238 action->in_flight++;
239 if (!hvm_do_IRQ_dpci(d, irq))
240 send_guest_pirq(d, irq);
242 }
243 }
245 /* Flush all ready EOIs from the top of this CPU's pending-EOI stack. */
246 static void flush_ready_eoi(void *unused)
247 {
248 struct pending_eoi *peoi = this_cpu(pending_eoi);
249 irq_desc_t *desc;
250 int vector, sp;
252 ASSERT(!local_irq_is_enabled());
254 sp = pending_eoi_sp(peoi);
256 while ( (--sp >= 0) && peoi[sp].ready )
257 {
258 vector = peoi[sp].vector;
259 desc = &irq_desc[vector];
260 spin_lock(&desc->lock);
261 desc->handler->end(vector);
262 spin_unlock(&desc->lock);
263 }
265 pending_eoi_sp(peoi) = sp+1;
266 }
268 static void __set_eoi_ready(irq_desc_t *desc)
269 {
270 irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
271 struct pending_eoi *peoi = this_cpu(pending_eoi);
272 int vector, sp;
274 vector = desc - irq_desc;
276 if ( !(desc->status & IRQ_GUEST) ||
277 (action->in_flight != 0) ||
278 !cpu_test_and_clear(smp_processor_id(), action->cpu_eoi_map) )
279 return;
281 sp = pending_eoi_sp(peoi);
282 do {
283 ASSERT(sp > 0);
284 } while ( peoi[--sp].vector != vector );
285 ASSERT(!peoi[sp].ready);
286 peoi[sp].ready = 1;
287 }
289 /* Mark specified IRQ as ready-for-EOI (if it really is) and attempt to EOI. */
290 static void set_eoi_ready(void *data)
291 {
292 irq_desc_t *desc = data;
294 ASSERT(!local_irq_is_enabled());
296 spin_lock(&desc->lock);
297 __set_eoi_ready(desc);
298 spin_unlock(&desc->lock);
300 flush_ready_eoi(NULL);
301 }
303 static void __pirq_guest_eoi(struct domain *d, int irq)
304 {
305 irq_desc_t *desc;
306 irq_guest_action_t *action;
307 cpumask_t cpu_eoi_map;
309 desc = &irq_desc[irq_to_vector(irq)];
310 action = (irq_guest_action_t *)desc->action;
312 spin_lock_irq(&desc->lock);
314 ASSERT(!test_bit(irq, d->pirq_mask) ||
315 (action->ack_type != ACKTYPE_NONE));
317 if ( unlikely(!test_and_clear_bit(irq, d->pirq_mask)) ||
318 unlikely(--action->in_flight != 0) )
319 {
320 spin_unlock_irq(&desc->lock);
321 return;
322 }
324 if ( action->ack_type == ACKTYPE_UNMASK )
325 {
326 ASSERT(cpus_empty(action->cpu_eoi_map));
327 desc->handler->end(irq_to_vector(irq));
328 spin_unlock_irq(&desc->lock);
329 return;
330 }
332 ASSERT(action->ack_type == ACKTYPE_EOI);
334 cpu_eoi_map = action->cpu_eoi_map;
336 if ( cpu_test_and_clear(smp_processor_id(), cpu_eoi_map) )
337 {
338 __set_eoi_ready(desc);
339 spin_unlock(&desc->lock);
340 flush_ready_eoi(NULL);
341 local_irq_enable();
342 }
343 else
344 {
345 spin_unlock_irq(&desc->lock);
346 }
348 if ( !cpus_empty(cpu_eoi_map) )
349 on_selected_cpus(cpu_eoi_map, set_eoi_ready, desc, 1, 0);
350 }
352 int pirq_guest_eoi(struct domain *d, int irq)
353 {
354 if ( (irq < 0) || (irq >= NR_IRQS) )
355 return -EINVAL;
357 __pirq_guest_eoi(d, irq);
359 return 0;
360 }
362 int pirq_guest_unmask(struct domain *d)
363 {
364 unsigned int irq;
365 shared_info_t *s = d->shared_info;
367 for ( irq = find_first_bit(d->pirq_mask, NR_IRQS);
368 irq < NR_IRQS;
369 irq = find_next_bit(d->pirq_mask, NR_IRQS, irq+1) )
370 {
371 if ( !test_bit(d->pirq_to_evtchn[irq], __shared_info_addr(d, s, evtchn_mask)) )
372 __pirq_guest_eoi(d, irq);
373 }
375 return 0;
376 }
378 extern int ioapic_ack_new;
379 int pirq_acktype(int irq)
380 {
381 irq_desc_t *desc;
382 unsigned int vector;
384 vector = irq_to_vector(irq);
385 if ( vector == 0 )
386 return ACKTYPE_NONE;
388 desc = &irq_desc[vector];
390 if ( desc->handler == &no_irq_type )
391 return ACKTYPE_NONE;
393 /*
394 * Edge-triggered IO-APIC and LAPIC interrupts need no final
395 * acknowledgement: we ACK early during interrupt processing.
396 */
397 if ( !strcmp(desc->handler->typename, "IO-APIC-edge") ||
398 !strcmp(desc->handler->typename, "local-APIC-edge") )
399 return ACKTYPE_NONE;
401 /*
402 * Level-triggered IO-APIC interrupts need to be acknowledged on the CPU
403 * on which they were received. This is because we tickle the LAPIC to EOI.
404 */
405 if ( !strcmp(desc->handler->typename, "IO-APIC-level") )
406 return ioapic_ack_new ? ACKTYPE_EOI : ACKTYPE_UNMASK;
408 /* Legacy PIC interrupts can be acknowledged from any CPU. */
409 if ( !strcmp(desc->handler->typename, "XT-PIC") )
410 return ACKTYPE_UNMASK;
412 if ( strstr(desc->handler->typename, "MPIC") )
413 {
414 if ( desc->status & IRQ_LEVEL )
415 return (desc->status & IRQ_PER_CPU) ? ACKTYPE_EOI : ACKTYPE_UNMASK;
416 return ACKTYPE_NONE; /* edge-triggered => no final EOI */
417 }
419 printk("Unknown PIC type '%s' for IRQ %d\n", desc->handler->typename, irq);
420 BUG();
422 return 0;
423 }
425 int pirq_shared(int irq)
426 {
427 unsigned int vector;
428 irq_desc_t *desc;
429 irq_guest_action_t *action;
430 unsigned long flags;
431 int shared;
433 vector = irq_to_vector(irq);
434 if ( vector == 0 )
435 return 0;
437 desc = &irq_desc[vector];
439 spin_lock_irqsave(&desc->lock, flags);
440 action = (irq_guest_action_t *)desc->action;
441 shared = ((desc->status & IRQ_GUEST) && (action->nr_guests > 1));
442 spin_unlock_irqrestore(&desc->lock, flags);
444 return shared;
445 }
447 int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
448 {
449 unsigned int vector;
450 irq_desc_t *desc;
451 irq_guest_action_t *action;
452 unsigned long flags;
453 int rc = 0;
454 cpumask_t cpumask = CPU_MASK_NONE;
456 retry:
457 vector = irq_to_vector(irq);
458 if ( vector == 0 )
459 return -EINVAL;
461 desc = &irq_desc[vector];
463 spin_lock_irqsave(&desc->lock, flags);
465 action = (irq_guest_action_t *)desc->action;
467 if ( !(desc->status & IRQ_GUEST) )
468 {
469 if ( desc->action != NULL )
470 {
471 gdprintk(XENLOG_INFO,
472 "Cannot bind IRQ %d to guest. In use by '%s'.\n",
473 irq, desc->action->name);
474 rc = -EBUSY;
475 goto out;
476 }
478 action = xmalloc(irq_guest_action_t);
479 if ( (desc->action = (struct irqaction *)action) == NULL )
480 {
481 gdprintk(XENLOG_INFO,
482 "Cannot bind IRQ %d to guest. Out of memory.\n",
483 irq);
484 rc = -ENOMEM;
485 goto out;
486 }
488 action->nr_guests = 0;
489 action->in_flight = 0;
490 action->shareable = will_share;
491 action->ack_type = pirq_acktype(irq);
492 cpus_clear(action->cpu_eoi_map);
494 desc->depth = 0;
495 desc->status |= IRQ_GUEST;
496 desc->status &= ~IRQ_DISABLED;
497 desc->handler->startup(vector);
499 /* Attempt to bind the interrupt target to the correct CPU. */
500 cpu_set(v->processor, cpumask);
501 if ( !opt_noirqbalance && (desc->handler->set_affinity != NULL) )
502 desc->handler->set_affinity(vector, cpumask);
503 }
504 else if ( !will_share || !action->shareable )
505 {
506 gdprintk(XENLOG_INFO, "Cannot bind IRQ %d to guest. "
507 "Will not share with others.\n",
508 irq);
509 rc = -EBUSY;
510 goto out;
511 }
512 else if ( action->nr_guests == 0 )
513 {
514 /*
515 * Indicates that an ACKTYPE_EOI interrupt is being released.
516 * Wait for that to happen before continuing.
517 */
518 ASSERT(action->ack_type == ACKTYPE_EOI);
519 ASSERT(desc->status & IRQ_DISABLED);
520 spin_unlock_irqrestore(&desc->lock, flags);
521 cpu_relax();
522 goto retry;
523 }
525 if ( action->nr_guests == IRQ_MAX_GUESTS )
526 {
527 gdprintk(XENLOG_INFO, "Cannot bind IRQ %d to guest. "
528 "Already at max share.\n", irq);
529 rc = -EBUSY;
530 goto out;
531 }
533 action->guest[action->nr_guests++] = v->domain;
535 out:
536 spin_unlock_irqrestore(&desc->lock, flags);
537 return rc;
538 }
540 int pirq_guest_unbind(struct domain *d, int irq)
541 {
542 unsigned int vector = irq_to_vector(irq);
543 irq_desc_t *desc = &irq_desc[vector];
544 irq_guest_action_t *action;
545 cpumask_t cpu_eoi_map;
546 unsigned long flags;
547 int i;
549 BUG_ON(vector == 0);
551 spin_lock_irqsave(&desc->lock, flags);
553 action = (irq_guest_action_t *)desc->action;
555 i = 0;
556 while ( action->guest[i] && (action->guest[i] != d) )
557 i++;
558 memmove(&action->guest[i], &action->guest[i+1], IRQ_MAX_GUESTS-i-1);
559 action->nr_guests--;
561 switch ( action->ack_type )
562 {
563 case ACKTYPE_UNMASK:
564 if ( test_and_clear_bit(irq, d->pirq_mask) &&
565 (--action->in_flight == 0) )
566 desc->handler->end(vector);
567 break;
568 case ACKTYPE_EOI:
569 /* NB. If #guests == 0 then we clear the eoi_map later on. */
570 if ( test_and_clear_bit(irq, d->pirq_mask) &&
571 (--action->in_flight == 0) &&
572 (action->nr_guests != 0) )
573 {
574 cpu_eoi_map = action->cpu_eoi_map;
575 spin_unlock_irqrestore(&desc->lock, flags);
576 on_selected_cpus(cpu_eoi_map, set_eoi_ready, desc, 1, 0);
577 spin_lock_irqsave(&desc->lock, flags);
578 }
579 break;
580 }
582 /*
583 * The guest cannot re-bind to this IRQ until this function returns. So,
584 * when we have flushed this IRQ from pirq_mask, it should remain flushed.
585 */
586 BUG_ON(test_bit(irq, d->pirq_mask));
588 if ( action->nr_guests != 0 )
589 goto out;
591 BUG_ON(action->in_flight != 0);
593 /* Disabling IRQ before releasing the desc_lock avoids an IRQ storm. */
594 desc->depth = 1;
595 desc->status |= IRQ_DISABLED;
596 desc->handler->disable(vector);
598 /*
599 * Mark any remaining pending EOIs as ready to flush.
600 * NOTE: We will need to make this a stronger barrier if in future we allow
601 * an interrupt vectors to be re-bound to a different PIC. In that case we
602 * would need to flush all ready EOIs before returning as otherwise the
603 * desc->handler could change and we would call the wrong 'end' hook.
604 */
605 cpu_eoi_map = action->cpu_eoi_map;
606 if ( !cpus_empty(cpu_eoi_map) )
607 {
608 BUG_ON(action->ack_type != ACKTYPE_EOI);
609 spin_unlock_irqrestore(&desc->lock, flags);
610 on_selected_cpus(cpu_eoi_map, set_eoi_ready, desc, 1, 1);
611 spin_lock_irqsave(&desc->lock, flags);
612 }
614 BUG_ON(!cpus_empty(action->cpu_eoi_map));
616 desc->action = NULL;
617 xfree(action);
618 desc->status &= ~IRQ_GUEST;
619 desc->handler->shutdown(vector);
621 out:
622 spin_unlock_irqrestore(&desc->lock, flags);
623 return 0;
624 }
626 extern void dump_ioapic_irq_info(void);
628 static void dump_irqs(unsigned char key)
629 {
630 int i, irq, vector;
631 irq_desc_t *desc;
632 irq_guest_action_t *action;
633 struct domain *d;
634 unsigned long flags;
636 printk("Guest interrupt information:\n");
638 for ( irq = 0; irq < NR_IRQS; irq++ )
639 {
640 vector = irq_to_vector(irq);
641 if ( vector == 0 )
642 continue;
644 desc = &irq_desc[vector];
646 spin_lock_irqsave(&desc->lock, flags);
648 if ( desc->status & IRQ_GUEST )
649 {
650 action = (irq_guest_action_t *)desc->action;
652 printk(" IRQ%3d Vec%3d: type=%-15s status=%08x "
653 "in-flight=%d domain-list=",
654 irq, vector, desc->handler->typename,
655 desc->status, action->in_flight);
657 for ( i = 0; i < action->nr_guests; i++ )
658 {
659 d = action->guest[i];
660 printk("%u(%c%c%c%c)",
661 d->domain_id,
662 (test_bit(d->pirq_to_evtchn[irq],
663 shared_info_addr(d, evtchn_pending)) ?
664 'P' : '-'),
665 (test_bit(d->pirq_to_evtchn[irq]/BITS_PER_GUEST_LONG(d),
666 vcpu_info_addr(d->vcpu[0], evtchn_pending_sel)) ?
667 'S' : '-'),
668 (test_bit(d->pirq_to_evtchn[irq],
669 shared_info_addr(d, evtchn_mask)) ?
670 'M' : '-'),
671 (test_bit(irq, d->pirq_mask) ?
672 'M' : '-'));
673 if ( i != action->nr_guests )
674 printk(",");
675 }
677 printk("\n");
678 }
680 spin_unlock_irqrestore(&desc->lock, flags);
681 }
683 dump_ioapic_irq_info();
684 }
686 static int __init setup_dump_irqs(void)
687 {
688 register_keyhandler('i', dump_irqs, "dump interrupt bindings");
689 return 0;
690 }
691 __initcall(setup_dump_irqs);
693 #ifdef CONFIG_HOTPLUG_CPU
694 #include <asm/mach-generic/mach_apic.h>
695 #include <xen/delay.h>
697 void fixup_irqs(cpumask_t map)
698 {
699 unsigned int irq;
700 static int warned;
702 for ( irq = 0; irq < NR_IRQS; irq++ )
703 {
704 cpumask_t mask;
705 if ( irq == 2 )
706 continue;
708 cpus_and(mask, irq_desc[irq].affinity, map);
709 if ( any_online_cpu(mask) == NR_CPUS )
710 {
711 printk("Breaking affinity for irq %i\n", irq);
712 mask = map;
713 }
714 if ( irq_desc[irq].handler->set_affinity )
715 irq_desc[irq].handler->set_affinity(irq, mask);
716 else if ( irq_desc[irq].action && !(warned++) )
717 printk("Cannot set affinity for irq %i\n", irq);
718 }
720 local_irq_enable();
721 mdelay(1);
722 local_irq_disable();
723 }
724 #endif