[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Fix unmask_evtchn() when the port is bound to a different
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 455b2b93542c728b88aba30de3e95c7d06d20ade # Parent 62d9ac63e7f509328815443d8604f849b64d0c9d Fix unmask_evtchn() when the port is bound to a different VCPU. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> diff -r 62d9ac63e7f5 -r 455b2b93542c linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Tue Dec 13 18:08:26 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Tue Dec 13 18:20:29 2005 @@ -639,6 +639,44 @@ } EXPORT_SYMBOL(notify_remote_via_irq); +void mask_evtchn(int port) +{ + shared_info_t *s = HYPERVISOR_shared_info; + synch_set_bit(port, &s->evtchn_mask[0]); +} +EXPORT_SYMBOL(mask_evtchn); + +void unmask_evtchn(int port) +{ + shared_info_t *s = HYPERVISOR_shared_info; + unsigned int cpu = smp_processor_id(); + vcpu_info_t *vcpu_info = &s->vcpu_info[cpu]; + + /* Slow path (hypercall) if this is a non-local port. */ + if (unlikely(cpu != cpu_from_evtchn(port))) { + evtchn_op_t op = { .cmd = EVTCHNOP_unmask, + .u.unmask.port = port }; + (void)HYPERVISOR_event_channel_op(&op); + return; + } + + synch_clear_bit(port, &s->evtchn_mask[0]); + + /* + * The following is basically the equivalent of 'hw_resend_irq'. Just + * like a real IO-APIC we 'lose the interrupt edge' if the channel is + * masked. + */ + if (synch_test_bit(port, &s->evtchn_pending[0]) && + !synch_test_and_set_bit(port / BITS_PER_LONG, + &vcpu_info->evtchn_pending_sel)) { + vcpu_info->evtchn_upcall_pending = 1; + if (!vcpu_info->evtchn_upcall_mask) + force_evtchn_callback(); + } +} +EXPORT_SYMBOL(unmask_evtchn); + void irq_resume(void) { evtchn_op_t op; diff -r 62d9ac63e7f5 -r 455b2b93542c linux-2.6-xen-sparse/include/asm-xen/evtchn.h --- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Tue Dec 13 18:08:26 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Tue Dec 13 18:20:29 2005 @@ -79,46 +79,16 @@ */ extern void unbind_from_irqhandler(unsigned int irq, void *dev_id); -/* - * Unlike notify_remote_via_evtchn(), this is safe to use across - * save/restore. Notifications on a broken connection are silently dropped. - */ -void notify_remote_via_irq(int irq); - extern void irq_resume(void); /* Entry point for notifications into Linux subsystems. */ asmlinkage void evtchn_do_upcall(struct pt_regs *regs); /* Entry point for notifications into the userland character device. */ -void evtchn_device_upcall(int port); +extern void evtchn_device_upcall(int port); -static inline void mask_evtchn(int port) -{ - shared_info_t *s = HYPERVISOR_shared_info; - synch_set_bit(port, &s->evtchn_mask[0]); -} - -static inline void unmask_evtchn(int port) -{ - shared_info_t *s = HYPERVISOR_shared_info; - vcpu_info_t *vcpu_info = &s->vcpu_info[smp_processor_id()]; - - synch_clear_bit(port, &s->evtchn_mask[0]); - - /* - * The following is basically the equivalent of 'hw_resend_irq'. Just - * like a real IO-APIC we 'lose the interrupt edge' if the channel is - * masked. - */ - if (synch_test_bit(port, &s->evtchn_pending[0]) && - !synch_test_and_set_bit(port / BITS_PER_LONG, - &vcpu_info->evtchn_pending_sel)) { - vcpu_info->evtchn_upcall_pending = 1; - if (!vcpu_info->evtchn_upcall_mask) - force_evtchn_callback(); - } -} +extern void mask_evtchn(int port); +extern void unmask_evtchn(int port); static inline void clear_evtchn(int port) { @@ -134,6 +104,12 @@ (void)HYPERVISOR_event_channel_op(&op); } +/* + * Unlike notify_remote_via_evtchn(), this is safe to use across + * save/restore. Notifications on a broken connection are silently dropped. + */ +extern void notify_remote_via_irq(int irq); + #endif /* __ASM_EVTCHN_H__ */ /* diff -r 62d9ac63e7f5 -r 455b2b93542c xen/common/event_channel.c --- a/xen/common/event_channel.c Tue Dec 13 18:08:26 2005 +++ b/xen/common/event_channel.c Tue Dec 13 18:20:29 2005 @@ -3,7 +3,7 @@ * * Event notifications from VIRQs, PIRQs, and other domains. * - * Copyright (c) 2003-2004, K A Fraser. + * Copyright (c) 2003-2005, K A Fraser. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -541,6 +541,41 @@ return rc; } +static long evtchn_unmask(evtchn_unmask_t *unmask) +{ + struct domain *d = current->domain; + shared_info_t *s = d->shared_info; + int port = unmask->port; + struct vcpu *v; + + spin_lock(&d->evtchn_lock); + + if ( unlikely(!port_is_valid(d, port)) ) + { + spin_unlock(&d->evtchn_lock); + return -EINVAL; + } + + v = d->vcpu[evtchn_from_port(d, port)->notify_vcpu_id]; + + /* + * These operations must happen in strict order. Based on + * include/xen/event.h:evtchn_set_pending(). + */ + if ( test_and_clear_bit(port, &s->evtchn_mask[0]) && + test_bit (port, &s->evtchn_pending[0]) && + !test_and_set_bit (port / BITS_PER_LONG, + &v->vcpu_info->evtchn_pending_sel) && + !test_and_set_bit (0, &v->vcpu_info->evtchn_upcall_pending) ) + { + evtchn_notify(v); + } + + spin_unlock(&d->evtchn_lock); + + return 0; +} + long do_event_channel_op(evtchn_op_t *uop) { long rc; @@ -600,6 +635,10 @@ case EVTCHNOP_bind_vcpu: rc = evtchn_bind_vcpu(&op.u.bind_vcpu); + break; + + case EVTCHNOP_unmask: + rc = evtchn_unmask(&op.u.unmask); break; default: diff -r 62d9ac63e7f5 -r 455b2b93542c xen/include/public/event_channel.h --- a/xen/include/public/event_channel.h Tue Dec 13 18:08:26 2005 +++ b/xen/include/public/event_channel.h Tue Dec 13 18:20:29 2005 @@ -164,6 +164,16 @@ uint32_t vcpu; } evtchn_bind_vcpu_t; +/* + * EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver + * a notification to the appropriate VCPU if an event is pending. + */ +#define EVTCHNOP_unmask 9 +typedef struct evtchn_unmask { + /* IN parameters. */ + evtchn_port_t port; +} evtchn_unmask_t; + typedef struct evtchn_op { uint32_t cmd; /* EVTCHNOP_* */ union { @@ -176,6 +186,7 @@ evtchn_send_t send; evtchn_status_t status; evtchn_bind_vcpu_t bind_vcpu; + evtchn_unmask_t unmask; } u; } evtchn_op_t; diff -r 62d9ac63e7f5 -r 455b2b93542c xen/include/xen/event.h --- a/xen/include/xen/event.h Tue Dec 13 18:08:26 2005 +++ b/xen/include/xen/event.h Tue Dec 13 18:20:29 2005 @@ -3,7 +3,7 @@ * * A nice interface for passing asynchronous events to guest OSes. * - * Copyright (c) 2002, K A Fraser + * Copyright (c) 2002-2005, K A Fraser */ #ifndef __XEN_EVENT_H__ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |