]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
drivers/9pfront: Rename `libxen9pfront` to `lib9pfront`
authorSimon Kuenzer <simon@unikraft.io>
Tue, 17 Sep 2024 09:31:22 +0000 (11:31 +0200)
committerUnikraft Bot <monkey@unikraft.io>
Sat, 14 Dec 2024 10:47:46 +0000 (10:47 +0000)
Rename the driver library and driver directory to better match
the naming of Xen. Configuration options are adopted accordingly.
Additionally, this commit improves the titles of the ring
configuration options in the menu.

Signed-off-by: Simon Kuenzer <simon@unikraft.io>
Reviewed-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
Reviewed-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
Reviewed-by: Michalis Pappas <michalis@unikraft.io>
Approved-by: Michalis Pappas <michalis@unikraft.io>
GitHub-Closes: #1501

15 files changed:
drivers/xen/9p/9pfront.c [deleted file]
drivers/xen/9p/9pfront.h [deleted file]
drivers/xen/9p/9pfront_xb.h [deleted file]
drivers/xen/9p/9pfront_xs.c [deleted file]
drivers/xen/9p/Config.uk [deleted file]
drivers/xen/9p/Makefile.uk [deleted file]
drivers/xen/9pfront/9pfront.c [new file with mode: 0644]
drivers/xen/9pfront/9pfront.h [new file with mode: 0644]
drivers/xen/9pfront/9pfront_xb.h [new file with mode: 0644]
drivers/xen/9pfront/9pfront_xs.c [new file with mode: 0644]
drivers/xen/9pfront/Config.uk [new file with mode: 0644]
drivers/xen/9pfront/Makefile.uk [new file with mode: 0644]
drivers/xen/9pfront/exportsyms.uk [new file with mode: 0644]
drivers/xen/Makefile.uk
plat/xen/Config.uk

