1745221e5SJean-Philippe Brucker #include "kvm/virtio.h" 2745221e5SJean-Philippe Brucker 3f84ab9ebSJean-Philippe Brucker #include <linux/kvm.h> 4f84ab9ebSJean-Philippe Brucker #include <linux/vhost.h> 5f84ab9ebSJean-Philippe Brucker #include <linux/list.h> 6f84ab9ebSJean-Philippe Brucker 7f84ab9ebSJean-Philippe Brucker void virtio_vhost_init(struct kvm *kvm, int vhost_fd) 8f84ab9ebSJean-Philippe Brucker { 9f84ab9ebSJean-Philippe Brucker struct kvm_mem_bank *bank; 10f84ab9ebSJean-Philippe Brucker struct vhost_memory *mem; 11f84ab9ebSJean-Philippe Brucker int i = 0, r; 12f84ab9ebSJean-Philippe Brucker 13f84ab9ebSJean-Philippe Brucker mem = calloc(1, sizeof(*mem) + 14f84ab9ebSJean-Philippe Brucker kvm->mem_slots * sizeof(struct vhost_memory_region)); 15f84ab9ebSJean-Philippe Brucker if (mem == NULL) 16f84ab9ebSJean-Philippe Brucker die("Failed allocating memory for vhost memory map"); 17f84ab9ebSJean-Philippe Brucker 18f84ab9ebSJean-Philippe Brucker list_for_each_entry(bank, &kvm->mem_banks, list) { 19f84ab9ebSJean-Philippe Brucker mem->regions[i] = (struct vhost_memory_region) { 20f84ab9ebSJean-Philippe Brucker .guest_phys_addr = bank->guest_phys_addr, 21f84ab9ebSJean-Philippe Brucker .memory_size = bank->size, 22f84ab9ebSJean-Philippe Brucker .userspace_addr = (unsigned long)bank->host_addr, 23f84ab9ebSJean-Philippe Brucker }; 24f84ab9ebSJean-Philippe Brucker i++; 25f84ab9ebSJean-Philippe Brucker } 26f84ab9ebSJean-Philippe Brucker mem->nregions = i; 27f84ab9ebSJean-Philippe Brucker 28f84ab9ebSJean-Philippe Brucker r = ioctl(vhost_fd, VHOST_SET_OWNER); 29f84ab9ebSJean-Philippe Brucker if (r != 0) 30f84ab9ebSJean-Philippe Brucker die_perror("VHOST_SET_OWNER failed"); 31f84ab9ebSJean-Philippe Brucker 32f84ab9ebSJean-Philippe Brucker r = ioctl(vhost_fd, VHOST_SET_MEM_TABLE, mem); 33f84ab9ebSJean-Philippe Brucker if (r != 0) 34f84ab9ebSJean-Philippe Brucker die_perror("VHOST_SET_MEM_TABLE failed"); 35f84ab9ebSJean-Philippe Brucker 36f84ab9ebSJean-Philippe Brucker free(mem); 37f84ab9ebSJean-Philippe Brucker } 38745221e5SJean-Philippe Brucker 39745221e5SJean-Philippe Brucker void virtio_vhost_set_vring(struct kvm *kvm, int vhost_fd, u32 index, 40745221e5SJean-Philippe Brucker struct virt_queue *queue) 41745221e5SJean-Philippe Brucker { 42745221e5SJean-Philippe Brucker int r; 43745221e5SJean-Philippe Brucker struct vhost_vring_addr addr = { 44745221e5SJean-Philippe Brucker .index = index, 45745221e5SJean-Philippe Brucker .desc_user_addr = (u64)(unsigned long)queue->vring.desc, 46745221e5SJean-Philippe Brucker .avail_user_addr = (u64)(unsigned long)queue->vring.avail, 47745221e5SJean-Philippe Brucker .used_user_addr = (u64)(unsigned long)queue->vring.used, 48745221e5SJean-Philippe Brucker }; 49745221e5SJean-Philippe Brucker struct vhost_vring_state state = { .index = index }; 50745221e5SJean-Philippe Brucker 51745221e5SJean-Philippe Brucker if (queue->endian != VIRTIO_ENDIAN_HOST) 52745221e5SJean-Philippe Brucker die("VHOST requires the same endianness in guest and host"); 53745221e5SJean-Philippe Brucker 54745221e5SJean-Philippe Brucker state.num = queue->vring.num; 55745221e5SJean-Philippe Brucker r = ioctl(vhost_fd, VHOST_SET_VRING_NUM, &state); 56745221e5SJean-Philippe Brucker if (r < 0) 57745221e5SJean-Philippe Brucker die_perror("VHOST_SET_VRING_NUM failed"); 58745221e5SJean-Philippe Brucker 59745221e5SJean-Philippe Brucker state.num = 0; 60745221e5SJean-Philippe Brucker r = ioctl(vhost_fd, VHOST_SET_VRING_BASE, &state); 61745221e5SJean-Philippe Brucker if (r < 0) 62745221e5SJean-Philippe Brucker die_perror("VHOST_SET_VRING_BASE failed"); 63745221e5SJean-Philippe Brucker 64745221e5SJean-Philippe Brucker r = ioctl(vhost_fd, VHOST_SET_VRING_ADDR, &addr); 65745221e5SJean-Philippe Brucker if (r < 0) 66745221e5SJean-Philippe Brucker die_perror("VHOST_SET_VRING_ADDR failed"); 67745221e5SJean-Philippe Brucker } 68*676c0c8aSJean-Philippe Brucker 69*676c0c8aSJean-Philippe Brucker void virtio_vhost_set_vring_kick(struct kvm *kvm, int vhost_fd, 70*676c0c8aSJean-Philippe Brucker u32 index, int event_fd) 71*676c0c8aSJean-Philippe Brucker { 72*676c0c8aSJean-Philippe Brucker int r; 73*676c0c8aSJean-Philippe Brucker struct vhost_vring_file file = { 74*676c0c8aSJean-Philippe Brucker .index = index, 75*676c0c8aSJean-Philippe Brucker .fd = event_fd, 76*676c0c8aSJean-Philippe Brucker }; 77*676c0c8aSJean-Philippe Brucker 78*676c0c8aSJean-Philippe Brucker r = ioctl(vhost_fd, VHOST_SET_VRING_KICK, &file); 79*676c0c8aSJean-Philippe Brucker if (r < 0) 80*676c0c8aSJean-Philippe Brucker die_perror("VHOST_SET_VRING_KICK failed"); 81*676c0c8aSJean-Philippe Brucker } 82