--- 2006-04-21/linux-2.6-xen-sparse/kernel/irq/handle.c 2006-03-20 06:53:29.000000000 +0100 +++ 2006-04-21/linux-2.6-xen-sparse/kernel/irq/handle.c 2006-04-27 10:16:35.000000000 +0200 @@ -12,6 +12,10 @@ #include #include +#ifdef CONFIG_XEN +#include +#endif + #include "internals.h" /* @@ -76,10 +80,19 @@ irqreturn_t no_action(int cpl, void *dev /* * Have got an event to handle: */ -fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, +fastcall /*irqreturn_t*/int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, struct irqaction *action) { - int ret, retval = 0, status = 0; + irqreturn_t ret, retval = IRQ_NONE; + unsigned int status = 0; + +#ifdef CONFIG_XEN + unsigned int pirq = irq_to_pirq(irq); + + BUILD_BUG_ON(BITS_TO_LONGS(NR_PIRQS) > sizeof(((shared_info_t *)0)->pirq_shared)); + if (pirq < NR_PIRQS && test_bit(pirq, HYPERVISOR_shared_info->pirq_shared)) + retval = IRQ_HANDLED; +#endif if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); --- 2006-04-21/xen/arch/x86/irq.c.0 2006-04-24 10:56:27.000000000 +0200 +++ 2006-04-21/xen/arch/x86/irq.c 2006-04-27 09:54:43.000000000 +0200 @@ -200,7 +200,7 @@ static void __do_IRQ_guest(int vector) if ( (action->ack_type != ACKTYPE_NONE) && !test_and_set_bit(irq, d->pirq_mask) ) action->in_flight++; - send_guest_pirq(d, irq); + send_guest_pirq(d, irq, action->nr_guests > 1); } } --- 2006-04-21/xen/arch/ia64/xen/irq.c.0 2006-04-06 17:50:25.000000000 +0200 +++ 2006-04-21/xen/arch/ia64/xen/irq.c 2006-04-27 09:54:32.000000000 +0200 @@ -411,7 +411,7 @@ static void __do_IRQ_guest(int irq) if ( (action->ack_type != ACKTYPE_NONE) && !test_and_set_bit(irq, &d->pirq_mask) ) action->in_flight++; - send_guest_pirq(d, irq); + send_guest_pirq(d, irq, action->nr_guests > 1); } } --- 2006-04-21/xen/common/event_channel.c.0 2006-04-06 17:50:26.000000000 +0200 +++ 2006-04-21/xen/common/event_channel.c 2006-04-27 09:57:36.000000000 +0200 @@ -539,13 +539,20 @@ void send_guest_virq(struct vcpu *v, int } -void send_guest_pirq(struct domain *d, int pirq) +void send_guest_pirq(struct domain *d, int pirq, int shared) { int port = d->pirq_to_evtchn[pirq]; struct evtchn *chn; + shared_info_t *s = d->shared_info; ASSERT(port != 0); + BUILD_BUG_ON(BITS_TO_LONGS(NR_PIRQS) > sizeof(((shared_info_t *)0)->pirq_shared)); + if (shared) + set_bit(pirq, s->pirq_shared); + else + clear_bit(pirq, s->pirq_shared); + chn = evtchn_from_port(d, port); evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port); } --- 2006-04-21/xen/include/public/xen.h.0 2006-04-07 10:05:06.000000000 +0200 +++ 2006-04-21/xen/include/public/xen.h 2006-04-27 11:36:53.000000000 +0200 @@ -408,6 +408,14 @@ typedef struct shared_info { struct arch_shared_info arch; + /* + * Indicator which PIRQs are shared with other domains, allowing the guest + * to not consider respective interrupts spurious even if no handler claims + * them, while still being able to detect spurious occurrences of un-shared + * interrupts. + */ + unsigned long pirq_shared[256 / (8 * sizeof(unsigned long))]; + }; typedef struct shared_info shared_info_t; --- 2006-04-21/xen/include/xen/event.h.0 2006-04-06 17:50:27.000000000 +0200 +++ 2006-04-21/xen/include/xen/event.h 2006-04-27 09:54:21.000000000 +0200 @@ -35,8 +35,9 @@ extern void send_guest_virq(struct vcpu * send_guest_pirq: * @d: Domain to which physical IRQ should be sent * @pirq: Physical IRQ number + * @shared: Indicator whether IRQ is shared with other domain(s) */ -extern void send_guest_pirq(struct domain *d, int pirq); +extern void send_guest_pirq(struct domain *d, int pirq, int shared); #define evtchn_pending(d, p) \ (test_bit((p), &(d)->shared_info->evtchn_pending[0]))