From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id 5CECB58E1 for ; Fri, 29 Apr 2016 03:18:49 +0200 (CEST) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga103.jf.intel.com with ESMTP; 28 Apr 2016 18:18:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.24,549,1455004800"; d="scan'208";a="694039337" Received: from dpdk06.sh.intel.com ([10.239.128.225]) by FMSMGA003.fm.intel.com with ESMTP; 28 Apr 2016 18:18:47 -0700 From: Jianfeng Tan To: dev@dpdk.org Cc: Jianfeng Tan , Huawei Xie , rich.lane@bigswitch.com, yuanhan.liu@linux.intel.com, mst@redhat.com, nakajima.yoshihiro@lab.ntt.co.jp, p.fedin@samsung.com, michael.qiu@intel.com, ann.zhuangyanying@huawei.com, mukawa@igel.co.jp, nhorman@tuxdriver.com Date: Fri, 29 Apr 2016 01:18:34 +0000 Message-Id: <1461892716-19122-7-git-send-email-jianfeng.tan@intel.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1461892716-19122-1-git-send-email-jianfeng.tan@intel.com> References: <1446748276-132087-1-git-send-email-jianfeng.tan@intel.com> <1461892716-19122-1-git-send-email-jianfeng.tan@intel.com> Subject: [dpdk-dev] [PATCH v4 6/8] virtio-user: add new virtual pci driver for virtio X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 29 Apr 2016 01:18:49 -0000 This patch implements another new instance of struct virtio_pci_ops to drive the virtio-user virtual device. Instead of rd/wr ioport or PCI configuration space, this virtual pci driver will rd/wr the virtual device struct virtio_user_hw, and when necessary, invokes APIs provided by device emulation later to start/stop the device. ---------------------- | ------------------ | | | virtio driver | |----> (virtio_user_pci.c) | ------------------ | | | | | ------------------ | ------> virtio-user PMD | | device emulate | | | | | | | | vhost adapter | | | ------------------ | ---------------------- | | | ------------------ | vhost backend | ------------------ Signed-off-by: Huawei Xie Signed-off-by: Jianfeng Tan Acked-By: Neil Horman --- drivers/net/virtio/Makefile | 1 + drivers/net/virtio/virtio_user/virtio_user_dev.h | 2 + drivers/net/virtio/virtio_user/virtio_user_pci.c | 209 +++++++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 drivers/net/virtio/virtio_user/virtio_user_pci.c diff --git a/drivers/net/virtio/Makefile b/drivers/net/virtio/Makefile index 68068bd..13b2b75 100644 --- a/drivers/net/virtio/Makefile +++ b/drivers/net/virtio/Makefile @@ -60,6 +60,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_user/vhost.c SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_user/vhost_user.c SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_user/vhost_kernel.c SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_user/virtio_user_dev.c +SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_user/virtio_user_pci.c endif # this lib depends upon: diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h index 76250f0..bc4dc1a 100644 --- a/drivers/net/virtio/virtio_user/virtio_user_dev.h +++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h @@ -56,4 +56,6 @@ struct virtio_user_hw { int virtio_user_start_device(struct virtio_user_hw *hw); int virtio_user_stop_device(struct virtio_user_hw *hw); +const struct virtio_pci_ops vdev_ops; + #endif diff --git a/drivers/net/virtio/virtio_user/virtio_user_pci.c b/drivers/net/virtio/virtio_user/virtio_user_pci.c new file mode 100644 index 0000000..60351d9 --- /dev/null +++ b/drivers/net/virtio/virtio_user/virtio_user_pci.c @@ -0,0 +1,209 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Intel Corporation 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 + * OWNER 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 +#include +#include + +#include "../virtio_logs.h" +#include "../virtio_pci.h" +#include "../virtqueue.h" +#include "virtio_user_dev.h" + +static void +vdev_read_dev_config(struct virtio_hw *hw, uint64_t offset, + void *dst, int length) +{ + int i; + struct virtio_user_hw *uhw = (struct virtio_user_hw *)hw->vdev_private; + + if (offset == offsetof(struct virtio_net_config, mac) && + length == ETHER_ADDR_LEN) { + for (i = 0; i < ETHER_ADDR_LEN; ++i) + ((uint8_t *)dst)[i] = uhw->mac_addr[i]; + return; + } + + if (offset == offsetof(struct virtio_net_config, status)) + *(uint16_t *)dst = uhw->status; + + if (offset == offsetof(struct virtio_net_config, max_virtqueue_pairs)) + *(uint16_t *)dst = uhw->max_queue_pairs; +} + +static void +vdev_write_dev_config(struct virtio_hw *hw, uint64_t offset, + const void *src, int length) +{ + int i; + struct virtio_user_hw *uhw = (struct virtio_user_hw *)hw->vdev_private; + + if ((offset == offsetof(struct virtio_net_config, mac)) && + (length == ETHER_ADDR_LEN)) + for (i = 0; i < ETHER_ADDR_LEN; ++i) + uhw->mac_addr[i] = ((const uint8_t *)src)[i]; + else + PMD_DRV_LOG(ERR, "not supported offset=%" PRIu64 ", length=%d", + offset, length); +} + +static void +vdev_set_status(struct virtio_hw *hw, uint8_t status) +{ + struct virtio_user_hw *uhw = (struct virtio_user_hw *)hw->vdev_private; + + if (status & VIRTIO_CONFIG_STATUS_DRIVER_OK) + virtio_user_start_device(uhw); + uhw->status = status; +} + +static void +vdev_reset(struct virtio_hw *hw) +{ + struct virtio_user_hw *uhw = (struct virtio_user_hw *)hw->vdev_private; + + virtio_user_stop_device(uhw); +} + +static uint8_t +vdev_get_status(struct virtio_hw *hw) +{ + struct virtio_user_hw *uhw = (struct virtio_user_hw *)hw->vdev_private; + + return uhw->status; +} + +static uint64_t +vdev_get_features(struct virtio_hw *hw) +{ + struct virtio_user_hw *uhw = (struct virtio_user_hw *)hw->vdev_private; + + return uhw->features; +} + +static void +vdev_set_features(struct virtio_hw *hw, uint64_t features) +{ + struct virtio_user_hw *uhw = (struct virtio_user_hw *)hw->vdev_private; + + uhw->features = features; +} + +static uint8_t +vdev_get_isr(struct virtio_hw *hw __rte_unused) +{ + /* When config interrupt happens, driver calls this function to query + * what kinds of change happen. Interrupt mode not supported for now. + */ + return 0; +} + +static uint16_t +vdev_set_config_irq(struct virtio_hw *hw __rte_unused, + uint16_t vec __rte_unused) +{ + return VIRTIO_MSI_NO_VECTOR; +} + +/* This function is to get the queue size, aka, number of descs, of a specified + * queue. Different with the VHOST_USER_GET_QUEUE_NUM, which is used to get the + * max supported queues. + */ +static uint16_t +vdev_get_queue_num(struct virtio_hw *hw, + uint16_t queue_id __rte_unused) +{ + struct virtio_user_hw *uhw = (struct virtio_user_hw *)hw->vdev_private; + + /* Currently, each queue has same queue size */ + return uhw->queue_size; +} + +static int +vdev_setup_queue(struct virtio_hw *hw __rte_unused, struct virtqueue *vq) +{ + /* Changed to use virtual addr */ + vq->vq_ring_mem = (phys_addr_t)vq->mz->addr; + if (vq->virtio_net_hdr_mz) { + vq->virtio_net_hdr_mem = + (phys_addr_t)vq->virtio_net_hdr_mz->addr; + /* Do it one more time after we reset virtio_net_hdr_mem */ + vring_hdr_desc_init(vq); + } + vq->offset = offsetof(struct rte_mbuf, buf_addr); + return 0; +} + +static void +vdev_del_queue(struct virtio_hw *hw, struct virtqueue *vq) +{ + /* For legacy devices, write 0 to VIRTIO_PCI_QUEUE_PFN port, QEMU + * correspondingly stops the ioeventfds, and reset the status of + * the device. + * For modern devices, set queue desc, avail, used in PCI bar to 0, + * not see any more behavior in QEMU. + * + * Here we just care about what information to deliver to vhost-user + * or vhost-kernel. And we just close ioeventfd for now. + */ + struct virtio_user_hw *uhw = (struct virtio_user_hw *)hw->vdev_private; + + close(uhw->callfds[vq->vq_queue_index]); + close(uhw->kickfds[vq->vq_queue_index]); +} + +static void +vdev_notify_queue(struct virtio_hw *hw, struct virtqueue *vq) +{ + uint64_t buf = 1; + struct virtio_user_hw *uhw = (struct virtio_user_hw *)hw->vdev_private; + + if (write(uhw->kickfds[vq->vq_queue_index], &buf, sizeof(buf)) < 0) + PMD_DRV_LOG(ERR, "failed to kick backend: %d", strerror(errno)); +} + +const struct virtio_pci_ops vdev_ops = { + .read_dev_cfg = vdev_read_dev_config, + .write_dev_cfg = vdev_write_dev_config, + .reset = vdev_reset, + .get_status = vdev_get_status, + .set_status = vdev_set_status, + .get_features = vdev_get_features, + .set_features = vdev_set_features, + .get_isr = vdev_get_isr, + .set_config_irq = vdev_set_config_irq, + .get_queue_num = vdev_get_queue_num, + .setup_queue = vdev_setup_queue, + .del_queue = vdev_del_queue, + .notify_queue = vdev_notify_queue, +}; -- 2.1.4