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.

vduse: add vq group support

This allows separate the different virtqueues in groups that shares the
same address space. Asking the VDUSE device for the groups of the vq at
the beginning as they're needed for the DMA API.

Allocating 3 vq groups as net is the device that need the most groups:
* Dataplane (guest passthrough)
* CVQ
* Shadowed vrings.

Future versions of the series can include dynamic allocation of the
groups array so VDUSE can declare more groups.

Acked-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Xie Yongji <xieyongji@bytedance.com>
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260119143306.1818855-4-eperezma@redhat.com>

authored by

Eugenio Pérez and committed by
Michael S. Tsirkin
9350a09a a006ed4e

+51 -8
+42 -5
drivers/vdpa/vdpa_user/vduse_dev.c
··· 39 39 #define DRV_LICENSE "GPL v2" 40 40 41 41 #define VDUSE_DEV_MAX (1U << MINORBITS) 42 + #define VDUSE_DEV_MAX_GROUPS 0xffff 42 43 #define VDUSE_MAX_BOUNCE_SIZE (1024 * 1024 * 1024) 43 44 #define VDUSE_MIN_BOUNCE_SIZE (1024 * 1024) 44 45 #define VDUSE_BOUNCE_SIZE (64 * 1024 * 1024) ··· 59 58 struct vdpa_vq_state state; 60 59 bool ready; 61 60 bool kicked; 61 + u32 group; 62 62 spinlock_t kick_lock; 63 63 spinlock_t irq_lock; 64 64 struct eventfd_ctx *kickfd; ··· 116 114 u8 status; 117 115 u32 vq_num; 118 116 u32 vq_align; 117 + u32 ngroups; 119 118 struct vduse_umem *umem; 120 119 struct mutex mem_lock; 121 120 unsigned int bounce_size; ··· 595 592 return 0; 596 593 } 597 594 595 + static u32 vduse_get_vq_group(struct vdpa_device *vdpa, u16 idx) 596 + { 597 + struct vduse_dev *dev = vdpa_to_vduse(vdpa); 598 + 599 + if (dev->api_version < VDUSE_API_VERSION_1) 600 + return 0; 601 + 602 + return dev->vqs[idx]->group; 603 + } 604 + 598 605 static int vduse_vdpa_get_vq_state(struct vdpa_device *vdpa, u16 idx, 599 606 struct vdpa_vq_state *state) 600 607 { ··· 802 789 .set_vq_cb = vduse_vdpa_set_vq_cb, 803 790 .set_vq_num = vduse_vdpa_set_vq_num, 804 791 .get_vq_size = vduse_vdpa_get_vq_size, 792 + .get_vq_group = vduse_get_vq_group, 805 793 .set_vq_ready = vduse_vdpa_set_vq_ready, 806 794 .get_vq_ready = vduse_vdpa_get_vq_ready, 807 795 .set_vq_state = vduse_vdpa_set_vq_state, ··· 1266 1252 if (config.index >= dev->vq_num) 1267 1253 break; 1268 1254 1269 - if (!is_mem_zero((const char *)config.reserved, 1270 - sizeof(config.reserved))) 1255 + if (dev->api_version < VDUSE_API_VERSION_1) { 1256 + if (config.group) 1257 + break; 1258 + } else { 1259 + if (config.group >= dev->ngroups) 1260 + break; 1261 + if (dev->status & VIRTIO_CONFIG_S_DRIVER_OK) 1262 + break; 1263 + } 1264 + 1265 + if (config.reserved1 || 1266 + !is_mem_zero((const char *)config.reserved2, 1267 + sizeof(config.reserved2))) 1271 1268 break; 1272 1269 1273 1270 index = array_index_nospec(config.index, dev->vq_num); 1274 1271 dev->vqs[index]->num_max = config.max_size; 1272 + dev->vqs[index]->group = config.group; 1275 1273 ret = 0; 1276 1274 break; 1277 1275 } ··· 1763 1737 return true; 1764 1738 } 1765 1739 1766 - static bool vduse_validate_config(struct vduse_dev_config *config) 1740 + static bool vduse_validate_config(struct vduse_dev_config *config, 1741 + u64 api_version) 1767 1742 { 1768 1743 if (!is_mem_zero((const char *)config->reserved, 1769 1744 sizeof(config->reserved))) 1745 + return false; 1746 + 1747 + if (api_version < VDUSE_API_VERSION_1 && config->ngroups) 1748 + return false; 1749 + 1750 + if (api_version >= VDUSE_API_VERSION_1 && 1751 + (!config->ngroups || config->ngroups > VDUSE_DEV_MAX_GROUPS)) 1770 1752 return false; 1771 1753 1772 1754 if (config->vq_align > PAGE_SIZE) ··· 1892 1858 dev->device_features = config->features; 1893 1859 dev->device_id = config->device_id; 1894 1860 dev->vendor_id = config->vendor_id; 1861 + dev->ngroups = (dev->api_version < VDUSE_API_VERSION_1) 1862 + ? 1 1863 + : config->ngroups; 1895 1864 dev->name = kstrdup(config->name, GFP_KERNEL); 1896 1865 if (!dev->name) 1897 1866 goto err_str; ··· 1973 1936 break; 1974 1937 1975 1938 ret = -EINVAL; 1976 - if (vduse_validate_config(&config) == false) 1939 + if (!vduse_validate_config(&config, control->api_version)) 1977 1940 break; 1978 1941 1979 1942 buf = vmemdup_user(argp + size, config.config_size); ··· 2054 2017 2055 2018 vdev = vdpa_alloc_device(struct vduse_vdpa, vdpa, dev->dev, 2056 2019 &vduse_vdpa_config_ops, &vduse_map_ops, 2057 - 1, 1, name, true); 2020 + dev->ngroups, 1, name, true); 2058 2021 if (IS_ERR(vdev)) 2059 2022 return PTR_ERR(vdev); 2060 2023
+9 -3
include/uapi/linux/vduse.h
··· 31 31 * @features: virtio features 32 32 * @vq_num: the number of virtqueues 33 33 * @vq_align: the allocation alignment of virtqueue's metadata 34 + * @ngroups: number of vq groups that VDUSE device declares 34 35 * @reserved: for future use, needs to be initialized to zero 35 36 * @config_size: the size of the configuration space 36 37 * @config: the buffer of the configuration space ··· 46 45 __u64 features; 47 46 __u32 vq_num; 48 47 __u32 vq_align; 49 - __u32 reserved[13]; 48 + __u32 ngroups; /* if VDUSE_API_VERSION >= 1 */ 49 + __u32 reserved[12]; 50 50 __u32 config_size; 51 51 __u8 config[]; 52 52 }; ··· 124 122 * struct vduse_vq_config - basic configuration of a virtqueue 125 123 * @index: virtqueue index 126 124 * @max_size: the max size of virtqueue 127 - * @reserved: for future use, needs to be initialized to zero 125 + * @reserved1: for future use, needs to be initialized to zero 126 + * @group: virtqueue group 127 + * @reserved2: for future use, needs to be initialized to zero 128 128 * 129 129 * Structure used by VDUSE_VQ_SETUP ioctl to setup a virtqueue. 130 130 */ 131 131 struct vduse_vq_config { 132 132 __u32 index; 133 133 __u16 max_size; 134 - __u16 reserved[13]; 134 + __u16 reserved1; 135 + __u32 group; 136 + __u16 reserved2[10]; 135 137 }; 136 138 137 139 /*