diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 267 |
1 files changed, 147 insertions, 120 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index e873bbb2f0c7..45343501c1f3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -1488,46 +1488,76 @@ error: | |||
1488 | } | 1488 | } |
1489 | 1489 | ||
1490 | /** | 1490 | /** |
1491 | * amdgpu_vm_handle_huge_pages - handle updating the PD with huge pages | 1491 | * amdgpu_vm_update_huge - figure out parameters for PTE updates |
1492 | * | 1492 | * |
1493 | * @p: see amdgpu_pte_update_params definition | 1493 | * Make sure to set the right flags for the PTEs at the desired level. |
1494 | * @entry: vm_pt entry to check | ||
1495 | * @parent: parent entry | ||
1496 | * @nptes: number of PTEs updated with this operation | ||
1497 | * @dst: destination address where the PTEs should point to | ||
1498 | * @flags: access flags fro the PTEs | ||
1499 | * | ||
1500 | * Check if we can update the PD with a huge page. | ||
1501 | */ | 1494 | */ |
1502 | static void amdgpu_vm_handle_huge_pages(struct amdgpu_pte_update_params *p, | 1495 | static void amdgpu_vm_update_huge(struct amdgpu_pte_update_params *params, |
1503 | struct amdgpu_vm_pt *entry, | 1496 | struct amdgpu_bo *bo, unsigned level, |
1504 | struct amdgpu_vm_pt *parent, | 1497 | uint64_t pe, uint64_t addr, |
1505 | unsigned nptes, uint64_t dst, | 1498 | unsigned count, uint32_t incr, |
1506 | uint64_t flags) | 1499 | uint64_t flags) |
1507 | { | ||
1508 | uint64_t pde; | ||
1509 | 1500 | ||
1510 | /* In the case of a mixed PT the PDE must point to it*/ | 1501 | { |
1511 | if (p->adev->asic_type >= CHIP_VEGA10 && !p->src && | 1502 | if (level != AMDGPU_VM_PTB) { |
1512 | nptes == AMDGPU_VM_PTE_COUNT(p->adev)) { | ||
1513 | /* Set the huge page flag to stop scanning at this PDE */ | ||
1514 | flags |= AMDGPU_PDE_PTE; | 1503 | flags |= AMDGPU_PDE_PTE; |
1504 | amdgpu_gmc_get_vm_pde(params->adev, level, &addr, &flags); | ||
1515 | } | 1505 | } |
1516 | 1506 | ||
1517 | if (!(flags & AMDGPU_PDE_PTE)) { | 1507 | amdgpu_vm_update_func(params, bo, pe, addr, count, incr, flags); |
1518 | if (entry->huge) { | 1508 | } |
1519 | /* Add the entry to the relocated list to update it. */ | 1509 | |
1520 | entry->huge = false; | 1510 | /** |
1521 | amdgpu_vm_bo_relocated(&entry->base); | 1511 | * amdgpu_vm_fragment - get fragment for PTEs |
1522 | } | 1512 | * |
1513 | * @params: see amdgpu_pte_update_params definition | ||
1514 | * @start: first PTE to handle | ||
1515 | * @end: last PTE to handle | ||
1516 | * @flags: hw mapping flags | ||
1517 | * @frag: resulting fragment size | ||
1518 | * @frag_end: end of this fragment | ||
1519 | * | ||
1520 | * Returns the first possible fragment for the start and end address. | ||
1521 | */ | ||
1522 | static void amdgpu_vm_fragment(struct amdgpu_pte_update_params *params, | ||
1523 | uint64_t start, uint64_t end, uint64_t flags, | ||
1524 | unsigned int *frag, uint64_t *frag_end) | ||
1525 | { | ||
1526 | /** | ||
1527 | * The MC L1 TLB supports variable sized pages, based on a fragment | ||
1528 | * field in the PTE. When this field is set to a non-zero value, page | ||
1529 | * granularity is increased from 4KB to (1 << (12 + frag)). The PTE | ||
1530 | * flags are considered valid for all PTEs within the fragment range | ||
1531 | * and corresponding mappings are assumed to be physically contiguous. | ||
1532 | * | ||
1533 | * The L1 TLB can store a single PTE for the whole fragment, | ||
1534 | * significantly increasing the space available for translation | ||
1535 | * caching. This leads to large improvements in throughput when the | ||
1536 | * TLB is under pressure. | ||
1537 | * | ||
1538 | * The L2 TLB distributes small and large fragments into two | ||
1539 | * asymmetric partitions. The large fragment cache is significantly | ||
1540 | * larger. Thus, we try to use large fragments wherever possible. | ||
1541 | * Userspace can support this by aligning virtual base address and | ||
1542 | * allocation size to the fragment size. | ||
1543 | */ | ||
1544 | unsigned max_frag = params->adev->vm_manager.fragment_size; | ||
1545 | |||
1546 | /* system pages are non continuously */ | ||
1547 | if (params->src || !(flags & AMDGPU_PTE_VALID)) { | ||
1548 | *frag = 0; | ||
1549 | *frag_end = end; | ||
1523 | return; | 1550 | return; |
1524 | } | 1551 | } |
1525 | 1552 | ||
1526 | entry->huge = true; | 1553 | /* This intentionally wraps around if no bit is set */ |
1527 | amdgpu_gmc_get_vm_pde(p->adev, AMDGPU_VM_PDB0, &dst, &flags); | 1554 | *frag = min((unsigned)ffs(start) - 1, (unsigned)fls64(end - start) - 1); |
1528 | 1555 | if (*frag >= max_frag) { | |
1529 | pde = (entry - parent->entries) * 8; | 1556 | *frag = max_frag; |
1530 | amdgpu_vm_update_func(p, parent->base.bo, pde, dst, 1, 0, flags); | 1557 | *frag_end = end & ~((1ULL << max_frag) - 1); |
1558 | } else { | ||
1559 | *frag_end = start + (1 << *frag); | ||
1560 | } | ||
1531 | } | 1561 | } |
1532 | 1562 | ||
1533 | /** | 1563 | /** |
@@ -1545,108 +1575,105 @@ static void amdgpu_vm_handle_huge_pages(struct amdgpu_pte_update_params *p, | |||
1545 | * 0 for success, -EINVAL for failure. | 1575 | * 0 for success, -EINVAL for failure. |
1546 | */ | 1576 | */ |
1547 | static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, | 1577 | static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, |
1548 | uint64_t start, uint64_t end, | 1578 | uint64_t start, uint64_t end, |
1549 | uint64_t dst, uint64_t flags) | 1579 | uint64_t dst, uint64_t flags) |
1550 | { | 1580 | { |
1551 | struct amdgpu_device *adev = params->adev; | 1581 | struct amdgpu_device *adev = params->adev; |
1552 | const uint64_t mask = AMDGPU_VM_PTE_COUNT(adev) - 1; | ||
1553 | struct amdgpu_vm_pt_cursor cursor; | 1582 | struct amdgpu_vm_pt_cursor cursor; |
1583 | uint64_t frag_start = start, frag_end; | ||
1584 | unsigned int frag; | ||
1554 | 1585 | ||
1555 | /* walk over the address space and update the page tables */ | 1586 | /* figure out the initial fragment */ |
1556 | for_each_amdgpu_vm_pt_leaf(adev, params->vm, start, end - 1, cursor) { | 1587 | amdgpu_vm_fragment(params, frag_start, end, flags, &frag, &frag_end); |
1588 | |||
1589 | /* walk over the address space and update the PTs */ | ||
1590 | amdgpu_vm_pt_start(adev, params->vm, start, &cursor); | ||
1591 | while (cursor.pfn < end) { | ||
1557 | struct amdgpu_bo *pt = cursor.entry->base.bo; | 1592 | struct amdgpu_bo *pt = cursor.entry->base.bo; |
1558 | uint64_t pe_start; | 1593 | unsigned shift, parent_shift, num_entries; |
1559 | unsigned nptes; | 1594 | uint64_t incr, entry_end, pe_start; |
1560 | 1595 | ||
1561 | if (!pt || cursor.level != AMDGPU_VM_PTB) | 1596 | if (!pt) |
1562 | return -ENOENT; | 1597 | return -ENOENT; |
1563 | 1598 | ||
1564 | if ((cursor.pfn & ~mask) == (end & ~mask)) | 1599 | /* The root level can't be a huge page */ |
1565 | nptes = end - cursor.pfn; | 1600 | if (cursor.level == adev->vm_manager.root_level) { |
1566 | else | 1601 | if (!amdgpu_vm_pt_descendant(adev, &cursor)) |
1567 | nptes = AMDGPU_VM_PTE_COUNT(adev) - (cursor.pfn & mask); | 1602 | return -ENOENT; |
1568 | |||
1569 | amdgpu_vm_handle_huge_pages(params, cursor.entry, cursor.parent, | ||
1570 | nptes, dst, flags); | ||
1571 | /* We don't need to update PTEs for huge pages */ | ||
1572 | if (cursor.entry->huge) { | ||
1573 | dst += nptes * AMDGPU_GPU_PAGE_SIZE; | ||
1574 | continue; | 1603 | continue; |
1575 | } | 1604 | } |
1576 | 1605 | ||
1577 | pe_start = (cursor.pfn & mask) * 8; | 1606 | /* First check if the entry is already handled */ |
1578 | amdgpu_vm_update_func(params, pt, pe_start, dst, nptes, | 1607 | if (cursor.pfn < frag_start) { |
1579 | AMDGPU_GPU_PAGE_SIZE, flags); | 1608 | cursor.entry->huge = true; |
1580 | dst += nptes * AMDGPU_GPU_PAGE_SIZE; | 1609 | amdgpu_vm_pt_next(adev, &cursor); |
1581 | } | 1610 | continue; |
1582 | 1611 | } | |
1583 | return 0; | ||
1584 | } | ||
1585 | 1612 | ||
1586 | /* | 1613 | /* If it isn't already handled it can't be a huge page */ |
1587 | * amdgpu_vm_frag_ptes - add fragment information to PTEs | 1614 | if (cursor.entry->huge) { |
1588 | * | 1615 | /* Add the entry to the relocated list to update it. */ |
1589 | * @params: see amdgpu_pte_update_params definition | 1616 | cursor.entry->huge = false; |
1590 | * @vm: requested vm | 1617 | amdgpu_vm_bo_relocated(&cursor.entry->base); |
1591 | * @start: first PTE to handle | 1618 | } |
1592 | * @end: last PTE to handle | ||
1593 | * @dst: addr those PTEs should point to | ||
1594 | * @flags: hw mapping flags | ||
1595 | * | ||
1596 | * Returns: | ||
1597 | * 0 for success, -EINVAL for failure. | ||
1598 | */ | ||
1599 | static int amdgpu_vm_frag_ptes(struct amdgpu_pte_update_params *params, | ||
1600 | uint64_t start, uint64_t end, | ||
1601 | uint64_t dst, uint64_t flags) | ||
1602 | { | ||
1603 | /** | ||
1604 | * The MC L1 TLB supports variable sized pages, based on a fragment | ||
1605 | * field in the PTE. When this field is set to a non-zero value, page | ||
1606 | * granularity is increased from 4KB to (1 << (12 + frag)). The PTE | ||
1607 | * flags are considered valid for all PTEs within the fragment range | ||
1608 | * and corresponding mappings are assumed to be physically contiguous. | ||
1609 | * | ||
1610 | * The L1 TLB can store a single PTE for the whole fragment, | ||
1611 | * significantly increasing the space available for translation | ||
1612 | * caching. This leads to large improvements in throughput when the | ||
1613 | * TLB is under pressure. | ||
1614 | * | ||
1615 | * The L2 TLB distributes small and large fragments into two | ||
1616 | * asymmetric partitions. The large fragment cache is significantly | ||
1617 | * larger. Thus, we try to use large fragments wherever possible. | ||
1618 | * Userspace can support this by aligning virtual base address and | ||
1619 | * allocation size to the fragment size. | ||
1620 | */ | ||
1621 | unsigned max_frag = params->adev->vm_manager.fragment_size; | ||
1622 | int r; | ||
1623 | 1619 | ||
1624 | /* system pages are non continuously */ | 1620 | shift = amdgpu_vm_level_shift(adev, cursor.level); |
1625 | if (params->src || !(flags & AMDGPU_PTE_VALID)) | 1621 | parent_shift = amdgpu_vm_level_shift(adev, cursor.level - 1); |
1626 | return amdgpu_vm_update_ptes(params, start, end, dst, flags); | 1622 | if (adev->asic_type < CHIP_VEGA10) { |
1627 | 1623 | /* No huge page support before GMC v9 */ | |
1628 | while (start != end) { | 1624 | if (cursor.level != AMDGPU_VM_PTB) { |
1629 | uint64_t frag_flags, frag_end; | 1625 | if (!amdgpu_vm_pt_descendant(adev, &cursor)) |
1630 | unsigned frag; | 1626 | return -ENOENT; |
1631 | 1627 | continue; | |
1632 | /* This intentionally wraps around if no bit is set */ | 1628 | } |
1633 | frag = min((unsigned)ffs(start) - 1, | 1629 | } else if (frag < shift) { |
1634 | (unsigned)fls64(end - start) - 1); | 1630 | /* We can't use this level when the fragment size is |
1635 | if (frag >= max_frag) { | 1631 | * smaller than the address shift. Go to the next |
1636 | frag_flags = AMDGPU_PTE_FRAG(max_frag); | 1632 | * child entry and try again. |
1637 | frag_end = end & ~((1ULL << max_frag) - 1); | 1633 | */ |
1638 | } else { | 1634 | if (!amdgpu_vm_pt_descendant(adev, &cursor)) |
1639 | frag_flags = AMDGPU_PTE_FRAG(frag); | 1635 | return -ENOENT; |
1640 | frag_end = start + (1 << frag); | 1636 | continue; |
1637 | } else if (frag >= parent_shift) { | ||
1638 | /* If the fragment size is even larger than the parent | ||
1639 | * shift we should go up one level and check it again. | ||
1640 | */ | ||
1641 | if (!amdgpu_vm_pt_ancestor(&cursor)) | ||
1642 | return -ENOENT; | ||
1643 | continue; | ||
1641 | } | 1644 | } |
1642 | 1645 | ||
1643 | r = amdgpu_vm_update_ptes(params, start, frag_end, dst, | 1646 | /* Looks good so far, calculate parameters for the update */ |
1644 | flags | frag_flags); | 1647 | incr = AMDGPU_GPU_PAGE_SIZE << shift; |
1645 | if (r) | 1648 | num_entries = amdgpu_vm_num_entries(adev, cursor.level); |
1646 | return r; | 1649 | pe_start = ((cursor.pfn >> shift) & (num_entries - 1)) * 8; |
1650 | entry_end = num_entries << shift; | ||
1651 | entry_end += cursor.pfn & ~(entry_end - 1); | ||
1652 | entry_end = min(entry_end, end); | ||
1653 | |||
1654 | do { | ||
1655 | uint64_t upd_end = min(entry_end, frag_end); | ||
1656 | unsigned nptes = (upd_end - frag_start) >> shift; | ||
1657 | |||
1658 | amdgpu_vm_update_huge(params, pt, cursor.level, | ||
1659 | pe_start, dst, nptes, incr, | ||
1660 | flags | AMDGPU_PTE_FRAG(frag)); | ||
1661 | |||
1662 | pe_start += nptes * 8; | ||
1663 | dst += nptes * AMDGPU_GPU_PAGE_SIZE << shift; | ||
1664 | |||
1665 | frag_start = upd_end; | ||
1666 | if (frag_start >= frag_end) { | ||
1667 | /* figure out the next fragment */ | ||
1668 | amdgpu_vm_fragment(params, frag_start, end, | ||
1669 | flags, &frag, &frag_end); | ||
1670 | if (frag < shift) | ||
1671 | break; | ||
1672 | } | ||
1673 | } while (frag_start < entry_end); | ||
1647 | 1674 | ||
1648 | dst += (frag_end - start) * AMDGPU_GPU_PAGE_SIZE; | 1675 | if (frag >= shift) |
1649 | start = frag_end; | 1676 | amdgpu_vm_pt_next(adev, &cursor); |
1650 | } | 1677 | } |
1651 | 1678 | ||
1652 | return 0; | 1679 | return 0; |
@@ -1708,8 +1735,8 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, | |||
1708 | 1735 | ||
1709 | params.func = amdgpu_vm_cpu_set_ptes; | 1736 | params.func = amdgpu_vm_cpu_set_ptes; |
1710 | params.pages_addr = pages_addr; | 1737 | params.pages_addr = pages_addr; |
1711 | return amdgpu_vm_frag_ptes(¶ms, start, last + 1, | 1738 | return amdgpu_vm_update_ptes(¶ms, start, last + 1, |
1712 | addr, flags); | 1739 | addr, flags); |
1713 | } | 1740 | } |
1714 | 1741 | ||
1715 | ring = container_of(vm->entity.rq->sched, struct amdgpu_ring, sched); | 1742 | ring = container_of(vm->entity.rq->sched, struct amdgpu_ring, sched); |
@@ -1788,7 +1815,7 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, | |||
1788 | if (r) | 1815 | if (r) |
1789 | goto error_free; | 1816 | goto error_free; |
1790 | 1817 | ||
1791 | r = amdgpu_vm_frag_ptes(¶ms, start, last + 1, addr, flags); | 1818 | r = amdgpu_vm_update_ptes(¶ms, start, last + 1, addr, flags); |
1792 | if (r) | 1819 | if (r) |
1793 | goto error_free; | 1820 | goto error_free; |
1794 | 1821 | ||