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

Re: [Minios-devel] [UNIKRAFT PATCH RFC v2 5/7] plat/virtio: Add new virtio_mmio device/driver on arm64



Hi Justin,

Thanks fort he patch. Please see my comments inline.

Best,
Santiago

On 23.10.19, 05:52, "Minios-devel on behalf of Jia He" 
<minios-devel-bounces@xxxxxxxxxxxxxxxxxxxx on behalf of justin.he@xxxxxxx> 
wrote:

    Based on [1], but device removing/releasing is not supported.
    
    [1] 
http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html#x1-1090002
    
    Signed-off-by: Jia He <justin.he@xxxxxxx>
    ---
     plat/drivers/include/virtio/virtio_mmio.h | 143 +++++++
     plat/drivers/virtio/virtio_mmio.c         | 493 ++++++++++++++++++++++
     2 files changed, 636 insertions(+)
     create mode 100644 plat/drivers/include/virtio/virtio_mmio.h
     create mode 100644 plat/drivers/virtio/virtio_mmio.c
    
    diff --git a/plat/drivers/include/virtio/virtio_mmio.h 
b/plat/drivers/include/virtio/virtio_mmio.h
    new file mode 100644
    index 0000000..4aeb89b
    --- /dev/null
    +++ b/plat/drivers/include/virtio/virtio_mmio.h
    @@ -0,0 +1,143 @@
    +/* SPDX-License-Identifier: BSD-3-Clause */
    +/*
    + * Virtio platform device driver
    + *
    + * Copyright 2011, ARM Ltd.
    + * Copyright 2018, ARM Ltd.
    + * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
    + *
    + * 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 IBM 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 IBM 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.
    + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
    + */
    +/**
    + * Taken and from Linux kernel
    + * include/uapi/linux/virtio_mmio.h
    + *
    + * commit-id: faa9b39f0e9d
    + */
    +#ifndef __VIRTIO_MMIO_H__
    +#define __VIRTIO_MMIO_H__
    +
    +/*
    + * Control registers
    + */
    +
    +/* Magic value ("virt" string) - Read Only */
    +#define VIRTIO_MMIO_MAGIC_VALUE            0x000
    +
    +/* Virtio device version - Read Only */
    +#define VIRTIO_MMIO_VERSION                0x004
    +
    +/* Virtio device ID - Read Only */
    +#define VIRTIO_MMIO_DEVICE_ID              0x008
    +
    +/* Virtio vendor ID - Read Only */
    +#define VIRTIO_MMIO_VENDOR_ID              0x00c
    +
    +/* Bitmask of the features supported by the device (host)
    + * (32 bits per set) - Read Only */
    +#define VIRTIO_MMIO_DEVICE_FEATURES        0x010
    +
    +/* Device (host) features set selector - Write Only */
    +#define VIRTIO_MMIO_DEVICE_FEATURES_SEL    0x014
    +
    +/* Bitmask of features activated by the driver (guest)
    + * (32 bits per set) - Write Only */
    +#define VIRTIO_MMIO_DRIVER_FEATURES        0x020
    +
    +/* Activated features set selector - Write Only */
    +#define VIRTIO_MMIO_DRIVER_FEATURES_SEL    0x024
    +
    +
    +#ifndef VIRTIO_MMIO_NO_LEGACY /* LEGACY DEVICES ONLY! */
    +
    +/* Guest's memory page size in bytes - Write Only */
    +#define VIRTIO_MMIO_GUEST_PAGE_SIZE        0x028
    +
    +#endif
    +
    +
    +/* Queue selector - Write Only */
    +#define VIRTIO_MMIO_QUEUE_SEL              0x030
    +
    +/* Maximum size of the currently selected queue - Read Only */
    +#define VIRTIO_MMIO_QUEUE_NUM_MAX  0x034
    +
    +/* Queue size for the currently selected queue - Write Only */
    +#define VIRTIO_MMIO_QUEUE_NUM              0x038
    +
    +
    +#ifndef VIRTIO_MMIO_NO_LEGACY /* LEGACY DEVICES ONLY! */
    +
    +/* Used Ring alignment for the currently selected queue - Write Only */
    +#define VIRTIO_MMIO_QUEUE_ALIGN            0x03c
    +
    +/* Guest's PFN for the currently selected queue - Read Write */
    +#define VIRTIO_MMIO_QUEUE_PFN              0x040
    +
    +#endif
    +
    +
    +/* Ready bit for the currently selected queue - Read Write */
    +#define VIRTIO_MMIO_QUEUE_READY            0x044
    +
    +/* Queue notifier - Write Only */
    +#define VIRTIO_MMIO_QUEUE_NOTIFY   0x050
    +
    +/* Interrupt status - Read Only */
    +#define VIRTIO_MMIO_INTERRUPT_STATUS       0x060
    +
    +/* Interrupt acknowledge - Write Only */
    +#define VIRTIO_MMIO_INTERRUPT_ACK  0x064
    +
    +/* Device status register - Read Write */
    +#define VIRTIO_MMIO_STATUS         0x070
    +
    +/* Selected queue's Descriptor Table address, 64 bits in two halves */
    +#define VIRTIO_MMIO_QUEUE_DESC_LOW 0x080
    +#define VIRTIO_MMIO_QUEUE_DESC_HIGH        0x084
    +
    +/* Selected queue's Available Ring address, 64 bits in two halves */
    +#define VIRTIO_MMIO_QUEUE_AVAIL_LOW        0x090
    +#define VIRTIO_MMIO_QUEUE_AVAIL_HIGH       0x094
    +
    +/* Selected queue's Used Ring address, 64 bits in two halves */
    +#define VIRTIO_MMIO_QUEUE_USED_LOW 0x0a0
    +#define VIRTIO_MMIO_QUEUE_USED_HIGH        0x0a4
    +
    +/* Configuration atomicity value */
    +#define VIRTIO_MMIO_CONFIG_GENERATION      0x0fc
    +
    +/* The config space is defined by each driver as
    + * the per-driver configuration space - Read Write */
    +#define VIRTIO_MMIO_CONFIG         0x100
    +
    +/*
    + * Interrupt flags (re: interrupt status & acknowledge registers)
    + */
    +#define VIRTIO_MMIO_INT_VRING              (1 << 0)
    +#define VIRTIO_MMIO_INT_CONFIG             (1 << 1)
    +
    +#endif /* __VIRTIO_MMIO_H__ */
    diff --git a/plat/drivers/virtio/virtio_mmio.c 
