[PATCH v7 01/46] virtio: add low-level APIs for feature bits
Add low level APIs to test/set/clear feature bits. For use by transports, to make it easier to write code independent of feature bit array format. Note: APIs is prefixed with __ and has _bit suffix to stress its low level nature. It's for use by transports only: drivers should use virtio_has_feature and never need to set/clear features. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- include/linux/virtio_config.h | 53 --- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 7f4ef66..d8e28a2 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -77,11 +77,47 @@ void virtio_check_driver_offered_feature(const struct virtio_device *vdev, unsigned int fbit); /** - * virtio_has_feature - helper to determine if this device has this feature. + * __virtio_test_bit - helper to test feature bits. For use by transports. + * Devices should normally use virtio_has_feature, + * which includes more checks. * @vdev: the device * @fbit: the feature bit */ -static inline bool virtio_has_feature(const struct virtio_device *vdev, +static inline bool __virtio_test_bit(const struct virtio_device *vdev, +unsigned int fbit) +{ + /* Did you forget to fix assumptions on max features? */ + if (__builtin_constant_p(fbit)) + BUILD_BUG_ON(fbit = 32); + else + BUG_ON(fbit = 32); + + return test_bit(fbit, vdev-features); +} + +/** + * __virtio_set_bit - helper to set feature bits. For use by transports. + * @vdev: the device + * @fbit: the feature bit + */ +static inline void __virtio_set_bit(struct virtio_device *vdev, + unsigned int fbit) +{ + /* Did you forget to fix assumptions on max features? */ + if (__builtin_constant_p(fbit)) + BUILD_BUG_ON(fbit = 32); + else + BUG_ON(fbit = 32); + + set_bit(fbit, vdev-features); +} + +/** + * __virtio_clear_bit - helper to clear feature bits. For use by transports. + * @vdev: the device + * @fbit: the feature bit + */ +static inline void __virtio_clear_bit(struct virtio_device *vdev, unsigned int fbit) { /* Did you forget to fix assumptions on max features? */ @@ -90,10 +126,21 @@ static inline bool virtio_has_feature(const struct virtio_device *vdev, else BUG_ON(fbit = 32); + clear_bit(fbit, vdev-features); +} + +/** + * virtio_has_feature - helper to determine if this device has this feature. + * @vdev: the device + * @fbit: the feature bit + */ +static inline bool virtio_has_feature(const struct virtio_device *vdev, + unsigned int fbit) +{ if (fbit VIRTIO_TRANSPORT_F_START) virtio_check_driver_offered_feature(vdev, fbit); - return test_bit(fbit, vdev-features); + return __virtio_test_bit(vdev, fbit); } static inline -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v7 04/46] virtio: add support for 64 bit features.
Change u32 to u64, and use BIT_ULL and 1ULL everywhere. Note: transports are unchanged, and only set low 32 bit. This guarantees that no transport sets e.g. VERSION_1 by mistake without proper support. Based on patch by Rusty. Signed-off-by: Rusty Russell ru...@rustcorp.com.au Signed-off-by: Cornelia Huck cornelia.h...@de.ibm.com Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: David Hildenbrand d...@linux.vnet.ibm.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com --- include/linux/virtio.h | 2 +- include/linux/virtio_config.h | 20 ++-- tools/virtio/linux/virtio.h| 2 +- drivers/lguest/lguest_device.c | 2 +- drivers/misc/mic/card/mic_virtio.c | 2 +- drivers/remoteproc/remoteproc_virtio.c | 2 +- drivers/s390/kvm/kvm_virtio.c | 2 +- drivers/s390/kvm/virtio_ccw.c | 2 +- drivers/virtio/virtio.c| 8 drivers/virtio/virtio_mmio.c | 2 +- drivers/virtio/virtio_pci.c| 2 +- 11 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 7828a7f..149284e 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -101,7 +101,7 @@ struct virtio_device { const struct virtio_config_ops *config; const struct vringh_config_ops *vringh_config; struct list_head vqs; - u32 features; + u64 features; void *priv; }; diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index ffc2ae0..f517884 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -66,7 +66,7 @@ struct virtio_config_ops { vq_callback_t *callbacks[], const char *names[]); void (*del_vqs)(struct virtio_device *); - u32 (*get_features)(struct virtio_device *vdev); + u64 (*get_features)(struct virtio_device *vdev); void (*finalize_features)(struct virtio_device *vdev); const char *(*bus_name)(struct virtio_device *vdev); int (*set_vq_affinity)(struct virtqueue *vq, int cpu); @@ -88,11 +88,11 @@ static inline bool __virtio_test_bit(const struct virtio_device *vdev, { /* Did you forget to fix assumptions on max features? */ if (__builtin_constant_p(fbit)) - BUILD_BUG_ON(fbit = 32); + BUILD_BUG_ON(fbit = 64); else - BUG_ON(fbit = 32); + BUG_ON(fbit = 64); - return vdev-features BIT(fbit); + return vdev-features BIT_ULL(fbit); } /** @@ -105,11 +105,11 @@ static inline void __virtio_set_bit(struct virtio_device *vdev, { /* Did you forget to fix assumptions on max features? */ if (__builtin_constant_p(fbit)) - BUILD_BUG_ON(fbit = 32); + BUILD_BUG_ON(fbit = 64); else - BUG_ON(fbit = 32); + BUG_ON(fbit = 64); - vdev-features |= BIT(fbit); + vdev-features |= BIT_ULL(fbit); } /** @@ -122,11 +122,11 @@ static inline void __virtio_clear_bit(struct virtio_device *vdev, { /* Did you forget to fix assumptions on max features? */ if (__builtin_constant_p(fbit)) - BUILD_BUG_ON(fbit = 32); + BUILD_BUG_ON(fbit = 64); else - BUG_ON(fbit = 32); + BUG_ON(fbit = 64); - vdev-features = ~BIT(fbit); + vdev-features = ~BIT_ULL(fbit); } /** diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h index 72bff70..8eb6421 100644 --- a/tools/virtio/linux/virtio.h +++ b/tools/virtio/linux/virtio.h @@ -10,7 +10,7 @@ struct virtio_device { void *dev; - u32 features; + u64 features; }; struct virtqueue { diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 97aeb7d..d81170a 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -94,7 +94,7 @@ static unsigned desc_size(const struct lguest_device_desc *desc) } /* This gets the device's feature bits. */ -static u32 lg_get_features(struct virtio_device *vdev) +static u64 lg_get_features(struct virtio_device *vdev) { unsigned int i; u32 features = 0; diff --git a/drivers/misc/mic/card/mic_virtio.c b/drivers/misc/mic/card/mic_virtio.c index d5da9ff..f5e7561 100644 --- a/drivers/misc/mic/card/mic_virtio.c +++ b/drivers/misc/mic/card/mic_virtio.c @@ -68,7 +68,7 @@ static inline struct device *mic_dev(struct mic_vdev *mvdev) } /* This gets the device's feature bits. */ -static u32 mic_get_features(struct virtio_device *vdev) +static u64 mic_get_features(struct virtio_device *vdev) { unsigned int i, bits; u32 features = 0; diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index dafaf38..62897db 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++
[PATCH v7 07/46] virtio: add virtio 1.0 feature bit
Based on original patches by Rusty Russell, Thomas Huth and Cornelia Huck. Note: at this time, we do not negotiate this feature bit in core, drivers have to declare VERSION_1 support explicitly. For this reason we treat this bit as a device bit and not as a transport bit for now. After all drivers are converted, we will be able to move VERSION_1 to core and drop it from all drivers. Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com --- include/uapi/linux/virtio_config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/uapi/linux/virtio_config.h b/include/uapi/linux/virtio_config.h index 3ce768c..80e7381 100644 --- a/include/uapi/linux/virtio_config.h +++ b/include/uapi/linux/virtio_config.h @@ -54,4 +54,7 @@ /* Can the device handle any descriptor layout? */ #define VIRTIO_F_ANY_LAYOUT27 +/* v1.0 compliant. */ +#define VIRTIO_F_VERSION_1 32 + #endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */ -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v7 02/46] virtio: use u32, not bitmap for features
It seemed like a good idea to use bitmap for features in struct virtio_device, but it's actually a pain, and seems to become even more painful when we get more than 32 feature bits. Just change it to a u32 for now. Based on patch by Rusty. Suggested-by: David Hildenbrand d...@linux.vnet.ibm.com Signed-off-by: Rusty Russell ru...@rustcorp.com.au Signed-off-by: Cornelia Huck cornelia.h...@de.ibm.com Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com --- include/linux/virtio.h | 3 +-- include/linux/virtio_config.h | 6 +++--- tools/virtio/linux/virtio.h| 22 +- tools/virtio/linux/virtio_config.h | 2 +- drivers/char/virtio_console.c | 2 +- drivers/lguest/lguest_device.c | 8 drivers/misc/mic/card/mic_virtio.c | 2 +- drivers/remoteproc/remoteproc_virtio.c | 2 +- drivers/s390/kvm/kvm_virtio.c | 2 +- drivers/s390/kvm/virtio_ccw.c | 23 +-- drivers/virtio/virtio.c| 10 +- drivers/virtio/virtio_mmio.c | 8 ++-- drivers/virtio/virtio_pci.c| 3 +-- drivers/virtio/virtio_ring.c | 2 +- tools/virtio/virtio_test.c | 5 ++--- tools/virtio/vringh_test.c | 16 16 files changed, 42 insertions(+), 74 deletions(-) diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 65261a7..7828a7f 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -101,8 +101,7 @@ struct virtio_device { const struct virtio_config_ops *config; const struct vringh_config_ops *vringh_config; struct list_head vqs; - /* Note that this is a Linux set_bit-style bitmap. */ - unsigned long features[1]; + u32 features; void *priv; }; diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index d8e28a2..ffc2ae0 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -92,7 +92,7 @@ static inline bool __virtio_test_bit(const struct virtio_device *vdev, else BUG_ON(fbit = 32); - return test_bit(fbit, vdev-features); + return vdev-features BIT(fbit); } /** @@ -109,7 +109,7 @@ static inline void __virtio_set_bit(struct virtio_device *vdev, else BUG_ON(fbit = 32); - set_bit(fbit, vdev-features); + vdev-features |= BIT(fbit); } /** @@ -126,7 +126,7 @@ static inline void __virtio_clear_bit(struct virtio_device *vdev, else BUG_ON(fbit = 32); - clear_bit(fbit, vdev-features); + vdev-features = ~BIT(fbit); } /** diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h index 5a2d1f0..72bff70 100644 --- a/tools/virtio/linux/virtio.h +++ b/tools/virtio/linux/virtio.h @@ -6,31 +6,11 @@ /* TODO: empty stubs for now. Broken but enough for virtio_ring.c */ #define list_add_tail(a, b) do {} while (0) #define list_del(a) do {} while (0) - -#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) -#define BITS_PER_BYTE 8 -#define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE) -#define BIT_MASK(nr) (1UL ((nr) % BITS_PER_LONG)) - -/* TODO: Not atomic as it should be: - * we don't use this for anything important. */ -static inline void clear_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); - - *p = ~mask; -} - -static inline int test_bit(int nr, const volatile unsigned long *addr) -{ -return 1UL (addr[BIT_WORD(nr)] (nr (BITS_PER_LONG-1))); -} /* end of stubs */ struct virtio_device { void *dev; - unsigned long features[1]; + u32 features; }; struct virtqueue { diff --git a/tools/virtio/linux/virtio_config.h b/tools/virtio/linux/virtio_config.h index 5049967..83b27e8 100644 --- a/tools/virtio/linux/virtio_config.h +++ b/tools/virtio/linux/virtio_config.h @@ -2,5 +2,5 @@ #define VIRTIO_TRANSPORT_F_END 32 #define virtio_has_feature(dev, feature) \ - test_bit((feature), (dev)-features) + (__virtio_test_bit((dev), feature)) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index cf7a561..8d00aa7 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -355,7 +355,7 @@ static inline bool use_multiport(struct ports_device *portdev) */ if (!portdev-vdev) return 0; - return portdev-vdev-features[0] (1 VIRTIO_CONSOLE_F_MULTIPORT); + return __virtio_test_bit(portdev-vdev, VIRTIO_CONSOLE_F_MULTIPORT); } static DEFINE_SPINLOCK(dma_bufs_lock); diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index d0a1d8a..97aeb7d 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -137,14 +137,14 @@
[PATCH v7 05/46] virtio: assert 32 bit features in transports
At this point, no transports set any of the high 32 feature bits. Since transports generally can't (yet) cope with such bits, add BUG_ON checks to make sure they are not set by mistake. Based on rproc patch by Rusty. Signed-off-by: Rusty Russell ru...@rustcorp.com.au Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: David Hildenbrand d...@linux.vnet.ibm.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com --- drivers/lguest/lguest_device.c | 3 +++ drivers/misc/mic/card/mic_virtio.c | 3 +++ drivers/remoteproc/remoteproc_virtio.c | 3 +++ drivers/s390/kvm/kvm_virtio.c | 3 +++ drivers/s390/kvm/virtio_ccw.c | 3 +++ drivers/virtio/virtio_mmio.c | 3 +++ drivers/virtio/virtio_pci.c| 3 +++ 7 files changed, 21 insertions(+) diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index d81170a..9b77b66 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -136,6 +136,9 @@ static void lg_finalize_features(struct virtio_device *vdev) /* Give virtio_ring a chance to accept features. */ vring_transport_features(vdev); + /* Make sure we don't have any features 32 bits! */ + BUG_ON((u32)vdev-features != vdev-features); + /* * Since lguest is currently x86-only, we're little-endian. That * means we could just memcpy. But it's not time critical, and in diff --git a/drivers/misc/mic/card/mic_virtio.c b/drivers/misc/mic/card/mic_virtio.c index f5e7561..d027d29 100644 --- a/drivers/misc/mic/card/mic_virtio.c +++ b/drivers/misc/mic/card/mic_virtio.c @@ -96,6 +96,9 @@ static void mic_finalize_features(struct virtio_device *vdev) /* Give virtio_ring a chance to accept features. */ vring_transport_features(vdev); + /* Make sure we don't have any features 32 bits! */ + BUG_ON((u32)vdev-features != vdev-features); + memset_io(out_features, 0, feature_len); bits = min_t(unsigned, feature_len, sizeof(vdev-features)) * 8; diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index 62897db..627737e 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c @@ -227,6 +227,9 @@ static void rproc_virtio_finalize_features(struct virtio_device *vdev) /* Give virtio_ring a chance to accept features */ vring_transport_features(vdev); + /* Make sure we don't have any features 32 bits! */ + BUG_ON((u32)vdev-features != vdev-features); + /* * Remember the finalized features of our vdev, and provide it * to the remote processor once it is powered on. diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 2336c7e..f5575cc 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -103,6 +103,9 @@ static void kvm_finalize_features(struct virtio_device *vdev) /* Give virtio_ring a chance to accept features. */ vring_transport_features(vdev); + /* Make sure we don't have any features 32 bits! */ + BUG_ON((u32)vdev-features != vdev-features); + memset(out_features, 0, desc-feature_len); bits = min_t(unsigned, desc-feature_len, sizeof(vdev-features)) * 8; for (i = 0; i bits; i++) { diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index 56d7895..244d611 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/kvm/virtio_ccw.c @@ -714,6 +714,9 @@ static void virtio_ccw_finalize_features(struct virtio_device *vdev) /* Give virtio_ring a chance to accept features. */ vring_transport_features(vdev); + /* Make sure we don't have any features 32 bits! */ + BUG_ON((u32)vdev-features != vdev-features); + features-index = 0; features-features = cpu_to_le32(vdev-features); /* Write the feature bits to the host. */ diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index c63d0ef..aec1dae 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -159,6 +159,9 @@ static void vm_finalize_features(struct virtio_device *vdev) /* Give virtio_ring a chance to accept features. */ vring_transport_features(vdev); + /* Make sure we don't have any features 32 bits! */ + BUG_ON((u32)vdev-features != vdev-features); + writel(0, vm_dev-base + VIRTIO_MMIO_GUEST_FEATURES_SEL); writel(vdev-features, vm_dev-base + VIRTIO_MMIO_GUEST_FEATURES); } diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 7e0efa7..dd6df97 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -119,6 +119,9 @@ static void vp_finalize_features(struct virtio_device *vdev) /* Give virtio_ring a chance to accept features. */ vring_transport_features(vdev); + /* Make sure we don't
[PATCH v7 09/46] virtio_ring: switch to new memory access APIs
Use virtioXX_to_cpu and friends for access to all multibyte structures in memory. Note: this is intentionally mechanical. A follow-up patch will split long lines etc. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/virtio/virtio_ring.c | 89 ++-- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 839247c..0d3c737 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -99,7 +99,8 @@ struct vring_virtqueue #define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq) -static struct vring_desc *alloc_indirect(unsigned int total_sg, gfp_t gfp) +static struct vring_desc *alloc_indirect(struct virtqueue *_vq, +unsigned int total_sg, gfp_t gfp) { struct vring_desc *desc; unsigned int i; @@ -116,7 +117,7 @@ static struct vring_desc *alloc_indirect(unsigned int total_sg, gfp_t gfp) return NULL; for (i = 0; i total_sg; i++) - desc[i].next = i+1; + desc[i].next = cpu_to_virtio16(_vq-vdev, i + 1); return desc; } @@ -165,17 +166,17 @@ static inline int virtqueue_add(struct virtqueue *_vq, /* If the host supports indirect descriptor tables, and we have multiple * buffers, then go indirect. FIXME: tune this threshold */ if (vq-indirect total_sg 1 vq-vq.num_free) - desc = alloc_indirect(total_sg, gfp); + desc = alloc_indirect(_vq, total_sg, gfp); else desc = NULL; if (desc) { /* Use a single buffer which doesn't continue */ - vq-vring.desc[head].flags = VRING_DESC_F_INDIRECT; - vq-vring.desc[head].addr = virt_to_phys(desc); + vq-vring.desc[head].flags = cpu_to_virtio16(_vq-vdev, VRING_DESC_F_INDIRECT); + vq-vring.desc[head].addr = cpu_to_virtio64(_vq-vdev, virt_to_phys(desc)); /* avoid kmemleak false positive (hidden by virt_to_phys) */ kmemleak_ignore(desc); - vq-vring.desc[head].len = total_sg * sizeof(struct vring_desc); + vq-vring.desc[head].len = cpu_to_virtio32(_vq-vdev, total_sg * sizeof(struct vring_desc)); /* Set up rest to use this indirect table. */ i = 0; @@ -205,28 +206,28 @@ static inline int virtqueue_add(struct virtqueue *_vq, for (n = 0; n out_sgs; n++) { for (sg = sgs[n]; sg; sg = sg_next(sg)) { - desc[i].flags = VRING_DESC_F_NEXT; - desc[i].addr = sg_phys(sg); - desc[i].len = sg-length; + desc[i].flags = cpu_to_virtio16(_vq-vdev, VRING_DESC_F_NEXT); + desc[i].addr = cpu_to_virtio64(_vq-vdev, sg_phys(sg)); + desc[i].len = cpu_to_virtio32(_vq-vdev, sg-length); prev = i; - i = desc[i].next; + i = virtio16_to_cpu(_vq-vdev, desc[i].next); } } for (; n (out_sgs + in_sgs); n++) { for (sg = sgs[n]; sg; sg = sg_next(sg)) { - desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE; - desc[i].addr = sg_phys(sg); - desc[i].len = sg-length; + desc[i].flags = cpu_to_virtio16(_vq-vdev, VRING_DESC_F_NEXT | VRING_DESC_F_WRITE); + desc[i].addr = cpu_to_virtio64(_vq-vdev, sg_phys(sg)); + desc[i].len = cpu_to_virtio32(_vq-vdev, sg-length); prev = i; - i = desc[i].next; + i = virtio16_to_cpu(_vq-vdev, desc[i].next); } } /* Last one doesn't continue. */ - desc[prev].flags = ~VRING_DESC_F_NEXT; + desc[prev].flags = cpu_to_virtio16(_vq-vdev, ~VRING_DESC_F_NEXT); /* Update free pointer */ if (indirect) - vq-free_head = vq-vring.desc[head].next; + vq-free_head = virtio16_to_cpu(_vq-vdev, vq-vring.desc[head].next); else vq-free_head = i; @@ -235,13 +236,13 @@ static inline int virtqueue_add(struct virtqueue *_vq, /* Put entry in available array (but don't update avail-idx until they * do sync). */ - avail = (vq-vring.avail-idx (vq-vring.num-1)); - vq-vring.avail-ring[avail] = head; + avail = virtio16_to_cpu(_vq-vdev, vq-vring.avail-idx) (vq-vring.num - 1); + vq-vring.avail-ring[avail] = cpu_to_virtio16(_vq-vdev, head); /* Descriptors and available array need to be set before we expose the * new available array entries. */ virtio_wmb(vq-weak_barriers); - vq-vring.avail-idx++; + vq-vring.avail-idx = cpu_to_virtio16(_vq-vdev,
[PATCH v7 13/46] virtio: simplify feature bit handling
Now that we use u64 for bits, we can simply them together. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/virtio/virtio.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 9248125..3e78f4b 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -160,6 +160,7 @@ static int virtio_dev_probe(struct device *_d) struct virtio_device *dev = dev_to_virtio(_d); struct virtio_driver *drv = drv_to_virtio(dev-dev.driver); u64 device_features; + u64 driver_features; unsigned status; /* We have a driver! */ @@ -168,15 +169,16 @@ static int virtio_dev_probe(struct device *_d) /* Figure out what features the device supports. */ device_features = dev-config-get_features(dev); - /* Features supported by both device and driver into dev-features. */ - dev-features = 0; + /* Figure out what features the driver supports. */ + driver_features = 0; for (i = 0; i drv-feature_table_size; i++) { unsigned int f = drv-feature_table[i]; BUG_ON(f = 64); - if (device_features (1ULL f)) - __virtio_set_bit(dev, f); + driver_features |= (1ULL f); } + dev-features = driver_features device_features; + /* Transport features always preserved to pass to finalize_features. */ for (i = VIRTIO_TRANSPORT_F_START; i VIRTIO_TRANSPORT_F_END; i++) if (device_features (1ULL i)) -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v7 12/46] virtio: set FEATURES_OK
set FEATURES_OK as per virtio 1.0 spec Signed-off-by: Michael S. Tsirkin m...@redhat.com --- include/uapi/linux/virtio_config.h | 2 ++ drivers/virtio/virtio.c| 29 ++--- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/include/uapi/linux/virtio_config.h b/include/uapi/linux/virtio_config.h index 80e7381..4d05671 100644 --- a/include/uapi/linux/virtio_config.h +++ b/include/uapi/linux/virtio_config.h @@ -38,6 +38,8 @@ #define VIRTIO_CONFIG_S_DRIVER 2 /* Driver has used its parts of the config, and is happy */ #define VIRTIO_CONFIG_S_DRIVER_OK 4 +/* Driver has finished configuring features */ +#define VIRTIO_CONFIG_S_FEATURES_OK8 /* We've given up on this device. */ #define VIRTIO_CONFIG_S_FAILED 0x80 diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 746d350..9248125 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -160,6 +160,7 @@ static int virtio_dev_probe(struct device *_d) struct virtio_device *dev = dev_to_virtio(_d); struct virtio_driver *drv = drv_to_virtio(dev-dev.driver); u64 device_features; + unsigned status; /* We have a driver! */ add_status(dev, VIRTIO_CONFIG_S_DRIVER); @@ -183,18 +184,32 @@ static int virtio_dev_probe(struct device *_d) dev-config-finalize_features(dev); + if (virtio_has_feature(dev, VIRTIO_F_VERSION_1)) { + add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); + status = dev-config-get_status(dev); + if (!(status VIRTIO_CONFIG_S_FEATURES_OK)) { + dev_err(_d, virtio: device refuses features: %x\n, + status); + err = -ENODEV; + goto err; + } + } + err = drv-probe(dev); if (err) - add_status(dev, VIRTIO_CONFIG_S_FAILED); - else { - add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); - if (drv-scan) - drv-scan(dev); + goto err; - virtio_config_enable(dev); - } + add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); + if (drv-scan) + drv-scan(dev); + + virtio_config_enable(dev); + return 0; +err: + add_status(dev, VIRTIO_CONFIG_S_FAILED); return err; + } static int virtio_dev_remove(struct device *_d) -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v7 15/46] virtio_net: v1.0 endianness
Based on patches by Rusty Russell, Cornelia Huck. Note: more code changes are needed for 1.0 support (due to different header size). So we don't advertize support for 1.0 yet. Signed-off-by: Rusty Russell ru...@rustcorp.com.au Signed-off-by: Cornelia Huck cornelia.h...@de.ibm.com Signed-off-by: Michael S. Tsirkin m...@redhat.com --- include/uapi/linux/virtio_net.h | 15 --- drivers/net/virtio_net.c| 33 - 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h index 172a7f0..b5f1677 100644 --- a/include/uapi/linux/virtio_net.h +++ b/include/uapi/linux/virtio_net.h @@ -28,6 +28,7 @@ #include linux/types.h #include linux/virtio_ids.h #include linux/virtio_config.h +#include linux/virtio_types.h #include linux/if_ether.h /* The feature bitmap for virtio net */ @@ -84,17 +85,17 @@ struct virtio_net_hdr { #define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP #define VIRTIO_NET_HDR_GSO_ECN 0x80// TCP has ECN set __u8 gso_type; - __u16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ - __u16 gso_size; /* Bytes to append to hdr_len per frame */ - __u16 csum_start; /* Position to start checksumming from */ - __u16 csum_offset; /* Offset after that to place checksum */ + __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ + __virtio16 gso_size;/* Bytes to append to hdr_len per frame */ + __virtio16 csum_start; /* Position to start checksumming from */ + __virtio16 csum_offset; /* Offset after that to place checksum */ }; /* This is the version of the header to use when the MRG_RXBUF * feature has been negotiated. */ struct virtio_net_hdr_mrg_rxbuf { struct virtio_net_hdr hdr; - __u16 num_buffers; /* Number of merged rx buffers */ + __virtio16 num_buffers; /* Number of merged rx buffers */ }; /* @@ -149,7 +150,7 @@ typedef __u8 virtio_net_ctrl_ack; * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. */ struct virtio_net_ctrl_mac { - __u32 entries; + __virtio32 entries; __u8 macs[][ETH_ALEN]; } __attribute__((packed)); @@ -193,7 +194,7 @@ struct virtio_net_ctrl_mac { * specified. */ struct virtio_net_ctrl_mq { - __u16 virtqueue_pairs; + __virtio16 virtqueue_pairs; }; #define VIRTIO_NET_CTRL_MQ 4 diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index b0bc8ea..c07e030 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -347,13 +347,14 @@ err: } static struct sk_buff *receive_mergeable(struct net_device *dev, +struct virtnet_info *vi, struct receive_queue *rq, unsigned long ctx, unsigned int len) { void *buf = mergeable_ctx_to_buf_address(ctx); struct skb_vnet_hdr *hdr = buf; - int num_buf = hdr-mhdr.num_buffers; + u16 num_buf = virtio16_to_cpu(rq-vq-vdev, hdr-mhdr.num_buffers); struct page *page = virt_to_head_page(buf); int offset = buf - page_address(page); unsigned int truesize = max(len, mergeable_ctx_to_buf_truesize(ctx)); @@ -369,7 +370,9 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, ctx = (unsigned long)virtqueue_get_buf(rq-vq, len); if (unlikely(!ctx)) { pr_debug(%s: rx error: %d buffers out of %d missing\n, -dev-name, num_buf, hdr-mhdr.num_buffers); +dev-name, num_buf, +virtio16_to_cpu(rq-vq-vdev, +hdr-mhdr.num_buffers)); dev-stats.rx_length_errors++; goto err_buf; } @@ -454,7 +457,7 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) } if (vi-mergeable_rx_bufs) - skb = receive_mergeable(dev, rq, (unsigned long)buf, len); + skb = receive_mergeable(dev, vi, rq, (unsigned long)buf, len); else if (vi-big_packets) skb = receive_big(dev, rq, buf, len); else @@ -473,8 +476,8 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) if (hdr-hdr.flags VIRTIO_NET_HDR_F_NEEDS_CSUM) { pr_debug(Needs csum!\n); if (!skb_partial_csum_set(skb, - hdr-hdr.csum_start, - hdr-hdr.csum_offset)) + virtio16_to_cpu(vi-vdev, hdr-hdr.csum_start), + virtio16_to_cpu(vi-vdev, hdr-hdr.csum_offset))) goto frame_err; } else if
[PATCH v7 22/46] virtio_blk: fix race at module removal
If a device appears while module is being removed, driver will get a callback after we've given up on the major number. In theory this means this major number can get reused by something else, resulting in a conflict. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/block/virtio_blk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 055f3df..1f8b111 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -884,8 +884,8 @@ out_destroy_workqueue: static void __exit fini(void) { - unregister_blkdev(major, virtblk); unregister_virtio_driver(virtio_blk); + unregister_blkdev(major, virtblk); destroy_workqueue(virtblk_wq); } module_init(init); -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v7 23/46] virtio_net: pass vi around
Too many places poke at [rs]q-vq-vdev-priv just to get the vi structure. Let's just pass the pointer around: seems cleaner, and might even be faster. Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com --- drivers/net/virtio_net.c | 38 -- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c07e030..1630c21 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -241,11 +241,11 @@ static unsigned long mergeable_buf_to_ctx(void *buf, unsigned int truesize) } /* Called from bottom half context */ -static struct sk_buff *page_to_skb(struct receive_queue *rq, +static struct sk_buff *page_to_skb(struct virtnet_info *vi, + struct receive_queue *rq, struct page *page, unsigned int offset, unsigned int len, unsigned int truesize) { - struct virtnet_info *vi = rq-vq-vdev-priv; struct sk_buff *skb; struct skb_vnet_hdr *hdr; unsigned int copy, hdr_len, hdr_padded_len; @@ -328,12 +328,13 @@ static struct sk_buff *receive_small(void *buf, unsigned int len) } static struct sk_buff *receive_big(struct net_device *dev, + struct virtnet_info *vi, struct receive_queue *rq, void *buf, unsigned int len) { struct page *page = buf; - struct sk_buff *skb = page_to_skb(rq, page, 0, len, PAGE_SIZE); + struct sk_buff *skb = page_to_skb(vi, rq, page, 0, len, PAGE_SIZE); if (unlikely(!skb)) goto err; @@ -359,7 +360,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, int offset = buf - page_address(page); unsigned int truesize = max(len, mergeable_ctx_to_buf_truesize(ctx)); - struct sk_buff *head_skb = page_to_skb(rq, page, offset, len, truesize); + struct sk_buff *head_skb = page_to_skb(vi, rq, page, offset, len, + truesize); struct sk_buff *curr_skb = head_skb; if (unlikely(!curr_skb)) @@ -433,9 +435,9 @@ err_buf: return NULL; } -static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) +static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, + void *buf, unsigned int len) { - struct virtnet_info *vi = rq-vq-vdev-priv; struct net_device *dev = vi-dev; struct virtnet_stats *stats = this_cpu_ptr(vi-stats); struct sk_buff *skb; @@ -459,7 +461,7 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) if (vi-mergeable_rx_bufs) skb = receive_mergeable(dev, vi, rq, (unsigned long)buf, len); else if (vi-big_packets) - skb = receive_big(dev, rq, buf, len); + skb = receive_big(dev, vi, rq, buf, len); else skb = receive_small(buf, len); @@ -539,9 +541,9 @@ frame_err: dev_kfree_skb(skb); } -static int add_recvbuf_small(struct receive_queue *rq, gfp_t gfp) +static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, +gfp_t gfp) { - struct virtnet_info *vi = rq-vq-vdev-priv; struct sk_buff *skb; struct skb_vnet_hdr *hdr; int err; @@ -664,9 +666,9 @@ static int add_recvbuf_mergeable(struct receive_queue *rq, gfp_t gfp) * before we're receiving packets, or from refill_work which is * careful to disable receiving (using napi_disable). */ -static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp) +static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq, + gfp_t gfp) { - struct virtnet_info *vi = rq-vq-vdev-priv; int err; bool oom; @@ -677,7 +679,7 @@ static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp) else if (vi-big_packets) err = add_recvbuf_big(rq, gfp); else - err = add_recvbuf_small(rq, gfp); + err = add_recvbuf_small(vi, rq, gfp); oom = err == -ENOMEM; if (err) @@ -726,7 +728,7 @@ static void refill_work(struct work_struct *work) struct receive_queue *rq = vi-rq[i]; napi_disable(rq-napi); - still_empty = !try_fill_recv(rq, GFP_KERNEL); + still_empty = !try_fill_recv(vi, rq, GFP_KERNEL); virtnet_napi_enable(rq); /* In theory, this can happen: if we don't get any buffers in @@ -745,12 +747,12 @@ static int virtnet_receive(struct receive_queue *rq, int budget) while (received budget (buf =
[PATCH v7 16/46] virtio_blk: v1.0 support
Based on patch by Cornelia Huck. Note: for consistency, and to avoid sparse errors, convert all fields, even those no longer in use for virtio v1.0. Signed-off-by: Cornelia Huck cornelia.h...@de.ibm.com Signed-off-by: Michael S. Tsirkin m...@redhat.com --- include/uapi/linux/virtio_blk.h | 15 - drivers/block/virtio_blk.c | 70 - 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/include/uapi/linux/virtio_blk.h b/include/uapi/linux/virtio_blk.h index 9ad67b2..247c8ba 100644 --- a/include/uapi/linux/virtio_blk.h +++ b/include/uapi/linux/virtio_blk.h @@ -28,6 +28,7 @@ #include linux/types.h #include linux/virtio_ids.h #include linux/virtio_config.h +#include linux/virtio_types.h /* Feature bits */ #define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */ @@ -114,18 +115,18 @@ struct virtio_blk_config { /* This is the first element of the read scatter-gather list. */ struct virtio_blk_outhdr { /* VIRTIO_BLK_T* */ - __u32 type; + __virtio32 type; /* io priority. */ - __u32 ioprio; + __virtio32 ioprio; /* Sector (ie. 512 byte offset) */ - __u64 sector; + __virtio64 sector; }; struct virtio_scsi_inhdr { - __u32 errors; - __u32 data_len; - __u32 sense_len; - __u32 residual; + __virtio32 errors; + __virtio32 data_len; + __virtio32 sense_len; + __virtio32 residual; }; /* And this is the final byte of the write scatter-gather list. */ diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index c6a27d5..f601f16 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -80,7 +80,7 @@ static int __virtblk_add_req(struct virtqueue *vq, { struct scatterlist hdr, status, cmd, sense, inhdr, *sgs[6]; unsigned int num_out = 0, num_in = 0; - int type = vbr-out_hdr.type ~VIRTIO_BLK_T_OUT; + __virtio32 type = vbr-out_hdr.type ~cpu_to_virtio32(vq-vdev, VIRTIO_BLK_T_OUT); sg_init_one(hdr, vbr-out_hdr, sizeof(vbr-out_hdr)); sgs[num_out++] = hdr; @@ -91,19 +91,19 @@ static int __virtblk_add_req(struct virtqueue *vq, * block, and before the normal inhdr we put the sense data and the * inhdr with additional status information. */ - if (type == VIRTIO_BLK_T_SCSI_CMD) { + if (type == cpu_to_virtio32(vq-vdev, VIRTIO_BLK_T_SCSI_CMD)) { sg_init_one(cmd, vbr-req-cmd, vbr-req-cmd_len); sgs[num_out++] = cmd; } if (have_data) { - if (vbr-out_hdr.type VIRTIO_BLK_T_OUT) + if (vbr-out_hdr.type cpu_to_virtio32(vq-vdev, VIRTIO_BLK_T_OUT)) sgs[num_out++] = data_sg; else sgs[num_out + num_in++] = data_sg; } - if (type == VIRTIO_BLK_T_SCSI_CMD) { + if (type == cpu_to_virtio32(vq-vdev, VIRTIO_BLK_T_SCSI_CMD)) { sg_init_one(sense, vbr-req-sense, SCSI_SENSE_BUFFERSIZE); sgs[num_out + num_in++] = sense; sg_init_one(inhdr, vbr-in_hdr, sizeof(vbr-in_hdr)); @@ -119,12 +119,13 @@ static int __virtblk_add_req(struct virtqueue *vq, static inline void virtblk_request_done(struct request *req) { struct virtblk_req *vbr = blk_mq_rq_to_pdu(req); + struct virtio_blk *vblk = req-q-queuedata; int error = virtblk_result(vbr); if (req-cmd_type == REQ_TYPE_BLOCK_PC) { - req-resid_len = vbr-in_hdr.residual; - req-sense_len = vbr-in_hdr.sense_len; - req-errors = vbr-in_hdr.errors; + req-resid_len = virtio32_to_cpu(vblk-vdev, vbr-in_hdr.residual); + req-sense_len = virtio32_to_cpu(vblk-vdev, vbr-in_hdr.sense_len); + req-errors = virtio32_to_cpu(vblk-vdev, vbr-in_hdr.errors); } else if (req-cmd_type == REQ_TYPE_SPECIAL) { req-errors = (error != 0); } @@ -173,25 +174,25 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req, vbr-req = req; if (req-cmd_flags REQ_FLUSH) { - vbr-out_hdr.type = VIRTIO_BLK_T_FLUSH; + vbr-out_hdr.type = cpu_to_virtio32(vblk-vdev, VIRTIO_BLK_T_FLUSH); vbr-out_hdr.sector = 0; - vbr-out_hdr.ioprio = req_get_ioprio(vbr-req); + vbr-out_hdr.ioprio = cpu_to_virtio32(vblk-vdev, req_get_ioprio(vbr-req)); } else { switch (req-cmd_type) { case REQ_TYPE_FS: vbr-out_hdr.type = 0; - vbr-out_hdr.sector = blk_rq_pos(vbr-req); - vbr-out_hdr.ioprio = req_get_ioprio(vbr-req); + vbr-out_hdr.sector = cpu_to_virtio64(vblk-vdev, blk_rq_pos(vbr-req)); + vbr-out_hdr.ioprio = cpu_to_virtio32(vblk-vdev,
[PATCH v7 21/46] virtio_blk: make serial attribute static
It's never declared so no need to make it extern. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/block/virtio_blk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index f601f16..055f3df 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -332,7 +332,8 @@ static ssize_t virtblk_serial_show(struct device *dev, return err; } -DEVICE_ATTR(serial, S_IRUGO, virtblk_serial_show, NULL); + +static DEVICE_ATTR(serial, S_IRUGO, virtblk_serial_show, NULL); static void virtblk_config_changed_work(struct work_struct *work) { -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v7 24/46] virtio_net: get rid of virtio_net_hdr/skb_vnet_hdr
virtio 1.0 doesn't use virtio_net_hdr anymore, and in fact, it's not really useful since virtio_net_hdr_mrg_rxbuf includes that as the first field anyway. Let's drop it, precalculate header len and store within vi instead. This way we can also remove struct skb_vnet_hdr. Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com Reviewed-by: Jason Wang jasow...@redhat.com --- drivers/net/virtio_net.c | 90 ++-- 1 file changed, 41 insertions(+), 49 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 1630c21..516f2cb 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -123,6 +123,9 @@ struct virtnet_info { /* Host can handle any s/g split between our header and packet data */ bool any_header_sg; + /* Packet virtio header size */ + u8 hdr_len; + /* Active statistics */ struct virtnet_stats __percpu *stats; @@ -139,21 +142,14 @@ struct virtnet_info { struct notifier_block nb; }; -struct skb_vnet_hdr { - union { - struct virtio_net_hdr hdr; - struct virtio_net_hdr_mrg_rxbuf mhdr; - }; -}; - struct padded_vnet_hdr { - struct virtio_net_hdr hdr; + struct virtio_net_hdr_mrg_rxbuf hdr; /* -* virtio_net_hdr should be in a separated sg buffer because of a -* QEMU bug, and data sg buffer shares same page with this header sg. -* This padding makes next sg 16 byte aligned after virtio_net_hdr. +* hdr is in a separate sg buffer, and data sg buffer shares same page +* with this header sg. This padding makes next sg 16 byte aligned +* after the header. */ - char padding[6]; + char padding[4]; }; /* Converting between virtqueue no. and kernel tx/rx queue no. @@ -179,9 +175,9 @@ static int rxq2vq(int rxq) return rxq * 2; } -static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb) +static inline struct virtio_net_hdr_mrg_rxbuf *skb_vnet_hdr(struct sk_buff *skb) { - return (struct skb_vnet_hdr *)skb-cb; + return (struct virtio_net_hdr_mrg_rxbuf *)skb-cb; } /* @@ -247,7 +243,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, unsigned int len, unsigned int truesize) { struct sk_buff *skb; - struct skb_vnet_hdr *hdr; + struct virtio_net_hdr_mrg_rxbuf *hdr; unsigned int copy, hdr_len, hdr_padded_len; char *p; @@ -260,13 +256,11 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, hdr = skb_vnet_hdr(skb); - if (vi-mergeable_rx_bufs) { - hdr_len = sizeof hdr-mhdr; - hdr_padded_len = sizeof hdr-mhdr; - } else { - hdr_len = sizeof hdr-hdr; + hdr_len = vi-hdr_len; + if (vi-mergeable_rx_bufs) + hdr_padded_len = sizeof *hdr; + else hdr_padded_len = sizeof(struct padded_vnet_hdr); - } memcpy(hdr, p, hdr_len); @@ -317,11 +311,11 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, return skb; } -static struct sk_buff *receive_small(void *buf, unsigned int len) +static struct sk_buff *receive_small(struct virtnet_info *vi, void *buf, unsigned int len) { struct sk_buff * skb = buf; - len -= sizeof(struct virtio_net_hdr); + len -= vi-hdr_len; skb_trim(skb, len); return skb; @@ -354,8 +348,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, unsigned int len) { void *buf = mergeable_ctx_to_buf_address(ctx); - struct skb_vnet_hdr *hdr = buf; - u16 num_buf = virtio16_to_cpu(rq-vq-vdev, hdr-mhdr.num_buffers); + struct virtio_net_hdr_mrg_rxbuf *hdr = buf; + u16 num_buf = virtio16_to_cpu(vi-vdev, hdr-num_buffers); struct page *page = virt_to_head_page(buf); int offset = buf - page_address(page); unsigned int truesize = max(len, mergeable_ctx_to_buf_truesize(ctx)); @@ -373,8 +367,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, if (unlikely(!ctx)) { pr_debug(%s: rx error: %d buffers out of %d missing\n, dev-name, num_buf, -virtio16_to_cpu(rq-vq-vdev, -hdr-mhdr.num_buffers)); +virtio16_to_cpu(vi-vdev, +hdr-num_buffers)); dev-stats.rx_length_errors++; goto err_buf; } @@ -441,7 +435,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, struct net_device *dev = vi-dev; struct virtnet_stats *stats = this_cpu_ptr(vi-stats);
[PATCH v7 26/46] virtio_net: bigger header when VERSION_1 is set
With VERSION_1 virtio_net uses same header size whether mergeable buffers are enabled or not. Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com Reviewed-by: Jason Wang jasow...@redhat.com --- drivers/net/virtio_net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 098f443..a0e64cf 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1805,7 +1805,8 @@ static int virtnet_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) vi-mergeable_rx_bufs = true; - if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) + if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) || + virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) vi-hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); else vi-hdr_len = sizeof(struct virtio_net_hdr); -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v7 29/46] vhost: add memory access wrappers
Add guest memory access wrappers to handle virtio endianness conversions. Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: Jason Wang jasow...@redhat.com --- drivers/vhost/vhost.h | 31 +++ 1 file changed, 31 insertions(+) diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index c624b09..1f321fd 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -176,4 +176,35 @@ static inline int vhost_has_feature(struct vhost_virtqueue *vq, int bit) { return vq-acked_features (1ULL bit); } + +/* Memory accessors */ +static inline u16 vhost16_to_cpu(struct vhost_virtqueue *vq, __virtio16 val) +{ + return __virtio16_to_cpu(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); +} + +static inline __virtio16 cpu_to_vhost16(struct vhost_virtqueue *vq, u16 val) +{ + return __cpu_to_virtio16(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); +} + +static inline u32 vhost32_to_cpu(struct vhost_virtqueue *vq, __virtio32 val) +{ + return __virtio32_to_cpu(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); +} + +static inline __virtio32 cpu_to_vhost32(struct vhost_virtqueue *vq, u32 val) +{ + return __cpu_to_virtio32(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); +} + +static inline u64 vhost64_to_cpu(struct vhost_virtqueue *vq, __virtio64 val) +{ + return __virtio64_to_cpu(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); +} + +static inline __virtio64 cpu_to_vhost64(struct vhost_virtqueue *vq, u64 val) +{ + return __cpu_to_virtio64(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); +} #endif -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v7 25/46] virtio_net: stricter short buffer length checks
Our buffer length check is not strict enough for mergeable buffers: buffer can still be shorter that header + address by 2 bytes. Fix that up. Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com Reviewed-by: Jason Wang jasow...@redhat.com --- drivers/net/virtio_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 516f2cb..098f443 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -437,7 +437,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, struct sk_buff *skb; struct virtio_net_hdr_mrg_rxbuf *hdr; - if (unlikely(len sizeof(struct virtio_net_hdr) + ETH_HLEN)) { + if (unlikely(len vi-hdr_len + ETH_HLEN)) { pr_debug(%s: short packet %i\n, dev-name, len); dev-stats.rx_length_errors++; if (vi-mergeable_rx_bufs) { -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v7 31/46] vhost: virtio 1.0 endian-ness support
Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/vhost/vhost.c | 93 +++ 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index c90f437..4d379ed 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -33,8 +33,8 @@ enum { VHOST_MEMORY_F_LOG = 0x1, }; -#define vhost_used_event(vq) ((u16 __user *)vq-avail-ring[vq-num]) -#define vhost_avail_event(vq) ((u16 __user *)vq-used-ring[vq-num]) +#define vhost_used_event(vq) ((__virtio16 __user *)vq-avail-ring[vq-num]) +#define vhost_avail_event(vq) ((__virtio16 __user *)vq-used-ring[vq-num]) static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh, poll_table *pt) @@ -1001,7 +1001,7 @@ EXPORT_SYMBOL_GPL(vhost_log_write); static int vhost_update_used_flags(struct vhost_virtqueue *vq) { void __user *used; - if (__put_user(vq-used_flags, vq-used-flags) 0) + if (__put_user(cpu_to_vhost16(vq, vq-used_flags), vq-used-flags) 0) return -EFAULT; if (unlikely(vq-log_used)) { /* Make sure the flag is seen before log. */ @@ -1019,7 +1019,7 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq) static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event) { - if (__put_user(vq-avail_idx, vhost_avail_event(vq))) + if (__put_user(cpu_to_vhost16(vq, vq-avail_idx), vhost_avail_event(vq))) return -EFAULT; if (unlikely(vq-log_used)) { void __user *used; @@ -1038,6 +1038,7 @@ static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event) int vhost_init_used(struct vhost_virtqueue *vq) { + __virtio16 last_used_idx; int r; if (!vq-private_data) return 0; @@ -1046,7 +1047,13 @@ int vhost_init_used(struct vhost_virtqueue *vq) if (r) return r; vq-signalled_used_valid = false; - return get_user(vq-last_used_idx, vq-used-idx); + if (!access_ok(VERIFY_READ, vq-used-idx, sizeof vq-used-idx)) + return -EFAULT; + r = __get_user(last_used_idx, vq-used-idx); + if (r) + return r; + vq-last_used_idx = vhost16_to_cpu(vq, last_used_idx); + return 0; } EXPORT_SYMBOL_GPL(vhost_init_used); @@ -1087,16 +1094,16 @@ static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, /* Each buffer in the virtqueues is actually a chain of descriptors. This * function returns the next descriptor in the chain, * or -1U if we're at the end. */ -static unsigned next_desc(struct vring_desc *desc) +static unsigned next_desc(struct vhost_virtqueue *vq, struct vring_desc *desc) { unsigned int next; /* If this descriptor says it doesn't chain, we're done. */ - if (!(desc-flags VRING_DESC_F_NEXT)) + if (!(desc-flags cpu_to_vhost16(vq, VRING_DESC_F_NEXT))) return -1U; /* Check they're not leading us off end of descriptors. */ - next = desc-next; + next = vhost16_to_cpu(vq, desc-next); /* Make sure compiler knows to grab that: we don't want it changing! */ /* We will use the result as an index in an array, so most * architectures only need a compiler barrier here. */ @@ -1113,18 +1120,19 @@ static int get_indirect(struct vhost_virtqueue *vq, { struct vring_desc desc; unsigned int i = 0, count, found = 0; + u32 len = vhost32_to_cpu(vq, indirect-len); int ret; /* Sanity check */ - if (unlikely(indirect-len % sizeof desc)) { + if (unlikely(len % sizeof desc)) { vq_err(vq, Invalid length in indirect descriptor: len 0x%llx not multiple of 0x%zx\n, - (unsigned long long)indirect-len, + (unsigned long long)vhost32_to_cpu(vq, indirect-len), sizeof desc); return -EINVAL; } - ret = translate_desc(vq, indirect-addr, indirect-len, vq-indirect, + ret = translate_desc(vq, vhost64_to_cpu(vq, indirect-addr), len, vq-indirect, UIO_MAXIOV); if (unlikely(ret 0)) { vq_err(vq, Translation failure %d in indirect.\n, ret); @@ -1135,7 +1143,7 @@ static int get_indirect(struct vhost_virtqueue *vq, * architectures only need a compiler barrier here. */ read_barrier_depends(); - count = indirect-len / sizeof desc; + count = len / sizeof desc; /* Buffers are chained via a 16 bit next field, so * we can have at most 2^16 of these. */ if (unlikely(count USHRT_MAX + 1)) { @@ -1155,16 +1163,17 @@ static int get_indirect(struct vhost_virtqueue *vq, if (unlikely(memcpy_fromiovec((unsigned char *)desc,
[PATCH v7 33/46] vhost/net: larger header for virtio 1.0
Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: Jason Wang jasow...@redhat.com --- drivers/vhost/net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index cae22f9..1ac58d0 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -1027,7 +1027,8 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features) size_t vhost_hlen, sock_hlen, hdr_len; int i; - hdr_len = (features (1 VIRTIO_NET_F_MRG_RXBUF)) ? + hdr_len = (features ((1ULL VIRTIO_NET_F_MRG_RXBUF) | + (1ULL VIRTIO_F_VERSION_1))) ? sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); if (features (1 VHOST_NET_F_VIRTIO_NET_HDR)) { -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v7 42/46] virtio_scsi: v1.0 support
Note: for consistency, and to avoid sparse errors, convert all fields, even those no longer in use for virtio v1.0. Signed-off-by: Michael S. Tsirkin m...@redhat.com Acked-by: Paolo Bonzini pbonz...@redhat.com --- include/linux/virtio_scsi.h | 32 +++- drivers/scsi/virtio_scsi.c | 51 - 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/include/linux/virtio_scsi.h b/include/linux/virtio_scsi.h index de429d1..af44864 100644 --- a/include/linux/virtio_scsi.h +++ b/include/linux/virtio_scsi.h @@ -27,13 +27,15 @@ #ifndef _LINUX_VIRTIO_SCSI_H #define _LINUX_VIRTIO_SCSI_H +#include linux/virtio_types.h + #define VIRTIO_SCSI_CDB_SIZE 32 #define VIRTIO_SCSI_SENSE_SIZE 96 /* SCSI command request, followed by data-out */ struct virtio_scsi_cmd_req { u8 lun[8]; /* Logical Unit Number */ - u64 tag;/* Command identifier */ + __virtio64 tag; /* Command identifier */ u8 task_attr; /* Task attribute */ u8 prio;/* SAM command priority field */ u8 crn; @@ -43,20 +45,20 @@ struct virtio_scsi_cmd_req { /* SCSI command request, followed by protection information */ struct virtio_scsi_cmd_req_pi { u8 lun[8]; /* Logical Unit Number */ - u64 tag;/* Command identifier */ + __virtio64 tag; /* Command identifier */ u8 task_attr; /* Task attribute */ u8 prio;/* SAM command priority field */ u8 crn; - u32 pi_bytesout;/* DataOUT PI Number of bytes */ - u32 pi_bytesin; /* DataIN PI Number of bytes */ + __virtio32 pi_bytesout; /* DataOUT PI Number of bytes */ + __virtio32 pi_bytesin; /* DataIN PI Number of bytes */ u8 cdb[VIRTIO_SCSI_CDB_SIZE]; } __packed; /* Response, followed by sense data and data-in */ struct virtio_scsi_cmd_resp { - u32 sense_len; /* Sense data length */ - u32 resid; /* Residual bytes in data buffer */ - u16 status_qualifier; /* Status qualifier */ + __virtio32 sense_len; /* Sense data length */ + __virtio32 resid; /* Residual bytes in data buffer */ + __virtio16 status_qualifier;/* Status qualifier */ u8 status; /* Command completion status */ u8 response;/* Response values */ u8 sense[VIRTIO_SCSI_SENSE_SIZE]; @@ -64,10 +66,10 @@ struct virtio_scsi_cmd_resp { /* Task Management Request */ struct virtio_scsi_ctrl_tmf_req { - u32 type; - u32 subtype; + __virtio32 type; + __virtio32 subtype; u8 lun[8]; - u64 tag; + __virtio64 tag; } __packed; struct virtio_scsi_ctrl_tmf_resp { @@ -76,20 +78,20 @@ struct virtio_scsi_ctrl_tmf_resp { /* Asynchronous notification query/subscription */ struct virtio_scsi_ctrl_an_req { - u32 type; + __virtio32 type; u8 lun[8]; - u32 event_requested; + __virtio32 event_requested; } __packed; struct virtio_scsi_ctrl_an_resp { - u32 event_actual; + __virtio32 event_actual; u8 response; } __packed; struct virtio_scsi_event { - u32 event; + __virtio32 event; u8 lun[8]; - u32 reason; + __virtio32 reason; } __packed; struct virtio_scsi_config { diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index b83846f..d9ec806 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -158,7 +158,7 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf) sc, resp-response, resp-status, resp-sense_len); sc-result = resp-status; - virtscsi_compute_resid(sc, resp-resid); + virtscsi_compute_resid(sc, virtio32_to_cpu(vscsi-vdev, resp-resid)); switch (resp-response) { case VIRTIO_SCSI_S_OK: set_host_byte(sc, DID_OK); @@ -196,10 +196,13 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf) break; } - WARN_ON(resp-sense_len VIRTIO_SCSI_SENSE_SIZE); + WARN_ON(virtio32_to_cpu(vscsi-vdev, resp-sense_len) + VIRTIO_SCSI_SENSE_SIZE); if (sc-sense_buffer) { memcpy(sc-sense_buffer, resp-sense, - min_t(u32, resp-sense_len, VIRTIO_SCSI_SENSE_SIZE)); + min_t(u32, +virtio32_to_cpu(vscsi-vdev, resp-sense_len), +VIRTIO_SCSI_SENSE_SIZE)); if (resp-sense_len) set_driver_byte(sc, DRIVER_SENSE); } @@ -323,7 +326,7 @@ static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi, unsigned int target = event-lun[1]; unsigned int lun = (event-lun[2] 8) | event-lun[3]; - switch
[PATCH v7 36/46] vhost/net: suppress compiler warning
len is always initialized since function is called with size 0. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/vhost/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 984242e..54ffbb0 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -501,7 +501,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, int headcount = 0; unsigned d; int r, nlogs = 0; - u32 len; + u32 uninitialized_var(len); while (datalen 0 headcount quota) { if (unlikely(seg = UIO_MAXIOV)) { -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH v7 28/46] vhost: make features 64 bit
Hello. On 11/30/2014 6:11 PM, Michael S. Tsirkin wrote: We need to use bit 32 for virtio 1.0 Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: Jason Wang jasow...@redhat.com --- drivers/vhost/vhost.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 3eda654..c624b09 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -106,7 +106,7 @@ struct vhost_virtqueue { /* Protected by virtqueue mutex. */ struct vhost_memory *memory; void *private_data; - unsigned acked_features; + u64 acked_features; /* Log write descriptors */ void __user *log_base; struct vhost_log *log; @@ -174,6 +174,6 @@ enum { static inline int vhost_has_feature(struct vhost_virtqueue *vq, int bit) { - return vq-acked_features (1 bit); + return vq-acked_features (1ULL bit); Erm, wouldn't the high word be just dropped when returning *int*? I think you need !!(vq-acked_features (1ULL bit)). [...] WBR, Sergei ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH v7 28/46] vhost: make features 64 bit
On Sun, 2014-11-30 at 18:44 +0300, Sergei Shtylyov wrote: Hello. On 11/30/2014 6:11 PM, Michael S. Tsirkin wrote: We need to use bit 32 for virtio 1.0 Signed-off-by: Michael S. Tsirkin m...@redhat.com Reviewed-by: Jason Wang jasow...@redhat.com --- drivers/vhost/vhost.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 3eda654..c624b09 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -106,7 +106,7 @@ struct vhost_virtqueue { /* Protected by virtqueue mutex. */ struct vhost_memory *memory; void *private_data; - unsigned acked_features; + u64 acked_features; /* Log write descriptors */ void __user *log_base; struct vhost_log *log; @@ -174,6 +174,6 @@ enum { static inline int vhost_has_feature(struct vhost_virtqueue *vq, int bit) { - return vq-acked_features (1 bit); + return vq-acked_features (1ULL bit); Erm, wouldn't the high word be just dropped when returning *int*? I think you need !!(vq-acked_features (1ULL bit)). Or change the return type to bool. Ben. -- Ben Hutchings The first rule of tautology club is the first rule of tautology club. signature.asc Description: This is a digitally signed message part ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization