Skip to content

Commit e503192

Browse files
Xu Yiweiopsiff
authored andcommitted
sw64: iommu: work around iova range check after resv_region
3.5G ~ 4G currently is seen as PCI 32-bit MEMIO space. In theory, this space should be excluded from memory space addressing (using resv_region APIs), which will leave a memory hole on the entire memory space naturally. However, some applications(especially qemu) under sunway do not support incontiguous memory allocation right now. This memory hole has to be seen as one of the valid IOVA ranges to pass VFIO validness check for qemu. In this case, CPU is still capable of allocating IOVA in this space, which is, frankly speaking, dangerous 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 users at the same time. So users can quickly learn if they are using these "illegal" IOVA and thus change their strategies accordingly. Signed-off-by: Xu Yiwei <xuyiwei@wxiat.com> Reviewed-by: He Sheng <hesheng@wxiat.com> Signed-off-by: Gu Zitao <guzitao@wxiat.com> (cherry picked from commit f4d6476)
1 parent b88b6f0 commit e503192

1 file changed

Lines changed: 59 additions & 13 deletions

File tree

drivers/iommu/sw64/iommu_v2.c

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/dma-mapping.h>
1717
#include <linux/dma-map-ops.h>
1818
#include <linux/dma-direct.h>
19+
#include <linux/iommu.h>
1920
#include <linux/iommu-helper.h>
2021
#include <linux/slab.h>
2122
#include <linux/delay.h>
@@ -431,7 +432,7 @@ set_entry_by_devid(u16 devid,
431432
dte_l2_val |= 0x1;
432433

433434
*dte_l2 = dte_l2_val;
434-
printk("device with id %d added to domain: %d with pte_root: %lx\n",
435+
pr_debug("device with id %d added to domain: %d with pte_root: %lx\n",
435436
devid, sdomain->id, dte_l2_val);
436437

437438
return 0;
@@ -1270,7 +1271,7 @@ static struct iommu_domain *sunway_iommu_domain_alloc(unsigned int type)
12701271
}
12711272

12721273
sdomain->domain.geometry.aperture_start = 0UL;
1273-
sdomain->domain.geometry.aperture_end = SW64_64BIT_DMA_LIMIT;
1274+
sdomain->domain.geometry.aperture_end = ~0UL;
12741275
sdomain->domain.geometry.force_aperture = true;
12751276
sdomain->type = IOMMU_DOMAIN_UNMANAGED;
12761277
break;
@@ -1388,9 +1389,16 @@ sunway_iommu_iova_to_phys(struct iommu_domain *dom, dma_addr_t iova)
13881389
unsigned long paddr, grn;
13891390
unsigned long is_last;
13901391

1392+
if ((iova > SW64_32BIT_DMA_LIMIT)
1393+
&& (iova <= DMA_BIT_MASK(32)))
1394+
return iova;
1395+
13911396
if (iova >= SW64_BAR_ADDRESS)
13921397
return iova;
13931398

1399+
if (iova >= MAX_IOVA_WIDTH)
1400+
return 0;
1401+
13941402
paddr = fetch_pte(sdomain, iova, PTE_LEVEL1_VAL);
13951403
if ((paddr & SW64_IOMMU_ENTRY_VALID) == 0)
13961404
return 0;
@@ -1449,21 +1457,41 @@ sunway_iommu_map(struct iommu_domain *dom, unsigned long iova,
14491457
int ret;
14501458

14511459
/*
1452-
* As VFIO cannot distinguish between normal DMA request
1453-
* and pci device BAR, check should be introduced manually
1454-
* to avoid VFIO trying to map pci config space.
1460+
* 3.5G ~ 4G currently is seen as PCI 32-bit MEMIO space. In theory,
1461+
* this space should be excluded from memory space addressing (using
1462+
* resv_region APIs), which will leave a memory hole on the entire memory
1463+
* space naturally.
1464+
*
1465+
* However, some applications(especially qemu) under sunway do not
1466+
* support incontiguous memory allocation right now. This memory
1467+
* hole has to be seen as one of the valid IOVA ranges to pass VFIO
1468+
* validness check for qemu. In this case, CPU is still capable of
1469+
* allocating IOVA in this space, which is, frankly speaking, dangerous
1470+
* and buggy.
1471+
*
1472+
* We manage to find a compromise solution, which is allow these IOVA
1473+
* being allocated and "mapped" as usual, but with a warning issued to
1474+
* users at the same time. So users can quickly learn if they are using
1475+
* these "illegal" IOVA and thus change their strategies accordingly.
14551476
*/
1456-
if (iova > IO_BASE) {
1457-
pr_err("iova %#lx is out of memory!\n", iova);
1458-
return -ENOMEM;
1477+
if ((iova > SW64_32BIT_DMA_LIMIT)
1478+
&& (iova <= DMA_BIT_MASK(32))) {
1479+
pr_warn_once("Domain %d are using IOVA: %lx\n", sdomain->id, iova);
1480+
return 0;
14591481
}
14601482

1461-
if (iova >= SW64_BAR_ADDRESS)
1483+
/*
1484+
* For the same reason, IOVA allocated from PCI dev BAR address should
1485+
* be warned as well.
1486+
*/
1487+
if (iova >= SW64_BAR_ADDRESS) {
1488+
pr_warn_once("Domain %d are using IOVA: %lx\n", sdomain->id, iova);
14621489
return 0;
1490+
}
14631491

14641492
/* IOMMU v2 supports 42 bit mapped address width*/
14651493
if (iova >= MAX_IOVA_WIDTH) {
1466-
pr_err("IOMMU cannot map provided address: %lx\n", iova);
1494+
pr_err("The IOMMU hardware cannot map provided address: %lx\n", iova);
14671495
return -EFAULT;
14681496
}
14691497

@@ -1479,13 +1507,17 @@ sunway_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
14791507
struct sunway_iommu_domain *sdomain = to_sunway_domain(dom);
14801508
size_t unmap_size;
14811509

1510+
if ((iova > SW64_32BIT_DMA_LIMIT)
1511+
&& (iova <= DMA_BIT_MASK(32)))
1512+
return page_size;
1513+
14821514
if (iova >= SW64_BAR_ADDRESS)
14831515
return page_size;
14841516

1485-
/* IOMMU v2 supports 42 bit mapped address width*/
1517+
/* IOMMU v2 supports 42 bit mapped address width */
14861518
if (iova >= MAX_IOVA_WIDTH) {
14871519
pr_err("Trying to unmap illegal IOVA : %lx\n", iova);
1488-
return -EFAULT;
1520+
return 0;
14891521
}
14901522

14911523
unmap_size = sunway_iommu_unmap_page(sdomain, iova, page_size);
@@ -1625,8 +1657,22 @@ static void sunway_iommu_get_resv_regions(struct device *dev,
16251657
struct list_head *head)
16261658
{
16271659
struct iommu_resv_region *region;
1660+
struct iommu_domain *domain;
1661+
1662+
domain = iommu_get_domain_for_dev(dev);
1663+
if (!domain)
1664+
goto do_resv;
1665+
/*
1666+
* Allow user applications have access to a contiguous memory space,
1667+
* so no reserves for unmanaged domains.
1668+
*
1669+
* See comments in map API for more detail.
1670+
*/
1671+
if (domain->type == IOMMU_DOMAIN_UNMANAGED)
1672+
return;
16281673

1629-
/* Reserve 3.5~4G for device */
1674+
do_resv:
1675+
/* Reserve 3.5~4G for MEMIO */
16301676
region = iommu_alloc_resv_region(SW64_32BIT_DMA_LIMIT,
16311677
(DMA_BIT_MASK(32) - SW64_32BIT_DMA_LIMIT),
16321678
IOMMU_NOEXEC | IOMMU_MMIO,

0 commit comments

Comments
 (0)