Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost

Pull virtio/vhost cross endian support from Michael Tsirkin:
"I have just queued some more bugfix patches today but none fix
regressions and none are related to these ones, so it looks like a
good time for a merge for -rc1.

The motivation for this is support for legacy BE guests on the new LE
hosts. There are two redeeming properties that made me merge this:

- It's a trivial amount of code: since we wrap host/guest accesses
anyway, almost all of it is well hidden from drivers.

- Sane platforms would never set flags like VHOST_CROSS_ENDIAN_LEGACY,
and when it's clear, there's zero overhead (as some point it was
tested by compiling with and without the patches, got the same
stripped binary).

Maybe we could create a Kconfig symbol to enforce the second point:
prevent people from enabling it eg on x86. I will look into this"

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
virtio-pci: alloc only resources actually used.
macvtap/tun: cross-endian support for little-endian hosts
vhost: cross-endian support for legacy devices
virtio: add explicit big-endian support to memory accessors
vhost: introduce vhost_is_little_endian() helper
vringh: introduce vringh_is_little_endian() helper
macvtap: introduce macvtap_is_little_endian() helper
tun: add tun_is_little_endian() helper
virtio: introduce virtio_is_little_endian() helper

+350 -47
+14
drivers/net/Kconfig
··· 258 258 259 259 If you don't know what to use this for, you don't need it. 260 260 261 + config TUN_VNET_CROSS_LE 262 + bool "Support for cross-endian vnet headers on little-endian kernels" 263 + default n 264 + ---help--- 265 + This option allows TUN/TAP and MACVTAP device drivers in a 266 + little-endian kernel to parse vnet headers that come from a 267 + big-endian legacy virtio device. 268 + 269 + Userspace programs can control the feature using the TUNSETVNETBE 270 + and TUNGETVNETBE ioctls. 271 + 272 + Unless you have a little-endian system hosting a big-endian virtual 273 + machine with a legacy virtio NIC, you should say N. 274 + 261 275 config VETH 262 276 tristate "Virtual ethernet pair device" 263 277 ---help---
+63 -2
drivers/net/macvtap.c
··· 48 48 #define MACVTAP_FEATURES (IFF_VNET_HDR | IFF_MULTI_QUEUE) 49 49 50 50 #define MACVTAP_VNET_LE 0x80000000 51 + #define MACVTAP_VNET_BE 0x40000000 52 + 53 + #ifdef CONFIG_TUN_VNET_CROSS_LE 54 + static inline bool macvtap_legacy_is_little_endian(struct macvtap_queue *q) 55 + { 56 + return q->flags & MACVTAP_VNET_BE ? false : 57 + virtio_legacy_is_little_endian(); 58 + } 59 + 60 + static long macvtap_get_vnet_be(struct macvtap_queue *q, int __user *sp) 61 + { 62 + int s = !!(q->flags & MACVTAP_VNET_BE); 63 + 64 + if (put_user(s, sp)) 65 + return -EFAULT; 66 + 67 + return 0; 68 + } 69 + 70 + static long macvtap_set_vnet_be(struct macvtap_queue *q, int __user *sp) 71 + { 72 + int s; 73 + 74 + if (get_user(s, sp)) 75 + return -EFAULT; 76 + 77 + if (s) 78 + q->flags |= MACVTAP_VNET_BE; 79 + else 80 + q->flags &= ~MACVTAP_VNET_BE; 81 + 82 + return 0; 83 + } 84 + #else 85 + static inline bool macvtap_legacy_is_little_endian(struct macvtap_queue *q) 86 + { 87 + return virtio_legacy_is_little_endian(); 88 + } 89 + 90 + static long macvtap_get_vnet_be(struct macvtap_queue *q, int __user *argp) 91 + { 92 + return -EINVAL; 93 + } 94 + 95 + static long macvtap_set_vnet_be(struct macvtap_queue *q, int __user *argp) 96 + { 97 + return -EINVAL; 98 + } 99 + #endif /* CONFIG_TUN_VNET_CROSS_LE */ 100 + 101 + static inline bool macvtap_is_little_endian(struct macvtap_queue *q) 102 + { 103 + return q->flags & MACVTAP_VNET_LE || 104 + macvtap_legacy_is_little_endian(q); 105 + } 51 106 52 107 static inline u16 macvtap16_to_cpu(struct macvtap_queue *q, __virtio16 val) 53 108 { 54 - return __virtio16_to_cpu(q->flags & MACVTAP_VNET_LE, val); 109 + return __virtio16_to_cpu(macvtap_is_little_endian(q), val); 55 110 } 56 111 57 112 static inline __virtio16 cpu_to_macvtap16(struct macvtap_queue *q, u16 val) 58 113 { 59 - return __cpu_to_virtio16(q->flags & MACVTAP_VNET_LE, val); 114 + return __cpu_to_virtio16(macvtap_is_little_endian(q), val); 60 115 } 61 116 62 117 static struct proto macvtap_proto = { ··· 1139 1084 else 1140 1085 q->flags &= ~MACVTAP_VNET_LE; 1141 1086 return 0; 1087 + 1088 + case TUNGETVNETBE: 1089 + return macvtap_get_vnet_be(q, sp); 1090 + 1091 + case TUNSETVNETBE: 1092 + return macvtap_set_vnet_be(q, sp); 1142 1093 1143 1094 case TUNSETOFFLOAD: 1144 1095 /* let the user check for future flags */
+65 -2
drivers/net/tun.c
··· 111 111 #define TUN_FASYNC IFF_ATTACH_QUEUE 112 112 /* High bits in flags field are unused. */ 113 113 #define TUN_VNET_LE 0x80000000 114 + #define TUN_VNET_BE 0x40000000 114 115 115 116 #define TUN_FEATURES (IFF_NO_PI | IFF_ONE_QUEUE | IFF_VNET_HDR | \ 116 117 IFF_MULTI_QUEUE) ··· 206 205 u32 flow_count; 207 206 }; 208 207 208 + #ifdef CONFIG_TUN_VNET_CROSS_LE 209 + static inline bool tun_legacy_is_little_endian(struct tun_struct *tun) 210 + { 211 + return tun->flags & TUN_VNET_BE ? false : 212 + virtio_legacy_is_little_endian(); 213 + } 214 + 215 + static long tun_get_vnet_be(struct tun_struct *tun, int __user *argp) 216 + { 217 + int be = !!(tun->flags & TUN_VNET_BE); 218 + 219 + if (put_user(be, argp)) 220 + return -EFAULT; 221 + 222 + return 0; 223 + } 224 + 225 + static long tun_set_vnet_be(struct tun_struct *tun, int __user *argp) 226 + { 227 + int be; 228 + 229 + if (get_user(be, argp)) 230 + return -EFAULT; 231 + 232 + if (be) 233 + tun->flags |= TUN_VNET_BE; 234 + else 235 + tun->flags &= ~TUN_VNET_BE; 236 + 237 + return 0; 238 + } 239 + #else 240 + static inline bool tun_legacy_is_little_endian(struct tun_struct *tun) 241 + { 242 + return virtio_legacy_is_little_endian(); 243 + } 244 + 245 + static long tun_get_vnet_be(struct tun_struct *tun, int __user *argp) 246 + { 247 + return -EINVAL; 248 + } 249 + 250 + static long tun_set_vnet_be(struct tun_struct *tun, int __user *argp) 251 + { 252 + return -EINVAL; 253 + } 254 + #endif /* CONFIG_TUN_VNET_CROSS_LE */ 255 + 256 + static inline bool tun_is_little_endian(struct tun_struct *tun) 257 + { 258 + return tun->flags & TUN_VNET_LE || 259 + tun_legacy_is_little_endian(tun); 260 + } 261 + 209 262 static inline u16 tun16_to_cpu(struct tun_struct *tun, __virtio16 val) 210 263 { 211 - return __virtio16_to_cpu(tun->flags & TUN_VNET_LE, val); 264 + return __virtio16_to_cpu(tun_is_little_endian(tun), val); 212 265 } 213 266 214 267 static inline __virtio16 cpu_to_tun16(struct tun_struct *tun, u16 val) 215 268 { 216 - return __cpu_to_virtio16(tun->flags & TUN_VNET_LE, val); 269 + return __cpu_to_virtio16(tun_is_little_endian(tun), val); 217 270 } 218 271 219 272 static inline u32 tun_hashfn(u32 rxhash) ··· 2097 2042 tun->flags |= TUN_VNET_LE; 2098 2043 else 2099 2044 tun->flags &= ~TUN_VNET_LE; 2045 + break; 2046 + 2047 + case TUNGETVNETBE: 2048 + ret = tun_get_vnet_be(tun, argp); 2049 + break; 2050 + 2051 + case TUNSETVNETBE: 2052 + ret = tun_set_vnet_be(tun, argp); 2100 2053 break; 2101 2054 2102 2055 case TUNATTACHFILTER:
+15
drivers/vhost/Kconfig
··· 32 32 ---help--- 33 33 This option is selected by any driver which needs to access 34 34 the core of vhost. 35 + 36 + config VHOST_CROSS_ENDIAN_LEGACY 37 + bool "Cross-endian support for vhost" 38 + default n 39 + ---help--- 40 + This option allows vhost to support guests with a different byte 41 + ordering from host while using legacy virtio. 42 + 43 + Userspace programs can control the feature using the 44 + VHOST_SET_VRING_ENDIAN and VHOST_GET_VRING_ENDIAN ioctls. 45 + 46 + This is only useful on a few platforms (ppc64 and arm64). Since it 47 + adds some overhead, it is disabled by default. 48 + 49 + If unsure, say "N".
+84 -1
drivers/vhost/vhost.c
··· 36 36 #define vhost_used_event(vq) ((__virtio16 __user *)&vq->avail->ring[vq->num]) 37 37 #define vhost_avail_event(vq) ((__virtio16 __user *)&vq->used->ring[vq->num]) 38 38 39 + #ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY 40 + static void vhost_vq_reset_user_be(struct vhost_virtqueue *vq) 41 + { 42 + vq->user_be = !virtio_legacy_is_little_endian(); 43 + } 44 + 45 + static long vhost_set_vring_endian(struct vhost_virtqueue *vq, int __user *argp) 46 + { 47 + struct vhost_vring_state s; 48 + 49 + if (vq->private_data) 50 + return -EBUSY; 51 + 52 + if (copy_from_user(&s, argp, sizeof(s))) 53 + return -EFAULT; 54 + 55 + if (s.num != VHOST_VRING_LITTLE_ENDIAN && 56 + s.num != VHOST_VRING_BIG_ENDIAN) 57 + return -EINVAL; 58 + 59 + vq->user_be = s.num; 60 + 61 + return 0; 62 + } 63 + 64 + static long vhost_get_vring_endian(struct vhost_virtqueue *vq, u32 idx, 65 + int __user *argp) 66 + { 67 + struct vhost_vring_state s = { 68 + .index = idx, 69 + .num = vq->user_be 70 + }; 71 + 72 + if (copy_to_user(argp, &s, sizeof(s))) 73 + return -EFAULT; 74 + 75 + return 0; 76 + } 77 + 78 + static void vhost_init_is_le(struct vhost_virtqueue *vq) 79 + { 80 + /* Note for legacy virtio: user_be is initialized at reset time 81 + * according to the host endianness. If userspace does not set an 82 + * explicit endianness, the default behavior is native endian, as 83 + * expected by legacy virtio. 84 + */ 85 + vq->is_le = vhost_has_feature(vq, VIRTIO_F_VERSION_1) || !vq->user_be; 86 + } 87 + #else 88 + static void vhost_vq_reset_user_be(struct vhost_virtqueue *vq) 89 + { 90 + } 91 + 92 + static long vhost_set_vring_endian(struct vhost_virtqueue *vq, int __user *argp) 93 + { 94 + return -ENOIOCTLCMD; 95 + } 96 + 97 + static long vhost_get_vring_endian(struct vhost_virtqueue *vq, u32 idx, 98 + int __user *argp) 99 + { 100 + return -ENOIOCTLCMD; 101 + } 102 + 103 + static void vhost_init_is_le(struct vhost_virtqueue *vq) 104 + { 105 + if (vhost_has_feature(vq, VIRTIO_F_VERSION_1)) 106 + vq->is_le = true; 107 + } 108 + #endif /* CONFIG_VHOST_CROSS_ENDIAN_LEGACY */ 109 + 39 110 static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh, 40 111 poll_table *pt) 41 112 { ··· 270 199 vq->call = NULL; 271 200 vq->log_ctx = NULL; 272 201 vq->memory = NULL; 202 + vq->is_le = virtio_legacy_is_little_endian(); 203 + vhost_vq_reset_user_be(vq); 273 204 } 274 205 275 206 static int vhost_worker(void *data) ··· 879 806 } else 880 807 filep = eventfp; 881 808 break; 809 + case VHOST_SET_VRING_ENDIAN: 810 + r = vhost_set_vring_endian(vq, argp); 811 + break; 812 + case VHOST_GET_VRING_ENDIAN: 813 + r = vhost_get_vring_endian(vq, idx, argp); 814 + break; 882 815 default: 883 816 r = -ENOIOCTLCMD; 884 817 } ··· 1123 1044 { 1124 1045 __virtio16 last_used_idx; 1125 1046 int r; 1126 - if (!vq->private_data) 1047 + if (!vq->private_data) { 1048 + vq->is_le = virtio_legacy_is_little_endian(); 1127 1049 return 0; 1050 + } 1051 + 1052 + vhost_init_is_le(vq); 1128 1053 1129 1054 r = vhost_update_used_flags(vq); 1130 1055 if (r)
+19 -6
drivers/vhost/vhost.h
··· 106 106 /* Log write descriptors */ 107 107 void __user *log_base; 108 108 struct vhost_log *log; 109 + 110 + /* Ring endianness. Defaults to legacy native endianness. 111 + * Set to true when starting a modern virtio device. */ 112 + bool is_le; 113 + #ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY 114 + /* Ring endianness requested by userspace for cross-endian support. */ 115 + bool user_be; 116 + #endif 109 117 }; 110 118 111 119 struct vhost_dev { ··· 181 173 return vq->acked_features & (1ULL << bit); 182 174 } 183 175 176 + static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq) 177 + { 178 + return vq->is_le; 179 + } 180 + 184 181 /* Memory accessors */ 185 182 static inline u16 vhost16_to_cpu(struct vhost_virtqueue *vq, __virtio16 val) 186 183 { 187 - return __virtio16_to_cpu(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); 184 + return __virtio16_to_cpu(vhost_is_little_endian(vq), val); 188 185 } 189 186 190 187 static inline __virtio16 cpu_to_vhost16(struct vhost_virtqueue *vq, u16 val) 191 188 { 192 - return __cpu_to_virtio16(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); 189 + return __cpu_to_virtio16(vhost_is_little_endian(vq), val); 193 190 } 194 191 195 192 static inline u32 vhost32_to_cpu(struct vhost_virtqueue *vq, __virtio32 val) 196 193 { 197 - return __virtio32_to_cpu(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); 194 + return __virtio32_to_cpu(vhost_is_little_endian(vq), val); 198 195 } 199 196 200 197 static inline __virtio32 cpu_to_vhost32(struct vhost_virtqueue *vq, u32 val) 201 198 { 202 - return __cpu_to_virtio32(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); 199 + return __cpu_to_virtio32(vhost_is_little_endian(vq), val); 203 200 } 204 201 205 202 static inline u64 vhost64_to_cpu(struct vhost_virtqueue *vq, __virtio64 val) 206 203 { 207 - return __virtio64_to_cpu(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); 204 + return __virtio64_to_cpu(vhost_is_little_endian(vq), val); 208 205 } 209 206 210 207 static inline __virtio64 cpu_to_vhost64(struct vhost_virtqueue *vq, u64 val) 211 208 { 212 - return __cpu_to_virtio64(vhost_has_feature(vq, VIRTIO_F_VERSION_1), val); 209 + return __cpu_to_virtio64(vhost_is_little_endian(vq), val); 213 210 } 214 211 #endif
-7
drivers/virtio/virtio_pci_common.c
··· 507 507 if (rc) 508 508 goto err_enable_device; 509 509 510 - rc = pci_request_regions(pci_dev, "virtio-pci"); 511 - if (rc) 512 - goto err_request_regions; 513 - 514 510 if (force_legacy) { 515 511 rc = virtio_pci_legacy_probe(vp_dev); 516 512 /* Also try modern mode if we can't map BAR0 (no IO space). */ ··· 536 540 else 537 541 virtio_pci_modern_remove(vp_dev); 538 542 err_probe: 539 - pci_release_regions(pci_dev); 540 - err_request_regions: 541 543 pci_disable_device(pci_dev); 542 544 err_enable_device: 543 545 kfree(vp_dev); ··· 553 559 else 554 560 virtio_pci_modern_remove(vp_dev); 555 561 556 - pci_release_regions(pci_dev); 557 562 pci_disable_device(pci_dev); 558 563 } 559 564
+2
drivers/virtio/virtio_pci_common.h
··· 75 75 /* Multiply queue_notify_off by this value. (non-legacy mode). */ 76 76 u32 notify_offset_multiplier; 77 77 78 + int modern_bars; 79 + 78 80 /* Legacy only field */ 79 81 /* the IO mapping for the PCI config space */ 80 82 void __iomem *ioaddr;
+12 -1
drivers/virtio/virtio_pci_legacy.c
··· 215 215 int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev) 216 216 { 217 217 struct pci_dev *pci_dev = vp_dev->pci_dev; 218 + int rc; 218 219 219 220 /* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */ 220 221 if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f) ··· 227 226 return -ENODEV; 228 227 } 229 228 229 + rc = pci_request_region(pci_dev, 0, "virtio-pci-legacy"); 230 + if (rc) 231 + return rc; 232 + 233 + rc = -ENOMEM; 230 234 vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0); 231 235 if (!vp_dev->ioaddr) 232 - return -ENOMEM; 236 + goto err_iomap; 233 237 234 238 vp_dev->isr = vp_dev->ioaddr + VIRTIO_PCI_ISR; 235 239 ··· 252 246 vp_dev->del_vq = del_vq; 253 247 254 248 return 0; 249 + 250 + err_iomap: 251 + pci_release_region(pci_dev, 0); 252 + return rc; 255 253 } 256 254 257 255 void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev) ··· 263 253 struct pci_dev *pci_dev = vp_dev->pci_dev; 264 254 265 255 pci_iounmap(pci_dev, vp_dev->ioaddr); 256 + pci_release_region(pci_dev, 0); 266 257 }
+18 -6
drivers/virtio/virtio_pci_modern.c
··· 499 499 * Returns offset of the capability, or 0. 500 500 */ 501 501 static inline int virtio_pci_find_capability(struct pci_dev *dev, u8 cfg_type, 502 - u32 ioresource_types) 502 + u32 ioresource_types, int *bars) 503 503 { 504 504 int pos; 505 505 ··· 520 520 521 521 if (type == cfg_type) { 522 522 if (pci_resource_len(dev, bar) && 523 - pci_resource_flags(dev, bar) & ioresource_types) 523 + pci_resource_flags(dev, bar) & ioresource_types) { 524 + *bars |= (1 << bar); 524 525 return pos; 526 + } 525 527 } 526 528 } 527 529 return 0; ··· 619 617 620 618 /* check for a common config: if not, use legacy mode (bar 0). */ 621 619 common = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_COMMON_CFG, 622 - IORESOURCE_IO | IORESOURCE_MEM); 620 + IORESOURCE_IO | IORESOURCE_MEM, 621 + &vp_dev->modern_bars); 623 622 if (!common) { 624 623 dev_info(&pci_dev->dev, 625 624 "virtio_pci: leaving for legacy driver\n"); ··· 629 626 630 627 /* If common is there, these should be too... */ 631 628 isr = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_ISR_CFG, 632 - IORESOURCE_IO | IORESOURCE_MEM); 629 + IORESOURCE_IO | IORESOURCE_MEM, 630 + &vp_dev->modern_bars); 633 631 notify = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_NOTIFY_CFG, 634 - IORESOURCE_IO | IORESOURCE_MEM); 632 + IORESOURCE_IO | IORESOURCE_MEM, 633 + &vp_dev->modern_bars); 635 634 if (!isr || !notify) { 636 635 dev_err(&pci_dev->dev, 637 636 "virtio_pci: missing capabilities %i/%i/%i\n", ··· 645 640 * device-specific configuration. 646 641 */ 647 642 device = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_DEVICE_CFG, 648 - IORESOURCE_IO | IORESOURCE_MEM); 643 + IORESOURCE_IO | IORESOURCE_MEM, 644 + &vp_dev->modern_bars); 645 + 646 + err = pci_request_selected_regions(pci_dev, vp_dev->modern_bars, 647 + "virtio-pci-modern"); 648 + if (err) 649 + return err; 649 650 650 651 err = -EINVAL; 651 652 vp_dev->common = map_capability(pci_dev, common, ··· 738 727 pci_iounmap(pci_dev, vp_dev->notify_base); 739 728 pci_iounmap(pci_dev, vp_dev->isr); 740 729 pci_iounmap(pci_dev, vp_dev->common); 730 + pci_release_selected_regions(pci_dev, vp_dev->modern_bars); 741 731 }
+14 -10
include/linux/virtio_byteorder.h
··· 3 3 #include <linux/types.h> 4 4 #include <uapi/linux/virtio_types.h> 5 5 6 - /* 7 - * Low-level memory accessors for handling virtio in modern little endian and in 8 - * compatibility native endian format. 9 - */ 6 + static inline bool virtio_legacy_is_little_endian(void) 7 + { 8 + #ifdef __LITTLE_ENDIAN 9 + return true; 10 + #else 11 + return false; 12 + #endif 13 + } 10 14 11 15 static inline u16 __virtio16_to_cpu(bool little_endian, __virtio16 val) 12 16 { 13 17 if (little_endian) 14 18 return le16_to_cpu((__force __le16)val); 15 19 else 16 - return (__force u16)val; 20 + return be16_to_cpu((__force __be16)val); 17 21 } 18 22 19 23 static inline __virtio16 __cpu_to_virtio16(bool little_endian, u16 val) ··· 25 21 if (little_endian) 26 22 return (__force __virtio16)cpu_to_le16(val); 27 23 else 28 - return (__force __virtio16)val; 24 + return (__force __virtio16)cpu_to_be16(val); 29 25 } 30 26 31 27 static inline u32 __virtio32_to_cpu(bool little_endian, __virtio32 val) ··· 33 29 if (little_endian) 34 30 return le32_to_cpu((__force __le32)val); 35 31 else 36 - return (__force u32)val; 32 + return be32_to_cpu((__force __be32)val); 37 33 } 38 34 39 35 static inline __virtio32 __cpu_to_virtio32(bool little_endian, u32 val) ··· 41 37 if (little_endian) 42 38 return (__force __virtio32)cpu_to_le32(val); 43 39 else 44 - return (__force __virtio32)val; 40 + return (__force __virtio32)cpu_to_be32(val); 45 41 } 46 42 47 43 static inline u64 __virtio64_to_cpu(bool little_endian, __virtio64 val) ··· 49 45 if (little_endian) 50 46 return le64_to_cpu((__force __le64)val); 51 47 else 52 - return (__force u64)val; 48 + return be64_to_cpu((__force __be64)val); 53 49 } 54 50 55 51 static inline __virtio64 __cpu_to_virtio64(bool little_endian, u64 val) ··· 57 53 if (little_endian) 58 54 return (__force __virtio64)cpu_to_le64(val); 59 55 else 60 - return (__force __virtio64)val; 56 + return (__force __virtio64)cpu_to_be64(val); 61 57 } 62 58 63 59 #endif /* _LINUX_VIRTIO_BYTEORDER */
+12 -6
include/linux/virtio_config.h
··· 205 205 return 0; 206 206 } 207 207 208 + static inline bool virtio_is_little_endian(struct virtio_device *vdev) 209 + { 210 + return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) || 211 + virtio_legacy_is_little_endian(); 212 + } 213 + 208 214 /* Memory accessors */ 209 215 static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val) 210 216 { 211 - return __virtio16_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); 217 + return __virtio16_to_cpu(virtio_is_little_endian(vdev), val); 212 218 } 213 219 214 220 static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val) 215 221 { 216 - return __cpu_to_virtio16(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); 222 + return __cpu_to_virtio16(virtio_is_little_endian(vdev), val); 217 223 } 218 224 219 225 static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val) 220 226 { 221 - return __virtio32_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); 227 + return __virtio32_to_cpu(virtio_is_little_endian(vdev), val); 222 228 } 223 229 224 230 static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val) 225 231 { 226 - return __cpu_to_virtio32(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); 232 + return __cpu_to_virtio32(virtio_is_little_endian(vdev), val); 227 233 } 228 234 229 235 static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val) 230 236 { 231 - return __virtio64_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); 237 + return __virtio64_to_cpu(virtio_is_little_endian(vdev), val); 232 238 } 233 239 234 240 static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val) 235 241 { 236 - return __cpu_to_virtio64(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); 242 + return __cpu_to_virtio64(virtio_is_little_endian(vdev), val); 237 243 } 238 244 239 245 /* Config space accessors. */
+12 -6
include/linux/vringh.h
··· 226 226 vrh->notify(vrh); 227 227 } 228 228 229 + static inline bool vringh_is_little_endian(const struct vringh *vrh) 230 + { 231 + return vrh->little_endian || 232 + virtio_legacy_is_little_endian(); 233 + } 234 + 229 235 static inline u16 vringh16_to_cpu(const struct vringh *vrh, __virtio16 val) 230 236 { 231 - return __virtio16_to_cpu(vrh->little_endian, val); 237 + return __virtio16_to_cpu(vringh_is_little_endian(vrh), val); 232 238 } 233 239 234 240 static inline __virtio16 cpu_to_vringh16(const struct vringh *vrh, u16 val) 235 241 { 236 - return __cpu_to_virtio16(vrh->little_endian, val); 242 + return __cpu_to_virtio16(vringh_is_little_endian(vrh), val); 237 243 } 238 244 239 245 static inline u32 vringh32_to_cpu(const struct vringh *vrh, __virtio32 val) 240 246 { 241 - return __virtio32_to_cpu(vrh->little_endian, val); 247 + return __virtio32_to_cpu(vringh_is_little_endian(vrh), val); 242 248 } 243 249 244 250 static inline __virtio32 cpu_to_vringh32(const struct vringh *vrh, u32 val) 245 251 { 246 - return __cpu_to_virtio32(vrh->little_endian, val); 252 + return __cpu_to_virtio32(vringh_is_little_endian(vrh), val); 247 253 } 248 254 249 255 static inline u64 vringh64_to_cpu(const struct vringh *vrh, __virtio64 val) 250 256 { 251 - return __virtio64_to_cpu(vrh->little_endian, val); 257 + return __virtio64_to_cpu(vringh_is_little_endian(vrh), val); 252 258 } 253 259 254 260 static inline __virtio64 cpu_to_vringh64(const struct vringh *vrh, u64 val) 255 261 { 256 - return __cpu_to_virtio64(vrh->little_endian, val); 262 + return __cpu_to_virtio64(vringh_is_little_endian(vrh), val); 257 263 } 258 264 #endif /* _LINUX_VRINGH_H */
+6
include/uapi/linux/if_tun.h
··· 50 50 #define TUNGETFILTER _IOR('T', 219, struct sock_fprog) 51 51 #define TUNSETVNETLE _IOW('T', 220, int) 52 52 #define TUNGETVNETLE _IOR('T', 221, int) 53 + /* The TUNSETVNETBE and TUNGETVNETBE ioctls are for cross-endian support on 54 + * little-endian hosts. Not all kernel configurations support them, but all 55 + * configurations that support SET also support GET. 56 + */ 57 + #define TUNSETVNETBE _IOW('T', 222, int) 58 + #define TUNGETVNETBE _IOR('T', 223, int) 53 59 54 60 /* TUNSETIFF ifr flags */ 55 61 #define IFF_TUN 0x0001
+14
include/uapi/linux/vhost.h
··· 103 103 /* Get accessor: reads index, writes value in num */ 104 104 #define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state) 105 105 106 + /* Set the vring byte order in num. Valid values are VHOST_VRING_LITTLE_ENDIAN 107 + * or VHOST_VRING_BIG_ENDIAN (other values return -EINVAL). 108 + * The byte order cannot be changed while the device is active: trying to do so 109 + * returns -EBUSY. 110 + * This is a legacy only API that is simply ignored when VIRTIO_F_VERSION_1 is 111 + * set. 112 + * Not all kernel configurations support this ioctl, but all configurations that 113 + * support SET also support GET. 114 + */ 115 + #define VHOST_VRING_LITTLE_ENDIAN 0 116 + #define VHOST_VRING_BIG_ENDIAN 1 117 + #define VHOST_SET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x13, struct vhost_vring_state) 118 + #define VHOST_GET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x14, struct vhost_vring_state) 119 + 106 120 /* The following ioctls use eventfd file descriptors to signal and poll 107 121 * for events. */ 108 122