vhost: fix physical address mapping
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
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.
--- lib/vhost/vhost.h | 1 + lib/vhost/vhost_user.c | 116 ++++++++++++++++++++--------------------- 2 files changed, 57 insertions(+), 60 deletions(-)
lib/vhost/vhost.h +1 -0
@@ -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
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
@@ -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
@@ -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
@@ -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
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
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.
--- 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
@@ -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
@@ -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
@@ -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
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.
--- lib/vhost/vhost.h | 1 + lib/vhost/vhost_user.c | 119 ++++++++++++++++++++--------------------- 2 files changed, 58 insertions(+), 62 deletions(-)
lib/vhost/vhost.h +1 -0
@@ -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
Maxime Coquelin
AppliedRe: [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_addrnaming in the guest page struct, rename it tohost_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 mappinglib/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