Message ID | 1698350834-415881-1-git-send-email-steven.sistare@oracle.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:d641:0:b0:403:3b70:6f57 with SMTP id cy1csp139846vqb; Thu, 26 Oct 2023 13:07:43 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGnHIEvDJSgYAf9pXcC+4X2WHR5Dv9lro6sFc4f+1U/9T+DB8ycbPfdsvmsu54ArpJYrIcH X-Received: by 2002:a25:bf8c:0:b0:d9a:3c58:6ba9 with SMTP id l12-20020a25bf8c000000b00d9a3c586ba9mr391529ybk.44.1698350862809; Thu, 26 Oct 2023 13:07:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698350862; cv=none; d=google.com; s=arc-20160816; b=kFemBN+7kk0hV+Lxjjz4QTofkf5zSoMDO15Nm4mf6Vnx5WypGxwRc2esUdQMhB5e5w 01gfrRWFfEZAp+5uDzwue8p3iOVaIzO0qk3eu0hc7VTDWhkfDUrjuB3hIlOBVxGvNt1A /eXsX1HL3yT9Kp2PLcHU7jGP3C6Zfz0jFN2Kq7u3XVD64YclHR5C9MvkNbSJ+tpeiRWb o5vyMcNn0jFQdL75UKV4xP1m15usTOxT2KKtIXEDtYEEW9kNJSh2YZXCMN3jofsixFRr BlploN6yJaHxe2k8YDukhJ30XZ6NpgXCa0LOgiPvvbF+9oYpIYK/Wnnp9l0TkHF8zNNz YZOg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:subject:cc:to:from :dkim-signature; bh=sEJaHi8D5zE3GzzOYXpgBAdryXTBPVqu/owy7NkIqfI=; fh=qcHRDgjZkmdzeM8Sg1Q7DeUe52QosSY+H+jnNIKrwWo=; b=rtTE+8+pVK4kouODIZro8/al9040TQvpFcc6Dm76VzA2NfgUfF/QjVH+91mYrslZko FseAbap4KeY0sBe1LpodXcaM7iiWH5fza9dfymGivCm60yk2wx9qJxVDYD0YbhuGiYV0 6WJjWDH+Fu1h+F5ZsqDJBsd+9nVrJLznj9OBaILefGiDTR4fuD/mKNRnDzl7tzKAozOp WQarVctDSWQM3zQAAKj//6EFosUqpRsOqaks4MOul6+jzKZ0tRSGEbBDyOeQt4I4Qn/t UvQcTxia3b0afYmRkfGbGSFldtpyYIVNA38Pvev3qoyNolgckpXbwFjzuBBlNhyTqpiF QAGg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@oracle.com header.s=corp-2023-03-30 header.b=f5E3oVbd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=oracle.com Received: from lipwig.vger.email (lipwig.vger.email. [23.128.96.33]) by mx.google.com with ESMTPS id s71-20020a25aa4d000000b00d9940128dd1si206881ybi.738.2023.10.26.13.07.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 13:07:42 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) client-ip=23.128.96.33; Authentication-Results: mx.google.com; dkim=pass header.i=@oracle.com header.s=corp-2023-03-30 header.b=f5E3oVbd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=oracle.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by lipwig.vger.email (Postfix) with ESMTP id 52DB58292BF5; Thu, 26 Oct 2023 13:07:40 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at lipwig.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231710AbjJZUH3 (ORCPT <rfc822;aposhian.dev@gmail.com> + 26 others); Thu, 26 Oct 2023 16:07:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58074 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231397AbjJZUH1 (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 26 Oct 2023 16:07:27 -0400 Received: from mx0b-00069f02.pphosted.com (mx0b-00069f02.pphosted.com [205.220.177.32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8A0AF129 for <linux-kernel@vger.kernel.org>; Thu, 26 Oct 2023 13:07:25 -0700 (PDT) Received: from pps.filterd (m0246630.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39QJsQmQ031910; Thu, 26 Oct 2023 20:07:17 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id; s=corp-2023-03-30; bh=sEJaHi8D5zE3GzzOYXpgBAdryXTBPVqu/owy7NkIqfI=; b=f5E3oVbdb+Bs6L3GvC+k7uZ0qpc8QsbNXVFtYRt/H/V9I7ylDG78ejl+D1yf0+kh5jdM ZkGJNWBnQLrE2Oc7Ei+yy6UNneFkpt+Ev1cgkEUOpK+qn2f21y6IrDZsiUYil8MuYttP guSLCpQYOxJZQ55rjm4cOc3raIYP2xS4OFzieGqWO4vRarzXtZJMqdfhoPGEfcfDdh/X 02nBTkQoOlHo8mJD2K2kCR+pDgSKb5dP1X+OVBvOjWIw1rtac5qqmLFoe7YWXhkttOuy Ik4HKDzYrk6iscfbefqxhCOSS43sMbUTEfS1A3JVMnMKs4hvb8bbRnPW40wVGKoSBiNC Dw== Received: from iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta01.appoci.oracle.com [130.35.100.223]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3tyx2183px-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 26 Oct 2023 20:07:17 +0000 Received: from pps.filterd (iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com (8.17.1.19/8.17.1.19) with ESMTP id 39QInaQL038583; Thu, 26 Oct 2023 20:07:17 GMT Received: from pps.reinject (localhost [127.0.0.1]) by iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTPS id 3tywqs2s3k-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 26 Oct 2023 20:07:16 +0000 Received: from iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 39QK7GAX019980; Thu, 26 Oct 2023 20:07:16 GMT Received: from ca-dev63.us.oracle.com (ca-dev63.us.oracle.com [10.211.8.221]) by iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTP id 3tywqs2s2j-1; Thu, 26 Oct 2023 20:07:16 +0000 From: Steve Sistare <steven.sistare@oracle.com> To: virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org Cc: "Michael S. Tsirkin" <mst@redhat.com>, Jason Wang <jasowang@redhat.com>, Eli Cohen <elic@nvidia.com>, Si-Wei Liu <si-wei.liu@oracle.com>, Dragos Tatulea <dtatulea@nvidia.com>, Xuan Zhuo <xuanzhuo@linux.alibaba.com> Subject: [RFC] vdpa/mlx5: preserve CVQ vringh index Date: Thu, 26 Oct 2023 13:07:14 -0700 Message-Id: <1698350834-415881-1-git-send-email-steven.sistare@oracle.com> X-Mailer: git-send-email 1.8.3.1 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.987,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-26_19,2023-10-26_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxscore=0 mlxlogscore=999 suspectscore=0 malwarescore=0 adultscore=0 phishscore=0 bulkscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2310240000 definitions=main-2310260174 X-Proofpoint-ORIG-GUID: fGcPzlz4eB_nP8pm3_qJeYh123OnxEEa X-Proofpoint-GUID: fGcPzlz4eB_nP8pm3_qJeYh123OnxEEa X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lipwig.vger.email Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (lipwig.vger.email [0.0.0.0]); Thu, 26 Oct 2023 13:07:40 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780849954103928730 X-GMAIL-MSGID: 1780849954103928730 |
Series |
[RFC] vdpa/mlx5: preserve CVQ vringh index
|
|
Commit Message
Steven Sistare
Oct. 26, 2023, 8:07 p.m. UTC
mlx5_vdpa does not preserve userland's view of vring base for the control
queue in the following sequence:
ioctl VHOST_SET_VRING_BASE
ioctl VHOST_VDPA_SET_STATUS VIRTIO_CONFIG_S_DRIVER_OK
mlx5_vdpa_set_status()
setup_cvq_vring()
vringh_init_iotlb()
vringh_init_kern()
vrh->last_avail_idx = 0;
ioctl VHOST_GET_VRING_BASE
To fix, restore the value of cvq->vring.last_avail_idx after calling
vringh_init_iotlb.
Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
---
drivers/vdpa/mlx5/net/mlx5_vnet.c | 7 ++++++-
drivers/vhost/vringh.c | 30 ++++++++++++++++++++++++++++++
include/linux/vringh.h | 2 ++
3 files changed, 38 insertions(+), 1 deletion(-)
Comments
On Fri, Oct 27, 2023 at 4:07 AM Steve Sistare <steven.sistare@oracle.com> wrote: > > mlx5_vdpa does not preserve userland's view of vring base for the control > queue in the following sequence: > > ioctl VHOST_SET_VRING_BASE > ioctl VHOST_VDPA_SET_STATUS VIRTIO_CONFIG_S_DRIVER_OK > mlx5_vdpa_set_status() > setup_cvq_vring() > vringh_init_iotlb() > vringh_init_kern() > vrh->last_avail_idx = 0; > ioctl VHOST_GET_VRING_BASE > > To fix, restore the value of cvq->vring.last_avail_idx after calling > vringh_init_iotlb. > > Signed-off-by: Steve Sistare <steven.sistare@oracle.com> > --- > drivers/vdpa/mlx5/net/mlx5_vnet.c | 7 ++++++- > drivers/vhost/vringh.c | 30 ++++++++++++++++++++++++++++++ > include/linux/vringh.h | 2 ++ > 3 files changed, 38 insertions(+), 1 deletion(-) > > diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c > index 946488b8989f..f64758143115 100644 > --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c > +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c > @@ -2795,13 +2795,18 @@ static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) > struct mlx5_control_vq *cvq = &mvdev->cvq; > int err = 0; > > - if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) > + if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) { > + u16 last_avail_idx = cvq->vring.last_avail_idx; > + > err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features, > MLX5_CVQ_MAX_ENT, false, > (struct vring_desc *)(uintptr_t)cvq->desc_addr, > (struct vring_avail *)(uintptr_t)cvq->driver_addr, > (struct vring_used *)(uintptr_t)cvq->device_addr); > > + if (!err) > + vringh_set_base_iotlb(&cvq->vring, last_avail_idx); Btw, vringh_set_base_iotlb() deserves an independent patch and it seems it is not specific to IOTLB, so we probably need an indirection to have vringh_set_base() first. Or I wonder if it's better to just introduce a new parameter to vringh_init_iotlb()... Thanks > + } > return err; > } > > diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c > index 7b8fd977f71c..799762c83007 100644 > --- a/drivers/vhost/vringh.c > +++ b/drivers/vhost/vringh.c > @@ -595,6 +595,24 @@ static inline void __vringh_notify_disable(struct vringh *vrh, > } > } > > +static inline int __vringh_set_base(struct vringh *vrh, u16 idx, > + int (*putu16)(const struct vringh *vrh, > + __virtio16 *p, u16 val)) > +{ > + int ret; > + > + ret = putu16(vrh, &vrh->vring.avail->idx, idx); > + if (ret) > + return ret; > + > + ret = putu16(vrh, &vrh->vring.used->idx, idx); > + if (ret) > + return ret; > + > + vrh->last_avail_idx = vrh->last_used_idx = idx; > + return 0; > +} > + > /* Userspace access helpers: in this case, addresses are really userspace. */ > static inline int getu16_user(const struct vringh *vrh, u16 *val, const __virtio16 *p) > { > @@ -1456,6 +1474,18 @@ void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb, > } > EXPORT_SYMBOL(vringh_set_iotlb); > > +/** > + * vringh_set_base_iotlb - set avail_idx and used_idx > + * @vrh: the vring > + * @idx: the value to set > + */ > +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx) > +{ > + return __vringh_set_base(vrh, idx, putu16_iotlb); > +} > +EXPORT_SYMBOL(vringh_set_base_iotlb); > + > + > /** > * vringh_getdesc_iotlb - get next available descriptor from ring with > * IOTLB. > diff --git a/include/linux/vringh.h b/include/linux/vringh.h > index c3a8117dabe8..e9b8af4e6a5e 100644 > --- a/include/linux/vringh.h > +++ b/include/linux/vringh.h > @@ -306,6 +306,8 @@ int vringh_init_iotlb_va(struct vringh *vrh, u64 features, > struct vring_avail *avail, > struct vring_used *used); > > +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx); > + > int vringh_getdesc_iotlb(struct vringh *vrh, > struct vringh_kiov *riov, > struct vringh_kiov *wiov, > -- > 2.39.3 >
On 10/27/2023 2:31 AM, Jason Wang wrote: > On Fri, Oct 27, 2023 at 4:07 AM Steve Sistare <steven.sistare@oracle.com> wrote: >> >> mlx5_vdpa does not preserve userland's view of vring base for the control >> queue in the following sequence: >> >> ioctl VHOST_SET_VRING_BASE >> ioctl VHOST_VDPA_SET_STATUS VIRTIO_CONFIG_S_DRIVER_OK >> mlx5_vdpa_set_status() >> setup_cvq_vring() >> vringh_init_iotlb() >> vringh_init_kern() >> vrh->last_avail_idx = 0; >> ioctl VHOST_GET_VRING_BASE >> >> To fix, restore the value of cvq->vring.last_avail_idx after calling >> vringh_init_iotlb. >> >> Signed-off-by: Steve Sistare <steven.sistare@oracle.com> >> --- >> drivers/vdpa/mlx5/net/mlx5_vnet.c | 7 ++++++- >> drivers/vhost/vringh.c | 30 ++++++++++++++++++++++++++++++ >> include/linux/vringh.h | 2 ++ >> 3 files changed, 38 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c >> index 946488b8989f..f64758143115 100644 >> --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c >> +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c >> @@ -2795,13 +2795,18 @@ static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) >> struct mlx5_control_vq *cvq = &mvdev->cvq; >> int err = 0; >> >> - if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) >> + if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) { >> + u16 last_avail_idx = cvq->vring.last_avail_idx; >> + >> err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features, >> MLX5_CVQ_MAX_ENT, false, >> (struct vring_desc *)(uintptr_t)cvq->desc_addr, >> (struct vring_avail *)(uintptr_t)cvq->driver_addr, >> (struct vring_used *)(uintptr_t)cvq->device_addr); >> >> + if (!err) >> + vringh_set_base_iotlb(&cvq->vring, last_avail_idx); > > Btw, vringh_set_base_iotlb() deserves an independent patch and it > seems it is not specific to IOTLB, Agreed on both. I initially submitted the smallest change needed to show the problem. so we probably need an indirection > to have vringh_set_base() first. Not sure what you mean. I have defined: static inline int __vringh_set_base() ... int vringh_set_base_iotlb() return __vringh_set_base(vrh, idx, putu16_iotlb); to which I would add: int vringh_set_base_user() return __vringh_set_base(vrh, idx, putu16_user); int vringh_set_base_kern() return __vringh_set_base(vrh, idx, putu16_kern; all in the same patch. The call site in mlx5_vnet.c would be a 2nd patch. - Steve > Or I wonder if it's better to just introduce a new parameter to > vringh_init_iotlb()... I considered that, but IMO the parameter list there is already large, and it would be strange to add a parameter for the initial value of avail, but not for used, and no one needs the latter. - Steve >> + } >> return err; >> } >> >> diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c >> index 7b8fd977f71c..799762c83007 100644 >> --- a/drivers/vhost/vringh.c >> +++ b/drivers/vhost/vringh.c >> @@ -595,6 +595,24 @@ static inline void __vringh_notify_disable(struct vringh *vrh, >> } >> } >> >> +static inline int __vringh_set_base(struct vringh *vrh, u16 idx, >> + int (*putu16)(const struct vringh *vrh, >> + __virtio16 *p, u16 val)) >> +{ >> + int ret; >> + >> + ret = putu16(vrh, &vrh->vring.avail->idx, idx); >> + if (ret) >> + return ret; >> + >> + ret = putu16(vrh, &vrh->vring.used->idx, idx); >> + if (ret) >> + return ret; >> + >> + vrh->last_avail_idx = vrh->last_used_idx = idx; >> + return 0; >> +} >> + >> /* Userspace access helpers: in this case, addresses are really userspace. */ >> static inline int getu16_user(const struct vringh *vrh, u16 *val, const __virtio16 *p) >> { >> @@ -1456,6 +1474,18 @@ void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb, >> } >> EXPORT_SYMBOL(vringh_set_iotlb); >> >> +/** >> + * vringh_set_base_iotlb - set avail_idx and used_idx >> + * @vrh: the vring >> + * @idx: the value to set >> + */ >> +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx) >> +{ >> + return __vringh_set_base(vrh, idx, putu16_iotlb); >> +} >> +EXPORT_SYMBOL(vringh_set_base_iotlb); >> + >> + >> /** >> * vringh_getdesc_iotlb - get next available descriptor from ring with >> * IOTLB. >> diff --git a/include/linux/vringh.h b/include/linux/vringh.h >> index c3a8117dabe8..e9b8af4e6a5e 100644 >> --- a/include/linux/vringh.h >> +++ b/include/linux/vringh.h >> @@ -306,6 +306,8 @@ int vringh_init_iotlb_va(struct vringh *vrh, u64 features, >> struct vring_avail *avail, >> struct vring_used *used); >> >> +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx); >> + >> int vringh_getdesc_iotlb(struct vringh *vrh, >> struct vringh_kiov *riov, >> struct vringh_kiov *wiov, >> -- >> 2.39.3 >> >
On Thu, Oct 26, 2023 at 10:09 PM Steve Sistare <steven.sistare@oracle.com> wrote: > > mlx5_vdpa does not preserve userland's view of vring base for the control > queue in the following sequence: > > ioctl VHOST_SET_VRING_BASE > ioctl VHOST_VDPA_SET_STATUS VIRTIO_CONFIG_S_DRIVER_OK > mlx5_vdpa_set_status() > setup_cvq_vring() > vringh_init_iotlb() > vringh_init_kern() > vrh->last_avail_idx = 0; > ioctl VHOST_GET_VRING_BASE > > To fix, restore the value of cvq->vring.last_avail_idx after calling > vringh_init_iotlb. > > Signed-off-by: Steve Sistare <steven.sistare@oracle.com> > --- > drivers/vdpa/mlx5/net/mlx5_vnet.c | 7 ++++++- > drivers/vhost/vringh.c | 30 ++++++++++++++++++++++++++++++ > include/linux/vringh.h | 2 ++ > 3 files changed, 38 insertions(+), 1 deletion(-) > > diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c > index 946488b8989f..f64758143115 100644 > --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c > +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c > @@ -2795,13 +2795,18 @@ static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) > struct mlx5_control_vq *cvq = &mvdev->cvq; > int err = 0; > > - if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) > + if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) { > + u16 last_avail_idx = cvq->vring.last_avail_idx; > + > err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features, > MLX5_CVQ_MAX_ENT, false, > (struct vring_desc *)(uintptr_t)cvq->desc_addr, > (struct vring_avail *)(uintptr_t)cvq->driver_addr, > (struct vring_used *)(uintptr_t)cvq->device_addr); > > + if (!err) > + vringh_set_base_iotlb(&cvq->vring, last_avail_idx); > + } > return err; > } > > diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c > index 7b8fd977f71c..799762c83007 100644 > --- a/drivers/vhost/vringh.c > +++ b/drivers/vhost/vringh.c > @@ -595,6 +595,24 @@ static inline void __vringh_notify_disable(struct vringh *vrh, > } > } > > +static inline int __vringh_set_base(struct vringh *vrh, u16 idx, > + int (*putu16)(const struct vringh *vrh, > + __virtio16 *p, u16 val)) > +{ > + int ret; > + > + ret = putu16(vrh, &vrh->vring.avail->idx, idx); > + if (ret) > + return ret; > + > + ret = putu16(vrh, &vrh->vring.used->idx, idx); > + if (ret) > + return ret; > + I don't think VMM should be able to modify the guest's vring memory. For vringh it should be enough with the next line, no need for previous. If I'm not wrong this was solved in the simulator by [1] and [2]. Am I missing something? Thanks! [1] https://lkml.org/lkml/2023/1/18/1045 [2] https://www.spinics.net/lists/kernel/msg4705724.html > + vrh->last_avail_idx = vrh->last_used_idx = idx; > + return 0; > +} > + > /* Userspace access helpers: in this case, addresses are really userspace. */ > static inline int getu16_user(const struct vringh *vrh, u16 *val, const __virtio16 *p) > { > @@ -1456,6 +1474,18 @@ void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb, > } > EXPORT_SYMBOL(vringh_set_iotlb); > > +/** > + * vringh_set_base_iotlb - set avail_idx and used_idx > + * @vrh: the vring > + * @idx: the value to set > + */ > +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx) > +{ > + return __vringh_set_base(vrh, idx, putu16_iotlb); > +} > +EXPORT_SYMBOL(vringh_set_base_iotlb); > + > + > /** > * vringh_getdesc_iotlb - get next available descriptor from ring with > * IOTLB. > diff --git a/include/linux/vringh.h b/include/linux/vringh.h > index c3a8117dabe8..e9b8af4e6a5e 100644 > --- a/include/linux/vringh.h > +++ b/include/linux/vringh.h > @@ -306,6 +306,8 @@ int vringh_init_iotlb_va(struct vringh *vrh, u64 features, > struct vring_avail *avail, > struct vring_used *used); > > +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx); > + > int vringh_getdesc_iotlb(struct vringh *vrh, > struct vringh_kiov *riov, > struct vringh_kiov *wiov, > -- > 2.39.3 >
On 10/30/2023 11:12 AM, Eugenio Perez Martin wrote: > On Thu, Oct 26, 2023 at 10:09 PM Steve Sistare > <steven.sistare@oracle.com> wrote: >> >> mlx5_vdpa does not preserve userland's view of vring base for the control >> queue in the following sequence: >> >> ioctl VHOST_SET_VRING_BASE >> ioctl VHOST_VDPA_SET_STATUS VIRTIO_CONFIG_S_DRIVER_OK >> mlx5_vdpa_set_status() >> setup_cvq_vring() >> vringh_init_iotlb() >> vringh_init_kern() >> vrh->last_avail_idx = 0; >> ioctl VHOST_GET_VRING_BASE >> >> To fix, restore the value of cvq->vring.last_avail_idx after calling >> vringh_init_iotlb. >> >> Signed-off-by: Steve Sistare <steven.sistare@oracle.com> >> --- >> drivers/vdpa/mlx5/net/mlx5_vnet.c | 7 ++++++- >> drivers/vhost/vringh.c | 30 ++++++++++++++++++++++++++++++ >> include/linux/vringh.h | 2 ++ >> 3 files changed, 38 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c >> index 946488b8989f..f64758143115 100644 >> --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c >> +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c >> @@ -2795,13 +2795,18 @@ static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) >> struct mlx5_control_vq *cvq = &mvdev->cvq; >> int err = 0; >> >> - if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) >> + if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) { >> + u16 last_avail_idx = cvq->vring.last_avail_idx; >> + >> err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features, >> MLX5_CVQ_MAX_ENT, false, >> (struct vring_desc *)(uintptr_t)cvq->desc_addr, >> (struct vring_avail *)(uintptr_t)cvq->driver_addr, >> (struct vring_used *)(uintptr_t)cvq->device_addr); >> >> + if (!err) >> + vringh_set_base_iotlb(&cvq->vring, last_avail_idx); >> + } >> return err; >> } >> >> diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c >> index 7b8fd977f71c..799762c83007 100644 >> --- a/drivers/vhost/vringh.c >> +++ b/drivers/vhost/vringh.c >> @@ -595,6 +595,24 @@ static inline void __vringh_notify_disable(struct vringh *vrh, >> } >> } >> >> +static inline int __vringh_set_base(struct vringh *vrh, u16 idx, >> + int (*putu16)(const struct vringh *vrh, >> + __virtio16 *p, u16 val)) >> +{ >> + int ret; >> + >> + ret = putu16(vrh, &vrh->vring.avail->idx, idx); >> + if (ret) >> + return ret; >> + >> + ret = putu16(vrh, &vrh->vring.used->idx, idx); >> + if (ret) >> + return ret; >> + > > I don't think VMM should be able to modify the guest's vring memory. > For vringh it should be enough with the next line, no need for > previous. > > If I'm not wrong this was solved in the simulator by [1] and [2]. Am I > missing something? > > Thanks! > > [1] https://lkml.org/lkml/2023/1/18/1045 > [2] https://www.spinics.net/lists/kernel/msg4705724.html > >> + vrh->last_avail_idx = vrh->last_used_idx = idx; >> + return 0; >> +} >> + OK, that makes sense. I just verified that the idx I pass to vringh_set_base_iotlb does indeed match vrh->vring.avail->idx and vrh->vring.used->idx. With no need to putu16, the fix could be confined to a few lines in the mlx5 driver: setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) { idx = cvq->vring.last_avail_idx; vringh_init_iotlb(&cvq->vring, ...); cvq->vring.last_avail_idx = cvq->vring.last_used_idx = idx; } However, I wonder if re-syncing with the guest values would be a more robust fix: setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) { vringh_init_iotlb(&cvq->vring, ...); vringh_sync_iotlb(&cvq->vring); } vringh_sync_iotlb(struct vringh *vrh) { getu16_iotlb(vrh, &vrh->last_avail_idx, &vrh->vring.avail->idx); getu16_iotlb(vrh, &vrh->last_used_idx, &vrh->vring.used->idx); } - Steve >> /* Userspace access helpers: in this case, addresses are really userspace. */ >> static inline int getu16_user(const struct vringh *vrh, u16 *val, const __virtio16 *p) >> { >> @@ -1456,6 +1474,18 @@ void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb, >> } >> EXPORT_SYMBOL(vringh_set_iotlb); >> >> +/** >> + * vringh_set_base_iotlb - set avail_idx and used_idx >> + * @vrh: the vring >> + * @idx: the value to set >> + */ >> +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx) >> +{ >> + return __vringh_set_base(vrh, idx, putu16_iotlb); >> +} >> +EXPORT_SYMBOL(vringh_set_base_iotlb); >> + >> + >> /** >> * vringh_getdesc_iotlb - get next available descriptor from ring with >> * IOTLB. >> diff --git a/include/linux/vringh.h b/include/linux/vringh.h >> index c3a8117dabe8..e9b8af4e6a5e 100644 >> --- a/include/linux/vringh.h >> +++ b/include/linux/vringh.h >> @@ -306,6 +306,8 @@ int vringh_init_iotlb_va(struct vringh *vrh, u64 features, >> struct vring_avail *avail, >> struct vring_used *used); >> >> +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx); >> + >> int vringh_getdesc_iotlb(struct vringh *vrh, >> struct vringh_kiov *riov, >> struct vringh_kiov *wiov, >> -- >> 2.39.3 >> >
On Mon, Oct 30, 2023 at 6:56 PM Steven Sistare <steven.sistare@oracle.com> wrote: > > On 10/30/2023 11:12 AM, Eugenio Perez Martin wrote: > > On Thu, Oct 26, 2023 at 10:09 PM Steve Sistare > > <steven.sistare@oracle.com> wrote: > >> > >> mlx5_vdpa does not preserve userland's view of vring base for the control > >> queue in the following sequence: > >> > >> ioctl VHOST_SET_VRING_BASE > >> ioctl VHOST_VDPA_SET_STATUS VIRTIO_CONFIG_S_DRIVER_OK > >> mlx5_vdpa_set_status() > >> setup_cvq_vring() > >> vringh_init_iotlb() > >> vringh_init_kern() > >> vrh->last_avail_idx = 0; > >> ioctl VHOST_GET_VRING_BASE > >> > >> To fix, restore the value of cvq->vring.last_avail_idx after calling > >> vringh_init_iotlb. > >> > >> Signed-off-by: Steve Sistare <steven.sistare@oracle.com> > >> --- > >> drivers/vdpa/mlx5/net/mlx5_vnet.c | 7 ++++++- > >> drivers/vhost/vringh.c | 30 ++++++++++++++++++++++++++++++ > >> include/linux/vringh.h | 2 ++ > >> 3 files changed, 38 insertions(+), 1 deletion(-) > >> > >> diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c > >> index 946488b8989f..f64758143115 100644 > >> --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c > >> +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c > >> @@ -2795,13 +2795,18 @@ static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) > >> struct mlx5_control_vq *cvq = &mvdev->cvq; > >> int err = 0; > >> > >> - if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) > >> + if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) { > >> + u16 last_avail_idx = cvq->vring.last_avail_idx; > >> + > >> err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features, > >> MLX5_CVQ_MAX_ENT, false, > >> (struct vring_desc *)(uintptr_t)cvq->desc_addr, > >> (struct vring_avail *)(uintptr_t)cvq->driver_addr, > >> (struct vring_used *)(uintptr_t)cvq->device_addr); > >> > >> + if (!err) > >> + vringh_set_base_iotlb(&cvq->vring, last_avail_idx); > >> + } > >> return err; > >> } > >> > >> diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c > >> index 7b8fd977f71c..799762c83007 100644 > >> --- a/drivers/vhost/vringh.c > >> +++ b/drivers/vhost/vringh.c > >> @@ -595,6 +595,24 @@ static inline void __vringh_notify_disable(struct vringh *vrh, > >> } > >> } > >> > >> +static inline int __vringh_set_base(struct vringh *vrh, u16 idx, > >> + int (*putu16)(const struct vringh *vrh, > >> + __virtio16 *p, u16 val)) > >> +{ > >> + int ret; > >> + > >> + ret = putu16(vrh, &vrh->vring.avail->idx, idx); > >> + if (ret) > >> + return ret; > >> + > >> + ret = putu16(vrh, &vrh->vring.used->idx, idx); > >> + if (ret) > >> + return ret; > >> + > > > > I don't think VMM should be able to modify the guest's vring memory. > > For vringh it should be enough with the next line, no need for > > previous. > > > > If I'm not wrong this was solved in the simulator by [1] and [2]. Am I > > missing something? > > > > Thanks! > > > > [1] https://lkml.org/lkml/2023/1/18/1045 > > [2] https://www.spinics.net/lists/kernel/msg4705724.html > > > >> + vrh->last_avail_idx = vrh->last_used_idx = idx; > >> + return 0; > >> +} > >> + > > OK, that makes sense. I just verified that the idx I pass to vringh_set_base_iotlb > does indeed match vrh->vring.avail->idx and vrh->vring.used->idx. > > With no need to putu16, the fix could be confined to a few lines in the mlx5 driver: > > setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) { > idx = cvq->vring.last_avail_idx; > vringh_init_iotlb(&cvq->vring, ...); > cvq->vring.last_avail_idx = cvq->vring.last_used_idx = idx; > } > > However, I wonder if re-syncing with the guest values would be a more robust fix: > > setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) { > vringh_init_iotlb(&cvq->vring, ...); > vringh_sync_iotlb(&cvq->vring); > } > > vringh_sync_iotlb(struct vringh *vrh) { > getu16_iotlb(vrh, &vrh->last_avail_idx, &vrh->vring.avail->idx); This is not valid. For example in the case of the net RX queue. The guest fills it periodically with rx buffers, but the next index to use is not avail_index but the index that vhost handles internally. If any, it *could* be valid to restore both of them from used_idx, since we trust the source to sync with the used ring. But this will not be valid once we migrate inflight descriptors too. If parent drivers start just restoring used idx for both, we will need to complicate behavior of the feature flag that indicates the vDPA device supports in-flight. > getu16_iotlb(vrh, &vrh->last_used_idx, &vrh->vring.used->idx); > } > > - Steve > > >> /* Userspace access helpers: in this case, addresses are really userspace. */ > >> static inline int getu16_user(const struct vringh *vrh, u16 *val, const __virtio16 *p) > >> { > >> @@ -1456,6 +1474,18 @@ void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb, > >> } > >> EXPORT_SYMBOL(vringh_set_iotlb); > >> > >> +/** > >> + * vringh_set_base_iotlb - set avail_idx and used_idx > >> + * @vrh: the vring > >> + * @idx: the value to set > >> + */ > >> +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx) > >> +{ > >> + return __vringh_set_base(vrh, idx, putu16_iotlb); > >> +} > >> +EXPORT_SYMBOL(vringh_set_base_iotlb); > >> + > >> + > >> /** > >> * vringh_getdesc_iotlb - get next available descriptor from ring with > >> * IOTLB. > >> diff --git a/include/linux/vringh.h b/include/linux/vringh.h > >> index c3a8117dabe8..e9b8af4e6a5e 100644 > >> --- a/include/linux/vringh.h > >> +++ b/include/linux/vringh.h > >> @@ -306,6 +306,8 @@ int vringh_init_iotlb_va(struct vringh *vrh, u64 features, > >> struct vring_avail *avail, > >> struct vring_used *used); > >> > >> +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx); > >> + > >> int vringh_getdesc_iotlb(struct vringh *vrh, > >> struct vringh_kiov *riov, > >> struct vringh_kiov *wiov, > >> -- > >> 2.39.3 > >> > > >
On Mon, Oct 30, 2023 at 10:06 PM Steven Sistare <steven.sistare@oracle.com> wrote: > > On 10/27/2023 2:31 AM, Jason Wang wrote: > > On Fri, Oct 27, 2023 at 4:07 AM Steve Sistare <steven.sistare@oracle.com> wrote: > >> > >> mlx5_vdpa does not preserve userland's view of vring base for the control > >> queue in the following sequence: > >> > >> ioctl VHOST_SET_VRING_BASE > >> ioctl VHOST_VDPA_SET_STATUS VIRTIO_CONFIG_S_DRIVER_OK > >> mlx5_vdpa_set_status() > >> setup_cvq_vring() > >> vringh_init_iotlb() > >> vringh_init_kern() > >> vrh->last_avail_idx = 0; > >> ioctl VHOST_GET_VRING_BASE > >> > >> To fix, restore the value of cvq->vring.last_avail_idx after calling > >> vringh_init_iotlb. > >> > >> Signed-off-by: Steve Sistare <steven.sistare@oracle.com> > >> --- > >> drivers/vdpa/mlx5/net/mlx5_vnet.c | 7 ++++++- > >> drivers/vhost/vringh.c | 30 ++++++++++++++++++++++++++++++ > >> include/linux/vringh.h | 2 ++ > >> 3 files changed, 38 insertions(+), 1 deletion(-) > >> > >> diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c > >> index 946488b8989f..f64758143115 100644 > >> --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c > >> +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c > >> @@ -2795,13 +2795,18 @@ static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) > >> struct mlx5_control_vq *cvq = &mvdev->cvq; > >> int err = 0; > >> > >> - if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) > >> + if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) { > >> + u16 last_avail_idx = cvq->vring.last_avail_idx; > >> + > >> err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features, > >> MLX5_CVQ_MAX_ENT, false, > >> (struct vring_desc *)(uintptr_t)cvq->desc_addr, > >> (struct vring_avail *)(uintptr_t)cvq->driver_addr, > >> (struct vring_used *)(uintptr_t)cvq->device_addr); > >> > >> + if (!err) > >> + vringh_set_base_iotlb(&cvq->vring, last_avail_idx); > > > > Btw, vringh_set_base_iotlb() deserves an independent patch and it > > seems it is not specific to IOTLB, > > Agreed on both. I initially submitted the smallest change needed to show the problem. > > so we probably need an indirection > > to have vringh_set_base() first. > > Not sure what you mean. I have defined: > > static inline int __vringh_set_base() ... > > int vringh_set_base_iotlb() > return __vringh_set_base(vrh, idx, putu16_iotlb); > > to which I would add: > > int vringh_set_base_user() > return __vringh_set_base(vrh, idx, putu16_user); > > int vringh_set_base_kern() > return __vringh_set_base(vrh, idx, putu16_kern; > > all in the same patch. > > The call site in mlx5_vnet.c would be a 2nd patch. Right, so we just need to split it. > > - Steve > > > Or I wonder if it's better to just introduce a new parameter to > > vringh_init_iotlb()... > > I considered that, but IMO the parameter list there is already large, and it would > be strange to add a parameter for the initial value of avail, but not for used, and > no one needs the latter. Fine. Thanks > > - Steve > > >> + } > >> return err; > >> } > >> > >> diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c > >> index 7b8fd977f71c..799762c83007 100644 > >> --- a/drivers/vhost/vringh.c > >> +++ b/drivers/vhost/vringh.c > >> @@ -595,6 +595,24 @@ static inline void __vringh_notify_disable(struct vringh *vrh, > >> } > >> } > >> > >> +static inline int __vringh_set_base(struct vringh *vrh, u16 idx, > >> + int (*putu16)(const struct vringh *vrh, > >> + __virtio16 *p, u16 val)) > >> +{ > >> + int ret; > >> + > >> + ret = putu16(vrh, &vrh->vring.avail->idx, idx); > >> + if (ret) > >> + return ret; > >> + > >> + ret = putu16(vrh, &vrh->vring.used->idx, idx); > >> + if (ret) > >> + return ret; > >> + > >> + vrh->last_avail_idx = vrh->last_used_idx = idx; > >> + return 0; > >> +} > >> + > >> /* Userspace access helpers: in this case, addresses are really userspace. */ > >> static inline int getu16_user(const struct vringh *vrh, u16 *val, const __virtio16 *p) > >> { > >> @@ -1456,6 +1474,18 @@ void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb, > >> } > >> EXPORT_SYMBOL(vringh_set_iotlb); > >> > >> +/** > >> + * vringh_set_base_iotlb - set avail_idx and used_idx > >> + * @vrh: the vring > >> + * @idx: the value to set > >> + */ > >> +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx) > >> +{ > >> + return __vringh_set_base(vrh, idx, putu16_iotlb); > >> +} > >> +EXPORT_SYMBOL(vringh_set_base_iotlb); > >> + > >> + > >> /** > >> * vringh_getdesc_iotlb - get next available descriptor from ring with > >> * IOTLB. > >> diff --git a/include/linux/vringh.h b/include/linux/vringh.h > >> index c3a8117dabe8..e9b8af4e6a5e 100644 > >> --- a/include/linux/vringh.h > >> +++ b/include/linux/vringh.h > >> @@ -306,6 +306,8 @@ int vringh_init_iotlb_va(struct vringh *vrh, u64 features, > >> struct vring_avail *avail, > >> struct vring_used *used); > >> > >> +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx); > >> + > >> int vringh_getdesc_iotlb(struct vringh *vrh, > >> struct vringh_kiov *riov, > >> struct vringh_kiov *wiov, > >> -- > >> 2.39.3 > >> > > >
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index 946488b8989f..f64758143115 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -2795,13 +2795,18 @@ static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) struct mlx5_control_vq *cvq = &mvdev->cvq; int err = 0; - if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) + if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) { + u16 last_avail_idx = cvq->vring.last_avail_idx; + err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features, MLX5_CVQ_MAX_ENT, false, (struct vring_desc *)(uintptr_t)cvq->desc_addr, (struct vring_avail *)(uintptr_t)cvq->driver_addr, (struct vring_used *)(uintptr_t)cvq->device_addr); + if (!err) + vringh_set_base_iotlb(&cvq->vring, last_avail_idx); + } return err; } diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c index 7b8fd977f71c..799762c83007 100644 --- a/drivers/vhost/vringh.c +++ b/drivers/vhost/vringh.c @@ -595,6 +595,24 @@ static inline void __vringh_notify_disable(struct vringh *vrh, } } +static inline int __vringh_set_base(struct vringh *vrh, u16 idx, + int (*putu16)(const struct vringh *vrh, + __virtio16 *p, u16 val)) +{ + int ret; + + ret = putu16(vrh, &vrh->vring.avail->idx, idx); + if (ret) + return ret; + + ret = putu16(vrh, &vrh->vring.used->idx, idx); + if (ret) + return ret; + + vrh->last_avail_idx = vrh->last_used_idx = idx; + return 0; +} + /* Userspace access helpers: in this case, addresses are really userspace. */ static inline int getu16_user(const struct vringh *vrh, u16 *val, const __virtio16 *p) { @@ -1456,6 +1474,18 @@ void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb, } EXPORT_SYMBOL(vringh_set_iotlb); +/** + * vringh_set_base_iotlb - set avail_idx and used_idx + * @vrh: the vring + * @idx: the value to set + */ +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx) +{ + return __vringh_set_base(vrh, idx, putu16_iotlb); +} +EXPORT_SYMBOL(vringh_set_base_iotlb); + + /** * vringh_getdesc_iotlb - get next available descriptor from ring with * IOTLB. diff --git a/include/linux/vringh.h b/include/linux/vringh.h index c3a8117dabe8..e9b8af4e6a5e 100644 --- a/include/linux/vringh.h +++ b/include/linux/vringh.h @@ -306,6 +306,8 @@ int vringh_init_iotlb_va(struct vringh *vrh, u64 features, struct vring_avail *avail, struct vring_used *used); +int vringh_set_base_iotlb(struct vringh *vrh, u16 idx); + int vringh_getdesc_iotlb(struct vringh *vrh, struct vringh_kiov *riov, struct vringh_kiov *wiov,