[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH V5 14/15] evtchn: implement 3-level event channel routines
3-level event channel ABI is fully functionaly at this point, set corresponding bit in ABI bitmap as well. Also rework domain_dump_evtchn_info. Ports are processed in batches, avoid holding event_lock for too long. --- xen/common/event_channel.c | 143 +++++++++++++++++++++++++++------------- xen/common/evtchn_bitmap_abi.c | 102 +++++++++++++++++++++++----- xen/include/xen/event.h | 8 ++- 3 files changed, 192 insertions(+), 61 deletions(-) diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index d5b2e37..0f9e8e4 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -33,7 +33,22 @@ #include <xsm/xsm.h> /* A bitmap of supported extended event channel ABIs */ -uint64_t extended_event_channel = EVTCHN_EXTENDED_NONE; +uint64_t extended_event_channel = (EVTCHN_EXTENDED_NONE | + EVTCHN_EXTENDED_L3); + +static inline const char * evtchn_abi_str(unsigned int abi) +{ + switch ( abi ) + { + case EVTCHN_EXTENDED_NONE: + return "2-level"; + case EVTCHN_EXTENDED_L3: + return "3-level"; + default: + BUG(); + } + return ""; /* make compiler happy */ +} #define ERROR_EXIT(_errno) \ do { \ @@ -1212,8 +1227,16 @@ void notify_via_xen_event_channel(struct domain *ld, int lport) const static struct evtchn_port_ops evtchn_2l_ops = { .is_pending = evtchn_bitmap_is_pending, .is_masked = evtchn_bitmap_is_masked, - .set_pending = evtchn_bitmap_set_pending, - .unmask = evtchn_bitmap_unmask, + .set_pending = evtchn_bitmap_2l_set_pending, + .unmask = evtchn_bitmap_2l_unmask, + .clear_pending = evtchn_bitmap_clear_pending +}; + +const static struct evtchn_port_ops evtchn_3l_ops = { + .is_pending = evtchn_bitmap_is_pending, + .is_masked = evtchn_bitmap_is_masked, + .set_pending = evtchn_bitmap_3l_set_pending, + .unmask = evtchn_bitmap_3l_unmask, .clear_pending = evtchn_bitmap_clear_pending }; @@ -1227,6 +1250,9 @@ void evtchn_set_abi(struct domain *d, uint64_t abi) case EVTCHN_EXTENDED_NONE: d->evtchn_ops = &evtchn_2l_ops; break; + case EVTCHN_EXTENDED_L3: + d->evtchn_ops = &evtchn_3l_ops; + break; default: BUG(); } @@ -1344,61 +1370,90 @@ static void domain_dump_evtchn_info(struct domain *d) { unsigned int port; int irq; + int i, j, k; bitmap_scnlistprintf(keyhandler_scratch, sizeof(keyhandler_scratch), d->poll_mask, d->max_vcpus); printk("Event channel information for domain %d:\n" + "Using %s event channel ABI\n" "Polling vCPUs: {%s}\n" - " port [p/m]\n", d->domain_id, keyhandler_scratch); + " port [p/m]\n", + d->domain_id, evtchn_abi_str(d->evtchn_extended), + keyhandler_scratch); - spin_lock(&d->event_lock); - - for ( port = 1; port < d->max_evtchns; ++port ) + /* + * Print out infomation on per-group basis, avoid holding + * event_lock for too long. It's worth noting that groups and + * buckets never shrink unless domain is being destroyed. + */ + for ( i = 0; i < NR_EVTCHN_GROUPS; i++ ) { - const struct evtchn *chn; - char *ssid; - - if ( !port_is_valid(d, port) ) - continue; - chn = evtchn_from_port(d, port); - if ( chn->state == ECS_FREE ) - continue; + if ( unlikely(d->is_dying) ) + break; - printk(" %4u [%d/%d]: s=%d n=%d x=%d", - port, - !!evtchn_is_pending(d, port), - !!evtchn_is_masked(d, port), - chn->state, chn->notify_vcpu_id, chn->xen_consumer); + spin_lock(&d->event_lock); - switch ( chn->state ) + if ( d->evtchn[i] == NULL ) { - case ECS_UNBOUND: - printk(" d=%d", chn->u.unbound.remote_domid); - break; - case ECS_INTERDOMAIN: - printk(" d=%d p=%d", - chn->u.interdomain.remote_dom->domain_id, - chn->u.interdomain.remote_port); - break; - case ECS_PIRQ: - irq = domain_pirq_to_irq(d, chn->u.pirq.irq); - printk(" p=%d i=%d", chn->u.pirq.irq, irq); - break; - case ECS_VIRQ: - printk(" v=%d", chn->u.virq); - break; + spin_unlock(&d->event_lock); + continue; } - ssid = xsm_show_security_evtchn(d, chn); - if (ssid) { - printk(" Z=%s\n", ssid); - xfree(ssid); - } else { - printk("\n"); + for ( j = 0; j < BUCKETS_PER_GROUP; j++ ) + { + if ( d->evtchn[i][j] == NULL ) + continue; + + for ( k = 0; k < EVTCHNS_PER_BUCKET; k++ ) + { + const struct evtchn *chn; + char *ssid; + + port = i * EVTCHNS_PER_GROUP + j * EVTCHNS_PER_BUCKET + k; + + if ( !port_is_valid(d, port) ) + continue; + chn = evtchn_from_port(d, port); + if ( chn->state == ECS_FREE ) + continue; + + printk(" %4u [%d/%d]: s=%d n=%d x=%d", + port, + !!evtchn_is_pending(d, port), + !!evtchn_is_masked(d, port), + chn->state, chn->notify_vcpu_id, chn->xen_consumer); + + switch ( chn->state ) + { + case ECS_UNBOUND: + printk(" d=%d", chn->u.unbound.remote_domid); + break; + case ECS_INTERDOMAIN: + printk(" d=%d p=%d", + chn->u.interdomain.remote_dom->domain_id, + chn->u.interdomain.remote_port); + break; + case ECS_PIRQ: + irq = domain_pirq_to_irq(d, chn->u.pirq.irq); + printk(" p=%d i=%d", chn->u.pirq.irq, irq); + break; + case ECS_VIRQ: + printk(" v=%d", chn->u.virq); + break; + } + + ssid = xsm_show_security_evtchn(d, chn); + if (ssid) + { + printk(" Z=%s\n", ssid); + xfree(ssid); + } else { + printk("\n"); + } + } } + spin_unlock(&d->event_lock); } - - spin_unlock(&d->event_lock); } static void dump_evtchn_info(unsigned char key) diff --git a/xen/common/evtchn_bitmap_abi.c b/xen/common/evtchn_bitmap_abi.c index e358691..5110613 100644 --- a/xen/common/evtchn_bitmap_abi.c +++ b/xen/common/evtchn_bitmap_abi.c @@ -1,7 +1,7 @@ /****************************************************************************** * evtchn_bitmap_abi.c * - * Event channel 2-level ABI implementation. + * Event channel 2/3-level ABI implementation. * * Copyright (c) 2013 Citrix Systems * @@ -167,10 +167,33 @@ int evtchn_bitmap_is_masked(struct domain *d, int port) return test_bit(port, d->evtchn_mask); } -void evtchn_bitmap_set_pending(struct vcpu *v, int port) +static void __check_vcpu_polling(struct vcpu *v, int port) { - struct domain *d = v->domain; int vcpuid; + struct domain *d = v->domain; + + /* Check if some VCPU might be polling for this event. */ + if ( likely(bitmap_empty(d->poll_mask, d->max_vcpus)) ) + return; + + /* Wake any interested (or potentially interested) pollers. */ + for ( vcpuid = find_first_bit(d->poll_mask, d->max_vcpus); + vcpuid < d->max_vcpus; + vcpuid = find_next_bit(d->poll_mask, d->max_vcpus, vcpuid+1) ) + { + v = d->vcpu[vcpuid]; + if ( ((v->poll_evtchn <= 0) || (v->poll_evtchn == port)) && + test_and_clear_bit(vcpuid, d->poll_mask) ) + { + v->poll_evtchn = 0; + vcpu_unblock(v); + } + } +} + +void evtchn_bitmap_2l_set_pending(struct vcpu *v, int port) +{ + struct domain *d = v->domain; /* * The following bit operations must happen in strict order. @@ -193,19 +216,36 @@ void evtchn_bitmap_set_pending(struct vcpu *v, int port) if ( likely(bitmap_empty(d->poll_mask, d->max_vcpus)) ) return; - /* Wake any interested (or potentially interested) pollers. */ - for ( vcpuid = find_first_bit(d->poll_mask, d->max_vcpus); - vcpuid < d->max_vcpus; - vcpuid = find_next_bit(d->poll_mask, d->max_vcpus, vcpuid+1) ) + __check_vcpu_polling(v, port); +} + +void evtchn_bitmap_3l_set_pending(struct vcpu *v, int port) +{ + struct domain *d = v->domain; + unsigned int l1bit = port >> (EVTCHN_WORD_BITORDER(d) << 1); + unsigned int l2bit = port >> EVTCHN_WORD_BITORDER(d); + + if (unlikely(!v->evtchn_pending_sel_l2)) + return; + + /* + * 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, d->evtchn_pending) ) + return; + + if ( !test_bit(port, d->evtchn_mask) && + !test_and_set_bit(l2bit, v->evtchn_pending_sel_l2) && + !test_and_set_bit(l1bit, &vcpu_info(v, evtchn_pending_sel)) ) { - v = d->vcpu[vcpuid]; - if ( ((v->poll_evtchn <= 0) || (v->poll_evtchn == port)) && - test_and_clear_bit(vcpuid, d->poll_mask) ) - { - v->poll_evtchn = 0; - vcpu_unblock(v); - } + vcpu_mark_events_pending(v); } + + __check_vcpu_polling(v, port); } void evtchn_bitmap_clear_pending(struct domain *d, int port) @@ -213,7 +253,7 @@ void evtchn_bitmap_clear_pending(struct domain *d, int port) clear_bit(port, d->evtchn_pending); } -int evtchn_bitmap_unmask(unsigned int port) +int evtchn_bitmap_2l_unmask(unsigned int port) { struct domain *d = current->domain; struct vcpu *v; @@ -240,6 +280,38 @@ int evtchn_bitmap_unmask(unsigned int port) return 0; } +int evtchn_bitmap_3l_unmask(unsigned int port) +{ + struct domain *d = current->domain; + struct vcpu *v; + unsigned int l1bit = port >> (EVTCHN_WORD_BITORDER(d) << 1); + unsigned int l2bit = port >> EVTCHN_WORD_BITORDER(d); + + ASSERT(spin_is_locked(&d->event_lock)); + + if ( unlikely(!port_is_valid(d, port)) ) + return -EINVAL; + + v = d->vcpu[evtchn_from_port(d, port)->notify_vcpu_id]; + + if (unlikely(!v->evtchn_pending_sel_l2)) + return -EINVAL; + + /* + * These operations must happen in strict order. Based on + * include/xen/event.h:evtchn_set_pending(). + */ + if ( test_and_clear_bit(port, d->evtchn_mask) && + test_bit (port, d->evtchn_pending) && + !test_and_set_bit (l2bit, v->evtchn_pending_sel_l2) && + !test_and_set_bit (l1bit, &vcpu_info(v, evtchn_pending_sel)) ) + { + vcpu_mark_events_pending(v); + } + + return 0; +} + /* * Local variables: * mode: C diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h index 182546c..3f7a18f 100644 --- a/xen/include/xen/event.h +++ b/xen/include/xen/event.h @@ -139,11 +139,15 @@ void notify_via_xen_event_channel(struct domain *ld, int lport); void evtchn_set_default_bitmap(struct domain *d); /* 2-level ABI routines */ +void evtchn_bitmap_2l_set_pending(struct vcpu *v, int port); +int evtchn_bitmap_2l_unmask(unsigned int port); +/* 3-level ABI routines */ +void evtchn_bitmap_3l_set_pending(struct vcpu *v, int port); +int evtchn_bitmap_3l_unmask(unsigned int port); +/* Shared routines for 2/3-level ABIs */ int evtchn_bitmap_is_pending(struct domain *d, int port); int evtchn_bitmap_is_masked(struct domain *d, int port); -void evtchn_bitmap_set_pending(struct vcpu *v, int port); void evtchn_bitmap_clear_pending(struct domain *d, int port); -int evtchn_bitmap_unmask(unsigned int port); /* Functions used to manipulate 3-level event channel pages */ long evtchn_map_l3_bitmaps(struct domain *d, evtchn_register_3level_t *reg); -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |