1a67da3beSAsias He #include "kvm/virtio-scsi.h" 2a67da3beSAsias He #include "kvm/virtio-pci-dev.h" 3a67da3beSAsias He #include "kvm/disk-image.h" 4a67da3beSAsias He #include "kvm/kvm.h" 5a67da3beSAsias He #include "kvm/pci.h" 6a67da3beSAsias He #include "kvm/ioeventfd.h" 7a67da3beSAsias He #include "kvm/guest_compat.h" 8a67da3beSAsias He #include "kvm/virtio-pci.h" 9a67da3beSAsias He #include "kvm/virtio.h" 10a67da3beSAsias He 11a67da3beSAsias He #include <linux/kernel.h> 12a67da3beSAsias He #include <linux/virtio_scsi.h> 13a67da3beSAsias He #include <linux/vhost.h> 14a67da3beSAsias He 15a67da3beSAsias He #define VIRTIO_SCSI_QUEUE_SIZE 128 16a67da3beSAsias He #define NUM_VIRT_QUEUES 3 17a67da3beSAsias He 18a67da3beSAsias He static LIST_HEAD(sdevs); 19a67da3beSAsias He static int compat_id = -1; 20a67da3beSAsias He 21a67da3beSAsias He struct scsi_dev { 22a67da3beSAsias He struct virt_queue vqs[NUM_VIRT_QUEUES]; 23a67da3beSAsias He struct virtio_scsi_config config; 24a67da3beSAsias He struct vhost_scsi_target target; 25a67da3beSAsias He u32 features; 26a67da3beSAsias He int vhost_fd; 27a67da3beSAsias He struct virtio_device vdev; 28a67da3beSAsias He struct list_head list; 29a67da3beSAsias He struct kvm *kvm; 30a67da3beSAsias He }; 31a67da3beSAsias He 32*c5ae742bSSasha Levin static u8 *get_config(struct kvm *kvm, void *dev) 33a67da3beSAsias He { 34a67da3beSAsias He struct scsi_dev *sdev = dev; 35a67da3beSAsias He 36*c5ae742bSSasha Levin return ((u8 *)(&sdev->config)); 37a67da3beSAsias He } 38a67da3beSAsias He 39a67da3beSAsias He static u32 get_host_features(struct kvm *kvm, void *dev) 40a67da3beSAsias He { 41a67da3beSAsias He return 1UL << VIRTIO_RING_F_EVENT_IDX | 42a67da3beSAsias He 1UL << VIRTIO_RING_F_INDIRECT_DESC; 43a67da3beSAsias He } 44a67da3beSAsias He 45a67da3beSAsias He static void set_guest_features(struct kvm *kvm, void *dev, u32 features) 46a67da3beSAsias He { 47a67da3beSAsias He struct scsi_dev *sdev = dev; 48a67da3beSAsias He 49a67da3beSAsias He sdev->features = features; 50a67da3beSAsias He } 51a67da3beSAsias He 52a67da3beSAsias He static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn) 53a67da3beSAsias He { 54a67da3beSAsias He struct vhost_vring_state state = { .index = vq }; 55a67da3beSAsias He struct vhost_vring_addr addr; 56a67da3beSAsias He struct scsi_dev *sdev = dev; 57a67da3beSAsias He struct virt_queue *queue; 58a67da3beSAsias He void *p; 59a67da3beSAsias He int r; 60a67da3beSAsias He 61a67da3beSAsias He compat__remove_message(compat_id); 62a67da3beSAsias He 63a67da3beSAsias He queue = &sdev->vqs[vq]; 64a67da3beSAsias He queue->pfn = pfn; 65a67da3beSAsias He p = guest_pfn_to_host(kvm, queue->pfn); 66a67da3beSAsias He 67a67da3beSAsias He vring_init(&queue->vring, VIRTIO_SCSI_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN); 68a67da3beSAsias He 69a67da3beSAsias He if (sdev->vhost_fd == 0) 70a67da3beSAsias He return 0; 71a67da3beSAsias He 72a67da3beSAsias He state.num = queue->vring.num; 73a67da3beSAsias He r = ioctl(sdev->vhost_fd, VHOST_SET_VRING_NUM, &state); 74a67da3beSAsias He if (r < 0) 75a67da3beSAsias He die_perror("VHOST_SET_VRING_NUM failed"); 76a67da3beSAsias He state.num = 0; 77a67da3beSAsias He r = ioctl(sdev->vhost_fd, VHOST_SET_VRING_BASE, &state); 78a67da3beSAsias He if (r < 0) 79a67da3beSAsias He die_perror("VHOST_SET_VRING_BASE failed"); 80a67da3beSAsias He 81a67da3beSAsias He addr = (struct vhost_vring_addr) { 82a67da3beSAsias He .index = vq, 83a67da3beSAsias He .desc_user_addr = (u64)(unsigned long)queue->vring.desc, 84a67da3beSAsias He .avail_user_addr = (u64)(unsigned long)queue->vring.avail, 85a67da3beSAsias He .used_user_addr = (u64)(unsigned long)queue->vring.used, 86a67da3beSAsias He }; 87a67da3beSAsias He 88a67da3beSAsias He r = ioctl(sdev->vhost_fd, VHOST_SET_VRING_ADDR, &addr); 89a67da3beSAsias He if (r < 0) 90a67da3beSAsias He die_perror("VHOST_SET_VRING_ADDR failed"); 91a67da3beSAsias He 92a67da3beSAsias He return 0; 93a67da3beSAsias He } 94a67da3beSAsias He 95a67da3beSAsias He static void notify_vq_gsi(struct kvm *kvm, void *dev, u32 vq, u32 gsi) 96a67da3beSAsias He { 97a67da3beSAsias He struct vhost_vring_file file; 98a67da3beSAsias He struct scsi_dev *sdev = dev; 99a67da3beSAsias He struct kvm_irqfd irq; 100a67da3beSAsias He int r; 101a67da3beSAsias He 102a67da3beSAsias He if (sdev->vhost_fd == 0) 103a67da3beSAsias He return; 104a67da3beSAsias He 105a67da3beSAsias He irq = (struct kvm_irqfd) { 106a67da3beSAsias He .gsi = gsi, 107a67da3beSAsias He .fd = eventfd(0, 0), 108a67da3beSAsias He }; 109a67da3beSAsias He file = (struct vhost_vring_file) { 110a67da3beSAsias He .index = vq, 111a67da3beSAsias He .fd = irq.fd, 112a67da3beSAsias He }; 113a67da3beSAsias He 114a67da3beSAsias He r = ioctl(kvm->vm_fd, KVM_IRQFD, &irq); 115a67da3beSAsias He if (r < 0) 116a67da3beSAsias He die_perror("KVM_IRQFD failed"); 117a67da3beSAsias He 118a67da3beSAsias He r = ioctl(sdev->vhost_fd, VHOST_SET_VRING_CALL, &file); 119a67da3beSAsias He if (r < 0) 120a67da3beSAsias He die_perror("VHOST_SET_VRING_CALL failed"); 121a67da3beSAsias He 122a67da3beSAsias He if (vq > 0) 123a67da3beSAsias He return; 124a67da3beSAsias He 125a67da3beSAsias He r = ioctl(sdev->vhost_fd, VHOST_SCSI_SET_ENDPOINT, &sdev->target); 126a67da3beSAsias He if (r != 0) 127a67da3beSAsias He die("VHOST_SCSI_SET_ENDPOINT failed %d", errno); 128a67da3beSAsias He } 129a67da3beSAsias He 130a67da3beSAsias He static void notify_vq_eventfd(struct kvm *kvm, void *dev, u32 vq, u32 efd) 131a67da3beSAsias He { 132a67da3beSAsias He struct scsi_dev *sdev = dev; 133a67da3beSAsias He struct vhost_vring_file file = { 134a67da3beSAsias He .index = vq, 135a67da3beSAsias He .fd = efd, 136a67da3beSAsias He }; 137a67da3beSAsias He int r; 138a67da3beSAsias He 139a67da3beSAsias He if (sdev->vhost_fd == 0) 140a67da3beSAsias He return; 141a67da3beSAsias He 142a67da3beSAsias He r = ioctl(sdev->vhost_fd, VHOST_SET_VRING_KICK, &file); 143a67da3beSAsias He if (r < 0) 144a67da3beSAsias He die_perror("VHOST_SET_VRING_KICK failed"); 145a67da3beSAsias He } 146a67da3beSAsias He 147a67da3beSAsias He static int notify_vq(struct kvm *kvm, void *dev, u32 vq) 148a67da3beSAsias He { 149a67da3beSAsias He return 0; 150a67da3beSAsias He } 151a67da3beSAsias He 152a67da3beSAsias He static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq) 153a67da3beSAsias He { 154a67da3beSAsias He struct scsi_dev *sdev = dev; 155a67da3beSAsias He 156a67da3beSAsias He return sdev->vqs[vq].pfn; 157a67da3beSAsias He } 158a67da3beSAsias He 159a67da3beSAsias He static int get_size_vq(struct kvm *kvm, void *dev, u32 vq) 160a67da3beSAsias He { 161a67da3beSAsias He return VIRTIO_SCSI_QUEUE_SIZE; 162a67da3beSAsias He } 163a67da3beSAsias He 164a67da3beSAsias He static int set_size_vq(struct kvm *kvm, void *dev, u32 vq, int size) 165a67da3beSAsias He { 166a67da3beSAsias He return size; 167a67da3beSAsias He } 168a67da3beSAsias He 169a67da3beSAsias He static struct virtio_ops scsi_dev_virtio_ops = (struct virtio_ops) { 170a67da3beSAsias He .get_config = get_config, 171a67da3beSAsias He .get_host_features = get_host_features, 172a67da3beSAsias He .set_guest_features = set_guest_features, 173a67da3beSAsias He .init_vq = init_vq, 174a67da3beSAsias He .get_pfn_vq = get_pfn_vq, 175a67da3beSAsias He .get_size_vq = get_size_vq, 176a67da3beSAsias He .set_size_vq = set_size_vq, 177a67da3beSAsias He .notify_vq = notify_vq, 178a67da3beSAsias He .notify_vq_gsi = notify_vq_gsi, 179a67da3beSAsias He .notify_vq_eventfd = notify_vq_eventfd, 180a67da3beSAsias He }; 181a67da3beSAsias He 182a67da3beSAsias He static void virtio_scsi_vhost_init(struct kvm *kvm, struct scsi_dev *sdev) 183a67da3beSAsias He { 184a67da3beSAsias He struct vhost_memory *mem; 185a67da3beSAsias He u64 features; 186a67da3beSAsias He int r; 187a67da3beSAsias He 188a67da3beSAsias He sdev->vhost_fd = open("/dev/vhost-scsi", O_RDWR); 189a67da3beSAsias He if (sdev->vhost_fd < 0) 190a67da3beSAsias He die_perror("Failed openning vhost-scsi device"); 191a67da3beSAsias He 192a67da3beSAsias He mem = calloc(1, sizeof(*mem) + sizeof(struct vhost_memory_region)); 193a67da3beSAsias He if (mem == NULL) 194a67da3beSAsias He die("Failed allocating memory for vhost memory map"); 195a67da3beSAsias He 196a67da3beSAsias He mem->nregions = 1; 197a67da3beSAsias He mem->regions[0] = (struct vhost_memory_region) { 198a67da3beSAsias He .guest_phys_addr = 0, 199a67da3beSAsias He .memory_size = kvm->ram_size, 200a67da3beSAsias He .userspace_addr = (unsigned long)kvm->ram_start, 201a67da3beSAsias He }; 202a67da3beSAsias He 203a67da3beSAsias He r = ioctl(sdev->vhost_fd, VHOST_SET_OWNER); 204a67da3beSAsias He if (r != 0) 205a67da3beSAsias He die_perror("VHOST_SET_OWNER failed"); 206a67da3beSAsias He 207a67da3beSAsias He r = ioctl(sdev->vhost_fd, VHOST_GET_FEATURES, &features); 208a67da3beSAsias He if (r != 0) 209a67da3beSAsias He die_perror("VHOST_GET_FEATURES failed"); 210a67da3beSAsias He 211a67da3beSAsias He r = ioctl(sdev->vhost_fd, VHOST_SET_FEATURES, &features); 212a67da3beSAsias He if (r != 0) 213a67da3beSAsias He die_perror("VHOST_SET_FEATURES failed"); 214a67da3beSAsias He r = ioctl(sdev->vhost_fd, VHOST_SET_MEM_TABLE, mem); 215a67da3beSAsias He if (r != 0) 216a67da3beSAsias He die_perror("VHOST_SET_MEM_TABLE failed"); 217a67da3beSAsias He 218a67da3beSAsias He sdev->vdev.use_vhost = true; 219a67da3beSAsias He 220a67da3beSAsias He free(mem); 221a67da3beSAsias He } 222a67da3beSAsias He 223a67da3beSAsias He 224a67da3beSAsias He static int virtio_scsi_init_one(struct kvm *kvm, struct disk_image *disk) 225a67da3beSAsias He { 226a67da3beSAsias He struct scsi_dev *sdev; 227a67da3beSAsias He 228a67da3beSAsias He if (!disk) 229a67da3beSAsias He return -EINVAL; 230a67da3beSAsias He 231a67da3beSAsias He sdev = calloc(1, sizeof(struct scsi_dev)); 232a67da3beSAsias He if (sdev == NULL) 233a67da3beSAsias He return -ENOMEM; 234a67da3beSAsias He 235a67da3beSAsias He *sdev = (struct scsi_dev) { 236a67da3beSAsias He .config = (struct virtio_scsi_config) { 237a67da3beSAsias He .num_queues = NUM_VIRT_QUEUES - 2, 238a67da3beSAsias He .seg_max = VIRTIO_SCSI_CDB_SIZE - 2, 239a67da3beSAsias He .max_sectors = 65535, 240a67da3beSAsias He .cmd_per_lun = 128, 241a67da3beSAsias He .sense_size = VIRTIO_SCSI_SENSE_SIZE, 242a67da3beSAsias He .cdb_size = VIRTIO_SCSI_CDB_SIZE, 243a67da3beSAsias He .max_channel = 0, 244a67da3beSAsias He .max_target = 0, 245a67da3beSAsias He .max_lun = 16383, 246a67da3beSAsias He .event_info_size = sizeof(struct virtio_scsi_event), 247a67da3beSAsias He }, 248a67da3beSAsias He .kvm = kvm, 249a67da3beSAsias He }; 250a67da3beSAsias He strncpy((char *)&sdev->target.vhost_wwpn, disk->wwpn, sizeof(sdev->target.vhost_wwpn)); 251a67da3beSAsias He sdev->target.vhost_tpgt = strtol(disk->tpgt, NULL, 0); 252a67da3beSAsias He 253a67da3beSAsias He virtio_init(kvm, sdev, &sdev->vdev, &scsi_dev_virtio_ops, 254a67da3beSAsias He VIRTIO_PCI, PCI_DEVICE_ID_VIRTIO_SCSI, VIRTIO_ID_SCSI, PCI_CLASS_BLK); 255a67da3beSAsias He 256a67da3beSAsias He list_add_tail(&sdev->list, &sdevs); 257a67da3beSAsias He 258a67da3beSAsias He virtio_scsi_vhost_init(kvm, sdev); 259a67da3beSAsias He 260a67da3beSAsias He if (compat_id == -1) 261a67da3beSAsias He compat_id = virtio_compat_add_message("virtio-scsi", "CONFIG_VIRTIO_SCSI"); 262a67da3beSAsias He 263a67da3beSAsias He return 0; 264a67da3beSAsias He } 265a67da3beSAsias He 266a67da3beSAsias He static int virtio_scsi_exit_one(struct kvm *kvm, struct scsi_dev *sdev) 267a67da3beSAsias He { 268a67da3beSAsias He int r; 269a67da3beSAsias He 270a67da3beSAsias He r = ioctl(sdev->vhost_fd, VHOST_SCSI_CLEAR_ENDPOINT, &sdev->target); 271a67da3beSAsias He if (r != 0) 272a67da3beSAsias He die("VHOST_SCSI_CLEAR_ENDPOINT failed %d", errno); 273a67da3beSAsias He 274a67da3beSAsias He list_del(&sdev->list); 275a67da3beSAsias He free(sdev); 276a67da3beSAsias He 277a67da3beSAsias He return 0; 278a67da3beSAsias He } 279a67da3beSAsias He 280a67da3beSAsias He int virtio_scsi_init(struct kvm *kvm) 281a67da3beSAsias He { 282a67da3beSAsias He int i, r = 0; 283a67da3beSAsias He 284a67da3beSAsias He for (i = 0; i < kvm->nr_disks; i++) { 285a67da3beSAsias He if (!kvm->disks[i]->wwpn) 286a67da3beSAsias He continue; 287a67da3beSAsias He r = virtio_scsi_init_one(kvm, kvm->disks[i]); 288a67da3beSAsias He if (r < 0) 289a67da3beSAsias He goto cleanup; 290a67da3beSAsias He } 291a67da3beSAsias He 292a67da3beSAsias He return 0; 293a67da3beSAsias He cleanup: 294a67da3beSAsias He return virtio_scsi_exit(kvm); 295a67da3beSAsias He } 296a67da3beSAsias He 297a67da3beSAsias He int virtio_scsi_exit(struct kvm *kvm) 298a67da3beSAsias He { 299a67da3beSAsias He while (!list_empty(&sdevs)) { 300a67da3beSAsias He struct scsi_dev *sdev; 301a67da3beSAsias He 302a67da3beSAsias He sdev = list_first_entry(&sdevs, struct scsi_dev, list); 303a67da3beSAsias He virtio_scsi_exit_one(kvm, sdev); 304a67da3beSAsias He } 305a67da3beSAsias He 306a67da3beSAsias He return 0; 307a67da3beSAsias He } 308