xref: /qemu/hw/virtio/vhost-backend.c (revision 8faf2f1de40e2fb919d8f584478d407a2fa7c80a)
11a1bfac9SNikolay Nikolaev /*
21a1bfac9SNikolay Nikolaev  * vhost-backend
31a1bfac9SNikolay Nikolaev  *
41a1bfac9SNikolay Nikolaev  * Copyright (c) 2013 Virtual Open Systems Sarl.
51a1bfac9SNikolay Nikolaev  *
61a1bfac9SNikolay Nikolaev  * This work is licensed under the terms of the GNU GPL, version 2 or later.
71a1bfac9SNikolay Nikolaev  * See the COPYING file in the top-level directory.
81a1bfac9SNikolay Nikolaev  *
91a1bfac9SNikolay Nikolaev  */
101a1bfac9SNikolay Nikolaev 
119b8bfe21SPeter Maydell #include "qemu/osdep.h"
121a1bfac9SNikolay Nikolaev #include "hw/virtio/vhost.h"
131a1bfac9SNikolay Nikolaev #include "hw/virtio/vhost-backend.h"
141a1bfac9SNikolay Nikolaev #include "qemu/error-report.h"
15db725815SMarkus Armbruster #include "qemu/main-loop.h"
1618658a3cSPaolo Bonzini #include "standard-headers/linux/vhost_types.h"
1718658a3cSPaolo Bonzini 
18108a6481SCindy Lu #include "hw/virtio/vhost-vdpa.h"
19299e6f19SPaolo Bonzini #ifdef CONFIG_VHOST_KERNEL
2018658a3cSPaolo Bonzini #include <linux/vhost.h>
2118658a3cSPaolo Bonzini #include <sys/ioctl.h>
221a1bfac9SNikolay Nikolaev 
231a1bfac9SNikolay Nikolaev static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request,
241a1bfac9SNikolay Nikolaev                              void *arg)
251a1bfac9SNikolay Nikolaev {
261a1bfac9SNikolay Nikolaev     int fd = (uintptr_t) dev->opaque;
271a1bfac9SNikolay Nikolaev 
281a1bfac9SNikolay Nikolaev     assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
291a1bfac9SNikolay Nikolaev 
301a1bfac9SNikolay Nikolaev     return ioctl(fd, request, arg);
311a1bfac9SNikolay Nikolaev }
321a1bfac9SNikolay Nikolaev 
331a1bfac9SNikolay Nikolaev static int vhost_kernel_init(struct vhost_dev *dev, void *opaque)
341a1bfac9SNikolay Nikolaev {
351a1bfac9SNikolay Nikolaev     assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
361a1bfac9SNikolay Nikolaev 
371a1bfac9SNikolay Nikolaev     dev->opaque = opaque;
381a1bfac9SNikolay Nikolaev 
391a1bfac9SNikolay Nikolaev     return 0;
401a1bfac9SNikolay Nikolaev }
411a1bfac9SNikolay Nikolaev 
421a1bfac9SNikolay Nikolaev static int vhost_kernel_cleanup(struct vhost_dev *dev)
431a1bfac9SNikolay Nikolaev {
441a1bfac9SNikolay Nikolaev     int fd = (uintptr_t) dev->opaque;
451a1bfac9SNikolay Nikolaev 
461a1bfac9SNikolay Nikolaev     assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
471a1bfac9SNikolay Nikolaev 
481a1bfac9SNikolay Nikolaev     return close(fd);
491a1bfac9SNikolay Nikolaev }
501a1bfac9SNikolay Nikolaev 
512ce68e4cSIgor Mammedov static int vhost_kernel_memslots_limit(struct vhost_dev *dev)
522ce68e4cSIgor Mammedov {
532ce68e4cSIgor Mammedov     int limit = 64;
542ce68e4cSIgor Mammedov     char *s;
552ce68e4cSIgor Mammedov 
562ce68e4cSIgor Mammedov     if (g_file_get_contents("/sys/module/vhost/parameters/max_mem_regions",
572ce68e4cSIgor Mammedov                             &s, NULL, NULL)) {
582ce68e4cSIgor Mammedov         uint64_t val = g_ascii_strtoull(s, NULL, 10);
592ce68e4cSIgor Mammedov         if (!((val == G_MAXUINT64 || !val) && errno)) {
6008b9e0baSPeng Hao             g_free(s);
612ce68e4cSIgor Mammedov             return val;
622ce68e4cSIgor Mammedov         }
632ce68e4cSIgor Mammedov         error_report("ignoring invalid max_mem_regions value in vhost module:"
642ce68e4cSIgor Mammedov                      " %s", s);
652ce68e4cSIgor Mammedov     }
6608b9e0baSPeng Hao     g_free(s);
672ce68e4cSIgor Mammedov     return limit;
682ce68e4cSIgor Mammedov }
692ce68e4cSIgor Mammedov 
7021e70425SMarc-André Lureau static int vhost_kernel_net_set_backend(struct vhost_dev *dev,
7121e70425SMarc-André Lureau                                         struct vhost_vring_file *file)
7221e70425SMarc-André Lureau {
7321e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_NET_SET_BACKEND, file);
7421e70425SMarc-André Lureau }
7521e70425SMarc-André Lureau 
7621e70425SMarc-André Lureau static int vhost_kernel_scsi_set_endpoint(struct vhost_dev *dev,
7721e70425SMarc-André Lureau                                           struct vhost_scsi_target *target)
7821e70425SMarc-André Lureau {
7921e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SCSI_SET_ENDPOINT, target);
8021e70425SMarc-André Lureau }
8121e70425SMarc-André Lureau 
8221e70425SMarc-André Lureau static int vhost_kernel_scsi_clear_endpoint(struct vhost_dev *dev,
8321e70425SMarc-André Lureau                                             struct vhost_scsi_target *target)
8421e70425SMarc-André Lureau {
8521e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SCSI_CLEAR_ENDPOINT, target);
8621e70425SMarc-André Lureau }
8721e70425SMarc-André Lureau 
8821e70425SMarc-André Lureau static int vhost_kernel_scsi_get_abi_version(struct vhost_dev *dev, int *version)
8921e70425SMarc-André Lureau {
9021e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SCSI_GET_ABI_VERSION, version);
9121e70425SMarc-André Lureau }
9221e70425SMarc-André Lureau 
9321e70425SMarc-André Lureau static int vhost_kernel_set_log_base(struct vhost_dev *dev, uint64_t base,
949a78a5ddSMarc-André Lureau                                      struct vhost_log *log)
95c2bea314SMarc-André Lureau {
96c2bea314SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SET_LOG_BASE, &base);
97c2bea314SMarc-André Lureau }
98c2bea314SMarc-André Lureau 
9921e70425SMarc-André Lureau static int vhost_kernel_set_mem_table(struct vhost_dev *dev,
10021e70425SMarc-André Lureau                                       struct vhost_memory *mem)
10121e70425SMarc-André Lureau {
10221e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SET_MEM_TABLE, mem);
10321e70425SMarc-André Lureau }
10421e70425SMarc-André Lureau 
10521e70425SMarc-André Lureau static int vhost_kernel_set_vring_addr(struct vhost_dev *dev,
10621e70425SMarc-André Lureau                                        struct vhost_vring_addr *addr)
10721e70425SMarc-André Lureau {
10821e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SET_VRING_ADDR, addr);
10921e70425SMarc-André Lureau }
11021e70425SMarc-André Lureau 
11121e70425SMarc-André Lureau static int vhost_kernel_set_vring_endian(struct vhost_dev *dev,
11221e70425SMarc-André Lureau                                          struct vhost_vring_state *ring)
11321e70425SMarc-André Lureau {
11421e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SET_VRING_ENDIAN, ring);
11521e70425SMarc-André Lureau }
11621e70425SMarc-André Lureau 
11721e70425SMarc-André Lureau static int vhost_kernel_set_vring_num(struct vhost_dev *dev,
11821e70425SMarc-André Lureau                                       struct vhost_vring_state *ring)
11921e70425SMarc-André Lureau {
12021e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SET_VRING_NUM, ring);
12121e70425SMarc-André Lureau }
12221e70425SMarc-André Lureau 
12321e70425SMarc-André Lureau static int vhost_kernel_set_vring_base(struct vhost_dev *dev,
12421e70425SMarc-André Lureau                                        struct vhost_vring_state *ring)
12521e70425SMarc-André Lureau {
12621e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SET_VRING_BASE, ring);
12721e70425SMarc-André Lureau }
12821e70425SMarc-André Lureau 
12921e70425SMarc-André Lureau static int vhost_kernel_get_vring_base(struct vhost_dev *dev,
13021e70425SMarc-André Lureau                                        struct vhost_vring_state *ring)
13121e70425SMarc-André Lureau {
13221e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_GET_VRING_BASE, ring);
13321e70425SMarc-André Lureau }
13421e70425SMarc-André Lureau 
13521e70425SMarc-André Lureau static int vhost_kernel_set_vring_kick(struct vhost_dev *dev,
13621e70425SMarc-André Lureau                                        struct vhost_vring_file *file)
13721e70425SMarc-André Lureau {
13821e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SET_VRING_KICK, file);
13921e70425SMarc-André Lureau }
14021e70425SMarc-André Lureau 
14121e70425SMarc-André Lureau static int vhost_kernel_set_vring_call(struct vhost_dev *dev,
14221e70425SMarc-André Lureau                                        struct vhost_vring_file *file)
14321e70425SMarc-André Lureau {
14421e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SET_VRING_CALL, file);
14521e70425SMarc-André Lureau }
14621e70425SMarc-André Lureau 
14769e87b32SJason Wang static int vhost_kernel_set_vring_busyloop_timeout(struct vhost_dev *dev,
14869e87b32SJason Wang                                                    struct vhost_vring_state *s)
14969e87b32SJason Wang {
15069e87b32SJason Wang     return vhost_kernel_call(dev, VHOST_SET_VRING_BUSYLOOP_TIMEOUT, s);
15169e87b32SJason Wang }
15269e87b32SJason Wang 
15321e70425SMarc-André Lureau static int vhost_kernel_set_features(struct vhost_dev *dev,
15421e70425SMarc-André Lureau                                      uint64_t features)
15521e70425SMarc-André Lureau {
15621e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SET_FEATURES, &features);
15721e70425SMarc-André Lureau }
15821e70425SMarc-André Lureau 
159b37556edSJason Wang static int vhost_kernel_set_backend_cap(struct vhost_dev *dev)
160b37556edSJason Wang {
161b37556edSJason Wang     uint64_t features;
162b37556edSJason Wang     uint64_t f = 0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2;
163b37556edSJason Wang     int r;
164b37556edSJason Wang 
165b37556edSJason Wang     if (vhost_kernel_call(dev, VHOST_GET_BACKEND_FEATURES, &features)) {
166b37556edSJason Wang         return 0;
167b37556edSJason Wang     }
168b37556edSJason Wang 
169b37556edSJason Wang     features &= f;
170b37556edSJason Wang     r = vhost_kernel_call(dev, VHOST_SET_BACKEND_FEATURES,
171b37556edSJason Wang                               &features);
172b37556edSJason Wang     if (r) {
173b37556edSJason Wang         return 0;
174b37556edSJason Wang     }
175b37556edSJason Wang 
176b37556edSJason Wang     dev->backend_cap = features;
177b37556edSJason Wang 
178b37556edSJason Wang     return 0;
179b37556edSJason Wang }
180b37556edSJason Wang 
18121e70425SMarc-André Lureau static int vhost_kernel_get_features(struct vhost_dev *dev,
18221e70425SMarc-André Lureau                                      uint64_t *features)
18321e70425SMarc-André Lureau {
18421e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_GET_FEATURES, features);
18521e70425SMarc-André Lureau }
18621e70425SMarc-André Lureau 
18721e70425SMarc-André Lureau static int vhost_kernel_set_owner(struct vhost_dev *dev)
18821e70425SMarc-André Lureau {
18921e70425SMarc-André Lureau     return vhost_kernel_call(dev, VHOST_SET_OWNER, NULL);
19021e70425SMarc-André Lureau }
19121e70425SMarc-André Lureau 
19221e70425SMarc-André Lureau static int vhost_kernel_reset_device(struct vhost_dev *dev)
19321e70425SMarc-André Lureau {
19460915dc4SYuanhan Liu     return vhost_kernel_call(dev, VHOST_RESET_OWNER, NULL);
19521e70425SMarc-André Lureau }
19621e70425SMarc-André Lureau 
19721e70425SMarc-André Lureau static int vhost_kernel_get_vq_index(struct vhost_dev *dev, int idx)
19821e70425SMarc-André Lureau {
19921e70425SMarc-André Lureau     assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
20021e70425SMarc-André Lureau 
20121e70425SMarc-André Lureau     return idx - dev->vq_index;
20221e70425SMarc-André Lureau }
20321e70425SMarc-André Lureau 
204fc0b9b0eSStefan Hajnoczi #ifdef CONFIG_VHOST_VSOCK
205fc0b9b0eSStefan Hajnoczi static int vhost_kernel_vsock_set_guest_cid(struct vhost_dev *dev,
206fc0b9b0eSStefan Hajnoczi                                             uint64_t guest_cid)
207fc0b9b0eSStefan Hajnoczi {
208fc0b9b0eSStefan Hajnoczi     return vhost_kernel_call(dev, VHOST_VSOCK_SET_GUEST_CID, &guest_cid);
209fc0b9b0eSStefan Hajnoczi }
210fc0b9b0eSStefan Hajnoczi 
211fc0b9b0eSStefan Hajnoczi static int vhost_kernel_vsock_set_running(struct vhost_dev *dev, int start)
212fc0b9b0eSStefan Hajnoczi {
213fc0b9b0eSStefan Hajnoczi     return vhost_kernel_call(dev, VHOST_VSOCK_SET_RUNNING, &start);
214fc0b9b0eSStefan Hajnoczi }
215fc0b9b0eSStefan Hajnoczi #endif /* CONFIG_VHOST_VSOCK */
216fc0b9b0eSStefan Hajnoczi 
217c471ad0eSJason Wang static void vhost_kernel_iotlb_read(void *opaque)
218c471ad0eSJason Wang {
219c471ad0eSJason Wang     struct vhost_dev *dev = opaque;
220c471ad0eSJason Wang     ssize_t len;
221c471ad0eSJason Wang 
222b37556edSJason Wang     if (dev->backend_cap &
223b37556edSJason Wang         (0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2)) {
224b37556edSJason Wang         struct vhost_msg_v2 msg;
225b37556edSJason Wang 
226b37556edSJason Wang         while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) {
227b37556edSJason Wang             if (len < sizeof msg) {
228b37556edSJason Wang                 error_report("Wrong vhost message len: %d", (int)len);
229b37556edSJason Wang                 break;
230b37556edSJason Wang             }
231b37556edSJason Wang             if (msg.type != VHOST_IOTLB_MSG_V2) {
232b37556edSJason Wang                 error_report("Unknown vhost iotlb message type");
233b37556edSJason Wang                 break;
234b37556edSJason Wang             }
235b37556edSJason Wang 
236b37556edSJason Wang             vhost_backend_handle_iotlb_msg(dev, &msg.iotlb);
237b37556edSJason Wang         }
238b37556edSJason Wang     } else {
239b37556edSJason Wang         struct vhost_msg msg;
240b37556edSJason Wang 
241c471ad0eSJason Wang         while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) {
242c471ad0eSJason Wang             if (len < sizeof msg) {
243c471ad0eSJason Wang                 error_report("Wrong vhost message len: %d", (int)len);
244c471ad0eSJason Wang                 break;
245c471ad0eSJason Wang             }
246c471ad0eSJason Wang             if (msg.type != VHOST_IOTLB_MSG) {
247c471ad0eSJason Wang                 error_report("Unknown vhost iotlb message type");
248c471ad0eSJason Wang                 break;
249c471ad0eSJason Wang             }
250020e571bSMaxime Coquelin 
251020e571bSMaxime Coquelin             vhost_backend_handle_iotlb_msg(dev, &msg.iotlb);
252c471ad0eSJason Wang         }
253c471ad0eSJason Wang     }
254b37556edSJason Wang }
255c471ad0eSJason Wang 
256020e571bSMaxime Coquelin static int vhost_kernel_send_device_iotlb_msg(struct vhost_dev *dev,
257020e571bSMaxime Coquelin                                               struct vhost_iotlb_msg *imsg)
258c471ad0eSJason Wang {
259b37556edSJason Wang     if (dev->backend_cap & (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2)) {
260*8faf2f1dSPhilippe Mathieu-Daudé         struct vhost_msg_v2 msg = {};
261b37556edSJason Wang 
262b37556edSJason Wang         msg.type = VHOST_IOTLB_MSG_V2;
263b37556edSJason Wang         msg.iotlb = *imsg;
264b37556edSJason Wang 
265b37556edSJason Wang         if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) {
266b37556edSJason Wang             error_report("Fail to update device iotlb");
267b37556edSJason Wang             return -EFAULT;
268b37556edSJason Wang         }
269b37556edSJason Wang     } else {
270*8faf2f1dSPhilippe Mathieu-Daudé         struct vhost_msg msg = {};
271c471ad0eSJason Wang 
272020e571bSMaxime Coquelin         msg.type = VHOST_IOTLB_MSG;
273020e571bSMaxime Coquelin         msg.iotlb = *imsg;
274c471ad0eSJason Wang 
275c471ad0eSJason Wang         if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) {
276c471ad0eSJason Wang             error_report("Fail to update device iotlb");
277c471ad0eSJason Wang             return -EFAULT;
278c471ad0eSJason Wang         }
279b37556edSJason Wang     }
280c471ad0eSJason Wang 
281c471ad0eSJason Wang     return 0;
282c471ad0eSJason Wang }
283c471ad0eSJason Wang 
284c471ad0eSJason Wang static void vhost_kernel_set_iotlb_callback(struct vhost_dev *dev,
285c471ad0eSJason Wang                                            int enabled)
286c471ad0eSJason Wang {
287c471ad0eSJason Wang     if (enabled)
288c471ad0eSJason Wang         qemu_set_fd_handler((uintptr_t)dev->opaque,
289c471ad0eSJason Wang                             vhost_kernel_iotlb_read, NULL, dev);
290c471ad0eSJason Wang     else
291c471ad0eSJason Wang         qemu_set_fd_handler((uintptr_t)dev->opaque, NULL, NULL, NULL);
292c471ad0eSJason Wang }
293c471ad0eSJason Wang 
2941a1bfac9SNikolay Nikolaev static const VhostOps kernel_ops = {
2951a1bfac9SNikolay Nikolaev         .backend_type = VHOST_BACKEND_TYPE_KERNEL,
2961a1bfac9SNikolay Nikolaev         .vhost_backend_init = vhost_kernel_init,
297fc57fd99SYuanhan Liu         .vhost_backend_cleanup = vhost_kernel_cleanup,
2982ce68e4cSIgor Mammedov         .vhost_backend_memslots_limit = vhost_kernel_memslots_limit,
29921e70425SMarc-André Lureau         .vhost_net_set_backend = vhost_kernel_net_set_backend,
30021e70425SMarc-André Lureau         .vhost_scsi_set_endpoint = vhost_kernel_scsi_set_endpoint,
30121e70425SMarc-André Lureau         .vhost_scsi_clear_endpoint = vhost_kernel_scsi_clear_endpoint,
30221e70425SMarc-André Lureau         .vhost_scsi_get_abi_version = vhost_kernel_scsi_get_abi_version,
30321e70425SMarc-André Lureau         .vhost_set_log_base = vhost_kernel_set_log_base,
30421e70425SMarc-André Lureau         .vhost_set_mem_table = vhost_kernel_set_mem_table,
30521e70425SMarc-André Lureau         .vhost_set_vring_addr = vhost_kernel_set_vring_addr,
30621e70425SMarc-André Lureau         .vhost_set_vring_endian = vhost_kernel_set_vring_endian,
30721e70425SMarc-André Lureau         .vhost_set_vring_num = vhost_kernel_set_vring_num,
30821e70425SMarc-André Lureau         .vhost_set_vring_base = vhost_kernel_set_vring_base,
30921e70425SMarc-André Lureau         .vhost_get_vring_base = vhost_kernel_get_vring_base,
31021e70425SMarc-André Lureau         .vhost_set_vring_kick = vhost_kernel_set_vring_kick,
31121e70425SMarc-André Lureau         .vhost_set_vring_call = vhost_kernel_set_vring_call,
31269e87b32SJason Wang         .vhost_set_vring_busyloop_timeout =
31369e87b32SJason Wang                                 vhost_kernel_set_vring_busyloop_timeout,
31421e70425SMarc-André Lureau         .vhost_set_features = vhost_kernel_set_features,
31521e70425SMarc-André Lureau         .vhost_get_features = vhost_kernel_get_features,
316b37556edSJason Wang         .vhost_set_backend_cap = vhost_kernel_set_backend_cap,
31721e70425SMarc-André Lureau         .vhost_set_owner = vhost_kernel_set_owner,
31821e70425SMarc-André Lureau         .vhost_reset_device = vhost_kernel_reset_device,
31921e70425SMarc-André Lureau         .vhost_get_vq_index = vhost_kernel_get_vq_index,
320fc0b9b0eSStefan Hajnoczi #ifdef CONFIG_VHOST_VSOCK
321fc0b9b0eSStefan Hajnoczi         .vhost_vsock_set_guest_cid = vhost_kernel_vsock_set_guest_cid,
322fc0b9b0eSStefan Hajnoczi         .vhost_vsock_set_running = vhost_kernel_vsock_set_running,
323fc0b9b0eSStefan Hajnoczi #endif /* CONFIG_VHOST_VSOCK */
324c471ad0eSJason Wang         .vhost_set_iotlb_callback = vhost_kernel_set_iotlb_callback,
325020e571bSMaxime Coquelin         .vhost_send_device_iotlb_msg = vhost_kernel_send_device_iotlb_msg,
3261a1bfac9SNikolay Nikolaev };
32718658a3cSPaolo Bonzini #endif
3281a1bfac9SNikolay Nikolaev 
3291a1bfac9SNikolay Nikolaev int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
3301a1bfac9SNikolay Nikolaev {
3311a1bfac9SNikolay Nikolaev     int r = 0;
3321a1bfac9SNikolay Nikolaev 
3331a1bfac9SNikolay Nikolaev     switch (backend_type) {
334299e6f19SPaolo Bonzini #ifdef CONFIG_VHOST_KERNEL
3351a1bfac9SNikolay Nikolaev     case VHOST_BACKEND_TYPE_KERNEL:
3361a1bfac9SNikolay Nikolaev         dev->vhost_ops = &kernel_ops;
3371a1bfac9SNikolay Nikolaev         break;
33818658a3cSPaolo Bonzini #endif
33918658a3cSPaolo Bonzini #ifdef CONFIG_VHOST_USER
3405f6f6664SNikolay Nikolaev     case VHOST_BACKEND_TYPE_USER:
3415f6f6664SNikolay Nikolaev         dev->vhost_ops = &user_ops;
3425f6f6664SNikolay Nikolaev         break;
34318658a3cSPaolo Bonzini #endif
344108a6481SCindy Lu #ifdef CONFIG_VHOST_VDPA
345108a6481SCindy Lu     case VHOST_BACKEND_TYPE_VDPA:
346108a6481SCindy Lu         dev->vhost_ops = &vdpa_ops;
347108a6481SCindy Lu         break;
348108a6481SCindy Lu #endif
3491a1bfac9SNikolay Nikolaev     default:
350c6547661SGonglei         error_report("Unknown vhost backend type");
3511a1bfac9SNikolay Nikolaev         r = -1;
3521a1bfac9SNikolay Nikolaev     }
3531a1bfac9SNikolay Nikolaev 
3541a1bfac9SNikolay Nikolaev     return r;
3551a1bfac9SNikolay Nikolaev }
356020e571bSMaxime Coquelin 
357020e571bSMaxime Coquelin int vhost_backend_update_device_iotlb(struct vhost_dev *dev,
358020e571bSMaxime Coquelin                                              uint64_t iova, uint64_t uaddr,
359020e571bSMaxime Coquelin                                              uint64_t len,
360020e571bSMaxime Coquelin                                              IOMMUAccessFlags perm)
361020e571bSMaxime Coquelin {
362020e571bSMaxime Coquelin     struct vhost_iotlb_msg imsg;
363020e571bSMaxime Coquelin 
364020e571bSMaxime Coquelin     imsg.iova =  iova;
365020e571bSMaxime Coquelin     imsg.uaddr = uaddr;
366020e571bSMaxime Coquelin     imsg.size = len;
367020e571bSMaxime Coquelin     imsg.type = VHOST_IOTLB_UPDATE;
368020e571bSMaxime Coquelin 
369020e571bSMaxime Coquelin     switch (perm) {
370020e571bSMaxime Coquelin     case IOMMU_RO:
371020e571bSMaxime Coquelin         imsg.perm = VHOST_ACCESS_RO;
372020e571bSMaxime Coquelin         break;
373020e571bSMaxime Coquelin     case IOMMU_WO:
374020e571bSMaxime Coquelin         imsg.perm = VHOST_ACCESS_WO;
375020e571bSMaxime Coquelin         break;
376020e571bSMaxime Coquelin     case IOMMU_RW:
377020e571bSMaxime Coquelin         imsg.perm = VHOST_ACCESS_RW;
378020e571bSMaxime Coquelin         break;
379020e571bSMaxime Coquelin     default:
380020e571bSMaxime Coquelin         return -EINVAL;
381020e571bSMaxime Coquelin     }
382020e571bSMaxime Coquelin 
383384b557dSMaxime Coquelin     if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg)
384020e571bSMaxime Coquelin         return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
385384b557dSMaxime Coquelin 
386384b557dSMaxime Coquelin     return -ENODEV;
387020e571bSMaxime Coquelin }
388020e571bSMaxime Coquelin 
389020e571bSMaxime Coquelin int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev,
390020e571bSMaxime Coquelin                                                  uint64_t iova, uint64_t len)
391020e571bSMaxime Coquelin {
392020e571bSMaxime Coquelin     struct vhost_iotlb_msg imsg;
393020e571bSMaxime Coquelin 
394020e571bSMaxime Coquelin     imsg.iova = iova;
395020e571bSMaxime Coquelin     imsg.size = len;
396020e571bSMaxime Coquelin     imsg.type = VHOST_IOTLB_INVALIDATE;
397020e571bSMaxime Coquelin 
398384b557dSMaxime Coquelin     if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg)
399020e571bSMaxime Coquelin         return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
400384b557dSMaxime Coquelin 
401384b557dSMaxime Coquelin     return -ENODEV;
402020e571bSMaxime Coquelin }
403020e571bSMaxime Coquelin 
404020e571bSMaxime Coquelin int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev,
405020e571bSMaxime Coquelin                                           struct vhost_iotlb_msg *imsg)
406020e571bSMaxime Coquelin {
407020e571bSMaxime Coquelin     int ret = 0;
408020e571bSMaxime Coquelin 
409020e571bSMaxime Coquelin     switch (imsg->type) {
410020e571bSMaxime Coquelin     case VHOST_IOTLB_MISS:
411020e571bSMaxime Coquelin         ret = vhost_device_iotlb_miss(dev, imsg->iova,
412020e571bSMaxime Coquelin                                       imsg->perm != VHOST_ACCESS_RO);
413020e571bSMaxime Coquelin         break;
414020e571bSMaxime Coquelin     case VHOST_IOTLB_ACCESS_FAIL:
415020e571bSMaxime Coquelin         /* FIXME: report device iotlb error */
416020e571bSMaxime Coquelin         error_report("Access failure IOTLB message type not supported");
417020e571bSMaxime Coquelin         ret = -ENOTSUP;
418020e571bSMaxime Coquelin         break;
419020e571bSMaxime Coquelin     case VHOST_IOTLB_UPDATE:
420020e571bSMaxime Coquelin     case VHOST_IOTLB_INVALIDATE:
421020e571bSMaxime Coquelin     default:
422020e571bSMaxime Coquelin         error_report("Unexpected IOTLB message type");
423020e571bSMaxime Coquelin         ret = -EINVAL;
424020e571bSMaxime Coquelin         break;
425020e571bSMaxime Coquelin     }
426020e571bSMaxime Coquelin 
427020e571bSMaxime Coquelin     return ret;
428020e571bSMaxime Coquelin }
429