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

[Minios-devel] [UNIKRAFT PATCH v4 6/7] plat/xen: Add Xenbus device probing


  • To: minios-devel@xxxxxxxxxxxxx
  • From: Costin Lupu <costin.lupu@xxxxxxxxx>
  • Date: Mon, 17 Sep 2018 13:32:30 +0300
  • Cc: yuri.volchkov@xxxxxxxxx
  • Delivery-date: Mon, 17 Sep 2018 10:32:46 +0000
  • Ironport-phdr: 9a23:iZ2AfxDiIbwcNXl4w/RCUyQJP3N1i/DPJgcQr6AfoPdwSPT7ocbcNUDSrc9gkEXOFd2Cra4c1KyO6+jJYi8p2d65qncMcZhBBVcuqP49uEgeOvODElDxN/XwbiY3T4xoXV5h+GynYwAOQJ6tL1LdrWev4jEMBx7xKRR6JvjvGo7Vks+7y/2+94fcbglUhjexe69+IAmrpgjNq8cahpdvJLwswRXTuHtIfOpWxWJsJV2Nmhv3+9m98p1+/SlOovwt78FPX7n0cKQ+VrxYES8pM3sp683xtBnMVhWA630BWWgLiBVIAgzF7BbnXpfttybxq+Rw1DWGMcDwULs5Xymp4aV2Rx/ykCoJNyA3/nzZhMJzi6xUohyhqgdjz4LIeoyZKOBzcr/Bcd4cWGFPXtxRVytEAo6kcYYPCPEBPfpZr4n7ulAAqwa+BRGxBOjyzTJHmnj23bYm0+QgFwHKxgggH88WsHTJt9j6KLwSXfqtzKnV1jrPdelW2TDk5YXObxsvoumMUKptfcfe1EUjDQDIg1WKpYD7IT+Y1P4BvmaD4+Z9Wu+jlnQrpgJxrzS12MshhIfEipgIxl3L6yl0xps+K8eiR05he9GkFYNdtySdN4RrXMwvW3pouCMmyr0evp67YTQKxIwnxxHBb/yHdJCF4gzmVOmLIDd4gGhpd66khxqo6Uig1/bzWtOu0FZNtiZFk9/MuW4R1xHL98SKReZx8l2i1DuPzQzf9P9ILEIumafVM5Ihx6Q/lpsXsUTNBC/2n0D2gbeKeUUj4eio9+XnYrP8qp+YKo90khz+P78ylcykG+g4KhUOUHOB9eSm073v5Vf5T6lSjv0qjqnZt4jXJcEapq6/Ag9V1Z0j5w+iADi4ztQXg30HIUlBeBKGlIjpJ0rOLOr3DPihhVSgijBrx+rJPrf5GJXCMmDDkKv9fbZ680NdyBczzcpe555OFLEBJ/bzVVPxtNzbCR85LRe5w+D5B9ph0oMRQ3mADrWHP6PP4he04bcqIu+NY5RQtDvjJvwN4//1kWR/iVIbO66z0sg5cne9S99hOFmYZzLIn88cWTMBuREiTeqsjECaTBZYfDCqQqh6/DZtW9HuNpvKWo342O/J5yy8BJADPm0=
  • List-id: Mini-os development list <minios-devel.lists.xenproject.org>

Extend the Xenbus bus driver with support for probing Xenbus
devices.

Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx>
---
 plat/xen/include/xenbus/client.h |  12 ++++
 plat/xen/include/xenbus/xenbus.h |  17 ++++-
 plat/xen/xenbus/client.c         |  12 ++++
 plat/xen/xenbus/exportsyms.uk    |   1 +
 plat/xen/xenbus/xenbus.c         | 131 ++++++++++++++++++++++++++++++++++++++-
 5 files changed, 171 insertions(+), 2 deletions(-)

diff --git a/plat/xen/include/xenbus/client.h b/plat/xen/include/xenbus/client.h
index f3540b7..8b7e8c1 100644
--- a/plat/xen/include/xenbus/client.h
+++ b/plat/xen/include/xenbus/client.h
@@ -86,4 +86,16 @@ int xenbus_watch_wait_event(struct xenbus_watch *watch);
  */
 int xenbus_watch_notify_event(struct xenbus_watch *watch);
 
