xref: /qemu/hw/virtio/vhost-vdpa.c (revision 108a64818e69be0a97cde3838d768f2d9910c08b)
1*108a6481SCindy Lu /*
2*108a6481SCindy Lu  * vhost-vdpa
3*108a6481SCindy Lu  *
4*108a6481SCindy Lu  *  Copyright(c) 2017-2018 Intel Corporation.
5*108a6481SCindy Lu  *  Copyright(c) 2020 Red Hat, Inc.
6*108a6481SCindy Lu  *
7*108a6481SCindy Lu  * This work is licensed under the terms of the GNU GPL, version 2 or later.
8*108a6481SCindy Lu  * See the COPYING file in the top-level directory.
9*108a6481SCindy Lu  *
10*108a6481SCindy Lu  */
11*108a6481SCindy Lu 
12*108a6481SCindy Lu #include "qemu/osdep.h"
13*108a6481SCindy Lu #include <linux/vhost.h>
14*108a6481SCindy Lu #include <linux/vfio.h>
15*108a6481SCindy Lu #include <sys/eventfd.h>
16*108a6481SCindy Lu #include <sys/ioctl.h>
17*108a6481SCindy Lu #include "hw/virtio/vhost.h"
18*108a6481SCindy Lu #include "hw/virtio/vhost-backend.h"
19*108a6481SCindy Lu #include "hw/virtio/virtio-net.h"
20*108a6481SCindy Lu #include "hw/virtio/vhost-vdpa.h"
21*108a6481SCindy Lu #include "qemu/main-loop.h"
22*108a6481SCindy Lu #include <linux/kvm.h>
23*108a6481SCindy Lu #include "sysemu/kvm.h"
24*108a6481SCindy Lu 
25*108a6481SCindy Lu static bool vhost_vdpa_listener_skipped_section(MemoryRegionSection *section)
26*108a6481SCindy Lu {
27*108a6481SCindy Lu     return (!memory_region_is_ram(section->mr) &&
28*108a6481SCindy Lu             !memory_region_is_iommu(section->mr)) ||
29*108a6481SCindy Lu            /*
30*108a6481SCindy Lu             * Sizing an enabled 64-bit BAR can cause spurious mappings to
31*108a6481SCindy Lu             * addresses in the upper part of the 64-bit address space.  These
32*108a6481SCindy Lu             * are never accessed by the CPU and beyond the address width of
33*108a6481SCindy Lu             * some IOMMU hardware.  TODO: VDPA should tell us the IOMMU width.
34*108a6481SCindy Lu             */
35*108a6481SCindy Lu            section->offset_within_address_space & (1ULL << 63);
36*108a6481SCindy Lu }
37*108a6481SCindy Lu 
38*108a6481SCindy Lu static int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size,
39*108a6481SCindy Lu                               void *vaddr, bool readonly)
40*108a6481SCindy Lu {
41*108a6481SCindy Lu     struct vhost_msg_v2 msg;
42*108a6481SCindy Lu     int fd = v->device_fd;
43*108a6481SCindy Lu     int ret = 0;
44*108a6481SCindy Lu 
45*108a6481SCindy Lu     msg.type = v->msg_type;
46*108a6481SCindy Lu     msg.iotlb.iova = iova;
47*108a6481SCindy Lu     msg.iotlb.size = size;
48*108a6481SCindy Lu     msg.iotlb.uaddr = (uint64_t)(uintptr_t)vaddr;
49*108a6481SCindy Lu     msg.iotlb.perm = readonly ? VHOST_ACCESS_RO : VHOST_ACCESS_RW;
50*108a6481SCindy Lu     msg.iotlb.type = VHOST_IOTLB_UPDATE;
51*108a6481SCindy Lu 
52*108a6481SCindy Lu     if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) {
53*108a6481SCindy Lu         error_report("failed to write, fd=%d, errno=%d (%s)",
54*108a6481SCindy Lu             fd, errno, strerror(errno));
55*108a6481SCindy Lu         return -EIO ;
56*108a6481SCindy Lu     }
57*108a6481SCindy Lu 
58*108a6481SCindy Lu     return ret;
59*108a6481SCindy Lu }
60*108a6481SCindy Lu 
61*108a6481SCindy Lu static int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova,
62*108a6481SCindy Lu                                 hwaddr size)
63*108a6481SCindy Lu {
64*108a6481SCindy Lu     struct vhost_msg_v2 msg;
65*108a6481SCindy Lu     int fd = v->device_fd;
66*108a6481SCindy Lu     int ret = 0;
67*108a6481SCindy Lu 
68*108a6481SCindy Lu     msg.type = v->msg_type;
69*108a6481SCindy Lu     msg.iotlb.iova = iova;
70*108a6481SCindy Lu     msg.iotlb.size = size;
71*108a6481SCindy Lu     msg.iotlb.type = VHOST_IOTLB_INVALIDATE;
72*108a6481SCindy Lu 
73*108a6481SCindy Lu     if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) {
74*108a6481SCindy Lu         error_report("failed to write, fd=%d, errno=%d (%s)",
75*108a6481SCindy Lu             fd, errno, strerror(errno));
76*108a6481SCindy Lu         return -EIO ;
77*108a6481SCindy Lu     }
78*108a6481SCindy Lu 
79*108a6481SCindy Lu     return ret;
80*108a6481SCindy Lu }
81*108a6481SCindy Lu 
82*108a6481SCindy Lu static void vhost_vdpa_listener_region_add(MemoryListener *listener,
83*108a6481SCindy Lu                                            MemoryRegionSection *section)
84*108a6481SCindy Lu {
85*108a6481SCindy Lu     struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener);
86*108a6481SCindy Lu     hwaddr iova;
87*108a6481SCindy Lu     Int128 llend, llsize;
88*108a6481SCindy Lu     void *vaddr;
89*108a6481SCindy Lu     int ret;
90*108a6481SCindy Lu 
91*108a6481SCindy Lu     if (vhost_vdpa_listener_skipped_section(section)) {
92*108a6481SCindy Lu         return;
93*108a6481SCindy Lu     }
94*108a6481SCindy Lu 
95*108a6481SCindy Lu     if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) !=
96*108a6481SCindy Lu                  (section->offset_within_region & ~TARGET_PAGE_MASK))) {
97*108a6481SCindy Lu         error_report("%s received unaligned region", __func__);
98*108a6481SCindy Lu         return;
99*108a6481SCindy Lu     }
100*108a6481SCindy Lu 
101*108a6481SCindy Lu     iova = TARGET_PAGE_ALIGN(section->offset_within_address_space);
102*108a6481SCindy Lu     llend = int128_make64(section->offset_within_address_space);
103*108a6481SCindy Lu     llend = int128_add(llend, section->size);
104*108a6481SCindy Lu     llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));
105*108a6481SCindy Lu 
106*108a6481SCindy Lu     if (int128_ge(int128_make64(iova), llend)) {
107*108a6481SCindy Lu         return;
108*108a6481SCindy Lu     }
109*108a6481SCindy Lu 
110*108a6481SCindy Lu     memory_region_ref(section->mr);
111*108a6481SCindy Lu 
112*108a6481SCindy Lu     /* Here we assume that memory_region_is_ram(section->mr)==true */
113*108a6481SCindy Lu 
114*108a6481SCindy Lu     vaddr = memory_region_get_ram_ptr(section->mr) +
115*108a6481SCindy Lu             section->offset_within_region +
116*108a6481SCindy Lu             (iova - section->offset_within_address_space);
117*108a6481SCindy Lu 
118*108a6481SCindy Lu     llsize = int128_sub(llend, int128_make64(iova));
119*108a6481SCindy Lu 
120*108a6481SCindy Lu     ret = vhost_vdpa_dma_map(v, iova, int128_get64(llsize),
121*108a6481SCindy Lu                              vaddr, section->readonly);
122*108a6481SCindy Lu     if (ret) {
123*108a6481SCindy Lu         error_report("vhost vdpa map fail!");
124*108a6481SCindy Lu         if (memory_region_is_ram_device(section->mr)) {
125*108a6481SCindy Lu             /* Allow unexpected mappings not to be fatal for RAM devices */
126*108a6481SCindy Lu             error_report("map ram fail!");
127*108a6481SCindy Lu           return ;
128*108a6481SCindy Lu         }
129*108a6481SCindy Lu         goto fail;
130*108a6481SCindy Lu     }
131*108a6481SCindy Lu 
132*108a6481SCindy Lu     return;
133*108a6481SCindy Lu 
134*108a6481SCindy Lu fail:
135*108a6481SCindy Lu     if (memory_region_is_ram_device(section->mr)) {
136*108a6481SCindy Lu         error_report("failed to vdpa_dma_map. pci p2p may not work");
137*108a6481SCindy Lu         return;
138*108a6481SCindy Lu 
139*108a6481SCindy Lu     }
140*108a6481SCindy Lu     /*
141*108a6481SCindy Lu      * On the initfn path, store the first error in the container so we
142*108a6481SCindy Lu      * can gracefully fail.  Runtime, there's not much we can do other
143*108a6481SCindy Lu      * than throw a hardware error.
144*108a6481SCindy Lu      */
145*108a6481SCindy Lu     error_report("vhost-vdpa: DMA mapping failed, unable to continue");
146*108a6481SCindy Lu     return;
147*108a6481SCindy Lu 
148*108a6481SCindy Lu }
149*108a6481SCindy Lu 
150*108a6481SCindy Lu static void vhost_vdpa_listener_region_del(MemoryListener *listener,
151*108a6481SCindy Lu                                            MemoryRegionSection *section)
152*108a6481SCindy Lu {
153*108a6481SCindy Lu     struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener);
154*108a6481SCindy Lu     hwaddr iova;
155*108a6481SCindy Lu     Int128 llend, llsize;
156*108a6481SCindy Lu     int ret;
157*108a6481SCindy Lu     bool try_unmap = true;
158*108a6481SCindy Lu 
159*108a6481SCindy Lu     if (vhost_vdpa_listener_skipped_section(section)) {
160*108a6481SCindy Lu         return;
161*108a6481SCindy Lu     }
162*108a6481SCindy Lu 
163*108a6481SCindy Lu     if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) !=
164*108a6481SCindy Lu                  (section->offset_within_region & ~TARGET_PAGE_MASK))) {
165*108a6481SCindy Lu         error_report("%s received unaligned region", __func__);
166*108a6481SCindy Lu         return;
167*108a6481SCindy Lu     }
168*108a6481SCindy Lu 
169*108a6481SCindy Lu     iova = TARGET_PAGE_ALIGN(section->offset_within_address_space);
170*108a6481SCindy Lu     llend = int128_make64(section->offset_within_address_space);
171*108a6481SCindy Lu     llend = int128_add(llend, section->size);
172*108a6481SCindy Lu     llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));
173*108a6481SCindy Lu 
174*108a6481SCindy Lu     if (int128_ge(int128_make64(iova), llend)) {
175*108a6481SCindy Lu         return;
176*108a6481SCindy Lu     }
177*108a6481SCindy Lu 
178*108a6481SCindy Lu     llsize = int128_sub(llend, int128_make64(iova));
179*108a6481SCindy Lu 
180*108a6481SCindy Lu     if (try_unmap) {
181*108a6481SCindy Lu         ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize));
182*108a6481SCindy Lu         if (ret) {
183*108a6481SCindy Lu             error_report("vhost_vdpa dma unmap error!");
184*108a6481SCindy Lu         }
185*108a6481SCindy Lu     }
186*108a6481SCindy Lu 
187*108a6481SCindy Lu     memory_region_unref(section->mr);
188*108a6481SCindy Lu }
189*108a6481SCindy Lu /*
190*108a6481SCindy Lu  * IOTLB API is used by vhost-vpda which requires incremental updating
191*108a6481SCindy Lu  * of the mapping. So we can not use generic vhost memory listener which
192*108a6481SCindy Lu  * depends on the addnop().
193*108a6481SCindy Lu  */
194*108a6481SCindy Lu static const MemoryListener vhost_vdpa_memory_listener = {
195*108a6481SCindy Lu     .region_add = vhost_vdpa_listener_region_add,
196*108a6481SCindy Lu     .region_del = vhost_vdpa_listener_region_del,
197*108a6481SCindy Lu };
198*108a6481SCindy Lu 
199*108a6481SCindy Lu static int vhost_vdpa_call(struct vhost_dev *dev, unsigned long int request,
200*108a6481SCindy Lu                              void *arg)
201*108a6481SCindy Lu {
202*108a6481SCindy Lu     struct vhost_vdpa *v = dev->opaque;
203*108a6481SCindy Lu     int fd = v->device_fd;
204*108a6481SCindy Lu 
205*108a6481SCindy Lu     assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
206*108a6481SCindy Lu 
207*108a6481SCindy Lu     return ioctl(fd, request, arg);
208*108a6481SCindy Lu }
209*108a6481SCindy Lu 
210*108a6481SCindy Lu static void vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status)
211*108a6481SCindy Lu {
212*108a6481SCindy Lu     uint8_t s;
213*108a6481SCindy Lu 
214*108a6481SCindy Lu     if (vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &s)) {
215*108a6481SCindy Lu         return;
216*108a6481SCindy Lu     }
217*108a6481SCindy Lu 
218*108a6481SCindy Lu     s |= status;
219*108a6481SCindy Lu 
220*108a6481SCindy Lu     vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &s);
221*108a6481SCindy Lu }
222*108a6481SCindy Lu 
223*108a6481SCindy Lu static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque)
224*108a6481SCindy Lu {
225*108a6481SCindy Lu     struct vhost_vdpa *v;
226*108a6481SCindy Lu     uint64_t features;
227*108a6481SCindy Lu     assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
228*108a6481SCindy Lu 
229*108a6481SCindy Lu     v = opaque;
230*108a6481SCindy Lu     dev->opaque =  opaque ;
231*108a6481SCindy Lu     vhost_vdpa_call(dev, VHOST_GET_FEATURES, &features);
232*108a6481SCindy Lu     dev->backend_features = features;
233*108a6481SCindy Lu     v->listener = vhost_vdpa_memory_listener;
234*108a6481SCindy Lu     v->msg_type = VHOST_IOTLB_MSG_V2;
235*108a6481SCindy Lu 
236*108a6481SCindy Lu     vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
237*108a6481SCindy Lu                                VIRTIO_CONFIG_S_DRIVER);
238*108a6481SCindy Lu 
239*108a6481SCindy Lu     return 0;
240*108a6481SCindy Lu }
241*108a6481SCindy Lu 
242*108a6481SCindy Lu static int vhost_vdpa_cleanup(struct vhost_dev *dev)
243*108a6481SCindy Lu {
244*108a6481SCindy Lu     struct vhost_vdpa *v;
245*108a6481SCindy Lu     assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
246*108a6481SCindy Lu     v = dev->opaque;
247*108a6481SCindy Lu     memory_listener_unregister(&v->listener);
248*108a6481SCindy Lu 
249*108a6481SCindy Lu     dev->opaque = NULL;
250*108a6481SCindy Lu     return 0;
251*108a6481SCindy Lu }
252*108a6481SCindy Lu 
253*108a6481SCindy Lu static int vhost_vdpa_memslots_limit(struct vhost_dev *dev)
254*108a6481SCindy Lu {
255*108a6481SCindy Lu     return INT_MAX;
256*108a6481SCindy Lu }
257*108a6481SCindy Lu 
258*108a6481SCindy Lu static int vhost_vdpa_set_mem_table(struct vhost_dev *dev,
259*108a6481SCindy Lu                                     struct vhost_memory *mem)
260*108a6481SCindy Lu {
261*108a6481SCindy Lu 
262*108a6481SCindy Lu     if (mem->padding) {
263*108a6481SCindy Lu         return -1;
264*108a6481SCindy Lu     }
265*108a6481SCindy Lu 
266*108a6481SCindy Lu     return 0;
267*108a6481SCindy Lu }
268*108a6481SCindy Lu 
269*108a6481SCindy Lu static int vhost_vdpa_set_features(struct vhost_dev *dev,
270*108a6481SCindy Lu                                    uint64_t features)
271*108a6481SCindy Lu {
272*108a6481SCindy Lu     int ret;
273*108a6481SCindy Lu     ret = vhost_vdpa_call(dev, VHOST_SET_FEATURES, &features);
274*108a6481SCindy Lu     uint8_t status = 0;
275*108a6481SCindy Lu     if (ret) {
276*108a6481SCindy Lu         return ret;
277*108a6481SCindy Lu     }
278*108a6481SCindy Lu     vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK);
279*108a6481SCindy Lu     vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status);
280*108a6481SCindy Lu 
281*108a6481SCindy Lu     return !(status & VIRTIO_CONFIG_S_FEATURES_OK);
282*108a6481SCindy Lu }
283*108a6481SCindy Lu 
284*108a6481SCindy Lu int vhost_vdpa_get_device_id(struct vhost_dev *dev,
285*108a6481SCindy Lu                                    uint32_t *device_id)
286*108a6481SCindy Lu {
287*108a6481SCindy Lu     return vhost_vdpa_call(dev, VHOST_VDPA_GET_DEVICE_ID, device_id);
288*108a6481SCindy Lu }
289*108a6481SCindy Lu 
290*108a6481SCindy Lu static int vhost_vdpa_reset_device(struct vhost_dev *dev)
291*108a6481SCindy Lu {
292*108a6481SCindy Lu     uint8_t status = 0;
293*108a6481SCindy Lu 
294*108a6481SCindy Lu     return vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &status);
295*108a6481SCindy Lu }
296*108a6481SCindy Lu 
297*108a6481SCindy Lu static int vhost_vdpa_get_vq_index(struct vhost_dev *dev, int idx)
298*108a6481SCindy Lu {
299*108a6481SCindy Lu     assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
300*108a6481SCindy Lu 
301*108a6481SCindy Lu     return idx - dev->vq_index;
302*108a6481SCindy Lu }
303*108a6481SCindy Lu 
304*108a6481SCindy Lu static int vhost_vdpa_set_vring_ready(struct vhost_dev *dev)
305*108a6481SCindy Lu {
306*108a6481SCindy Lu     int i;
307*108a6481SCindy Lu     for (i = 0; i < dev->nvqs; ++i) {
308*108a6481SCindy Lu         struct vhost_vring_state state = {
309*108a6481SCindy Lu             .index = dev->vq_index + i,
310*108a6481SCindy Lu             .num = 1,
311*108a6481SCindy Lu         };
312*108a6481SCindy Lu         vhost_vdpa_call(dev, VHOST_VDPA_SET_VRING_ENABLE, &state);
313*108a6481SCindy Lu     }
314*108a6481SCindy Lu     return 0;
315*108a6481SCindy Lu }
316*108a6481SCindy Lu 
317*108a6481SCindy Lu static int vhost_vdpa_set_config(struct vhost_dev *dev, const uint8_t *data,
318*108a6481SCindy Lu                                    uint32_t offset, uint32_t size,
319*108a6481SCindy Lu                                    uint32_t flags)
320*108a6481SCindy Lu {
321*108a6481SCindy Lu     struct vhost_vdpa_config *config;
322*108a6481SCindy Lu     int ret;
323*108a6481SCindy Lu     unsigned long config_size = offsetof(struct vhost_vdpa_config, buf);
324*108a6481SCindy Lu     config = g_malloc(size + config_size);
325*108a6481SCindy Lu     if (config == NULL) {
326*108a6481SCindy Lu         return -1;
327*108a6481SCindy Lu     }
328*108a6481SCindy Lu     config->off = offset;
329*108a6481SCindy Lu     config->len = size;
330*108a6481SCindy Lu     memcpy(config->buf, data, size);
331*108a6481SCindy Lu     ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG, config);
332*108a6481SCindy Lu     g_free(config);
333*108a6481SCindy Lu     return ret;
334*108a6481SCindy Lu }
335*108a6481SCindy Lu 
336*108a6481SCindy Lu static int vhost_vdpa_get_config(struct vhost_dev *dev, uint8_t *config,
337*108a6481SCindy Lu                                    uint32_t config_len)
338*108a6481SCindy Lu {
339*108a6481SCindy Lu     struct vhost_vdpa_config *v_config;
340*108a6481SCindy Lu     unsigned long config_size = offsetof(struct vhost_vdpa_config, buf);
341*108a6481SCindy Lu     int ret;
342*108a6481SCindy Lu 
343*108a6481SCindy Lu     v_config = g_malloc(config_len + config_size);
344*108a6481SCindy Lu     if (v_config == NULL) {
345*108a6481SCindy Lu         return -1;
346*108a6481SCindy Lu     }
347*108a6481SCindy Lu     v_config->len = config_len;
348*108a6481SCindy Lu     v_config->off = 0;
349*108a6481SCindy Lu     ret = vhost_vdpa_call(dev, VHOST_VDPA_GET_CONFIG, v_config);
350*108a6481SCindy Lu     memcpy(config, v_config->buf, config_len);
351*108a6481SCindy Lu     g_free(v_config);
352*108a6481SCindy Lu     return ret;
353*108a6481SCindy Lu  }
354*108a6481SCindy Lu 
355*108a6481SCindy Lu static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
356*108a6481SCindy Lu {
357*108a6481SCindy Lu     struct vhost_vdpa *v = dev->opaque;
358*108a6481SCindy Lu     if (started) {
359*108a6481SCindy Lu         uint8_t status = 0;
360*108a6481SCindy Lu         memory_listener_register(&v->listener, &address_space_memory);
361*108a6481SCindy Lu         vhost_vdpa_set_vring_ready(dev);
362*108a6481SCindy Lu         vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
363*108a6481SCindy Lu         vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status);
364*108a6481SCindy Lu 
365*108a6481SCindy Lu         return !(status & VIRTIO_CONFIG_S_DRIVER_OK);
366*108a6481SCindy Lu     } else {
367*108a6481SCindy Lu         vhost_vdpa_reset_device(dev);
368*108a6481SCindy Lu         vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
369*108a6481SCindy Lu                                    VIRTIO_CONFIG_S_DRIVER);
370*108a6481SCindy Lu         memory_listener_unregister(&v->listener);
371*108a6481SCindy Lu 
372*108a6481SCindy Lu         return 0;
373*108a6481SCindy Lu     }
374*108a6481SCindy Lu }
375*108a6481SCindy Lu 
376*108a6481SCindy Lu static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base,
377*108a6481SCindy Lu                                      struct vhost_log *log)
378*108a6481SCindy Lu {
379*108a6481SCindy Lu     return vhost_vdpa_call(dev, VHOST_SET_LOG_BASE, &base);
380*108a6481SCindy Lu }
381*108a6481SCindy Lu 
382*108a6481SCindy Lu static int vhost_vdpa_set_vring_addr(struct vhost_dev *dev,
383*108a6481SCindy Lu                                        struct vhost_vring_addr *addr)
384*108a6481SCindy Lu {
385*108a6481SCindy Lu     return vhost_vdpa_call(dev, VHOST_SET_VRING_ADDR, addr);
386*108a6481SCindy Lu }
387*108a6481SCindy Lu 
388*108a6481SCindy Lu static int vhost_vdpa_set_vring_num(struct vhost_dev *dev,
389*108a6481SCindy Lu                                       struct vhost_vring_state *ring)
390*108a6481SCindy Lu {
391*108a6481SCindy Lu     return vhost_vdpa_call(dev, VHOST_SET_VRING_NUM, ring);
392*108a6481SCindy Lu }
393*108a6481SCindy Lu 
394*108a6481SCindy Lu static int vhost_vdpa_set_vring_base(struct vhost_dev *dev,
395*108a6481SCindy Lu                                        struct vhost_vring_state *ring)
396*108a6481SCindy Lu {
397*108a6481SCindy Lu     return vhost_vdpa_call(dev, VHOST_SET_VRING_BASE, ring);
398*108a6481SCindy Lu }
399*108a6481SCindy Lu 
400*108a6481SCindy Lu static int vhost_vdpa_get_vring_base(struct vhost_dev *dev,
401*108a6481SCindy Lu                                        struct vhost_vring_state *ring)
402*108a6481SCindy Lu {
403*108a6481SCindy Lu     return vhost_vdpa_call(dev, VHOST_GET_VRING_BASE, ring);
404*108a6481SCindy Lu }
405*108a6481SCindy Lu 
406*108a6481SCindy Lu static int vhost_vdpa_set_vring_kick(struct vhost_dev *dev,
407*108a6481SCindy Lu                                        struct vhost_vring_file *file)
408*108a6481SCindy Lu {
409*108a6481SCindy Lu     return vhost_vdpa_call(dev, VHOST_SET_VRING_KICK, file);
410*108a6481SCindy Lu }
411*108a6481SCindy Lu 
412*108a6481SCindy Lu static int vhost_vdpa_set_vring_call(struct vhost_dev *dev,
413*108a6481SCindy Lu                                        struct vhost_vring_file *file)
414*108a6481SCindy Lu {
415*108a6481SCindy Lu     return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file);
416*108a6481SCindy Lu }
417*108a6481SCindy Lu 
418*108a6481SCindy Lu static int vhost_vdpa_get_features(struct vhost_dev *dev,
419*108a6481SCindy Lu                                      uint64_t *features)
420*108a6481SCindy Lu {
421*108a6481SCindy Lu     return vhost_vdpa_call(dev, VHOST_GET_FEATURES, features);
422*108a6481SCindy Lu }
423*108a6481SCindy Lu 
424*108a6481SCindy Lu static int vhost_vdpa_set_owner(struct vhost_dev *dev)
425*108a6481SCindy Lu {
426*108a6481SCindy Lu     return vhost_vdpa_call(dev, VHOST_SET_OWNER, NULL);
427*108a6481SCindy Lu }
428*108a6481SCindy Lu 
429*108a6481SCindy Lu static int vhost_vdpa_vq_get_addr(struct vhost_dev *dev,
430*108a6481SCindy Lu                     struct vhost_vring_addr *addr, struct vhost_virtqueue *vq)
431*108a6481SCindy Lu {
432*108a6481SCindy Lu     assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
433*108a6481SCindy Lu     addr->desc_user_addr = (uint64_t)(unsigned long)vq->desc_phys;
434*108a6481SCindy Lu     addr->avail_user_addr = (uint64_t)(unsigned long)vq->avail_phys;
435*108a6481SCindy Lu     addr->used_user_addr = (uint64_t)(unsigned long)vq->used_phys;
436*108a6481SCindy Lu     return 0;
437*108a6481SCindy Lu }
438*108a6481SCindy Lu 
439*108a6481SCindy Lu static bool  vhost_vdpa_force_iommu(struct vhost_dev *dev)
440*108a6481SCindy Lu {
441*108a6481SCindy Lu     return true;
442*108a6481SCindy Lu }
443*108a6481SCindy Lu 
444*108a6481SCindy Lu const VhostOps vdpa_ops = {
445*108a6481SCindy Lu         .backend_type = VHOST_BACKEND_TYPE_VDPA,
446*108a6481SCindy Lu         .vhost_backend_init = vhost_vdpa_init,
447*108a6481SCindy Lu         .vhost_backend_cleanup = vhost_vdpa_cleanup,
448*108a6481SCindy Lu         .vhost_set_log_base = vhost_vdpa_set_log_base,
449*108a6481SCindy Lu         .vhost_set_vring_addr = vhost_vdpa_set_vring_addr,
450*108a6481SCindy Lu         .vhost_set_vring_num = vhost_vdpa_set_vring_num,
451*108a6481SCindy Lu         .vhost_set_vring_base = vhost_vdpa_set_vring_base,
452*108a6481SCindy Lu         .vhost_get_vring_base = vhost_vdpa_get_vring_base,
453*108a6481SCindy Lu         .vhost_set_vring_kick = vhost_vdpa_set_vring_kick,
454*108a6481SCindy Lu         .vhost_set_vring_call = vhost_vdpa_set_vring_call,
455*108a6481SCindy Lu         .vhost_get_features = vhost_vdpa_get_features,
456*108a6481SCindy Lu         .vhost_set_owner = vhost_vdpa_set_owner,
457*108a6481SCindy Lu         .vhost_set_vring_endian = NULL,
458*108a6481SCindy Lu         .vhost_backend_memslots_limit = vhost_vdpa_memslots_limit,
459*108a6481SCindy Lu         .vhost_set_mem_table = vhost_vdpa_set_mem_table,
460*108a6481SCindy Lu         .vhost_set_features = vhost_vdpa_set_features,
461*108a6481SCindy Lu         .vhost_reset_device = vhost_vdpa_reset_device,
462*108a6481SCindy Lu         .vhost_get_vq_index = vhost_vdpa_get_vq_index,
463*108a6481SCindy Lu         .vhost_get_config  = vhost_vdpa_get_config,
464*108a6481SCindy Lu         .vhost_set_config = vhost_vdpa_set_config,
465*108a6481SCindy Lu         .vhost_requires_shm_log = NULL,
466*108a6481SCindy Lu         .vhost_migration_done = NULL,
467*108a6481SCindy Lu         .vhost_backend_can_merge = NULL,
468*108a6481SCindy Lu         .vhost_net_set_mtu = NULL,
469*108a6481SCindy Lu         .vhost_set_iotlb_callback = NULL,
470*108a6481SCindy Lu         .vhost_send_device_iotlb_msg = NULL,
471*108a6481SCindy Lu         .vhost_dev_start = vhost_vdpa_dev_start,
472*108a6481SCindy Lu         .vhost_get_device_id = vhost_vdpa_get_device_id,
473*108a6481SCindy Lu          .vhost_vq_get_addr = vhost_vdpa_vq_get_addr,
474*108a6481SCindy Lu          .vhost_force_iommu = vhost_vdpa_force_iommu,
475*108a6481SCindy Lu };
476