diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 17:14:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 17:14:04 -0400 |
commit | 736a2dd2571ac56b11ed95a7814d838d5311be04 (patch) | |
tree | de10d107025970c6e51d5b6faeba799ed4b9caae /include/linux | |
parent | 0b2e3b6bb4a415379f16e38fc92db42379be47a1 (diff) | |
parent | 01d779a14ef800b74684d9692add4944df052461 (diff) |
Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull virtio & lguest updates from Rusty Russell:
"Lots of virtio work which wasn't quite ready for last merge window.
Plus I dived into lguest again, reworking the pagetable code so we can
move the switcher page: our fixmaps sometimes take more than 2MB now..."
Ugh. Annoying conflicts with the tcm_vhost -> vhost_scsi rename.
Hopefully correctly resolved.
* tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux: (57 commits)
caif_virtio: Remove bouncing email addresses
lguest: improve code readability in lg_cpu_start.
virtio-net: fill only rx queues which are being used
lguest: map Switcher below fixmap.
lguest: cache last cpu we ran on.
lguest: map Switcher text whenever we allocate a new pagetable.
lguest: don't share Switcher PTE pages between guests.
lguest: expost switcher_pages array (as lg_switcher_pages).
lguest: extract shadow PTE walking / allocating.
lguest: make check_gpte et. al return bool.
lguest: assume Switcher text is a single page.
lguest: rename switcher_page to switcher_pages.
lguest: remove RESERVE_MEM constant.
lguest: check vaddr not pgd for Switcher protection.
lguest: prepare to make SWITCHER_ADDR a variable.
virtio: console: replace EMFILE with EBUSY for already-open port
virtio-scsi: reset virtqueue affinity when doing cpu hotplug
virtio-scsi: introduce multiqueue support
virtio-scsi: push vq lock/unlock into virtscsi_vq_done
virtio-scsi: pass struct virtio_scsi to virtqueue completion function
...
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/scatterlist.h | 16 | ||||
-rw-r--r-- | include/linux/virtio.h | 20 | ||||
-rw-r--r-- | include/linux/virtio_caif.h | 24 | ||||
-rw-r--r-- | include/linux/virtio_ring.h | 57 | ||||
-rw-r--r-- | include/linux/vringh.h | 225 |
5 files changed, 342 insertions, 0 deletions
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 2d8bdaef9611..bfc47e0de81c 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h | |||
@@ -172,6 +172,22 @@ static inline void sg_mark_end(struct scatterlist *sg) | |||
172 | } | 172 | } |
173 | 173 | ||
174 | /** | 174 | /** |
175 | * sg_unmark_end - Undo setting the end of the scatterlist | ||
176 | * @sg: SG entryScatterlist | ||
177 | * | ||
178 | * Description: | ||
179 | * Removes the termination marker from the given entry of the scatterlist. | ||
180 | * | ||
181 | **/ | ||
182 | static inline void sg_unmark_end(struct scatterlist *sg) | ||
183 | { | ||
184 | #ifdef CONFIG_DEBUG_SG | ||
185 | BUG_ON(sg->sg_magic != SG_MAGIC); | ||
186 | #endif | ||
187 | sg->page_link &= ~0x02; | ||
188 | } | ||
189 | |||
190 | /** | ||
175 | * sg_phys - Return physical address of an sg entry | 191 | * sg_phys - Return physical address of an sg entry |
176 | * @sg: SG entry | 192 | * @sg: SG entry |
177 | * | 193 | * |
diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 2d7a5e045908..9ff8645b7e0b 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/device.h> | 8 | #include <linux/device.h> |
9 | #include <linux/mod_devicetable.h> | 9 | #include <linux/mod_devicetable.h> |
10 | #include <linux/gfp.h> | 10 | #include <linux/gfp.h> |
11 | #include <linux/vringh.h> | ||
11 | 12 | ||
12 | /** | 13 | /** |
13 | * virtqueue - a queue to register buffers for sending or receiving. | 14 | * virtqueue - a queue to register buffers for sending or receiving. |
@@ -40,6 +41,23 @@ int virtqueue_add_buf(struct virtqueue *vq, | |||
40 | void *data, | 41 | void *data, |
41 | gfp_t gfp); | 42 | gfp_t gfp); |
42 | 43 | ||
44 | int virtqueue_add_outbuf(struct virtqueue *vq, | ||
45 | struct scatterlist sg[], unsigned int num, | ||
46 | void *data, | ||
47 | gfp_t gfp); | ||
48 | |||
49 | int virtqueue_add_inbuf(struct virtqueue *vq, | ||
50 | struct scatterlist sg[], unsigned int num, | ||
51 | void *data, | ||
52 | gfp_t gfp); | ||
53 | |||
54 | int virtqueue_add_sgs(struct virtqueue *vq, | ||
55 | struct scatterlist *sgs[], | ||
56 | unsigned int out_sgs, | ||
57 | unsigned int in_sgs, | ||
58 | void *data, | ||
59 | gfp_t gfp); | ||
60 | |||
43 | void virtqueue_kick(struct virtqueue *vq); | 61 | void virtqueue_kick(struct virtqueue *vq); |
44 | 62 | ||
45 | bool virtqueue_kick_prepare(struct virtqueue *vq); | 63 | bool virtqueue_kick_prepare(struct virtqueue *vq); |
@@ -64,6 +82,7 @@ unsigned int virtqueue_get_vring_size(struct virtqueue *vq); | |||
64 | * @dev: underlying device. | 82 | * @dev: underlying device. |
65 | * @id: the device type identification (used to match it with a driver). | 83 | * @id: the device type identification (used to match it with a driver). |
66 | * @config: the configuration ops for this device. | 84 | * @config: the configuration ops for this device. |
85 | * @vringh_config: configuration ops for host vrings. | ||
67 | * @vqs: the list of virtqueues for this device. | 86 | * @vqs: the list of virtqueues for this device. |
68 | * @features: the features supported by both driver and device. | 87 | * @features: the features supported by both driver and device. |
69 | * @priv: private pointer for the driver's use. | 88 | * @priv: private pointer for the driver's use. |
@@ -73,6 +92,7 @@ struct virtio_device { | |||
73 | struct device dev; | 92 | struct device dev; |
74 | struct virtio_device_id id; | 93 | struct virtio_device_id id; |
75 | const struct virtio_config_ops *config; | 94 | const struct virtio_config_ops *config; |
95 | const struct vringh_config_ops *vringh_config; | ||
76 | struct list_head vqs; | 96 | struct list_head vqs; |
77 | /* Note that this is a Linux set_bit-style bitmap. */ | 97 | /* Note that this is a Linux set_bit-style bitmap. */ |
78 | unsigned long features[1]; | 98 | unsigned long features[1]; |
diff --git a/include/linux/virtio_caif.h b/include/linux/virtio_caif.h new file mode 100644 index 000000000000..5d2d3124ca3d --- /dev/null +++ b/include/linux/virtio_caif.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2012 | ||
3 | * Author: Sjur Brændeland <sjur.brandeland@stericsson.com> | ||
4 | * | ||
5 | * This header is BSD licensed so | ||
6 | * anyone can use the definitions to implement compatible remote processors | ||
7 | */ | ||
8 | |||
9 | #ifndef VIRTIO_CAIF_H | ||
10 | #define VIRTIO_CAIF_H | ||
11 | |||
12 | #include <linux/types.h> | ||
13 | struct virtio_caif_transf_config { | ||
14 | u16 headroom; | ||
15 | u16 tailroom; | ||
16 | u32 mtu; | ||
17 | u8 reserved[4]; | ||
18 | }; | ||
19 | |||
20 | struct virtio_caif_config { | ||
21 | struct virtio_caif_transf_config uplink, downlink; | ||
22 | u8 reserved[8]; | ||
23 | }; | ||
24 | #endif | ||
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index 63c6ea199519..ca3ad41c2c82 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h | |||
@@ -4,6 +4,63 @@ | |||
4 | #include <linux/irqreturn.h> | 4 | #include <linux/irqreturn.h> |
5 | #include <uapi/linux/virtio_ring.h> | 5 | #include <uapi/linux/virtio_ring.h> |
6 | 6 | ||
7 | /* | ||
8 | * Barriers in virtio are tricky. Non-SMP virtio guests can't assume | ||
9 | * they're not on an SMP host system, so they need to assume real | ||
10 | * barriers. Non-SMP virtio hosts could skip the barriers, but does | ||
11 | * anyone care? | ||
12 | * | ||
13 | * For virtio_pci on SMP, we don't need to order with respect to MMIO | ||
14 | * accesses through relaxed memory I/O windows, so smp_mb() et al are | ||
15 | * sufficient. | ||
16 | * | ||
17 | * For using virtio to talk to real devices (eg. other heterogeneous | ||
18 | * CPUs) we do need real barriers. In theory, we could be using both | ||
19 | * kinds of virtio, so it's a runtime decision, and the branch is | ||
20 | * actually quite cheap. | ||
21 | */ | ||
22 | |||
23 | #ifdef CONFIG_SMP | ||
24 | static inline void virtio_mb(bool weak_barriers) | ||
25 | { | ||
26 | if (weak_barriers) | ||
27 | smp_mb(); | ||
28 | else | ||
29 | mb(); | ||
30 | } | ||
31 | |||
32 | static inline void virtio_rmb(bool weak_barriers) | ||
33 | { | ||
34 | if (weak_barriers) | ||
35 | smp_rmb(); | ||
36 | else | ||
37 | rmb(); | ||
38 | } | ||
39 | |||
40 | static inline void virtio_wmb(bool weak_barriers) | ||
41 | { | ||
42 | if (weak_barriers) | ||
43 | smp_wmb(); | ||
44 | else | ||
45 | wmb(); | ||
46 | } | ||
47 | #else | ||
48 | static inline void virtio_mb(bool weak_barriers) | ||
49 | { | ||
50 | mb(); | ||
51 | } | ||
52 | |||
53 | static inline void virtio_rmb(bool weak_barriers) | ||
54 | { | ||
55 | rmb(); | ||
56 | } | ||
57 | |||
58 | static inline void virtio_wmb(bool weak_barriers) | ||
59 | { | ||
60 | wmb(); | ||
61 | } | ||
62 | #endif | ||
63 | |||
7 | struct virtio_device; | 64 | struct virtio_device; |
8 | struct virtqueue; | 65 | struct virtqueue; |
9 | 66 | ||
diff --git a/include/linux/vringh.h b/include/linux/vringh.h new file mode 100644 index 000000000000..749cde28728b --- /dev/null +++ b/include/linux/vringh.h | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * Linux host-side vring helpers; for when the kernel needs to access | ||
3 | * someone else's vring. | ||
4 | * | ||
5 | * Copyright IBM Corporation, 2013. | ||
6 | * Parts taken from drivers/vhost/vhost.c Copyright 2009 Red Hat, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | * Written by: Rusty Russell <rusty@rustcorp.com.au> | ||
23 | */ | ||
24 | #ifndef _LINUX_VRINGH_H | ||
25 | #define _LINUX_VRINGH_H | ||
26 | #include <uapi/linux/virtio_ring.h> | ||
27 | #include <linux/uio.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <asm/barrier.h> | ||
30 | |||
31 | /* virtio_ring with information needed for host access. */ | ||
32 | struct vringh { | ||
33 | /* Guest publishes used event idx (note: we always do). */ | ||
34 | bool event_indices; | ||
35 | |||
36 | /* Can we get away with weak barriers? */ | ||
37 | bool weak_barriers; | ||
38 | |||
39 | /* Last available index we saw (ie. where we're up to). */ | ||
40 | u16 last_avail_idx; | ||
41 | |||
42 | /* Last index we used. */ | ||
43 | u16 last_used_idx; | ||
44 | |||
45 | /* How many descriptors we've completed since last need_notify(). */ | ||
46 | u32 completed; | ||
47 | |||
48 | /* The vring (note: it may contain user pointers!) */ | ||
49 | struct vring vring; | ||
50 | |||
51 | /* The function to call to notify the guest about added buffers */ | ||
52 | void (*notify)(struct vringh *); | ||
53 | }; | ||
54 | |||
55 | /** | ||
56 | * struct vringh_config_ops - ops for creating a host vring from a virtio driver | ||
57 | * @find_vrhs: find the host vrings and instantiate them | ||
58 | * vdev: the virtio_device | ||
59 | * nhvrs: the number of host vrings to find | ||
60 | * hvrs: on success, includes new host vrings | ||
61 | * callbacks: array of driver callbacks, for each host vring | ||
62 | * include a NULL entry for vqs that do not need a callback | ||
63 | * Returns 0 on success or error status | ||
64 | * @del_vrhs: free the host vrings found by find_vrhs(). | ||
65 | */ | ||
66 | struct virtio_device; | ||
67 | typedef void vrh_callback_t(struct virtio_device *, struct vringh *); | ||
68 | struct vringh_config_ops { | ||
69 | int (*find_vrhs)(struct virtio_device *vdev, unsigned nhvrs, | ||
70 | struct vringh *vrhs[], vrh_callback_t *callbacks[]); | ||
71 | void (*del_vrhs)(struct virtio_device *vdev); | ||
72 | }; | ||
73 | |||
74 | /* The memory the vring can access, and what offset to apply. */ | ||
75 | struct vringh_range { | ||
76 | u64 start, end_incl; | ||
77 | u64 offset; | ||
78 | }; | ||
79 | |||
80 | /** | ||
81 | * struct vringh_iov - iovec mangler. | ||
82 | * | ||
83 | * Mangles iovec in place, and restores it. | ||
84 | * Remaining data is iov + i, of used - i elements. | ||
85 | */ | ||
86 | struct vringh_iov { | ||
87 | struct iovec *iov; | ||
88 | size_t consumed; /* Within iov[i] */ | ||
89 | unsigned i, used, max_num; | ||
90 | }; | ||
91 | |||
92 | /** | ||
93 | * struct vringh_iov - kvec mangler. | ||
94 | * | ||
95 | * Mangles kvec in place, and restores it. | ||
96 | * Remaining data is iov + i, of used - i elements. | ||
97 | */ | ||
98 | struct vringh_kiov { | ||
99 | struct kvec *iov; | ||
100 | size_t consumed; /* Within iov[i] */ | ||
101 | unsigned i, used, max_num; | ||
102 | }; | ||
103 | |||
104 | /* Flag on max_num to indicate we're kmalloced. */ | ||
105 | #define VRINGH_IOV_ALLOCATED 0x8000000 | ||
106 | |||
107 | /* Helpers for userspace vrings. */ | ||
108 | int vringh_init_user(struct vringh *vrh, u32 features, | ||
109 | unsigned int num, bool weak_barriers, | ||
110 | struct vring_desc __user *desc, | ||
111 | struct vring_avail __user *avail, | ||
112 | struct vring_used __user *used); | ||
113 | |||
114 | static inline void vringh_iov_init(struct vringh_iov *iov, | ||
115 | struct iovec *iovec, unsigned num) | ||
116 | { | ||
117 | iov->used = iov->i = 0; | ||
118 | iov->consumed = 0; | ||
119 | iov->max_num = num; | ||
120 | iov->iov = iovec; | ||
121 | } | ||
122 | |||
123 | static inline void vringh_iov_reset(struct vringh_iov *iov) | ||
124 | { | ||
125 | iov->iov[iov->i].iov_len += iov->consumed; | ||
126 | iov->iov[iov->i].iov_base -= iov->consumed; | ||
127 | iov->consumed = 0; | ||
128 | iov->i = 0; | ||
129 | } | ||
130 | |||
131 | static inline void vringh_iov_cleanup(struct vringh_iov *iov) | ||
132 | { | ||
133 | if (iov->max_num & VRINGH_IOV_ALLOCATED) | ||
134 | kfree(iov->iov); | ||
135 | iov->max_num = iov->used = iov->i = iov->consumed = 0; | ||
136 | iov->iov = NULL; | ||
137 | } | ||
138 | |||
139 | /* Convert a descriptor into iovecs. */ | ||
140 | int vringh_getdesc_user(struct vringh *vrh, | ||
141 | struct vringh_iov *riov, | ||
142 | struct vringh_iov *wiov, | ||
143 | bool (*getrange)(struct vringh *vrh, | ||
144 | u64 addr, struct vringh_range *r), | ||
145 | u16 *head); | ||
146 | |||
147 | /* Copy bytes from readable vsg, consuming it (and incrementing wiov->i). */ | ||
148 | ssize_t vringh_iov_pull_user(struct vringh_iov *riov, void *dst, size_t len); | ||
149 | |||
150 | /* Copy bytes into writable vsg, consuming it (and incrementing wiov->i). */ | ||
151 | ssize_t vringh_iov_push_user(struct vringh_iov *wiov, | ||
152 | const void *src, size_t len); | ||
153 | |||
154 | /* Mark a descriptor as used. */ | ||
155 | int vringh_complete_user(struct vringh *vrh, u16 head, u32 len); | ||
156 | int vringh_complete_multi_user(struct vringh *vrh, | ||
157 | const struct vring_used_elem used[], | ||
158 | unsigned num_used); | ||
159 | |||
160 | /* Pretend we've never seen descriptor (for easy error handling). */ | ||
161 | void vringh_abandon_user(struct vringh *vrh, unsigned int num); | ||
162 | |||
163 | /* Do we need to fire the eventfd to notify the other side? */ | ||
164 | int vringh_need_notify_user(struct vringh *vrh); | ||
165 | |||
166 | bool vringh_notify_enable_user(struct vringh *vrh); | ||
167 | void vringh_notify_disable_user(struct vringh *vrh); | ||
168 | |||
169 | /* Helpers for kernelspace vrings. */ | ||
170 | int vringh_init_kern(struct vringh *vrh, u32 features, | ||
171 | unsigned int num, bool weak_barriers, | ||
172 | struct vring_desc *desc, | ||
173 | struct vring_avail *avail, | ||
174 | struct vring_used *used); | ||
175 | |||
176 | static inline void vringh_kiov_init(struct vringh_kiov *kiov, | ||
177 | struct kvec *kvec, unsigned num) | ||
178 | { | ||
179 | kiov->used = kiov->i = 0; | ||
180 | kiov->consumed = 0; | ||
181 | kiov->max_num = num; | ||
182 | kiov->iov = kvec; | ||
183 | } | ||
184 | |||
185 | static inline void vringh_kiov_reset(struct vringh_kiov *kiov) | ||
186 | { | ||
187 | kiov->iov[kiov->i].iov_len += kiov->consumed; | ||
188 | kiov->iov[kiov->i].iov_base -= kiov->consumed; | ||
189 | kiov->consumed = 0; | ||
190 | kiov->i = 0; | ||
191 | } | ||
192 | |||
193 | static inline void vringh_kiov_cleanup(struct vringh_kiov *kiov) | ||
194 | { | ||
195 | if (kiov->max_num & VRINGH_IOV_ALLOCATED) | ||
196 | kfree(kiov->iov); | ||
197 | kiov->max_num = kiov->used = kiov->i = kiov->consumed = 0; | ||
198 | kiov->iov = NULL; | ||
199 | } | ||
200 | |||
201 | int vringh_getdesc_kern(struct vringh *vrh, | ||
202 | struct vringh_kiov *riov, | ||
203 | struct vringh_kiov *wiov, | ||
204 | u16 *head, | ||
205 | gfp_t gfp); | ||
206 | |||
207 | ssize_t vringh_iov_pull_kern(struct vringh_kiov *riov, void *dst, size_t len); | ||
208 | ssize_t vringh_iov_push_kern(struct vringh_kiov *wiov, | ||
209 | const void *src, size_t len); | ||
210 | void vringh_abandon_kern(struct vringh *vrh, unsigned int num); | ||
211 | int vringh_complete_kern(struct vringh *vrh, u16 head, u32 len); | ||
212 | |||
213 | bool vringh_notify_enable_kern(struct vringh *vrh); | ||
214 | void vringh_notify_disable_kern(struct vringh *vrh); | ||
215 | |||
216 | int vringh_need_notify_kern(struct vringh *vrh); | ||
217 | |||
218 | /* Notify the guest about buffers added to the used ring */ | ||
219 | static inline void vringh_notify(struct vringh *vrh) | ||
220 | { | ||
221 | if (vrh->notify) | ||
222 | vrh->notify(vrh); | ||
223 | } | ||
224 | |||
225 | #endif /* _LINUX_VRINGH_H */ | ||