[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.