[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH V3 17/22] Infrastructure to manipulate 3-level event channel pages
Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx> --- xen/common/event_channel.c | 170 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 807f05f..26daa7e 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -1034,6 +1034,176 @@ out: } +static long __map_l3_arrays(struct domain *d, xen_pfn_t *pending, + xen_pfn_t *mask, int nr_pages) +{ + int rc = -ENOMEM; + void *mapping; + + mapping = vmap(pending, nr_pages); + if ( !mapping ) + goto out; + d->evtchn_pending = mapping; + + mapping = vmap(mask, nr_pages); + if ( !mapping ) + { + vunmap(d->evtchn_pending); + d->evtchn_pending = NULL; + goto out; + } + d->evtchn_mask = mapping; + + rc = 0; + out: + return rc; +} + +static void __unmap_l3_arrays(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; + } +} + +static long __map_l2_selector(struct vcpu *v, unsigned long gfn, + unsigned long off) +{ + int rc = -ENOMEM; + void *mapping; + + mapping = vmap(&gfn, 1); + + if ( mapping == NULL ) + goto out; + + v->evtchn_pending_sel_l2 = mapping + off; + 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_arrays(d); +} + +static void __evtchn_setup_bitmap_l3(struct domain *d) +{ + struct vcpu *v; + + /* Easy way to setup 3-level bitmap, just move existing selector + * to next level then copy pending array and mask array */ + for_each_vcpu ( d, v ) + { + 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)); + } + + 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))); +} + +static long evtchn_register_3level(evtchn_register_3level_t *arg) +{ + struct domain *d = current->domain; + struct vcpu *v; + int rc = 0; + xen_pfn_t evtchn_pending[EVTCHN_MAX_L3_PAGES]; + xen_pfn_t evtchn_mask[EVTCHN_MAX_L3_PAGES]; + xen_pfn_t l2sel_mfn = 0; + xen_pfn_t l2sel_offset = 0; + + if ( d->evtchn_extended ) + { + rc = -EINVAL; + goto out; + } + + if ( arg->nr_vcpus > d->max_vcpus || + arg->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, arg->evtchn_pending, arg->nr_pages) ) + goto out; + if ( copy_from_guest(evtchn_mask, arg->evtchn_mask, arg->nr_pages) ) + goto out; + + rc = __map_l3_arrays(d, evtchn_pending, evtchn_mask, arg->nr_pages); + if ( rc ) + goto out; + + for_each_vcpu ( d, v ) + { + int vcpu_id = v->vcpu_id; + + rc = -EFAULT; /* common error code for following operations */ + if ( unlikely(copy_from_guest_offset(&l2sel_mfn, arg->l2sel_mfns, + vcpu_id, 1)) ) + { + __evtchn_unmap_all_3level(d); + goto out; + } + if ( unlikely(copy_from_guest_offset(&l2sel_offset, arg->l2sel_offsets, + vcpu_id, 1)) ) + { + __evtchn_unmap_all_3level(d); + goto out; + } + + if ( (rc = __map_l2_selector(v, l2sel_mfn, l2sel_offset)) ) + { + __evtchn_unmap_all_3level(d); + goto out; + } + } + + __evtchn_setup_bitmap_l3(d); + + d->evtchn_extended = EVTCHN_EXTENDED_L3; + + rc = 0; + + out: + return rc; +} + long do_event_channel_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) { long rc; -- 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 |