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

[Minios-devel] [UNIKRAFT PATCH v2 5/5] plat/drivers: Implement virtio 9P request and recv


  • To: "minios-devel@xxxxxxxxxxxxx" <minios-devel@xxxxxxxxxxxxx>
  • From: Vlad-Andrei BĂDOIU (78692) <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
  • Date: Sat, 7 Sep 2019 09:45:30 +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=IiV3c+9iWggxIX1R8TI5Bf8LjCMHMgmbH/VkwxPpDho=; b=ZQt4RaAGymEK5sZDwuGp/wDzqtXKKn5L6CQP4IdxK98lGKCdzOR7gZaG3msBdKQq5Ct45yFrZNoH7GZDv/zVF9Tmy+edTgUfmovtLtCP3eEElNtYHm4hfvup1wyHdVFPr/7IbHIlE137wNYh6k9M/N5Pa1hrF10Lc94Q4xwFMWRt5ukeKjMnhvHIxHjCwJV+CKO9wT08XEcMAoOaRik5PzGNbDpBbMhm8Au9vOFz87P7qvoOCJXXgXBxgfD27ltRttHl8zILYfpGdDA67efD4fphQc8zQLZf83mARLuH8amwIaKVEVm9D20OHkypF0QeZgUXbBRu6wXsyTCYVpMmsg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Wvwl1Z8LubKBE3TyspXf+kTufY9ZGperkPGRV9BJ7S3vBTNhagqmEaya4Z97gn8N6y6Y7KMJ+Km3OnqNe4nkZauNDVAUseYu/Y46JtJj1kZNJHPLGKDvsItxAd1Cytknp2uZNkqn+gwk4KWr/15LBcMBylULdI+kFHip5OrYkrN6mSgdVJoCqRQovv8FyFm+Cd9QI3Q5cDokPxT2JjHfVrHtdsrdGxkyrMc0U9XfXqT5kDN4eY2N5ogWk4j1THsxCkD/bUli6AB4Y4QsrKZ8dAvgQ2mOifYppfyutTcQvYuR0zM9oIsPjHSo6g6n6UQOfH569W9GHdYrpt3Dyd1QOg==
  • 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 09:45:58 +0000
  • List-id: Mini-os development list <minios-devel.lists.xenproject.org>
  • Thread-index: AQHVZWD8w7Mezqtol0G1g8tFVsTgng==
  • Thread-topic: [UNIKRAFT PATCH v2 5/5] plat/drivers: Implement virtio 9P request and recv

From: Cristian Banu <cristb@xxxxxxxxx>

This patch implements the virtio request and receive callbacks.

Signed-off-by: Cristian Banu <cristb@xxxxxxxxx>
---
 plat/drivers/virtio/virtio_9p.c | 161 +++++++++++++++++++++++++++++++-
 1 file changed, 156 insertions(+), 5 deletions(-)

diff --git a/plat/drivers/virtio/virtio_9p.c b/plat/drivers/virtio/virtio_9p.c
index 8094ec70..fe0d69ab 100644
--- a/plat/drivers/virtio/virtio_9p.c
+++ b/plat/drivers/virtio/virtio_9p.c
@@ -35,6 +35,9 @@
 #include <inttypes.h>
 #include <uk/alloc.h>
 #include <uk/essentials.h>
+#include <uk/sglist.h>
+#include <uk/9pdev.h>
+#include <uk/9preq.h>
 #include <uk/9pdev_trans.h>
 #include <virtio/virtio_bus.h>
 #include <virtio/virtio_9p.h>
@@ -61,6 +64,11 @@ struct virtio_9p_device {
        uint16_t hwvq_id;
        /* libuk9p associated device (NULL if the device is not in use). */
        struct uk_9pdev *p9dev;
+       /* Scatter-gather list. */
+       struct uk_sglist sg;
+       struct uk_sglist_seg sgsegs[NUM_SEGMENTS];
+       /* Spinlock protecting the sg list and the vq. */
+       spinlock_t spinlock;
 };
 
 static int virtio_9p_connect(struct uk_9pdev *p9dev,
@@ -120,10 +128,96 @@ static int virtio_9p_disconnect(struct uk_9pdev *p9dev)
        return 0;
 }
 
