|  | /* | 
|  | * 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. | 
|  | */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #include <stdint.h> | 
|  | #include <err.h> | 
|  | #include <sys/uio.h> | 
|  | #include <vmm/virtio_ring.h> | 
|  | #include <vmm/sched.h> | 
|  |  | 
|  | // This file contains the core virtio structs, functions, and macros for Akaros | 
|  |  | 
|  | // 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__) | 
|  |  | 
|  | // 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__) | 
|  |  | 
|  | // 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__) | 
|  |  | 
|  |  | 
|  |  | 
|  | struct virtio_vq { | 
|  | // The name of the vq e.g. for printing errors | 
|  | char *name; | 
|  |  | 
|  | // The vqdev that contains this vq | 
|  | struct virtio_vq_dev *vqdev; | 
|  |  | 
|  | // 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; | 
|  |  | 
|  | // 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; | 
|  |  | 
|  | // The driver writes 0x1 to qready to tell the device | 
|  | // that it can execute requests from this vq | 
|  | uint32_t qready; | 
|  |  | 
|  | // The last vq.vring.avail->idx that the service function saw while | 
|  | // processing the queue | 
|  | uint16_t last_avail; | 
|  |  | 
|  | // The service function that processes buffers for this queue | 
|  | void *(*srv_fn)(void *arg); | 
|  |  | 
|  | // The thread that the service function is running in | 
|  | struct task_thread *srv_th; | 
|  |  | 
|  | // 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; | 
|  |  | 
|  | // The number of virtio_vqs on the device | 
|  | uint32_t num_vqs; | 
|  |  | 
|  | // A pointer to the device-specific config space | 
|  | void *cfg; | 
|  |  | 
|  | // 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[]; | 
|  | }; | 
|  |  | 
|  | // 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); |