From 3588fe2e3f36543664beafedd3bb6dc3ffa896c5 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 27 Aug 2010 17:30:24 -0700 Subject: xen/events: change to using fasteoi Change event delivery to: - mask+clear event in the upcall function - use handle_fasteoi_irq as the handler - unmask in the eoi function (and handle migration) Signed-off-by: Jeremy Fitzhardinge --- drivers/xen/events.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/xen/events.c') diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 13365ba..8beb2bc 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -378,7 +378,7 @@ int bind_evtchn_to_irq(unsigned int evtchn) irq = find_unbound_irq(); set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, - handle_edge_irq, "event"); + handle_fasteoi_irq, "event"); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_evtchn_info(evtchn); @@ -664,6 +664,9 @@ static void __xen_evtchn_do_upcall(void) int irq = evtchn_to_irq[port]; struct irq_desc *desc; + mask_evtchn(port); + clear_evtchn(port); + if (irq != -1) { desc = irq_to_desc(irq); if (desc) @@ -801,10 +804,10 @@ static void ack_dynirq(unsigned int irq) { int evtchn = evtchn_from_irq(irq); - move_native_irq(irq); + move_masked_irq(irq); if (VALID_EVTCHN(evtchn)) - clear_evtchn(evtchn); + unmask_evtchn(evtchn); } static int retrigger_dynirq(unsigned int irq) @@ -960,7 +963,7 @@ static struct irq_chip xen_dynamic_chip __read_mostly = { .mask = disable_dynirq, .unmask = enable_dynirq, - .ack = ack_dynirq, + .eoi = ack_dynirq, .set_affinity = set_affinity_irq, .retrigger = retrigger_dynirq, }; -- cgit v1.1 From b0097adeec27e30223c989561ab0f7aa60d1fe93 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 8 Oct 2010 16:59:12 +0100 Subject: xen: ensure that all event channels start off bound to VCPU 0 All event channels startbound to VCPU 0 so ensure that cpu_evtchn_mask is initialised to reflect this. Otherwise there is a race after registering an event channel but before the affinity is explicitly set where the event channel can be delivered. If this happens then the event channel remains pending in the L1 (evtchn_pending) array but is cleared in L2 (evtchn_pending_sel), this means the event channel cannot be reraised until another event channel happens to trigger the same L2 entry on that VCPU. sizeof(cpu_evtchn_mask(0))==sizeof(unsigned long*) which is not correct, and causes only the first 32 or 64 event channels (depending on architecture) to be initially bound to VCPU0. Use sizeof(struct cpu_evtchn_s) instead. Signed-off-by: Ian Campbell Cc: Jeremy Fitzhardinge Cc: stable@kernel.org --- drivers/xen/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/xen/events.c') diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 8beb2bc..b4e7301 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -261,7 +261,7 @@ static void init_evtchn_cpu_bindings(void) } #endif - memset(cpu_evtchn_mask(0), ~0, sizeof(cpu_evtchn_mask(0))); + memset(cpu_evtchn_mask(0), ~0, sizeof(struct cpu_evtchn_s)); } static inline void clear_evtchn(int port) -- cgit v1.1 From a52521f149c42b35a28423ee30be9a7afa51dfbf Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 22 Sep 2010 15:28:52 -0700 Subject: xen: set up IRQ before binding virq to evtchn Make sure the irq is set up before binding a virq event channel to it. Signed-off-by: Jeremy Fitzhardinge --- drivers/xen/events.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/xen/events.c') diff --git a/drivers/xen/events.c b/drivers/xen/events.c index b4e7301..a336247 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -436,6 +436,11 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) irq = per_cpu(virq_to_irq, cpu)[virq]; if (irq == -1) { + irq = find_unbound_irq(); + + set_irq_chip_and_handler_name(irq, &xen_percpu_chip, + handle_percpu_irq, "virq"); + bind_virq.virq = virq; bind_virq.vcpu = cpu; if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, @@ -443,11 +448,6 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) BUG(); evtchn = bind_virq.port; - irq = find_unbound_irq(); - - set_irq_chip_and_handler_name(irq, &xen_percpu_chip, - handle_percpu_irq, "virq"); - evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_virq_info(evtchn, virq); -- cgit v1.1 From cb52e6d9ed9bb9cf74f8396a603ecf12b64c1ec1 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 15 Oct 2010 11:52:46 +0100 Subject: xen: improvements to VIRQ_DEBUG output * Fix bitmask formatting on 64 bit by specifying correct field widths. * Output both global and local masked and pending information. * Indicate in list of pending interrupts whether they are pending in the L2, masked globally and/or masked locally. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge --- drivers/xen/events.c | 78 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 22 deletions(-) (limited to 'drivers/xen/events.c') diff --git a/drivers/xen/events.c b/drivers/xen/events.c index a336247..b0cf80b 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -579,41 +579,75 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) { struct shared_info *sh = HYPERVISOR_shared_info; int cpu = smp_processor_id(); + unsigned long *cpu_evtchn = cpu_evtchn_mask(cpu); int i; unsigned long flags; static DEFINE_SPINLOCK(debug_lock); + struct vcpu_info *v; spin_lock_irqsave(&debug_lock, flags); - printk("vcpu %d\n ", cpu); + printk("\nvcpu %d\n ", cpu); for_each_online_cpu(i) { - struct vcpu_info *v = per_cpu(xen_vcpu, i); - printk("%d: masked=%d pending=%d event_sel %08lx\n ", i, - (get_irq_regs() && i == cpu) ? xen_irqs_disabled(get_irq_regs()) : v->evtchn_upcall_mask, - v->evtchn_upcall_pending, - v->evtchn_pending_sel); + int pending; + v = per_cpu(xen_vcpu, i); + pending = (get_irq_regs() && i == cpu) + ? xen_irqs_disabled(get_irq_regs()) + : v->evtchn_upcall_mask; + printk("%d: masked=%d pending=%d event_sel %0*lx\n ", i, + pending, v->evtchn_upcall_pending, + (int)(sizeof(v->evtchn_pending_sel)*2), + v->evtchn_pending_sel); + } + v = per_cpu(xen_vcpu, cpu); + + printk("\npending:\n "); + for (i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--) + printk("%0*lx%s", (int)sizeof(sh->evtchn_pending[0])*2, + sh->evtchn_pending[i], + i % 8 == 0 ? "\n " : " "); + printk("\nglobal mask:\n "); + for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) + printk("%0*lx%s", + (int)(sizeof(sh->evtchn_mask[0])*2), + sh->evtchn_mask[i], + i % 8 == 0 ? "\n " : " "); + + printk("\nglobally unmasked:\n "); + for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) + printk("%0*lx%s", (int)(sizeof(sh->evtchn_mask[0])*2), + sh->evtchn_pending[i] & ~sh->evtchn_mask[i], + i % 8 == 0 ? "\n " : " "); + + printk("\nlocal cpu%d mask:\n ", cpu); + for (i = (NR_EVENT_CHANNELS/BITS_PER_LONG)-1; i >= 0; i--) + printk("%0*lx%s", (int)(sizeof(cpu_evtchn[0])*2), + cpu_evtchn[i], + i % 8 == 0 ? "\n " : " "); + + printk("\nlocally unmasked:\n "); + for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) { + unsigned long pending = sh->evtchn_pending[i] + & ~sh->evtchn_mask[i] + & cpu_evtchn[i]; + printk("%0*lx%s", (int)(sizeof(sh->evtchn_mask[0])*2), + pending, i % 8 == 0 ? "\n " : " "); } - printk("pending:\n "); - for(i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--) - printk("%08lx%s", sh->evtchn_pending[i], - i % 8 == 0 ? "\n " : " "); - printk("\nmasks:\n "); - for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) - printk("%08lx%s", sh->evtchn_mask[i], - i % 8 == 0 ? "\n " : " "); - - printk("\nunmasked:\n "); - for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) - printk("%08lx%s", sh->evtchn_pending[i] & ~sh->evtchn_mask[i], - i % 8 == 0 ? "\n " : " "); printk("\npending list:\n"); - for(i = 0; i < NR_EVENT_CHANNELS; i++) { + for (i = 0; i < NR_EVENT_CHANNELS; i++) { if (sync_test_bit(i, sh->evtchn_pending)) { - printk(" %d: event %d -> irq %d\n", + int word_idx = i / BITS_PER_LONG; + printk(" %d: event %d -> irq %d%s%s%s\n", cpu_from_evtchn(i), i, - evtchn_to_irq[i]); + evtchn_to_irq[i], + sync_test_bit(word_idx, &v->evtchn_pending_sel) + ? "" : " l2-clear", + !sync_test_bit(i, sh->evtchn_mask) + ? "" : " globally-masked", + sync_test_bit(i, cpu_evtchn) + ? "" : " locally-masked"); } } -- cgit v1.1