aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2018-09-06 11:13:06 -0400
committerAlex Deucher <alexander.deucher@amd.com>2018-09-13 16:14:10 -0400
commitdfcd99f6273e7ae9aae10eafacc5521018bee143 (patch)
tree440a266b0a9717c9206274e30477f15ee68585d1 /drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
parentdfa70550f5b77252d99ba9c410b9fbe6e4088e51 (diff)
drm/amdgpu: meld together VM fragment and huge page handling
This optimizes the generating of PTEs by walking the hierarchy only once for a range and making changes as necessary. It allows for both huge (2MB) as well giant (1GB) pages to be used on Vega and Raven. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Huang Rui <ray.huang@amd.com> Acked-by: Junwei Zhang <Jerry.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c267
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 */
1502static void amdgpu_vm_handle_huge_pages(struct amdgpu_pte_update_params *p, 1495static 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 */
1522static 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 */
1547static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, 1577static 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 */
1599static 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(&params, start, last + 1, 1738 return amdgpu_vm_update_ptes(&params, 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(&params, start, last + 1, addr, flags); 1818 r = amdgpu_vm_update_ptes(&params, start, last + 1, addr, flags);
1792 if (r) 1819 if (r)
1793 goto error_free; 1820 goto error_free;
1794 1821