diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2007-10-21 21:03:40 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2007-10-23 01:49:55 -0400 |
commit | 0a8a69dd77ddbd4513b21363021ecde7e1025502 (patch) | |
tree | ed6d8f0756835390b4c0d9a172422f2e42a65523 /include/linux | |
parent | b01d9f2863349b0e041b90c3c86a998ee0fed2b0 (diff) |
Virtio helper routines for a descriptor ringbuffer implementation
These helper routines supply most of the virtqueue_ops for hypervisors
which want to use a ring for virtio. Unlike the previous lguest
implementation:
1) The rings are variable sized (2^n-1 elements).
2) They have an unfortunate limit of 65535 bytes per sg element.
3) The page numbers are always 64 bit (PAE anyone?)
4) They no longer place used[] on a separate page, just a separate
cacheline.
5) We do a modulo on a variable. We could be tricky if we cared.
6) Interrupts and notifies are suppressed using flags within the rings.
Users need only get the ring pages and provide a notify hook (KVM
wants the guest to allocate the rings, lguest does it sanely).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Dor Laor <dor.laor@qumranet.com>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/virtio_ring.h | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h new file mode 100644 index 000000000000..ac69e7bb5a14 --- /dev/null +++ b/include/linux/virtio_ring.h | |||
@@ -0,0 +1,119 @@ | |||
1 | #ifndef _LINUX_VIRTIO_RING_H | ||
2 | #define _LINUX_VIRTIO_RING_H | ||
3 | /* An interface for efficient virtio implementation, currently for use by KVM | ||
4 | * and lguest, but hopefully others soon. Do NOT change this since it will | ||
5 | * break existing servers and clients. | ||
6 | * | ||
7 | * This header is BSD licensed so anyone can use the definitions to implement | ||
8 | * compatible drivers/servers. | ||
9 | * | ||
10 | * Copyright Rusty Russell IBM Corporation 2007. */ | ||
11 | #include <linux/types.h> | ||
12 | |||
13 | /* This marks a buffer as continuing via the next field. */ | ||
14 | #define VRING_DESC_F_NEXT 1 | ||
15 | /* This marks a buffer as write-only (otherwise read-only). */ | ||
16 | #define VRING_DESC_F_WRITE 2 | ||
17 | |||
18 | /* This means don't notify other side when buffer added. */ | ||
19 | #define VRING_USED_F_NO_NOTIFY 1 | ||
20 | /* This means don't interrupt guest when buffer consumed. */ | ||
21 | #define VRING_AVAIL_F_NO_INTERRUPT 1 | ||
22 | |||
23 | /* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ | ||
24 | struct vring_desc | ||
25 | { | ||
26 | /* Address (guest-physical). */ | ||
27 | __u64 addr; | ||
28 | /* Length. */ | ||
29 | __u32 len; | ||
30 | /* The flags as indicated above. */ | ||
31 | __u16 flags; | ||
32 | /* We chain unused descriptors via this, too */ | ||
33 | __u16 next; | ||
34 | }; | ||
35 | |||
36 | struct vring_avail | ||
37 | { | ||
38 | __u16 flags; | ||
39 | __u16 idx; | ||
40 | __u16 ring[]; | ||
41 | }; | ||
42 | |||
43 | /* u32 is used here for ids for padding reasons. */ | ||
44 | struct vring_used_elem | ||
45 | { | ||
46 | /* Index of start of used descriptor chain. */ | ||
47 | __u32 id; | ||
48 | /* Total length of the descriptor chain which was used (written to) */ | ||
49 | __u32 len; | ||
50 | }; | ||
51 | |||
52 | struct vring_used | ||
53 | { | ||
54 | __u16 flags; | ||
55 | __u16 idx; | ||
56 | struct vring_used_elem ring[]; | ||
57 | }; | ||
58 | |||
59 | struct vring { | ||
60 | unsigned int num; | ||
61 | |||
62 | struct vring_desc *desc; | ||
63 | |||
64 | struct vring_avail *avail; | ||
65 | |||
66 | struct vring_used *used; | ||
67 | }; | ||
68 | |||
69 | /* The standard layout for the ring is a continuous chunk of memory which looks | ||
70 | * like this. The used fields will be aligned to a "num+1" boundary. | ||
71 | * | ||
72 | * struct vring | ||
73 | * { | ||
74 | * // The actual descriptors (16 bytes each) | ||
75 | * struct vring_desc desc[num]; | ||
76 | * | ||
77 | * // A ring of available descriptor heads with free-running index. | ||
78 | * __u16 avail_flags; | ||
79 | * __u16 avail_idx; | ||
80 | * __u16 available[num]; | ||
81 | * | ||
82 | * // Padding so a correctly-chosen num value will cache-align used_idx. | ||
83 | * char pad[sizeof(struct vring_desc) - sizeof(avail_flags)]; | ||
84 | * | ||
85 | * // A ring of used descriptor heads with free-running index. | ||
86 | * __u16 used_flags; | ||
87 | * __u16 used_idx; | ||
88 | * struct vring_used_elem used[num]; | ||
89 | * }; | ||
90 | */ | ||
91 | static inline void vring_init(struct vring *vr, unsigned int num, void *p) | ||
92 | { | ||
93 | vr->num = num; | ||
94 | vr->desc = p; | ||
95 | vr->avail = p + num*sizeof(struct vring); | ||
96 | vr->used = p + (num+1)*(sizeof(struct vring) + sizeof(__u16)); | ||
97 | } | ||
98 | |||
99 | static inline unsigned vring_size(unsigned int num) | ||
100 | { | ||
101 | return (num + 1) * (sizeof(struct vring_desc) + sizeof(__u16)) | ||
102 | + sizeof(__u32) + num * sizeof(struct vring_used_elem); | ||
103 | } | ||
104 | |||
105 | #ifdef __KERNEL__ | ||
106 | #include <linux/irqreturn.h> | ||
107 | struct virtio_device; | ||
108 | struct virtqueue; | ||
109 | |||
110 | struct virtqueue *vring_new_virtqueue(unsigned int num, | ||
111 | struct virtio_device *vdev, | ||
112 | void *pages, | ||
113 | void (*notify)(struct virtqueue *vq), | ||
114 | bool (*callback)(struct virtqueue *vq)); | ||
115 | void vring_del_virtqueue(struct virtqueue *vq); | ||
116 | |||
117 | irqreturn_t vring_interrupt(int irq, void *_vq); | ||
118 | #endif /* __KERNEL__ */ | ||
119 | #endif /* _LINUX_VIRTIO_RING_H */ | ||