From nobody Wed Sep 24 15:20:54 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 696532BEFE3 for ; Fri, 19 Sep 2025 09:34:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274459; cv=none; b=h/aSlq9ulV6sedicVhGASDh5K+FzS7yReMqa0CH/RmTCvW2WScEmnjfWnldPKeLzoX3HPDhrHArGLtm24Q4MsYcJqcSDnQjMVQMZrEk9VWotkIVJTQCqAHErtx7MZm3lSeXxtYIe08Guz9sZEZKgybvPrIyEGte5MTeLvx5lyaE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274459; c=relaxed/simple; bh=9PYuUF/DYNZD3i4NXd60/aqNFPJGSMuk3TXdcJ3Krww=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ob9qLkth95Lx8Gxaz/kUEUulJEV5+5p6np4MkXEY2N5MxIx9Mf31+kRuoMjna3FAGB0dHFjUDDElX0uSuxl3ctWitxROEhcvFUEEINNdVgJi1j7XEqiTzcTOjD3FYE1lFVrXCqJeix3cFJjyR29a8VHR/w9RCYBaQjvJv55Wpps= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=VfK5sDnO; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="VfK5sDnO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758274456; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=S/QNNhx0VTtnBtXTR4YMB03fF9qZTx0+PBNjpo35Ye4=; b=VfK5sDnO3ZcNEiA6+yNK96eYZcr2QuyuHiFAogC9M8QOE42WeGcBCxyocMXg8EkOVj7Eu4 rH6hKODTK5HnrAg9SRBS346aZUlEESf1NQqVFSOY5CjEJuV2eU6ZPDWR51vWYK0P4lIs5q OcIWdQZQfcWyjPDsFpL7fw1x+Qt+7Ic= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-450-nkLd7JISO8iHG6rCodzx_Q-1; Fri, 19 Sep 2025 05:34:13 -0400 X-MC-Unique: nkLd7JISO8iHG6rCodzx_Q-1 X-Mimecast-MFC-AGG-ID: nkLd7JISO8iHG6rCodzx_Q_1758274452 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 184FD1800371; Fri, 19 Sep 2025 09:34:12 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 120391800447; Fri, 19 Sep 2025 09:34:05 +0000 (UTC) From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= To: "Michael S . Tsirkin " Cc: =?UTF-8?q?Eugenio=20P=C3=A9rez?= , Yongji Xie , Maxime Coquelin , linux-kernel@vger.kernel.org, Xuan Zhuo , virtualization@lists.linux.dev, Cindy Lu , jasowang@redhat.com, Laurent Vivier , Stefano Garzarella Subject: [PATCH v3 1/6] vduse: make domain_lock an rwlock Date: Fri, 19 Sep 2025 11:33:54 +0200 Message-ID: <20250919093359.961296-2-eperezma@redhat.com> In-Reply-To: <20250919093359.961296-1-eperezma@redhat.com> References: <20250919093359.961296-1-eperezma@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 It will be used in a few more scenarios read-only so make it more scalable. Suggested-by: Xie Yongji Acked-by: Jason Wang Reviewed-by: Xie Yongji Signed-off-by: Eugenio P=C3=A9rez --- v2: New in v2 --- drivers/vdpa/vdpa_user/vduse_dev.c | 41 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vd= use_dev.c index e7bced0b5542..2b6a8958ffe0 100644 --- a/drivers/vdpa/vdpa_user/vduse_dev.c +++ b/drivers/vdpa/vdpa_user/vduse_dev.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -117,7 +118,7 @@ struct vduse_dev { struct vduse_umem *umem; struct mutex mem_lock; unsigned int bounce_size; - struct mutex domain_lock; + rwlock_t domain_lock; }; =20 struct vduse_dev_msg { @@ -1176,9 +1177,9 @@ static long vduse_dev_ioctl(struct file *file, unsign= ed int cmd, if (entry.start > entry.last) break; =20 - mutex_lock(&dev->domain_lock); + read_lock(&dev->domain_lock); if (!dev->domain) { - mutex_unlock(&dev->domain_lock); + read_unlock(&dev->domain_lock); break; } spin_lock(&dev->domain->iotlb_lock); @@ -1193,7 +1194,7 @@ static long vduse_dev_ioctl(struct file *file, unsign= ed int cmd, entry.perm =3D map->perm; } spin_unlock(&dev->domain->iotlb_lock); - mutex_unlock(&dev->domain_lock); + read_unlock(&dev->domain_lock); ret =3D -EINVAL; if (!f) break; @@ -1346,10 +1347,10 @@ static long vduse_dev_ioctl(struct file *file, unsi= gned int cmd, sizeof(umem.reserved))) break; =20 - mutex_lock(&dev->domain_lock); + write_lock(&dev->domain_lock); ret =3D vduse_dev_reg_umem(dev, umem.iova, umem.uaddr, umem.size); - mutex_unlock(&dev->domain_lock); + write_unlock(&dev->domain_lock); break; } case VDUSE_IOTLB_DEREG_UMEM: { @@ -1363,10 +1364,10 @@ static long vduse_dev_ioctl(struct file *file, unsi= gned int cmd, if (!is_mem_zero((const char *)umem.reserved, sizeof(umem.reserved))) break; - mutex_lock(&dev->domain_lock); + write_lock(&dev->domain_lock); ret =3D vduse_dev_dereg_umem(dev, umem.iova, umem.size); - mutex_unlock(&dev->domain_lock); + write_unlock(&dev->domain_lock); break; } case VDUSE_IOTLB_GET_INFO: { @@ -1385,9 +1386,9 @@ static long vduse_dev_ioctl(struct file *file, unsign= ed int cmd, sizeof(info.reserved))) break; =20 - mutex_lock(&dev->domain_lock); + read_lock(&dev->domain_lock); if (!dev->domain) { - mutex_unlock(&dev->domain_lock); + read_unlock(&dev->domain_lock); break; } spin_lock(&dev->domain->iotlb_lock); @@ -1402,7 +1403,7 @@ static long vduse_dev_ioctl(struct file *file, unsign= ed int cmd, info.capability |=3D VDUSE_IOVA_CAP_UMEM; } spin_unlock(&dev->domain->iotlb_lock); - mutex_unlock(&dev->domain_lock); + read_unlock(&dev->domain_lock); if (!map) break; =20 @@ -1425,10 +1426,10 @@ static int vduse_dev_release(struct inode *inode, s= truct file *file) { struct vduse_dev *dev =3D file->private_data; =20 - mutex_lock(&dev->domain_lock); + write_lock(&dev->domain_lock); if (dev->domain) vduse_dev_dereg_umem(dev, 0, dev->domain->bounce_size); - mutex_unlock(&dev->domain_lock); + write_unlock(&dev->domain_lock); spin_lock(&dev->msg_lock); /* Make sure the inflight messages can processed after reconncection */ list_splice_init(&dev->recv_list, &dev->send_list); @@ -1647,7 +1648,7 @@ static struct vduse_dev *vduse_dev_create(void) =20 mutex_init(&dev->lock); mutex_init(&dev->mem_lock); - mutex_init(&dev->domain_lock); + rwlock_init(&dev->domain_lock); spin_lock_init(&dev->msg_lock); INIT_LIST_HEAD(&dev->send_list); INIT_LIST_HEAD(&dev->recv_list); @@ -1805,7 +1806,7 @@ static ssize_t bounce_size_store(struct device *devic= e, int ret; =20 ret =3D -EPERM; - mutex_lock(&dev->domain_lock); + write_lock(&dev->domain_lock); if (dev->domain) goto unlock; =20 @@ -1821,7 +1822,7 @@ static ssize_t bounce_size_store(struct device *devic= e, dev->bounce_size =3D bounce_size & PAGE_MASK; ret =3D count; unlock: - mutex_unlock(&dev->domain_lock); + write_unlock(&dev->domain_lock); return ret; } =20 @@ -2045,11 +2046,11 @@ static int vdpa_dev_add(struct vdpa_mgmt_dev *mdev,= const char *name, if (ret) return ret; =20 - mutex_lock(&dev->domain_lock); + write_lock(&dev->domain_lock); if (!dev->domain) dev->domain =3D vduse_domain_create(VDUSE_IOVA_SIZE - 1, dev->bounce_size); - mutex_unlock(&dev->domain_lock); + write_unlock(&dev->domain_lock); if (!dev->domain) { put_device(&dev->vdev->vdpa.dev); return -ENOMEM; @@ -2059,10 +2060,10 @@ static int vdpa_dev_add(struct vdpa_mgmt_dev *mdev,= const char *name, ret =3D _vdpa_register_device(&dev->vdev->vdpa, dev->vq_num); if (ret) { put_device(&dev->vdev->vdpa.dev); - mutex_lock(&dev->domain_lock); + write_lock(&dev->domain_lock); vduse_domain_destroy(dev->domain); dev->domain =3D NULL; - mutex_unlock(&dev->domain_lock); + write_unlock(&dev->domain_lock); return ret; } =20 --=20 2.51.0 From nobody Wed Sep 24 15:20:54 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A28EC2F3C2B for ; Fri, 19 Sep 2025 09:34:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274464; cv=none; b=UrCEEq1I2H86sa/QDpn8Mjy8Xowb2Sihck2Jhby2v3nNPX4SC4b5rN3FyIUDt6lAIDgi5r7qnol0ZeyZKMPcr8G6c6RnJWosjOefsjBg4EIL4apgMlEJFyrfXRexBriA0OFLvo2E7ZKTt9V9qZEsZUrIw4BtROi81aClry9bCD4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274464; c=relaxed/simple; bh=pbBzLjrUvy4Jws3IrdIk6Q8D7H91HuRG6YGPY55CtrI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Zz12nyVtLmU07oOgpfTeJqdL+G4NDH4arlBG9Z1lWbk38NAP+BV5SpAAPT+bAnm6WGANjmdRCxu4v69tnQtW6oovsAL//mzRw7NFqdOWRj7LmMPww9IXyElLnuMp6ZPoRBZ5Xx69zBlnIlcLn3t7wTVXpBSxomHyXr2Pdwi888g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=UwnhPh2m; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="UwnhPh2m" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758274461; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6Dg27mnkpxY6+wpImWrHzQoz+UEHN7ql4f1eRWWfzQk=; b=UwnhPh2mdN8+ADGTgYSXZZjLah0eS2usEyWNT+6Pv4fsPWIVw/BnTnblXozwGob2WS8NP2 BAMplKK+7h6YofFSLoJI/87SC3liNOPbdwCBrgAD+5dnguASsBn4h6NpA2PDDhtPQkH6HB cCngKNE32kyY59JUs6xbBtDjI2bR9dk= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-2-8KnZ_OZvMDqR9sEoVoYRpQ-1; Fri, 19 Sep 2025 05:34:18 -0400 X-MC-Unique: 8KnZ_OZvMDqR9sEoVoYRpQ-1 X-Mimecast-MFC-AGG-ID: 8KnZ_OZvMDqR9sEoVoYRpQ_1758274457 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EFF2219560B4; Fri, 19 Sep 2025 09:34:16 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9F05918004A3; Fri, 19 Sep 2025 09:34:12 +0000 (UTC) From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= To: "Michael S . Tsirkin " Cc: =?UTF-8?q?Eugenio=20P=C3=A9rez?= , Yongji Xie , Maxime Coquelin , linux-kernel@vger.kernel.org, Xuan Zhuo , virtualization@lists.linux.dev, Cindy Lu , jasowang@redhat.com, Laurent Vivier , Stefano Garzarella Subject: [PATCH v3 2/6] vduse: add v1 API definition Date: Fri, 19 Sep 2025 11:33:55 +0200 Message-ID: <20250919093359.961296-3-eperezma@redhat.com> In-Reply-To: <20250919093359.961296-1-eperezma@redhat.com> References: <20250919093359.961296-1-eperezma@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 This allows the kernel to detect whether the userspace VDUSE device supports the VQ group and ASID features. VDUSE devices that don't set the V1 API will not receive the new messages, and vdpa device will be created with only one vq group and asid. The next patches implement the new feature incrementally, only enabling the VDUSE device to set the V1 API version by the end of the series. Signed-off-by: Eugenio P=C3=A9rez --- include/uapi/linux/vduse.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/uapi/linux/vduse.h b/include/uapi/linux/vduse.h index 10ad71aa00d6..ccb92a1efce0 100644 --- a/include/uapi/linux/vduse.h +++ b/include/uapi/linux/vduse.h @@ -10,6 +10,10 @@ =20 #define VDUSE_API_VERSION 0 =20 +/* VQ groups and ASID support */ + +#define VDUSE_API_VERSION_1 1 + /* * Get the version of VDUSE API that kernel supported (VDUSE_API_VERSION). * This is used for future extension. --=20 2.51.0 From nobody Wed Sep 24 15:20:54 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 85380306B1E for ; Fri, 19 Sep 2025 09:34:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274468; cv=none; b=L5O/gE0pIFPHiDSwq1oXjGgBbDuf10fZqvecwpBktqLQ/DlJuOtAYPdXCy5V3KhvP9CLIxEGYp9mABFLn1Y68y4nlV/jxXXEJ0hqrQG+5O3v4bsSm0+QIEyWdEViB72BWKK6wBZ2E6Iv/FayjtTA6t0flWOfLLHADlsjaTFdkfU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274468; c=relaxed/simple; bh=k/3+6JVrPWh07iZLjgM5A8ukiUPo5SQojJ3B04q5YRc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ousxrfu7wzCBIqBek3q/KXlv2yfleZt9Swwkv8ehbHubNRXmxJ2xTumAZzM7vwuFOE9ic8+hWHwf+sCEWSzEvO4yaWeX2Uvunhm4XVGeRNsOCYoFHbxfJciDTb45aLoBdZg+2HBwZ5bTxNRKnvbV++9QulpD5IDfeJLXmiCNNXY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=B94Syhfb; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="B94Syhfb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758274465; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wkzzjSg/UFdQEsIBAFwFFMlTrWks0AFtzULNTjenjIE=; b=B94Syhfbm/osOFW8iTtTCE5kd/VLcX5Rn5DAtplB1PHS6FFjDQWcGeDU6c53pyP+fcVslP HkWzKiPYDn088jSUa2j66vGeHjFwL25yc0G1rOhsQSJAQ5Hei7GPs6Y9jA7qTCquMSzDhE h1pdvQydIFnCMhBeObfgJlwzyXd3HCc= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-158-n4ezJPYcPDOKIulXfpZQzQ-1; Fri, 19 Sep 2025 05:34:23 -0400 X-MC-Unique: n4ezJPYcPDOKIulXfpZQzQ-1 X-Mimecast-MFC-AGG-ID: n4ezJPYcPDOKIulXfpZQzQ_1758274462 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 14EBA1800452; Fri, 19 Sep 2025 09:34:22 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A783618004A3; Fri, 19 Sep 2025 09:34:17 +0000 (UTC) From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= To: "Michael S . Tsirkin " Cc: =?UTF-8?q?Eugenio=20P=C3=A9rez?= , Yongji Xie , Maxime Coquelin , linux-kernel@vger.kernel.org, Xuan Zhuo , virtualization@lists.linux.dev, Cindy Lu , jasowang@redhat.com, Laurent Vivier , Stefano Garzarella Subject: [PATCH v3 3/6] vduse: add vq group support Date: Fri, 19 Sep 2025 11:33:56 +0200 Message-ID: <20250919093359.961296-4-eperezma@redhat.com> In-Reply-To: <20250919093359.961296-1-eperezma@redhat.com> References: <20250919093359.961296-1-eperezma@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 This allows sepparate 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. Signed-off-by: Eugenio P=C3=A9rez --- v3: * Make the default group an invalid group as long as VDUSE device does not set it to some valid u32 value. Modify the vdpa core to take that into account (Jason). * Create the VDUSE_DEV_MAX_GROUPS instead of using a magic number v2: * Now the vq group is in vduse_vq_config struct instead of issuing one VDUSE message per vq. v1: * Fix: Remove BIT_ULL(VIRTIO_S_*), as _S_ is already the bit (Maxime) RFC v3: * Increase VDUSE_MAX_VQ_GROUPS to 0xffff (Jason). It was set to a lower value to reduce memory consumption, but vqs are already limited to that value and userspace VDUSE is able to allocate that many vqs. * Remove the descs vq group capability as it will not be used and we can add it on top. * Do not ask for vq groups in number of vq groups < 2. * Move the valid vq groups range check to vduse_validate_config. RFC v2: * Cache group information in kernel, as we need to provide the vq map tokens properly. * Add descs vq group to optimize SVQ forwarding and support indirect descriptors out of the box. --- drivers/vdpa/ifcvf/ifcvf_main.c | 2 +- drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +- drivers/vdpa/vdpa_sim/vdpa_sim.c | 2 +- drivers/vdpa/vdpa_user/vduse_dev.c | 51 +++++++++++++++++++++++++++--- drivers/vhost/vdpa.c | 11 +++++-- include/linux/vdpa.h | 5 +-- include/uapi/linux/vduse.h | 12 +++++-- 7 files changed, 69 insertions(+), 16 deletions(-) diff --git a/drivers/vdpa/ifcvf/ifcvf_main.c b/drivers/vdpa/ifcvf/ifcvf_mai= n.c index 6658dc74d915..ea6643760fb7 100644 --- a/drivers/vdpa/ifcvf/ifcvf_main.c +++ b/drivers/vdpa/ifcvf/ifcvf_main.c @@ -559,7 +559,7 @@ static size_t ifcvf_vdpa_get_config_size(struct vdpa_de= vice *vdpa_dev) return vf->config_size; } =20 -static u32 ifcvf_vdpa_get_vq_group(struct vdpa_device *vdpa, u16 idx) +static s64 ifcvf_vdpa_get_vq_group(struct vdpa_device *vdpa, u16 idx) { return 0; } diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5= _vnet.c index 82034efb74fc..daab0ccb78b2 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -2640,7 +2640,7 @@ static u32 mlx5_vdpa_get_vq_align(struct vdpa_device = *vdev) return PAGE_SIZE; } =20 -static u32 mlx5_vdpa_get_vq_group(struct vdpa_device *vdev, u16 idx) +static s64 mlx5_vdpa_get_vq_group(struct vdpa_device *vdev, u16 idx) { struct mlx5_vdpa_dev *mvdev =3D to_mvdev(vdev); =20 diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_= sim.c index c1c6431950e1..fe4d65aaf6aa 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c @@ -412,7 +412,7 @@ static u32 vdpasim_get_vq_align(struct vdpa_device *vdp= a) return VDPASIM_QUEUE_ALIGN; } =20 -static u32 vdpasim_get_vq_group(struct vdpa_device *vdpa, u16 idx) +static s64 vdpasim_get_vq_group(struct vdpa_device *vdpa, u16 idx) { /* RX and TX belongs to group 0, CVQ belongs to group 1 */ if (idx =3D=3D 2) diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vd= use_dev.c index 2b6a8958ffe0..7ddd81456f7b 100644 --- a/drivers/vdpa/vdpa_user/vduse_dev.c +++ b/drivers/vdpa/vdpa_user/vduse_dev.c @@ -40,6 +40,7 @@ #define DRV_LICENSE "GPL v2" =20 #define VDUSE_DEV_MAX (1U << MINORBITS) +#define VDUSE_DEV_MAX_GROUPS 0xffff #define VDUSE_MAX_BOUNCE_SIZE (1024 * 1024 * 1024) #define VDUSE_MIN_BOUNCE_SIZE (1024 * 1024) #define VDUSE_BOUNCE_SIZE (64 * 1024 * 1024) @@ -49,6 +50,8 @@ =20 #define IRQ_UNBOUND -1 =20 +#define VQ_GROUP_INVALID -1 + struct vduse_virtqueue { u16 index; u16 num_max; @@ -59,6 +62,7 @@ struct vduse_virtqueue { struct vdpa_vq_state state; bool ready; bool kicked; + u32 vq_group; spinlock_t kick_lock; spinlock_t irq_lock; struct eventfd_ctx *kickfd; @@ -115,6 +119,7 @@ struct vduse_dev { u8 status; u32 vq_num; u32 vq_align; + u32 ngroups; struct vduse_umem *umem; struct mutex mem_lock; unsigned int bounce_size; @@ -456,6 +461,7 @@ static void vduse_dev_reset(struct vduse_dev *dev) vq->driver_addr =3D 0; vq->device_addr =3D 0; vq->num =3D 0; + vq->vq_group =3D VQ_GROUP_INVALID; memset(&vq->state, 0, sizeof(vq->state)); =20 spin_lock(&vq->kick_lock); @@ -593,6 +599,19 @@ static int vduse_vdpa_set_vq_state(struct vdpa_device = *vdpa, u16 idx, return 0; } =20 +static s64 vduse_get_vq_group(struct vdpa_device *vdpa, u16 idx) +{ + struct vduse_dev *dev =3D vdpa_to_vduse(vdpa); + + if (dev->api_version < VDUSE_API_VERSION_1) + return 0; + + if (dev->vqs[idx]->vq_group =3D=3D VQ_GROUP_INVALID) + return -EINVAL; + + return dev->vqs[idx]->vq_group; +} + static int vduse_vdpa_get_vq_state(struct vdpa_device *vdpa, u16 idx, struct vdpa_vq_state *state) { @@ -790,6 +809,7 @@ static const struct vdpa_config_ops vduse_vdpa_config_o= ps =3D { .set_vq_cb =3D vduse_vdpa_set_vq_cb, .set_vq_num =3D vduse_vdpa_set_vq_num, .get_vq_size =3D vduse_vdpa_get_vq_size, + .get_vq_group =3D vduse_get_vq_group, .set_vq_ready =3D vduse_vdpa_set_vq_ready, .get_vq_ready =3D vduse_vdpa_get_vq_ready, .set_vq_state =3D vduse_vdpa_set_vq_state, @@ -1253,12 +1273,24 @@ static long vduse_dev_ioctl(struct file *file, unsi= gned int cmd, if (config.index >=3D dev->vq_num) break; =20 - if (!is_mem_zero((const char *)config.reserved, - sizeof(config.reserved))) + if (dev->api_version < VDUSE_API_VERSION_1 && config.group) + break; + + if (dev->api_version >=3D VDUSE_API_VERSION_1) { + if (config.group > dev->ngroups) + break; + if (dev->status & VIRTIO_CONFIG_S_DRIVER_OK) + break; + } + + if (config.reserved1 || + !is_mem_zero((const char *)config.reserved2, + sizeof(config.reserved2))) break; =20 index =3D array_index_nospec(config.index, dev->vq_num); dev->vqs[index]->num_max =3D config.max_size; + dev->vqs[index]->vq_group =3D config.group; ret =3D 0; break; } @@ -1738,12 +1770,20 @@ static bool features_is_valid(struct vduse_dev_conf= ig *config) return true; } =20 -static bool vduse_validate_config(struct vduse_dev_config *config) +static bool vduse_validate_config(struct vduse_dev_config *config, + u64 api_version) { if (!is_mem_zero((const char *)config->reserved, sizeof(config->reserved))) return false; =20 + if (api_version < VDUSE_API_VERSION_1 && config->ngroups) + return false; + + if (api_version >=3D VDUSE_API_VERSION_1 && + config->ngroups > VDUSE_DEV_MAX_GROUPS) + return false; + if (config->vq_align > PAGE_SIZE) return false; =20 @@ -1859,6 +1899,7 @@ static int vduse_create_dev(struct vduse_dev_config *= config, dev->device_features =3D config->features; dev->device_id =3D config->device_id; dev->vendor_id =3D config->vendor_id; + dev->ngroups =3D (dev->api_version < 1) ? 1 : (config->ngroups ?: 1); dev->name =3D kstrdup(config->name, GFP_KERNEL); if (!dev->name) goto err_str; @@ -1937,7 +1978,7 @@ static long vduse_ioctl(struct file *file, unsigned i= nt cmd, break; =20 ret =3D -EINVAL; - if (vduse_validate_config(&config) =3D=3D false) + if (!vduse_validate_config(&config, control->api_version)) break; =20 buf =3D vmemdup_user(argp + size, config.config_size); @@ -2018,7 +2059,7 @@ static int vduse_dev_init_vdpa(struct vduse_dev *dev,= const char *name) =20 vdev =3D vdpa_alloc_device(struct vduse_vdpa, vdpa, dev->dev, &vduse_vdpa_config_ops, &vduse_map_ops, - 1, 1, name, true); + dev->ngroups, 1, name, true); if (IS_ERR(vdev)) return PTR_ERR(vdev); =20 diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index 05a481e4c385..6305382eacbb 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -22,6 +22,7 @@ #include #include #include +#include =20 #include "vhost.h" =20 @@ -657,16 +658,20 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa = *v, unsigned int cmd, return -EFAULT; ops->set_vq_ready(vdpa, idx, s.num); return 0; - case VHOST_VDPA_GET_VRING_GROUP: + case VHOST_VDPA_GET_VRING_GROUP: { + u64 group; + if (!ops->get_vq_group) return -EOPNOTSUPP; s.index =3D idx; - s.num =3D ops->get_vq_group(vdpa, idx); - if (s.num >=3D vdpa->ngroups) + group =3D ops->get_vq_group(vdpa, idx); + if (group >=3D vdpa->ngroups || group > U32_MAX || group < 0) return -EIO; else if (copy_to_user(argp, &s, sizeof(s))) return -EFAULT; + s.num =3D group; return 0; + } case VHOST_VDPA_GET_VRING_DESC_GROUP: if (!vhost_vdpa_has_desc_group(v)) return -EOPNOTSUPP; diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h index 4cf21d6e9cfd..76a673ef7deb 100644 --- a/include/linux/vdpa.h +++ b/include/linux/vdpa.h @@ -211,7 +211,8 @@ struct vdpa_map_file { * virtqueue (optional) * @vdev: vdpa device * @idx: virtqueue index - * Returns u32: group id for this virtqueue + * Returns i64: (32 bits wide) group id for this + * virtqueue if >0. If <0, errno. * @get_vq_desc_group: Get the group id for the descriptor table of * a specific virtqueue (optional) * @vdev: vdpa device @@ -398,7 +399,7 @@ struct vdpa_config_ops { =20 /* Device ops */ u32 (*get_vq_align)(struct vdpa_device *vdev); - u32 (*get_vq_group)(struct vdpa_device *vdev, u16 idx); + s64 (*get_vq_group)(struct vdpa_device *vdev, u16 idx); u32 (*get_vq_desc_group)(struct vdpa_device *vdev, u16 idx); u64 (*get_device_features)(struct vdpa_device *vdev); u64 (*get_backend_features)(const struct vdpa_device *vdev); diff --git a/include/uapi/linux/vduse.h b/include/uapi/linux/vduse.h index ccb92a1efce0..a3d51cf6df3a 100644 --- a/include/uapi/linux/vduse.h +++ b/include/uapi/linux/vduse.h @@ -31,6 +31,7 @@ * @features: virtio features * @vq_num: the number of virtqueues * @vq_align: the allocation alignment of virtqueue's metadata + * @ngroups: number of vq groups 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 @@ -45,7 +46,8 @@ struct vduse_dev_config { __u64 features; __u32 vq_num; __u32 vq_align; - __u32 reserved[13]; + __u32 ngroups; /* if VDUSE_API_VERSION >=3D 1 */ + __u32 reserved[12]; __u32 config_size; __u8 config[]; }; @@ -122,14 +124,18 @@ struct vduse_config_data { * struct vduse_vq_config - basic configuration of a virtqueue * @index: virtqueue index * @max_size: the max size of virtqueue - * @reserved: for future use, needs to be initialized to zero + * @reserved1: for future use, needs to be initialized to zero + * @group: virtqueue group + * @reserved2: for future use, needs to be initialized to zero * * Structure used by VDUSE_VQ_SETUP ioctl to setup a virtqueue. */ struct vduse_vq_config { __u32 index; __u16 max_size; - __u16 reserved[13]; + __u16 reserved1; + __u32 group; + __u16 reserved2[10]; }; =20 /* --=20 2.51.0 From nobody Wed Sep 24 15:20:54 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 41CCB306D4A for ; Fri, 19 Sep 2025 09:34:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274475; cv=none; b=FfRmTofKJhCbRVfX/NheQtn+vBe3joGy8bulPq7k9NuEjciB50LZcmEpnHg8+/8qXd2JoxCGj8z71CeJwOLYkhEjkHcAIeKEepgx/oBoJ1GXf9zareKindWVROQDpyXgy/+kQsqadSdcqDajihvftG5dzOqAo7jiBM5uVupcCro= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274475; c=relaxed/simple; bh=wLSqDJ2E7jOCn4G3iCd5jisMjiBa/HRAsKNOwGReuRE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=cdi7kIE5H+y6VSwaXvb62YelapRi6cL9YxMdU0y+KO/aBid2VZJrzaTfev0kYKF024CKXltNpSwJVWd9eSw6VDDj/rxeQ63++BrfxWnFLPfCMe38089o3FmyHbVdiZb6yvNr00K9HuMaWBSgPH7pff/3a3zBWUxI7IpA2EiV9WE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=T+beMT4G; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="T+beMT4G" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758274472; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uU0QFvZkgbONix0ZNU2JdIVRas5qkokSX3OvSMTiTuU=; b=T+beMT4GOTXknMh8N+Rlo+guoNF7WHoLqFcai1DmRUF/dPslnvZuQzaH6DHSpjk5YXWu/u T6SfXkv1KWuIjAGAiWwVk2ovS1QhrikYxSfqUMG86Kdx/k7o3D3Zg61jcmNpZhqSO8b0DI fnGz+3SdHv4kp6hETQUoP04beUz7g60= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-348-91yUQuAsOsO4fwZ6RX6ZrA-1; Fri, 19 Sep 2025 05:34:29 -0400 X-MC-Unique: 91yUQuAsOsO4fwZ6RX6ZrA-1 X-Mimecast-MFC-AGG-ID: 91yUQuAsOsO4fwZ6RX6ZrA_1758274466 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C52521954B33; Fri, 19 Sep 2025 09:34:26 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A6983180035C; Fri, 19 Sep 2025 09:34:22 +0000 (UTC) From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= To: "Michael S . Tsirkin " Cc: =?UTF-8?q?Eugenio=20P=C3=A9rez?= , Yongji Xie , Maxime Coquelin , linux-kernel@vger.kernel.org, Xuan Zhuo , virtualization@lists.linux.dev, Cindy Lu , jasowang@redhat.com, Laurent Vivier , Stefano Garzarella Subject: [PATCH v3 4/6] vduse: return internal vq group struct as map token Date: Fri, 19 Sep 2025 11:33:57 +0200 Message-ID: <20250919093359.961296-5-eperezma@redhat.com> In-Reply-To: <20250919093359.961296-1-eperezma@redhat.com> References: <20250919093359.961296-1-eperezma@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Return the internal struct that represents the vq group as virtqueue map token, instead of the device. This allows the map functions to access the information per group. At this moment all the virtqueues share the same vq group, that only can point to ASID 0. This change prepares the infrastructure for actual per-group address space handling Signed-off-by: Eugenio P=C3=A9rez --- v3: * Adapt all virtio_map_ops callbacks to handle empty tokens in case of invalid groups. * Make setting status DRIVER_OK fail if vq group is not valid. * Remove the _int name suffix from struct vduse_vq_group. RFC v3: * Make the vq groups a dynamic array to support an arbitrary number of them. --- drivers/vdpa/vdpa_user/vduse_dev.c | 111 ++++++++++++++++++++++++++--- include/linux/virtio.h | 6 +- 2 files changed, 105 insertions(+), 12 deletions(-) diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vd= use_dev.c index 7ddd81456f7b..6fdabc3c910e 100644 --- a/drivers/vdpa/vdpa_user/vduse_dev.c +++ b/drivers/vdpa/vdpa_user/vduse_dev.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -88,6 +89,10 @@ struct vduse_umem { struct mm_struct *mm; }; =20 +struct vduse_vq_group { + struct vduse_dev *dev; +}; + struct vduse_dev { struct vduse_vdpa *vdev; struct device *dev; @@ -121,6 +126,7 @@ struct vduse_dev { u32 vq_align; u32 ngroups; struct vduse_umem *umem; + struct vduse_vq_group *groups; struct mutex mem_lock; unsigned int bounce_size; rwlock_t domain_lock; @@ -308,6 +314,13 @@ static int vduse_dev_set_status(struct vduse_dev *dev,= u8 status) msg.req.type =3D VDUSE_SET_STATUS; msg.req.s.status =3D status; =20 + if (dev->api_version >=3D VDUSE_API_VERSION_1 && + !(dev->status & VIRTIO_CONFIG_S_DRIVER_OK) && + status & VIRTIO_CONFIG_S_DRIVER_OK) + for (u32 i =3D 0; i < dev->vq_num; ++i) + if (dev->vqs[i]->vq_group =3D=3D VQ_GROUP_INVALID) + return -EIO; + return vduse_dev_msg_sync(dev, &msg); } =20 @@ -612,6 +625,20 @@ static s64 vduse_get_vq_group(struct vdpa_device *vdpa= , u16 idx) return dev->vqs[idx]->vq_group; } =20 +static union virtio_map vduse_get_vq_map(struct vdpa_device *vdpa, u16 idx) +{ + struct vduse_dev *dev =3D vdpa_to_vduse(vdpa); + u32 vq_group =3D vduse_get_vq_group(vdpa, idx); + union virtio_map ret; + + if (vq_group < 0) + ret.group =3D NULL; + else + ret.group =3D &dev->groups[vq_group]; + + return ret; +} + static int vduse_vdpa_get_vq_state(struct vdpa_device *vdpa, u16 idx, struct vdpa_vq_state *state) { @@ -832,6 +859,7 @@ static const struct vdpa_config_ops vduse_vdpa_config_o= ps =3D { .get_vq_affinity =3D vduse_vdpa_get_vq_affinity, .reset =3D vduse_vdpa_reset, .set_map =3D vduse_vdpa_set_map, + .get_vq_map =3D vduse_get_vq_map, .free =3D vduse_vdpa_free, }; =20 @@ -839,7 +867,14 @@ static void vduse_dev_sync_single_for_device(union vir= tio_map token, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - struct vduse_iova_domain *domain =3D token.iova_domain; + struct vduse_dev *vdev; + struct vduse_iova_domain *domain; + + if (!token.group) + return; + + vdev =3D token.group->dev; + domain =3D vdev->domain; =20 vduse_domain_sync_single_for_device(domain, dma_addr, size, dir); } @@ -848,7 +883,14 @@ static void vduse_dev_sync_single_for_cpu(union virtio= _map token, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - struct vduse_iova_domain *domain =3D token.iova_domain; + struct vduse_dev *vdev; + struct vduse_iova_domain *domain; + + if (!token.group) + return; + + vdev =3D token.group->dev; + domain =3D vdev->domain; =20 vduse_domain_sync_single_for_cpu(domain, dma_addr, size, dir); } @@ -858,7 +900,14 @@ static dma_addr_t vduse_dev_map_page(union virtio_map = token, struct page *page, enum dma_data_direction dir, unsigned long attrs) { - struct vduse_iova_domain *domain =3D token.iova_domain; + struct vduse_dev *vdev; + struct vduse_iova_domain *domain; + + if (!token.group) + return DMA_MAPPING_ERROR; + + vdev =3D token.group->dev; + domain =3D vdev->domain; =20 return vduse_domain_map_page(domain, page, offset, size, dir, attrs); } @@ -867,7 +916,14 @@ static void vduse_dev_unmap_page(union virtio_map toke= n, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir, unsigned long attrs) { - struct vduse_iova_domain *domain =3D token.iova_domain; + struct vduse_dev *vdev; + struct vduse_iova_domain *domain; + + if (!token.group) + return; + + vdev =3D token.group->dev; + domain =3D vdev->domain; =20 return vduse_domain_unmap_page(domain, dma_addr, size, dir, attrs); } @@ -875,11 +931,17 @@ static void vduse_dev_unmap_page(union virtio_map tok= en, dma_addr_t dma_addr, static void *vduse_dev_alloc_coherent(union virtio_map token, size_t size, dma_addr_t *dma_addr, gfp_t flag) { - struct vduse_iova_domain *domain =3D token.iova_domain; + struct vduse_dev *vdev; + struct vduse_iova_domain *domain; unsigned long iova; void *addr; =20 *dma_addr =3D DMA_MAPPING_ERROR; + if (!token.group) + return NULL; + + vdev =3D token.group->dev; + domain =3D vdev->domain; addr =3D vduse_domain_alloc_coherent(domain, size, (dma_addr_t *)&iova, flag); if (!addr) @@ -894,14 +956,28 @@ static void vduse_dev_free_coherent(union virtio_map = token, size_t size, void *vaddr, dma_addr_t dma_addr, unsigned long attrs) { - struct vduse_iova_domain *domain =3D token.iova_domain; + struct vduse_dev *vdev; + struct vduse_iova_domain *domain; + + if (!token.group) + return; + + vdev =3D token.group->dev; + domain =3D vdev->domain; =20 vduse_domain_free_coherent(domain, size, vaddr, dma_addr, attrs); } =20 static bool vduse_dev_need_sync(union virtio_map token, dma_addr_t dma_add= r) { - struct vduse_iova_domain *domain =3D token.iova_domain; + struct vduse_dev *vdev; + struct vduse_iova_domain *domain; + + if (!token.group) + return false; + + vdev =3D token.group->dev; + domain =3D vdev->domain; =20 return dma_addr < domain->bounce_size; } @@ -915,7 +991,14 @@ static int vduse_dev_mapping_error(union virtio_map to= ken, dma_addr_t dma_addr) =20 static size_t vduse_dev_max_mapping_size(union virtio_map token) { - struct vduse_iova_domain *domain =3D token.iova_domain; + struct vduse_dev *vdev; + struct vduse_iova_domain *domain; + + if (!token.group) + return 0; + + vdev =3D token.group->dev; + domain =3D vdev->domain; =20 return domain->bounce_size; } @@ -1733,6 +1816,7 @@ static int vduse_destroy_dev(char *name) if (dev->domain) vduse_domain_destroy(dev->domain); kfree(dev->name); + kfree(dev->groups); vduse_dev_destroy(dev); module_put(THIS_MODULE); =20 @@ -1899,7 +1983,15 @@ static int vduse_create_dev(struct vduse_dev_config = *config, dev->device_features =3D config->features; dev->device_id =3D config->device_id; dev->vendor_id =3D config->vendor_id; + dev->ngroups =3D (dev->api_version < 1) ? 1 : (config->ngroups ?: 1); + dev->groups =3D kcalloc(dev->ngroups, sizeof(dev->groups[0]), + GFP_KERNEL); + if (!dev->groups) + goto err_vq_groups; + for (u32 i =3D 0; i < dev->ngroups; ++i) + dev->groups[i].dev =3D dev; + dev->name =3D kstrdup(config->name, GFP_KERNEL); if (!dev->name) goto err_str; @@ -1936,6 +2028,8 @@ static int vduse_create_dev(struct vduse_dev_config *= config, err_idr: kfree(dev->name); err_str: + kfree(dev->groups); +err_vq_groups: vduse_dev_destroy(dev); err: return ret; @@ -2097,7 +2191,6 @@ static int vdpa_dev_add(struct vdpa_mgmt_dev *mdev, c= onst char *name, return -ENOMEM; } =20 - dev->vdev->vdpa.vmap.iova_domain =3D dev->domain; ret =3D _vdpa_register_device(&dev->vdev->vdpa, dev->vq_num); if (ret) { put_device(&dev->vdev->vdpa.dev); diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 96c66126c074..302109029700 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -41,13 +41,13 @@ struct virtqueue { void *priv; }; =20 -struct vduse_iova_domain; +struct vduse_vq_group; =20 union virtio_map { /* Device that performs DMA */ struct device *dma_dev; - /* VDUSE specific mapping data */ - struct vduse_iova_domain *iova_domain; + /* VDUSE specific virtqueue group for doing map */ + struct vduse_vq_group *group; }; =20 int virtqueue_add_outbuf(struct virtqueue *vq, --=20 2.51.0 From nobody Wed Sep 24 15:20:54 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 33C5D2F6192 for ; Fri, 19 Sep 2025 09:34:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274486; cv=none; b=P1IKGzEV2Q5OTFxL0Ff/dao9/A87JeyjPSCZaqtjOIDhxanza+91zJSE8x4y+GbK9Jb4UWP2duZrExcJhKyQXq2/mci8VjDlsDvvu2hr+NxHGBHq58obOfOnGCFp1EEiLhmk5OWVSNQkVB1Ly8XM2MzaulWea+sD0wBrb/YerEc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274486; c=relaxed/simple; bh=6C5Yl/Cmz+sBeyqwSNtsV4+MY553vAKHfOAi1oO9XXA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=GViZUt22qIxvHP2ZZ5KBwPY3tnukJp2aqkbgJzfxXUgZaKU3NOQZROffBE2UUafvw1NrrgskyEYLRUqCMHvq9GCXQs7pkP16kW3v8Z8cXztDIwnjYwjMYvQqZ3QPY66LA7li4XywjF8zVRkrVqTbTQdjJ1FvchdCCHokZVfYyOY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=M+e0Mesn; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="M+e0Mesn" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758274483; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rcnqmHle66NisZf/1+zURB1rhajdZYMCSkWCvEGe+Jo=; b=M+e0Mesn6BA+xuXmx/eo4hi477hpPyQsZylgxusbf1YFc8XiFfmoO3APmOZ+o4pZpzUrrn 1mB5NjmUQ7ggHKylnFPPoYQRkLLSw80WI8xTIiWuMRUJ7SUXPXknnsqEhC7MlkLSQkN9fO /fVKPRyi2gkrHqUzpGWqumSE/tXIYGs= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-562-81oea8KKPlm8Z-NmAVrMbg-1; Fri, 19 Sep 2025 05:34:37 -0400 X-MC-Unique: 81oea8KKPlm8Z-NmAVrMbg-1 X-Mimecast-MFC-AGG-ID: 81oea8KKPlm8Z-NmAVrMbg_1758274475 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C7E351805A35; Fri, 19 Sep 2025 09:34:31 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5C31018004A3; Fri, 19 Sep 2025 09:34:27 +0000 (UTC) From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= To: "Michael S . Tsirkin " Cc: =?UTF-8?q?Eugenio=20P=C3=A9rez?= , Yongji Xie , Maxime Coquelin , linux-kernel@vger.kernel.org, Xuan Zhuo , virtualization@lists.linux.dev, Cindy Lu , jasowang@redhat.com, Laurent Vivier , Stefano Garzarella Subject: [PATCH v3 5/6] vduse: add vq group asid support Date: Fri, 19 Sep 2025 11:33:58 +0200 Message-ID: <20250919093359.961296-6-eperezma@redhat.com> In-Reply-To: <20250919093359.961296-1-eperezma@redhat.com> References: <20250919093359.961296-1-eperezma@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Add support for assigning Address Space Identifiers (ASIDs) to each VQ group. This enables mapping each group into a distinct memory space. Now that the driver can change ASID in the middle of operation, the domain that each vq address point is also protected by domain_lock. Signed-off-by: Eugenio P=C3=A9rez --- v3: * Get the vduse domain through the vduse_as in the map functions (Jason). * Squash with the patch creating the vduse_as struct (Jason). * Create VDUSE_DEV_MAX_AS instead of comparing agains a magic number (Jason) v2: * Convert the use of mutex to rwlock. RFC v3: * Increase VDUSE_MAX_VQ_GROUPS to 0xffff (Jason). It was set to a lower value to reduce memory consumption, but vqs are already limited to that value and userspace VDUSE is able to allocate that many vqs. * Remove TODO about merging VDUSE_IOTLB_GET_FD ioctl with VDUSE_IOTLB_GET_INFO. * Use of array_index_nospec in VDUSE device ioctls. * Embed vduse_iotlb_entry into vduse_iotlb_entry_v2. * Move the umem mutex to asid struct so there is no contention between ASIDs. RFC v2: * Make iotlb entry the last one of vduse_iotlb_entry_v2 so the first part of the struct is the same. --- drivers/vdpa/vdpa_user/vduse_dev.c | 327 ++++++++++++++++++++--------- include/uapi/linux/vduse.h | 51 ++++- 2 files changed, 281 insertions(+), 97 deletions(-) diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vd= use_dev.c index 6fdabc3c910e..c6c70cfd4887 100644 --- a/drivers/vdpa/vdpa_user/vduse_dev.c +++ b/drivers/vdpa/vdpa_user/vduse_dev.c @@ -42,6 +42,7 @@ =20 #define VDUSE_DEV_MAX (1U << MINORBITS) #define VDUSE_DEV_MAX_GROUPS 0xffff +#define VDUSE_DEV_MAX_AS 0xffff #define VDUSE_MAX_BOUNCE_SIZE (1024 * 1024 * 1024) #define VDUSE_MIN_BOUNCE_SIZE (1024 * 1024) #define VDUSE_BOUNCE_SIZE (64 * 1024 * 1024) @@ -89,7 +90,14 @@ struct vduse_umem { struct mm_struct *mm; }; =20 +struct vduse_as { + struct vduse_iova_domain *domain; + struct vduse_umem *umem; + struct mutex mem_lock; +}; + struct vduse_vq_group { + struct vduse_as *as; struct vduse_dev *dev; }; =20 @@ -97,7 +105,7 @@ struct vduse_dev { struct vduse_vdpa *vdev; struct device *dev; struct vduse_virtqueue **vqs; - struct vduse_iova_domain *domain; + struct vduse_as *as; char *name; struct mutex lock; spinlock_t msg_lock; @@ -125,9 +133,8 @@ struct vduse_dev { u32 vq_num; u32 vq_align; u32 ngroups; - struct vduse_umem *umem; + u32 nas; struct vduse_vq_group *groups; - struct mutex mem_lock; unsigned int bounce_size; rwlock_t domain_lock; }; @@ -324,7 +331,7 @@ static int vduse_dev_set_status(struct vduse_dev *dev, = u8 status) return vduse_dev_msg_sync(dev, &msg); } =20 -static int vduse_dev_update_iotlb(struct vduse_dev *dev, +static int vduse_dev_update_iotlb(struct vduse_dev *dev, u32 asid, u64 start, u64 last) { struct vduse_dev_msg msg =3D { 0 }; @@ -333,8 +340,14 @@ static int vduse_dev_update_iotlb(struct vduse_dev *de= v, return -EINVAL; =20 msg.req.type =3D VDUSE_UPDATE_IOTLB; - msg.req.iova.start =3D start; - msg.req.iova.last =3D last; + if (dev->api_version < VDUSE_API_VERSION_1) { + msg.req.iova.start =3D start; + msg.req.iova.last =3D last; + } else { + msg.req.iova_v2.start =3D start; + msg.req.iova_v2.last =3D last; + msg.req.iova_v2.asid =3D asid; + } =20 return vduse_dev_msg_sync(dev, &msg); } @@ -446,14 +459,29 @@ static __poll_t vduse_dev_poll(struct file *file, pol= l_table *wait) return mask; } =20 +/* Force set the asid to a vq group without a message to the VDUSE device = */ +static void vduse_set_group_asid_nomsg(struct vduse_dev *dev, + unsigned int group, unsigned int asid) +{ + write_lock(&dev->domain_lock); + dev->groups[group].as =3D &dev->as[asid]; + write_unlock(&dev->domain_lock); +} + static void vduse_dev_reset(struct vduse_dev *dev) { int i; - struct vduse_iova_domain *domain =3D dev->domain; =20 /* The coherent mappings are handled in vduse_dev_free_coherent() */ - if (domain && domain->bounce_map) - vduse_domain_reset_bounce_map(domain); + for (i =3D 0; i < dev->nas; i++) { + struct vduse_iova_domain *domain =3D dev->as[i].domain; + + if (domain && domain->bounce_map) + vduse_domain_reset_bounce_map(domain); + } + + for (i =3D 0; i < dev->ngroups; i++) + vduse_set_group_asid_nomsg(dev, i, 0); =20 down_write(&dev->rwsem); =20 @@ -639,6 +667,29 @@ static union virtio_map vduse_get_vq_map(struct vdpa_d= evice *vdpa, u16 idx) return ret; } =20 +static int vduse_set_group_asid(struct vdpa_device *vdpa, unsigned int gro= up, + unsigned int asid) +{ + struct vduse_dev *dev =3D vdpa_to_vduse(vdpa); + struct vduse_dev_msg msg =3D { 0 }; + int r; + + if (dev->api_version < VDUSE_API_VERSION_1 || + group >=3D dev->ngroups || asid >=3D dev->nas) + return -EINVAL; + + msg.req.type =3D VDUSE_SET_VQ_GROUP_ASID; + msg.req.vq_group_asid.group =3D group; + msg.req.vq_group_asid.asid =3D asid; + + r =3D vduse_dev_msg_sync(dev, &msg); + if (r < 0) + return r; + + vduse_set_group_asid_nomsg(dev, group, asid); + return 0; +} + static int vduse_vdpa_get_vq_state(struct vdpa_device *vdpa, u16 idx, struct vdpa_vq_state *state) { @@ -810,13 +861,13 @@ static int vduse_vdpa_set_map(struct vdpa_device *vdp= a, struct vduse_dev *dev =3D vdpa_to_vduse(vdpa); int ret; =20 - ret =3D vduse_domain_set_map(dev->domain, iotlb); + ret =3D vduse_domain_set_map(dev->as[asid].domain, iotlb); if (ret) return ret; =20 - ret =3D vduse_dev_update_iotlb(dev, 0ULL, ULLONG_MAX); + ret =3D vduse_dev_update_iotlb(dev, asid, 0ULL, ULLONG_MAX); if (ret) { - vduse_domain_clear_map(dev->domain, iotlb); + vduse_domain_clear_map(dev->as[asid].domain, iotlb); return ret; } =20 @@ -859,6 +910,7 @@ static const struct vdpa_config_ops vduse_vdpa_config_o= ps =3D { .get_vq_affinity =3D vduse_vdpa_get_vq_affinity, .reset =3D vduse_vdpa_reset, .set_map =3D vduse_vdpa_set_map, + .set_group_asid =3D vduse_set_group_asid, .get_vq_map =3D vduse_get_vq_map, .free =3D vduse_vdpa_free, }; @@ -874,9 +926,10 @@ static void vduse_dev_sync_single_for_device(union vir= tio_map token, return; =20 vdev =3D token.group->dev; - domain =3D vdev->domain; - + read_lock(&vdev->domain_lock); + domain =3D token.group->as->domain; vduse_domain_sync_single_for_device(domain, dma_addr, size, dir); + read_unlock(&vdev->domain_lock); } =20 static void vduse_dev_sync_single_for_cpu(union virtio_map token, @@ -890,9 +943,10 @@ static void vduse_dev_sync_single_for_cpu(union virtio= _map token, return; =20 vdev =3D token.group->dev; - domain =3D vdev->domain; - + read_lock(&vdev->domain_lock); + domain =3D token.group->as->domain; vduse_domain_sync_single_for_cpu(domain, dma_addr, size, dir); + read_unlock(&vdev->domain_lock); } =20 static dma_addr_t vduse_dev_map_page(union virtio_map token, struct page *= page, @@ -902,14 +956,18 @@ static dma_addr_t vduse_dev_map_page(union virtio_map= token, struct page *page, { struct vduse_dev *vdev; struct vduse_iova_domain *domain; + dma_addr_t r; =20 if (!token.group) return DMA_MAPPING_ERROR; =20 vdev =3D token.group->dev; - domain =3D vdev->domain; + read_lock(&vdev->domain_lock); + domain =3D token.group->as->domain; + r =3D vduse_domain_map_page(domain, page, offset, size, dir, attrs); + read_unlock(&vdev->domain_lock); =20 - return vduse_domain_map_page(domain, page, offset, size, dir, attrs); + return r; } =20 static void vduse_dev_unmap_page(union virtio_map token, dma_addr_t dma_ad= dr, @@ -923,9 +981,10 @@ static void vduse_dev_unmap_page(union virtio_map toke= n, dma_addr_t dma_addr, return; =20 vdev =3D token.group->dev; - domain =3D vdev->domain; - - return vduse_domain_unmap_page(domain, dma_addr, size, dir, attrs); + read_lock(&vdev->domain_lock); + domain =3D token.group->as->domain; + vduse_domain_unmap_page(domain, dma_addr, size, dir, attrs); + read_unlock(&vdev->domain_lock); } =20 static void *vduse_dev_alloc_coherent(union virtio_map token, size_t size, @@ -934,21 +993,21 @@ static void *vduse_dev_alloc_coherent(union virtio_ma= p token, size_t size, struct vduse_dev *vdev; struct vduse_iova_domain *domain; unsigned long iova; - void *addr; + void *addr =3D NULL; =20 *dma_addr =3D DMA_MAPPING_ERROR; if (!token.group) return NULL; =20 vdev =3D token.group->dev; - domain =3D vdev->domain; + read_lock(&vdev->domain_lock); + domain =3D token.group->as->domain; addr =3D vduse_domain_alloc_coherent(domain, size, (dma_addr_t *)&iova, flag); - if (!addr) - return NULL; - - *dma_addr =3D (dma_addr_t)iova; + if (addr) + *dma_addr =3D (dma_addr_t)iova; =20 + read_unlock(&vdev->domain_lock); return addr; } =20 @@ -963,23 +1022,28 @@ static void vduse_dev_free_coherent(union virtio_map= token, size_t size, return; =20 vdev =3D token.group->dev; - domain =3D vdev->domain; - + read_lock(&vdev->domain_lock); + domain =3D token.group->as->domain; vduse_domain_free_coherent(domain, size, vaddr, dma_addr, attrs); + read_unlock(&vdev->domain_lock); } =20 static bool vduse_dev_need_sync(union virtio_map token, dma_addr_t dma_add= r) { struct vduse_dev *vdev; struct vduse_iova_domain *domain; + size_t bounce_size; =20 if (!token.group) return false; =20 vdev =3D token.group->dev; - domain =3D vdev->domain; + read_lock(&vdev->domain_lock); + domain =3D token.group->as->domain; + bounce_size =3D domain->bounce_size; + read_unlock(&vdev->domain_lock); =20 - return dma_addr < domain->bounce_size; + return dma_addr < bounce_size; } =20 static int vduse_dev_mapping_error(union virtio_map token, dma_addr_t dma_= addr) @@ -993,14 +1057,18 @@ static size_t vduse_dev_max_mapping_size(union virti= o_map token) { struct vduse_dev *vdev; struct vduse_iova_domain *domain; + size_t bounce_size; =20 if (!token.group) return 0; =20 vdev =3D token.group->dev; - domain =3D vdev->domain; + read_lock(&vdev->domain_lock); + domain =3D token.group->as->domain; + bounce_size =3D domain->bounce_size; + read_unlock(&vdev->domain_lock); =20 - return domain->bounce_size; + return bounce_size; } =20 static const struct virtio_map_ops vduse_map_ops =3D { @@ -1140,39 +1208,40 @@ static int vduse_dev_queue_irq_work(struct vduse_de= v *dev, return ret; } =20 -static int vduse_dev_dereg_umem(struct vduse_dev *dev, +static int vduse_dev_dereg_umem(struct vduse_dev *dev, u32 asid, u64 iova, u64 size) { int ret; =20 - mutex_lock(&dev->mem_lock); + mutex_lock(&dev->as[asid].mem_lock); ret =3D -ENOENT; - if (!dev->umem) + if (!dev->as[asid].umem) goto unlock; =20 ret =3D -EINVAL; - if (!dev->domain) + if (!dev->as[asid].domain) goto unlock; =20 - if (dev->umem->iova !=3D iova || size !=3D dev->domain->bounce_size) + if (dev->as[asid].umem->iova !=3D iova || + size !=3D dev->as[asid].domain->bounce_size) goto unlock; =20 - vduse_domain_remove_user_bounce_pages(dev->domain); - unpin_user_pages_dirty_lock(dev->umem->pages, - dev->umem->npages, true); - atomic64_sub(dev->umem->npages, &dev->umem->mm->pinned_vm); - mmdrop(dev->umem->mm); - vfree(dev->umem->pages); - kfree(dev->umem); - dev->umem =3D NULL; + vduse_domain_remove_user_bounce_pages(dev->as[asid].domain); + unpin_user_pages_dirty_lock(dev->as[asid].umem->pages, + dev->as[asid].umem->npages, true); + atomic64_sub(dev->as[asid].umem->npages, &dev->as[asid].umem->mm->pinned_= vm); + mmdrop(dev->as[asid].umem->mm); + vfree(dev->as[asid].umem->pages); + kfree(dev->as[asid].umem); + dev->as[asid].umem =3D NULL; ret =3D 0; unlock: - mutex_unlock(&dev->mem_lock); + mutex_unlock(&dev->as[asid].mem_lock); return ret; } =20 static int vduse_dev_reg_umem(struct vduse_dev *dev, - u64 iova, u64 uaddr, u64 size) + u32 asid, u64 iova, u64 uaddr, u64 size) { struct page **page_list =3D NULL; struct vduse_umem *umem =3D NULL; @@ -1180,14 +1249,14 @@ static int vduse_dev_reg_umem(struct vduse_dev *dev, unsigned long npages, lock_limit; int ret; =20 - if (!dev->domain || !dev->domain->bounce_map || - size !=3D dev->domain->bounce_size || + if (!dev->as[asid].domain || !dev->as[asid].domain->bounce_map || + size !=3D dev->as[asid].domain->bounce_size || iova !=3D 0 || uaddr & ~PAGE_MASK) return -EINVAL; =20 - mutex_lock(&dev->mem_lock); + mutex_lock(&dev->as[asid].mem_lock); ret =3D -EEXIST; - if (dev->umem) + if (dev->as[asid].umem) goto unlock; =20 ret =3D -ENOMEM; @@ -1211,7 +1280,7 @@ static int vduse_dev_reg_umem(struct vduse_dev *dev, goto out; } =20 - ret =3D vduse_domain_add_user_bounce_pages(dev->domain, + ret =3D vduse_domain_add_user_bounce_pages(dev->as[asid].domain, page_list, pinned); if (ret) goto out; @@ -1224,7 +1293,7 @@ static int vduse_dev_reg_umem(struct vduse_dev *dev, umem->mm =3D current->mm; mmgrab(current->mm); =20 - dev->umem =3D umem; + dev->as[asid].umem =3D umem; out: if (ret && pinned > 0) unpin_user_pages(page_list, pinned); @@ -1235,7 +1304,7 @@ static int vduse_dev_reg_umem(struct vduse_dev *dev, vfree(page_list); kfree(umem); } - mutex_unlock(&dev->mem_lock); + mutex_unlock(&dev->as[asid].mem_lock); return ret; } =20 @@ -1267,47 +1336,66 @@ static long vduse_dev_ioctl(struct file *file, unsi= gned int cmd, =20 switch (cmd) { case VDUSE_IOTLB_GET_FD: { - struct vduse_iotlb_entry entry; + struct vduse_iotlb_entry_v2 entry; struct vhost_iotlb_map *map; struct vdpa_map_file *map_file; struct file *f =3D NULL; + u32 asid; =20 ret =3D -EFAULT; - if (copy_from_user(&entry, argp, sizeof(entry))) - break; + if (dev->api_version >=3D VDUSE_API_VERSION_1) { + if (copy_from_user(&entry, argp, sizeof(entry))) + break; + } else { + entry.asid =3D 0; + if (copy_from_user(&entry.v1, argp, + sizeof(entry.v1))) + break; + } =20 ret =3D -EINVAL; - if (entry.start > entry.last) + if (entry.v1.start > entry.v1.last) + break; + + if (entry.asid >=3D dev->nas) break; =20 read_lock(&dev->domain_lock); - if (!dev->domain) { + asid =3D array_index_nospec(entry.asid, dev->nas); + if (!dev->as[asid].domain) { read_unlock(&dev->domain_lock); break; } - spin_lock(&dev->domain->iotlb_lock); - map =3D vhost_iotlb_itree_first(dev->domain->iotlb, - entry.start, entry.last); + spin_lock(&dev->as[asid].domain->iotlb_lock); + map =3D vhost_iotlb_itree_first(dev->as[asid].domain->iotlb, + entry.v1.start, entry.v1.last); if (map) { map_file =3D (struct vdpa_map_file *)map->opaque; f =3D get_file(map_file->file); - entry.offset =3D map_file->offset; - entry.start =3D map->start; - entry.last =3D map->last; - entry.perm =3D map->perm; + entry.v1.offset =3D map_file->offset; + entry.v1.start =3D map->start; + entry.v1.last =3D map->last; + entry.v1.perm =3D map->perm; } - spin_unlock(&dev->domain->iotlb_lock); + spin_unlock(&dev->as[asid].domain->iotlb_lock); read_unlock(&dev->domain_lock); ret =3D -EINVAL; if (!f) break; =20 ret =3D -EFAULT; - if (copy_to_user(argp, &entry, sizeof(entry))) { + if (dev->api_version >=3D VDUSE_API_VERSION_1) + ret =3D copy_to_user(argp, &entry, + sizeof(entry)); + else + ret =3D copy_to_user(argp, &entry.v1, + sizeof(entry.v1)); + + if (ret) { fput(f); break; } - ret =3D receive_fd(f, NULL, perm_to_file_flags(entry.perm)); + ret =3D receive_fd(f, NULL, perm_to_file_flags(entry.v1.perm)); fput(f); break; } @@ -1452,6 +1540,7 @@ static long vduse_dev_ioctl(struct file *file, unsign= ed int cmd, } case VDUSE_IOTLB_REG_UMEM: { struct vduse_iova_umem umem; + u32 asid; =20 ret =3D -EFAULT; if (copy_from_user(&umem, argp, sizeof(umem))) @@ -1459,17 +1548,21 @@ static long vduse_dev_ioctl(struct file *file, unsi= gned int cmd, =20 ret =3D -EINVAL; if (!is_mem_zero((const char *)umem.reserved, - sizeof(umem.reserved))) + sizeof(umem.reserved)) || + (dev->api_version < VDUSE_API_VERSION_1 && + umem.asid !=3D 0) || umem.asid >=3D dev->nas) break; =20 write_lock(&dev->domain_lock); - ret =3D vduse_dev_reg_umem(dev, umem.iova, + asid =3D array_index_nospec(umem.asid, dev->nas); + ret =3D vduse_dev_reg_umem(dev, asid, umem.iova, umem.uaddr, umem.size); write_unlock(&dev->domain_lock); break; } case VDUSE_IOTLB_DEREG_UMEM: { struct vduse_iova_umem umem; + u32 asid; =20 ret =3D -EFAULT; if (copy_from_user(&umem, argp, sizeof(umem))) @@ -1477,10 +1570,15 @@ static long vduse_dev_ioctl(struct file *file, unsi= gned int cmd, =20 ret =3D -EINVAL; if (!is_mem_zero((const char *)umem.reserved, - sizeof(umem.reserved))) + sizeof(umem.reserved)) || + (dev->api_version < VDUSE_API_VERSION_1 && + umem.asid !=3D 0) || + umem.asid >=3D dev->nas) break; + write_lock(&dev->domain_lock); - ret =3D vduse_dev_dereg_umem(dev, umem.iova, + asid =3D array_index_nospec(umem.asid, dev->nas); + ret =3D vduse_dev_dereg_umem(dev, asid, umem.iova, umem.size); write_unlock(&dev->domain_lock); break; @@ -1488,6 +1586,7 @@ static long vduse_dev_ioctl(struct file *file, unsign= ed int cmd, case VDUSE_IOTLB_GET_INFO: { struct vduse_iova_info info; struct vhost_iotlb_map *map; + u32 asid; =20 ret =3D -EFAULT; if (copy_from_user(&info, argp, sizeof(info))) @@ -1501,23 +1600,31 @@ static long vduse_dev_ioctl(struct file *file, unsi= gned int cmd, sizeof(info.reserved))) break; =20 + if (dev->api_version < VDUSE_API_VERSION_1) { + if (info.asid) + break; + } else if (info.asid >=3D dev->nas) + break; + read_lock(&dev->domain_lock); - if (!dev->domain) { + asid =3D array_index_nospec(info.asid, dev->nas); + if (!dev->as[asid].domain) { read_unlock(&dev->domain_lock); break; } - spin_lock(&dev->domain->iotlb_lock); - map =3D vhost_iotlb_itree_first(dev->domain->iotlb, + spin_lock(&dev->as[asid].domain->iotlb_lock); + map =3D vhost_iotlb_itree_first(dev->as[asid].domain->iotlb, info.start, info.last); if (map) { info.start =3D map->start; info.last =3D map->last; info.capability =3D 0; - if (dev->domain->bounce_map && map->start =3D=3D 0 && - map->last =3D=3D dev->domain->bounce_size - 1) + if (dev->as[asid].domain->bounce_map && + map->start =3D=3D 0 && + map->last =3D=3D dev->as[asid].domain->bounce_size - 1) info.capability |=3D VDUSE_IOVA_CAP_UMEM; } - spin_unlock(&dev->domain->iotlb_lock); + spin_unlock(&dev->as[asid].domain->iotlb_lock); read_unlock(&dev->domain_lock); if (!map) break; @@ -1542,8 +1649,10 @@ static int vduse_dev_release(struct inode *inode, st= ruct file *file) struct vduse_dev *dev =3D file->private_data; =20 write_lock(&dev->domain_lock); - if (dev->domain) - vduse_dev_dereg_umem(dev, 0, dev->domain->bounce_size); + for (int i =3D 0; i < dev->nas; i++) + if (dev->as[i].domain) + vduse_dev_dereg_umem(dev, i, 0, + dev->as[i].domain->bounce_size); write_unlock(&dev->domain_lock); spin_lock(&dev->msg_lock); /* Make sure the inflight messages can processed after reconncection */ @@ -1762,7 +1871,6 @@ static struct vduse_dev *vduse_dev_create(void) return NULL; =20 mutex_init(&dev->lock); - mutex_init(&dev->mem_lock); rwlock_init(&dev->domain_lock); spin_lock_init(&dev->msg_lock); INIT_LIST_HEAD(&dev->send_list); @@ -1813,8 +1921,11 @@ static int vduse_destroy_dev(char *name) idr_remove(&vduse_idr, dev->minor); kvfree(dev->config); vduse_dev_deinit_vqs(dev); - if (dev->domain) - vduse_domain_destroy(dev->domain); + for (int i =3D 0; i < dev->nas; i++) { + if (dev->as[i].domain) + vduse_domain_destroy(dev->as[i].domain); + } + kfree(dev->as); kfree(dev->name); kfree(dev->groups); vduse_dev_destroy(dev); @@ -1861,13 +1972,18 @@ static bool vduse_validate_config(struct vduse_dev_= config *config, sizeof(config->reserved))) return false; =20 - if (api_version < VDUSE_API_VERSION_1 && config->ngroups) + if (api_version < VDUSE_API_VERSION_1 && + (config->ngroups || config->nas)) return false; =20 if (api_version >=3D VDUSE_API_VERSION_1 && config->ngroups > VDUSE_DEV_MAX_GROUPS) return false; =20 + if (api_version >=3D VDUSE_API_VERSION_1 && + config->nas > VDUSE_DEV_MAX_AS) + return false; + if (config->vq_align > PAGE_SIZE) return false; =20 @@ -1931,7 +2047,8 @@ static ssize_t bounce_size_store(struct device *devic= e, =20 ret =3D -EPERM; write_lock(&dev->domain_lock); - if (dev->domain) + /* Assuming that if the first domain is allocated, all are allocated */ + if (dev->as[0].domain) goto unlock; =20 ret =3D kstrtouint(buf, 10, &bounce_size); @@ -1992,6 +2109,13 @@ static int vduse_create_dev(struct vduse_dev_config = *config, for (u32 i =3D 0; i < dev->ngroups; ++i) dev->groups[i].dev =3D dev; =20 + dev->nas =3D (dev->api_version < 1) ? 1 : (config->nas ?: 1); + dev->as =3D kcalloc(dev->nas, sizeof(dev->as[0]), GFP_KERNEL); + if (!dev->as) + goto err_as; + for (int i =3D 0; i < dev->nas; i++) + mutex_init(&dev->as[i].mem_lock); + dev->name =3D kstrdup(config->name, GFP_KERNEL); if (!dev->name) goto err_str; @@ -2028,6 +2152,8 @@ static int vduse_create_dev(struct vduse_dev_config *= config, err_idr: kfree(dev->name); err_str: + kfree(dev->as); +err_as: kfree(dev->groups); err_vq_groups: vduse_dev_destroy(dev); @@ -2153,7 +2279,7 @@ static int vduse_dev_init_vdpa(struct vduse_dev *dev,= const char *name) =20 vdev =3D vdpa_alloc_device(struct vduse_vdpa, vdpa, dev->dev, &vduse_vdpa_config_ops, &vduse_map_ops, - dev->ngroups, 1, name, true); + dev->ngroups, dev->nas, name, true); if (IS_ERR(vdev)) return PTR_ERR(vdev); =20 @@ -2182,11 +2308,20 @@ static int vdpa_dev_add(struct vdpa_mgmt_dev *mdev,= const char *name, return ret; =20 write_lock(&dev->domain_lock); - if (!dev->domain) - dev->domain =3D vduse_domain_create(VDUSE_IOVA_SIZE - 1, - dev->bounce_size); + ret =3D 0; + + for (int i =3D 0; i < dev->nas; ++i) { + dev->as[i].domain =3D vduse_domain_create(VDUSE_IOVA_SIZE - 1, + dev->bounce_size); + if (!dev->as[i].domain) { + ret =3D -ENOMEM; + for (int j =3D 0; j < i; ++j) + vduse_domain_destroy(dev->as[j].domain); + } + } + write_unlock(&dev->domain_lock); - if (!dev->domain) { + if (ret =3D=3D -ENOMEM) { put_device(&dev->vdev->vdpa.dev); return -ENOMEM; } @@ -2195,8 +2330,12 @@ static int vdpa_dev_add(struct vdpa_mgmt_dev *mdev, = const char *name, if (ret) { put_device(&dev->vdev->vdpa.dev); write_lock(&dev->domain_lock); - vduse_domain_destroy(dev->domain); - dev->domain =3D NULL; + for (int i =3D 0; i < dev->nas; i++) { + if (dev->as[i].domain) { + vduse_domain_destroy(dev->as[i].domain); + dev->as[i].domain =3D NULL; + } + } write_unlock(&dev->domain_lock); return ret; } diff --git a/include/uapi/linux/vduse.h b/include/uapi/linux/vduse.h index a3d51cf6df3a..da73c3f2c280 100644 --- a/include/uapi/linux/vduse.h +++ b/include/uapi/linux/vduse.h @@ -47,7 +47,8 @@ struct vduse_dev_config { __u32 vq_num; __u32 vq_align; __u32 ngroups; /* if VDUSE_API_VERSION >=3D 1 */ - __u32 reserved[12]; + __u32 nas; /* if VDUSE_API_VERSION >=3D 1 */ + __u32 reserved[11]; __u32 config_size; __u8 config[]; }; @@ -82,6 +83,18 @@ struct vduse_iotlb_entry { __u8 perm; }; =20 +/** + * struct vduse_iotlb_entry_v2 - entry of IOTLB to describe one IOVA regio= n in an ASID + * @v1: the original vduse_iotlb_entry + * @asid: address space ID of the IOVA region + * + * Structure used by VDUSE_IOTLB_GET_FD ioctl to find an overlapped IOVA r= egion. + */ +struct vduse_iotlb_entry_v2 { + struct vduse_iotlb_entry v1; + __u32 asid; +}; + /* * Find the first IOVA region that overlaps with the range [start, last] * and return the corresponding file descriptor. Return -EINVAL means the @@ -166,6 +179,16 @@ struct vduse_vq_state_packed { __u16 last_used_idx; }; =20 +/** + * struct vduse_vq_group - virtqueue group + @ @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 +248,7 @@ struct vduse_vq_eventfd { * @uaddr: start address of userspace memory, it must be aligned to page s= ize * @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 +258,8 @@ struct vduse_iova_umem { __u64 uaddr; __u64 iova; __u64 size; - __u64 reserved[3]; + __u32 asid; + __u32 reserved[5]; }; =20 /* Register userspace memory for IOVA regions */ @@ -248,6 +273,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 = >=3D 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 +284,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 >=3D 1 */ + __u32 reserved[5]; }; =20 /* @@ -280,6 +307,7 @@ enum vduse_req_type { VDUSE_GET_VQ_STATE, VDUSE_SET_STATUS, VDUSE_UPDATE_IOTLB, + VDUSE_SET_VQ_GROUP_ASID, }; =20 /** @@ -314,6 +342,18 @@ struct vduse_iova_range { __u64 last; }; =20 +/** + * struct vduse_iova_range - IOVA range [start, last] if API_VERSION >=3D 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 +362,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 >=3D 1 + * @vq_group_asid: ASID of a virtqueue group * @padding: padding * * Structure used by read(2) on /dev/vduse/$NAME. @@ -334,6 +376,9 @@ struct vduse_dev_request { struct vduse_vq_state vq_state; struct vduse_dev_status s; struct vduse_iova_range iova; + /* Following members only if vduse api version >=3D 1 */; + struct vduse_iova_range_v2 iova_v2; + struct vduse_vq_group_asid vq_group_asid; __u32 padding[32]; }; }; --=20 2.51.0 From nobody Wed Sep 24 15:20:54 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2BCB12ECEAB for ; Fri, 19 Sep 2025 09:34:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274484; cv=none; b=oOLIzlClVSVUXePXkMeCMcQ6wf2QWNvxEucxOY2hL5UUrlOQ5Lwfce31tI5Zf8K2jy3tuNesGyEGN6eIH8kEnuxIbOMfykg1uuvhq3kRnXUMCVqdc/N1Aj0shvsgqhKxKnRIQVXIGAO82PA9F3ezkwj5hBt35vyZ9gyk0IWzHW8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758274484; c=relaxed/simple; bh=Z/pKFvEBHtxOP5jR2phobA80ogKglZ89DhR08bGclpA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qiR22jfNDRFfJzEionblhNdm8b4dDryjqvmE5pW8j9XdyW6AVZELIw24IwvX81iWj8seQ2gNWBOX2aCxRfxTxUTRIVDamPVPJvExNxwn6ghCEMQdFErBhBvTkmgKhRV0FFUOKkIsHJWWNSK1OVtggRj7UiZ9stKlMkpB24iQt/Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=S9T2RZK6; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="S9T2RZK6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1758274482; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hccOUlPXnLXU/IJ5y5buDrd2kdvNfHWXluEA21aaChQ=; b=S9T2RZK6bwgOKPYGdFmx8I3KpvDz7pDchsqeLqZbcRHZv8/+zZSSaq0YnUAJOiSA21Od0d Hv6n9WrkpCa9tf4DJFleEZ2pDPBAlF5UEhrph1nze1Lzw0Dc1BpU9LXgbYM3yRKHlI656z jl7G7GrnPitlo5qr/gMjSSitrfuRgwE= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-634-g350QPhrM5ihY2gjZ6IaeA-1; Fri, 19 Sep 2025 05:34:38 -0400 X-MC-Unique: g350QPhrM5ihY2gjZ6IaeA-1 X-Mimecast-MFC-AGG-ID: g350QPhrM5ihY2gjZ6IaeA_1758274477 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 80510195605A; Fri, 19 Sep 2025 09:34:37 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E50811800447; Fri, 19 Sep 2025 09:34:32 +0000 (UTC) From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= To: "Michael S . Tsirkin " Cc: =?UTF-8?q?Eugenio=20P=C3=A9rez?= , Yongji Xie , Maxime Coquelin , linux-kernel@vger.kernel.org, Xuan Zhuo , virtualization@lists.linux.dev, Cindy Lu , jasowang@redhat.com, Laurent Vivier , Stefano Garzarella Subject: [PATCH v3 6/6] vduse: bump version number Date: Fri, 19 Sep 2025 11:33:59 +0200 Message-ID: <20250919093359.961296-7-eperezma@redhat.com> In-Reply-To: <20250919093359.961296-1-eperezma@redhat.com> References: <20250919093359.961296-1-eperezma@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Finalize the series by advertising VDUSE API v1 support to userspace. Now that all required infrastructure for v1 (ASIDs, VQ groups, update_iotlb_v2) is in place, VDUSE devices can opt in to the new features. Signed-off-by: Eugenio P=C3=A9rez --- drivers/vdpa/vdpa_user/vduse_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vd= use_dev.c index c6c70cfd4887..68d086fc19f0 100644 --- a/drivers/vdpa/vdpa_user/vduse_dev.c +++ b/drivers/vdpa/vdpa_user/vduse_dev.c @@ -2181,7 +2181,7 @@ static long vduse_ioctl(struct file *file, unsigned i= nt cmd, break; =20 ret =3D -EINVAL; - if (api_version > VDUSE_API_VERSION) + if (api_version > VDUSE_API_VERSION_1) break; =20 ret =3D 0; @@ -2248,7 +2248,7 @@ static int vduse_open(struct inode *inode, struct fil= e *file) if (!control) return -ENOMEM; =20 - control->api_version =3D VDUSE_API_VERSION; + control->api_version =3D VDUSE_API_VERSION_1; file->private_data =3D control; =20 return 0; --=20 2.51.0