Skip to contentSkip to conversation

vhost: fix physical address mapping

PATCH Superseded [email protected] 2 participants 7 messages Jan 14, 2022 – Feb 17, 2022

lore
Share & tools
lore
#0 lore raw

cover vhost: fix physical address mapping

From: Xuan Ding <[email protected]>

This patchset fixes the issue of incorrect DMA mapping in PA mode. Due to the ambiguity of host_phys_addr naming in the guest page struct, rename it to host_iova.

Xuan Ding (2):
vhost: fix physical address mapping
vhost: rename field in guest page struct

 lib/vhost/vhost.h      |  11 ++--
 lib/vhost/vhost_user.c | 130 ++++++++++++++++++++---------------------
 lib/vhost/virtio_net.c |  11 ++--
 3 files changed, 75 insertions(+), 77 deletions(-)
Signature · 1 line
2.17.1
#1 lore raw

PATCH 1/2 vhost: fix physical address mapping

From: Xuan Ding <[email protected]>

When choosing IOVA as PA mode, IOVA is likely to be discontinuous, which requires page by page mapping for DMA devices. To be consistent, this patch implements page by page mapping instead of mapping at the region granularity for both IOVA as VA and PA mode.

Fixes 7c61fa08b716 ("vhost: enable IOMMU for async vhost")
---
 lib/vhost/vhost.h      |   1 +
 lib/vhost/vhost_user.c | 116 ++++++++++++++++++++---------------------
 2 files changed, 57 insertions(+), 60 deletions(-)