b/plat/drivers/virtio/virtio_mmio.c
    new file mode 100644
    index 0000000..d57cdb1
    --- /dev/null
    +++ b/plat/drivers/virtio/virtio_mmio.c
    @@ -0,0 +1,493 @@
    +/* SPDX-License-Identifier: BSD-3-Clause */
    +/*
    + * Authors: Jia He <justin.he@xxxxxxx>
    + *
    + * Copyright (c) 2018, Arm Ltd. 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.
    + *
    + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
    + */
    +
    +#include <uk/config.h>
    +#include <uk/arch/types.h>
    +#include <errno.h>
    +#include <string.h>
    +#include <uk/alloc.h>
    +#include <uk/print.h>
    +#include <uk/plat/lcpu.h>
    +#include <uk/plat/irq.h>
    +#include <uk/bus.h>
    +#include <uk/bitops.h>
    +
    +#include <platform_bus.h>
    +#include <virtio/virtio_config.h>
    +#include <virtio/virtio_bus.h>
    +#include <virtio/virtqueue.h>
    +#include <virtio/virtio_mmio.h>
    +#include <uk/essentials.h>
    +
    +/*
    + * The alignment to use between consumer and producer parts of vring.
    + * Currently hardcoded to the page size.
    + */
    +#define VIRTIO_MMIO_VRING_ALIGN            __PAGE_SIZE
    +
    +static struct uk_alloc *a;
    +struct virtio_mmio_device_id {
    +   uint16_t device_id;
    +   uint32_t vendor;
    +};
    +
    +struct virtio_mmio_device {
    +   struct virtio_dev vdev;
    +   char *name;
    +   struct virtio_mmio_device_id  id;
    +   struct virtio_mmio_driver     *drv;
    +   unsigned long version;
    +   unsigned long irq;
    +   void *base;
    +   struct pf_device *pfdev;
    +};
    +
    +#define to_virtio_mmio_device(_dev) \
    +   __containerof(_dev, struct virtio_mmio_device, vdev)
    +
    +struct virtio_mmio_vq_info {
    +   /* the actual virtqueue */
    +   struct virtqueue *vq;
    +};
    +
    +typedef void vq_callback_t(struct virtqueue *);
    +
    +/* Configuration interface */
    +
    +static __u64 vm_get_features(struct virtio_dev *vdev)
    +{
    +   struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
    +   __u64 features = 0;
    +
    +   virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES_SEL, 1);
    +   features = virtio_cread32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES);
    +   features <<= 32;
    +
    +   virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES_SEL, 0);
    +   features |= virtio_cread32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES);
    +
    +   return features;
    +}
    +
    +static void vm_set_features(struct virtio_dev *vdev,
    +                                    __u64 features)
    +{
    +   struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
    +
    +   /* Give virtio_ring a chance to accept features. */
    +   virtqueue_feature_negotiate(features);
    +
    +   /* Make sure there is are no mixed devices */
    +   if (vm_dev->version == 2 &&
    +           !uk_test_bit(VIRTIO_F_VERSION_1, &vdev->features)) {
    +           uk_pr_err("New virtio-mmio dev(version 2) must provide"
    +                     " VIRTIO_F_VERSION_1 feature!\n");
    +           return;
    +   }
    +
    +   virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES_SEL, 1);
    +   virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES,
    +                                           (__u32)(vdev->features >> 32));
    +
    +   virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES_SEL, 0);
    +   virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES,
    +                                           (__u32)vdev->features);
    +}
    +
    +static int vm_get(struct virtio_dev *vdev, __u16 offset,
    +              void *buf, __u32 len, __u8 type_len __unused)
    +{
    +   struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
    +   void *base = vm_dev->base + VIRTIO_MMIO_CONFIG;
    +   __u8 b;
    +   __u16 w;
    +   __u32 l;
    +
    +   if (vm_dev->version == 1) {
    +           __u8 *ptr = buf;
    +           unsigned int i;
    +
    +           for (i = 0; i < len; i++)
    +                   ptr[i] = virtio_cread8(base, offset + i);
    +           return 0;
    +   }
    +
    +   switch (len) {
    +   case 1:
    +           b = virtio_cread8(base, offset);
    +           memcpy(buf, &b, sizeof(b));
    +           break;
    +   case 2:
    +           w = (virtio_cread16(base, offset));
    +           memcpy(buf, &w, sizeof(w));
    +           break;
    +   case 4:
    +           l = (virtio_cread32(base, offset));
    +           memcpy(buf, &l, sizeof(l));
    +           break;
    +   case 8:
    +           l = (virtio_cread32(base, offset));
    +           memcpy(buf, &l, sizeof(l));
    +           l = (virtio_cread32(base, offset + sizeof(l)));
    +           memcpy(buf + sizeof(l), &l, sizeof(l));
    +           break;
    +   default:
    +           uk_pr_err("Not supported length(%d) for io read\n", len);
    +           UK_BUG();
    +   }
    +
    +   return 0;
    +}
    +
    +static int vm_set(struct virtio_dev *vdev, __u16 offset,
    +              const void *buf, __u32 len)
    +{
    +   struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
    +   void *base = vm_dev->base + VIRTIO_MMIO_CONFIG;
    +   __u8 b;
    +   __u16 w;
    +   __u32 l;
    +
    +   if (vm_dev->version == 1) {
    +           const __u8 *ptr = buf;
    +           __u32 i;
    +
    +           for (i = 0; i < len; i++)
    +                   virtio_cwrite8(base, offset + i, ptr[i]);
    +           return 0;
    +   }
    +
    +   switch (len) {
    +   case 1:
    +           memcpy(&b, buf, sizeof(b));
    +           virtio_cwrite8(base, offset, b);
    +           break;
    +   case 2:
    +           memcpy(&w, buf, sizeof(w));
    +           virtio_cwrite16(base, offset, w);
    +           break;
    +   case 4:
    +           memcpy(&l, buf, sizeof(l));
    +           virtio_cwrite32(base, offset, l);
    +           break;
    +   case 8:
    +           memcpy(&l, buf, sizeof(l));
    +           virtio_cwrite32(base, offset, l);
    +           memcpy(&l, buf + sizeof(l), sizeof(l));
    +           virtio_cwrite32(base, offset + sizeof(l), l);
    +           break;
    +   default:
    +           uk_pr_err("Not supported length(%d) for io write\n", len);
    +           UK_BUG();
    +   }
    +
    +   return 0;
    +}
    +
    +static __u8 vm_get_status(struct virtio_dev *vdev)
    +{
    +   struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
    +
    +   return virtio_cread32(vm_dev->base, VIRTIO_MMIO_STATUS) & 0xff;
    +}
    +
    +static void vm_set_status(struct virtio_dev *vdev, __u8 status)
    +{
    +   struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
    +
    +   /* We should never be setting status to 0. */
    +   UK_BUGON(status == 0);
    +
    +   virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_STATUS, status);
    +}
    +
    +static void vm_reset(struct virtio_dev *vdev)
    +{
    +   struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
    +
    +   /* 0 status means a reset. */
    +   virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_STATUS, 0);
    +}
    +
    +/* Transport interface */
    +
    +/* the notify function used when creating a virt queue */
    +static int vm_notify(struct virtio_dev *vdev, __u16 queue_id)
    +{
    +   struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
    +
    +   /*
    +    * We write the queue's selector into the notification register to
    +    * signal the other end
    +    */
    +   virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_NOTIFY, queue_id);
    +   return 1;
    +}
    +
    +/* Notify all virtqueues on an interrupt. */
    +static int vm_interrupt(void *opaque)
    +{
    +   struct virtio_mmio_device *vm_dev = opaque;
    +   unsigned long status;
    +   unsigned long flags;
    +   int rc = 0;
    +   struct virtqueue *vq;
    +
    +   /* Read and acknowledge interrupts */
    +   status = virtio_cread32(vm_dev->base, VIRTIO_MMIO_INTERRUPT_STATUS);
    +   virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_INTERRUPT_ACK, status);
    +
    +   if (unlikely(status & VIRTIO_MMIO_INT_CONFIG)) {
    +           uk_pr_warn("Unsupported cfg change interrupt recved(%p)\n",
    +                      vm_dev);
    +   }
    +
    +   if (likely(status & VIRTIO_MMIO_INT_VRING)) {
    +           flags = ukplat_lcpu_save_irqf();
    +           UK_TAILQ_FOREACH(vq, &vm_dev->vdev.vqs, next) {
    +                   rc |= virtqueue_ring_interrupt(vq);
    +           }
    +           ukplat_lcpu_restore_irqf(flags);
    +   }
    +
    +   return rc;
    +}
    +
    +
    +static struct virtqueue *vm_setup_vq(struct virtio_dev *vdev,
    +                                   __u16 queue_id,
    +                                   __u16 num_desc,
    +                                   virtqueue_callback_t callback,
    +                                   struct uk_alloc *a)
    +{
    +   struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
    +   struct virtqueue *vq;
    +   unsigned long flags;
    +   void *base = vm_dev->base;
    +
    +   /* Create the vring */
    +   vq = virtqueue_create(queue_id, num_desc, VIRTIO_MMIO_VRING_ALIGN,
    +                         callback, vm_notify, vdev, a);
    +
    +   if (PTRISERR(vq)) {
    +           uk_pr_err("Failed to create the virtqueue: %d\n",
    +                     PTR2ERR(vq));
    +
No need of this goto here, as you are only returning a single value, and this 
is the only failure point in the function
    +           goto err_exit;
    +   }
    +
    +   /* Select the queue we're interested in */
    +   virtio_cwrite32(base, VIRTIO_MMIO_QUEUE_SEL, queue_id);
    +
    +   /* Activate the queue */
    +   virtio_cwrite32(base, VIRTIO_MMIO_QUEUE_NUM,
    +                   (__u32)virtqueue_vring_get_num(vq));
    +
    +   if (vm_dev->version == 1) {
    +           virtio_cwrite32(base, VIRTIO_MMIO_QUEUE_ALIGN,
    +                           __PAGE_SIZE);
    +           virtio_cwrite32(base, VIRTIO_MMIO_QUEUE_PFN,
    +                           virtqueue_physaddr(vq) >> __PAGE_SHIFT);
    +   } else {
    +           __u64 addr;
    +
    +           addr = virtqueue_physaddr(vq);
    +           virtio_cwrite32(base, VIRTIO_MMIO_QUEUE_DESC_LOW, (__u32)addr);
    +           virtio_cwrite32(base, VIRTIO_MMIO_QUEUE_DESC_HIGH,
    +                           (__u32)(addr >> 32));
    +
    +           addr = virtqueue_get_avail_addr(vq);
    +           virtio_cwrite32(base, VIRTIO_MMIO_QUEUE_AVAIL_LOW, (__u32)addr);
    +           virtio_cwrite32(base, VIRTIO_MMIO_QUEUE_AVAIL_HIGH,
    +                           (__u32)(addr >> 32));
    +
    +           addr =  virtqueue_get_used_addr(vq);
    +           virtio_cwrite32(base, VIRTIO_MMIO_QUEUE_USED_LOW, (__u32)addr);
    +           virtio_cwrite32(base, VIRTIO_MMIO_QUEUE_USED_HIGH,
    +                           (__u32)(addr >> 32));
    +
    +           virtio_cwrite32(base, VIRTIO_MMIO_QUEUE_READY, 1);
    +   }
    +
    +   flags = ukplat_lcpu_save_irqf();
    +   UK_TAILQ_INSERT_TAIL(&vm_dev->vdev.vqs, vq, next);
    +   ukplat_lcpu_restore_irqf(flags);
    +
    +err_exit:
    +   return vq;
    +}
    +
    +static int vm_find_vqs(struct virtio_dev *vdev, __u16 num_vqs,
    +                   __u16 *qdesc_size)
    +{
    +   struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
    +   unsigned int irq = vm_dev->pfdev->irq;
    +   int i, err;
    +   int vq_cnt = 0;
    +
    +   err = ukplat_irq_register(irq, vm_interrupt, vm_dev);
    +   if (err)
Why not "goto error_exit"? like the other error points in this function?
    +           return err;
    +
    +   for (i = 0; i < num_vqs; ++i) {
    +           /* Select the queue we're interested in */
    +           virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_SEL, i);
    +
    +           /* Queue shouldn't already be set up. */
    +           if (virtio_cread32(vm_dev->base, (vm_dev->version == 1 ?
    +                   VIRTIO_MMIO_QUEUE_PFN : VIRTIO_MMIO_QUEUE_READY))) {
    +                   uk_pr_err("vm find vqs error mmio queue not ready\n");
    +
    +                   err = -ENOENT;
    +                   goto error_exit;
    +           }
    +
    +           qdesc_size[i] = virtio_cread32(vm_dev->base,
    +                                           VIRTIO_MMIO_QUEUE_NUM_MAX);
    +           if (qdesc_size[i] == 0) {
    +                   err = -ENOENT;
    +                   goto error_exit;
    +           }
    +
    +           vq_cnt++;
    +   }
    +
    +   return vq_cnt;
    +error_exit:
    +   uk_pr_err("err in vm find vqs :%d\n", err);
    +   return err;
    +}
    +
    +static struct virtio_config_ops virtio_mmio_config_ops = {
    +   .config_get     = vm_get,
    +   .config_set     = vm_set,
    +   .status_get     = vm_get_status,
    +   .status_set     = vm_set_status,
    +   .device_reset   = vm_reset,
    +   .features_get   = vm_get_features,
    +   .features_set   = vm_set_features,
    +   .vqs_find       = vm_find_vqs,
    +   .vq_setup       = vm_setup_vq,
    +};
    +
    +static int virtio_mmio_add_dev(struct pf_device *pfdev)
    +{
    +   struct virtio_mmio_device *vm_dev;
    +   unsigned int magic;
    +   int rc;
    +
    +   UK_ASSERT(pfdev != NULL);
    +   uk_pr_info("virtiommio add dev\n");
    +
    +   vm_dev = uk_malloc(a, sizeof(*vm_dev));
    +   if (!vm_dev) {
    +           uk_pr_err("Failed to allocate virtio-pci device\n");
    +           return -ENOMEM;
    +   }
    +
    +   /* Fetch Pf Device information */
    +   vm_dev->pfdev = pfdev;
    +   vm_dev->base = (void *)pfdev->base;
    +   vm_dev->vdev.cops = &virtio_mmio_config_ops;
    +   vm_dev->name = "virtio_mmio";
    +
    +   if (vm_dev->base == NULL)
    +           return -EFAULT;
    +
    +   magic = virtio_cread32(vm_dev->base, VIRTIO_MMIO_MAGIC_VALUE);
Please encode this magic number (i.e., ('v' | 'I' ....) in a #define somewhere 
at the top of this file o
    +   if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) {
    +           uk_pr_err("Wrong magic value 0x%x!\n", magic);
    +           return -ENODEV;
    +   }
    +
    +   /* Check device version */
    +   vm_dev->version = virtio_cread32(vm_dev->base, VIRTIO_MMIO_VERSION);
    +   if (vm_dev->version < 1 || vm_dev->version > 2) {
    +           uk_pr_err("Version %ld not supported!\n", vm_dev->version);
    +           return -ENXIO;
    +   }
    +
    +   vm_dev->vdev.id.virtio_device_id = virtio_cread32(vm_dev->base,
    +                                                   VIRTIO_MMIO_DEVICE_ID);
    +   if (vm_dev->vdev.id.virtio_device_id == 0) {
    +           /*
    +            * virtio-mmio device with an ID 0 is a (dummy) placeholder
    +            * with no function. End probing now with no error reported.
    +            */
    +           uk_pr_err("virtio_device_id is 0\n");
    +
    +           return -ENODEV;
    +   }
    +   vm_dev->id.vendor = virtio_cread32(vm_dev->base, VIRTIO_MMIO_VENDOR_ID);
    +
    +   virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_GUEST_PAGE_SIZE, __PAGE_SIZE);
    +
    +   rc = virtio_bus_register_device(&vm_dev->vdev);
    +   if (rc != 0) {
    +           uk_pr_err("Failed to register the virtio device: %d\n", rc);
No need of this goto here, as it is the only point in the function where you 
are jumping to free_pf_dev label. You might just as well put the code under the 
label here and return.
    +           goto free_pf_dev;
    +   }
    +
    +   uk_pr_info("finish add a virtio mmio dev\n");
    +
    +   return rc;
    +
    +free_pf_dev:
    +   uk_free(a, vm_dev);
    +
    +   return 0;
    +}
    +
    +static int virtio_mmio_drv_init(struct uk_alloc *drv_allocator)
    +{
    +   /* driver initialization */
    +   if (!drv_allocator)
    +           return -EINVAL;
    +
    +   a = drv_allocator;
    +
    +   return 0;
    +}
    +
    +static const struct pf_device_id virtio_mmio_ids = {
    +           .device_id = VIRTIO_MMIO_ID
    +};
    +
    +static struct pf_driver virtio_mmio_drv = {
    +   .device_ids = &virtio_mmio_ids,
    +   .init = virtio_mmio_drv_init,
    +   .add_dev = virtio_mmio_add_dev
    +};
    +
    +PF_REGISTER_DRIVER(&virtio_mmio_drv);
    -- 
    2.17.1
    
    
    _______________________________________________
    Minios-devel mailing list
    Minios-devel@xxxxxxxxxxxxxxxxxxxx
    https://lists.xenproject.org/mailman/listinfo/minios-devel

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