diff --git a/drivers/xen/9p/9pfront.c b/drivers/xen/9p/9pfront.c
deleted file mode 100644 (file)
index bf1139f..0000000
+++ /dev/null
@@ -1,528 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/*
- * Authors: Cristian Banu <cristb@gmail.com>
- *
- * Copyright (c) 2019, University Politehnica of Bucharest. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <uk/config.h>
-#include <uk/alloc.h>
-#include <uk/assert.h>
-#include <uk/essentials.h>
-#include <uk/errptr.h>
-#include <uk/list.h>
-#if CONFIG_LIBUKSCHED
-#include <uk/thread.h>
-#endif
-#include <uk/9pdev.h>
-#include <uk/9preq.h>
-#include <uk/9pdev_trans.h>
-#include <uk/plat/spinlock.h>
-#if defined(__i386__) || defined(__x86_64__)
-#include <xen-x86/mm.h>
-#include <xen-x86/irq.h>
-#elif defined(__aarch64__)
-#include <xen-arm/mm.h>
-#else
-#error "Unsupported architecture"
-#endif
-#include <uk/xenbus/xenbus.h>
-
-#include "9pfront_xb.h"
-
-#define DRIVER_NAME    "xen-9pfront"
-
-static struct uk_alloc *a;
-static UK_LIST_HEAD(p9front_device_list);
-static __spinlock p9front_device_list_lock;
-
-struct p9front_header {
-       uint32_t size;
-       uint8_t type;
-       uint16_t tag;
-} __packed;
-
-static void p9front_recv(struct p9front_dev_ring *ring);
-
-#if CONFIG_LIBUKSCHED
-
-static __noreturn void p9front_bh_handler(void *arg)
-{
-       struct p9front_dev_ring *ring = arg;
-
-       while (1) {
-               uk_waitq_wait_event(&ring->bh_wq,
-                               UK_READ_ONCE(ring->data_avail));
-               p9front_recv(ring);
-       }
-}
-
-#endif
-
-static void p9front_recv(struct p9front_dev_ring *ring)
-{
-       struct p9front_dev *p9fdev = ring->dev;
-       evtchn_port_t evtchn = ring->evtchn;
-       RING_IDX cons, prod, masked_cons, masked_prod;
-       int ring_size, rc;
-       struct p9front_header hdr;
-       struct uk_9preq *req;
-       uint32_t buf_cnt, zc_buf_cnt;
-
-       ring_size = XEN_FLEX_RING_SIZE(p9fdev->ring_order);
-
-       while (1) {
-               cons = ring->intf->in_cons;
-               prod = ring->intf->in_prod;
-               xen_rmb();
-
-               if (xen_9pfs_queued(prod, cons, ring_size) < sizeof(hdr)) {
-#if CONFIG_LIBUKSCHED
-                       UK_WRITE_ONCE(ring->data_avail, false);
-#endif
-                       notify_remote_via_evtchn(evtchn);
-                       return;
-               }
-
-               masked_prod = xen_9pfs_mask(prod, ring_size);
-               masked_cons = xen_9pfs_mask(cons, ring_size);
-
-               xen_9pfs_read_packet(&hdr, ring->data.in, sizeof(hdr),
-                               masked_prod, &masked_cons, ring_size);
-
-               req = uk_9pdev_req_lookup(p9fdev->p9dev, hdr.tag);
-               if (PTRISERR(req)) {
-                       uk_pr_warn("Found invalid tag=%u\n", hdr.tag);
-                       cons += hdr.size;
-                       xen_mb();
-                       ring->intf->in_cons = cons;
-                       continue;
-               }
-
-               masked_cons = xen_9pfs_mask(cons, ring_size);
-
-               /*
-                * Compute amount of data to read into request buffer and into
-                * zero-copy buffer.
-                */
-               buf_cnt = hdr.size;
-               if (hdr.type != UK_9P_RERROR && req->recv.zc_buf)
-                       buf_cnt = MIN(buf_cnt, req->recv.zc_offset);
-               zc_buf_cnt = hdr.size - buf_cnt;
-
-               xen_9pfs_read_packet(req->recv.buf, ring->data.in, buf_cnt,
-                               masked_prod, &masked_cons, ring_size);
-               xen_9pfs_read_packet(req->recv.zc_buf, ring->data.in,
-                               zc_buf_cnt, masked_prod, &masked_cons,
-                               ring_size);
-               cons += hdr.size;
-               xen_mb();
-               ring->intf->in_cons = cons;
-
-               rc = uk_9preq_receive_cb(req, hdr.size);
-               if (rc)
-                       uk_pr_warn("Could not receive reply: %d\n", rc);
-
-               /* Release reference held by uk_9pdev_req_lookup(). */
-               uk_9preq_put(req);
-       }
-}
-
-static void p9front_handler(evtchn_port_t evtchn,
-                           struct __regs *regs __unused,
-                           void *arg)
-{
-       struct p9front_dev_ring *ring = arg;
-
-       UK_ASSERT(ring);
-       UK_ASSERT(ring->evtchn == evtchn);
-
-       /*
-        * A new interrupt means that there is a response to be received, which
-        * means that a previously sent request has been removed from the out
-        * ring. Thus, the API can be notified of the possibility of retrying to
-        * send requests blocked on ENOSPC errors.
-        */
-       if (ring->dev->p9dev)
-               uk_9pdev_xmit_notify(ring->dev->p9dev);
-#if CONFIG_LIBUKSCHED
-       UK_WRITE_ONCE(ring->data_avail, true);
-       uk_waitq_wake_up(&ring->bh_wq);
-#else
-       p9front_recv(ring);
-#endif
-}
-
-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);
-
-       if (ring->bh_thread_name)
-               free(ring->bh_thread_name);
-       uk_sched_thread_terminate(ring->bh_thread);
-       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,
-                1ul << (p9fdev->ring_order + XEN_PAGE_SHIFT - PAGE_SHIFT));
-       gnttab_end_access(ring->ref);
-       uk_pfree(a, ring->intf, 1);
-       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_init(&ring->spinlock);
-       ring->dev = p9fdev;
-
-       /* Allocate ring intf page. */
-       ring->intf = uk_palloc(a, 1);
-       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, 1ul << (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);
-
-#if CONFIG_LIBUKSCHED
-       /* Allocate bottom-half thread. */
-       ring->data_avail = false;
-       uk_waitq_init(&ring->bh_wq);
-
-       rc = asprintf(&ring->bh_thread_name, DRIVER_NAME"-recv-%s-%u",
-                       p9fdev->tag, idx);
-       ring->bh_thread = uk_sched_thread_create(uk_sched_current(),
-                                                p9front_bh_handler, ring,
-                                                ring->bh_thread_name);
-       if (PTRISERR(ring->bh_thread)) {
-               rc = PTR2ERR(ring->bh_thread);
-               ring->bh_thread = NULL;
-               goto out_free_grants;
-       }
-#endif
-
-       /* 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_thread;
-       }
-
-       unmask_evtchn(ring->evtchn);
-
-       /* Mark ring as initialized. */
-       ring->initialized = true;
-
-       return 0;
-
-out_free_thread:
-       if (ring->bh_thread_name)
-               free(ring->bh_thread_name);
-       uk_sched_thread_terminate(ring->bh_thread);
-out_free_grants:
-       for (i = 0; i < (1 << p9fdev->ring_order); i++)
-               gnttab_end_access(ring->intf->ref[i]);
-       uk_pfree(a, data_bytes,
-                1ul << (p9fdev->ring_order + XEN_PAGE_SHIFT - PAGE_SHIFT));
-out_free_intf:
-       gnttab_end_access(ring->ref);
-       uk_pfree(a, ring->intf, 1);
-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_connect(struct uk_9pdev *p9dev,
-                          const char *device_identifier,
-                          const char *mount_args __unused)
-{
-       struct p9front_dev *p9fdev = NULL;
-       int rc = 0;
-       int found = 0;
-
-       ukarch_spin_lock(&p9front_device_list_lock);
-       uk_list_for_each_entry(p9fdev, &p9front_device_list, _list) {
-               if (!strcmp(p9fdev->tag, device_identifier)) {
-                       if (p9fdev->p9dev != NULL) {
-                               rc = -EBUSY;
-                               goto out;
-                       }
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (!found) {
-               rc = -ENODEV;
-               goto out;
-       }
-
-       /* The msize is given by the size of the flex ring. */
-       p9dev->max_msize = XEN_FLEX_RING_SIZE(p9fdev->ring_order);
-
-       p9fdev->p9dev = p9dev;
-       p9dev->priv = p9fdev;
-       rc = 0;
-       found = 1;
-
-out:
-       ukarch_spin_unlock(&p9front_device_list_lock);
-       return rc;
-}
-
-static int p9front_disconnect(struct uk_9pdev *p9dev __unused)
-{
-       struct p9front_dev *p9fdev;
-
-       UK_ASSERT(p9dev);
-       p9fdev = p9dev->priv;
-
-       ukarch_spin_lock(&p9front_device_list_lock);
-       p9fdev->p9dev = NULL;
-       ukarch_spin_unlock(&p9front_device_list_lock);
-
-       return 0;
-}
-
-static int p9front_request(struct uk_9pdev *p9dev,
-                          struct uk_9preq *req)
-{
-       struct p9front_dev *p9fdev;
-       struct p9front_dev_ring *ring;
-       int ring_idx, ring_size;
-       RING_IDX masked_prod, masked_cons, prod, cons;
-
-       UK_ASSERT(p9dev);
-       UK_ASSERT(req);
-       UK_ASSERT(req->state == UK_9PREQ_READY);
-
-       p9fdev = p9dev->priv;
-
-       ring_size = XEN_FLEX_RING_SIZE(p9fdev->ring_order);
-
-       ring_idx = req->tag % p9fdev->nb_rings;
-       ring = &p9fdev->rings[ring_idx];
-
-       /* Protect against concurrent writes to the out ring. */
-       ukarch_spin_lock(&ring->spinlock);
-       cons = ring->intf->out_cons;
-       prod = ring->intf->out_prod;
-       xen_mb();
-
-       masked_prod = xen_9pfs_mask(prod, ring_size);
-       masked_cons = xen_9pfs_mask(cons, ring_size);
-
-       if (ring_size - xen_9pfs_queued(prod, cons, ring_size) <
-                       req->xmit.size + req->xmit.zc_size) {
-               ukarch_spin_unlock(&ring->spinlock);
-               return -ENOSPC;
-       }
-
-       xen_9pfs_write_packet(ring->data.out, req->xmit.buf, req->xmit.size,
-                             &masked_prod, masked_cons, ring_size);
-       xen_9pfs_write_packet(ring->data.out, req->xmit.zc_buf, req->xmit.zc_size,
-                             &masked_prod, masked_cons, ring_size);
-       req->state = UK_9PREQ_SENT;
-       xen_wmb();
-       prod += req->xmit.size + req->xmit.zc_size;
-       ring->intf->out_prod = prod;
-
-       ukarch_spin_unlock(&ring->spinlock);
-       notify_remote_via_evtchn(ring->evtchn);
-
-       return 0;
-}
-
-static const struct uk_9pdev_trans_ops p9front_trans_ops = {
-       .connect        = p9front_connect,
-       .disconnect     = p9front_disconnect,
-       .request        = p9front_request
-};
-
-static struct uk_9pdev_trans p9front_trans = {
-       .name           = "xen",
-       .ops            = &p9front_trans_ops,
-       .a              = NULL /* Set below. */
-};
-
-
-static int p9front_drv_init(struct uk_alloc *drv_allocator)
-{
-       if (!drv_allocator)
-               return -EINVAL;
-
-       a = drv_allocator;
-       p9front_trans.a = a;
-
-       return uk_9pdev_trans_register(&p9front_trans);
-}
-
-static int p9front_add_dev(struct xenbus_device *xendev)
-{
-       struct p9front_dev *p9fdev;
-       int rc;
-
-       p9fdev = uk_calloc(a, 1, sizeof(*p9fdev));
-       if (!p9fdev) {
-               rc = -ENOMEM;
-               goto out;
-       }
-
-       p9fdev->xendev = xendev;
-       rc = p9front_xb_init(p9fdev);
-       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_LIBXEN_9PFRONT_NB_RINGS,
-                               p9fdev->nb_max_rings);
-       p9fdev->ring_order = MIN(CONFIG_LIBXEN_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;
-       ukarch_spin_lock(&p9front_device_list_lock);
-       uk_list_add(&p9fdev->_list, &p9front_device_list);
-       ukarch_spin_unlock(&p9front_device_list_lock);
-
-       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:
-       return rc;
-}
-
-static const xenbus_dev_type_t p9front_devtypes[] = {
-       xenbus_dev_9pfs,
-};
-
-static struct xenbus_driver p9front_driver = {
-       .device_types   = p9front_devtypes,
-       .init           = p9front_drv_init,
-       .add_dev        = p9front_add_dev
-};
-
-XENBUS_REGISTER_DRIVER(&p9front_driver);
diff --git a/drivers/xen/9p/9pfront.h b/drivers/xen/9p/9pfront.h
deleted file mode 100644 (file)
index 77be134..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/*
- * Authors: Cristian Banu <cristb@gmail.com>
- *
- * Copyright (c) 2019, University Politehnica of Bucharest. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#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>
-#if CONFIG_LIBUKSCHED
-#include <uk/sched.h>
-#endif
-#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 spinlock;
-       /* Tracks if this ring was initialized. */
-       bool initialized;
-#if CONFIG_LIBUKSCHED
-       /* Tracks if there is any data available on this ring. */
-       bool data_avail;
-       /* Bottom-half thread. */
-       struct uk_thread *bh_thread;
-       /* Bottom-half thread name. */
-       char *bh_thread_name;
-       /* Wait-queue on which the thread waits for available data. */
-       struct uk_waitq bh_wq;
-#endif
-};
-
-struct p9front_dev {
-       /* Xenbus device. */
-       struct xenbus_device *xendev;
-       /* 9P API device. */
-       struct uk_9pdev *p9dev;
-       /* Entry within the 9pfront device list. */
-       struct uk_list_head _list;
-       /* Number of maximum rings, read from xenstore. */
-       int nb_max_rings;
-       /* Maximum ring page order, read from xenstore. */
-       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/drivers/xen/9p/9pfront_xb.h b/drivers/xen/9p/9pfront_xb.h
deleted file mode 100644 (file)
index bfa094f..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/*
- * Authors: Cristian Banu <cristb@gmail.com>
- *
- * Copyright (c) 2019, University Politehnica of Bucharest. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __9PFRONT_XB_H__
-#define __9PFRONT_XB_H__
-
-#include "9pfront.h"
-
-/**
- * Reads device information from the xenstore, such as the mount tag
- * and details about the device rings.
- *
- * @param p9fdev
- *   9P frontend device
- * @return
- *   - (0): Successful.
- *   - (-EINVAL): Invalid data.
- *   - (< 0): Error while reading.
- */
-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/drivers/xen/9p/9pfront_xs.c b/drivers/xen/9p/9pfront_xs.c
deleted file mode 100644 (file)
index 8aa8914..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/*
- * Authors: Cristian Banu <cristb@gmail.com>
- *
- * Copyright (c) 2019, University Politehnica of Bucharest. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <uk/config.h>
-#include <uk/assert.h>
-#include <uk/essentials.h>
-#include <uk/errptr.h>
-#include <uk/xenbus/xs.h>
-#include <uk/xenbus/client.h>
-
-#include "9pfront_xb.h"
-
-static int xs_read_backend_info(struct xenbus_device *xendev)
-{
-       int rc, val;
-       char *path = NULL;
-
-       /* Read backend id. */
-       rc = asprintf(&path, "%s/backend-id", xendev->nodename);
-       if (rc <= 0) {
-               uk_pr_err("Failed to allocate format path: %d\n", rc);
-               goto out;
-       }
-
-       rc = xs_read_integer(XBT_NIL, path, &val);
-       if (rc)
-               goto out;
-       xendev->otherend_id = (domid_t)val;
-
-       /* Read backend path. */
-       xendev->otherend = xs_read(XBT_NIL, xendev->nodename, "backend");
-       if (PTRISERR(xendev->otherend)) {
-               rc = PTR2ERR(xendev->otherend);
-               xendev->otherend = NULL;
-       }
-
-out:
-       free(path);
-       return rc;
-}
-
-static int xs_read_backend_ring_info(struct xenbus_device *xendev,
-                                    int *nb_max_rings,
-                                    int *max_ring_page_order)
-{
-       int rc;
-       char *int_str;
-
-       /* Read max-rings. */
-       int_str = xs_read(XBT_NIL, xendev->otherend, "max-rings");
-       if (PTRISERR(int_str)) {
-               rc = PTR2ERR(int_str);
-               uk_pr_err("Error: %d\n", rc);
-               goto out;
-       }
-
-       *nb_max_rings = strtol(int_str, NULL, 10);
-       free(int_str);
-
-       /* Read max-ring-page-order. */
-       int_str = xs_read(XBT_NIL, xendev->otherend, "max-ring-page-order");
-       if (PTRISERR(int_str)) {
-               rc = PTR2ERR(int_str);
-               uk_pr_err("Error: %d\n", rc);
-               goto out;
-       }
-
-       *max_ring_page_order = strtol(int_str, NULL, 10);
-       free(int_str);
-       rc = 0;
-
-out:
-       return rc;
-}
-
-int p9front_xb_init(struct p9front_dev *p9fdev)
-{
-       struct xenbus_device *xendev;
-       char *versions;
-       int rc;
-
-       UK_ASSERT(p9fdev != NULL);
-
-       xendev = p9fdev->xendev;
-       UK_ASSERT(xendev != NULL);
-
-       /* Read backend node and backend id. */
-       rc = xs_read_backend_info(xendev);
-       if (rc) {
-               uk_pr_err("Error initializing backend node and id.\n");
-               goto out;
-       }
-
-       /* Check versions string. */
-       versions = xs_read(XBT_NIL, xendev->otherend, "versions");
-       if (PTRISERR(versions)) {
-               uk_pr_err("Error reading backend version information.\n");
-               rc = PTR2ERR(versions);
-               goto out;
-       }
-
-       if (strcmp(versions, "1")) {
-               uk_pr_err("Backend does not support xen protocol version 1.\n");
-               free(versions);
-               rc = -EINVAL;
-               goto out;
-       }
-       free(versions);
-
-       /* Read ring information. */
-       rc = xs_read_backend_ring_info(xendev, &p9fdev->nb_max_rings,
-                                      &p9fdev->max_ring_page_order);
-       if (rc) {
-               uk_pr_err("Error reading backend ring information.\n");
-               goto out;
-       }
-
-       /* Read tag. */
-       p9fdev->tag = xs_read(XBT_NIL, xendev->nodename, "tag");
-       if (PTRISERR(p9fdev->tag)) {
-               uk_pr_err("Error reading 9pfs mount tag.\n");
-               rc = PTR2ERR(p9fdev->tag);
-               p9fdev->tag = NULL;
-       }
-
-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 = uk_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",
-                               uk_xenbus_state_to_str(be_state));
-               be_watch_stop(xendev);
-               goto out;
-       }
-
-       rc = uk_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 = uk_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;
-}
diff --git a/drivers/xen/9p/Config.uk b/drivers/xen/9p/Config.uk
deleted file mode 100644 (file)
index af0d5fb..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-menuconfig LIBXEN_9PFRONT
-       bool "Xenbus 9pfront Driver"
-       select LIBXENBUS
-       select LIBXENHEADERS
-       depends on PLAT_XEN
-       depends on LIBUK9P
-       help
-               Driver for 9pfs devices
-
-config LIBXEN_9PFRONT_NB_RINGS
-       int "Xen 9P ring number"
-       default 2
-       depends on LIBXEN_9PFRONT
-       help
-               Number of rings to allocate.
-               Will be clamped to the maximum value allowed by the backend.
-
-config LIBXEN_9PFRONT_RING_ORDER
-       int "Xen 9P ring order"
-       default 6
-       depends on LIBXEN_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.
diff --git a/drivers/xen/9p/Makefile.uk b/drivers/xen/9p/Makefile.uk
deleted file mode 100644 (file)
index ef81b98..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-$(eval $(call addlib_s,libxen9pfront,$(CONFIG_LIBXEN_9PFRONT)))
-
-LIBXEN9PFRONT_CFLAGS-y         += $(LIBXENPLAT_CFLAGS-y)
-LIBXEN9PFRONT_CINCLUDES-y      += $(LIBXENPLAT_CINCLUDES-y)
-LIBXEN9PFRONT_CINCLUDES-y      += $(LIBXENBUS_CINCLUDES-y)
-LIBXEN9PFRONT_SRCS-y           += $(LIBXEN9PFRONT_BASE)/9pfront.c
-LIBXEN9PFRONT_SRCS-y           += $(LIBXEN9PFRONT_BASE)/9pfront_xs.c
diff --git a/drivers/xen/9pfront/9pfront.c b/drivers/xen/9pfront/9pfront.c
new file mode 100644 (file)
index 0000000..d7d7431
--- /dev/null
@@ -0,0 +1,528 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Cristian Banu <cristb@gmail.com>
+ *
+ * Copyright (c) 2019, University Politehnica of Bucharest. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <uk/config.h>
+#include <uk/alloc.h>
+#include <uk/assert.h>
+#include <uk/essentials.h>
+#include <uk/errptr.h>
+#include <uk/list.h>
+#if CONFIG_LIBUKSCHED
+#include <uk/thread.h>
+#endif
+#include <uk/9pdev.h>
+#include <uk/9preq.h>
+#include <uk/9pdev_trans.h>
+#include <uk/plat/spinlock.h>
+#if defined(__i386__) || defined(__x86_64__)
+#include <xen-x86/mm.h>
+#include <xen-x86/irq.h>
+#elif defined(__aarch64__)
+#include <xen-arm/mm.h>
+#else
+#error "Unsupported architecture"
+#endif
+#include <uk/xenbus/xenbus.h>
+
+#include "9pfront_xb.h"
+
+#define DRIVER_NAME    "xen-9pfront"
+
+static struct uk_alloc *a;
+static UK_LIST_HEAD(p9front_device_list);
+static __spinlock p9front_device_list_lock;
+
+struct p9front_header {
+       uint32_t size;
+       uint8_t type;
+       uint16_t tag;
+} __packed;
+
+static void p9front_recv(struct p9front_dev_ring *ring);
+
+#if CONFIG_LIBUKSCHED
+
+static __noreturn void p9front_bh_handler(void *arg)
+{
+       struct p9front_dev_ring *ring = arg;
+
+       while (1) {
+               uk_waitq_wait_event(&ring->bh_wq,
+                               UK_READ_ONCE(ring->data_avail));
+               p9front_recv(ring);
+       }
+}
+
+#endif
+
+static void p9front_recv(struct p9front_dev_ring *ring)
+{
+       struct p9front_dev *p9fdev = ring->dev;
+       evtchn_port_t evtchn = ring->evtchn;
+       RING_IDX cons, prod, masked_cons, masked_prod;
+       int ring_size, rc;
+       struct p9front_header hdr;
+       struct uk_9preq *req;
+       uint32_t buf_cnt, zc_buf_cnt;
+
+       ring_size = XEN_FLEX_RING_SIZE(p9fdev->ring_order);
+
+       while (1) {
+               cons = ring->intf->in_cons;
+               prod = ring->intf->in_prod;
+               xen_rmb();
+
+               if (xen_9pfs_queued(prod, cons, ring_size) < sizeof(hdr)) {
+#if CONFIG_LIBUKSCHED
+                       UK_WRITE_ONCE(ring->data_avail, false);
+#endif
+                       notify_remote_via_evtchn(evtchn);
+                       return;
+               }
+
+               masked_prod = xen_9pfs_mask(prod, ring_size);
+               masked_cons = xen_9pfs_mask(cons, ring_size);
+
+               xen_9pfs_read_packet(&hdr, ring->data.in, sizeof(hdr),
+                               masked_prod, &masked_cons, ring_size);
+
+               req = uk_9pdev_req_lookup(p9fdev->p9dev, hdr.tag);
+               if (PTRISERR(req)) {
+                       uk_pr_warn("Found invalid tag=%u\n", hdr.tag);
+                       cons += hdr.size;
+                       xen_mb();
+                       ring->intf->in_cons = cons;
+                       continue;
+               }
+
+               masked_cons = xen_9pfs_mask(cons, ring_size);
+
+               /*
+                * Compute amount of data to read into request buffer and into
+                * zero-copy buffer.
+                */
+               buf_cnt = hdr.size;
+               if (hdr.type != UK_9P_RERROR && req->recv.zc_buf)
+                       buf_cnt = MIN(buf_cnt, req->recv.zc_offset);
+               zc_buf_cnt = hdr.size - buf_cnt;
+
+               xen_9pfs_read_packet(req->recv.buf, ring->data.in, buf_cnt,
+                               masked_prod, &masked_cons, ring_size);
+               xen_9pfs_read_packet(req->recv.zc_buf, ring->data.in,
+                               zc_buf_cnt, masked_prod, &masked_cons,
+                               ring_size);
+               cons += hdr.size;
+               xen_mb();
+               ring->intf->in_cons = cons;
+
+               rc = uk_9preq_receive_cb(req, hdr.size);
+               if (rc)
+                       uk_pr_warn("Could not receive reply: %d\n", rc);
+
+               /* Release reference held by uk_9pdev_req_lookup(). */
+               uk_9preq_put(req);
+       }
+}
+
+static void p9front_handler(evtchn_port_t evtchn,
+                           struct __regs *regs __unused,
+                           void *arg)
+{
+       struct p9front_dev_ring *ring = arg;
+
+       UK_ASSERT(ring);
+       UK_ASSERT(ring->evtchn == evtchn);
+
+       /*
+        * A new interrupt means that there is a response to be received, which
+        * means that a previously sent request has been removed from the out
+        * ring. Thus, the API can be notified of the possibility of retrying to
+        * send requests blocked on ENOSPC errors.
+        */
+       if (ring->dev->p9dev)
+               uk_9pdev_xmit_notify(ring->dev->p9dev);
+#if CONFIG_LIBUKSCHED
+       UK_WRITE_ONCE(ring->data_avail, true);
+       uk_waitq_wake_up(&ring->bh_wq);
+#else
+       p9front_recv(ring);
+#endif
+}
+
+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);
+
+       if (ring->bh_thread_name)
+               free(ring->bh_thread_name);
+       uk_sched_thread_terminate(ring->bh_thread);
+       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,
+                1ul << (p9fdev->ring_order + XEN_PAGE_SHIFT - PAGE_SHIFT));
+       gnttab_end_access(ring->ref);
+       uk_pfree(a, ring->intf, 1);
+       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_init(&ring->spinlock);
+       ring->dev = p9fdev;
+
+       /* Allocate ring intf page. */
+       ring->intf = uk_palloc(a, 1);
+       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, 1ul << (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);
+
+#if CONFIG_LIBUKSCHED
+       /* Allocate bottom-half thread. */
+       ring->data_avail = false;
+       uk_waitq_init(&ring->bh_wq);
+
+       rc = asprintf(&ring->bh_thread_name, DRIVER_NAME"-recv-%s-%u",
+                       p9fdev->tag, idx);
+       ring->bh_thread = uk_sched_thread_create(uk_sched_current(),
+                                                p9front_bh_handler, ring,
+                                                ring->bh_thread_name);
+       if (PTRISERR(ring->bh_thread)) {
+               rc = PTR2ERR(ring->bh_thread);
+               ring->bh_thread = NULL;
+               goto out_free_grants;
+       }
+#endif
+
+       /* 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_thread;
+       }
+
+       unmask_evtchn(ring->evtchn);
+
+       /* Mark ring as initialized. */
+       ring->initialized = true;
+
+       return 0;
+
+out_free_thread:
+       if (ring->bh_thread_name)
+               free(ring->bh_thread_name);
+       uk_sched_thread_terminate(ring->bh_thread);
+out_free_grants:
+       for (i = 0; i < (1 << p9fdev->ring_order); i++)
+               gnttab_end_access(ring->intf->ref[i]);
+       uk_pfree(a, data_bytes,
+                1ul << (p9fdev->ring_order + XEN_PAGE_SHIFT - PAGE_SHIFT));
+out_free_intf:
+       gnttab_end_access(ring->ref);
+       uk_pfree(a, ring->intf, 1);
+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_connect(struct uk_9pdev *p9dev,
+                          const char *device_identifier,
+                          const char *mount_args __unused)
+{
+       struct p9front_dev *p9fdev = NULL;
+       int rc = 0;
+       int found = 0;
+
+       ukarch_spin_lock(&p9front_device_list_lock);
+       uk_list_for_each_entry(p9fdev, &p9front_device_list, _list) {
+               if (!strcmp(p9fdev->tag, device_identifier)) {
+                       if (p9fdev->p9dev != NULL) {
+                               rc = -EBUSY;
+                               goto out;
+                       }
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found) {
+               rc = -ENODEV;
+               goto out;
+       }
+
+       /* The msize is given by the size of the flex ring. */
+       p9dev->max_msize = XEN_FLEX_RING_SIZE(p9fdev->ring_order);
+
+       p9fdev->p9dev = p9dev;
+       p9dev->priv = p9fdev;
+       rc = 0;
+       found = 1;
+
+out:
+       ukarch_spin_unlock(&p9front_device_list_lock);
+       return rc;
+}
+
+static int p9front_disconnect(struct uk_9pdev *p9dev __unused)
+{
+       struct p9front_dev *p9fdev;
+
+       UK_ASSERT(p9dev);
+       p9fdev = p9dev->priv;
+
+       ukarch_spin_lock(&p9front_device_list_lock);
+       p9fdev->p9dev = NULL;
+       ukarch_spin_unlock(&p9front_device_list_lock);
+
+       return 0;
+}
+
+static int p9front_request(struct uk_9pdev *p9dev,
+                          struct uk_9preq *req)
+{
+       struct p9front_dev *p9fdev;
+       struct p9front_dev_ring *ring;
+       int ring_idx, ring_size;
+       RING_IDX masked_prod, masked_cons, prod, cons;
+
+       UK_ASSERT(p9dev);
+       UK_ASSERT(req);
+       UK_ASSERT(req->state == UK_9PREQ_READY);
+
+       p9fdev = p9dev->priv;
+
+       ring_size = XEN_FLEX_RING_SIZE(p9fdev->ring_order);
+
+       ring_idx = req->tag % p9fdev->nb_rings;
+       ring = &p9fdev->rings[ring_idx];
+
+       /* Protect against concurrent writes to the out ring. */
+       ukarch_spin_lock(&ring->spinlock);
+       cons = ring->intf->out_cons;
+       prod = ring->intf->out_prod;
+       xen_mb();
+
+       masked_prod = xen_9pfs_mask(prod, ring_size);
+       masked_cons = xen_9pfs_mask(cons, ring_size);
+
+       if (ring_size - xen_9pfs_queued(prod, cons, ring_size) <
+                       req->xmit.size + req->xmit.zc_size) {
+               ukarch_spin_unlock(&ring->spinlock);
+               return -ENOSPC;
+       }
+
+       xen_9pfs_write_packet(ring->data.out, req->xmit.buf, req->xmit.size,
+                             &masked_prod, masked_cons, ring_size);
+       xen_9pfs_write_packet(ring->data.out, req->xmit.zc_buf, req->xmit.zc_size,
+                             &masked_prod, masked_cons, ring_size);
+       req->state = UK_9PREQ_SENT;
+       xen_wmb();
+       prod += req->xmit.size + req->xmit.zc_size;
+       ring->intf->out_prod = prod;
+
+       ukarch_spin_unlock(&ring->spinlock);
+       notify_remote_via_evtchn(ring->evtchn);
+
+       return 0;
+}
+
+static const struct uk_9pdev_trans_ops p9front_trans_ops = {
+       .connect        = p9front_connect,
+       .disconnect     = p9front_disconnect,
+       .request        = p9front_request
+};
+
+static struct uk_9pdev_trans p9front_trans = {
+       .name           = "xen",
+       .ops            = &p9front_trans_ops,
+       .a              = NULL /* Set below. */
+};
+
+
+static int p9front_drv_init(struct uk_alloc *drv_allocator)
+{
+       if (!drv_allocator)
+               return -EINVAL;
+
+       a = drv_allocator;
+       p9front_trans.a = a;
+
+       return uk_9pdev_trans_register(&p9front_trans);
+}
+
+static int p9front_add_dev(struct xenbus_device *xendev)
+{
+       struct p9front_dev *p9fdev;
+       int rc;
+
+       p9fdev = uk_calloc(a, 1, sizeof(*p9fdev));
+       if (!p9fdev) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       p9fdev->xendev = xendev;
+       rc = p9front_xb_init(p9fdev);
+       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_LIB9PFRONT_NB_RINGS,
+                              p9fdev->nb_max_rings);
+       p9fdev->ring_order = MIN(CONFIG_LIB9PFRONT_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;
+       ukarch_spin_lock(&p9front_device_list_lock);
+       uk_list_add(&p9fdev->_list, &p9front_device_list);
+       ukarch_spin_unlock(&p9front_device_list_lock);
+
+       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:
+       return rc;
+}
+
+static const xenbus_dev_type_t p9front_devtypes[] = {
+       xenbus_dev_9pfs,
+};
+
+static struct xenbus_driver p9front_driver = {
+       .device_types   = p9front_devtypes,
+       .init           = p9front_drv_init,
+       .add_dev        = p9front_add_dev
+};
+
+XENBUS_REGISTER_DRIVER(&p9front_driver);
diff --git a/drivers/xen/9pfront/9pfront.h b/drivers/xen/9pfront/9pfront.h
new file mode 100644 (file)
index 0000000..77be134
--- /dev/null
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Cristian Banu <cristb@gmail.com>
+ *
+ * Copyright (c) 2019, University Politehnica of Bucharest. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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>
+#if CONFIG_LIBUKSCHED
+#include <uk/sched.h>
+#endif
+#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 spinlock;
+       /* Tracks if this ring was initialized. */
+       bool initialized;
+#if CONFIG_LIBUKSCHED
+       /* Tracks if there is any data available on this ring. */
+       bool data_avail;
+       /* Bottom-half thread. */
+       struct uk_thread *bh_thread;
+       /* Bottom-half thread name. */
+       char *bh_thread_name;
+       /* Wait-queue on which the thread waits for available data. */
+       struct uk_waitq bh_wq;
+#endif
+};
+
+struct p9front_dev {
+       /* Xenbus device. */
+       struct xenbus_device *xendev;
+       /* 9P API device. */
+       struct uk_9pdev *p9dev;
+       /* Entry within the 9pfront device list. */
+       struct uk_list_head _list;
+       /* Number of maximum rings, read from xenstore. */
+       int nb_max_rings;
+       /* Maximum ring page order, read from xenstore. */
+       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/drivers/xen/9pfront/9pfront_xb.h b/drivers/xen/9pfront/9pfront_xb.h
new file mode 100644 (file)
index 0000000..bfa094f
--- /dev/null
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Cristian Banu <cristb@gmail.com>
+ *
+ * Copyright (c) 2019, University Politehnica of Bucharest. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __9PFRONT_XB_H__
+#define __9PFRONT_XB_H__
+
+#include "9pfront.h"
+
+/**
+ * Reads device information from the xenstore, such as the mount tag
+ * and details about the device rings.
+ *
+ * @param p9fdev
+ *   9P frontend device
+ * @return
+ *   - (0): Successful.
+ *   - (-EINVAL): Invalid data.
+ *   - (< 0): Error while reading.
+ */
+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/drivers/xen/9pfront/9pfront_xs.c b/drivers/xen/9pfront/9pfront_xs.c
new file mode 100644 (file)
index 0000000..8aa8914
--- /dev/null
@@ -0,0 +1,364 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Cristian Banu <cristb@gmail.com>
+ *
+ * Copyright (c) 2019, University Politehnica of Bucharest. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <uk/config.h>
+#include <uk/assert.h>
+#include <uk/essentials.h>
+#include <uk/errptr.h>
+#include <uk/xenbus/xs.h>
+#include <uk/xenbus/client.h>
+
+#include "9pfront_xb.h"
+
+static int xs_read_backend_info(struct xenbus_device *xendev)
+{
+       int rc, val;
+       char *path = NULL;
+
+       /* Read backend id. */
+       rc = asprintf(&path, "%s/backend-id", xendev->nodename);
+       if (rc <= 0) {
+               uk_pr_err("Failed to allocate format path: %d\n", rc);
+               goto out;
+       }
+
+       rc = xs_read_integer(XBT_NIL, path, &val);
+       if (rc)
+               goto out;
+       xendev->otherend_id = (domid_t)val;
+
+       /* Read backend path. */
+       xendev->otherend = xs_read(XBT_NIL, xendev->nodename, "backend");
+       if (PTRISERR(xendev->otherend)) {
+               rc = PTR2ERR(xendev->otherend);
+               xendev->otherend = NULL;
+       }
+
+out:
+       free(path);
+       return rc;
+}
+
+static int xs_read_backend_ring_info(struct xenbus_device *xendev,
+                                    int *nb_max_rings,
+                                    int *max_ring_page_order)
+{
+       int rc;
+       char *int_str;
+
+       /* Read max-rings. */
+       int_str = xs_read(XBT_NIL, xendev->otherend, "max-rings");
+       if (PTRISERR(int_str)) {
+               rc = PTR2ERR(int_str);
+               uk_pr_err("Error: %d\n", rc);
+               goto out;
+       }
+
+       *nb_max_rings = strtol(int_str, NULL, 10);
+       free(int_str);
+
+       /* Read max-ring-page-order. */
+       int_str = xs_read(XBT_NIL, xendev->otherend, "max-ring-page-order");
+       if (PTRISERR(int_str)) {
+               rc = PTR2ERR(int_str);
+               uk_pr_err("Error: %d\n", rc);
+               goto out;
+       }
+
+       *max_ring_page_order = strtol(int_str, NULL, 10);
+       free(int_str);
+       rc = 0;
+
+out:
+       return rc;
+}
+
+int p9front_xb_init(struct p9front_dev *p9fdev)
+{
+       struct xenbus_device *xendev;
+       char *versions;
+       int rc;
+
+       UK_ASSERT(p9fdev != NULL);
+
+       xendev = p9fdev->xendev;
+       UK_ASSERT(xendev != NULL);
+
+       /* Read backend node and backend id. */
+       rc = xs_read_backend_info(xendev);
+       if (rc) {
+               uk_pr_err("Error initializing backend node and id.\n");
+               goto out;
+       }
+
+       /* Check versions string. */
+       versions = xs_read(XBT_NIL, xendev->otherend, "versions");
+       if (PTRISERR(versions)) {
+               uk_pr_err("Error reading backend version information.\n");
+               rc = PTR2ERR(versions);
+               goto out;
+       }
+
+       if (strcmp(versions, "1")) {
+               uk_pr_err("Backend does not support xen protocol version 1.\n");
+               free(versions);
+               rc = -EINVAL;
+               goto out;
+       }
+       free(versions);
+
+       /* Read ring information. */
+       rc = xs_read_backend_ring_info(xendev, &p9fdev->nb_max_rings,
+                                      &p9fdev->max_ring_page_order);
+       if (rc) {
+               uk_pr_err("Error reading backend ring information.\n");
+               goto out;
+       }
+
+       /* Read tag. */
+       p9fdev->tag = xs_read(XBT_NIL, xendev->nodename, "tag");
+       if (PTRISERR(p9fdev->tag)) {
+               uk_pr_err("Error reading 9pfs mount tag.\n");
+               rc = PTR2ERR(p9fdev->tag);
+               p9fdev->tag = NULL;
+       }
+
+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 = uk_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",
+                               uk_xenbus_state_to_str(be_state));
+               be_watch_stop(xendev);
+               goto out;
+       }
+
+       rc = uk_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 = uk_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;
+}
diff --git a/drivers/xen/9pfront/Config.uk b/drivers/xen/9pfront/Config.uk
new file mode 100644 (file)
index 0000000..40ea67a
--- /dev/null
@@ -0,0 +1,25 @@
+menuconfig LIB9PFRONT
+       bool "9pfront: Xen 9pfs volumes"
+       select LIBXENBUS
+       select LIBXENHEADERS
+       depends on PLAT_XEN
+       depends on LIBUK9P
+       help
+               Xen driver for 9pfs volumes
+
+if LIB9PFRONT
+config LIB9PFRONT_NB_RINGS
+       int "Number of rings"
+       default 2
+       help
+               Number of rings to allocate.
+               Will be clamped to the maximum value allowed by the backend.
+
+config LIB9PFRONT_RING_ORDER
+       int "Ring size order"
+       default 6
+       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.
+endif
diff --git a/drivers/xen/9pfront/Makefile.uk b/drivers/xen/9pfront/Makefile.uk
new file mode 100644 (file)
index 0000000..d2e0416
--- /dev/null
@@ -0,0 +1,8 @@
+$(eval $(call addlib_s,lib9pfront,$(CONFIG_LIB9PFRONT)))
+
+# FIXME: Extra includes should be removed
+LIB9PFRONT_CFLAGS-y         += $(LIBXENPLAT_CFLAGS-y)
+LIB9PFRONT_CINCLUDES-y      += $(LIBXENPLAT_CINCLUDES-y)
+LIB9PFRONT_CINCLUDES-y      += $(LIBXENBUS_CINCLUDES-y)
+LIB9PFRONT_SRCS-y           += $(LIB9PFRONT_BASE)/9pfront.c
+LIB9PFRONT_SRCS-y           += $(LIB9PFRONT_BASE)/9pfront_xs.c
diff --git a/drivers/xen/9pfront/exportsyms.uk b/drivers/xen/9pfront/exportsyms.uk
new file mode 100644 (file)
index 0000000..32986ff
--- /dev/null
@@ -0,0 +1 @@
+# No public symbols
index 81540bdcd07315bf89369ac841e651742f322cc5..7ba19681130c7b04bc19d2183f4771357ed2a09e 100644 (file)
@@ -7,7 +7,7 @@
 UK_DRIV_XEN_BASE := $(UK_DRIV_BASE)/xen
 
 $(eval $(call import_lib,$(UK_DRIV_XEN_BASE)/xenheaders))
-$(eval $(call import_lib,$(UK_DRIV_XEN_BASE)/9p))
+$(eval $(call import_lib,$(UK_DRIV_XEN_BASE)/9pfront))
 $(eval $(call import_lib,$(UK_DRIV_XEN_BASE)/blk))
 $(eval $(call import_lib,$(UK_DRIV_XEN_BASE)/net))
 $(eval $(call import_lib,$(UK_DRIV_XEN_BASE)/xenbus))
index 8a868f61f0ec2c72924539a1df6079404b5a3bb7..e0f3d935be8e51ab9975cdeccbc152d673d6ddb3 100644 (file)
@@ -17,7 +17,7 @@ menuconfig PLAT_XEN
        select HAVE_INTCTLR
        imply LIBUKINTCTLR_GICV3 if ARCH_ARM_64
        imply LIBXEN_NETFRONT if LIBUKNETDEV
-       imply LIBXEN_9PFRONT if LIBUK9P
+       imply LIB9PFRONT if LIBUK9P
        imply LIBXEN_BLKFRONT if LIBUKBLKDEV
        imply LIBXEN_CONSOLE
        help