Skip to content

Commit 7dc8f11

Browse files
committed
drm/i915/gem: Drop relocation slowpath
Since the relocations are no longer performed under a global struct_mutex, or any other lock, that is also held by pagefault handlers, we can relax and allow our fast path to take a fault. As we no longer need to abort the fast path for lock avoidance, we no longer need the slow path handling at all. Signed-off-by: Chris Wilson <[email protected]> Reviewed-by: Matthew Auld <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 07bcfd1 commit 7dc8f11

File tree

1 file changed

+4
-235
lines changed

1 file changed

+4
-235
lines changed

drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c

Lines changed: 4 additions & 235 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,9 +1440,7 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev)
14401440
* we would try to acquire the struct mutex again. Obviously
14411441
* this is bad and so lockdep complains vehemently.
14421442
*/
1443-
pagefault_disable();
1444-
copied = __copy_from_user_inatomic(r, urelocs, count * sizeof(r[0]));
1445-
pagefault_enable();
1443+
copied = __copy_from_user(r, urelocs, count * sizeof(r[0]));
14461444
if (unlikely(copied)) {
14471445
remain = -EFAULT;
14481446
goto out;
@@ -1492,236 +1490,6 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev)
14921490
return remain;
14931491
}
14941492

1495-
static int
1496-
eb_relocate_vma_slow(struct i915_execbuffer *eb, struct eb_vma *ev)
1497-
{
1498-
const struct drm_i915_gem_exec_object2 *entry = ev->exec;
1499-
struct drm_i915_gem_relocation_entry *relocs =
1500-
u64_to_ptr(typeof(*relocs), entry->relocs_ptr);
1501-
unsigned int i;
1502-
int err;
1503-
1504-
for (i = 0; i < entry->relocation_count; i++) {
1505-
u64 offset = eb_relocate_entry(eb, ev, &relocs[i]);
1506-
1507-
if ((s64)offset < 0) {
1508-
err = (int)offset;
1509-
goto err;
1510-
}
1511-
}
1512-
err = 0;
1513-
err:
1514-
reloc_cache_reset(&eb->reloc_cache);
1515-
return err;
1516-
}
1517-
1518-
static int check_relocations(const struct drm_i915_gem_exec_object2 *entry)
1519-
{
1520-
const char __user *addr, *end;
1521-
unsigned long size;
1522-
char __maybe_unused c;
1523-
1524-
size = entry->relocation_count;
1525-
if (size == 0)
1526-
return 0;
1527-
1528-
if (size > N_RELOC(ULONG_MAX))
1529-
return -EINVAL;
1530-
1531-
addr = u64_to_user_ptr(entry->relocs_ptr);
1532-
size *= sizeof(struct drm_i915_gem_relocation_entry);
1533-
if (!access_ok(addr, size))
1534-
return -EFAULT;
1535-
1536-
end = addr + size;
1537-
for (; addr < end; addr += PAGE_SIZE) {
1538-
int err = __get_user(c, addr);
1539-
if (err)
1540-
return err;
1541-
}
1542-
return __get_user(c, end - 1);
1543-
}
1544-
1545-
static int eb_copy_relocations(const struct i915_execbuffer *eb)
1546-
{
1547-
struct drm_i915_gem_relocation_entry *relocs;
1548-
const unsigned int count = eb->buffer_count;
1549-
unsigned int i;
1550-
int err;
1551-
1552-
for (i = 0; i < count; i++) {
1553-
const unsigned int nreloc = eb->exec[i].relocation_count;
1554-
struct drm_i915_gem_relocation_entry __user *urelocs;
1555-
unsigned long size;
1556-
unsigned long copied;
1557-
1558-
if (nreloc == 0)
1559-
continue;
1560-
1561-
err = check_relocations(&eb->exec[i]);
1562-
if (err)
1563-
goto err;
1564-
1565-
urelocs = u64_to_user_ptr(eb->exec[i].relocs_ptr);
1566-
size = nreloc * sizeof(*relocs);
1567-
1568-
relocs = kvmalloc_array(size, 1, GFP_KERNEL);
1569-
if (!relocs) {
1570-
err = -ENOMEM;
1571-
goto err;
1572-
}
1573-
1574-
/* copy_from_user is limited to < 4GiB */
1575-
copied = 0;
1576-
do {
1577-
unsigned int len =
1578-
min_t(u64, BIT_ULL(31), size - copied);
1579-
1580-
if (__copy_from_user((char *)relocs + copied,
1581-
(char __user *)urelocs + copied,
1582-
len))
1583-
goto end;
1584-
1585-
copied += len;
1586-
} while (copied < size);
1587-
1588-
/*
1589-
* As we do not update the known relocation offsets after
1590-
* relocating (due to the complexities in lock handling),
1591-
* we need to mark them as invalid now so that we force the
1592-
* relocation processing next time. Just in case the target
1593-
* object is evicted and then rebound into its old
1594-
* presumed_offset before the next execbuffer - if that
1595-
* happened we would make the mistake of assuming that the
1596-
* relocations were valid.
1597-
*/
1598-
if (!user_access_begin(urelocs, size))
1599-
goto end;
1600-
1601-
for (copied = 0; copied < nreloc; copied++)
1602-
unsafe_put_user(-1,
1603-
&urelocs[copied].presumed_offset,
1604-
end_user);
1605-
user_access_end();
1606-
1607-
eb->exec[i].relocs_ptr = (uintptr_t)relocs;
1608-
}
1609-
1610-
return 0;
1611-
1612-
end_user:
1613-
user_access_end();
1614-
end:
1615-
kvfree(relocs);
1616-
err = -EFAULT;
1617-
err:
1618-
while (i--) {
1619-
relocs = u64_to_ptr(typeof(*relocs), eb->exec[i].relocs_ptr);
1620-
if (eb->exec[i].relocation_count)
1621-
kvfree(relocs);
1622-
}
1623-
return err;
1624-
}
1625-
1626-
static int eb_prefault_relocations(const struct i915_execbuffer *eb)
1627-
{
1628-
const unsigned int count = eb->buffer_count;
1629-
unsigned int i;
1630-
1631-
for (i = 0; i < count; i++) {
1632-
int err;
1633-
1634-
err = check_relocations(&eb->exec[i]);
1635-
if (err)
1636-
return err;
1637-
}
1638-
1639-
return 0;
1640-
}
1641-
1642-
static noinline int eb_relocate_slow(struct i915_execbuffer *eb)
1643-
{
1644-
bool have_copy = false;
1645-
struct eb_vma *ev;
1646-
int err = 0;
1647-
1648-
repeat:
1649-
if (signal_pending(current)) {
1650-
err = -ERESTARTSYS;
1651-
goto out;
1652-
}
1653-
1654-
/*
1655-
* We take 3 passes through the slowpatch.
1656-
*
1657-
* 1 - we try to just prefault all the user relocation entries and
1658-
* then attempt to reuse the atomic pagefault disabled fast path again.
1659-
*
1660-
* 2 - we copy the user entries to a local buffer here outside of the
1661-
* local and allow ourselves to wait upon any rendering before
1662-
* relocations
1663-
*
1664-
* 3 - we already have a local copy of the relocation entries, but
1665-
* were interrupted (EAGAIN) whilst waiting for the objects, try again.
1666-
*/
1667-
if (!err) {
1668-
err = eb_prefault_relocations(eb);
1669-
} else if (!have_copy) {
1670-
err = eb_copy_relocations(eb);
1671-
have_copy = err == 0;
1672-
} else {
1673-
cond_resched();
1674-
err = 0;
1675-
}
1676-
if (err)
1677-
goto out;
1678-
1679-
list_for_each_entry(ev, &eb->relocs, reloc_link) {
1680-
if (!have_copy) {
1681-
pagefault_disable();
1682-
err = eb_relocate_vma(eb, ev);
1683-
pagefault_enable();
1684-
if (err)
1685-
goto repeat;
1686-
} else {
1687-
err = eb_relocate_vma_slow(eb, ev);
1688-
if (err)
1689-
goto err;
1690-
}
1691-
}
1692-
1693-
/*
1694-
* Leave the user relocations as are, this is the painfully slow path,
1695-
* and we want to avoid the complication of dropping the lock whilst
1696-
* having buffers reserved in the aperture and so causing spurious
1697-
* ENOSPC for random operations.
1698-
*/
1699-
1700-
err:
1701-
if (err == -EAGAIN)
1702-
goto repeat;
1703-
1704-
out:
1705-
if (have_copy) {
1706-
const unsigned int count = eb->buffer_count;
1707-
unsigned int i;
1708-
1709-
for (i = 0; i < count; i++) {
1710-
const struct drm_i915_gem_exec_object2 *entry =
1711-
&eb->exec[i];
1712-
struct drm_i915_gem_relocation_entry *relocs;
1713-
1714-
if (!entry->relocation_count)
1715-
continue;
1716-
1717-
relocs = u64_to_ptr(typeof(*relocs), entry->relocs_ptr);
1718-
kvfree(relocs);
1719-
}
1720-
}
1721-
1722-
return err;
1723-
}
1724-
17251493
static int eb_relocate(struct i915_execbuffer *eb)
17261494
{
17271495
int err;
@@ -1743,8 +1511,9 @@ static int eb_relocate(struct i915_execbuffer *eb)
17431511
struct eb_vma *ev;
17441512

17451513
list_for_each_entry(ev, &eb->relocs, reloc_link) {
1746-
if (eb_relocate_vma(eb, ev))
1747-
return eb_relocate_slow(eb);
1514+
err = eb_relocate_vma(eb, ev);
1515+
if (err)
1516+
return err;
17481517
}
17491518
}
17501519

0 commit comments

Comments
 (0)