docs/devel/testing.rst: add missing newlines after code block
[qemu/ar7.git] / hw / virtio / vhost-backend.c
blob7f09efab8b910233e03d4cc300607f333237c0eb
1 /*
2 * vhost-backend
4 * Copyright (c) 2013 Virtual Open Systems Sarl.
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
9 */
11 #include "qemu/osdep.h"
12 #include <linux/vhost.h>
13 #include <sys/ioctl.h>
14 #include "hw/virtio/vhost.h"
15 #include "hw/virtio/vhost-backend.h"
16 #include "qemu/error-report.h"
18 static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request,
19 void *arg)
21 int fd = (uintptr_t) dev->opaque;
23 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
25 return ioctl(fd, request, arg);
28 static int vhost_kernel_init(struct vhost_dev *dev, void *opaque)
30 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
32 dev->opaque = opaque;
34 return 0;
37 static int vhost_kernel_cleanup(struct vhost_dev *dev)
39 int fd = (uintptr_t) dev->opaque;
41 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
43 return close(fd);
46 static int vhost_kernel_memslots_limit(struct vhost_dev *dev)
48 int limit = 64;
49 char *s;
51 if (g_file_get_contents("/sys/module/vhost/parameters/max_mem_regions",
52 &s, NULL, NULL)) {
53 uint64_t val = g_ascii_strtoull(s, NULL, 10);
54 if (!((val == G_MAXUINT64 || !val) && errno)) {
55 g_free(s);
56 return val;
58 error_report("ignoring invalid max_mem_regions value in vhost module:"
59 " %s", s);
61 g_free(s);
62 return limit;
65 static int vhost_kernel_net_set_backend(struct vhost_dev *dev,
66 struct vhost_vring_file *file)
68 return vhost_kernel_call(dev, VHOST_NET_SET_BACKEND, file);
71 static int vhost_kernel_scsi_set_endpoint(struct vhost_dev *dev,
72 struct vhost_scsi_target *target)
74 return vhost_kernel_call(dev, VHOST_SCSI_SET_ENDPOINT, target);
77 static int vhost_kernel_scsi_clear_endpoint(struct vhost_dev *dev,
78 struct vhost_scsi_target *target)
80 return vhost_kernel_call(dev, VHOST_SCSI_CLEAR_ENDPOINT, target);
83 static int vhost_kernel_scsi_get_abi_version(struct vhost_dev *dev, int *version)
85 return vhost_kernel_call(dev, VHOST_SCSI_GET_ABI_VERSION, version);
88 static int vhost_kernel_set_log_base(struct vhost_dev *dev, uint64_t base,
89 struct vhost_log *log)
91 return vhost_kernel_call(dev, VHOST_SET_LOG_BASE, &base);
94 static int vhost_kernel_set_mem_table(struct vhost_dev *dev,
95 struct vhost_memory *mem)
97 return vhost_kernel_call(dev, VHOST_SET_MEM_TABLE, mem);
100 static int vhost_kernel_set_vring_addr(struct vhost_dev *dev,
101 struct vhost_vring_addr *addr)
103 return vhost_kernel_call(dev, VHOST_SET_VRING_ADDR, addr);
106 static int vhost_kernel_set_vring_endian(struct vhost_dev *dev,
107 struct vhost_vring_state *ring)
109 return vhost_kernel_call(dev, VHOST_SET_VRING_ENDIAN, ring);
112 static int vhost_kernel_set_vring_num(struct vhost_dev *dev,
113 struct vhost_vring_state *ring)
115 return vhost_kernel_call(dev, VHOST_SET_VRING_NUM, ring);
118 static int vhost_kernel_set_vring_base(struct vhost_dev *dev,
119 struct vhost_vring_state *ring)
121 return vhost_kernel_call(dev, VHOST_SET_VRING_BASE, ring);
124 static int vhost_kernel_get_vring_base(struct vhost_dev *dev,
125 struct vhost_vring_state *ring)
127 return vhost_kernel_call(dev, VHOST_GET_VRING_BASE, ring);
130 static int vhost_kernel_set_vring_kick(struct vhost_dev *dev,
131 struct vhost_vring_file *file)
133 return vhost_kernel_call(dev, VHOST_SET_VRING_KICK, file);
136 static int vhost_kernel_set_vring_call(struct vhost_dev *dev,
137 struct vhost_vring_file *file)
139 return vhost_kernel_call(dev, VHOST_SET_VRING_CALL, file);
142 static int vhost_kernel_set_vring_busyloop_timeout(struct vhost_dev *dev,
143 struct vhost_vring_state *s)
145 return vhost_kernel_call(dev, VHOST_SET_VRING_BUSYLOOP_TIMEOUT, s);
148 static int vhost_kernel_set_features(struct vhost_dev *dev,
149 uint64_t features)
151 return vhost_kernel_call(dev, VHOST_SET_FEATURES, &features);
154 static int vhost_kernel_get_features(struct vhost_dev *dev,
155 uint64_t *features)
157 return vhost_kernel_call(dev, VHOST_GET_FEATURES, features);
160 static int vhost_kernel_set_owner(struct vhost_dev *dev)
162 return vhost_kernel_call(dev, VHOST_SET_OWNER, NULL);
165 static int vhost_kernel_reset_device(struct vhost_dev *dev)
167 return vhost_kernel_call(dev, VHOST_RESET_OWNER, NULL);
170 static int vhost_kernel_get_vq_index(struct vhost_dev *dev, int idx)
172 assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
174 return idx - dev->vq_index;
177 #ifdef CONFIG_VHOST_VSOCK
178 static int vhost_kernel_vsock_set_guest_cid(struct vhost_dev *dev,
179 uint64_t guest_cid)
181 return vhost_kernel_call(dev, VHOST_VSOCK_SET_GUEST_CID, &guest_cid);
184 static int vhost_kernel_vsock_set_running(struct vhost_dev *dev, int start)
186 return vhost_kernel_call(dev, VHOST_VSOCK_SET_RUNNING, &start);
188 #endif /* CONFIG_VHOST_VSOCK */
190 static void vhost_kernel_iotlb_read(void *opaque)
192 struct vhost_dev *dev = opaque;
193 struct vhost_msg msg;
194 ssize_t len;
196 while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) {
197 if (len < sizeof msg) {
198 error_report("Wrong vhost message len: %d", (int)len);
199 break;
201 if (msg.type != VHOST_IOTLB_MSG) {
202 error_report("Unknown vhost iotlb message type");
203 break;
206 vhost_backend_handle_iotlb_msg(dev, &msg.iotlb);
210 static int vhost_kernel_send_device_iotlb_msg(struct vhost_dev *dev,
211 struct vhost_iotlb_msg *imsg)
213 struct vhost_msg msg;
215 msg.type = VHOST_IOTLB_MSG;
216 msg.iotlb = *imsg;
218 if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) {
219 error_report("Fail to update device iotlb");
220 return -EFAULT;
223 return 0;
226 static void vhost_kernel_set_iotlb_callback(struct vhost_dev *dev,
227 int enabled)
229 if (enabled)
230 qemu_set_fd_handler((uintptr_t)dev->opaque,
231 vhost_kernel_iotlb_read, NULL, dev);
232 else
233 qemu_set_fd_handler((uintptr_t)dev->opaque, NULL, NULL, NULL);
236 static const VhostOps kernel_ops = {
237 .backend_type = VHOST_BACKEND_TYPE_KERNEL,
238 .vhost_backend_init = vhost_kernel_init,
239 .vhost_backend_cleanup = vhost_kernel_cleanup,
240 .vhost_backend_memslots_limit = vhost_kernel_memslots_limit,
241 .vhost_net_set_backend = vhost_kernel_net_set_backend,
242 .vhost_scsi_set_endpoint = vhost_kernel_scsi_set_endpoint,
243 .vhost_scsi_clear_endpoint = vhost_kernel_scsi_clear_endpoint,
244 .vhost_scsi_get_abi_version = vhost_kernel_scsi_get_abi_version,
245 .vhost_set_log_base = vhost_kernel_set_log_base,
246 .vhost_set_mem_table = vhost_kernel_set_mem_table,
247 .vhost_set_vring_addr = vhost_kernel_set_vring_addr,
248 .vhost_set_vring_endian = vhost_kernel_set_vring_endian,
249 .vhost_set_vring_num = vhost_kernel_set_vring_num,
250 .vhost_set_vring_base = vhost_kernel_set_vring_base,
251 .vhost_get_vring_base = vhost_kernel_get_vring_base,
252 .vhost_set_vring_kick = vhost_kernel_set_vring_kick,
253 .vhost_set_vring_call = vhost_kernel_set_vring_call,
254 .vhost_set_vring_busyloop_timeout =
255 vhost_kernel_set_vring_busyloop_timeout,
256 .vhost_set_features = vhost_kernel_set_features,
257 .vhost_get_features = vhost_kernel_get_features,
258 .vhost_set_owner = vhost_kernel_set_owner,
259 .vhost_reset_device = vhost_kernel_reset_device,
260 .vhost_get_vq_index = vhost_kernel_get_vq_index,
261 #ifdef CONFIG_VHOST_VSOCK
262 .vhost_vsock_set_guest_cid = vhost_kernel_vsock_set_guest_cid,
263 .vhost_vsock_set_running = vhost_kernel_vsock_set_running,
264 #endif /* CONFIG_VHOST_VSOCK */
265 .vhost_set_iotlb_callback = vhost_kernel_set_iotlb_callback,
266 .vhost_send_device_iotlb_msg = vhost_kernel_send_device_iotlb_msg,
269 int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
271 int r = 0;
273 switch (backend_type) {
274 case VHOST_BACKEND_TYPE_KERNEL:
275 dev->vhost_ops = &kernel_ops;
276 break;
277 case VHOST_BACKEND_TYPE_USER:
278 dev->vhost_ops = &user_ops;
279 break;
280 default:
281 error_report("Unknown vhost backend type");
282 r = -1;
285 return r;
288 int vhost_backend_update_device_iotlb(struct vhost_dev *dev,
289 uint64_t iova, uint64_t uaddr,
290 uint64_t len,
291 IOMMUAccessFlags perm)
293 struct vhost_iotlb_msg imsg;
295 imsg.iova = iova;
296 imsg.uaddr = uaddr;
297 imsg.size = len;
298 imsg.type = VHOST_IOTLB_UPDATE;
300 switch (perm) {
301 case IOMMU_RO:
302 imsg.perm = VHOST_ACCESS_RO;
303 break;
304 case IOMMU_WO:
305 imsg.perm = VHOST_ACCESS_WO;
306 break;
307 case IOMMU_RW:
308 imsg.perm = VHOST_ACCESS_RW;
309 break;
310 default:
311 return -EINVAL;
314 if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg)
315 return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
317 return -ENODEV;
320 int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev,
321 uint64_t iova, uint64_t len)
323 struct vhost_iotlb_msg imsg;
325 imsg.iova = iova;
326 imsg.size = len;
327 imsg.type = VHOST_IOTLB_INVALIDATE;
329 if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg)
330 return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
332 return -ENODEV;
335 int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev,
336 struct vhost_iotlb_msg *imsg)
338 int ret = 0;
340 switch (imsg->type) {
341 case VHOST_IOTLB_MISS:
342 ret = vhost_device_iotlb_miss(dev, imsg->iova,
343 imsg->perm != VHOST_ACCESS_RO);
344 break;
345 case VHOST_IOTLB_ACCESS_FAIL:
346 /* FIXME: report device iotlb error */
347 error_report("Access failure IOTLB message type not supported");
348 ret = -ENOTSUP;
349 break;
350 case VHOST_IOTLB_UPDATE:
351 case VHOST_IOTLB_INVALIDATE:
352 default:
353 error_report("Unexpected IOTLB message type");
354 ret = -EINVAL;
355 break;
358 return ret;