| @@ -62,6 +62,7 @@ MODULE_PARM_DESC(dma_entry_limit, · 61 unmodified lines |
| 62 | | 62 | |
| 63 | struct vfio_iommu { | 63 | struct vfio_iommu { |
| 64 | struct list_head domain_list; | 64 | struct list_head domain_list; |
| | 65 | struct list_head iova_list; |
| 65 | struct vfio_domain *external_domain; /* domain for external user */ | 66 | struct vfio_domain *external_domain; /* domain for external user */ |
| 66 | struct mutex lock; | 67 | struct mutex lock; |
| 67 | struct rb_root dma_list; | 68 | struct rb_root dma_list; |
| @@ -97,6 +98,12 @@ struct vfio_group { · 29 unmodified lines |
| 97 | bool mdev_group; /* An mdev group */ | 98 | bool mdev_group; /* An mdev group */ |
| 98 | }; | 99 | }; |
| 99 | | 100 | |
| | 101 | struct vfio_iova { |
| | 102 | struct list_head list; |
| | 103 | dma_addr_t start; |
| | 104 | dma_addr_t end; |
| | 105 | }; |
| | 106 | |
| 100 | /* | 107 | /* |
| 101 | * Guest RAM pinning working set or DMA target | 108 | * Guest RAM pinning working set or DMA target |
| 102 | */ | 109 | */ |
| @@ -1031,6 +1038,27 @@ static int vfio_pin_map_dma(struct vfio_iommu *iommu, struct vfio_dma *dma, · 928 unmodified lines |
| 1031 | return ret; | 1038 | return ret; |
| 1032 | } | 1039 | } |
| 1033 | | 1040 | |
| | 1041 | /* |
| | 1042 | * Check dma map request is within a valid iova range |
| | 1043 | */ |
| | 1044 | static bool vfio_iommu_iova_dma_valid(struct vfio_iommu *iommu, |
| | 1045 | dma_addr_t start, dma_addr_t end) |
| | 1046 | { |
| | 1047 | struct list_head *iova = &iommu->iova_list; |
| | 1048 | struct vfio_iova *node; |
| | 1049 | |
| | 1050 | list_for_each_entry(node, iova, list) { |
| | 1051 | if (start >= node->start && end <= node->end) |
| | 1052 | return true; |
| | 1053 | } |
| | 1054 | |
| | 1055 | /* |
| | 1056 | * Check for list_empty() as well since a container with |
| | 1057 | * a single mdev device will have an empty list. |
| | 1058 | */ |
| | 1059 | return list_empty(iova); |
| | 1060 | } |
| | 1061 | |
| 1034 | static int vfio_dma_do_map(struct vfio_iommu *iommu, | 1062 | static int vfio_dma_do_map(struct vfio_iommu *iommu, |
| 1035 | struct vfio_iommu_type1_dma_map *map) | 1063 | struct vfio_iommu_type1_dma_map *map) |
| 1036 | { | 1064 | { |
| @@ -1074,6 +1102,11 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, · 37 unmodified lines |
| 1074 | goto out_unlock; | 1102 | goto out_unlock; |
| 1075 | } | 1103 | } |
| 1076 | | 1104 | |
| | 1105 | if (!vfio_iommu_iova_dma_valid(iommu, iova, iova + size - 1)) { |
| | 1106 | ret = -EINVAL; |
| | 1107 | goto out_unlock; |
| | 1108 | } |
| | 1109 | |
| 1077 | dma = kzalloc(sizeof(*dma), GFP_KERNEL); | 1110 | dma = kzalloc(sizeof(*dma), GFP_KERNEL); |
| 1078 | if (!dma) { | 1111 | if (!dma) { |
| 1079 | ret = -ENOMEM; | 1112 | ret = -ENOMEM; |
| @@ -1263,15 +1296,13 @@ static struct vfio_group *find_iommu_group(struct vfio_domain *domain, · 183 unmodified lines |
| 1263 | return NULL; | 1296 | return NULL; |
| 1264 | } | 1297 | } |
| 1265 | | 1298 | |
| 1266 | static bool vfio_iommu_has_sw_msi(struct iommu_group *group, phys_addr_t *base) | 1299 | static bool vfio_iommu_has_sw_msi(struct list_head *group_resv_regions, |
| | 1300 | phys_addr_t *base) |
| 1267 | { | 1301 | { |
| 1268 | struct list_head group_resv_regions; | 1302 | struct iommu_resv_region *region; |
| 1269 | struct iommu_resv_region *region, *next; | | |
| 1270 | bool ret = false; | 1303 | bool ret = false; |
| 1271 | | 1304 | |
| 1272 | INIT_LIST_HEAD(&group_resv_regions); | 1305 | list_for_each_entry(region, group_resv_regions, list) { |
| 1273 | iommu_get_group_resv_regions(group, &group_resv_regions); | | |
| 1274 | list_for_each_entry(region, &group_resv_regions, list) { | | |
| 1275 | /* | 1306 | /* |
| 1276 | * The presence of any 'real' MSI regions should take | 1307 | * The presence of any 'real' MSI regions should take |
| 1277 | * precedence over the software-managed one if the | 1308 | * precedence over the software-managed one if the |
| @@ -1287,8 +1318,7 @@ static bool vfio_iommu_has_sw_msi(struct iommu_group *group, phys_addr_t *base) · 9 unmodified lines |
| 1287 | ret = true; | 1318 | ret = true; |
| 1288 | } | 1319 | } |
| 1289 | } | 1320 | } |
| 1290 | list_for_each_entry_safe(region, next, &group_resv_regions, list) | 1321 | |
| 1291 | kfree(region); | | |
| 1292 | return ret; | 1322 | return ret; |
| 1293 | } | 1323 | } |
| 1294 | | 1324 | |
| @@ -1388,6 +1418,228 @@ static int vfio_mdev_iommu_device(struct device *dev, void *data) · 93 unmodified lines |
| 1388 | return 0; | 1418 | return 0; |
| 1389 | } | 1419 | } |
| 1390 | | 1420 | |
| | 1421 | /* |
| | 1422 | * This is a helper function to insert an address range to iova list. |
| | 1423 | * The list is initially created with a single entry corresponding to |
| | 1424 | * the IOMMU domain geometry to which the device group is attached. |
| | 1425 | * The list aperture gets modified when a new domain is added to the |
| | 1426 | * container if the new aperture doesn't conflict with the current one |
| | 1427 | * or with any existing dma mappings. The list is also modified to |
| | 1428 | * exclude any reserved regions associated with the device group. |
| | 1429 | */ |
| | 1430 | static int vfio_iommu_iova_insert(struct list_head *head, |
| | 1431 | dma_addr_t start, dma_addr_t end) |
| | 1432 | { |
| | 1433 | struct vfio_iova *region; |
| | 1434 | |
| | 1435 | region = kmalloc(sizeof(*region), GFP_KERNEL); |
| | 1436 | if (!region) |
| | 1437 | return -ENOMEM; |
| | 1438 | |
| | 1439 | INIT_LIST_HEAD(®ion->list); |
| | 1440 | region->start = start; |
| | 1441 | region->end = end; |
| | 1442 | |
| | 1443 | list_add_tail(®ion->list, head); |
| | 1444 | return 0; |
| | 1445 | } |
| | 1446 | |
| | 1447 | /* |
| | 1448 | * Check the new iommu aperture conflicts with existing aper or with any |
| | 1449 | * existing dma mappings. |
| | 1450 | */ |
| | 1451 | static bool vfio_iommu_aper_conflict(struct vfio_iommu *iommu, |
| | 1452 | dma_addr_t start, dma_addr_t end) |
| | 1453 | { |
| | 1454 | struct vfio_iova *first, *last; |
| | 1455 | struct list_head *iova = &iommu->iova_list; |
| | 1456 | |
| | 1457 | if (list_empty(iova)) |
| | 1458 | return false; |
| | 1459 | |
| | 1460 | /* Disjoint sets, return conflict */ |
| | 1461 | first = list_first_entry(iova, struct vfio_iova, list); |
| | 1462 | last = list_last_entry(iova, struct vfio_iova, list); |
| | 1463 | if (start > last->end || end < first->start) |
| | 1464 | return true; |
| | 1465 | |
| | 1466 | /* Check for any existing dma mappings below the new start */ |
| | 1467 | if (start > first->start) { |
| | 1468 | if (vfio_find_dma(iommu, first->start, start - first->start)) |
| | 1469 | return true; |
| | 1470 | } |
| | 1471 | |
| | 1472 | /* Check for any existing dma mappings beyond the new end */ |
| | 1473 | if (end < last->end) { |
| | 1474 | if (vfio_find_dma(iommu, end + 1, last->end - end)) |
| | 1475 | return true; |
| | 1476 | } |
| | 1477 | |
| | 1478 | return false; |
| | 1479 | } |
| | 1480 | |
| | 1481 | /* |
| | 1482 | * Resize iommu iova aperture window. This is called only if the new |
| | 1483 | * aperture has no conflict with existing aperture and dma mappings. |
| | 1484 | */ |
| | 1485 | static int vfio_iommu_aper_resize(struct list_head *iova, |
| | 1486 | dma_addr_t start, dma_addr_t end) |
| | 1487 | { |
| | 1488 | struct vfio_iova *node, *next; |
| | 1489 | |
| | 1490 | if (list_empty(iova)) |
| | 1491 | return vfio_iommu_iova_insert(iova, start, end); |
| | 1492 | |
| | 1493 | /* Adjust iova list start */ |
| | 1494 | list_for_each_entry_safe(node, next, iova, list) { |
| | 1495 | if (start < node->start) |
| | 1496 | break; |
| | 1497 | if (start >= node->start && start < node->end) { |
| | 1498 | node->start = start; |
| | 1499 | break; |
| | 1500 | } |
| | 1501 | /* Delete nodes before new start */ |
| | 1502 | list_del(&node->list); |
| | 1503 | kfree(node); |
| | 1504 | } |
| | 1505 | |
| | 1506 | /* Adjust iova list end */ |
| | 1507 | list_for_each_entry_safe(node, next, iova, list) { |
| | 1508 | if (end > node->end) |
| | 1509 | continue; |
| | 1510 | if (end > node->start && end <= node->end) { |
| | 1511 | node->end = end; |
| | 1512 | continue; |
| | 1513 | } |
| | 1514 | /* Delete nodes after new end */ |
| | 1515 | list_del(&node->list); |
| | 1516 | kfree(node); |
| | 1517 | } |
| | 1518 | |
| | 1519 | return 0; |
| | 1520 | } |
| | 1521 | |
| | 1522 | /* |
| | 1523 | * Check reserved region conflicts with existing dma mappings |
| | 1524 | */ |
| | 1525 | static bool vfio_iommu_resv_conflict(struct vfio_iommu *iommu, |
| | 1526 | struct list_head *resv_regions) |
| | 1527 | { |
| | 1528 | struct iommu_resv_region *region; |
| | 1529 | |
| | 1530 | /* Check for conflict with existing dma mappings */ |
| | 1531 | list_for_each_entry(region, resv_regions, list) { |
| | 1532 | if (region->type == IOMMU_RESV_DIRECT_RELAXABLE) |
| | 1533 | continue; |
| | 1534 | |
| | 1535 | if (vfio_find_dma(iommu, region->start, region->length)) |
| | 1536 | return true; |
| | 1537 | } |
| | 1538 | |
| | 1539 | return false; |
| | 1540 | } |
| | 1541 | |
| | 1542 | /* |
| | 1543 | * Check iova region overlap with reserved regions and |
| | 1544 | * exclude them from the iommu iova range |
| | 1545 | */ |
| | 1546 | static int vfio_iommu_resv_exclude(struct list_head *iova, |
| | 1547 | struct list_head *resv_regions) |
| | 1548 | { |
| | 1549 | struct iommu_resv_region *resv; |
| | 1550 | struct vfio_iova *n, *next; |
| | 1551 | |
| | 1552 | list_for_each_entry(resv, resv_regions, list) { |
| | 1553 | phys_addr_t start, end; |
| | 1554 | |
| | 1555 | if (resv->type == IOMMU_RESV_DIRECT_RELAXABLE) |
| | 1556 | continue; |
| | 1557 | |
| | 1558 | start = resv->start; |
| | 1559 | end = resv->start + resv->length - 1; |
| | 1560 | |
| | 1561 | list_for_each_entry_safe(n, next, iova, list) { |
| | 1562 | int ret = 0; |
| | 1563 | |
| | 1564 | /* No overlap */ |
| | 1565 | if (start > n->end || end < n->start) |
| | 1566 | continue; |
| | 1567 | /* |
| | 1568 | * Insert a new node if current node overlaps with the |
| | 1569 | * reserve region to exlude that from valid iova range. |
| | 1570 | * Note that, new node is inserted before the current |
| | 1571 | * node and finally the current node is deleted keeping |
| | 1572 | * the list updated and sorted. |
| | 1573 | */ |
| | 1574 | if (start > n->start) |
| | 1575 | ret = vfio_iommu_iova_insert(&n->list, n->start, |
| | 1576 | start - 1); |
| | 1577 | if (!ret && end < n->end) |
| | 1578 | ret = vfio_iommu_iova_insert(&n->list, end + 1, |
| | 1579 | n->end); |
| | 1580 | if (ret) |
| | 1581 | return ret; |
| | 1582 | |
| | 1583 | list_del(&n->list); |
| | 1584 | kfree(n); |
| | 1585 | } |
| | 1586 | } |
| | 1587 | |
| | 1588 | if (list_empty(iova)) |
| | 1589 | return -EINVAL; |
| | 1590 | |
| | 1591 | return 0; |
| | 1592 | } |
| | 1593 | |
| | 1594 | static void vfio_iommu_resv_free(struct list_head *resv_regions) |
| | 1595 | { |
| | 1596 | struct iommu_resv_region *n, *next; |
| | 1597 | |
| | 1598 | list_for_each_entry_safe(n, next, resv_regions, list) { |
| | 1599 | list_del(&n->list); |
| | 1600 | kfree(n); |
| | 1601 | } |
| | 1602 | } |
| | 1603 | |
| | 1604 | static void vfio_iommu_iova_free(struct list_head *iova) |
| | 1605 | { |
| | 1606 | struct vfio_iova *n, *next; |
| | 1607 | |
| | 1608 | list_for_each_entry_safe(n, next, iova, list) { |
| | 1609 | list_del(&n->list); |
| | 1610 | kfree(n); |
| | 1611 | } |
| | 1612 | } |
| | 1613 | |
| | 1614 | static int vfio_iommu_iova_get_copy(struct vfio_iommu *iommu, |
| | 1615 | struct list_head *iova_copy) |
| | 1616 | { |
| | 1617 | struct list_head *iova = &iommu->iova_list; |
| | 1618 | struct vfio_iova *n; |
| | 1619 | int ret; |
| | 1620 | |
| | 1621 | list_for_each_entry(n, iova, list) { |
| | 1622 | ret = vfio_iommu_iova_insert(iova_copy, n->start, n->end); |
| | 1623 | if (ret) |
| | 1624 | goto out_free; |
| | 1625 | } |
| | 1626 | |
| | 1627 | return 0; |
| | 1628 | |
| | 1629 | out_free: |
| | 1630 | vfio_iommu_iova_free(iova_copy); |
| | 1631 | return ret; |
| | 1632 | } |
| | 1633 | |
| | 1634 | static void vfio_iommu_iova_insert_copy(struct vfio_iommu *iommu, |
| | 1635 | struct list_head *iova_copy) |
| | 1636 | { |
| | 1637 | struct list_head *iova = &iommu->iova_list; |
| | 1638 | |
| | 1639 | vfio_iommu_iova_free(iova); |
| | 1640 | |
| | 1641 | list_splice_tail(iova_copy, iova); |
| | 1642 | } |
| 1391 | static int vfio_iommu_type1_attach_group(void *iommu_data, | 1643 | static int vfio_iommu_type1_attach_group(void *iommu_data, |
| 1392 | struct iommu_group *iommu_group) | 1644 | struct iommu_group *iommu_group) |
| 1393 | { | 1645 | { |
| @@ -1398,6 +1650,9 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, · 4 unmodified lines |
| 1398 | int ret; | 1650 | int ret; |
| 1399 | bool resv_msi, msi_remap; | 1651 | bool resv_msi, msi_remap; |
| 1400 | phys_addr_t resv_msi_base; | 1652 | phys_addr_t resv_msi_base; |
| | 1653 | struct iommu_domain_geometry geo; |
| | 1654 | LIST_HEAD(iova_copy); |
| | 1655 | LIST_HEAD(group_resv_regions); |
| 1401 | | 1656 | |
| 1402 | mutex_lock(&iommu->lock); | 1657 | mutex_lock(&iommu->lock); |
| 1403 | | 1658 | |
| @@ -1474,7 +1729,43 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, · 70 unmodified lines |
| 1474 | if (ret) | 1729 | if (ret) |
| 1475 | goto out_domain; | 1730 | goto out_domain; |
| 1476 | | 1731 | |
| 1477 | resv_msi = vfio_iommu_has_sw_msi(iommu_group, &resv_msi_base); | 1732 | /* Get aperture info */ |
| | 1733 | iommu_domain_get_attr(domain->domain, DOMAIN_ATTR_GEOMETRY, &geo); |
| | 1734 | |
| | 1735 | if (vfio_iommu_aper_conflict(iommu, geo.aperture_start, |
| | 1736 | geo.aperture_end)) { |
| | 1737 | ret = -EINVAL; |
| | 1738 | goto out_detach; |
| | 1739 | } |
| | 1740 | |
| | 1741 | ret = iommu_get_group_resv_regions(iommu_group, &group_resv_regions); |
| | 1742 | if (ret) |
| | 1743 | goto out_detach; |
| | 1744 | |
| | 1745 | if (vfio_iommu_resv_conflict(iommu, &group_resv_regions)) { |
| | 1746 | ret = -EINVAL; |
| | 1747 | goto out_detach; |
| | 1748 | } |
| | 1749 | |
| | 1750 | /* |
| | 1751 | * We don't want to work on the original iova list as the list |
| | 1752 | * gets modified and in case of failure we have to retain the |
| | 1753 | * original list. Get a copy here. |
| | 1754 | */ |
| | 1755 | ret = vfio_iommu_iova_get_copy(iommu, &iova_copy); |
| | 1756 | if (ret) |
| | 1757 | goto out_detach; |
| | 1758 | |
| | 1759 | ret = vfio_iommu_aper_resize(&iova_copy, geo.aperture_start, |
| | 1760 | geo.aperture_end); |
| | 1761 | if (ret) |
| | 1762 | goto out_detach; |
| | 1763 | |
| | 1764 | ret = vfio_iommu_resv_exclude(&iova_copy, &group_resv_regions); |
| | 1765 | if (ret) |
| | 1766 | goto out_detach; |
| | 1767 | |
| | 1768 | resv_msi = vfio_iommu_has_sw_msi(&group_resv_regions, &resv_msi_base); |
| 1478 | | 1769 | |
| 1479 | INIT_LIST_HEAD(&domain->group_list); | 1770 | INIT_LIST_HEAD(&domain->group_list); |
| 1480 | list_add(&group->next, &domain->group_list); | 1771 | list_add(&group->next, &domain->group_list); |
| @@ -1507,8 +1798,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, · 26 unmodified lines |
| 1507 | list_add(&group->next, &d->group_list); | 1798 | list_add(&group->next, &d->group_list); |
| 1508 | iommu_domain_free(domain->domain); | 1799 | iommu_domain_free(domain->domain); |
| 1509 | kfree(domain); | 1800 | kfree(domain); |
| 1510 | mutex_unlock(&iommu->lock); | 1801 | goto done; |
| 1511 | return 0; | | |
| 1512 | } | 1802 | } |
| 1513 | | 1803 | |
| 1514 | ret = vfio_iommu_attach_group(domain, group); | 1804 | ret = vfio_iommu_attach_group(domain, group); |
| @@ -1531,8 +1821,11 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, · 16 unmodified lines |
| 1531 | } | 1821 | } |
| 1532 | | 1822 | |
| 1533 | list_add(&domain->next, &iommu->domain_list); | 1823 | list_add(&domain->next, &iommu->domain_list); |
| 1534 | | 1824 | done: |
| | 1825 | /* Delete the old one and insert new iova list */ |
| | 1826 | vfio_iommu_iova_insert_copy(iommu, &iova_copy); |
| 1535 | mutex_unlock(&iommu->lock); | 1827 | mutex_unlock(&iommu->lock); |
| | 1828 | vfio_iommu_resv_free(&group_resv_regions); |
| 1536 | | 1829 | |
| 1537 | return 0; | 1830 | return 0; |
| 1538 | | 1831 | |
| @@ -1540,6 +1833,8 @@ out_detach: · 1 unmodified line |
| 1540 | vfio_iommu_detach_group(domain, group); | 1833 | vfio_iommu_detach_group(domain, group); |
| 1541 | out_domain: | 1834 | out_domain: |
| 1542 | iommu_domain_free(domain->domain); | 1835 | iommu_domain_free(domain->domain); |
| | 1836 | vfio_iommu_iova_free(&iova_copy); |
| | 1837 | vfio_iommu_resv_free(&group_resv_regions); |
| 1543 | out_free: | 1838 | out_free: |
| 1544 | kfree(domain); | 1839 | kfree(domain); |
| 1545 | kfree(group); | 1840 | kfree(group); |
| @@ -1595,12 +1890,93 @@ static void vfio_sanity_check_pfn_list(struct vfio_iommu *iommu) · 49 unmodified lines |
| 1595 | WARN_ON(iommu->notifier.head); | 1890 | WARN_ON(iommu->notifier.head); |
| 1596 | } | 1891 | } |
| 1597 | | 1892 | |
| | 1893 | /* |
| | 1894 | * Called when a domain is removed in detach. It is possible that |
| | 1895 | * the removed domain decided the iova aperture window. Modify the |
| | 1896 | * iova aperture with the smallest window among existing domains. |
| | 1897 | */ |
| | 1898 | static void vfio_iommu_aper_expand(struct vfio_iommu *iommu, |
| | 1899 | struct list_head *iova_copy) |
| | 1900 | { |
| | 1901 | struct vfio_domain *domain; |
| | 1902 | struct iommu_domain_geometry geo; |
| | 1903 | struct vfio_iova *node; |
| | 1904 | dma_addr_t start = 0; |
| | 1905 | dma_addr_t end = (dma_addr_t)~0; |
| | 1906 | |
| | 1907 | if (list_empty(iova_copy)) |
| | 1908 | return; |
| | 1909 | |
| | 1910 | list_for_each_entry(domain, &iommu->domain_list, next) { |
| | 1911 | iommu_domain_get_attr(domain->domain, DOMAIN_ATTR_GEOMETRY, |
| | 1912 | &geo); |
| | 1913 | if (geo.aperture_start > start) |
| | 1914 | start = geo.aperture_start; |
| | 1915 | if (geo.aperture_end < end) |
| | 1916 | end = geo.aperture_end; |
| | 1917 | } |
| | 1918 | |
| | 1919 | /* Modify aperture limits. The new aper is either same or bigger */ |
| | 1920 | node = list_first_entry(iova_copy, struct vfio_iova, list); |
| | 1921 | node->start = start; |
| | 1922 | node = list_last_entry(iova_copy, struct vfio_iova, list); |
| | 1923 | node->end = end; |
| | 1924 | } |
| | 1925 | |
| | 1926 | /* |
| | 1927 | * Called when a group is detached. The reserved regions for that |
| | 1928 | * group can be part of valid iova now. But since reserved regions |
| | 1929 | * may be duplicated among groups, populate the iova valid regions |
| | 1930 | * list again. |
| | 1931 | */ |
| | 1932 | static int vfio_iommu_resv_refresh(struct vfio_iommu *iommu, |
| | 1933 | struct list_head *iova_copy) |
| | 1934 | { |
| | 1935 | struct vfio_domain *d; |
| | 1936 | struct vfio_group *g; |
| | 1937 | struct vfio_iova *node; |
| | 1938 | dma_addr_t start, end; |
| | 1939 | LIST_HEAD(resv_regions); |
| | 1940 | int ret; |
| | 1941 | |
| | 1942 | if (list_empty(iova_copy)) |
| | 1943 | return -EINVAL; |
| | 1944 | |
| | 1945 | list_for_each_entry(d, &iommu->domain_list, next) { |
| | 1946 | list_for_each_entry(g, &d->group_list, next) { |
| | 1947 | ret = iommu_get_group_resv_regions(g->iommu_group, |
| | 1948 | &resv_regions); |
| | 1949 | if (ret) |
| | 1950 | goto done; |
| | 1951 | } |
| | 1952 | } |
| | 1953 | |
| | 1954 | node = list_first_entry(iova_copy, struct vfio_iova, list); |
| | 1955 | start = node->start; |
| | 1956 | node = list_last_entry(iova_copy, struct vfio_iova, list); |
| | 1957 | end = node->end; |
| | 1958 | |
| | 1959 | /* purge the iova list and create new one */ |
| | 1960 | vfio_iommu_iova_free(iova_copy); |
| | 1961 | |
| | 1962 | ret = vfio_iommu_aper_resize(iova_copy, start, end); |
| | 1963 | if (ret) |
| | 1964 | goto done; |
| | 1965 | |
| | 1966 | /* Exclude current reserved regions from iova ranges */ |
| | 1967 | ret = vfio_iommu_resv_exclude(iova_copy, &resv_regions); |
| | 1968 | done: |
| | 1969 | vfio_iommu_resv_free(&resv_regions); |
| | 1970 | return ret; |
| | 1971 | } |
| | 1972 | |
| 1598 | static void vfio_iommu_type1_detach_group(void *iommu_data, | 1973 | static void vfio_iommu_type1_detach_group(void *iommu_data, |
| 1599 | struct iommu_group *iommu_group) | 1974 | struct iommu_group *iommu_group) |
| 1600 | { | 1975 | { |
| 1601 | struct vfio_iommu *iommu = iommu_data; | 1976 | struct vfio_iommu *iommu = iommu_data; |
| 1602 | struct vfio_domain *domain; | 1977 | struct vfio_domain *domain; |
| 1603 | struct vfio_group *group; | 1978 | struct vfio_group *group; |
| | 1979 | LIST_HEAD(iova_copy); |
| 1604 | | 1980 | |
| 1605 | mutex_lock(&iommu->lock); | 1981 | mutex_lock(&iommu->lock); |
| 1606 | | 1982 | |
| @@ -1623,6 +1999,13 @@ static void vfio_iommu_type1_detach_group(void *iommu_data, · 16 unmodified lines |
| 1623 | } | 1999 | } |
| 1624 | } | 2000 | } |
| 1625 | | 2001 | |
| | 2002 | /* |
| | 2003 | * Get a copy of iova list. This will be used to update |
| | 2004 | * and to replace the current one later. Please note that |
| | 2005 | * we will leave the original list as it is if update fails. |
| | 2006 | */ |
| | 2007 | vfio_iommu_iova_get_copy(iommu, &iova_copy); |
| | 2008 | |
| 1626 | list_for_each_entry(domain, &iommu->domain_list, next) { | 2009 | list_for_each_entry(domain, &iommu->domain_list, next) { |
| 1627 | group = find_iommu_group(domain, iommu_group); | 2010 | group = find_iommu_group(domain, iommu_group); |
| 1628 | if (!group) | 2011 | if (!group) |
| @@ -1648,10 +2031,16 @@ static void vfio_iommu_type1_detach_group(void *iommu_data, · 19 unmodified lines |
| 1648 | iommu_domain_free(domain->domain); | 2031 | iommu_domain_free(domain->domain); |
| 1649 | list_del(&domain->next); | 2032 | list_del(&domain->next); |
| 1650 | kfree(domain); | 2033 | kfree(domain); |
| | 2034 | vfio_iommu_aper_expand(iommu, &iova_copy); |
| 1651 | } | 2035 | } |
| 1652 | break; | 2036 | break; |
| 1653 | } | 2037 | } |
| 1654 | | 2038 | |
| | 2039 | if (!vfio_iommu_resv_refresh(iommu, &iova_copy)) |
| | 2040 | vfio_iommu_iova_insert_copy(iommu, &iova_copy); |
| | 2041 | else |
| | 2042 | vfio_iommu_iova_free(&iova_copy); |
| | 2043 | |
| 1655 | detach_group_done: | 2044 | detach_group_done: |
| 1656 | mutex_unlock(&iommu->lock); | 2045 | mutex_unlock(&iommu->lock); |
| 1657 | } | 2046 | } |
| @@ -1679,6 +2068,7 @@ static void *vfio_iommu_type1_open(unsigned long arg) · 21 unmodified lines |
| 1679 | } | 2068 | } |
| 1680 | | 2069 | |
| 1681 | INIT_LIST_HEAD(&iommu->domain_list); | 2070 | INIT_LIST_HEAD(&iommu->domain_list); |
| | 2071 | INIT_LIST_HEAD(&iommu->iova_list); |
| 1682 | iommu->dma_list = RB_ROOT; | 2072 | iommu->dma_list = RB_ROOT; |
| 1683 | iommu->dma_avail = dma_entry_limit; | 2073 | iommu->dma_avail = dma_entry_limit; |
| 1684 | mutex_init(&iommu->lock); | 2074 | mutex_init(&iommu->lock); |
| @@ -1722,6 +2112,9 @@ static void vfio_iommu_type1_release(void *iommu_data) · 37 unmodified lines |
| 1722 | list_del(&domain->next); | 2112 | list_del(&domain->next); |
| 1723 | kfree(domain); | 2113 | kfree(domain); |
| 1724 | } | 2114 | } |
| | 2115 | |
| | 2116 | vfio_iommu_iova_free(&iommu->iova_list); |
| | 2117 | |
| 1725 | kfree(iommu); | 2118 | kfree(iommu); |
| 1726 | } | 2119 | } |
| 1727 | | 2120 | |
| @@ -1742,6 +2135,73 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu) · 14 unmodified lines |
| 1742 | return ret; | 2135 | return ret; |
| 1743 | } | 2136 | } |
| 1744 | | 2137 | |
| | 2138 | static int vfio_iommu_iova_add_cap(struct vfio_info_cap *caps, |
| | 2139 | struct vfio_iommu_type1_info_cap_iova_range *cap_iovas, |
| | 2140 | size_t size) |
| | 2141 | { |
| | 2142 | struct vfio_info_cap_header *header; |
| | 2143 | struct vfio_iommu_type1_info_cap_iova_range *iova_cap; |
| | 2144 | |
| | 2145 | header = vfio_info_cap_add(caps, size, |
| | 2146 | VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE, 1); |
| | 2147 | if (IS_ERR(header)) |
| | 2148 | return PTR_ERR(header); |
| | 2149 | |
| | 2150 | iova_cap = container_of(header, |
| | 2151 | struct vfio_iommu_type1_info_cap_iova_range, |
| | 2152 | header); |
| | 2153 | iova_cap->nr_iovas = cap_iovas->nr_iovas; |
| | 2154 | memcpy(iova_cap->iova_ranges, cap_iovas->iova_ranges, |
| | 2155 | cap_iovas->nr_iovas * sizeof(*cap_iovas->iova_ranges)); |
| | 2156 | return 0; |
| | 2157 | } |
| | 2158 | |
| | 2159 | static int vfio_iommu_iova_build_caps(struct vfio_iommu *iommu, |
| | 2160 | struct vfio_info_cap *caps) |
| | 2161 | { |
| | 2162 | struct vfio_iommu_type1_info_cap_iova_range *cap_iovas; |
| | 2163 | struct vfio_iova *iova; |
| | 2164 | size_t size; |
| | 2165 | int iovas = 0, i = 0, ret; |
| | 2166 | |
| | 2167 | mutex_lock(&iommu->lock); |
| | 2168 | |
| | 2169 | list_for_each_entry(iova, &iommu->iova_list, list) |
| | 2170 | iovas++; |
| | 2171 | |
| | 2172 | if (!iovas) { |
| | 2173 | /* |
| | 2174 | * Return 0 as a container with a single mdev device |
| | 2175 | * will have an empty list |
| | 2176 | */ |
| | 2177 | ret = 0; |
| | 2178 | goto out_unlock; |
| | 2179 | } |
| | 2180 | |
| | 2181 | size = sizeof(*cap_iovas) + (iovas * sizeof(*cap_iovas->iova_ranges)); |
| | 2182 | |
| | 2183 | cap_iovas = kzalloc(size, GFP_KERNEL); |
| | 2184 | if (!cap_iovas) { |
| | 2185 | ret = -ENOMEM; |
| | 2186 | goto out_unlock; |
| | 2187 | } |
| | 2188 | |
| | 2189 | cap_iovas->nr_iovas = iovas; |
| | 2190 | |
| | 2191 | list_for_each_entry(iova, &iommu->iova_list, list) { |
| | 2192 | cap_iovas->iova_ranges[i].start = iova->start; |
| | 2193 | cap_iovas->iova_ranges[i].end = iova->end; |
| | 2194 | i++; |
| | 2195 | } |
| | 2196 | |
| | 2197 | ret = vfio_iommu_iova_add_cap(caps, cap_iovas, size); |
| | 2198 | |
| | 2199 | kfree(cap_iovas); |
| | 2200 | out_unlock: |
| | 2201 | mutex_unlock(&iommu->lock); |
| | 2202 | return ret; |
| | 2203 | } |
| | 2204 | |
| 1745 | static long vfio_iommu_type1_ioctl(void *iommu_data, | 2205 | static long vfio_iommu_type1_ioctl(void *iommu_data, |
| 1746 | unsigned int cmd, unsigned long arg) | 2206 | unsigned int cmd, unsigned long arg) |
| 1747 | { | 2207 | { |
| @@ -1763,19 +2223,53 @@ static long vfio_iommu_type1_ioctl(void *iommu_data, · 15 unmodified lines |
| 1763 | } | 2223 | } |
| 1764 | } else if (cmd == VFIO_IOMMU_GET_INFO) { | 2224 | } else if (cmd == VFIO_IOMMU_GET_INFO) { |
| 1765 | struct vfio_iommu_type1_info info; | 2225 | struct vfio_iommu_type1_info info; |
| | 2226 | struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; |
| | 2227 | unsigned long capsz; |
| | 2228 | int ret; |
| 1766 | | 2229 | |
| 1767 | minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes); | 2230 | minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes); |
| 1768 | | 2231 | |
| | 2232 | /* For backward compatibility, cannot require this */ |
| | 2233 | capsz = offsetofend(struct vfio_iommu_type1_info, cap_offset); |
| | 2234 | |
| 1769 | if (copy_from_user(&info, (void __user *)arg, minsz)) | 2235 | if (copy_from_user(&info, (void __user *)arg, minsz)) |
| 1770 | return -EFAULT; | 2236 | return -EFAULT; |
| 1771 | | 2237 | |
| 1772 | if (info.argsz < minsz) | 2238 | if (info.argsz < minsz) |
| 1773 | return -EINVAL; | 2239 | return -EINVAL; |
| 1774 | | 2240 | |
| | 2241 | if (info.argsz >= capsz) { |
| | 2242 | minsz = capsz; |
| | 2243 | info.cap_offset = 0; /* output, no-recopy necessary */ |
| | 2244 | } |
| | 2245 | |
| 1775 | info.flags = VFIO_IOMMU_INFO_PGSIZES; | 2246 | info.flags = VFIO_IOMMU_INFO_PGSIZES; |
| 1776 | | 2247 | |
| 1777 | info.iova_pgsizes = vfio_pgsize_bitmap(iommu); | 2248 | info.iova_pgsizes = vfio_pgsize_bitmap(iommu); |
| 1778 | | 2249 | |
| | 2250 | ret = vfio_iommu_iova_build_caps(iommu, &caps); |
| | 2251 | if (ret) |
| | 2252 | return ret; |
| | 2253 | |
| | 2254 | if (caps.size) { |
| | 2255 | info.flags |= VFIO_IOMMU_INFO_CAPS; |
| | 2256 | |
| | 2257 | if (info.argsz < sizeof(info) + caps.size) { |
| | 2258 | info.argsz = sizeof(info) + caps.size; |
| | 2259 | } else { |
| | 2260 | vfio_info_cap_shift(&caps, sizeof(info)); |
| | 2261 | if (copy_to_user((void __user *)arg + |
| | 2262 | sizeof(info), caps.buf, |
| | 2263 | caps.size)) { |
| | 2264 | kfree(caps.buf); |
| | 2265 | return -EFAULT; |
| | 2266 | } |
| | 2267 | info.cap_offset = sizeof(info); |
| | 2268 | } |
| | 2269 | |
| | 2270 | kfree(caps.buf); |
| | 2271 | } |
| | 2272 | |
| 1779 | return copy_to_user((void __user *)arg, &info, minsz) ? | 2273 | return copy_to_user((void __user *)arg, &info, minsz) ? |
| 1780 | -EFAULT : 0; | 2274 | -EFAULT : 0; |
| 1781 | | 2275 | |