diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-18 23:50:30 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-18 23:50:30 -0500 |
commit | 64ec45bff6b3dade2643ed4c0f688a15ecf46ea2 (patch) | |
tree | 29816f500d80a64c84455778918d94ff3ddf02e4 | |
parent | c0f486fde3f353232c1cc2fd4d62783ac782a467 (diff) | |
parent | 5ff16110c637726111662c1df41afd9df7ef36bd (diff) |
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
Pull virtio fixes from Michael S Tsirkin:
"virtio 1.0 related fixes
Most importantly, this fixes using virtio_pci as a module.
Further, the big virtio 1.0 conversion missed a couple of places.
This fixes them up.
This isn't 100% sparse-clean yet because on many architectures
get_user triggers sparse warnings when used with __bitwise tag (when
same tag is on both pointer and value read).
I posted a patchset to fix it up by adding __force on all arches that
don't already have it (many do), when that's merged these warnings
will go away"
* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
virtio_pci: restore module attributes
mic/host: fix up virtio 1.0 APIs
vringh: update for virtio 1.0 APIs
vringh: 64 bit features
tools/virtio: add virtio 1.0 in vringh_test
tools/virtio: add virtio 1.0 in virtio_test
tools/virtio: enable -Werror
tools/virtio: 64 bit features
tools/virtio: fix vringh test
tools/virtio: more stubs
virtio: core support for config generation
virtio_pci: add VIRTIO_PCI_NO_LEGACY
virtio_pci: move probe to common file
virtio_pci_common.h: drop VIRTIO_PCI_NO_LEGACY
virtio_config: fix virtio_cread_bytes
virtio: set VIRTIO_CONFIG_S_FEATURES_OK on restore
-rw-r--r-- | drivers/misc/mic/host/mic_debugfs.c | 18 | ||||
-rw-r--r-- | drivers/vhost/vringh.c | 125 | ||||
-rw-r--r-- | drivers/virtio/virtio.c | 37 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci_common.c | 39 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci_common.h | 7 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci_legacy.c | 24 | ||||
-rw-r--r-- | include/linux/virtio_config.h | 29 | ||||
-rw-r--r-- | include/linux/vringh.h | 37 | ||||
-rw-r--r-- | include/uapi/linux/virtio_pci.h | 15 | ||||
-rw-r--r-- | tools/virtio/Makefile | 2 | ||||
-rw-r--r-- | tools/virtio/linux/virtio.h | 1 | ||||
-rw-r--r-- | tools/virtio/linux/virtio_byteorder.h | 8 | ||||
-rw-r--r-- | tools/virtio/linux/virtio_config.h | 70 | ||||
-rw-r--r-- | tools/virtio/uapi/linux/virtio_types.h | 1 | ||||
-rw-r--r-- | tools/virtio/virtio_test.c | 15 | ||||
-rw-r--r-- | tools/virtio/vringh_test.c | 5 |
16 files changed, 324 insertions, 109 deletions
diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c index 028ba5d6fd1c..687e9aacf3bb 100644 --- a/drivers/misc/mic/host/mic_debugfs.c +++ b/drivers/misc/mic/host/mic_debugfs.c | |||
@@ -326,21 +326,27 @@ static int mic_vdev_info_show(struct seq_file *s, void *unused) | |||
326 | } | 326 | } |
327 | avail = vrh->vring.avail; | 327 | avail = vrh->vring.avail; |
328 | seq_printf(s, "avail flags 0x%x idx %d\n", | 328 | seq_printf(s, "avail flags 0x%x idx %d\n", |
329 | avail->flags, avail->idx & (num - 1)); | 329 | vringh16_to_cpu(vrh, avail->flags), |
330 | vringh16_to_cpu(vrh, avail->idx) & (num - 1)); | ||
330 | seq_printf(s, "avail flags 0x%x idx %d\n", | 331 | seq_printf(s, "avail flags 0x%x idx %d\n", |
331 | avail->flags, avail->idx); | 332 | vringh16_to_cpu(vrh, avail->flags), |
333 | vringh16_to_cpu(vrh, avail->idx)); | ||
332 | for (j = 0; j < num; j++) | 334 | for (j = 0; j < num; j++) |
333 | seq_printf(s, "avail ring[%d] %d\n", | 335 | seq_printf(s, "avail ring[%d] %d\n", |
334 | j, avail->ring[j]); | 336 | j, avail->ring[j]); |
335 | used = vrh->vring.used; | 337 | used = vrh->vring.used; |
336 | seq_printf(s, "used flags 0x%x idx %d\n", | 338 | seq_printf(s, "used flags 0x%x idx %d\n", |
337 | used->flags, used->idx & (num - 1)); | 339 | vringh16_to_cpu(vrh, used->flags), |
340 | vringh16_to_cpu(vrh, used->idx) & (num - 1)); | ||
338 | seq_printf(s, "used flags 0x%x idx %d\n", | 341 | seq_printf(s, "used flags 0x%x idx %d\n", |
339 | used->flags, used->idx); | 342 | vringh16_to_cpu(vrh, used->flags), |
343 | vringh16_to_cpu(vrh, used->idx)); | ||
340 | for (j = 0; j < num; j++) | 344 | for (j = 0; j < num; j++) |
341 | seq_printf(s, "used ring[%d] id %d len %d\n", | 345 | seq_printf(s, "used ring[%d] id %d len %d\n", |
342 | j, used->ring[j].id, | 346 | j, vringh32_to_cpu(vrh, |
343 | used->ring[j].len); | 347 | used->ring[j].id), |
348 | vringh32_to_cpu(vrh, | ||
349 | used->ring[j].len)); | ||
344 | } | 350 | } |
345 | } | 351 | } |
346 | mutex_unlock(&mdev->mic_mutex); | 352 | mutex_unlock(&mdev->mic_mutex); |
diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c index 5174ebac288d..3bb02c60a2f5 100644 --- a/drivers/vhost/vringh.c +++ b/drivers/vhost/vringh.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/uaccess.h> | 11 | #include <linux/uaccess.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/export.h> | 13 | #include <linux/export.h> |
14 | #include <uapi/linux/virtio_config.h> | ||
14 | 15 | ||
15 | static __printf(1,2) __cold void vringh_bad(const char *fmt, ...) | 16 | static __printf(1,2) __cold void vringh_bad(const char *fmt, ...) |
16 | { | 17 | { |
@@ -28,13 +29,14 @@ static __printf(1,2) __cold void vringh_bad(const char *fmt, ...) | |||
28 | 29 | ||
29 | /* Returns vring->num if empty, -ve on error. */ | 30 | /* Returns vring->num if empty, -ve on error. */ |
30 | static inline int __vringh_get_head(const struct vringh *vrh, | 31 | static inline int __vringh_get_head(const struct vringh *vrh, |
31 | int (*getu16)(u16 *val, const u16 *p), | 32 | int (*getu16)(const struct vringh *vrh, |
33 | u16 *val, const __virtio16 *p), | ||
32 | u16 *last_avail_idx) | 34 | u16 *last_avail_idx) |
33 | { | 35 | { |
34 | u16 avail_idx, i, head; | 36 | u16 avail_idx, i, head; |
35 | int err; | 37 | int err; |
36 | 38 | ||
37 | err = getu16(&avail_idx, &vrh->vring.avail->idx); | 39 | err = getu16(vrh, &avail_idx, &vrh->vring.avail->idx); |
38 | if (err) { | 40 | if (err) { |
39 | vringh_bad("Failed to access avail idx at %p", | 41 | vringh_bad("Failed to access avail idx at %p", |
40 | &vrh->vring.avail->idx); | 42 | &vrh->vring.avail->idx); |
@@ -49,7 +51,7 @@ static inline int __vringh_get_head(const struct vringh *vrh, | |||
49 | 51 | ||
50 | i = *last_avail_idx & (vrh->vring.num - 1); | 52 | i = *last_avail_idx & (vrh->vring.num - 1); |
51 | 53 | ||
52 | err = getu16(&head, &vrh->vring.avail->ring[i]); | 54 | err = getu16(vrh, &head, &vrh->vring.avail->ring[i]); |
53 | if (err) { | 55 | if (err) { |
54 | vringh_bad("Failed to read head: idx %d address %p", | 56 | vringh_bad("Failed to read head: idx %d address %p", |
55 | *last_avail_idx, &vrh->vring.avail->ring[i]); | 57 | *last_avail_idx, &vrh->vring.avail->ring[i]); |
@@ -144,28 +146,32 @@ static inline bool no_range_check(struct vringh *vrh, u64 addr, size_t *len, | |||
144 | } | 146 | } |
145 | 147 | ||
146 | /* No reason for this code to be inline. */ | 148 | /* No reason for this code to be inline. */ |
147 | static int move_to_indirect(int *up_next, u16 *i, void *addr, | 149 | static int move_to_indirect(const struct vringh *vrh, |
150 | int *up_next, u16 *i, void *addr, | ||
148 | const struct vring_desc *desc, | 151 | const struct vring_desc *desc, |
149 | struct vring_desc **descs, int *desc_max) | 152 | struct vring_desc **descs, int *desc_max) |
150 | { | 153 | { |
154 | u32 len; | ||
155 | |||
151 | /* Indirect tables can't have indirect. */ | 156 | /* Indirect tables can't have indirect. */ |
152 | if (*up_next != -1) { | 157 | if (*up_next != -1) { |
153 | vringh_bad("Multilevel indirect %u->%u", *up_next, *i); | 158 | vringh_bad("Multilevel indirect %u->%u", *up_next, *i); |
154 | return -EINVAL; | 159 | return -EINVAL; |
155 | } | 160 | } |
156 | 161 | ||
157 | if (unlikely(desc->len % sizeof(struct vring_desc))) { | 162 | len = vringh32_to_cpu(vrh, desc->len); |
163 | if (unlikely(len % sizeof(struct vring_desc))) { | ||
158 | vringh_bad("Strange indirect len %u", desc->len); | 164 | vringh_bad("Strange indirect len %u", desc->len); |
159 | return -EINVAL; | 165 | return -EINVAL; |
160 | } | 166 | } |
161 | 167 | ||
162 | /* We will check this when we follow it! */ | 168 | /* We will check this when we follow it! */ |
163 | if (desc->flags & VRING_DESC_F_NEXT) | 169 | if (desc->flags & cpu_to_vringh16(vrh, VRING_DESC_F_NEXT)) |
164 | *up_next = desc->next; | 170 | *up_next = vringh16_to_cpu(vrh, desc->next); |
165 | else | 171 | else |
166 | *up_next = -2; | 172 | *up_next = -2; |
167 | *descs = addr; | 173 | *descs = addr; |
168 | *desc_max = desc->len / sizeof(struct vring_desc); | 174 | *desc_max = len / sizeof(struct vring_desc); |
169 | 175 | ||
170 | /* Now, start at the first indirect. */ | 176 | /* Now, start at the first indirect. */ |
171 | *i = 0; | 177 | *i = 0; |
@@ -287,22 +293,25 @@ __vringh_iov(struct vringh *vrh, u16 i, | |||
287 | if (unlikely(err)) | 293 | if (unlikely(err)) |
288 | goto fail; | 294 | goto fail; |
289 | 295 | ||
290 | if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) { | 296 | if (unlikely(desc.flags & |
297 | cpu_to_vringh16(vrh, VRING_DESC_F_INDIRECT))) { | ||
298 | u64 a = vringh64_to_cpu(vrh, desc.addr); | ||
299 | |||
291 | /* Make sure it's OK, and get offset. */ | 300 | /* Make sure it's OK, and get offset. */ |
292 | len = desc.len; | 301 | len = vringh32_to_cpu(vrh, desc.len); |
293 | if (!rcheck(vrh, desc.addr, &len, &range, getrange)) { | 302 | if (!rcheck(vrh, a, &len, &range, getrange)) { |
294 | err = -EINVAL; | 303 | err = -EINVAL; |
295 | goto fail; | 304 | goto fail; |
296 | } | 305 | } |
297 | 306 | ||
298 | if (unlikely(len != desc.len)) { | 307 | if (unlikely(len != vringh32_to_cpu(vrh, desc.len))) { |
299 | slow = true; | 308 | slow = true; |
300 | /* We need to save this range to use offset */ | 309 | /* We need to save this range to use offset */ |
301 | slowrange = range; | 310 | slowrange = range; |
302 | } | 311 | } |
303 | 312 | ||
304 | addr = (void *)(long)(desc.addr + range.offset); | 313 | addr = (void *)(long)(a + range.offset); |
305 | err = move_to_indirect(&up_next, &i, addr, &desc, | 314 | err = move_to_indirect(vrh, &up_next, &i, addr, &desc, |
306 | &descs, &desc_max); | 315 | &descs, &desc_max); |
307 | if (err) | 316 | if (err) |
308 | goto fail; | 317 | goto fail; |
@@ -315,7 +324,7 @@ __vringh_iov(struct vringh *vrh, u16 i, | |||
315 | goto fail; | 324 | goto fail; |
316 | } | 325 | } |
317 | 326 | ||
318 | if (desc.flags & VRING_DESC_F_WRITE) | 327 | if (desc.flags & cpu_to_vringh16(vrh, VRING_DESC_F_WRITE)) |
319 | iov = wiov; | 328 | iov = wiov; |
320 | else { | 329 | else { |
321 | iov = riov; | 330 | iov = riov; |
@@ -336,12 +345,14 @@ __vringh_iov(struct vringh *vrh, u16 i, | |||
336 | 345 | ||
337 | again: | 346 | again: |
338 | /* Make sure it's OK, and get offset. */ | 347 | /* Make sure it's OK, and get offset. */ |
339 | len = desc.len; | 348 | len = vringh32_to_cpu(vrh, desc.len); |
340 | if (!rcheck(vrh, desc.addr, &len, &range, getrange)) { | 349 | if (!rcheck(vrh, vringh64_to_cpu(vrh, desc.addr), &len, &range, |
350 | getrange)) { | ||
341 | err = -EINVAL; | 351 | err = -EINVAL; |
342 | goto fail; | 352 | goto fail; |
343 | } | 353 | } |
344 | addr = (void *)(unsigned long)(desc.addr + range.offset); | 354 | addr = (void *)(unsigned long)(vringh64_to_cpu(vrh, desc.addr) + |
355 | range.offset); | ||
345 | 356 | ||
346 | if (unlikely(iov->used == (iov->max_num & ~VRINGH_IOV_ALLOCATED))) { | 357 | if (unlikely(iov->used == (iov->max_num & ~VRINGH_IOV_ALLOCATED))) { |
347 | err = resize_iovec(iov, gfp); | 358 | err = resize_iovec(iov, gfp); |
@@ -353,14 +364,16 @@ __vringh_iov(struct vringh *vrh, u16 i, | |||
353 | iov->iov[iov->used].iov_len = len; | 364 | iov->iov[iov->used].iov_len = len; |
354 | iov->used++; | 365 | iov->used++; |
355 | 366 | ||
356 | if (unlikely(len != desc.len)) { | 367 | if (unlikely(len != vringh32_to_cpu(vrh, desc.len))) { |
357 | desc.len -= len; | 368 | desc.len = cpu_to_vringh32(vrh, |
358 | desc.addr += len; | 369 | vringh32_to_cpu(vrh, desc.len) - len); |
370 | desc.addr = cpu_to_vringh64(vrh, | ||
371 | vringh64_to_cpu(vrh, desc.addr) + len); | ||
359 | goto again; | 372 | goto again; |
360 | } | 373 | } |
361 | 374 | ||
362 | if (desc.flags & VRING_DESC_F_NEXT) { | 375 | if (desc.flags & cpu_to_vringh16(vrh, VRING_DESC_F_NEXT)) { |
363 | i = desc.next; | 376 | i = vringh16_to_cpu(vrh, desc.next); |
364 | } else { | 377 | } else { |
365 | /* Just in case we need to finish traversing above. */ | 378 | /* Just in case we need to finish traversing above. */ |
366 | if (unlikely(up_next > 0)) { | 379 | if (unlikely(up_next > 0)) { |
@@ -387,7 +400,8 @@ fail: | |||
387 | static inline int __vringh_complete(struct vringh *vrh, | 400 | static inline int __vringh_complete(struct vringh *vrh, |
388 | const struct vring_used_elem *used, | 401 | const struct vring_used_elem *used, |
389 | unsigned int num_used, | 402 | unsigned int num_used, |
390 | int (*putu16)(u16 *p, u16 val), | 403 | int (*putu16)(const struct vringh *vrh, |
404 | __virtio16 *p, u16 val), | ||
391 | int (*putused)(struct vring_used_elem *dst, | 405 | int (*putused)(struct vring_used_elem *dst, |
392 | const struct vring_used_elem | 406 | const struct vring_used_elem |
393 | *src, unsigned num)) | 407 | *src, unsigned num)) |
@@ -420,7 +434,7 @@ static inline int __vringh_complete(struct vringh *vrh, | |||
420 | /* Make sure buffer is written before we update index. */ | 434 | /* Make sure buffer is written before we update index. */ |
421 | virtio_wmb(vrh->weak_barriers); | 435 | virtio_wmb(vrh->weak_barriers); |
422 | 436 | ||
423 | err = putu16(&vrh->vring.used->idx, used_idx + num_used); | 437 | err = putu16(vrh, &vrh->vring.used->idx, used_idx + num_used); |
424 | if (err) { | 438 | if (err) { |
425 | vringh_bad("Failed to update used index at %p", | 439 | vringh_bad("Failed to update used index at %p", |
426 | &vrh->vring.used->idx); | 440 | &vrh->vring.used->idx); |
@@ -433,7 +447,9 @@ static inline int __vringh_complete(struct vringh *vrh, | |||
433 | 447 | ||
434 | 448 | ||
435 | static inline int __vringh_need_notify(struct vringh *vrh, | 449 | static inline int __vringh_need_notify(struct vringh *vrh, |
436 | int (*getu16)(u16 *val, const u16 *p)) | 450 | int (*getu16)(const struct vringh *vrh, |
451 | u16 *val, | ||
452 | const __virtio16 *p)) | ||
437 | { | 453 | { |
438 | bool notify; | 454 | bool notify; |
439 | u16 used_event; | 455 | u16 used_event; |
@@ -447,7 +463,7 @@ static inline int __vringh_need_notify(struct vringh *vrh, | |||
447 | /* Old-style, without event indices. */ | 463 | /* Old-style, without event indices. */ |
448 | if (!vrh->event_indices) { | 464 | if (!vrh->event_indices) { |
449 | u16 flags; | 465 | u16 flags; |
450 | err = getu16(&flags, &vrh->vring.avail->flags); | 466 | err = getu16(vrh, &flags, &vrh->vring.avail->flags); |
451 | if (err) { | 467 | if (err) { |
452 | vringh_bad("Failed to get flags at %p", | 468 | vringh_bad("Failed to get flags at %p", |
453 | &vrh->vring.avail->flags); | 469 | &vrh->vring.avail->flags); |
@@ -457,7 +473,7 @@ static inline int __vringh_need_notify(struct vringh *vrh, | |||
457 | } | 473 | } |
458 | 474 | ||
459 | /* Modern: we know when other side wants to know. */ | 475 | /* Modern: we know when other side wants to know. */ |
460 | err = getu16(&used_event, &vring_used_event(&vrh->vring)); | 476 | err = getu16(vrh, &used_event, &vring_used_event(&vrh->vring)); |
461 | if (err) { | 477 | if (err) { |
462 | vringh_bad("Failed to get used event idx at %p", | 478 | vringh_bad("Failed to get used event idx at %p", |
463 | &vring_used_event(&vrh->vring)); | 479 | &vring_used_event(&vrh->vring)); |
@@ -478,20 +494,22 @@ static inline int __vringh_need_notify(struct vringh *vrh, | |||
478 | } | 494 | } |
479 | 495 | ||
480 | static inline bool __vringh_notify_enable(struct vringh *vrh, | 496 | static inline bool __vringh_notify_enable(struct vringh *vrh, |
481 | int (*getu16)(u16 *val, const u16 *p), | 497 | int (*getu16)(const struct vringh *vrh, |
482 | int (*putu16)(u16 *p, u16 val)) | 498 | u16 *val, const __virtio16 *p), |
499 | int (*putu16)(const struct vringh *vrh, | ||
500 | __virtio16 *p, u16 val)) | ||
483 | { | 501 | { |
484 | u16 avail; | 502 | u16 avail; |
485 | 503 | ||
486 | if (!vrh->event_indices) { | 504 | if (!vrh->event_indices) { |
487 | /* Old-school; update flags. */ | 505 | /* Old-school; update flags. */ |
488 | if (putu16(&vrh->vring.used->flags, 0) != 0) { | 506 | if (putu16(vrh, &vrh->vring.used->flags, 0) != 0) { |
489 | vringh_bad("Clearing used flags %p", | 507 | vringh_bad("Clearing used flags %p", |
490 | &vrh->vring.used->flags); | 508 | &vrh->vring.used->flags); |
491 | return true; | 509 | return true; |
492 | } | 510 | } |
493 | } else { | 511 | } else { |
494 | if (putu16(&vring_avail_event(&vrh->vring), | 512 | if (putu16(vrh, &vring_avail_event(&vrh->vring), |
495 | vrh->last_avail_idx) != 0) { | 513 | vrh->last_avail_idx) != 0) { |
496 | vringh_bad("Updating avail event index %p", | 514 | vringh_bad("Updating avail event index %p", |
497 | &vring_avail_event(&vrh->vring)); | 515 | &vring_avail_event(&vrh->vring)); |
@@ -503,7 +521,7 @@ static inline bool __vringh_notify_enable(struct vringh *vrh, | |||
503 | * sure it's written, then check again. */ | 521 | * sure it's written, then check again. */ |
504 | virtio_mb(vrh->weak_barriers); | 522 | virtio_mb(vrh->weak_barriers); |
505 | 523 | ||
506 | if (getu16(&avail, &vrh->vring.avail->idx) != 0) { | 524 | if (getu16(vrh, &avail, &vrh->vring.avail->idx) != 0) { |
507 | vringh_bad("Failed to check avail idx at %p", | 525 | vringh_bad("Failed to check avail idx at %p", |
508 | &vrh->vring.avail->idx); | 526 | &vrh->vring.avail->idx); |
509 | return true; | 527 | return true; |
@@ -516,11 +534,13 @@ static inline bool __vringh_notify_enable(struct vringh *vrh, | |||
516 | } | 534 | } |
517 | 535 | ||
518 | static inline void __vringh_notify_disable(struct vringh *vrh, | 536 | static inline void __vringh_notify_disable(struct vringh *vrh, |
519 | int (*putu16)(u16 *p, u16 val)) | 537 | int (*putu16)(const struct vringh *vrh, |
538 | __virtio16 *p, u16 val)) | ||
520 | { | 539 | { |
521 | if (!vrh->event_indices) { | 540 | if (!vrh->event_indices) { |
522 | /* Old-school; update flags. */ | 541 | /* Old-school; update flags. */ |
523 | if (putu16(&vrh->vring.used->flags, VRING_USED_F_NO_NOTIFY)) { | 542 | if (putu16(vrh, &vrh->vring.used->flags, |
543 | VRING_USED_F_NO_NOTIFY)) { | ||
524 | vringh_bad("Setting used flags %p", | 544 | vringh_bad("Setting used flags %p", |
525 | &vrh->vring.used->flags); | 545 | &vrh->vring.used->flags); |
526 | } | 546 | } |
@@ -528,14 +548,18 @@ static inline void __vringh_notify_disable(struct vringh *vrh, | |||
528 | } | 548 | } |
529 | 549 | ||
530 | /* Userspace access helpers: in this case, addresses are really userspace. */ | 550 | /* Userspace access helpers: in this case, addresses are really userspace. */ |
531 | static inline int getu16_user(u16 *val, const u16 *p) | 551 | static inline int getu16_user(const struct vringh *vrh, u16 *val, const __virtio16 *p) |
532 | { | 552 | { |
533 | return get_user(*val, (__force u16 __user *)p); | 553 | __virtio16 v = 0; |
554 | int rc = get_user(v, (__force __virtio16 __user *)p); | ||
555 | *val = vringh16_to_cpu(vrh, v); | ||
556 | return rc; | ||
534 | } | 557 | } |
535 | 558 | ||
536 | static inline int putu16_user(u16 *p, u16 val) | 559 | static inline int putu16_user(const struct vringh *vrh, __virtio16 *p, u16 val) |
537 | { | 560 | { |
538 | return put_user(val, (__force u16 __user *)p); | 561 | __virtio16 v = cpu_to_vringh16(vrh, val); |
562 | return put_user(v, (__force __virtio16 __user *)p); | ||
539 | } | 563 | } |
540 | 564 | ||
541 | static inline int copydesc_user(void *dst, const void *src, size_t len) | 565 | static inline int copydesc_user(void *dst, const void *src, size_t len) |
@@ -577,7 +601,7 @@ static inline int xfer_to_user(void *dst, void *src, size_t len) | |||
577 | * Returns an error if num is invalid: you should check pointers | 601 | * Returns an error if num is invalid: you should check pointers |
578 | * yourself! | 602 | * yourself! |
579 | */ | 603 | */ |
580 | int vringh_init_user(struct vringh *vrh, u32 features, | 604 | int vringh_init_user(struct vringh *vrh, u64 features, |
581 | unsigned int num, bool weak_barriers, | 605 | unsigned int num, bool weak_barriers, |
582 | struct vring_desc __user *desc, | 606 | struct vring_desc __user *desc, |
583 | struct vring_avail __user *avail, | 607 | struct vring_avail __user *avail, |
@@ -589,6 +613,7 @@ int vringh_init_user(struct vringh *vrh, u32 features, | |||
589 | return -EINVAL; | 613 | return -EINVAL; |
590 | } | 614 | } |
591 | 615 | ||
616 | vrh->little_endian = (features & (1ULL << VIRTIO_F_VERSION_1)); | ||
592 | vrh->event_indices = (features & (1 << VIRTIO_RING_F_EVENT_IDX)); | 617 | vrh->event_indices = (features & (1 << VIRTIO_RING_F_EVENT_IDX)); |
593 | vrh->weak_barriers = weak_barriers; | 618 | vrh->weak_barriers = weak_barriers; |
594 | vrh->completed = 0; | 619 | vrh->completed = 0; |
@@ -729,8 +754,8 @@ int vringh_complete_user(struct vringh *vrh, u16 head, u32 len) | |||
729 | { | 754 | { |
730 | struct vring_used_elem used; | 755 | struct vring_used_elem used; |
731 | 756 | ||
732 | used.id = head; | 757 | used.id = cpu_to_vringh32(vrh, head); |
733 | used.len = len; | 758 | used.len = cpu_to_vringh32(vrh, len); |
734 | return __vringh_complete(vrh, &used, 1, putu16_user, putused_user); | 759 | return __vringh_complete(vrh, &used, 1, putu16_user, putused_user); |
735 | } | 760 | } |
736 | EXPORT_SYMBOL(vringh_complete_user); | 761 | EXPORT_SYMBOL(vringh_complete_user); |
@@ -792,15 +817,16 @@ int vringh_need_notify_user(struct vringh *vrh) | |||
792 | EXPORT_SYMBOL(vringh_need_notify_user); | 817 | EXPORT_SYMBOL(vringh_need_notify_user); |
793 | 818 | ||
794 | /* Kernelspace access helpers. */ | 819 | /* Kernelspace access helpers. */ |
795 | static inline int getu16_kern(u16 *val, const u16 *p) | 820 | static inline int getu16_kern(const struct vringh *vrh, |
821 | u16 *val, const __virtio16 *p) | ||
796 | { | 822 | { |
797 | *val = ACCESS_ONCE(*p); | 823 | *val = vringh16_to_cpu(vrh, ACCESS_ONCE(*p)); |
798 | return 0; | 824 | return 0; |
799 | } | 825 | } |
800 | 826 | ||
801 | static inline int putu16_kern(u16 *p, u16 val) | 827 | static inline int putu16_kern(const struct vringh *vrh, __virtio16 *p, u16 val) |
802 | { | 828 | { |
803 | ACCESS_ONCE(*p) = val; | 829 | ACCESS_ONCE(*p) = cpu_to_vringh16(vrh, val); |
804 | return 0; | 830 | return 0; |
805 | } | 831 | } |
806 | 832 | ||
@@ -836,7 +862,7 @@ static inline int xfer_kern(void *src, void *dst, size_t len) | |||
836 | * | 862 | * |
837 | * Returns an error if num is invalid. | 863 | * Returns an error if num is invalid. |
838 | */ | 864 | */ |
839 | int vringh_init_kern(struct vringh *vrh, u32 features, | 865 | int vringh_init_kern(struct vringh *vrh, u64 features, |
840 | unsigned int num, bool weak_barriers, | 866 | unsigned int num, bool weak_barriers, |
841 | struct vring_desc *desc, | 867 | struct vring_desc *desc, |
842 | struct vring_avail *avail, | 868 | struct vring_avail *avail, |
@@ -848,6 +874,7 @@ int vringh_init_kern(struct vringh *vrh, u32 features, | |||
848 | return -EINVAL; | 874 | return -EINVAL; |
849 | } | 875 | } |
850 | 876 | ||
877 | vrh->little_endian = (features & (1ULL << VIRTIO_F_VERSION_1)); | ||
851 | vrh->event_indices = (features & (1 << VIRTIO_RING_F_EVENT_IDX)); | 878 | vrh->event_indices = (features & (1 << VIRTIO_RING_F_EVENT_IDX)); |
852 | vrh->weak_barriers = weak_barriers; | 879 | vrh->weak_barriers = weak_barriers; |
853 | vrh->completed = 0; | 880 | vrh->completed = 0; |
@@ -962,8 +989,8 @@ int vringh_complete_kern(struct vringh *vrh, u16 head, u32 len) | |||
962 | { | 989 | { |
963 | struct vring_used_elem used; | 990 | struct vring_used_elem used; |
964 | 991 | ||
965 | used.id = head; | 992 | used.id = cpu_to_vringh32(vrh, head); |
966 | used.len = len; | 993 | used.len = cpu_to_vringh32(vrh, len); |
967 | 994 | ||
968 | return __vringh_complete(vrh, &used, 1, putu16_kern, putused_kern); | 995 | return __vringh_complete(vrh, &used, 1, putu16_kern, putused_kern); |
969 | } | 996 | } |
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index f22665868781..b9f70dfc4751 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c | |||
@@ -162,6 +162,27 @@ static void virtio_config_enable(struct virtio_device *dev) | |||
162 | spin_unlock_irq(&dev->config_lock); | 162 | spin_unlock_irq(&dev->config_lock); |
163 | } | 163 | } |
164 | 164 | ||
165 | static int virtio_finalize_features(struct virtio_device *dev) | ||
166 | { | ||
167 | int ret = dev->config->finalize_features(dev); | ||
168 | unsigned status; | ||
169 | |||
170 | if (ret) | ||
171 | return ret; | ||
172 | |||
173 | if (!virtio_has_feature(dev, VIRTIO_F_VERSION_1)) | ||
174 | return 0; | ||
175 | |||
176 | add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); | ||
177 | status = dev->config->get_status(dev); | ||
178 | if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) { | ||
179 | dev_err(&dev->dev, "virtio: device refuses features: %x\n", | ||
180 | status); | ||
181 | return -ENODEV; | ||
182 | } | ||
183 | return 0; | ||
184 | } | ||
185 | |||
165 | static int virtio_dev_probe(struct device *_d) | 186 | static int virtio_dev_probe(struct device *_d) |
166 | { | 187 | { |
167 | int err, i; | 188 | int err, i; |
@@ -170,7 +191,6 @@ static int virtio_dev_probe(struct device *_d) | |||
170 | u64 device_features; | 191 | u64 device_features; |
171 | u64 driver_features; | 192 | u64 driver_features; |
172 | u64 driver_features_legacy; | 193 | u64 driver_features_legacy; |
173 | unsigned status; | ||
174 | 194 | ||
175 | /* We have a driver! */ | 195 | /* We have a driver! */ |
176 | add_status(dev, VIRTIO_CONFIG_S_DRIVER); | 196 | add_status(dev, VIRTIO_CONFIG_S_DRIVER); |
@@ -208,21 +228,10 @@ static int virtio_dev_probe(struct device *_d) | |||
208 | if (device_features & (1ULL << i)) | 228 | if (device_features & (1ULL << i)) |
209 | __virtio_set_bit(dev, i); | 229 | __virtio_set_bit(dev, i); |
210 | 230 | ||
211 | err = dev->config->finalize_features(dev); | 231 | err = virtio_finalize_features(dev); |
212 | if (err) | 232 | if (err) |
213 | goto err; | 233 | goto err; |
214 | 234 | ||
215 | if (virtio_has_feature(dev, VIRTIO_F_VERSION_1)) { | ||
216 | add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); | ||
217 | status = dev->config->get_status(dev); | ||
218 | if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) { | ||
219 | dev_err(_d, "virtio: device refuses features: %x\n", | ||
220 | status); | ||
221 | err = -ENODEV; | ||
222 | goto err; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | err = drv->probe(dev); | 235 | err = drv->probe(dev); |
227 | if (err) | 236 | if (err) |
228 | goto err; | 237 | goto err; |
@@ -372,7 +381,7 @@ int virtio_device_restore(struct virtio_device *dev) | |||
372 | /* We have a driver! */ | 381 | /* We have a driver! */ |
373 | add_status(dev, VIRTIO_CONFIG_S_DRIVER); | 382 | add_status(dev, VIRTIO_CONFIG_S_DRIVER); |
374 | 383 | ||
375 | ret = dev->config->finalize_features(dev); | 384 | ret = virtio_finalize_features(dev); |
376 | if (ret) | 385 | if (ret) |
377 | goto err; | 386 | goto err; |
378 | 387 | ||
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 953057d84185..2ef9529809d8 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c | |||
@@ -458,7 +458,44 @@ static int virtio_pci_restore(struct device *dev) | |||
458 | return virtio_device_restore(&vp_dev->vdev); | 458 | return virtio_device_restore(&vp_dev->vdev); |
459 | } | 459 | } |
460 | 460 | ||
461 | const struct dev_pm_ops virtio_pci_pm_ops = { | 461 | static const struct dev_pm_ops virtio_pci_pm_ops = { |
462 | SET_SYSTEM_SLEEP_PM_OPS(virtio_pci_freeze, virtio_pci_restore) | 462 | SET_SYSTEM_SLEEP_PM_OPS(virtio_pci_freeze, virtio_pci_restore) |
463 | }; | 463 | }; |
464 | #endif | 464 | #endif |
465 | |||
466 | |||
467 | /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */ | ||
468 | static const struct pci_device_id virtio_pci_id_table[] = { | ||
469 | { PCI_DEVICE(0x1af4, PCI_ANY_ID) }, | ||
470 | { 0 } | ||
471 | }; | ||
472 | |||
473 | MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); | ||
474 | |||
475 | static int virtio_pci_probe(struct pci_dev *pci_dev, | ||
476 | const struct pci_device_id *id) | ||
477 | { | ||
478 | return virtio_pci_legacy_probe(pci_dev, id); | ||
479 | } | ||
480 | |||
481 | static void virtio_pci_remove(struct pci_dev *pci_dev) | ||
482 | { | ||
483 | virtio_pci_legacy_remove(pci_dev); | ||
484 | } | ||
485 | |||
486 | static struct pci_driver virtio_pci_driver = { | ||
487 | .name = "virtio-pci", | ||
488 | .id_table = virtio_pci_id_table, | ||
489 | .probe = virtio_pci_probe, | ||
490 | .remove = virtio_pci_remove, | ||
491 | #ifdef CONFIG_PM_SLEEP | ||
492 | .driver.pm = &virtio_pci_pm_ops, | ||
493 | #endif | ||
494 | }; | ||
495 | |||
496 | module_pci_driver(virtio_pci_driver); | ||
497 | |||
498 | MODULE_AUTHOR("Anthony Liguori <aliguori@us.ibm.com>"); | ||
499 | MODULE_DESCRIPTION("virtio-pci"); | ||
500 | MODULE_LICENSE("GPL"); | ||
501 | MODULE_VERSION("1"); | ||
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h index d840dad4149d..adddb647b21d 100644 --- a/drivers/virtio/virtio_pci_common.h +++ b/drivers/virtio/virtio_pci_common.h | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/virtio.h> | 27 | #include <linux/virtio.h> |
28 | #include <linux/virtio_config.h> | 28 | #include <linux/virtio_config.h> |
29 | #include <linux/virtio_ring.h> | 29 | #include <linux/virtio_ring.h> |
30 | #define VIRTIO_PCI_NO_LEGACY | ||
31 | #include <linux/virtio_pci.h> | 30 | #include <linux/virtio_pci.h> |
32 | #include <linux/highmem.h> | 31 | #include <linux/highmem.h> |
33 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
@@ -129,8 +128,8 @@ const char *vp_bus_name(struct virtio_device *vdev); | |||
129 | int vp_set_vq_affinity(struct virtqueue *vq, int cpu); | 128 | int vp_set_vq_affinity(struct virtqueue *vq, int cpu); |
130 | void virtio_pci_release_dev(struct device *); | 129 | void virtio_pci_release_dev(struct device *); |
131 | 130 | ||
132 | #ifdef CONFIG_PM_SLEEP | 131 | int virtio_pci_legacy_probe(struct pci_dev *pci_dev, |
133 | extern const struct dev_pm_ops virtio_pci_pm_ops; | 132 | const struct pci_device_id *id); |
134 | #endif | 133 | void virtio_pci_legacy_remove(struct pci_dev *pci_dev); |
135 | 134 | ||
136 | #endif | 135 | #endif |
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c index 2588252e5c1c..6c76f0f5658c 100644 --- a/drivers/virtio/virtio_pci_legacy.c +++ b/drivers/virtio/virtio_pci_legacy.c | |||
@@ -19,14 +19,6 @@ | |||
19 | 19 | ||
20 | #include "virtio_pci_common.h" | 20 | #include "virtio_pci_common.h" |
21 | 21 | ||
22 | /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */ | ||
23 | static const struct pci_device_id virtio_pci_id_table[] = { | ||
24 | { PCI_DEVICE(0x1af4, PCI_ANY_ID) }, | ||
25 | { 0 } | ||
26 | }; | ||
27 | |||
28 | MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); | ||
29 | |||
30 | /* virtio config->get_features() implementation */ | 22 | /* virtio config->get_features() implementation */ |
31 | static u64 vp_get_features(struct virtio_device *vdev) | 23 | static u64 vp_get_features(struct virtio_device *vdev) |
32 | { | 24 | { |
@@ -220,7 +212,7 @@ static const struct virtio_config_ops virtio_pci_config_ops = { | |||
220 | }; | 212 | }; |
221 | 213 | ||
222 | /* the PCI probing function */ | 214 | /* the PCI probing function */ |
223 | static int virtio_pci_probe(struct pci_dev *pci_dev, | 215 | int virtio_pci_legacy_probe(struct pci_dev *pci_dev, |
224 | const struct pci_device_id *id) | 216 | const struct pci_device_id *id) |
225 | { | 217 | { |
226 | struct virtio_pci_device *vp_dev; | 218 | struct virtio_pci_device *vp_dev; |
@@ -300,7 +292,7 @@ out: | |||
300 | return err; | 292 | return err; |
301 | } | 293 | } |
302 | 294 | ||
303 | static void virtio_pci_remove(struct pci_dev *pci_dev) | 295 | void virtio_pci_legacy_remove(struct pci_dev *pci_dev) |
304 | { | 296 | { |
305 | struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); | 297 | struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); |
306 | 298 | ||
@@ -312,15 +304,3 @@ static void virtio_pci_remove(struct pci_dev *pci_dev) | |||
312 | pci_disable_device(pci_dev); | 304 | pci_disable_device(pci_dev); |
313 | kfree(vp_dev); | 305 | kfree(vp_dev); |
314 | } | 306 | } |
315 | |||
316 | static struct pci_driver virtio_pci_driver = { | ||
317 | .name = "virtio-pci", | ||
318 | .id_table = virtio_pci_id_table, | ||
319 | .probe = virtio_pci_probe, | ||
320 | .remove = virtio_pci_remove, | ||
321 | #ifdef CONFIG_PM_SLEEP | ||
322 | .driver.pm = &virtio_pci_pm_ops, | ||
323 | #endif | ||
324 | }; | ||
325 | |||
326 | module_pci_driver(virtio_pci_driver); | ||
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 7979f850e7ac..ca3ed78e5ec7 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h | |||
@@ -19,6 +19,9 @@ | |||
19 | * offset: the offset of the configuration field | 19 | * offset: the offset of the configuration field |
20 | * buf: the buffer to read the field value from. | 20 | * buf: the buffer to read the field value from. |
21 | * len: the length of the buffer | 21 | * len: the length of the buffer |
22 | * @generation: config generation counter | ||
23 | * vdev: the virtio_device | ||
24 | * Returns the config generation counter | ||
22 | * @get_status: read the status byte | 25 | * @get_status: read the status byte |
23 | * vdev: the virtio_device | 26 | * vdev: the virtio_device |
24 | * Returns the status byte | 27 | * Returns the status byte |
@@ -60,6 +63,7 @@ struct virtio_config_ops { | |||
60 | void *buf, unsigned len); | 63 | void *buf, unsigned len); |
61 | void (*set)(struct virtio_device *vdev, unsigned offset, | 64 | void (*set)(struct virtio_device *vdev, unsigned offset, |
62 | const void *buf, unsigned len); | 65 | const void *buf, unsigned len); |
66 | u32 (*generation)(struct virtio_device *vdev); | ||
63 | u8 (*get_status)(struct virtio_device *vdev); | 67 | u8 (*get_status)(struct virtio_device *vdev); |
64 | void (*set_status)(struct virtio_device *vdev, u8 status); | 68 | void (*set_status)(struct virtio_device *vdev, u8 status); |
65 | void (*reset)(struct virtio_device *vdev); | 69 | void (*reset)(struct virtio_device *vdev); |
@@ -301,11 +305,33 @@ static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset) | |||
301 | return ret; | 305 | return ret; |
302 | } | 306 | } |
303 | 307 | ||
308 | /* Read @count fields, @bytes each. */ | ||
309 | static inline void __virtio_cread_many(struct virtio_device *vdev, | ||
310 | unsigned int offset, | ||
311 | void *buf, size_t count, size_t bytes) | ||
312 | { | ||
313 | u32 old, gen = vdev->config->generation ? | ||
314 | vdev->config->generation(vdev) : 0; | ||
315 | int i; | ||
316 | |||
317 | do { | ||
318 | old = gen; | ||
319 | |||
320 | for (i = 0; i < count; i++) | ||
321 | vdev->config->get(vdev, offset + bytes * i, | ||
322 | buf + i * bytes, bytes); | ||
323 | |||
324 | gen = vdev->config->generation ? | ||
325 | vdev->config->generation(vdev) : 0; | ||
326 | } while (gen != old); | ||
327 | } | ||
328 | |||
329 | |||
304 | static inline void virtio_cread_bytes(struct virtio_device *vdev, | 330 | static inline void virtio_cread_bytes(struct virtio_device *vdev, |
305 | unsigned int offset, | 331 | unsigned int offset, |
306 | void *buf, size_t len) | 332 | void *buf, size_t len) |
307 | { | 333 | { |
308 | vdev->config->get(vdev, offset, buf, len); | 334 | __virtio_cread_many(vdev, offset, buf, len, 1); |
309 | } | 335 | } |
310 | 336 | ||
311 | static inline void virtio_cwrite8(struct virtio_device *vdev, | 337 | static inline void virtio_cwrite8(struct virtio_device *vdev, |
@@ -349,6 +375,7 @@ static inline u64 virtio_cread64(struct virtio_device *vdev, | |||
349 | { | 375 | { |
350 | u64 ret; | 376 | u64 ret; |
351 | vdev->config->get(vdev, offset, &ret, sizeof(ret)); | 377 | vdev->config->get(vdev, offset, &ret, sizeof(ret)); |
378 | __virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret)); | ||
352 | return virtio64_to_cpu(vdev, (__force __virtio64)ret); | 379 | return virtio64_to_cpu(vdev, (__force __virtio64)ret); |
353 | } | 380 | } |
354 | 381 | ||
diff --git a/include/linux/vringh.h b/include/linux/vringh.h index 749cde28728b..a3fa537e717a 100644 --- a/include/linux/vringh.h +++ b/include/linux/vringh.h | |||
@@ -24,12 +24,16 @@ | |||
24 | #ifndef _LINUX_VRINGH_H | 24 | #ifndef _LINUX_VRINGH_H |
25 | #define _LINUX_VRINGH_H | 25 | #define _LINUX_VRINGH_H |
26 | #include <uapi/linux/virtio_ring.h> | 26 | #include <uapi/linux/virtio_ring.h> |
27 | #include <linux/virtio_byteorder.h> | ||
27 | #include <linux/uio.h> | 28 | #include <linux/uio.h> |
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
29 | #include <asm/barrier.h> | 30 | #include <asm/barrier.h> |
30 | 31 | ||
31 | /* virtio_ring with information needed for host access. */ | 32 | /* virtio_ring with information needed for host access. */ |
32 | struct vringh { | 33 | struct vringh { |
34 | /* Everything is little endian */ | ||
35 | bool little_endian; | ||
36 | |||
33 | /* Guest publishes used event idx (note: we always do). */ | 37 | /* Guest publishes used event idx (note: we always do). */ |
34 | bool event_indices; | 38 | bool event_indices; |
35 | 39 | ||
@@ -105,7 +109,7 @@ struct vringh_kiov { | |||
105 | #define VRINGH_IOV_ALLOCATED 0x8000000 | 109 | #define VRINGH_IOV_ALLOCATED 0x8000000 |
106 | 110 | ||
107 | /* Helpers for userspace vrings. */ | 111 | /* Helpers for userspace vrings. */ |
108 | int vringh_init_user(struct vringh *vrh, u32 features, | 112 | int vringh_init_user(struct vringh *vrh, u64 features, |
109 | unsigned int num, bool weak_barriers, | 113 | unsigned int num, bool weak_barriers, |
110 | struct vring_desc __user *desc, | 114 | struct vring_desc __user *desc, |
111 | struct vring_avail __user *avail, | 115 | struct vring_avail __user *avail, |
@@ -167,7 +171,7 @@ bool vringh_notify_enable_user(struct vringh *vrh); | |||
167 | void vringh_notify_disable_user(struct vringh *vrh); | 171 | void vringh_notify_disable_user(struct vringh *vrh); |
168 | 172 | ||
169 | /* Helpers for kernelspace vrings. */ | 173 | /* Helpers for kernelspace vrings. */ |
170 | int vringh_init_kern(struct vringh *vrh, u32 features, | 174 | int vringh_init_kern(struct vringh *vrh, u64 features, |
171 | unsigned int num, bool weak_barriers, | 175 | unsigned int num, bool weak_barriers, |
172 | struct vring_desc *desc, | 176 | struct vring_desc *desc, |
173 | struct vring_avail *avail, | 177 | struct vring_avail *avail, |
@@ -222,4 +226,33 @@ static inline void vringh_notify(struct vringh *vrh) | |||
222 | vrh->notify(vrh); | 226 | vrh->notify(vrh); |
223 | } | 227 | } |
224 | 228 | ||
229 | static inline u16 vringh16_to_cpu(const struct vringh *vrh, __virtio16 val) | ||
230 | { | ||
231 | return __virtio16_to_cpu(vrh->little_endian, val); | ||
232 | } | ||
233 | |||
234 | static inline __virtio16 cpu_to_vringh16(const struct vringh *vrh, u16 val) | ||
235 | { | ||
236 | return __cpu_to_virtio16(vrh->little_endian, val); | ||
237 | } | ||
238 | |||
239 | static inline u32 vringh32_to_cpu(const struct vringh *vrh, __virtio32 val) | ||
240 | { | ||
241 | return __virtio32_to_cpu(vrh->little_endian, val); | ||
242 | } | ||
243 | |||
244 | static inline __virtio32 cpu_to_vringh32(const struct vringh *vrh, u32 val) | ||
245 | { | ||
246 | return __cpu_to_virtio32(vrh->little_endian, val); | ||
247 | } | ||
248 | |||
249 | static inline u64 vringh64_to_cpu(const struct vringh *vrh, __virtio64 val) | ||
250 | { | ||
251 | return __virtio64_to_cpu(vrh->little_endian, val); | ||
252 | } | ||
253 | |||
254 | static inline __virtio64 cpu_to_vringh64(const struct vringh *vrh, u64 val) | ||
255 | { | ||
256 | return __cpu_to_virtio64(vrh->little_endian, val); | ||
257 | } | ||
225 | #endif /* _LINUX_VRINGH_H */ | 258 | #endif /* _LINUX_VRINGH_H */ |
diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h index e5ec1caab82a..35b552c7f330 100644 --- a/include/uapi/linux/virtio_pci.h +++ b/include/uapi/linux/virtio_pci.h | |||
@@ -41,6 +41,8 @@ | |||
41 | 41 | ||
42 | #include <linux/virtio_config.h> | 42 | #include <linux/virtio_config.h> |
43 | 43 | ||
44 | #ifndef VIRTIO_PCI_NO_LEGACY | ||
45 | |||
44 | /* A 32-bit r/o bitmask of the features supported by the host */ | 46 | /* A 32-bit r/o bitmask of the features supported by the host */ |
45 | #define VIRTIO_PCI_HOST_FEATURES 0 | 47 | #define VIRTIO_PCI_HOST_FEATURES 0 |
46 | 48 | ||
@@ -67,16 +69,11 @@ | |||
67 | * a read-and-acknowledge. */ | 69 | * a read-and-acknowledge. */ |
68 | #define VIRTIO_PCI_ISR 19 | 70 | #define VIRTIO_PCI_ISR 19 |
69 | 71 | ||
70 | /* The bit of the ISR which indicates a device configuration change. */ | ||
71 | #define VIRTIO_PCI_ISR_CONFIG 0x2 | ||
72 | |||
73 | /* MSI-X registers: only enabled if MSI-X is enabled. */ | 72 | /* MSI-X registers: only enabled if MSI-X is enabled. */ |
74 | /* A 16-bit vector for configuration changes. */ | 73 | /* A 16-bit vector for configuration changes. */ |
75 | #define VIRTIO_MSI_CONFIG_VECTOR 20 | 74 | #define VIRTIO_MSI_CONFIG_VECTOR 20 |
76 | /* A 16-bit vector for selected queue notifications. */ | 75 | /* A 16-bit vector for selected queue notifications. */ |
77 | #define VIRTIO_MSI_QUEUE_VECTOR 22 | 76 | #define VIRTIO_MSI_QUEUE_VECTOR 22 |
78 | /* Vector value used to disable MSI for queue */ | ||
79 | #define VIRTIO_MSI_NO_VECTOR 0xffff | ||
80 | 77 | ||
81 | /* The remaining space is defined by each driver as the per-driver | 78 | /* The remaining space is defined by each driver as the per-driver |
82 | * configuration space */ | 79 | * configuration space */ |
@@ -94,4 +91,12 @@ | |||
94 | /* The alignment to use between consumer and producer parts of vring. | 91 | /* The alignment to use between consumer and producer parts of vring. |
95 | * x86 pagesize again. */ | 92 | * x86 pagesize again. */ |
96 | #define VIRTIO_PCI_VRING_ALIGN 4096 | 93 | #define VIRTIO_PCI_VRING_ALIGN 4096 |
94 | |||
95 | #endif /* VIRTIO_PCI_NO_LEGACY */ | ||
96 | |||
97 | /* The bit of the ISR which indicates a device configuration change. */ | ||
98 | #define VIRTIO_PCI_ISR_CONFIG 0x2 | ||
99 | /* Vector value used to disable MSI for queue */ | ||
100 | #define VIRTIO_MSI_NO_VECTOR 0xffff | ||
101 | |||
97 | #endif | 102 | #endif |
diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile index 9325f4693821..505ad51b3b51 100644 --- a/tools/virtio/Makefile +++ b/tools/virtio/Makefile | |||
@@ -3,7 +3,7 @@ test: virtio_test vringh_test | |||
3 | virtio_test: virtio_ring.o virtio_test.o | 3 | virtio_test: virtio_ring.o virtio_test.o |
4 | vringh_test: vringh_test.o vringh.o virtio_ring.o | 4 | vringh_test: vringh_test.o vringh.o virtio_ring.o |
5 | 5 | ||
6 | CFLAGS += -g -O2 -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE | 6 | CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE |
7 | vpath %.c ../../drivers/virtio ../../drivers/vhost | 7 | vpath %.c ../../drivers/virtio ../../drivers/vhost |
8 | mod: | 8 | mod: |
9 | ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test | 9 | ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test |
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h index 8eb6421761cd..a3e07016a440 100644 --- a/tools/virtio/linux/virtio.h +++ b/tools/virtio/linux/virtio.h | |||
@@ -6,6 +6,7 @@ | |||
6 | /* TODO: empty stubs for now. Broken but enough for virtio_ring.c */ | 6 | /* TODO: empty stubs for now. Broken but enough for virtio_ring.c */ |
7 | #define list_add_tail(a, b) do {} while (0) | 7 | #define list_add_tail(a, b) do {} while (0) |
8 | #define list_del(a) do {} while (0) | 8 | #define list_del(a) do {} while (0) |
9 | #define list_for_each_entry(a, b, c) while (0) | ||
9 | /* end of stubs */ | 10 | /* end of stubs */ |
10 | 11 | ||
11 | struct virtio_device { | 12 | struct virtio_device { |
diff --git a/tools/virtio/linux/virtio_byteorder.h b/tools/virtio/linux/virtio_byteorder.h new file mode 100644 index 000000000000..9de9e6ac1d10 --- /dev/null +++ b/tools/virtio/linux/virtio_byteorder.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _LINUX_VIRTIO_BYTEORDER_STUB_H | ||
2 | #define _LINUX_VIRTIO_BYTEORDER_STUB_H | ||
3 | |||
4 | #include <asm/byteorder.h> | ||
5 | #include "../../include/linux/byteorder/generic.h" | ||
6 | #include "../../include/linux/virtio_byteorder.h" | ||
7 | |||
8 | #endif | ||
diff --git a/tools/virtio/linux/virtio_config.h b/tools/virtio/linux/virtio_config.h index 83b27e8e9d72..806d683ab107 100644 --- a/tools/virtio/linux/virtio_config.h +++ b/tools/virtio/linux/virtio_config.h | |||
@@ -1,6 +1,72 @@ | |||
1 | #define VIRTIO_TRANSPORT_F_START 28 | 1 | #include <linux/virtio_byteorder.h> |
2 | #define VIRTIO_TRANSPORT_F_END 32 | 2 | #include <linux/virtio.h> |
3 | #include <uapi/linux/virtio_config.h> | ||
4 | |||
5 | /* | ||
6 | * __virtio_test_bit - helper to test feature bits. For use by transports. | ||
7 | * Devices should normally use virtio_has_feature, | ||
8 | * which includes more checks. | ||
9 | * @vdev: the device | ||
10 | * @fbit: the feature bit | ||
11 | */ | ||
12 | static inline bool __virtio_test_bit(const struct virtio_device *vdev, | ||
13 | unsigned int fbit) | ||
14 | { | ||
15 | return vdev->features & (1ULL << fbit); | ||
16 | } | ||
17 | |||
18 | /** | ||
19 | * __virtio_set_bit - helper to set feature bits. For use by transports. | ||
20 | * @vdev: the device | ||
21 | * @fbit: the feature bit | ||
22 | */ | ||
23 | static inline void __virtio_set_bit(struct virtio_device *vdev, | ||
24 | unsigned int fbit) | ||
25 | { | ||
26 | vdev->features |= (1ULL << fbit); | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * __virtio_clear_bit - helper to clear feature bits. For use by transports. | ||
31 | * @vdev: the device | ||
32 | * @fbit: the feature bit | ||
33 | */ | ||
34 | static inline void __virtio_clear_bit(struct virtio_device *vdev, | ||
35 | unsigned int fbit) | ||
36 | { | ||
37 | vdev->features &= ~(1ULL << fbit); | ||
38 | } | ||
3 | 39 | ||
4 | #define virtio_has_feature(dev, feature) \ | 40 | #define virtio_has_feature(dev, feature) \ |
5 | (__virtio_test_bit((dev), feature)) | 41 | (__virtio_test_bit((dev), feature)) |
6 | 42 | ||
43 | static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val) | ||
44 | { | ||
45 | return __virtio16_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
46 | } | ||
47 | |||
48 | static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val) | ||
49 | { | ||
50 | return __cpu_to_virtio16(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
51 | } | ||
52 | |||
53 | static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val) | ||
54 | { | ||
55 | return __virtio32_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
56 | } | ||
57 | |||
58 | static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val) | ||
59 | { | ||
60 | return __cpu_to_virtio32(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
61 | } | ||
62 | |||
63 | static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val) | ||
64 | { | ||
65 | return __virtio64_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
66 | } | ||
67 | |||
68 | static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val) | ||
69 | { | ||
70 | return __cpu_to_virtio64(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | ||
71 | } | ||
72 | |||
diff --git a/tools/virtio/uapi/linux/virtio_types.h b/tools/virtio/uapi/linux/virtio_types.h new file mode 100644 index 000000000000..e7a1096e7c97 --- /dev/null +++ b/tools/virtio/uapi/linux/virtio_types.h | |||
@@ -0,0 +1 @@ | |||
#include "../../include/uapi/linux/virtio_types.h" | |||
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c index db3437c641a6..e0445898f08f 100644 --- a/tools/virtio/virtio_test.c +++ b/tools/virtio/virtio_test.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <sys/types.h> | 11 | #include <sys/types.h> |
12 | #include <fcntl.h> | 12 | #include <fcntl.h> |
13 | #include <stdbool.h> | 13 | #include <stdbool.h> |
14 | #include <linux/virtio_types.h> | ||
14 | #include <linux/vhost.h> | 15 | #include <linux/vhost.h> |
15 | #include <linux/virtio.h> | 16 | #include <linux/virtio.h> |
16 | #include <linux/virtio_ring.h> | 17 | #include <linux/virtio_ring.h> |
@@ -227,6 +228,14 @@ const struct option longopts[] = { | |||
227 | .val = 'i', | 228 | .val = 'i', |
228 | }, | 229 | }, |
229 | { | 230 | { |
231 | .name = "virtio-1", | ||
232 | .val = '1', | ||
233 | }, | ||
234 | { | ||
235 | .name = "no-virtio-1", | ||
236 | .val = '0', | ||
237 | }, | ||
238 | { | ||
230 | .name = "delayed-interrupt", | 239 | .name = "delayed-interrupt", |
231 | .val = 'D', | 240 | .val = 'D', |
232 | }, | 241 | }, |
@@ -243,6 +252,7 @@ static void help(void) | |||
243 | fprintf(stderr, "Usage: virtio_test [--help]" | 252 | fprintf(stderr, "Usage: virtio_test [--help]" |
244 | " [--no-indirect]" | 253 | " [--no-indirect]" |
245 | " [--no-event-idx]" | 254 | " [--no-event-idx]" |
255 | " [--no-virtio-1]" | ||
246 | " [--delayed-interrupt]" | 256 | " [--delayed-interrupt]" |
247 | "\n"); | 257 | "\n"); |
248 | } | 258 | } |
@@ -251,7 +261,7 @@ int main(int argc, char **argv) | |||
251 | { | 261 | { |
252 | struct vdev_info dev; | 262 | struct vdev_info dev; |
253 | unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | | 263 | unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | |
254 | (1ULL << VIRTIO_RING_F_EVENT_IDX); | 264 | (1ULL << VIRTIO_RING_F_EVENT_IDX) | (1ULL << VIRTIO_F_VERSION_1); |
255 | int o; | 265 | int o; |
256 | bool delayed = false; | 266 | bool delayed = false; |
257 | 267 | ||
@@ -272,6 +282,9 @@ int main(int argc, char **argv) | |||
272 | case 'i': | 282 | case 'i': |
273 | features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC); | 283 | features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC); |
274 | break; | 284 | break; |
285 | case '0': | ||
286 | features &= ~(1ULL << VIRTIO_F_VERSION_1); | ||
287 | break; | ||
275 | case 'D': | 288 | case 'D': |
276 | delayed = true; | 289 | delayed = true; |
277 | break; | 290 | break; |
diff --git a/tools/virtio/vringh_test.c b/tools/virtio/vringh_test.c index 9d4b1bca54be..5f94f5105678 100644 --- a/tools/virtio/vringh_test.c +++ b/tools/virtio/vringh_test.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/virtio.h> | 7 | #include <linux/virtio.h> |
8 | #include <linux/vringh.h> | 8 | #include <linux/vringh.h> |
9 | #include <linux/virtio_ring.h> | 9 | #include <linux/virtio_ring.h> |
10 | #include <linux/virtio_config.h> | ||
10 | #include <linux/uaccess.h> | 11 | #include <linux/uaccess.h> |
11 | #include <sys/types.h> | 12 | #include <sys/types.h> |
12 | #include <sys/stat.h> | 13 | #include <sys/stat.h> |
@@ -131,7 +132,7 @@ static inline int vringh_get_head(struct vringh *vrh, u16 *head) | |||
131 | return 1; | 132 | return 1; |
132 | } | 133 | } |
133 | 134 | ||
134 | static int parallel_test(unsigned long features, | 135 | static int parallel_test(u64 features, |
135 | bool (*getrange)(struct vringh *vrh, | 136 | bool (*getrange)(struct vringh *vrh, |
136 | u64 addr, struct vringh_range *r), | 137 | u64 addr, struct vringh_range *r), |
137 | bool fast_vringh) | 138 | bool fast_vringh) |
@@ -456,6 +457,8 @@ int main(int argc, char *argv[]) | |||
456 | __virtio_set_bit(&vdev, VIRTIO_RING_F_INDIRECT_DESC); | 457 | __virtio_set_bit(&vdev, VIRTIO_RING_F_INDIRECT_DESC); |
457 | else if (strcmp(argv[1], "--eventidx") == 0) | 458 | else if (strcmp(argv[1], "--eventidx") == 0) |
458 | __virtio_set_bit(&vdev, VIRTIO_RING_F_EVENT_IDX); | 459 | __virtio_set_bit(&vdev, VIRTIO_RING_F_EVENT_IDX); |
460 | else if (strcmp(argv[1], "--virtio-1") == 0) | ||
461 | __virtio_set_bit(&vdev, VIRTIO_F_VERSION_1); | ||
459 | else if (strcmp(argv[1], "--slow-range") == 0) | 462 | else if (strcmp(argv[1], "--slow-range") == 0) |
460 | getrange = getrange_slow; | 463 | getrange = getrange_slow; |
461 | else if (strcmp(argv[1], "--fast-vringh") == 0) | 464 | else if (strcmp(argv[1], "--fast-vringh") == 0) |