anolis: sw64: iommu: do real map on iova in 32bit mmio space

ANBZ: #4688

According to commit bf4ff7699135 ("anolis: sw64: iommu: work around iova
range check after resv_region"), the current map/unmap strategy will
directly return success, without doing real map when application
trying to use IOVA in 3.5G~4G.

This solved the problem of passing IOVA check on initiating certain
application, but what we do not expect is that VFIO will still pin
the physical memory pages for these IOVA (in 3.5~4G). It seems to work
fine during normal using. But when it comes to unmap/unpin, as VFIO
cannot find the related physical pfns through mapping tables, (because
we did not actually map them!), it will cause a 512M physical memory
leak after application exits.

The current strategy is to do real mappings for these IOVA. As for
possible collisions, we rely on OS to not initiate access requests
in this range.

Fixes: bf4ff7699135 ("anolis: sw64: iommu: work around iova range check after
resv_region")

Signed-off-by: Xu Yiwei <xuyiwei@wxiat.com>
Reviewed-by: He Sheng <hesheng@wxiat.com>
Signed-off-by: Gu Zitao <guzitao@wxiat.com>
Reviewed-by: Min Li <gumi@linux.alibaba.com>
Link: https://gitee.com/anolis/cloud-kernel/pulls/5372
This commit is contained in:
Xu Yiwei 2025-05-09 01:06:47 +00:00 committed by 小龙
parent 2bfe2539b8
commit f32648b9f7
1 changed files with 4 additions and 12 deletions

View File

@ -1433,10 +1433,6 @@ sunway_iommu_iova_to_phys(struct iommu_domain *dom, dma_addr_t iova)
unsigned long paddr, grn;
unsigned long is_last;
if ((iova > SW64_32BIT_DMA_LIMIT)
&& (iova <= DMA_BIT_MASK(32)))
return iova;
if (iova >= SW64_BAR_ADDRESS)
return iova;
@ -1515,14 +1511,14 @@ sunway_iommu_map(struct iommu_domain *dom, unsigned long iova,
* and buggy.
*
* We manage to find a compromise solution, which is allow these IOVA
* being allocated and "mapped" as usual, but with a warning issued to
* being allocated and mapped as usual, and with a warning issued to
* users at the same time. So users can quickly learn if they are using
* these "illegal" IOVA and thus change their strategies accordingly.
*/
if ((iova > SW64_32BIT_DMA_LIMIT)
if ((SW64_32BIT_DMA_LIMIT < iova + page_size)
&& (iova <= DMA_BIT_MASK(32))) {
pr_warn_once("Domain %d are using IOVA: %lx\n", sdomain->id, iova);
return 0;
pr_warn_once("process %s (pid:%d) is using domain %d with IOVA: %lx\n",
current->comm, current->pid, sdomain->id, iova);
}
/*
@ -1553,10 +1549,6 @@ sunway_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
struct sunway_iommu_domain *sdomain = to_sunway_domain(dom);
size_t unmap_size;
if ((iova > SW64_32BIT_DMA_LIMIT)
&& (iova <= DMA_BIT_MASK(32)))
return page_size;
if (iova >= SW64_BAR_ADDRESS)
return page_size;