@@ -69,12 +69,12 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"
6969
7070#define VHOST_DMA_IS_DONE (len ) ((__force u32)(len) >= (__force u32)VHOST_DMA_DONE_LEN)
7171
72- enum {
73- VHOST_NET_FEATURES = VHOST_FEATURES |
74- (1ULL << VHOST_NET_F_VIRTIO_NET_HDR ) |
75- (1ULL << VIRTIO_NET_F_MRG_RXBUF ) |
76- (1ULL << VIRTIO_F_ACCESS_PLATFORM ) |
77- (1ULL << VIRTIO_F_RING_RESET )
72+ static const u64 vhost_net_features [ VIRTIO_FEATURES_DWORDS ] = {
73+ VHOST_FEATURES |
74+ (1ULL << VHOST_NET_F_VIRTIO_NET_HDR ) |
75+ (1ULL << VIRTIO_NET_F_MRG_RXBUF ) |
76+ (1ULL << VIRTIO_F_ACCESS_PLATFORM ) |
77+ (1ULL << VIRTIO_F_RING_RESET ),
7878};
7979
8080enum {
@@ -1614,16 +1614,17 @@ static long vhost_net_reset_owner(struct vhost_net *n)
16141614 return err ;
16151615}
16161616
1617- static int vhost_net_set_features (struct vhost_net * n , u64 features )
1617+ static int vhost_net_set_features (struct vhost_net * n , const u64 * features )
16181618{
16191619 size_t vhost_hlen , sock_hlen , hdr_len ;
16201620 int i ;
16211621
1622- hdr_len = (features & ((1ULL << VIRTIO_NET_F_MRG_RXBUF ) |
1623- (1ULL << VIRTIO_F_VERSION_1 ))) ?
1624- sizeof (struct virtio_net_hdr_mrg_rxbuf ) :
1625- sizeof (struct virtio_net_hdr );
1626- if (features & (1 << VHOST_NET_F_VIRTIO_NET_HDR )) {
1622+ hdr_len = virtio_features_test_bit (features , VIRTIO_NET_F_MRG_RXBUF ) ||
1623+ virtio_features_test_bit (features , VIRTIO_F_VERSION_1 ) ?
1624+ sizeof (struct virtio_net_hdr_mrg_rxbuf ) :
1625+ sizeof (struct virtio_net_hdr );
1626+
1627+ if (virtio_features_test_bit (features , VHOST_NET_F_VIRTIO_NET_HDR )) {
16271628 /* vhost provides vnet_hdr */
16281629 vhost_hlen = hdr_len ;
16291630 sock_hlen = 0 ;
@@ -1633,18 +1634,19 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features)
16331634 sock_hlen = hdr_len ;
16341635 }
16351636 mutex_lock (& n -> dev .mutex );
1636- if ((features & ( 1 << VHOST_F_LOG_ALL ) ) &&
1637+ if (virtio_features_test_bit (features , VHOST_F_LOG_ALL ) &&
16371638 !vhost_log_access_ok (& n -> dev ))
16381639 goto out_unlock ;
16391640
1640- if ((features & ( 1ULL << VIRTIO_F_ACCESS_PLATFORM ) )) {
1641+ if (virtio_features_test_bit (features , VIRTIO_F_ACCESS_PLATFORM )) {
16411642 if (vhost_init_device_iotlb (& n -> dev ))
16421643 goto out_unlock ;
16431644 }
16441645
16451646 for (i = 0 ; i < VHOST_NET_VQ_MAX ; ++ i ) {
16461647 mutex_lock (& n -> vqs [i ].vq .mutex );
1647- n -> vqs [i ].vq .acked_features = features ;
1648+ virtio_features_copy (n -> vqs [i ].vq .acked_features_array ,
1649+ features );
16481650 n -> vqs [i ].vhost_hlen = vhost_hlen ;
16491651 n -> vqs [i ].sock_hlen = sock_hlen ;
16501652 mutex_unlock (& n -> vqs [i ].vq .mutex );
@@ -1681,29 +1683,74 @@ static long vhost_net_set_owner(struct vhost_net *n)
16811683static long vhost_net_ioctl (struct file * f , unsigned int ioctl ,
16821684 unsigned long arg )
16831685{
1686+ u64 all_features [VIRTIO_FEATURES_DWORDS ];
16841687 struct vhost_net * n = f -> private_data ;
16851688 void __user * argp = (void __user * )arg ;
16861689 u64 __user * featurep = argp ;
16871690 struct vhost_vring_file backend ;
1688- u64 features ;
1689- int r ;
1691+ u64 features , count , copied ;
1692+ int r , i ;
16901693
16911694 switch (ioctl ) {
16921695 case VHOST_NET_SET_BACKEND :
16931696 if (copy_from_user (& backend , argp , sizeof backend ))
16941697 return - EFAULT ;
16951698 return vhost_net_set_backend (n , backend .index , backend .fd );
16961699 case VHOST_GET_FEATURES :
1697- features = VHOST_NET_FEATURES ;
1700+ features = vhost_net_features [ 0 ] ;
16981701 if (copy_to_user (featurep , & features , sizeof features ))
16991702 return - EFAULT ;
17001703 return 0 ;
17011704 case VHOST_SET_FEATURES :
17021705 if (copy_from_user (& features , featurep , sizeof features ))
17031706 return - EFAULT ;
1704- if (features & ~VHOST_NET_FEATURES )
1707+ if (features & ~vhost_net_features [ 0 ] )
17051708 return - EOPNOTSUPP ;
1706- return vhost_net_set_features (n , features );
1709+
1710+ virtio_features_from_u64 (all_features , features );
1711+ return vhost_net_set_features (n , all_features );
1712+ case VHOST_GET_FEATURES_ARRAY :
1713+ if (copy_from_user (& count , featurep , sizeof (count )))
1714+ return - EFAULT ;
1715+
1716+ /* Copy the net features, up to the user-provided buffer size */
1717+ argp += sizeof (u64 );
1718+ copied = min (count , VIRTIO_FEATURES_DWORDS );
1719+ if (copy_to_user (argp , vhost_net_features ,
1720+ copied * sizeof (u64 )))
1721+ return - EFAULT ;
1722+
1723+ /* Zero the trailing space provided by user-space, if any */
1724+ if (clear_user (argp , size_mul (count - copied , sizeof (u64 ))))
1725+ return - EFAULT ;
1726+ return 0 ;
1727+ case VHOST_SET_FEATURES_ARRAY :
1728+ if (copy_from_user (& count , featurep , sizeof (count )))
1729+ return - EFAULT ;
1730+
1731+ virtio_features_zero (all_features );
1732+ argp += sizeof (u64 );
1733+ copied = min (count , VIRTIO_FEATURES_DWORDS );
1734+ if (copy_from_user (all_features , argp , copied * sizeof (u64 )))
1735+ return - EFAULT ;
1736+
1737+ /*
1738+ * Any feature specified by user-space above
1739+ * VIRTIO_FEATURES_MAX is not supported by definition.
1740+ */
1741+ for (i = copied ; i < count ; ++ i ) {
1742+ if (copy_from_user (& features , featurep + 1 + i ,
1743+ sizeof (features )))
1744+ return - EFAULT ;
1745+ if (features )
1746+ return - EOPNOTSUPP ;
1747+ }
1748+
1749+ for (i = 0 ; i < VIRTIO_FEATURES_DWORDS ; i ++ )
1750+ if (all_features [i ] & ~vhost_net_features [i ])
1751+ return - EOPNOTSUPP ;
1752+
1753+ return vhost_net_set_features (n , all_features );
17071754 case VHOST_GET_BACKEND_FEATURES :
17081755 features = VHOST_NET_BACKEND_FEATURES ;
17091756 if (copy_to_user (featurep , & features , sizeof (features )))
0 commit comments