aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/event_2l.c
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2013-10-14 10:15:49 +0200
committerJan Beulich <jbeulich@suse.com>2013-10-14 10:15:49 +0200
commitfbbd5009e6ed1201731b1727762070c1a988e67d (patch)
tree381a98fa04cc3a6625df6030b60bde4c4e701145 /xen/common/event_2l.c
parent17ae93b12ddf22f2d794260a3dc2947858c625a0 (diff)
downloadxen-fbbd5009e6ed1201731b1727762070c1a988e67d.tar.gz
xen-fbbd5009e6ed1201731b1727762070c1a988e67d.tar.bz2
xen-fbbd5009e6ed1201731b1727762070c1a988e67d.zip
evtchn: refactor low-level event channel port ops
Use functions for the low-level event channel port operations (set/clear pending, unmask, is_pending and is_masked). Group these functions into a struct evtchn_port_op so they can be replaced by alternate implementations (for different ABIs) on a per-domain basis. Signed-off-by: David Vrabel <david.vrabel@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/common/event_2l.c')
-rw-r--r--xen/common/event_2l.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/xen/common/event_2l.c b/xen/common/event_2l.c
new file mode 100644
index 0000000000..7b28942933
--- /dev/null
+++ b/xen/common/event_2l.c
@@ -0,0 +1,99 @@
+/*
+ * Event channel port operations.
+ *
+ * Copyright (c) 2003-2006, K A Fraser.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2 or later. See the file COPYING for more details.
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/sched.h>
+#include <xen/event.h>
+
+static void evtchn_2l_set_pending(struct vcpu *v, struct evtchn *evtchn)
+{
+ struct domain *d = v->domain;
+ unsigned int port = evtchn->port;
+
+ /*
+ * The following bit operations must happen in strict order.
+ * NB. On x86, the atomic bit operations also act as memory barriers.
+ * There is therefore sufficiently strict ordering for this architecture --
+ * others may require explicit memory barriers.
+ */
+
+ if ( test_and_set_bit(port, &shared_info(d, evtchn_pending)) )
+ return;
+
+ if ( !test_bit (port, &shared_info(d, evtchn_mask)) &&
+ !test_and_set_bit(port / BITS_PER_EVTCHN_WORD(d),
+ &vcpu_info(v, evtchn_pending_sel)) )
+ {
+ vcpu_mark_events_pending(v);
+ }
+
+ evtchn_check_pollers(d, port);
+}
+
+static void evtchn_2l_clear_pending(struct domain *d, struct evtchn *evtchn)
+{
+ clear_bit(evtchn->port, &shared_info(d, evtchn_pending));
+}
+
+static void evtchn_2l_unmask(struct domain *d, struct evtchn *evtchn)
+{
+ struct vcpu *v = d->vcpu[evtchn->notify_vcpu_id];
+ unsigned int port = evtchn->port;
+
+ /*
+ * These operations must happen in strict order. Based on
+ * evtchn_2l_set_pending() above.
+ */
+ if ( test_and_clear_bit(port, &shared_info(d, evtchn_mask)) &&
+ test_bit (port, &shared_info(d, evtchn_pending)) &&
+ !test_and_set_bit (port / BITS_PER_EVTCHN_WORD(d),
+ &vcpu_info(v, evtchn_pending_sel)) )
+ {
+ vcpu_mark_events_pending(v);
+ }
+}
+
+static bool_t evtchn_2l_is_pending(struct domain *d,
+ const struct evtchn *evtchn)
+{
+ return test_bit(evtchn->port, &shared_info(d, evtchn_pending));
+}
+
+static bool_t evtchn_2l_is_masked(struct domain *d,
+ const struct evtchn *evtchn)
+{
+ return test_bit(evtchn->port, &shared_info(d, evtchn_mask));
+}
+
+static const struct evtchn_port_ops evtchn_port_ops_2l =
+{
+ .set_pending = evtchn_2l_set_pending,
+ .clear_pending = evtchn_2l_clear_pending,
+ .unmask = evtchn_2l_unmask,
+ .is_pending = evtchn_2l_is_pending,
+ .is_masked = evtchn_2l_is_masked,
+};
+
+void evtchn_2l_init(struct domain *d)
+{
+ d->evtchn_port_ops = &evtchn_port_ops_2l;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */