[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT PATCH 5/9] plat/xen/drivers/9p: Connect to xenbus device


  • To: "minios-devel@xxxxxxxxxxxxx" <minios-devel@xxxxxxxxxxxxx>
  • From: Vlad-Andrei BĂDOIU (78692) <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
  • Date: Sat, 7 Sep 2019 10:21:58 +0000
  • Accept-language: en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=stud.acs.upb.ro; dmarc=pass action=none header.from=stud.acs.upb.ro; dkim=pass header.d=stud.acs.upb.ro; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Y3HBAzU4Xe5K7Hl8Yeq30X/tLWuZPtUNMISrc8R614Q=; b=R3iRgeFITHQr+K8/eyy3XwcnIOA9rDmcvCBQW1t3GghHLH0Cd/4ovOMEUrqAD3nvLo1g91IHio4w1YFKISOqYZb16N6CGbLhtoNlUXxGiDsWATsMbZgC4i9JOYthQQIkQwwUBxhBtnBCNWk257M6p0pZvjbqKkO6U/Kyu0I/scWWQ7GdolbLE438LHfygv2sWSEMgfFCDrTO5JuYjpzwj/+lX+YyosvEQS6zEz4Ee+z3p/3eShMCQ/PjV0ZgK/fXMRhol0TJ/hfpm41UrzMw2a83eXtEDiKT4ha4NLVB2wCK4JeVZAC91xXMRHxPq3MI+eF7scl2OXA+4SA+TafUGg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=brSBFZAEYc3xcMsrmyv1F61IVQpqr4y+q2KK8JgfVYGoM+7XutjoG1gA0DvbLnZpo2DIFPwY6w4rGEojsPoX+0isAivkvzS6eHN6WYTcZmV1ZI3gcG1IDyFji7ekj365pm/4qod6yeIfkiz1oQyFH/+Et0pJJNcHsCQz8/XN5qgQLa13r1Z7uxBXw6FE/rKb43A//OK7qPA9ndKbOgFvbxFCGo6awBttgi5EVAiLT+sihduY9ONgRbz8OGrQhgfEjHvHCTCg44v6Qi7OWM3ow84KgSzxyAr1lzx0BVAIkZEKK2S2prj+LHKrSZpOSHZW5reXUdF9oyAG7b0X9zZPTQ==
  • Authentication-results: spf=none (sender IP is ) smtp.mailfrom=vlad_andrei.badoiu@xxxxxxxxxxxxxxx;
  • Cc: "costin.lupu@xxxxxxxxx" <costin.lupu@xxxxxxxxx>, Cristian Banu <cristb@xxxxxxxxx>
  • Delivery-date: Sat, 07 Sep 2019 10:22:30 +0000
  • List-id: Mini-os development list <minios-devel.lists.xenproject.org>
  • Thread-index: AQHVZWYUHIYNG9M/aEywvXKU87klPg==
  • Thread-topic: [UNIKRAFT PATCH 5/9] plat/xen/drivers/9p: Connect to xenbus device

From: Cristian Banu <cristb@xxxxxxxxx>

This patch implements ring allocation, reference granting and event channel
allocation, with the purpose of establishing the connection to the
backend 9pfs device.

Signed-off-by: Cristian Banu <cristb@xxxxxxxxx>
---
 plat/xen/Config.uk               |  19 ++-
 plat/xen/drivers/9p/9pfront.c    | 167 +++++++++++++++++++++++++
 plat/xen/drivers/9p/9pfront.h    |  29 +++++
 plat/xen/drivers/9p/9pfront_xb.h |  12 ++
 plat/xen/drivers/9p/9pfront_xs.c | 204 +++++++++++++++++++++++++++++++
 5 files changed, 430 insertions(+), 1 deletion(-)

diff --git a/plat/xen/Config.uk b/plat/xen/Config.uk
index dfffb320..1ad7f7e4 100644
--- a/plat/xen/Config.uk
+++ b/plat/xen/Config.uk
@@ -73,11 +73,28 @@ menu "Xenbus Drivers"
         depends on XEN_XENBUS
         depends on XEN_GNTTAB
 
-config XEN_9PFRONT
+menuconfig XEN_9PFRONT
        bool "Xenbus 9pfront Driver"
        default n
        depends on LIBUK9P
        help
                Driver for 9pfs devices
+
+config XEN_9PFRONT_NB_RINGS
+       int "Xen 9P ring number"
+       default 2
+       depends on XEN_9PFRONT
+       help
+               Number of rings to allocate.
+               Will be clamped to the maximum value allowed by the backend.
+
+config XEN_9PFRONT_RING_ORDER
+       int "Xen 9P ring order"
+       default 6
+       depends on XEN_9PFRONT
+       help
+               Ring order for xen 9P devices. Orders of 0, 1, 2, ..., 9 will
+               create rings of size 4K, 8K, 16K, ..., 2M respectively.
+               Will be clamped to the maximum value allowed by the backend.
 endmenu
 endif
diff --git a/plat/xen/drivers/9p/9pfront.c b/plat/xen/drivers/9p/9pfront.c
index f289cd05..3898cb85 100644
--- a/plat/xen/drivers/9p/9pfront.c
+++ b/plat/xen/drivers/9p/9pfront.c
@@ -32,12 +32,15 @@
  * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
  */
 
+#include <stdbool.h>
 #include <uk/config.h>
 #include <uk/alloc.h>
 #include <uk/assert.h>
 #include <uk/essentials.h>
 #include <uk/list.h>
 #include <uk/plat/spinlock.h>
+#include <xen-x86/mm.h>
+#include <xen-x86/irq.h>
 #include <xenbus/xenbus.h>
 
 #include "9pfront_xb.h"
@@ -48,6 +51,142 @@ static struct uk_alloc *a;
 static UK_LIST_HEAD(p9front_device_list);
 static DEFINE_SPINLOCK(p9front_device_list_lock);
 
+static void p9front_handler(evtchn_port_t evtchn __unused,
+                           struct __regs *regs __unused,
+                           void *arg __unused)
+{
+}
+
+static void p9front_free_dev_ring(struct p9front_dev *p9fdev, int idx)
+{
+       struct p9front_dev_ring *ring = &p9fdev->rings[idx];
+       int i;
+
+       UK_ASSERT(ring->initialized);
+
+       unbind_evtchn(ring->evtchn);
+       for (i = 0; i < (1 << p9fdev->ring_order); i++)
+               gnttab_end_access(ring->intf->ref[i]);
+       uk_pfree(a, ring->data.in,
+               p9fdev->ring_order + XEN_PAGE_SHIFT - PAGE_SHIFT);
+       gnttab_end_access(ring->ref);
+       uk_pfree(a, ring->intf, 0);
+       ring->initialized = false;
+}
+
+static void p9front_free_dev_rings(struct p9front_dev *p9fdev)
+{
+       int i;
+
+       for (i = 0; i < p9fdev->nb_rings; i++) {
+               if (!p9fdev->rings[i].initialized)
+                       continue;
+               p9front_free_dev_ring(p9fdev, i);
+       }
+
+       uk_free(a, p9fdev->rings);
+}
+
+static int p9front_allocate_dev_ring(struct p9front_dev *p9fdev, int idx)
+{
+       struct xenbus_device *xendev = p9fdev->xendev;
+       struct p9front_dev_ring *ring;
+       int rc, i;
+       void *data_bytes;
+
+       /* Sanity checks. */
+       UK_ASSERT(idx >= 0 && idx < p9fdev->nb_rings);
+
+       ring = &p9fdev->rings[idx];
+       UK_ASSERT(!ring->initialized);
+
+       ukarch_spin_lock_init(&ring->spinlock);
+       ring->dev = p9fdev;
+
+       /* Allocate ring intf page. */
+       ring->intf = uk_palloc(a, 0);
+       if (!ring->intf) {
+               rc = -ENOMEM;
+               goto out;
+       }
+       memset(ring->intf, 0, PAGE_SIZE);
+
+       /* Grant access to the allocated page to the backend. */
+       ring->ref = gnttab_grant_access(xendev->otherend_id,
+                       virt_to_mfn(ring->intf), 0);
+       UK_ASSERT(ring->ref != GRANT_INVALID_REF);
+
+       /* Allocate memory for the data. */
+       data_bytes = uk_palloc(a,
+                       p9fdev->ring_order + XEN_PAGE_SHIFT - PAGE_SHIFT);
+       if (!data_bytes) {
+               rc = -ENOMEM;
+               goto out_free_intf;
+       }
+       memset(data_bytes, 0, XEN_FLEX_RING_SIZE(p9fdev->ring_order) * 2);
+
+       /* Grant refs to the entire data. */
+       for (i = 0; i < (1 << p9fdev->ring_order); i++) {
+               ring->intf->ref[i] = gnttab_grant_access(xendev->otherend_id,
+                               virt_to_mfn(data_bytes) + i, 0);
+               UK_ASSERT(ring->intf->ref[i] != GRANT_INVALID_REF);
+       }
+
+       ring->intf->ring_order = p9fdev->ring_order;
+       ring->data.in = data_bytes;
+       ring->data.out = data_bytes + XEN_FLEX_RING_SIZE(p9fdev->ring_order);
+
+       /* Allocate event channel. */
+       rc = evtchn_alloc_unbound(xendev->otherend_id, p9front_handler, ring,
+                               &ring->evtchn);
+       if (rc) {
+               uk_pr_err(DRIVER_NAME": Error creating evt channel: %d\n", rc);
+               goto out_free_grants;
+       }
+
+       unmask_evtchn(ring->evtchn);
+
+       /* Mark ring as initialized. */
+       ring->initialized = true;
+
+       return 0;
+
+out_free_grants:
+       for (i = 0; i < (1 << p9fdev->ring_order); i++)
+               gnttab_end_access(ring->intf->ref[i]);
+       uk_pfree(a, data_bytes,
+               p9fdev->ring_order + XEN_PAGE_SHIFT - PAGE_SHIFT);
+out_free_intf:
+       gnttab_end_access(ring->ref);
+       uk_pfree(a, ring->intf, 0);
+out:
+       return rc;
+}
+
+static int p9front_allocate_dev_rings(struct p9front_dev *p9fdev)
+{
+       int rc, i;
+
+       p9fdev->rings = uk_calloc(a, p9fdev->nb_rings, sizeof(*p9fdev->rings));
+       if (!p9fdev->rings) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       for (i = 0; i < p9fdev->nb_rings; i++) {
+               rc = p9front_allocate_dev_ring(p9fdev, i);
+               if (rc)
+                       goto out_free;
+       }
+
+       return 0;
+
+out_free:
+       p9front_free_dev_rings(p9fdev);
+out:
+       return rc;
+}
+
 static int p9front_drv_init(struct uk_alloc *drv_allocator)
 {
        if (!drv_allocator)
@@ -75,11 +214,39 @@ static int p9front_add_dev(struct xenbus_device *xendev)
        if (rc)
                goto out_free;
 
+       uk_pr_info("Initialized 9pfront dev: tag=%s,maxrings=%d,maxorder=%d\n",
+               p9fdev->tag, p9fdev->nb_max_rings, p9fdev->max_ring_page_order);
+
+       p9fdev->nb_rings = MIN(CONFIG_XEN_9PFRONT_NB_RINGS,
+                               p9fdev->nb_max_rings);
+       p9fdev->ring_order = MIN(CONFIG_XEN_9PFRONT_RING_ORDER,
+                               p9fdev->max_ring_page_order);
+
+       rc = p9front_allocate_dev_rings(p9fdev);
+       if (rc) {
+               uk_pr_err(DRIVER_NAME": Could not initialize device rings: 
%d\n",
+                       rc);
+               goto out_free;
+       }
+
+       rc = p9front_xb_connect(p9fdev);
+       if (rc) {
+               uk_pr_err(DRIVER_NAME": Could not connect: %d\n", rc);
+               goto out_free_rings;
+       }
+
        rc = 0;
        ukplat_spin_lock_irqsave(&p9front_device_list_lock, flags);
        uk_list_add(&p9fdev->_list, &p9front_device_list);
        ukplat_spin_unlock_irqrestore(&p9front_device_list_lock, flags);
 
+       uk_pr_info(DRIVER_NAME": Connected 9pfront dev: 
tag=%s,rings=%d,order=%d\n",
+               p9fdev->tag, p9fdev->nb_rings, p9fdev->ring_order);
+
+       goto out;
+
+out_free_rings:
+       p9front_free_dev_rings(p9fdev);
 out_free:
        uk_free(a, p9fdev);
 out:
diff --git a/plat/xen/drivers/9p/9pfront.h b/plat/xen/drivers/9p/9pfront.h
index e77f315a..97c986d8 100644
--- a/plat/xen/drivers/9p/9pfront.h
+++ b/plat/xen/drivers/9p/9pfront.h
@@ -35,9 +35,31 @@
 #ifndef __9PFRONT_H__
 #define __9PFRONT_H__
 
+#include <string.h>
 #include <uk/config.h>
 #include <uk/essentials.h>
 #include <uk/list.h>
+#include <uk/plat/spinlock.h>
+#include <xen/io/9pfs.h>
+#include <common/events.h>
+#include <common/gnttab.h>
+
+struct p9front_dev_ring {
+       /* Backpointer to the p9front device. */
+       struct p9front_dev *dev;
+       /* The 9pfs data interface, as dedfined by the xen headers. */
+       struct xen_9pfs_data_intf *intf;
+       /* The 9pfs data, as defined by the xen headers. */
+       struct xen_9pfs_data data;
+       /* The event channel for this ring. */
+       evtchn_port_t evtchn;
+       /* Grant reference for the interface. */
+       grant_ref_t ref;
+       /* Per-ring spinlock. */
+       spinlock_t spinlock;
+       /* Tracks if this ring was initialized. */
+       bool initialized;
+};
 
 struct p9front_dev {
        /* Xenbus device. */
@@ -50,6 +72,13 @@ struct p9front_dev {
        int max_ring_page_order;
        /* Mount tag for this device, read from xenstore. */
        char *tag;
+
+       /* Number of rings to use. */
+       int nb_rings;
+       /* Ring page order. */
+       int ring_order;
+       /* Device data rings. */
+       struct p9front_dev_ring *rings;
 };
 
 #endif /* __9PFRONT_H__ */
diff --git a/plat/xen/drivers/9p/9pfront_xb.h b/plat/xen/drivers/9p/9pfront_xb.h
index 224df7af..6e2697f9 100644
--- a/plat/xen/drivers/9p/9pfront_xb.h
+++ b/plat/xen/drivers/9p/9pfront_xb.h
@@ -50,4 +50,16 @@
  */
 int p9front_xb_init(struct p9front_dev *p9fdev);
 
+/**
+ * Connects to the backend by setting up the communication between
+ * frontend and backend.
+ *
+ * @param p9fdev
+ *   9P frontend device
+ * @return
+ *   - (0): Successful.
+ *   - (< 0): Error while committing XenStore transaction.
+ */
+int p9front_xb_connect(struct p9front_dev *p9fdev);
+
 #endif /* __9PFRONT_XB_H__ */
diff --git a/plat/xen/drivers/9p/9pfront_xs.c b/plat/xen/drivers/9p/9pfront_xs.c
index 5b5dc2e4..7185061c 100644
--- a/plat/xen/drivers/9p/9pfront_xs.c
+++ b/plat/xen/drivers/9p/9pfront_xs.c
@@ -154,3 +154,207 @@ int p9front_xb_init(struct p9front_dev *p9fdev)
 out:
        return rc;
 }
+
+static int xs_write_ring(struct p9front_dev *p9fdev,
+                        int i,
+                        xenbus_transaction_t xbt)
+{
+       struct xenbus_device *xendev = p9fdev->xendev;
+       struct p9front_dev_ring *ring = &p9fdev->rings[i];
+       char *path;
+       int rc;
+
+       rc = asprintf(&path, "ring-ref%u", i);
+       if (rc < 0)
+               goto out;
+
+       rc = xs_printf(xbt, xendev->nodename, path, "%u", ring->ref);
+       if (rc < 0)
+               goto out_path;
+
+       free(path);
+       rc = asprintf(&path, "event-channel-%u", i);
+       if (rc < 0)
+               goto out;
+
+       rc = xs_printf(xbt, xendev->nodename, path, "%u", ring->evtchn);
+       if (rc < 0)
+               goto out_path;
+
+       rc = 0;
+
+out_path:
+       free(path);
+out:
+       return rc;
+}
+
+static void xs_delete_ring(struct p9front_dev *p9fdev,
+                          int i,
+                          xenbus_transaction_t xbt)
+{
+       struct xenbus_device *xendev = p9fdev->xendev;
+       int rc;
+       char *path;
+
+       rc = asprintf(&path, "%s/ring-ref%u", xendev->nodename, i);
+       if (rc < 0)
+               return;
+       xs_rm(xbt, path);
+       free(path);
+
+       rc = asprintf(&path, "%s/event-channel-%u", xendev->nodename, i);
+       if (rc < 0)
+               return;
+       xs_rm(xbt, path);
+       free(path);
+}
+
+static int p9front_xb_front_init(struct p9front_dev *p9fdev,
+                                xenbus_transaction_t xbt)
+{
+       int i, rc;
+       struct xenbus_device *xendev = p9fdev->xendev;
+
+       /*
+        * Assert that the p9fdev ring information has been properly
+        * configured before attempting to connect.
+        */
+       UK_ASSERT(p9fdev->nb_rings != 0 && p9fdev->nb_rings <= 9);
+       UK_ASSERT(p9fdev->ring_order != 0);
+
+       /*
+        * Assert that the p9fdev rings have been initialized.
+        */
+       UK_ASSERT(p9fdev->rings != NULL);
+
+       /* Write version... */
+       rc = xs_printf(xbt, xendev->nodename, "version", "%u", 1);
+       if (rc < 0)
+               goto out;
+
+       /* ... and num-rings... */
+       rc = xs_printf(xbt, xendev->nodename, "num-rings", "%u",
+                       p9fdev->nb_rings);
+       if (rc < 0)
+               goto out;
+
+       /* ... and each ring. */
+       for (i = 0; i < p9fdev->nb_rings; i++) {
+               rc = xs_write_ring(p9fdev, i, xbt);
+               if (rc)
+                       goto out;
+       }
+
+out:
+       return rc;
+}
+
+static void p9front_xb_front_fini(struct p9front_dev *p9fdev,
+                                 xenbus_transaction_t xbt)
+{
+       int i;
+
+       for (i = 0; i < p9fdev->nb_rings; i++)
+               xs_delete_ring(p9fdev, i, xbt);
+}
+
+static int be_watch_start(struct xenbus_device *xendev, const char *path)
+{
+       struct xenbus_watch *watch;
+
+       watch = xs_watch_path(XBT_NIL, path);
+       if (PTRISERR(watch))
+               return PTR2ERR(watch);
+
+       xendev->otherend_watch = watch;
+
+       return 0;
+}
+
+static int be_watch_stop(struct xenbus_device *xendev)
+{
+       return xs_unwatch(XBT_NIL, xendev->otherend_watch);
+}
+
+#define WAIT_BE_STATE_CHANGE_WHILE_COND(state_cond) \
+       do { \
+               rc = xs_read_integer(XBT_NIL, be_state_path, \
+                       (int *) &be_state); \
+               if (rc) \
+                       goto out; \
+               while (!rc && (state_cond)) \
+                       rc = xenbus_wait_for_state_change(be_state_path, \
+                               &be_state, xendev->otherend_watch); \
+               if (rc) \
+                       goto out; \
+       } while (0)
+
+static int p9front_xb_wait_be_connect(struct p9front_dev *p9fdev)
+{
+       struct xenbus_device *xendev = p9fdev->xendev;
+       char be_state_path[strlen(xendev->otherend) + sizeof("/state")];
+       XenbusState be_state;
+       int rc;
+
+       sprintf(be_state_path, "%s/state", xendev->otherend);
+
+       rc = be_watch_start(xendev, be_state_path);
+       if (rc)
+               goto out;
+
+       WAIT_BE_STATE_CHANGE_WHILE_COND(be_state < XenbusStateConnected);
+
+       if (be_state != XenbusStateConnected) {
+               uk_pr_err("Backend not available, state=%s\n",
+                               xenbus_state_to_str(be_state));
+               be_watch_stop(xendev);
+               goto out;
+       }
+
+       rc = xenbus_switch_state(XBT_NIL, xendev, XenbusStateConnected);
+       if (rc)
+               goto out;
+
+out:
+       return rc;
+}
+
+int p9front_xb_connect(struct p9front_dev *p9fdev)
+{
+       struct xenbus_device *xendev;
+       xenbus_transaction_t xbt;
+       int rc;
+
+       UK_ASSERT(p9fdev != NULL);
+
+       xendev = p9fdev->xendev;
+       UK_ASSERT(xendev != NULL);
+
+again:
+       rc = xs_transaction_start(&xbt);
+       if (rc)
+               goto abort_transaction;
+
+       rc = p9front_xb_front_init(p9fdev, xbt);
+       if (rc)
+               goto abort_transaction;
+
+       rc = xenbus_switch_state(xbt, xendev, XenbusStateInitialised);
+       if (rc)
+               goto abort_transaction;
+
+       rc = xs_transaction_end(xbt, 0);
+       if (rc == -EAGAIN)
+               goto again;
+
+       rc = p9front_xb_wait_be_connect(p9fdev);
+       if (rc)
+               p9front_xb_front_fini(p9fdev, XBT_NIL);
+
+       return rc;
+
+abort_transaction:
+       xs_transaction_end(xbt, 1);
+       return rc;
+}
-- 
2.20.1


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

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