+/*
+ * Driver states
+ */
+
+/*
+ * Returns the driver state found at the given Xenstore path.
+ *
+ * @param path Xenstore path
+ * @return The Xenbus driver state
+ */
+XenbusState xenbus_read_driver_state(const char *path);
+
 #endif /* __XENBUS_CLIENT_H__ */
diff --git a/plat/xen/include/xenbus/xenbus.h b/plat/xen/include/xenbus/xenbus.h
index 230dcd4..3d3b540 100644
--- a/plat/xen/include/xenbus/xenbus.h
+++ b/plat/xen/include/xenbus/xenbus.h
@@ -110,7 +110,22 @@ UK_TAILQ_HEAD(xenbus_watch_list, struct xenbus_watch);
  */
 
 struct xenbus_device {
-
+       /**< in use by Xenbus handler */
+       UK_TAILQ_ENTRY(struct xenbus_device) next;
+       /**< Device state */
+       XenbusState state;
+       /**< Device type */
+       enum xenbus_dev_type devtype;
+       /**< Xenstore path of the device */
+       char *nodename;
+       /**< Xenstore path of the device peer (e.g. backend for frontend) */
+       char *otherend;
+       /**< Domain id of the other end */
+       domid_t otherend_id;
+       /**< Watch for monitoring changes on other end */
+       struct xenbus_watch *otherend_watch;
+       /**< Xenbus driver */
+       struct xenbus_driver *drv;
 };
 UK_TAILQ_HEAD(xenbus_device_list, struct xenbus_device);
 
diff --git a/plat/xen/xenbus/client.c b/plat/xen/xenbus/client.c
index 3dbca0f..274e6e7 100644
--- a/plat/xen/xenbus/client.c
+++ b/plat/xen/xenbus/client.c
@@ -44,6 +44,7 @@
 #include <string.h>
 #include <uk/errptr.h>
 #include <uk/wait.h>
+#include <xenbus/xs.h>
 #include <xenbus/client.h>
 
 
@@ -130,3 +131,14 @@ int xenbus_watch_notify_event(struct xenbus_watch *watch)
 
        return 0;
 }
+
+XenbusState xenbus_read_driver_state(const char *path)
+{
+       char state_path[strlen(path) + sizeof("/state")];
+       XenbusState state = XenbusStateUnknown;
+
+       sprintf(state_path, "%s/state", path);
+       xs_read_integer(XBT_NIL, state_path, (int *) &state);
+
+       return state;
+}
diff --git a/plat/xen/xenbus/exportsyms.uk b/plat/xen/xenbus/exportsyms.uk
index a424fd9..d57a2a5 100644
--- a/plat/xen/xenbus/exportsyms.uk
+++ b/plat/xen/xenbus/exportsyms.uk
@@ -27,3 +27,4 @@ xenbus_state_to_str
 xenbus_devtype_to_str
 xenbus_str_to_devtype
 xenbus_watch_wait_event
+xenbus_read_driver_state
diff --git a/plat/xen/xenbus/xenbus.c b/plat/xen/xenbus/xenbus.c
index a20546b..28f0cfd 100644
--- a/plat/xen/xenbus/xenbus.c
+++ b/plat/xen/xenbus/xenbus.c
@@ -43,8 +43,12 @@
 #include <uk/errptr.h>
 #include <uk/assert.h>
 #include <xenbus/xenbus.h>
+#include <xenbus/xs.h>
+#include <xenbus/client.h>
 #include "xs_comms.h"
 
+#define XS_DEV_PATH "device"
+
 static struct xenbus_handler xbh;
 
 
@@ -67,13 +71,138 @@ void uk_xb_free(void *ptr)
        uk_free(xbh.a, ptr);
 }
 
