From fbbd5009e6ed1201731b1727762070c1a988e67d Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Mon, 14 Oct 2013 10:15:49 +0200 Subject: 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 Reviewed-by: Jan Beulich Acked-by: Keir Fraser --- xen/common/event_2l.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 xen/common/event_2l.c (limited to 'xen/common/event_2l.c') 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 +#include +#include +#include +#include +#include + +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: + */ -- cgit v1.2.3