4 * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/types.h>
38 #include "virtio_logs.h"
39 #include "virtio_pci.h"
40 #include "virtqueue.h"
41 #include "virtio_user/virtio_user_dev.h"
43 #define virtio_user_get_dev(hw) \
44 ((struct virtio_user_dev *)(hw)->virtio_user_dev)
47 virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset,
48 void *dst, int length)
51 struct virtio_user_dev *dev = virtio_user_get_dev(hw);
53 if (offset == offsetof(struct virtio_net_config, mac) &&
54 length == ETHER_ADDR_LEN) {
55 for (i = 0; i < ETHER_ADDR_LEN; ++i)
56 ((uint8_t *)dst)[i] = dev->mac_addr[i];
60 if (offset == offsetof(struct virtio_net_config, status))
61 *(uint16_t *)dst = dev->status;
63 if (offset == offsetof(struct virtio_net_config, max_virtqueue_pairs))
64 *(uint16_t *)dst = dev->max_queue_pairs;
68 virtio_user_write_dev_config(struct virtio_hw *hw, size_t offset,
69 const void *src, int length)
72 struct virtio_user_dev *dev = virtio_user_get_dev(hw);
74 if ((offset == offsetof(struct virtio_net_config, mac)) &&
75 (length == ETHER_ADDR_LEN))
76 for (i = 0; i < ETHER_ADDR_LEN; ++i)
77 dev->mac_addr[i] = ((const uint8_t *)src)[i];
79 PMD_DRV_LOG(ERR, "not supported offset=%" PRIu64 ", len=%d\n",
84 virtio_user_set_status(struct virtio_hw *hw, uint8_t status)
86 struct virtio_user_dev *dev = virtio_user_get_dev(hw);
88 if (status & VIRTIO_CONFIG_STATUS_DRIVER_OK)
89 virtio_user_start_device(dev);
94 virtio_user_reset(struct virtio_hw *hw)
96 struct virtio_user_dev *dev = virtio_user_get_dev(hw);
98 virtio_user_stop_device(dev);
102 virtio_user_get_status(struct virtio_hw *hw)
104 struct virtio_user_dev *dev = virtio_user_get_dev(hw);
110 virtio_user_get_features(struct virtio_hw *hw)
112 struct virtio_user_dev *dev = virtio_user_get_dev(hw);
114 return dev->features;
118 virtio_user_set_features(struct virtio_hw *hw, uint64_t features)
120 struct virtio_user_dev *dev = virtio_user_get_dev(hw);
122 dev->features = features;
126 virtio_user_get_isr(struct virtio_hw *hw __rte_unused)
128 /* When config interrupt happens, driver calls this function to query
129 * what kinds of change happen. Interrupt mode not supported for now.
135 virtio_user_set_config_irq(struct virtio_hw *hw __rte_unused,
136 uint16_t vec __rte_unused)
138 return VIRTIO_MSI_NO_VECTOR;
141 /* This function is to get the queue size, aka, number of descs, of a specified
142 * queue. Different with the VHOST_USER_GET_QUEUE_NUM, which is used to get the
143 * max supported queues.
146 virtio_user_get_queue_num(struct virtio_hw *hw, uint16_t queue_id __rte_unused)
148 struct virtio_user_dev *dev = virtio_user_get_dev(hw);
150 /* Currently, each queue has same queue size */
151 return dev->queue_size;
155 virtio_user_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
157 struct virtio_user_dev *dev = virtio_user_get_dev(hw);
158 uint16_t queue_idx = vq->vq_queue_index;
159 uint64_t desc_addr, avail_addr, used_addr;
161 desc_addr = (uintptr_t)vq->vq_ring_virt_mem;
162 avail_addr = desc_addr + vq->vq_nentries * sizeof(struct vring_desc);
163 used_addr = RTE_ALIGN_CEIL(avail_addr + offsetof(struct vring_avail,
164 ring[vq->vq_nentries]),
165 VIRTIO_PCI_VRING_ALIGN);
167 dev->vrings[queue_idx].num = vq->vq_nentries;
168 dev->vrings[queue_idx].desc = (void *)(uintptr_t)desc_addr;
169 dev->vrings[queue_idx].avail = (void *)(uintptr_t)avail_addr;
170 dev->vrings[queue_idx].used = (void *)(uintptr_t)used_addr;
176 virtio_user_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
178 /* For legacy devices, write 0 to VIRTIO_PCI_QUEUE_PFN port, QEMU
179 * correspondingly stops the ioeventfds, and reset the status of
181 * For modern devices, set queue desc, avail, used in PCI bar to 0,
182 * not see any more behavior in QEMU.
184 * Here we just care about what information to deliver to vhost-user
185 * or vhost-kernel. So we just close ioeventfd for now.
187 struct virtio_user_dev *dev = virtio_user_get_dev(hw);
189 close(dev->callfds[vq->vq_queue_index]);
190 close(dev->kickfds[vq->vq_queue_index]);
194 virtio_user_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
197 struct virtio_user_dev *dev = virtio_user_get_dev(hw);
199 if (write(dev->kickfds[vq->vq_queue_index], &buf, sizeof(buf)) < 0)
200 PMD_DRV_LOG(ERR, "failed to kick backend: %s\n",
204 static const struct virtio_pci_ops virtio_user_ops = {
205 .read_dev_cfg = virtio_user_read_dev_config,
206 .write_dev_cfg = virtio_user_write_dev_config,
207 .reset = virtio_user_reset,
208 .get_status = virtio_user_get_status,
209 .set_status = virtio_user_set_status,
210 .get_features = virtio_user_get_features,
211 .set_features = virtio_user_set_features,
212 .get_isr = virtio_user_get_isr,
213 .set_config_irq = virtio_user_set_config_irq,
214 .get_queue_num = virtio_user_get_queue_num,
215 .setup_queue = virtio_user_setup_queue,
216 .del_queue = virtio_user_del_queue,
217 .notify_queue = virtio_user_notify_queue,