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.
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
,
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
);
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
);
46 static int vhost_kernel_memslots_limit(struct vhost_dev
*dev
)
51 if (g_file_get_contents("/sys/module/vhost/parameters/max_mem_regions",
53 uint64_t val
= g_ascii_strtoull(s
, NULL
, 10);
54 if (!((val
== G_MAXUINT64
|| !val
) && errno
)) {
58 error_report("ignoring invalid max_mem_regions value in vhost module:"
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
,
151 return vhost_kernel_call(dev
, VHOST_SET_FEATURES
, &features
);
154 static int vhost_kernel_get_features(struct vhost_dev
*dev
,
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
,
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
;
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
);
201 if (msg
.type
!= VHOST_IOTLB_MSG
) {
202 error_report("Unknown vhost iotlb message type");
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
;
218 if (write((uintptr_t)dev
->opaque
, &msg
, sizeof msg
) != sizeof msg
) {
219 error_report("Fail to update device iotlb");
226 static void vhost_kernel_set_iotlb_callback(struct vhost_dev
*dev
,
230 qemu_set_fd_handler((uintptr_t)dev
->opaque
,
231 vhost_kernel_iotlb_read
, NULL
, dev
);
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
)
273 switch (backend_type
) {
274 case VHOST_BACKEND_TYPE_KERNEL
:
275 dev
->vhost_ops
= &kernel_ops
;
277 case VHOST_BACKEND_TYPE_USER
:
278 dev
->vhost_ops
= &user_ops
;
281 error_report("Unknown vhost backend type");
288 int vhost_backend_update_device_iotlb(struct vhost_dev
*dev
,
289 uint64_t iova
, uint64_t uaddr
,
291 IOMMUAccessFlags perm
)
293 struct vhost_iotlb_msg imsg
;
298 imsg
.type
= VHOST_IOTLB_UPDATE
;
302 imsg
.perm
= VHOST_ACCESS_RO
;
305 imsg
.perm
= VHOST_ACCESS_WO
;
308 imsg
.perm
= VHOST_ACCESS_RW
;
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
);
320 int vhost_backend_invalidate_device_iotlb(struct vhost_dev
*dev
,
321 uint64_t iova
, uint64_t len
)
323 struct vhost_iotlb_msg imsg
;
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
);
335 int vhost_backend_handle_iotlb_msg(struct vhost_dev
*dev
,
336 struct vhost_iotlb_msg
*imsg
)
340 switch (imsg
->type
) {
341 case VHOST_IOTLB_MISS
:
342 ret
= vhost_device_iotlb_miss(dev
, imsg
->iova
,
343 imsg
->perm
!= VHOST_ACCESS_RO
);
345 case VHOST_IOTLB_ACCESS_FAIL
:
346 /* FIXME: report device iotlb error */
347 error_report("Access failure IOTLB message type not supported");
350 case VHOST_IOTLB_UPDATE
:
351 case VHOST_IOTLB_INVALIDATE
:
353 error_report("Unexpected IOTLB message type");