vhost/virtio: 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.
 
 Cc: Rusty Russell <rusty@rustcorp.com.au>
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJUkSztAAoJECgfDbjSjVRp5DkH/ibw+0ZaEFP/SXWnw6WONpaG
 pzMsrfMG/vxlOfutSUdDqG+oqqU2fSLvFq5qDK6Xk9/emRSwGduz29ZaxGh8J1MZ
 /Ojqtu/HSLl+UASTs+fMw49itghoIjmAPBwwMkQjvanfqLclgdz9UxzoCOc4YkO0
 PJQA/Vw6blVSP1m0p97PvzZkAiIetI2ixZn2vPJZc8vSkOHtygM9HdXKTv785HbG
 ycRbR9B3OBMvq26FIuWeyuY93FnyX2Qtf2bzwSSRdzo7qlsNhVVG7sKyWOOR+1xG
 TLmjhyTF57oA2GgZCVfgnFxsfiuIKMumfG0jbABTXmBGgA/ULef7HcF/lzLgdq8=
 =32cU
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2014-12-18 20:50:30 -08:00
commit 64ec45bff6
16 changed files with 324 additions and 109 deletions

View file

@ -19,6 +19,9 @@
* offset: the offset of the configuration field
* buf: the buffer to read the field value from.
* len: the length of the buffer
* @generation: config generation counter
* vdev: the virtio_device
* Returns the config generation counter
* @get_status: read the status byte
* vdev: the virtio_device
* Returns the status byte
@ -60,6 +63,7 @@ struct virtio_config_ops {
void *buf, unsigned len);
void (*set)(struct virtio_device *vdev, unsigned offset,
const void *buf, unsigned len);
u32 (*generation)(struct virtio_device *vdev);
u8 (*get_status)(struct virtio_device *vdev);
void (*set_status)(struct virtio_device *vdev, u8 status);
void (*reset)(struct virtio_device *vdev);
@ -301,11 +305,33 @@ static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset)
return ret;
}
/* Read @count fields, @bytes each. */
static inline void __virtio_cread_many(struct virtio_device *vdev,
unsigned int offset,
void *buf, size_t count, size_t bytes)
{
u32 old, gen = vdev->config->generation ?
vdev->config->generation(vdev) : 0;
int i;
do {
old = gen;
for (i = 0; i < count; i++)
vdev->config->get(vdev, offset + bytes * i,
buf + i * bytes, bytes);
gen = vdev->config->generation ?
vdev->config->generation(vdev) : 0;
} while (gen != old);
}
static inline void virtio_cread_bytes(struct virtio_device *vdev,
unsigned int offset,
void *buf, size_t len)
{
vdev->config->get(vdev, offset, buf, len);
__virtio_cread_many(vdev, offset, buf, len, 1);
}
static inline void virtio_cwrite8(struct virtio_device *vdev,
@ -349,6 +375,7 @@ static inline u64 virtio_cread64(struct virtio_device *vdev,
{
u64 ret;
vdev->config->get(vdev, offset, &ret, sizeof(ret));
__virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret));
return virtio64_to_cpu(vdev, (__force __virtio64)ret);
}

View file

@ -24,12 +24,16 @@
#ifndef _LINUX_VRINGH_H
#define _LINUX_VRINGH_H
#include <uapi/linux/virtio_ring.h>
#include <linux/virtio_byteorder.h>
#include <linux/uio.h>
#include <linux/slab.h>
#include <asm/barrier.h>
/* virtio_ring with information needed for host access. */
struct vringh {
/* Everything is little endian */
bool little_endian;
/* Guest publishes used event idx (note: we always do). */
bool event_indices;
@ -105,7 +109,7 @@ struct vringh_kiov {
#define VRINGH_IOV_ALLOCATED 0x8000000
/* Helpers for userspace vrings. */
int vringh_init_user(struct vringh *vrh, u32 features,
int vringh_init_user(struct vringh *vrh, u64 features,
unsigned int num, bool weak_barriers,
struct vring_desc __user *desc,
struct vring_avail __user *avail,
@ -167,7 +171,7 @@ bool vringh_notify_enable_user(struct vringh *vrh);
void vringh_notify_disable_user(struct vringh *vrh);
/* Helpers for kernelspace vrings. */
int vringh_init_kern(struct vringh *vrh, u32 features,
int vringh_init_kern(struct vringh *vrh, u64 features,
unsigned int num, bool weak_barriers,
struct vring_desc *desc,
struct vring_avail *avail,
@ -222,4 +226,33 @@ static inline void vringh_notify(struct vringh *vrh)
vrh->notify(vrh);
}
static inline u16 vringh16_to_cpu(const struct vringh *vrh, __virtio16 val)
{
return __virtio16_to_cpu(vrh->little_endian, val);
}
static inline __virtio16 cpu_to_vringh16(const struct vringh *vrh, u16 val)
{
return __cpu_to_virtio16(vrh->little_endian, val);
}
static inline u32 vringh32_to_cpu(const struct vringh *vrh, __virtio32 val)
{
return __virtio32_to_cpu(vrh->little_endian, val);
}
static inline __virtio32 cpu_to_vringh32(const struct vringh *vrh, u32 val)
{
return __cpu_to_virtio32(vrh->little_endian, val);
}
static inline u64 vringh64_to_cpu(const struct vringh *vrh, __virtio64 val)
{
return __virtio64_to_cpu(vrh->little_endian, val);
}
static inline __virtio64 cpu_to_vringh64(const struct vringh *vrh, u64 val)
{
return __cpu_to_virtio64(vrh->little_endian, val);
}
#endif /* _LINUX_VRINGH_H */