vduse: add vq group asid support

Add support for assigning Address Space Identifiers (ASIDs) to each VQ
group.  This enables mapping each group into a distinct memory space.

The vq group to ASID association is protected by a rwlock now.  But the
mutex domain_lock keeps protecting the domains of all ASIDs, as some
operations like the one related with the bounce buffer size still
requires to lock all the ASIDs.

Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260119143306.1818855-12-eperezma@redhat.com>
This commit is contained in:
Eugenio Pérez
2026-01-28 15:32:18 -05:00
committed by Michael S. Tsirkin
parent f3dc3a8a3e
commit 079212f687
2 changed files with 315 additions and 136 deletions
File diff suppressed because it is too large Load Diff
+63 -3
View File
@@ -32,6 +32,7 @@
* @vq_num: the number of virtqueues
* @vq_align: the allocation alignment of virtqueue's metadata
* @ngroups: number of vq groups that VDUSE device declares
* @nas: number of address spaces that VDUSE device declares
* @reserved: for future use, needs to be initialized to zero
* @config_size: the size of the configuration space
* @config: the buffer of the configuration space
@@ -47,7 +48,8 @@ struct vduse_dev_config {
__u32 vq_num;
__u32 vq_align;
__u32 ngroups; /* if VDUSE_API_VERSION >= 1 */
__u32 reserved[12];
__u32 nas; /* if VDUSE_API_VERSION >= 1 */
__u32 reserved[11];
__u32 config_size;
__u8 config[];
};
@@ -166,6 +168,16 @@ struct vduse_vq_state_packed {
__u16 last_used_idx;
};
/**
* struct vduse_vq_group_asid - virtqueue group ASID
* @group: Index of the virtqueue group
* @asid: Address space ID of the group
*/
struct vduse_vq_group_asid {
__u32 group;
__u32 asid;
};
/**
* struct vduse_vq_info - information of a virtqueue
* @index: virtqueue index
@@ -225,6 +237,7 @@ struct vduse_vq_eventfd {
* @uaddr: start address of userspace memory, it must be aligned to page size
* @iova: start of the IOVA region
* @size: size of the IOVA region
* @asid: Address space ID of the IOVA region
* @reserved: for future use, needs to be initialized to zero
*
* Structure used by VDUSE_IOTLB_REG_UMEM and VDUSE_IOTLB_DEREG_UMEM
@@ -234,7 +247,8 @@ struct vduse_iova_umem {
__u64 uaddr;
__u64 iova;
__u64 size;
__u64 reserved[3];
__u32 asid;
__u32 reserved[5];
};
/* Register userspace memory for IOVA regions */
@@ -248,6 +262,7 @@ struct vduse_iova_umem {
* @start: start of the IOVA region
* @last: last of the IOVA region
* @capability: capability of the IOVA region
* @asid: Address space ID of the IOVA region, only if device API version >= 1
* @reserved: for future use, needs to be initialized to zero
*
* Structure used by VDUSE_IOTLB_GET_INFO ioctl to get information of
@@ -258,7 +273,8 @@ struct vduse_iova_info {
__u64 last;
#define VDUSE_IOVA_CAP_UMEM (1 << 0)
__u64 capability;
__u64 reserved[3];
__u32 asid; /* Only if device API version >= 1 */
__u32 reserved[5];
};
/*
@@ -267,6 +283,28 @@ struct vduse_iova_info {
*/
#define VDUSE_IOTLB_GET_INFO _IOWR(VDUSE_BASE, 0x1a, struct vduse_iova_info)
/**
* struct vduse_iotlb_entry_v2 - entry of IOTLB to describe one IOVA region
*
* @v1: the original vduse_iotlb_entry
* @asid: address space ID of the IOVA region
* @reserved: for future use, needs to be initialized to zero
*
* Structure used by VDUSE_IOTLB_GET_FD2 ioctl to find an overlapped IOVA region.
*/
struct vduse_iotlb_entry_v2 {
struct vduse_iotlb_entry v1;
__u32 asid;
__u32 reserved[12];
};
/*
* Same as VDUSE_IOTLB_GET_FD but with vduse_iotlb_entry_v2 argument that
* support extra fields.
*/
#define VDUSE_IOTLB_GET_FD2 _IOWR(VDUSE_BASE, 0x1b, struct vduse_iotlb_entry_v2)
/* The control messages definition for read(2)/write(2) on /dev/vduse/$NAME */
/**
@@ -275,11 +313,14 @@ struct vduse_iova_info {
* @VDUSE_SET_STATUS: set the device status
* @VDUSE_UPDATE_IOTLB: Notify userspace to update the memory mapping for
* specified IOVA range via VDUSE_IOTLB_GET_FD ioctl
* @VDUSE_SET_VQ_GROUP_ASID: Notify userspace to update the address space of a
* virtqueue group.
*/
enum vduse_req_type {
VDUSE_GET_VQ_STATE,
VDUSE_SET_STATUS,
VDUSE_UPDATE_IOTLB,
VDUSE_SET_VQ_GROUP_ASID,
};
/**
@@ -314,6 +355,18 @@ struct vduse_iova_range {
__u64 last;
};
/**
* struct vduse_iova_range_v2 - IOVA range [start, last] if API_VERSION >= 1
* @start: start of the IOVA range
* @last: last of the IOVA range
* @asid: address space ID of the IOVA range
*/
struct vduse_iova_range_v2 {
__u64 start;
__u64 last;
__u32 asid;
};
/**
* struct vduse_dev_request - control request
* @type: request type
@@ -322,6 +375,8 @@ struct vduse_iova_range {
* @vq_state: virtqueue state, only index field is available
* @s: device status
* @iova: IOVA range for updating
* @iova_v2: IOVA range for updating if API_VERSION >= 1
* @vq_group_asid: ASID of a virtqueue group
* @padding: padding
*
* Structure used by read(2) on /dev/vduse/$NAME.
@@ -334,6 +389,11 @@ struct vduse_dev_request {
struct vduse_vq_state vq_state;
struct vduse_dev_status s;
struct vduse_iova_range iova;
/* Following members but padding exist only if vduse api
* version >= 1
*/
struct vduse_iova_range_v2 iova_v2;
struct vduse_vq_group_asid vq_group_asid;
__u32 padding[32];
};
};