vmm: Added more syscalls and helpers to linuxemu
[akaros.git] / user / vmm / include / vmm / virtio.h
index d92d722..473d5bf 100644 (file)
-#pragma once
+/*
+ * Copyright (c) 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
-#include <ros/arch/membar.h>
-#include <ros/arch/mmu.h>
-#include <ros/virtio_ring.h>
-#include <ros/common.h>
+ #pragma once
 
-#include <stddef.h>
-#include <stdbool.h>
+#include <stdint.h>
+#include <err.h>
+#include <sys/uio.h>
+#include <vmm/virtio_ring.h>
+#include <vmm/sched.h>
 
-/* this is just an iov but we're going to keep the type for now, in case
- * we want it at some point.
- */
-struct scatterlist {
-       void *v;
-       int length;
-};
+// This file contains the core virtio structs, functions, and macros for Akaros
 
-#define unlikely(x) (x)
-#define virtio_rmb(x) rmb()
-#define virtio_wmb(x) wmb()
-#define virtio_mb(x) mb()
-
-#define sg_phys(x) ((uintptr_t)x)
-#define virt_to_phys(x) ((uintptr_t)x)
-
-struct virtqueue *vring_new_virtqueue(unsigned int index,
-                                     unsigned int num,
-                                     unsigned int vring_align,
-                                     bool weak_barriers,
-                                     void *pages,
-                                     bool (*notify)(struct virtqueue *),
-                                     void (*callback)(struct virtqueue *),
-                                     const char *name);
-
-int virtqueue_add_outbuf_avail(struct virtqueue *vq,
-                        struct scatterlist sg[], unsigned int num,
-                        void *data,
-                              int opts); // Opts only used in kernel functions.
-unsigned int virtqueue_get_vring_size(struct virtqueue *_vq);
-void *virtqueue_get_buf_used(struct virtqueue *_vq, unsigned int *len);
-int virtqueue_add_inbuf_avail(struct virtqueue *vq,
-                       struct scatterlist sg[], unsigned int num,
-                             void *data, int opts);
-
-/* linux-isms we may or may not ever care about. */
-#define __user
-#define __force
-#define __cold
-
-int avail(struct virtqueue *_vq);
-void showvq(struct virtqueue *_vq);
-void showdesc(struct virtqueue *_vq, uint16_t head);
-int virtio_get_buf_avail_start(struct virtqueue *_vq, uint16_t *last_avail_idx, struct scatterlist **sgp, int *sgplen);
-void virtio_get_buf_avail_done(struct virtqueue *_vq, uint16_t last_avail_idx, int id, int len);
-void showscatterlist(struct scatterlist *sg, int num);
-
-unsigned int wait_for_vq_desc(struct virtqueue *vq,
-                                struct scatterlist iov[],
-                                unsigned int *out_num, unsigned int *in_num);
-void add_used(struct virtqueue *vq, unsigned int head, int len);
-
-/**
- * virtqueue - a queue to register buffers for sending or receiving.
- * @list: the chain of virtqueues for this device
- * @callback: the function to call when buffers are consumed (can be NULL).
- * @name: the name of this virtqueue (mainly for debugging)
- * @vdev: the virtio device this queue was created for.
- * @priv: a pointer for the virtqueue implementation to use.
- * @index: the zero-based ordinal number for this queue.
- * @num_free: number of elements we expect to be able to fit.
- *
- * A note on @num_free: with indirect buffers, each buffer needs one
- * element in the queue, otherwise a buffer will need one element per
- * sg element.
- */
-struct virtqueue {
-       void (*callback)(struct virtqueue *vq);
-       const char *name;
-       unsigned int index;
-       unsigned int num_free;
-       void *priv;
-};
+// Print errors caused by incorrect driver behavior
+#define VIRTIO_DRI_ERRX(dev, fmt, ...) \
+       errx(1, "\n  %s:%d\n  Virtio Device: %s: Error, driver behavior.\n  "\
+               fmt, __FILE__, __LINE__, (dev)->name, ## __VA_ARGS__)
+
+// Print warnings caused by incorrect driver behavior
+#define VIRTIO_DRI_WARNX(dev, fmt, ...) \
+       warnx("\n  %s:%d\n  Virtio Device: %s: Warning, driver behavior.\n  "\
+               fmt, __FILE__, __LINE__, (dev)->name, ## __VA_ARGS__)
 
-int virtqueue_add_outbuf(struct virtqueue *vq,
-                        struct scatterlist sg[], unsigned int num,
-                        void *data,
-                        int flags);
+// Print errors caused by incorrect device behavior
+#define VIRTIO_DEV_ERRX(dev, fmt, ...) \
+       errx(1, "\n  %s:%d\n  Virtio Device: %s: Error, device behavior.\n  "\
+               fmt, __FILE__, __LINE__, (dev)->name, ## __VA_ARGS__)
 
-int virtqueue_add_inbuf(struct virtqueue *vq,
-                       struct scatterlist sg[], unsigned int num,
-                       void *data,
-                       int flags);
+// Print warnings caused by incorrect device behavior
+#define VIRTIO_DEV_WARNX(dev, fmt, ...) \
+       warnx("\n  %s:%d\n  Virtio Device: %s: Warning, device behavior.\n  "\
+               fmt, __FILE__, __LINE__, (dev)->name, ## __VA_ARGS__)
 
-int virtqueue_add_sgs(struct virtqueue *vq,
-                     struct scatterlist *sgs[],
-                     unsigned int out_sgs,
-                     unsigned int in_sgs,
-                     void *data,
-                     int flags);
 
-bool virtqueue_kick(struct virtqueue *vq);
 
-bool virtqueue_kick_prepare(struct virtqueue *vq);
+struct virtio_vq {
+       // The name of the vq e.g. for printing errors
+       char *name;
 
-bool virtqueue_notify(struct virtqueue *vq);
+       // The vqdev that contains this vq
+       struct virtio_vq_dev *vqdev;
 
-void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len);
+       // The vring contains pointers to the descriptor table and available and
+       // used rings as well as the number of elements in the queue.
+       struct vring vring;
 
-void virtqueue_disable_cb(struct virtqueue *vq);
+       // The maximum number of elements in the queue that the device is ready to
+       // process. Reads from the register corresponding to this value return 0x0
+       // if the queue is not available. A queue's size is always a power of 2.
+       int qnum_max;
 
-bool virtqueue_enable_cb(struct virtqueue *vq);
+       // The driver writes 0x1 to qready to tell the device
+       // that it can execute requests from this vq
+       uint32_t qready;
 
-unsigned virtqueue_enable_cb_prepare(struct virtqueue *vq);
+       // The last vq.vring.avail->idx that the service function saw while
+       // processing the queue
+       uint16_t last_avail;
 
-bool virtqueue_poll(struct virtqueue *vq, unsigned);
+       // The service function that processes buffers for this queue
+       void *(*srv_fn)(void *arg);
 
-bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
+       // The thread that the service function is running in
+       struct task_thread *srv_th;
 
-void *virtqueue_detach_unused_buf(struct virtqueue *vq);
+       // Write eventfd to wake up the service function; it blocks on eventfd read
+       int eventfd;
+};
+
+struct virtio_vq_dev {
+       // The name of the device e.g. for printing errors
+       char *name;
+
+       // The type of the device e.g. VIRTIO_ID_CONSOLE for a console device
+       uint32_t dev_id;
+
+       // The features supported by this device
+       uint64_t dev_feat;
+
+       // The features supported by the driver (these are set by the guest)
+       uint64_t dri_feat;
 
-unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
+       // The number of virtio_vqs on the device
+       uint32_t num_vqs;
 
-bool virtqueue_is_broken(struct virtqueue *vq);
-void virtqueue_close(struct virtqueue *vq);
+       // A pointer to the device-specific config space
+       void *cfg;
 
-static inline uint32_t read32(const volatile void *addr)
-{
-       return *(const volatile uint32_t *)addr;
-}
+       // A pointer to a default device-specific config space
+       // If set, cfg_sz bytes, starting at cfg_d, will be
+       // copied to cfg.
+       void *cfg_d;
+
+       // The size, in bytes, of the device-specific config space
+       // Used by the device to bounds-check driver access
+       uint64_t cfg_sz;
+
+       // The virtio transport dev that contains this vqdev
+       // i.e. struct virtio_mmio_dev
+       void *transport_dev;
+
+       // Flexible array of vqs on this device
+       struct virtio_vq vqs[];
+};
 
-static inline void write32(volatile void *addr, uint32_t value)
-{
-       *(volatile uint32_t *)addr = value;
-}
+// Do not include virtio_lguest_helpers.h directly. You should include the
+// contained functions by including virtio.h. These functions are kept apart
+// from virtio.h so that we can keep a clean separation between our code
+// and code derived from lguest.
+#include <vmm/virtio_lguest_helpers.h>
+
+// Returns NULL if the features are valid, otherwise returns
+// an error string describing what part of validation failed
+// We pass the vqdev instead of just the dev_id in case we
+// also want to validate the device-specific config space.
+// feat is the feature vector that you want to validate for the vqdev
+const char *virtio_validate_feat(struct virtio_vq_dev *vqdev, uint64_t feat);