From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 2E058A0542 for ; Thu, 13 Feb 2020 11:05:23 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 1ED3B1F28; Thu, 13 Feb 2020 11:05:23 +0100 (CET) Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [205.139.110.61]) by dpdk.org (Postfix) with ESMTP id 0D3BA11A4 for ; Thu, 13 Feb 2020 11:05:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581588319; 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; bh=LkqvBUv+slmGe/pvM5IbWWLKJr4wOoO15lhjUvYhPMM=; b=dA/0wZoOTMJU8Z2BdLIW+x0io+gsfmNulbPbDz07GWa0rCXBczLEwDUiHKHZ0bOOcTbjFv QayNiN/+qtHxprzVEKmKYvpa2rsfu5XjSKXXBa5oPOLSvYkIaFe4nVPZglnTzQgj5/wrpJ 8jilOFOAazgpekLMKQOjjTEDCRX6Grg= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-354-Yp7RBZBvOeiW5jQwL1xb3g-1; Thu, 13 Feb 2020 05:05:07 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9DDEE801E78; Thu, 13 Feb 2020 10:05:06 +0000 (UTC) Received: from amorenoz.users.ipa.redhat.com (unknown [10.36.118.173]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3057C5C1BB; Thu, 13 Feb 2020 10:04:59 +0000 (UTC) From: Adrian Moreno To: dev@dpdk.org Cc: maxime.coquelin@redhat.com, Tiwei Bie , Zhihong Wang , Adrian Moreno , stable@dpdk.org Date: Thu, 13 Feb 2020 11:04:58 +0100 Message-Id: <20200213100458.483410-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-MC-Unique: Yp7RBZBvOeiW5jQwL1xb3g-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Subject: [dpdk-stable] [PATCH] vhost: protect log addr translation in iotlb updates X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: stable-bounces@dpdk.org Sender: "stable" Currently, the log address translation only happens in the vhost-user's translate_ring_addresses(). However, the IOTLB update handler is not checking if it was mapped to re-trigger that translation. Since the log address mapping could fail, check it on iotlb updates. Also, check it on vring_translate() so we do not dirty pages if the logging address is not yet ready. Additionally, properly protect the accesses to the iotlb structures. Fixes: 657414f3788a ("vhost: protect log addr translation in iotlb updates"= ) Cc: stable@dpdk.org Signed-off-by: Adrian Moreno --- lib/librte_vhost/vhost.c | 55 +++++++++++++++++++++++++++++++++ lib/librte_vhost/vhost.h | 15 +++++++-- lib/librte_vhost/vhost_user.c | 57 +++++++++++++++-------------------- 3 files changed, 92 insertions(+), 35 deletions(-) diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c index c819a8477..442d896ef 100644 --- a/lib/librte_vhost/vhost.c +++ b/lib/librte_vhost/vhost.c @@ -353,6 +353,56 @@ free_device(struct virtio_net *dev) =09rte_free(dev); } =20 +static __rte_always_inline int +log_translate(struct virtio_net *dev, struct vhost_virtqueue *vq) +{ +=09if (likely(!(vq->ring_addrs.flags & (1 << VHOST_VRING_F_LOG)))) +=09=09return 0; + +=09vq->log_guest_addr =3D translate_log_addr(dev, vq, +=09=09=09=09=09=09vq->ring_addrs.log_guest_addr); +=09if (vq->log_guest_addr =3D=3D 0) +=09=09return -1; + +=09return 0; +} + +/* + * Converts vring log address to GPA + * If IOMMU is enabled, the log address is IOVA + * If IOMMU not enabled, the log address is already GPA + * + * Caller should have iotlb_lock read-locked + */ +uint64_t +translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq, +=09=09uint64_t log_addr) +{ +=09if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) { +=09=09const uint64_t exp_size =3D sizeof(uint64_t); +=09=09uint64_t hva, gpa; +=09=09uint64_t size =3D exp_size; + +=09=09hva =3D vhost_iova_to_vva(dev, vq, log_addr, +=09=09=09=09=09&size, VHOST_ACCESS_RW); + +=09=09if (size !=3D exp_size) +=09=09=09return 0; + +=09=09gpa =3D hva_to_gpa(dev, hva, exp_size); +=09=09if (!gpa) { +=09=09=09VHOST_LOG_CONFIG(ERR, +=09=09=09=09"VQ: Failed to find GPA for log_addr: 0x%" PRIx64 " hva: 0x%" = PRIx64 "\n", +=09=09=09=09log_addr, hva); +=09=09=09return 0; +=09=09} +=09=09return gpa; + +=09} else +=09=09return log_addr; +} + +/* Caller should have iotlb_lock read-locked */ static int vring_translate_split(struct virtio_net *dev, struct vhost_virtqueue *vq) { @@ -391,6 +441,7 @@ vring_translate_split(struct virtio_net *dev, struct vh= ost_virtqueue *vq) =09return 0; } =20 +/* Caller should have iotlb_lock read-locked */ static int vring_translate_packed(struct virtio_net *dev, struct vhost_virtqueue *vq) { @@ -437,6 +488,10 @@ vring_translate(struct virtio_net *dev, struct vhost_v= irtqueue *vq) =09=09if (vring_translate_split(dev, vq) < 0) =09=09=09return -1; =09} + +=09if (log_translate(dev, vq) < 0) +=09=09return -1; + =09vq->access_ok =3D 1; =20 =09return 0; diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h index 686ce42a2..2087d1400 100644 --- a/lib/librte_vhost/vhost.h +++ b/lib/librte_vhost/vhost.h @@ -462,14 +462,23 @@ static __rte_always_inline void vhost_log_cache_used_vring(struct virtio_net *dev, struct vhost_virtqueue = *vq, =09=09=09uint64_t offset, uint64_t len) { -=09vhost_log_cache_write(dev, vq, vq->log_guest_addr + offset, len); +=09if (unlikely(dev->features & (1ULL << VHOST_F_LOG_ALL))) { +=09=09if (unlikely(vq->log_guest_addr =3D=3D 0)) +=09=09=09return; +=09=09__vhost_log_cache_write(dev, vq, vq->log_guest_addr + offset, +=09=09=09=09=09len); +=09} } =20 static __rte_always_inline void vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq, =09=09 uint64_t offset, uint64_t len) { -=09vhost_log_write(dev, vq->log_guest_addr + offset, len); +=09if (unlikely(dev->features & (1ULL << VHOST_F_LOG_ALL))) { +=09=09if (unlikely(vq->log_guest_addr =3D=3D 0)) +=09=09=09return; +=09=09__vhost_log_write(dev, vq->log_guest_addr + offset, len); +=09} } =20 static __rte_always_inline void @@ -626,6 +635,8 @@ void *vhost_alloc_copy_ind_table(struct virtio_net *dev= , =09=09=09struct vhost_virtqueue *vq, =09=09=09uint64_t desc_addr, uint64_t desc_len); int vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq); +uint64_t translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue= *vq, +=09=09uint64_t log_addr); void vring_invalidate(struct virtio_net *dev, struct vhost_virtqueue *vq); =20 static __rte_always_inline uint64_t diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index 69b84a882..5db9f148f 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -656,13 +656,11 @@ ring_addr_to_vva(struct virtio_net *dev, struct vhost= _virtqueue *vq, { =09if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) { =09=09uint64_t vva; -=09=09uint64_t req_size =3D *size; =20 -=09=09vva =3D vhost_user_iotlb_cache_find(vq, ra, +=09=09vhost_user_iotlb_rd_lock(vq); +=09=09vva =3D vhost_iova_to_vva(dev, vq, ra, =09=09=09=09=09size, VHOST_ACCESS_RW); -=09=09if (req_size !=3D *size) -=09=09=09vhost_user_iotlb_miss(dev, (ra + *size), -=09=09=09=09=09 VHOST_ACCESS_RW); +=09=09vhost_user_iotlb_rd_unlock(vq); =20 =09=09return vva; =09} @@ -670,37 +668,16 @@ ring_addr_to_vva(struct virtio_net *dev, struct vhost= _virtqueue *vq, =09return qva_to_vva(dev, ra, size); } =20 -/* - * Converts vring log address to GPA - * If IOMMU is enabled, the log address is IOVA - * If IOMMU not enabled, the log address is already GPA - */ static uint64_t -translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq, -=09=09uint64_t log_addr) +log_addr_to_gpa(struct virtio_net *dev, struct vhost_virtqueue *vq) { -=09if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) { -=09=09const uint64_t exp_size =3D sizeof(struct vring_used) + -=09=09=09sizeof(struct vring_used_elem) * vq->size; -=09=09uint64_t hva, gpa; -=09=09uint64_t size =3D exp_size; - -=09=09hva =3D vhost_iova_to_vva(dev, vq, log_addr, -=09=09=09=09=09&size, VHOST_ACCESS_RW); -=09=09if (size !=3D exp_size) -=09=09=09return 0; +=09uint64_t log_gpa; =20 -=09=09gpa =3D hva_to_gpa(dev, hva, exp_size); -=09=09if (!gpa) { -=09=09=09VHOST_LOG_CONFIG(ERR, -=09=09=09=09"VQ: Failed to find GPA for log_addr: 0x%" PRIx64 " hva: 0x%" = PRIx64 "\n", -=09=09=09=09log_addr, hva); -=09=09=09return 0; -=09=09} -=09=09return gpa; +=09vhost_user_iotlb_rd_lock(vq); +=09log_gpa =3D translate_log_addr(dev, vq, vq->ring_addrs.log_guest_addr); +=09vhost_user_iotlb_rd_unlock(vq); =20 -=09} else -=09=09return log_addr; +=09return log_gpa; } =20 static struct virtio_net * @@ -712,7 +689,7 @@ translate_ring_addresses(struct virtio_net *dev, int vq= _index) =20 =09if (addr->flags & (1 << VHOST_VRING_F_LOG)) { =09=09vq->log_guest_addr =3D -=09=09=09translate_log_addr(dev, vq, addr->log_guest_addr); +=09=09=09log_addr_to_gpa(dev, vq); =09=09if (vq->log_guest_addr =3D=3D 0) { =09=09=09VHOST_LOG_CONFIG(DEBUG, =09=09=09=09"(%d) failed to map log_guest_addr.\n", @@ -2229,6 +2206,13 @@ is_vring_iotlb_split(struct vhost_virtqueue *vq, str= uct vhost_iotlb_msg *imsg) =09if (ra->used_user_addr < end && (ra->used_user_addr + len) > start) =09=09return 1; =20 +=09if (ra->flags & (1 << VHOST_VRING_F_LOG)) { +=09=09len =3D sizeof(uint64_t); +=09=09if (ra->log_guest_addr < end && +=09=09 (ra->log_guest_addr + len) > start) +=09=09=09return 1; +=09} + =09return 0; } =20 @@ -2254,6 +2238,13 @@ is_vring_iotlb_packed(struct vhost_virtqueue *vq, st= ruct vhost_iotlb_msg *imsg) =09if (ra->used_user_addr < end && (ra->used_user_addr + len) > start) =09=09return 1; =20 +=09if (ra->flags & (1 << VHOST_VRING_F_LOG)) { +=09=09len =3D sizeof(uint64_t); +=09=09if (ra->log_guest_addr < end && +=09=09 (ra->log_guest_addr + len) > start) +=09=09=09return 1; +=09} + =09return 0; } =20 --=20 2.24.1