-static int virtio_9p_request(struct uk_9pdev *p9dev __unused,
-                            struct uk_9preq *req __unused)
+static int virtio_9p_request(struct uk_9pdev *p9dev,
+                            struct uk_9preq *req)
 {
-       return -EOPNOTSUPP;
+       struct virtio_9p_device *dev;
+       int rc, host_notified = 0;
+       unsigned long flags;
+       size_t read_segs, write_segs;
+       bool failed = false;
+
+       UK_ASSERT(p9dev);
+       UK_ASSERT(req);
+       UK_ASSERT(UK_READ_ONCE(req->state) == UK_9PREQ_READY);
+
+       /*
+        * Get the request such that it won't get freed while it's
+        * used as a cookie for the virtqueue.
+        */
+       uk_9preq_get(req);
+       dev = p9dev->priv;
+       ukplat_spin_lock_irqsave(&dev->spinlock, flags);
+       uk_sglist_reset(&dev->sg);
+
+       rc = uk_sglist_append(&dev->sg, req->xmit.buf, req->xmit.size);
+       if (rc < 0) {
+               failed = true;
+               goto out_unlock;
+       }
+
+       if (req->xmit.zc_buf) {
+               rc = uk_sglist_append(&dev->sg, req->xmit.zc_buf,
+                               req->xmit.zc_size);
+               if (rc < 0) {
+                       failed = true;
+                       goto out_unlock;
+               }
+       }
+
+       read_segs = dev->sg.sg_nseg;
+
+       rc = uk_sglist_append(&dev->sg, req->recv.buf, req->recv.size);
+       if (rc < 0) {
+               failed = true;
+               goto out_unlock;
+       }
+
+       if (req->recv.zc_buf) {
+               uint32_t recv_size = req->recv.size + req->recv.zc_size;
+
+               rc = uk_sglist_append(&dev->sg, req->recv.zc_buf,
+                               req->recv.zc_size);
+               if (rc < 0) {
+                       failed = true;
+                       goto out_unlock;
+               }
+
+               /* Make eure there is sufficient space for Rerror replies. */
+               if (recv_size < UK_9P_RERROR_MAXSIZE) {
+                       uint32_t leftover = UK_9P_RERROR_MAXSIZE - recv_size;
+
+                       rc = uk_sglist_append(&dev->sg,
+                                       req->recv.buf + recv_size, leftover);
+                       if (rc < 0) {
+                               failed = true;
+                               goto out_unlock;
+                       }
+               }
+       }
+
+       write_segs = dev->sg.sg_nseg - read_segs;
+
+       rc = virtqueue_buffer_enqueue(dev->vq, req, &dev->sg,
+                                     read_segs, write_segs);
+       if (likely(rc >= 0)) {
+               UK_WRITE_ONCE(req->state, UK_9PREQ_SENT);
+               virtqueue_host_notify(dev->vq);
+               host_notified = 1;
+               rc = 0;
+       }
+
+out_unlock:
+       if (failed)
+               uk_pr_err(DRIVER_NAME": Failed to append to the sg list.\n");
+       ukplat_spin_unlock_irqrestore(&dev->spinlock, flags);
+       /*
+        * Release the reference to the 9P request if it was not successfully
+        * sent.
+        */
+       if (!host_notified)
+               uk_9preq_put(req);
+       return rc;
 }
 
 static const struct uk_9pdev_trans_ops v9p_trans_ops = {
@@ -138,9 +232,63 @@ static struct uk_9pdev_trans v9p_trans = {
        .a              = NULL /* Set by the driver initialization. */
 };
 
-static int virtio_9p_recv(struct virtqueue *vq __unused, void *priv __unused)
+static int virtio_9p_recv(struct virtqueue *vq, void *priv)
 {
-       return 0;
+       struct virtio_9p_device *dev;
+       struct uk_9preq *req = NULL;
+       uint32_t len;
+       int rc = 0;
+       int handled = 0;
+
+       UK_ASSERT(vq);
+       UK_ASSERT(priv);
+
+       dev = priv;
+       UK_ASSERT(vq == dev->vq);
+
+       while (1) {
+               /*
+                * Protect against data races with virtio_9p_request() calls
+                * which are trying to enqueue to the same vq.
+                */
+               ukarch_spin_lock(&dev->spinlock);
+               rc = virtqueue_buffer_dequeue(dev->vq, (void **)&req, &len);
+               ukarch_spin_unlock(&dev->spinlock);
+               if (rc < 0)
+                       break;
+
+               /*
+                * Notify the 9P API that this request has been successfully
+                * received, release the reference to the request.
+                */
+               uk_9preq_receive_cb(req, len);
+
+               /*
+                * Check for Rerror messages, fixup the error message if
+                * needed.
+                */
+               if (req->recv.type == UK_9P_RERROR) {
+                       memcpy(req->recv.buf + req->recv.zc_offset,
+                              req->recv.zc_buf,
+                              MIN(req->recv.zc_size, len - UK_9P_HEADER_SIZE));
+               }
+
+               uk_9preq_put(req);
+               handled = 1;
+
+               /* Break if there are no more buffers on the virtqueue. */
+               if (rc == 0)
+                       break;
+       }
+
+       /*
+        * As the virtqueue might have empty slots now, notify any threads
+        * blocked on ENOSPC errors.
+        */
+       if (handled)
+               uk_9pdev_xmit_notify(dev->p9dev);
+
+       return handled;
 }
 
 static int virtio_9p_vq_alloc(struct virtio_9p_device *d)
@@ -165,6 +313,8 @@ static int virtio_9p_vq_alloc(struct virtio_9p_device *d)
                goto exit;
        }
 
+       uk_sglist_init(&d->sg, ARRAY_SIZE(d->sgsegs), &d->sgsegs[0]);
+
        d->vq = virtio_vqueue_setup(d->vdev,
                                    d->hwvq_id,
                                    qdesc_size,
@@ -272,6 +422,7 @@ static int virtio_9p_add_dev(struct virtio_dev *vdev)
                rc = -ENOMEM;
                goto out;
        }
+       ukarch_spin_lock_init(&d->spinlock);
        d->vdev = vdev;
        virtio_9p_feature_set(d);
        rc = virtio_9p_configure(d);
-- 
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®.