Mailing List Archive

Fix unmask_evtchn() when the port is bound to a different
# HG changeset patch
# User kaf24@firebug.cl.cam.ac.uk
# Node ID 455b2b93542c728b88aba30de3e95c7d06d20ade
# Parent 62d9ac63e7f509328815443d8604f849b64d0c9d
Fix unmask_evtchn() when the port is bound to a different
VCPU.

Signed-off-by: Keir Fraser <keir@xensource.com>

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@lists.xensource.com
http://lists.xensource.com/xen-changelog