Index: head-2006-04-05/arch/i386/kernel/irq-xen.c =================================================================== --- head-2006-04-05.orig/arch/i386/kernel/irq-xen.c 2006-04-06 11:49:12.000000000 +0200 +++ head-2006-04-05/arch/i386/kernel/irq-xen.c 2006-04-06 12:09:55.000000000 +0200 @@ -224,9 +224,17 @@ int show_interrupts(struct seq_file *p, } if (i < NR_IRQS) { + unsigned any_count = 0; + spin_lock_irqsave(&irq_desc[i].lock, flags); +#ifndef CONFIG_SMP + any_count = kstat_irqs(i); +#else + for_each_online_cpu(j) + any_count |= kstat_cpu(j).irqs[i]; +#endif action = irq_desc[i].action; - if (!action) + if (!action && !any_count) goto skip; seq_printf(p, "%3d: ",i); #ifndef CONFIG_SMP @@ -236,10 +244,12 @@ int show_interrupts(struct seq_file *p, seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); #endif seq_printf(p, " %14s", irq_desc[i].handler->typename); - seq_printf(p, " %s", action->name); - for (action=action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); + if (action) { + seq_printf(p, " %s", action->name); + while ((action = action->next) != NULL) + seq_printf(p, ", %s", action->name); + } seq_putc(p, '\n'); skip: Index: head-2006-04-05/arch/x86_64/kernel/irq-xen.c =================================================================== --- head-2006-04-05.orig/arch/x86_64/kernel/irq-xen.c 2006-04-06 11:49:12.000000000 +0200 +++ head-2006-04-05/arch/x86_64/kernel/irq-xen.c 2006-04-06 12:09:55.000000000 +0200 @@ -45,9 +45,17 @@ int show_interrupts(struct seq_file *p, } if (i < NR_IRQS) { + unsigned any_count = 0; + spin_lock_irqsave(&irq_desc[i].lock, flags); +#ifndef CONFIG_SMP + any_count = kstat_irqs(i); +#else + for (j=0; jtypename); - seq_printf(p, " %s", action->name); - for (action=action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); + if (action) { + seq_printf(p, " %s", action->name); + while ((action = action->next) != NULL) + seq_printf(p, ", %s", action->name); + } seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); Index: head-2006-04-05/include/linux/irq.h =================================================================== --- head-2006-04-05.orig/include/linux/irq.h 2006-04-06 11:51:31.000000000 +0200 +++ head-2006-04-05/include/linux/irq.h 2006-04-06 12:09:55.000000000 +0200 @@ -80,6 +80,9 @@ typedef struct irq_desc { #if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE) unsigned int move_irq; /* Flag need to re-target intr dest*/ #endif +#ifdef CONFIG_XEN + unsigned int unhandled_threshold; +#endif } ____cacheline_aligned irq_desc_t; extern irq_desc_t irq_desc [NR_IRQS]; Index: head-2006-04-05/kernel/irq/spurious.c =================================================================== --- head-2006-04-05.orig/kernel/irq/spurious.c 2006-03-20 06:53:29.000000000 +0100 +++ head-2006-04-05/kernel/irq/spurious.c 2006-04-06 12:09:55.000000000 +0200 @@ -125,7 +125,11 @@ __report_bad_irq(unsigned int irq, irq_d static void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret) { +#ifndef CONFIG_XEN static int count = 100; +#else + static int count = NR_IRQS * 50; +#endif if (count > 0) { count--; @@ -133,6 +137,10 @@ static void report_bad_irq(unsigned int } } +#ifdef CONFIG_XEN +#include +#endif + void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret, struct pt_regs *regs) { @@ -140,6 +148,20 @@ void note_interrupt(unsigned int irq, ir desc->irqs_unhandled++; if (action_ret != IRQ_NONE) report_bad_irq(irq, desc, action_ret); +#ifdef CONFIG_XEN + else if (desc->irqs_unhandled > desc->unhandled_threshold) { +unsigned cpu = smp_processor_id(); +const struct evtchn_irq_status*status = &per_cpu(evtchn_irq_status, cpu); + +printk("On CPU#%u:\n", cpu); +do { + printk("IRQ%u: l1=%08lX(%u) l2=%08lX(%u)\n", irq, status->l1, status->l1i, status->l2, status->l2i); + status = status->link; +} while(status); + desc->unhandled_threshold |= desc->irqs_unhandled; + report_bad_irq(irq, desc, action_ret); + } +#endif } if (unlikely(irqfixup)) { Index: head-2006-04-05/drivers/xen/core/evtchn.c =================================================================== --- head-2006-04-05.orig/drivers/xen/core/evtchn.c 2006-04-06 11:49:28.000000000 +0200 +++ head-2006-04-05/drivers/xen/core/evtchn.c 2006-04-06 12:09:55.000000000 +0200 @@ -123,6 +123,7 @@ static void bind_evtchn_to_cpu(unsigned clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]); set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]); cpu_evtchn[chn] = cpu; +printk("Event channel %u is now on CPU#%u\n", chn, cpu); } static void init_evtchn_cpu_bindings(void) @@ -190,6 +191,8 @@ void force_evtchn_callback(void) } EXPORT_SYMBOL_GPL(force_evtchn_callback); +DEFINE_PER_CPU(struct evtchn_irq_status, evtchn_irq_status); + /* NB. Interrupts are disabled on entry. */ asmlinkage void evtchn_do_upcall(struct pt_regs *regs) { @@ -198,17 +201,30 @@ asmlinkage void evtchn_do_upcall(struct int irq, cpu = smp_processor_id(); shared_info_t *s = HYPERVISOR_shared_info; vcpu_info_t *vcpu_info = &s->vcpu_info[cpu]; +struct evtchn_irq_status old_status, *cur_status; vcpu_info->evtchn_upcall_pending = 0; +cur_status = &per_cpu(evtchn_irq_status, cpu); +if(cur_status->l1) { + old_status = *cur_status; + cur_status->link = &old_status; +} +else + old_status.l1 = 0; + /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ l1 = xchg(&vcpu_info->evtchn_pending_sel, 0); +cur_status->l1 = l1; while (l1 != 0) { l1i = __ffs(l1); l1 &= ~(1UL << l1i); +cur_status->l1i = l1i; while ((l2 = active_evtchns(cpu, s, l1i)) != 0) { +cur_status->l2 = l2; l2i = __ffs(l2); +cur_status->l2i = l2i; port = (l1i * BITS_PER_LONG) + l2i; if ((irq = evtchn_to_irq[port]) != -1) @@ -219,6 +235,8 @@ asmlinkage void evtchn_do_upcall(struct } } } +if(old_status.l1) + *cur_status = old_status; } static int find_unbound_irq(void) @@ -852,6 +870,44 @@ void __init init_IRQ(void) } } +void dump_evtchn_op(const struct evtchn_op*op, int rc) +{ + if(rc < 0) + printk("EvtChnOp %u failed (%d)\n", op->cmd, rc); + else switch(op->cmd) { + case EVTCHNOP_alloc_unbound: + printk("EventChannel %u is now allocated\n", op->u.alloc_unbound.port); + break; + case EVTCHNOP_bind_interdomain: + printk("EventChannel %u is now bound to remote channel %u\n", op->u.bind_interdomain.local_port, op->u.bind_interdomain.remote_port); + break; + case EVTCHNOP_bind_virq: + printk("EventChannel %u is now bound to VIRQ %u on VCPU %u\n", op->u.bind_virq.port, op->u.bind_virq.virq, op->u.bind_virq.vcpu); + break; + case EVTCHNOP_bind_pirq: + printk("EventChannel %u is now bound to PIRQ %u\n", op->u.bind_pirq.port, op->u.bind_pirq.pirq); + break; + case EVTCHNOP_bind_ipi: + printk("EventChannel %u is now bound to IPI on VCPU %u\n", op->u.bind_ipi.port, op->u.bind_ipi.vcpu); + break; + case EVTCHNOP_close: + printk("EventChannel %u is now closed\n", op->u.close.port); + break; + case EVTCHNOP_bind_vcpu: + printk("EventChannel %u is now bound to VCPU %u\n", op->u.bind_vcpu.port, op->u.bind_vcpu.vcpu); + break; + case EVTCHNOP_unmask: + printk("EventChannel %u is now unmasked\n", op->u.unmask.port); + break; + case EVTCHNOP_send: + break; + default: + printk("EventChannel operation %u completed\n", op->cmd); + break; + } +} +EXPORT_SYMBOL_GPL(dump_evtchn_op); + /* * Local variables: * c-file-style: "linux" Index: head-2006-04-05/include/xen/evtchn.h =================================================================== --- head-2006-04-05.orig/include/xen/evtchn.h 2006-04-06 11:49:12.000000000 +0200 +++ head-2006-04-05/include/xen/evtchn.h 2006-04-06 12:09:55.000000000 +0200 @@ -113,6 +113,16 @@ static inline void notify_remote_via_evt */ extern void notify_remote_via_irq(int irq); +struct evtchn_irq_status { + struct evtchn_irq_status *link; + unsigned long l1, l2; + unsigned int l1i, l2i; +}; +DECLARE_PER_CPU(struct evtchn_irq_status, evtchn_irq_status); + +struct evtchn_op; +extern void dump_evtchn_op(const struct evtchn_op*, int); + #endif /* __ASM_EVTCHN_H__ */ /* Index: head-2006-04-05/include/asm-x86_64/mach-xen/asm/hypercall.h =================================================================== --- head-2006-04-05.orig/include/asm-x86_64/mach-xen/asm/hypercall.h 2006-04-06 11:49:12.000000000 +0200 +++ head-2006-04-05/include/asm-x86_64/mach-xen/asm/hypercall.h 2006-04-06 12:09:55.000000000 +0200 @@ -241,11 +241,17 @@ HYPERVISOR_update_va_mapping( return _hypercall3(int, update_va_mapping, va, new_val.pte, flags); } +struct evtchn_op; +extern void dump_evtchn_op(const struct evtchn_op*, int); + static inline int HYPERVISOR_event_channel_op( void *op) { - return _hypercall1(int, event_channel_op, op); + int rc = _hypercall1(int, event_channel_op, op); + + dump_evtchn_op(op, rc); + return rc; } static inline int