+
+static struct xenbus_driver *xenbus_find_driver(xenbus_dev_type_t devtype)
+{
+       struct xenbus_driver *drv;
+       const xenbus_dev_type_t *pdevtype;
+
+       UK_TAILQ_FOREACH(drv, &xbh.drv_list, next) {
+               for (pdevtype = drv->device_types;
+                               *pdevtype != xenbus_dev_none; pdevtype++) {
+                       if (*pdevtype == devtype)
+                               return drv;
+               }
+       }
+
+       return NULL; /* no driver found */
+}
+
+static int xenbus_probe_device(struct xenbus_driver *drv,
+               xenbus_dev_type_t type, const char *name)
+{
+       int err;
+       struct xenbus_device *dev;
+       char *nodename = NULL;
+       XenbusState state;
+
+       /* device/type/name */
+       err = asprintf(&nodename, "%s/%s/%s",
+               XS_DEV_PATH, xenbus_devtype_to_str(type), name);
+       if (err < 0)
+               goto out;
+
+       state = xenbus_read_driver_state(nodename);
+       if (state != XenbusStateInitialising)
+               return 0;
+
+       uk_printd(DLVL_INFO, "Xenbus device: %s\n", nodename);
+
+       dev = uk_xb_calloc(1, sizeof(*dev) + strlen(nodename) + 1);
+       if (!dev) {
+               uk_printd(DLVL_ERR, "Failed to initialize: Out of memory!\n");
+               err = -ENOMEM;
+               goto out;
+       }
+
+       dev->state = XenbusStateInitialising;
+       dev->devtype = type;
+       dev->nodename = (char *) (dev + 1);
+       strcpy(dev->nodename, nodename);
+
+       err = drv->add_dev(dev);
+       if (err) {
+               uk_printd(DLVL_ERR, "Failed to add device.\n");
+               uk_xb_free(dev);
+       }
+
+out:
+       if (nodename)
+               free(nodename);
+
+       return err;
+}
+
+static int xenbus_probe_device_type(const char *devtype_str)
+{
+       struct xenbus_driver *drv;
+       xenbus_dev_type_t devtype;
+       char dirname[sizeof(XS_DEV_PATH) + strlen(devtype_str)];
+       char **devices = NULL;
+       int err = 0;
+
+       devtype = xenbus_str_to_devtype(devtype_str);
+       if (!devtype) {
+               uk_printd(DLVL_WARN,
+                       "Unsupported device type: %s\n", devtype_str);
+               goto out;
+       }
+
+       drv = xenbus_find_driver(devtype);
+       if (!drv) {
+               uk_printd(DLVL_WARN,
+                       "No driver for device type: %s\n", devtype_str);
+               goto out;
+       }
+
+       sprintf(dirname, "%s/%s", XS_DEV_PATH, devtype_str);
+
+       /* Get device list */
+       devices = xs_ls(XBT_NIL, dirname);
+       if (PTRISERR(devices)) {
+               err = PTR2ERR(devices);
+               uk_printd(DLVL_ERR,
+                       "Error reading %s devices: %d\n", devtype_str, err);
+               goto out;
+       }
+
+       for (int i = 0; devices[i] != NULL; i++) {
+               /* Probe only if no prior error */
+               if (err == 0)
+                       err = xenbus_probe_device(drv, devtype, devices[i]);
+       }
+
+out:
+       if (!PTRISERR(devices))
+               free(devices);
+
+       return err;
+}
+
 static int xenbus_probe(void)
 {
+       char **devtypes;
        int err = 0;
 
        uk_printd(DLVL_INFO, "Probe Xenbus\n");
 
-       /* TODO */
+       /* Get device types list */
+       devtypes = xs_ls(XBT_NIL, XS_DEV_PATH);
+       if (PTRISERR(devtypes)) {
+               err = PTR2ERR(devtypes);
+               uk_printd(DLVL_ERR, "Error reading device types: %d\n", err);
+               goto out;
+       }
+
+       for (int i = 0; devtypes[i] != NULL; i++) {
+               /* Probe only if no previous error */
+               if (err == 0)
+                       err = xenbus_probe_device_type(devtypes[i]);
+       }
+
+out:
+       if (!PTRISERR(devtypes))
+               free(devtypes);
 
        return err;
 }
-- 
2.11.0


_______________________________________________
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®.