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 111a1bfac9SNikolay Nikolaev #include "hw/virtio/vhost.h" 121a1bfac9SNikolay Nikolaev #include "hw/virtio/vhost-backend.h" 131a1bfac9SNikolay Nikolaev #include "qemu/error-report.h" 142ce68e4cSIgor Mammedov #include "linux/vhost.h" 151a1bfac9SNikolay Nikolaev 161a1bfac9SNikolay Nikolaev #include <sys/ioctl.h> 171a1bfac9SNikolay Nikolaev 181a1bfac9SNikolay Nikolaev static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request, 191a1bfac9SNikolay Nikolaev void *arg) 201a1bfac9SNikolay Nikolaev { 211a1bfac9SNikolay Nikolaev int fd = (uintptr_t) dev->opaque; 221a1bfac9SNikolay Nikolaev 231a1bfac9SNikolay Nikolaev assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL); 241a1bfac9SNikolay Nikolaev 251a1bfac9SNikolay Nikolaev return ioctl(fd, request, arg); 261a1bfac9SNikolay Nikolaev } 271a1bfac9SNikolay Nikolaev 281a1bfac9SNikolay Nikolaev static int vhost_kernel_init(struct vhost_dev *dev, void *opaque) 291a1bfac9SNikolay Nikolaev { 301a1bfac9SNikolay Nikolaev assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL); 311a1bfac9SNikolay Nikolaev 321a1bfac9SNikolay Nikolaev dev->opaque = opaque; 331a1bfac9SNikolay Nikolaev 341a1bfac9SNikolay Nikolaev return 0; 351a1bfac9SNikolay Nikolaev } 361a1bfac9SNikolay Nikolaev 371a1bfac9SNikolay Nikolaev static int vhost_kernel_cleanup(struct vhost_dev *dev) 381a1bfac9SNikolay Nikolaev { 391a1bfac9SNikolay Nikolaev int fd = (uintptr_t) dev->opaque; 401a1bfac9SNikolay Nikolaev 411a1bfac9SNikolay Nikolaev assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL); 421a1bfac9SNikolay Nikolaev 431a1bfac9SNikolay Nikolaev return close(fd); 441a1bfac9SNikolay Nikolaev } 451a1bfac9SNikolay Nikolaev 46fc57fd99SYuanhan Liu static int vhost_kernel_get_vq_index(struct vhost_dev *dev, int idx) 47fc57fd99SYuanhan Liu { 48fc57fd99SYuanhan Liu assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs); 49fc57fd99SYuanhan Liu 50fc57fd99SYuanhan Liu return idx - dev->vq_index; 51fc57fd99SYuanhan Liu } 52fc57fd99SYuanhan Liu 532ce68e4cSIgor Mammedov static int vhost_kernel_memslots_limit(struct vhost_dev *dev) 542ce68e4cSIgor Mammedov { 552ce68e4cSIgor Mammedov int limit = 64; 562ce68e4cSIgor Mammedov char *s; 572ce68e4cSIgor Mammedov 582ce68e4cSIgor Mammedov if (g_file_get_contents("/sys/module/vhost/parameters/max_mem_regions", 592ce68e4cSIgor Mammedov &s, NULL, NULL)) { 602ce68e4cSIgor Mammedov uint64_t val = g_ascii_strtoull(s, NULL, 10); 612ce68e4cSIgor Mammedov if (!((val == G_MAXUINT64 || !val) && errno)) { 622ce68e4cSIgor Mammedov return val; 632ce68e4cSIgor Mammedov } 642ce68e4cSIgor Mammedov error_report("ignoring invalid max_mem_regions value in vhost module:" 652ce68e4cSIgor Mammedov " %s", s); 662ce68e4cSIgor Mammedov } 672ce68e4cSIgor Mammedov return limit; 682ce68e4cSIgor Mammedov } 692ce68e4cSIgor Mammedov 70*9a78a5ddSMarc-André Lureau static int vhost_set_log_base(struct vhost_dev *dev, uint64_t base, 71*9a78a5ddSMarc-André Lureau struct vhost_log *log) 72c2bea314SMarc-André Lureau { 73c2bea314SMarc-André Lureau return vhost_kernel_call(dev, VHOST_SET_LOG_BASE, &base); 74c2bea314SMarc-André Lureau } 75c2bea314SMarc-André Lureau 761a1bfac9SNikolay Nikolaev static const VhostOps kernel_ops = { 771a1bfac9SNikolay Nikolaev .backend_type = VHOST_BACKEND_TYPE_KERNEL, 781a1bfac9SNikolay Nikolaev .vhost_call = vhost_kernel_call, 791a1bfac9SNikolay Nikolaev .vhost_backend_init = vhost_kernel_init, 80fc57fd99SYuanhan Liu .vhost_backend_cleanup = vhost_kernel_cleanup, 81fc57fd99SYuanhan Liu .vhost_backend_get_vq_index = vhost_kernel_get_vq_index, 822ce68e4cSIgor Mammedov .vhost_backend_memslots_limit = vhost_kernel_memslots_limit, 83c2bea314SMarc-André Lureau .vhost_set_log_base = vhost_set_log_base, 841a1bfac9SNikolay Nikolaev }; 851a1bfac9SNikolay Nikolaev 861a1bfac9SNikolay Nikolaev int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type) 871a1bfac9SNikolay Nikolaev { 881a1bfac9SNikolay Nikolaev int r = 0; 891a1bfac9SNikolay Nikolaev 901a1bfac9SNikolay Nikolaev switch (backend_type) { 911a1bfac9SNikolay Nikolaev case VHOST_BACKEND_TYPE_KERNEL: 921a1bfac9SNikolay Nikolaev dev->vhost_ops = &kernel_ops; 931a1bfac9SNikolay Nikolaev break; 945f6f6664SNikolay Nikolaev case VHOST_BACKEND_TYPE_USER: 955f6f6664SNikolay Nikolaev dev->vhost_ops = &user_ops; 965f6f6664SNikolay Nikolaev break; 971a1bfac9SNikolay Nikolaev default: 98c6547661SGonglei error_report("Unknown vhost backend type"); 991a1bfac9SNikolay Nikolaev r = -1; 1001a1bfac9SNikolay Nikolaev } 1011a1bfac9SNikolay Nikolaev 1021a1bfac9SNikolay Nikolaev return r; 1031a1bfac9SNikolay Nikolaev } 104