/* * Move folios to appropriate lru and release the batch, decrementing the * ref count of those folios.
*/ staticvoid check_release_folio_batch(struct folio_batch *fbatch)
{
check_move_unevictable_folios(fbatch);
__folio_batch_release(fbatch);
cond_resched();
}
if (overflows_type(size / PAGE_SIZE, page_count)) return -E2BIG;
page_count = size / PAGE_SIZE; /* * If there's no chance of allocating enough pages for the whole * object, bail early.
*/ if (size > resource_size(&mr->region)) return -ENOMEM;
if (sg_alloc_table(st, page_count, GFP_KERNEL | __GFP_NOWARN)) return -ENOMEM;
/* * Get the list of pages out of our struct file. They'll be pinned * at this point until we release them. * * Fail silently without starting the shrinker
*/
mapping_set_unevictable(mapping);
noreclaim = mapping_gfp_constraint(mapping, ~__GFP_RECLAIM);
noreclaim |= __GFP_NORETRY | __GFP_NOWARN;
/* * We've tried hard to allocate the memory by reaping * our own buffer, now let the real VM do its job and * go down in flames if truly OOM. * * However, since graphics tend to be disposable, * defer the oom here by reporting the ENOMEM back * to userspace.
*/ if (!*s) { /* reclaim and warn, but no oom */
gfp = mapping_gfp_mask(mapping);
/* * Our bo are always dirty and so we require * kswapd to reclaim our pages (direct reclaim * does not effectively begin pageout of our * buffers on its own). However, direct reclaim * only waits for kswapd when under allocation * congestion. So as a result __GFP_RECLAIM is * unreliable and fails to actually reclaim our * dirty pages -- unless you try over and over * again with !__GFP_NORETRY. However, we still * want to fail this allocation rather than * trigger the out-of-memory killer and for * this we want __GFP_RETRY_MAYFAIL.
*/
gfp |= __GFP_RETRY_MAYFAIL | __GFP_NOWARN;
}
} while (1);
/* * shmemfs first checks if there is enough memory to allocate the page * and reports ENOSPC should there be insufficient, along with the usual * ENOMEM for a genuine allocation failure. * * We use ENOSPC in our driver to mean that we have run out of aperture * space and so want to translate the error from shmemfs back to our * usual understanding of ENOMEM.
*/ if (ret == -ENOSPC)
ret = -ENOMEM;
/* * Assert that the object is not currently in any GPU domain. As it * wasn't in the GTT, there shouldn't be any way it could have been in * a GPU cache
*/
GEM_BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS);
GEM_BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS);
rebuild_st:
st = kmalloc(sizeof(*st), GFP_KERNEL | __GFP_NOWARN); if (!st) return -ENOMEM;
ret = shmem_sg_alloc_table(i915, st, obj->base.size, mem, mapping,
max_segment); if (ret) goto err_st;
ret = i915_gem_gtt_prepare_pages(obj, st); if (ret) { /* * DMA remapping failed? One possible cause is that * it could not reserve enough large entries, asking * for PAGE_SIZE chunks instead may be helpful.
*/ if (max_segment > PAGE_SIZE) {
shmem_sg_free_table(st, mapping, false, false);
kfree(st);
if (i915_gem_object_needs_bit17_swizzle(obj))
i915_gem_object_do_bit_17_swizzle(obj, st);
if (i915_gem_object_can_bypass_llc(obj))
obj->cache_dirty = true;
__i915_gem_object_set_pages(obj, st);
return 0;
err_pages:
shmem_sg_free_table(st, mapping, false, false); /* * shmemfs first checks if there is enough memory to allocate the page * and reports ENOSPC should there be insufficient, along with the usual * ENOMEM for a genuine allocation failure. * * We use ENOSPC in our driver to mean that we have run out of aperture * space and so want to translate the error from shmemfs back to our * usual understanding of ENOMEM.
*/
err_st: if (ret == -ENOSPC)
ret = -ENOMEM;
kfree(st);
return ret;
}
staticint
shmem_truncate(struct drm_i915_gem_object *obj)
{ /* * Our goal here is to return as much of the memory as * is possible back to the system as we are called from OOM. * To do this we must instruct the shmfs to drop all of its * backing pages, *now*.
*/
shmem_truncate_range(file_inode(obj->base.filp), 0, (loff_t)-1);
obj->mm.madv = __I915_MADV_PURGED;
obj->mm.pages = ERR_PTR(-EFAULT);
/* * Leave mmapings intact (GTT will have been revoked on unbinding, * leaving only CPU mmapings around) and add those folios to the LRU * instead of invoking writeback so they are aged and paged out * as normal.
*/ while ((folio = writeback_iter(mapping, &wbc, folio, &error))) { if (folio_mapped(folio))
folio_redirty_for_writepage(&wbc, folio); else
error = shmem_writeout(folio, NULL, NULL);
}
}
__start_cpu_write(obj); /* * On non-LLC igfx platforms, force the flush-on-acquire if this is ever * swapped-in. Our async flush path is not trust worthy enough yet(and * happens in the wrong order), and with some tricks it's conceivable * for userspace to change the cache-level to I915_CACHE_NONE after the * pages are swapped-in, and since execbuf binds the object before doing * the async flush, we have a race window.
*/ if (!HAS_LLC(i915) && !IS_DGFX(i915))
obj->cache_dirty = true;
}
/* Caller already validated user args */
GEM_BUG_ON(!access_ok(user_data, arg->size));
if (!i915_gem_object_has_struct_page(obj)) return i915_gem_object_pwrite_phys(obj, arg);
/* * Before we instantiate/pin the backing store for our use, we * can prepopulate the shmemfs filp efficiently using a write into * the pagecache. We avoid the penalty of instantiating all the * pages, important if the user is just writing to a few and never * uses the object on the GPU, and using a direct write into shmemfs * allows it to avoid the cost of retrieving a page (either swapin * or clearing-before-use) before it is overwritten.
*/ if (i915_gem_object_has_pages(obj)) return -ENODEV;
if (obj->mm.madv != I915_MADV_WILLNEED) return -EFAULT;
/* XXX: The __shmem_file_setup() function returns -EINVAL if size is * greater than MAX_LFS_FILESIZE. * To handle the same error as other code that returns -E2BIG when * the size is too large, we add a code that returns -E2BIG when the * size is larger than the size that can be handled. * If BITS_PER_LONG is 32, size > MAX_LFS_FILESIZE is always false, * so we only needs to check when BITS_PER_LONG is 64. * If BITS_PER_LONG is 32, E2BIG checks are processed when * i915_gem_object_size_2big() is called before init_object() callback * is called.
*/ if (BITS_PER_LONG == 64 && size > MAX_LFS_FILESIZE) return -E2BIG;
if (i915->mm.gemfs)
filp = shmem_file_setup_with_mnt(i915->mm.gemfs, "i915", size,
flags); else
filp = shmem_file_setup("i915", size, flags); if (IS_ERR(filp)) return PTR_ERR(filp);
/* * Prevent -EFBIG by allowing large writes beyond MAX_NON_LFS on shmem * objects by setting O_LARGEFILE.
*/ if (force_o_largefile())
filp->f_flags |= O_LARGEFILE;
/* * MTL doesn't snoop CPU cache by default for GPU access (namely * 1-way coherency). However some UMD's are currently depending on * that. Make 1-way coherent the default setting for MTL. A follow * up patch will extend the GEM_CREATE uAPI to allow UMD's specify * caching mode at BO creation time
*/ if (HAS_LLC(i915) || (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))) /* On some devices, we can have the GPU use the LLC (the CPU * cache) for about a 10% performance improvement * compared to uncached. Graphics requests other than * display scanout are coherent with the CPU in * accessing this cache. This means in this mode we * don't need to clflush on the CPU side, and on the * GPU side we only need to flush internal caches to * get data visible to the CPU. * * However, we maintain the display planes as UC, and so * need to rebind when first used as such.
*/
cache_level = I915_CACHE_LLC; else
cache_level = I915_CACHE_NONE;
/* Allocate a new GEM object and fill it with the supplied data */ struct drm_i915_gem_object *
i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915, constvoid *data, resource_size_t size)
{ struct drm_i915_gem_object *obj; struct file *file;
loff_t pos = 0;
ssize_t err;
GEM_WARN_ON(IS_DGFX(i915));
obj = i915_gem_object_create_shmem(i915, round_up(size, PAGE_SIZE)); if (IS_ERR(obj)) return obj;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.