lib/vhost/vhost.h +1 -0
index 7085e0885c..d246538ca5 100644
@@ -355,6 +355,7 @@ struct vring_packed_desc_event {
 struct guest_page {
 	uint64_t guest_phys_addr;
 	uint64_t host_phys_addr;
+	uint64_t host_user_addr;
 	uint64_t size;
 };
 
lib/vhost/vhost_user.c +56 -60

187 lines not on this page · raw message

Signature · 1 line
2.17.1
#2 lore raw

PATCH 2/2 vhost: rename field in guest page struct

In reply to [email protected]

From: Xuan Ding <[email protected]>

This patch renames the host_phys_addr to host_iova in guest_page struct. The host_phys_addr is iova, it depends on the DPDK IOVA mode.

---
 lib/vhost/vhost.h      | 10 +++++-----
 lib/vhost/vhost_user.c | 24 ++++++++++++------------
 lib/vhost/virtio_net.c | 11 ++++++-----
 3 files changed, 23 insertions(+), 22 deletions(-)
lib/vhost/vhost.h +5 -5
index d246538ca5..9521ae56da 100644
@@ -354,7 +354,7 @@ struct vring_packed_desc_event {
 
 struct guest_page {
 	uint64_t guest_phys_addr;
-	uint64_t host_phys_addr;
+	uint64_t host_iova;
 	uint64_t host_user_addr;
 	uint64_t size;
 };
@@ -605,13 +605,13 @@ gpa_to_first_hpa(struct virtio_net *dev, uint64_t gpa,
 			if (gpa + gpa_size <=
 					page->guest_phys_addr + page->size) {
 				return gpa - page->guest_phys_addr +
-					page->host_phys_addr;
+					page->host_iova;
 			} else if (gpa < page->guest_phys_addr +
 						page->size) {
 				*hpa_size = page->guest_phys_addr +
 					page->size - gpa;
 				return gpa - page->guest_phys_addr +
-					page->host_phys_addr;
+					page->host_iova;
 			}
 		}
 	} else {
@@ -622,13 +622,13 @@ gpa_to_first_hpa(struct virtio_net *dev, uint64_t gpa,
 				if (gpa + gpa_size <=
 					page->guest_phys_addr + page->size) {
 					return gpa - page->guest_phys_addr +
-						page->host_phys_addr;
+						page->host_iova;
 				} else if (gpa < page->guest_phys_addr +
 							page->size) {
 					*hpa_size = page->guest_phys_addr +
 						page->size - gpa;
 					return gpa - page->guest_phys_addr +
-						page->host_phys_addr;
+						page->host_iova;
 				}
 			}
 		}
lib/vhost/vhost_user.c +12 -12
index 6d888766b0..e2e56308b9 100644
@@ -154,7 +154,7 @@ async_dma_map(struct virtio_net *dev, bool do_map)
 			page = &dev->guest_pages[i];
 			ret = rte_vfio_container_dma_map(RTE_VFIO_DEFAULT_CONTAINER_FD,
 							 page->host_user_addr,
-							 page->host_phys_addr,
+							 page->host_iova,
 							 page->size);
 			if (ret) {
 				/*
@@ -182,7 +182,7 @@ async_dma_map(struct virtio_net *dev, bool do_map)
 			page = &dev->guest_pages[i];
 			ret = rte_vfio_container_dma_unmap(RTE_VFIO_DEFAULT_CONTAINER_FD,
 							   page->host_user_addr,
-							   page->host_phys_addr,
+							   page->host_iova,
 							   page->size);
 			if (ret) {
 				/* like DMA map, ignore the kernel driver case when unmap. */
@@ -977,7 +977,7 @@ vhost_user_set_vring_base(struct virtio_net **pdev,
 
 static int
 add_one_guest_page(struct virtio_net *dev, uint64_t guest_phys_addr,
-		   uint64_t host_phys_addr, uint64_t host_user_addr, uint64_t size)
+		   uint64_t host_iova, uint64_t host_user_addr, uint64_t size)
 {
 	struct guest_page *page, *last_page;
 	struct guest_page *old_pages;
@@ -998,7 +998,7 @@ add_one_guest_page(struct virtio_net *dev, uint64_t guest_phys_addr,
 	if (dev->nr_guest_pages > 0) {
 		last_page = &dev->guest_pages[dev->nr_guest_pages - 1];
 		/* merge if the two pages are continuous */
-		if (host_phys_addr == last_page->host_phys_addr + last_page->size
+		if (host_iova == last_page->host_iova + last_page->size
 		    && guest_phys_addr == last_page->guest_phys_addr + last_page->size
 		    && host_user_addr == last_page->host_user_addr + last_page->size) {
 			last_page->size += size;
@@ -1008,7 +1008,7 @@ add_one_guest_page(struct virtio_net *dev, uint64_t guest_phys_addr,
 
 	page = &dev->guest_pages[dev->nr_guest_pages++];
 	page->guest_phys_addr = guest_phys_addr;
-	page->host_phys_addr  = host_phys_addr;
+	page->host_iova  = host_iova;
 	page->host_user_addr = host_user_addr;
 	page->size = size;
 
@@ -1022,14 +1022,14 @@ add_guest_pages(struct virtio_net *dev, struct rte_vhost_mem_region *reg,
 	uint64_t reg_size = reg->size;
 	uint64_t host_user_addr  = reg->host_user_addr;
 	uint64_t guest_phys_addr = reg->guest_phys_addr;
-	uint64_t host_phys_addr;
+	uint64_t host_iova;
 	uint64_t size;
 
-	host_phys_addr = rte_mem_virt2iova((void *)(uintptr_t)host_user_addr);
+	host_iova = rte_mem_virt2iova((void *)(uintptr_t)host_user_addr);
 	size = page_size - (guest_phys_addr & (page_size - 1));
 	size = RTE_MIN(size, reg_size);
 
-	if (add_one_guest_page(dev, guest_phys_addr, host_phys_addr,
+	if (add_one_guest_page(dev, guest_phys_addr, host_iova,
 			       host_user_addr, size) < 0)
 		return -1;
 
@@ -1039,9 +1039,9 @@ add_guest_pages(struct virtio_net *dev, struct rte_vhost_mem_region *reg,
 
 	while (reg_size > 0) {
 		size = RTE_MIN(reg_size, page_size);
-		host_phys_addr = rte_mem_virt2iova((void *)(uintptr_t)
+		host_iova = rte_mem_virt2iova((void *)(uintptr_t)
 						  host_user_addr);
-		if (add_one_guest_page(dev, guest_phys_addr, host_phys_addr,
+		if (add_one_guest_page(dev, guest_phys_addr, host_iova,
 				       host_user_addr, size) < 0)
 			return -1;
 
@@ -1073,11 +1073,11 @@ dump_guest_pages(struct virtio_net *dev)
 		VHOST_LOG_CONFIG(INFO,
 			"guest physical page region %u\n"
 			"\t guest_phys_addr: %" PRIx64 "\n"
-			"\t host_phys_addr : %" PRIx64 "\n"
+			"\t host_iova      : %" PRIx64 "\n"
 			"\t size           : %" PRIx64 "\n",
 			i,
 			page->guest_phys_addr,
-			page->host_phys_addr,
+			page->host_iova,
 			page->size);
 	}
 }
lib/vhost/virtio_net.c +6 -5
index b3d954aab4..226dcc8b18 100644
@@ -870,20 +870,21 @@ async_mbuf_to_desc_seg(struct virtio_net *dev, struct vhost_virtqueue *vq,
 	struct vhost_async *async = vq->async;
 	uint64_t mapped_len;
 	uint32_t buf_offset = 0;
-	void *hpa;
+	void *host_iova;
 
 	while (cpy_len) {
-		hpa = (void *)(uintptr_t)gpa_to_first_hpa(dev,
+		host_iova = (void *)(uintptr_t)gpa_to_first_hpa(dev,
 				buf_iova + buf_offset, cpy_len, &mapped_len);
-		if (unlikely(!hpa)) {
-			VHOST_LOG_DATA(ERR, "(%d) %s: failed to get hpa.\n", dev->vid, __func__);
+		if (unlikely(!host_iova)) {
+			VHOST_LOG_DATA(ERR, "(%d) %s: failed to get host iova.\n",
+				       dev->vid, __func__);
 			return -1;
 		}
 
 		if (unlikely(async_iter_add_iovec(async,
 						(void *)(uintptr_t)rte_pktmbuf_iova_offset(m,
 							mbuf_offset),
-						hpa, (size_t)mapped_len)))
+						host_iova, (size_t)mapped_len)))
 			return -1;
 
 		cpy_len -= (uint32_t)mapped_len;
Signature · 1 line
2.17.1
#3 lore raw

v4 cover vhost: fix async address mapping

In reply to [email protected]

From: Xuan Ding <[email protected]>

This patchset fixes the issue of incorrect DMA mapping in PA mode. Due to the ambiguity of host_phys_addr naming in the guest page struct, rename it to host_iova.

v4:
* Fix the patch timezone.

v3:
* Fix some format issues.

v2:
* Change the order of patch.

Xuan Ding (2):
vhost: fix field naming in guest page struct
vhost: fix physical address mapping

 lib/vhost/vhost.h      |  11 ++--
 lib/vhost/vhost_user.c | 133 ++++++++++++++++++++---------------------
 lib/vhost/virtio_net.c |  11 ++--
 3 files changed, 76 insertions(+), 79 deletions(-)
Signature · 1 line
2.17.1
#4 lore raw

PATCH v4 1/2 vhost: fix field naming in guest page struct

From: Xuan Ding <[email protected]>

This patch renames the host_phys_addr to host_iova in guest_page struct. The host_phys_addr is iova, it depends on the DPDK IOVA mode.

Fixes e246896178e6 ("vhost: get guest/host physical address mappings")
---
 lib/vhost/vhost.h      | 10 +++++-----
 lib/vhost/vhost_user.c | 20 ++++++++++----------
 lib/vhost/virtio_net.c | 11 ++++++-----
 3 files changed, 21 insertions(+), 20 deletions(-)
lib/vhost/vhost.h +5 -5
index 1c2ee29600..ccac679c25 100644
@@ -426,7 +426,7 @@ struct vring_packed_desc_event {
 
 struct guest_page {
 	uint64_t guest_phys_addr;
-	uint64_t host_phys_addr;
+	uint64_t host_iova;
 	uint64_t size;
 };
 
@@ -689,13 +689,13 @@ gpa_to_first_hpa(struct virtio_net *dev, uint64_t gpa,
 			if (gpa + gpa_size <=
 					page->guest_phys_addr + page->size) {
 				return gpa - page->guest_phys_addr +
-					page->host_phys_addr;
+					page->host_iova;
 			} else if (gpa < page->guest_phys_addr +
 						page->size) {
 				*hpa_size = page->guest_phys_addr +
 					page->size - gpa;
 				return gpa - page->guest_phys_addr +
-					page->host_phys_addr;
+					page->host_iova;
 			}
 		}
 	} else {
@@ -706,13 +706,13 @@ gpa_to_first_hpa(struct virtio_net *dev, uint64_t gpa,
 				if (gpa + gpa_size <=
 					page->guest_phys_addr + page->size) {
 					return gpa - page->guest_phys_addr +
-						page->host_phys_addr;
+						page->host_iova;
 				} else if (gpa < page->guest_phys_addr +
 							page->size) {
 					*hpa_size = page->guest_phys_addr +
 						page->size - gpa;
 					return gpa - page->guest_phys_addr +
-						page->host_phys_addr;
+						page->host_iova;
 				}
 			}
 		}
lib/vhost/vhost_user.c +10 -10
index 1d3f89afd8..066adfb464 100644
@@ -988,7 +988,7 @@ vhost_user_set_vring_base(struct virtio_net **pdev,
 
 static int
 add_one_guest_page(struct virtio_net *dev, uint64_t guest_phys_addr,
-		   uint64_t host_phys_addr, uint64_t size)
+		   uint64_t host_iova, uint64_t size)
 {
 	struct guest_page *page, *last_page;
 	struct guest_page *old_pages;
@@ -1009,7 +1009,7 @@ add_one_guest_page(struct virtio_net *dev, uint64_t guest_phys_addr,
 	if (dev->nr_guest_pages > 0) {
 		last_page = &dev->guest_pages[dev->nr_guest_pages - 1];
 		/* merge if the two pages are continuous */
-		if (host_phys_addr == last_page->host_phys_addr +
+		if (host_iova == last_page->host_iova +
 				      last_page->size) {
 			last_page->size += size;
 			return 0;
@@ -1018,7 +1018,7 @@ add_one_guest_page(struct virtio_net *dev, uint64_t guest_phys_addr,
 
 	page = &dev->guest_pages[dev->nr_guest_pages++];
 	page->guest_phys_addr = guest_phys_addr;
-	page->host_phys_addr  = host_phys_addr;
+	page->host_iova  = host_iova;
 	page->size = size;
 
 	return 0;
@@ -1031,14 +1031,14 @@ add_guest_pages(struct virtio_net *dev, struct rte_vhost_mem_region *reg,
 	uint64_t reg_size = reg->size;
 	uint64_t host_user_addr  = reg->host_user_addr;
 	uint64_t guest_phys_addr = reg->guest_phys_addr;
-	uint64_t host_phys_addr;
+	uint64_t host_iova;
 	uint64_t size;
 
-	host_phys_addr = rte_mem_virt2iova((void *)(uintptr_t)host_user_addr);
+	host_iova = rte_mem_virt2iova((void *)(uintptr_t)host_user_addr);
 	size = page_size - (guest_phys_addr & (page_size - 1));
 	size = RTE_MIN(size, reg_size);
 
-	if (add_one_guest_page(dev, guest_phys_addr, host_phys_addr, size) < 0)
+	if (add_one_guest_page(dev, guest_phys_addr, host_iova, size) < 0)
 		return -1;
 
 	host_user_addr  += size;
@@ -1047,9 +1047,9 @@ add_guest_pages(struct virtio_net *dev, struct rte_vhost_mem_region *reg,
 
 	while (reg_size > 0) {
 		size = RTE_MIN(reg_size, page_size);
-		host_phys_addr = rte_mem_virt2iova((void *)(uintptr_t)
+		host_iova = rte_mem_virt2iova((void *)(uintptr_t)
 						  host_user_addr);
-		if (add_one_guest_page(dev, guest_phys_addr, host_phys_addr,
+		if (add_one_guest_page(dev, guest_phys_addr, host_iova,
 				size) < 0)
 			return -1;
 
@@ -1082,8 +1082,8 @@ dump_guest_pages(struct virtio_net *dev)
 				dev->ifname, i);
 		VHOST_LOG_CONFIG(INFO, "(%s)\tguest_phys_addr: %" PRIx64 "\n",
 				dev->ifname, page->guest_phys_addr);
-		VHOST_LOG_CONFIG(INFO, "(%s)\thost_phys_addr : %" PRIx64 "\n",
-				dev->ifname, page->host_phys_addr);
+		VHOST_LOG_CONFIG(INFO, "(%s)\thost_iova : %" PRIx64 "\n",
+				dev->ifname, page->host_iova);
 		VHOST_LOG_CONFIG(INFO, "(%s)\tsize           : %" PRIx64 "\n",
 				dev->ifname, page->size);
 	}
lib/vhost/virtio_net.c +6 -5
index 886e076b28..5f432b0d77 100644
@@ -1004,20 +1004,21 @@ async_mbuf_to_desc_seg(struct virtio_net *dev, struct vhost_virtqueue *vq,
 	struct vhost_async *async = vq->async;
 	uint64_t mapped_len;
 	uint32_t buf_offset = 0;
-	void *hpa;
+	void *host_iova;
 
 	while (cpy_len) {
-		hpa = (void *)(uintptr_t)gpa_to_first_hpa(dev,
+		host_iova = (void *)(uintptr_t)gpa_to_first_hpa(dev,
 				buf_iova + buf_offset, cpy_len, &mapped_len);
-		if (unlikely(!hpa)) {
-			VHOST_LOG_DATA(ERR, "(%s) %s: failed to get hpa.\n", dev->ifname, __func__);
+		if (unlikely(!host_iova)) {
+			VHOST_LOG_DATA(ERR, "(%s) %s: failed to get host iova.\n",
+				       dev->ifname, __func__);
 			return -1;
 		}
 
 		if (unlikely(async_iter_add_iovec(dev, async,
 						(void *)(uintptr_t)rte_pktmbuf_iova_offset(m,
 							mbuf_offset),
-						hpa, (size_t)mapped_len)))
+						host_iova, (size_t)mapped_len)))
 			return -1;
 
 		cpy_len -= (uint32_t)mapped_len;
Signature · 1 line
2.17.1
#5 lore raw

PATCH v4 2/2 vhost: fix physical address mapping

In reply to [email protected]

From: Xuan Ding <[email protected]>

When choosing IOVA as PA mode, IOVA is likely to be discontinuous, which requires page by page mapping for DMA devices. To be consistent, this patch implements page by page mapping instead of mapping at the region granularity for both IOVA as VA and PA mode.

Fixes 7c61fa08b716 ("vhost: enable IOMMU for async vhost")
---
 lib/vhost/vhost.h      |   1 +
 lib/vhost/vhost_user.c | 119 ++++++++++++++++++++---------------------
 2 files changed, 58 insertions(+), 62 deletions(-)
lib/vhost/vhost.h +1 -0
index ccac679c25..21e1866a52 100644
@@ -427,6 +427,7 @@ struct vring_packed_desc_event {
 struct guest_page {
 	uint64_t guest_phys_addr;
 	uint64_t host_iova;
+	uint64_t host_user_addr;
 	uint64_t size;
 };
 
lib/vhost/vhost_user.c +57 -62

197 lines not on this page · raw message

Signature · 1 line
2.17.1
#6 lore raw

Re: [PATCH v4 0/2] vhost: fix async address mapping

In reply to [email protected]
Quoted 15 lines · On 2/16/22 03:28, [email protected] wrote:

From: Xuan Ding <[email protected]>

This patchset fixes the issue of incorrect DMA mapping in PA mode. Due to the ambiguity of host_phys_addr naming in the guest page struct, rename it to host_iova.

v4:
* Fix the patch timezone.

v3:
* Fix some format issues.

v2:
* Change the order of patch.

Quoted 9 lines

Xuan Ding (2):
vhost: fix field naming in guest page struct
vhost: fix physical address mapping

  lib/vhost/vhost.h      |  11 ++--
  lib/vhost/vhost_user.c | 133 ++++++++++++++++++++---------------------
  lib/vhost/virtio_net.c |  11 ++--
  3 files changed, 76 insertions(+), 79 deletions(-)

Applied to dpdk-next-virtio/main.

Thanks,
Maxime