[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH V4 15/18] Infrastructure to manipulate 3-level event channel pages
Introduce __{,un}map_l3_bitmaps, __{,un}map_l2_selector for 3-level event channel ABI. Introduce evtchn_unregister_extended in the teardown path. Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx> --- xen/common/event_channel.c | 210 ++++++++++++++++++++++++++++++++++++++++++++ xen/include/xen/sched.h | 3 + 2 files changed, 213 insertions(+) diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 4fb7794..4cf172b 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -1025,6 +1025,191 @@ static void __set_evtchn_abi(struct domain *d, uint64_t abi) d->max_evtchns = max_evtchns(d); } +static long __map_l3_bitmaps(struct domain *d, evtchn_register_3level_t *reg) +{ + int rc; + void *pending_mapping, *mask_mapping; + xen_pfn_t evtchn_pending[EVTCHN_MAX_L3_PAGES]; + xen_pfn_t evtchn_mask[EVTCHN_MAX_L3_PAGES]; + uint32_t nr_pages; + + /* Return if we've mapped those bitmaps */ + if ( d->evtchn_extended == EVTCHN_EXTENDED_L3 ) + return -EBUSY; + + nr_pages = reg->u.bitmaps.nr_pages; + + if ( nr_pages > EVTCHN_MAX_L3_PAGES ) + { + rc = -EINVAL; + goto out; + } + + memset(evtchn_pending, 0, sizeof(xen_pfn_t) * EVTCHN_MAX_L3_PAGES); + memset(evtchn_mask, 0, sizeof(xen_pfn_t) * EVTCHN_MAX_L3_PAGES); + + rc = -EFAULT; /* common error code for following operations */ + if ( copy_from_guest(evtchn_pending, reg->u.bitmaps.evtchn_pending, + nr_pages) ) + goto out; + if ( copy_from_guest(evtchn_mask, reg->u.bitmaps.evtchn_mask, + nr_pages) ) + goto out; + + rc = -ENOMEM; + pending_mapping = vmap(evtchn_pending, nr_pages); + if ( !pending_mapping ) + goto out; + + + mask_mapping = vmap(evtchn_mask, nr_pages); + if ( !mask_mapping ) + { + vunmap(pending_mapping); + goto out; + } + + d->evtchn_pending = pending_mapping; + d->evtchn_mask = mask_mapping; + + __set_evtchn_abi(d, EVTCHN_EXTENDED_L3); + + memcpy(d->evtchn_pending, &shared_info(d, evtchn_pending), + sizeof(shared_info(d, evtchn_pending))); + memcpy(d->evtchn_mask, &shared_info(d, evtchn_mask), + sizeof(shared_info(d, evtchn_mask))); + + rc = 0; + out: + return rc; +} + +static void __unmap_l3_bitmaps(struct domain *d) +{ + if ( d->evtchn_pending ) + { + vunmap(d->evtchn_pending); + d->evtchn_pending = NULL; + } + + if ( d->evtchn_mask ) + { + vunmap(d->evtchn_mask); + d->evtchn_mask = NULL; + } + + __set_evtchn_abi(d, EVTCHN_EXTENDED_NONE); +} + +static long __map_l2_selector(struct vcpu *v, evtchn_register_3level_t *reg) +{ + int rc; + void *mapping; + xen_pfn_t mfn = 0; + xen_pfn_t offset = 0; + + mfn = reg->u.l2_selector.mfn; + offset = reg->u.l2_selector.offset; + + /* Already mapped? */ + if ( v->evtchn_pending_sel_l2 ) + return -EBUSY; + + /* must within one page */ + if ( offset + sizeof(xen_ulong_t)*sizeof(xen_ulong_t)*8 > PAGE_SIZE ) + { + rc = -EINVAL; + goto out; + } + + mapping = vmap(&mfn, 1); + + if ( mapping == NULL ) + { + rc = -ENOMEM; + goto out; + } + + v->evtchn_pending_sel_l2 = mapping + offset; + + memcpy(&v->evtchn_pending_sel_l2[0], + &vcpu_info(v, evtchn_pending_sel), + sizeof(vcpu_info(v, evtchn_pending_sel))); + memset(&vcpu_info(v, evtchn_pending_sel), 0, + sizeof(vcpu_info(v, evtchn_pending_sel))); + set_bit(0, &vcpu_info(v, evtchn_pending_sel)); + + rc = 0; + + out: + return rc; +} + +static void __unmap_l2_selector(struct vcpu *v) +{ + if ( v->evtchn_pending_sel_l2 ) + { + unsigned long addr = + (unsigned long)(v->evtchn_pending_sel_l2) & PAGE_MASK; + vunmap((void *)addr); + v->evtchn_pending_sel_l2 = NULL; + } +} + +static void __evtchn_unmap_all_3level(struct domain *d) +{ + struct vcpu *v; + for_each_vcpu ( d, v ) + __unmap_l2_selector(v); + __unmap_l3_bitmaps(d); +} + +static long evtchn_register_3level(evtchn_register_3level_t *arg) +{ + struct domain *d = current->domain; + int rc; + + /* + * This domain must be in one of the two states: + * a) it has no active extended ABI in use and tries to register + * L3 bitmaps + * b) it has activated 3-level ABI and tries to register L2 + * selector + */ + if ( !((d->evtchn_extended == EVTCHN_EXTENDED_NONE && + arg->cmd == REGISTER_BITMAPS) || + (d->evtchn_extended == EVTCHN_EXTENDED_L3 && + arg->cmd == REGISTER_L2_SELECTOR)) ) + { + rc = -EINVAL; + goto out; + } + + switch ( arg->cmd ) + { + case REGISTER_BITMAPS: + rc = __map_l3_bitmaps(d, arg); + break; + case REGISTER_L2_SELECTOR: { + int vcpu_id = arg->u.l2_selector.cpu_id; + struct vcpu *v; + if ( vcpu_id >= d->max_vcpus ) + rc = -EINVAL; + else + { + v = d->vcpu[vcpu_id]; + rc = __map_l2_selector(v, arg); + } + break; + } + default: + rc = -EINVAL; + } + + out: + return rc; +} + long do_event_channel_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) { long rc; @@ -1142,6 +1327,14 @@ long do_event_channel_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) break; } + case EVTCHNOP_register_3level: { + struct evtchn_register_3level reg; + if ( copy_from_guest(®, arg, 1) != 0 ) + return -EFAULT; + rc = evtchn_register_3level(®); + break; + } + default: rc = -ENOSYS; break; @@ -1270,6 +1463,21 @@ int evtchn_init(struct domain *d) return 0; } +/* Clean up all extended event channel ABI mappings */ +static void evtchn_unregister_extended(struct domain *d) +{ + switch ( d->evtchn_extended ) + { + case EVTCHN_EXTENDED_NONE: + /* Nothing to do */ + break; + case EVTCHN_EXTENDED_L3: + __evtchn_unmap_all_3level(d); + break; + default: + BUG(); + } +} void evtchn_destroy(struct domain *d) { @@ -1298,6 +1506,8 @@ void evtchn_destroy(struct domain *d) clear_global_virq_handlers(d); + evtchn_unregister_extended(d); + xfree(d->evtchn); } diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 74a8d43..cca5e7f 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -57,6 +57,9 @@ struct vcpu struct domain *domain; + /* For 3-level event channel ABI */ + xen_ulong_t *evtchn_pending_sel_l2; + struct vcpu *next_in_list; s_time_t periodic_period; -- 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 |