Add linux-next specific files for 20110831
[linux-2.6/next.git] / tools / kvm / virtio / core.c
blobd7c132b1ade6560af773ff2d34959a32450b62eb
1 #include <linux/virtio_ring.h>
2 #include <linux/types.h>
3 #include <sys/uio.h>
5 #include "kvm/barrier.h"
7 #include "kvm/kvm.h"
8 #include "kvm/virtio.h"
10 struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32 head, u32 len)
12 struct vring_used_elem *used_elem;
14 used_elem = &queue->vring.used->ring[queue->vring.used->idx % queue->vring.num];
15 used_elem->id = head;
16 used_elem->len = len;
19 * Use wmb to assure that used elem was updated with head and len.
20 * We need a wmb here since we can't advance idx unless we're ready
21 * to pass the used element to the guest.
23 wmb();
24 queue->vring.used->idx++;
27 * Use wmb to assure used idx has been increased before we signal the guest.
28 * Without a wmb here the guest may ignore the queue since it won't see
29 * an updated idx.
31 wmb();
33 return used_elem;
36 u16 virt_queue__get_iov(struct virt_queue *queue, struct iovec iov[], u16 *out, u16 *in, struct kvm *kvm)
38 struct vring_desc *desc;
39 u16 head, idx;
41 idx = head = virt_queue__pop(queue);
42 *out = *in = 0;
44 do {
45 desc = virt_queue__get_desc(queue, idx);
46 iov[*out + *in].iov_base = guest_flat_to_host(kvm, desc->addr);
47 iov[*out + *in].iov_len = desc->len;
48 if (desc->flags & VRING_DESC_F_WRITE)
49 (*in)++;
50 else
51 (*out)++;
52 if (desc->flags & VRING_DESC_F_NEXT)
53 idx = desc->next;
54 else
55 break;
56 } while (1);
58 return head;
61 /* in and out are relative to guest */
62 u16 virt_queue__get_inout_iov(struct kvm *kvm, struct virt_queue *queue,
63 struct iovec in_iov[], struct iovec out_iov[],
64 u16 *in, u16 *out)
66 u16 head, idx;
67 struct vring_desc *desc;
69 idx = head = virt_queue__pop(queue);
70 *out = *in = 0;
71 do {
72 desc = virt_queue__get_desc(queue, idx);
73 if (desc->flags & VRING_DESC_F_WRITE) {
74 in_iov[*in].iov_base = guest_flat_to_host(kvm,
75 desc->addr);
76 in_iov[*in].iov_len = desc->len;
77 (*in)++;
78 } else {
79 out_iov[*out].iov_base = guest_flat_to_host(kvm,
80 desc->addr);
81 out_iov[*out].iov_len = desc->len;
82 (*out)++;
84 if (desc->flags & VRING_DESC_F_NEXT)
85 idx = desc->next;
86 else
87 break;
88 } while (1);
89 return head;
93 void virt_queue__trigger_irq(struct virt_queue *vq, int irq, u8 *isr, struct kvm *kvm)
95 if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
96 return;
98 if (*isr == VIRTIO_IRQ_LOW) {
99 *isr = VIRTIO_IRQ_HIGH;
100 kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH);
104 int virtio__get_dev_specific_field(int offset, bool msix, bool features_hi, u32 *config_off)
106 if (msix) {
107 if (offset < 4)
108 return VIRTIO_PCI_O_MSIX;
109 else
110 offset -= 4;
113 if (features_hi) {
114 if (offset < 4)
115 return VIRTIO_PCI_O_FEATURES;
116 else
117 offset -= 4;
120 *config_off = offset;
122 return VIRTIO_PCI_O_CONFIG;