|
[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 |