[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-arm] [RFC 15/20] hw/vfio/common: Introduce vfio_dma_(un)map_ram_se
From: |
Eric Auger |
Subject: |
[Qemu-arm] [RFC 15/20] hw/vfio/common: Introduce vfio_dma_(un)map_ram_section helpers |
Date: |
Sat, 1 Sep 2018 16:23:07 +0200 |
This code is going to be duplicated soon, so let's introduce
an helper which dma (unp)maps a ram memory section.
No functional change.
Signed-off-by: Eric Auger <address@hidden>
---
hw/vfio/common.c | 198 ++++++++++++++++++++++++++-----------------
hw/vfio/trace-events | 4 +-
2 files changed, 123 insertions(+), 79 deletions(-)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 2342bccf38..a47ac63e1d 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -415,13 +415,130 @@ static VFIOGuestIOMMU
*vfio_alloc_guest_iommu(VFIOContainer *container,
return giommu;
}
+static int vfio_dma_map_ram_section(VFIOContainer *container,
+ MemoryRegionSection *section)
+{
+ VFIOHostDMAWindow *hostwin;
+ Int128 llend, llsize;
+ bool hostwin_found;
+ hwaddr iova, end;
+ void *vaddr;
+ int ret;
+
+ assert(memory_region_is_ram(section->mr));
+
+ iova = TARGET_PAGE_ALIGN(section->offset_within_address_space);
+ llend = int128_make64(section->offset_within_address_space);
+ llend = int128_add(llend, section->size);
+ llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));
+ end = int128_get64(int128_sub(llend, int128_one()));
+
+ vaddr = memory_region_get_ram_ptr(section->mr) +
+ section->offset_within_region +
+ (iova - section->offset_within_address_space);
+
+ hostwin_found = false;
+ QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {
+ if (hostwin->min_iova <= iova && end <= hostwin->max_iova) {
+ hostwin_found = true;
+ break;
+ }
+ }
+
+ if (!hostwin_found) {
+ error_report("vfio: IOMMU container %p can't map guest IOVA region"
+ " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx,
+ container, iova, end);
+ return -EFAULT;
+ }
+
+ trace_vfio_dma_map_ram(iova, end, vaddr);
+
+ llsize = int128_sub(llend, int128_make64(iova));
+
+ if (memory_region_is_ram_device(section->mr)) {
+ hwaddr pgmask = (1ULL << ctz64(hostwin->iova_pgsizes)) - 1;
+
+ if ((iova & pgmask) || (int128_get64(llsize) & pgmask)) {
+ trace_vfio_listener_region_add_no_dma_map(
+ memory_region_name(section->mr),
+ section->offset_within_address_space,
+ int128_getlo(section->size),
+ pgmask + 1);
+ return 0;
+ }
+ }
+
+ ret = vfio_dma_map(container, iova, int128_get64(llsize),
+ vaddr, section->readonly);
+ if (ret) {
+ error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
+ "0x%"HWADDR_PRIx", %p) = %d (%m)",
+ container, iova, int128_get64(llsize), vaddr, ret);
+ if (memory_region_is_ram_device(section->mr)) {
+ /* Allow unexpected mappings not to be fatal for RAM devices */
+ return 0;
+ }
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void vfio_dma_unmap_ram_section(VFIOContainer *container,
+ MemoryRegionSection *section)
+{
+ Int128 llend, llsize;
+ hwaddr iova, end;
+ bool try_unmap = true;
+ int ret;
+
+ iova = TARGET_PAGE_ALIGN(section->offset_within_address_space);
+ llend = int128_make64(section->offset_within_address_space);
+ llend = int128_add(llend, section->size);
+ llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));
+
+ if (int128_ge(int128_make64(iova), llend)) {
+ return;
+ }
+ end = int128_get64(int128_sub(llend, int128_one()));
+
+ llsize = int128_sub(llend, int128_make64(iova));
+
+ trace_vfio_dma_unmap_ram(iova, end);
+
+ if (memory_region_is_ram_device(section->mr)) {
+ hwaddr pgmask;
+ VFIOHostDMAWindow *hostwin;
+ bool hostwin_found = false;
+
+ QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {
+ if (hostwin->min_iova <= iova && end <= hostwin->max_iova) {
+ hostwin_found = true;
+ break;
+ }
+ }
+ assert(hostwin_found); /* or region_add() would have failed */
+
+ pgmask = (1ULL << ctz64(hostwin->iova_pgsizes)) - 1;
+ try_unmap = !((iova & pgmask) || (int128_get64(llsize) & pgmask));
+ }
+
+ if (try_unmap) {
+ ret = vfio_dma_unmap(container, iova, int128_get64(llsize));
+ if (ret) {
+ error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", "
+ "0x%"HWADDR_PRIx") = %d (%m)",
+ container, iova, int128_get64(llsize), ret);
+ }
+ }
+}
+
static void vfio_listener_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
VFIOContainer *container = container_of(listener, VFIOContainer, listener);
hwaddr iova, end;
- Int128 llend, llsize;
- void *vaddr;
+ Int128 llend;
int ret;
VFIOHostDMAWindow *hostwin;
bool hostwin_found;
@@ -556,41 +673,10 @@ static void vfio_listener_region_add(MemoryListener
*listener,
}
/* Here we assume that memory_region_is_ram(section->mr)==true */
-
- vaddr = memory_region_get_ram_ptr(section->mr) +
- section->offset_within_region +
- (iova - section->offset_within_address_space);
-
- trace_vfio_listener_region_add_ram(iova, end, vaddr);
-
- llsize = int128_sub(llend, int128_make64(iova));
-
- if (memory_region_is_ram_device(section->mr)) {
- hwaddr pgmask = (1ULL << ctz64(hostwin->iova_pgsizes)) - 1;
-
- if ((iova & pgmask) || (int128_get64(llsize) & pgmask)) {
- trace_vfio_listener_region_add_no_dma_map(
- memory_region_name(section->mr),
- section->offset_within_address_space,
- int128_getlo(section->size),
- pgmask + 1);
- return;
- }
- }
-
- ret = vfio_dma_map(container, iova, int128_get64(llsize),
- vaddr, section->readonly);
+ ret = vfio_dma_map_ram_section(container, section);
if (ret) {
- error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
- "0x%"HWADDR_PRIx", %p) = %d (%m)",
- container, iova, int128_get64(llsize), vaddr, ret);
- if (memory_region_is_ram_device(section->mr)) {
- /* Allow unexpected mappings not to be fatal for RAM devices */
- return;
- }
goto fail;
}
-
return;
fail:
@@ -616,10 +702,6 @@ static void vfio_listener_region_del(MemoryListener
*listener,
MemoryRegionSection *section)
{
VFIOContainer *container = container_of(listener, VFIOContainer, listener);
- hwaddr iova, end;
- Int128 llend, llsize;
- int ret;
- bool try_unmap = true;
if (vfio_listener_skipped_section(section)) {
trace_vfio_listener_region_del_skip(
@@ -664,45 +746,7 @@ static void vfio_listener_region_del(MemoryListener
*listener,
*/
}
- iova = TARGET_PAGE_ALIGN(section->offset_within_address_space);
- llend = int128_make64(section->offset_within_address_space);
- llend = int128_add(llend, section->size);
- llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));
-
- if (int128_ge(int128_make64(iova), llend)) {
- return;
- }
- end = int128_get64(int128_sub(llend, int128_one()));
-
- llsize = int128_sub(llend, int128_make64(iova));
-
- trace_vfio_listener_region_del(iova, end);
-
- if (memory_region_is_ram_device(section->mr)) {
- hwaddr pgmask;
- VFIOHostDMAWindow *hostwin;
- bool hostwin_found = false;
-
- QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {
- if (hostwin->min_iova <= iova && end <= hostwin->max_iova) {
- hostwin_found = true;
- break;
- }
- }
- assert(hostwin_found); /* or region_add() would have failed */
-
- pgmask = (1ULL << ctz64(hostwin->iova_pgsizes)) - 1;
- try_unmap = !((iova & pgmask) || (int128_get64(llsize) & pgmask));
- }
-
- if (try_unmap) {
- ret = vfio_dma_unmap(container, iova, int128_get64(llsize));
- if (ret) {
- error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", "
- "0x%"HWADDR_PRIx") = %d (%m)",
- container, iova, int128_get64(llsize), ret);
- }
- }
+ vfio_dma_unmap_ram_section(container, section);
memory_region_unref(section->mr);
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index a85e8662ea..cee49ef124 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -93,10 +93,10 @@ vfio_region_read(char *name, int index, uint64_t addr,
unsigned size, uint64_t d
vfio_iommu_map_notify(const char *op, uint64_t iova_start, uint64_t iova_end)
"iommu %s @ 0x%"PRIx64" - 0x%"PRIx64
vfio_listener_region_add_skip(uint64_t start, uint64_t end) "SKIPPING
region_add 0x%"PRIx64" - 0x%"PRIx64
vfio_listener_region_add_iommu(uint64_t start, uint64_t end) "region_add
[iommu] 0x%"PRIx64" - 0x%"PRIx64
-vfio_listener_region_add_ram(uint64_t iova_start, uint64_t iova_end, void
*vaddr) "region_add [ram] 0x%"PRIx64" - 0x%"PRIx64" [%p]"
+vfio_dma_map_ram(uint64_t iova_start, uint64_t iova_end, void *vaddr)
"region_add [ram] 0x%"PRIx64" - 0x%"PRIx64" [%p]"
vfio_listener_region_add_no_dma_map(const char *name, uint64_t iova, uint64_t
size, uint64_t page_size) "Region \"%s\" 0x%"PRIx64" size=0x%"PRIx64" is not
aligned to 0x%"PRIx64" and cannot be mapped for DMA"
vfio_listener_region_del_skip(uint64_t start, uint64_t end) "SKIPPING
region_del 0x%"PRIx64" - 0x%"PRIx64
-vfio_listener_region_del(uint64_t start, uint64_t end) "region_del 0x%"PRIx64"
- 0x%"PRIx64
+vfio_dma_unmap_ram(uint64_t start, uint64_t end) "region_del 0x%"PRIx64" -
0x%"PRIx64
vfio_disconnect_container(int fd) "close container->fd=%d"
vfio_put_group(int fd) "close group->fd=%d"
vfio_get_device(const char * name, unsigned int flags, unsigned int
num_regions, unsigned int num_irqs) "Device %s flags: %u, regions: %u, irqs: %u"
--
2.17.1
- [Qemu-arm] [RFC 00/20] vSMMUv3/pSMMUv3 2 stage VFIO integration, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 05/20] hw/arm/smmuv3: Implement get_attr API to report IOMMU_ATTR_VFIO_NESTED, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 20/20] hw/arm/smmuv3: Remove warning about unsupported MAP notifiers, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 04/20] memory: add IOMMU_ATTR_VFIO_NESTED IOMMU memory region attribute, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 19/20] vfio/pci: Always set up MSI route before enabling vectors, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 18/20] target/arm/kvm: Notifies IOMMU on MSI stage 1 binding, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 16/20] hw/vfio/common: Register specific nested mode notifiers and memory_listener, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 15/20] hw/vfio/common: Introduce vfio_dma_(un)map_ram_section helpers,
Eric Auger <=
- [Qemu-arm] [RFC 17/20] hw/vfio/common: Register MAP notifier for MSI binding, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 14/20] hw/vfio/common: Introduce vfio_alloc_guest_iommu helper, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 13/20] hw/arm/smmuv3: Notify on config changes, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 10/20] memory: Add IOMMUConfigNotifier, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 11/20] hw/arm/smmuv3: Store s1ctrptr in translation config data, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 12/20] hw/arm/smmuv3: Implement dummy replay, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 08/20] memory: Introduce IOMMUIOLTBNotifier, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 09/20] memory: rename memory_region notify_iommu, notify_one, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 07/20] hw/vfio/common: Force nested if iommu requires it, Eric Auger, 2018/09/01
- [Qemu-arm] [RFC 06/20] hw/vfio/common: Refactor container initialization, Eric Auger, 2018/09/01