1 #include <linux/virtio_ring.h> 2 #include <linux/types.h> 3 #include <sys/uio.h> 4 #include <stdlib.h> 5 6 #include "kvm/guest_compat.h" 7 #include "kvm/barrier.h" 8 #include "kvm/virtio.h" 9 #include "kvm/virtio-pci.h" 10 #include "kvm/virtio-mmio.h" 11 #include "kvm/util.h" 12 #include "kvm/kvm.h" 13 14 15 const char* virtio_trans_name(enum virtio_trans trans) 16 { 17 if (trans == VIRTIO_PCI) 18 return "pci"; 19 else if (trans == VIRTIO_MMIO) 20 return "mmio"; 21 return "unknown"; 22 } 23 24 struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32 head, u32 len) 25 { 26 struct vring_used_elem *used_elem; 27 u16 idx = virtio_guest_to_host_u16(queue, queue->vring.used->idx); 28 29 used_elem = &queue->vring.used->ring[idx % queue->vring.num]; 30 used_elem->id = virtio_host_to_guest_u32(queue, head); 31 used_elem->len = virtio_host_to_guest_u32(queue, len); 32 33 /* 34 * Use wmb to assure that used elem was updated with head and len. 35 * We need a wmb here since we can't advance idx unless we're ready 36 * to pass the used element to the guest. 37 */ 38 wmb(); 39 idx++; 40 queue->vring.used->idx = virtio_host_to_guest_u16(queue, idx); 41 42 /* 43 * Use wmb to assure used idx has been increased before we signal the guest. 44 * Without a wmb here the guest may ignore the queue since it won't see 45 * an updated idx. 46 */ 47 wmb(); 48 49 return used_elem; 50 } 51 52 static inline bool virt_desc__test_flag(struct virt_queue *vq, 53 struct vring_desc *desc, u16 flag) 54 { 55 return !!(virtio_guest_to_host_u16(vq, desc->flags) & flag); 56 } 57 58 /* 59 * Each buffer in the virtqueues is actually a chain of descriptors. This 60 * function returns the next descriptor in the chain, or vq->vring.num if we're 61 * at the end. 62 */ 63 static unsigned next_desc(struct virt_queue *vq, struct vring_desc *desc, 64 unsigned int i, unsigned int max) 65 { 66 unsigned int next; 67 68 /* If this descriptor says it doesn't chain, we're done. */ 69 if (!virt_desc__test_flag(vq, &desc[i], VRING_DESC_F_NEXT)) 70 return max; 71 72 /* Check they're not leading us off end of descriptors. */ 73 next = virtio_guest_to_host_u16(vq, desc[i].next); 74 /* Make sure compiler knows to grab that: we don't want it changing! */ 75 wmb(); 76 77 return next; 78 } 79 80 u16 virt_queue__get_head_iov(struct virt_queue *vq, struct iovec iov[], u16 *out, u16 *in, u16 head, struct kvm *kvm) 81 { 82 struct vring_desc *desc; 83 u16 idx; 84 u16 max; 85 86 idx = head; 87 *out = *in = 0; 88 max = vq->vring.num; 89 desc = vq->vring.desc; 90 91 if (virt_desc__test_flag(vq, &desc[idx], VRING_DESC_F_INDIRECT)) { 92 max = virtio_guest_to_host_u32(vq, desc[idx].len) / sizeof(struct vring_desc); 93 desc = guest_flat_to_host(kvm, virtio_guest_to_host_u64(vq, desc[idx].addr)); 94 idx = 0; 95 } 96 97 do { 98 /* Grab the first descriptor, and check it's OK. */ 99 iov[*out + *in].iov_len = virtio_guest_to_host_u32(vq, desc[idx].len); 100 iov[*out + *in].iov_base = guest_flat_to_host(kvm, 101 virtio_guest_to_host_u64(vq, desc[idx].addr)); 102 /* If this is an input descriptor, increment that count. */ 103 if (virt_desc__test_flag(vq, &desc[idx], VRING_DESC_F_WRITE)) 104 (*in)++; 105 else 106 (*out)++; 107 } while ((idx = next_desc(vq, desc, idx, max)) != max); 108 109 return head; 110 } 111 112 u16 virt_queue__get_iov(struct virt_queue *vq, struct iovec iov[], u16 *out, u16 *in, struct kvm *kvm) 113 { 114 u16 head; 115 116 head = virt_queue__pop(vq); 117 118 return virt_queue__get_head_iov(vq, iov, out, in, head, kvm); 119 } 120 121 /* in and out are relative to guest */ 122 u16 virt_queue__get_inout_iov(struct kvm *kvm, struct virt_queue *queue, 123 struct iovec in_iov[], struct iovec out_iov[], 124 u16 *in, u16 *out) 125 { 126 struct vring_desc *desc; 127 u16 head, idx; 128 129 idx = head = virt_queue__pop(queue); 130 *out = *in = 0; 131 do { 132 u64 addr; 133 desc = virt_queue__get_desc(queue, idx); 134 addr = virtio_guest_to_host_u64(queue, desc->addr); 135 if (virt_desc__test_flag(queue, desc, VRING_DESC_F_WRITE)) { 136 in_iov[*in].iov_base = guest_flat_to_host(kvm, addr); 137 in_iov[*in].iov_len = virtio_guest_to_host_u32(queue, desc->len); 138 (*in)++; 139 } else { 140 out_iov[*out].iov_base = guest_flat_to_host(kvm, addr); 141 out_iov[*out].iov_len = virtio_guest_to_host_u32(queue, desc->len); 142 (*out)++; 143 } 144 if (virt_desc__test_flag(queue, desc, VRING_DESC_F_NEXT)) 145 idx = virtio_guest_to_host_u16(queue, desc->next); 146 else 147 break; 148 } while (1); 149 150 return head; 151 } 152 153 int virtio__get_dev_specific_field(int offset, bool msix, u32 *config_off) 154 { 155 if (msix) { 156 if (offset < 4) 157 return VIRTIO_PCI_O_MSIX; 158 else 159 offset -= 4; 160 } 161 162 *config_off = offset; 163 164 return VIRTIO_PCI_O_CONFIG; 165 } 166 167 bool virtio_queue__should_signal(struct virt_queue *vq) 168 { 169 u16 old_idx, new_idx, event_idx; 170 171 old_idx = vq->last_used_signalled; 172 new_idx = virtio_guest_to_host_u16(vq, vq->vring.used->idx); 173 event_idx = virtio_guest_to_host_u16(vq, vring_used_event(&vq->vring)); 174 175 if (vring_need_event(event_idx, new_idx, old_idx)) { 176 vq->last_used_signalled = new_idx; 177 return true; 178 } 179 180 return false; 181 } 182 183 int virtio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev, 184 struct virtio_ops *ops, enum virtio_trans trans, 185 int device_id, int subsys_id, int class) 186 { 187 void *virtio; 188 189 switch (trans) { 190 case VIRTIO_PCI: 191 virtio = calloc(sizeof(struct virtio_pci), 1); 192 if (!virtio) 193 return -ENOMEM; 194 vdev->virtio = virtio; 195 vdev->ops = ops; 196 vdev->ops->signal_vq = virtio_pci__signal_vq; 197 vdev->ops->signal_config = virtio_pci__signal_config; 198 vdev->ops->init = virtio_pci__init; 199 vdev->ops->exit = virtio_pci__exit; 200 vdev->ops->init(kvm, dev, vdev, device_id, subsys_id, class); 201 break; 202 case VIRTIO_MMIO: 203 virtio = calloc(sizeof(struct virtio_mmio), 1); 204 if (!virtio) 205 return -ENOMEM; 206 vdev->virtio = virtio; 207 vdev->ops = ops; 208 vdev->ops->signal_vq = virtio_mmio_signal_vq; 209 vdev->ops->signal_config = virtio_mmio_signal_config; 210 vdev->ops->init = virtio_mmio_init; 211 vdev->ops->exit = virtio_mmio_exit; 212 vdev->ops->init(kvm, dev, vdev, device_id, subsys_id, class); 213 break; 214 default: 215 return -1; 216 }; 217 218 return 0; 219 } 220 221 int virtio_compat_add_message(const char *device, const char *config) 222 { 223 int len = 1024; 224 int compat_id; 225 char *title; 226 char *desc; 227 228 title = malloc(len); 229 if (!title) 230 return -ENOMEM; 231 232 desc = malloc(len); 233 if (!desc) { 234 free(title); 235 return -ENOMEM; 236 } 237 238 snprintf(title, len, "%s device was not detected.", device); 239 snprintf(desc, len, "While you have requested a %s device, " 240 "the guest kernel did not initialize it.\n" 241 "\tPlease make sure that the guest kernel was " 242 "compiled with %s=y enabled in .config.", 243 device, config); 244 245 compat_id = compat__add_message(title, desc); 246 247 free(desc); 248 free(title); 249 250 return compat_id; 251 } 252