162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright © 2008-2010 Intel Corporation 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * The above copyright notice and this permission notice (including the next 1262306a36Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 1362306a36Sopenharmony_ci * Software. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1862306a36Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1962306a36Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2062306a36Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2162306a36Sopenharmony_ci * IN THE SOFTWARE. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Authors: 2462306a36Sopenharmony_ci * Eric Anholt <eric@anholt.net> 2562306a36Sopenharmony_ci * Chris Wilson <chris@chris-wilson.co.uuk> 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include "gem/i915_gem_context.h" 3062306a36Sopenharmony_ci#include "gt/intel_gt.h" 3162306a36Sopenharmony_ci#include "gt/intel_gt_requests.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include "i915_drv.h" 3462306a36Sopenharmony_ci#include "i915_gem_evict.h" 3562306a36Sopenharmony_ci#include "i915_trace.h" 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciI915_SELFTEST_DECLARE(static struct igt_evict_ctl { 3862306a36Sopenharmony_ci bool fail_if_busy:1; 3962306a36Sopenharmony_ci} igt_evict_ctl;) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic bool dying_vma(struct i915_vma *vma) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci return !kref_read(&vma->obj->base.refcount); 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic int ggtt_flush(struct i915_address_space *vm) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); 4962306a36Sopenharmony_ci struct intel_gt *gt; 5062306a36Sopenharmony_ci int ret = 0; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci list_for_each_entry(gt, &ggtt->gt_list, ggtt_link) { 5362306a36Sopenharmony_ci /* 5462306a36Sopenharmony_ci * Not everything in the GGTT is tracked via vma (otherwise we 5562306a36Sopenharmony_ci * could evict as required with minimal stalling) so we are forced 5662306a36Sopenharmony_ci * to idle the GPU and explicitly retire outstanding requests in 5762306a36Sopenharmony_ci * the hopes that we can then remove contexts and the like only 5862306a36Sopenharmony_ci * bound by their active reference. 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_ci ret = intel_gt_wait_for_idle(gt, MAX_SCHEDULE_TIMEOUT); 6162306a36Sopenharmony_ci if (ret) 6262306a36Sopenharmony_ci return ret; 6362306a36Sopenharmony_ci } 6462306a36Sopenharmony_ci return ret; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic bool grab_vma(struct i915_vma *vma, struct i915_gem_ww_ctx *ww) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci /* 7062306a36Sopenharmony_ci * We add the extra refcount so the object doesn't drop to zero until 7162306a36Sopenharmony_ci * after ungrab_vma(), this way trylock is always paired with unlock. 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_ci if (i915_gem_object_get_rcu(vma->obj)) { 7462306a36Sopenharmony_ci if (!i915_gem_object_trylock(vma->obj, ww)) { 7562306a36Sopenharmony_ci i915_gem_object_put(vma->obj); 7662306a36Sopenharmony_ci return false; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci } else { 7962306a36Sopenharmony_ci /* Dead objects don't need pins */ 8062306a36Sopenharmony_ci atomic_and(~I915_VMA_PIN_MASK, &vma->flags); 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci return true; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic void ungrab_vma(struct i915_vma *vma) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci if (dying_vma(vma)) 8962306a36Sopenharmony_ci return; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci i915_gem_object_unlock(vma->obj); 9262306a36Sopenharmony_ci i915_gem_object_put(vma->obj); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic bool 9662306a36Sopenharmony_cimark_free(struct drm_mm_scan *scan, 9762306a36Sopenharmony_ci struct i915_gem_ww_ctx *ww, 9862306a36Sopenharmony_ci struct i915_vma *vma, 9962306a36Sopenharmony_ci unsigned int flags, 10062306a36Sopenharmony_ci struct list_head *unwind) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci if (i915_vma_is_pinned(vma)) 10362306a36Sopenharmony_ci return false; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci if (!grab_vma(vma, ww)) 10662306a36Sopenharmony_ci return false; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci list_add(&vma->evict_link, unwind); 10962306a36Sopenharmony_ci return drm_mm_scan_add_block(scan, &vma->node); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic bool defer_evict(struct i915_vma *vma) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci if (i915_vma_is_active(vma)) 11562306a36Sopenharmony_ci return true; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci if (i915_vma_is_scanout(vma)) 11862306a36Sopenharmony_ci return true; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci return false; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci/** 12462306a36Sopenharmony_ci * i915_gem_evict_something - Evict vmas to make room for binding a new one 12562306a36Sopenharmony_ci * @vm: address space to evict from 12662306a36Sopenharmony_ci * @ww: An optional struct i915_gem_ww_ctx. 12762306a36Sopenharmony_ci * @min_size: size of the desired free space 12862306a36Sopenharmony_ci * @alignment: alignment constraint of the desired free space 12962306a36Sopenharmony_ci * @color: color for the desired space 13062306a36Sopenharmony_ci * @start: start (inclusive) of the range from which to evict objects 13162306a36Sopenharmony_ci * @end: end (exclusive) of the range from which to evict objects 13262306a36Sopenharmony_ci * @flags: additional flags to control the eviction algorithm 13362306a36Sopenharmony_ci * 13462306a36Sopenharmony_ci * This function will try to evict vmas until a free space satisfying the 13562306a36Sopenharmony_ci * requirements is found. Callers must check first whether any such hole exists 13662306a36Sopenharmony_ci * already before calling this function. 13762306a36Sopenharmony_ci * 13862306a36Sopenharmony_ci * This function is used by the object/vma binding code. 13962306a36Sopenharmony_ci * 14062306a36Sopenharmony_ci * Since this function is only used to free up virtual address space it only 14162306a36Sopenharmony_ci * ignores pinned vmas, and not object where the backing storage itself is 14262306a36Sopenharmony_ci * pinned. Hence obj->pages_pin_count does not protect against eviction. 14362306a36Sopenharmony_ci * 14462306a36Sopenharmony_ci * To clarify: This is for freeing up virtual address space, not for freeing 14562306a36Sopenharmony_ci * memory in e.g. the shrinker. 14662306a36Sopenharmony_ci */ 14762306a36Sopenharmony_ciint 14862306a36Sopenharmony_cii915_gem_evict_something(struct i915_address_space *vm, 14962306a36Sopenharmony_ci struct i915_gem_ww_ctx *ww, 15062306a36Sopenharmony_ci u64 min_size, u64 alignment, 15162306a36Sopenharmony_ci unsigned long color, 15262306a36Sopenharmony_ci u64 start, u64 end, 15362306a36Sopenharmony_ci unsigned flags) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci struct drm_mm_scan scan; 15662306a36Sopenharmony_ci struct list_head eviction_list; 15762306a36Sopenharmony_ci struct i915_vma *vma, *next; 15862306a36Sopenharmony_ci struct drm_mm_node *node; 15962306a36Sopenharmony_ci enum drm_mm_insert_mode mode; 16062306a36Sopenharmony_ci struct i915_vma *active; 16162306a36Sopenharmony_ci struct intel_gt *gt; 16262306a36Sopenharmony_ci int ret; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci lockdep_assert_held(&vm->mutex); 16562306a36Sopenharmony_ci trace_i915_gem_evict(vm, min_size, alignment, flags); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci /* 16862306a36Sopenharmony_ci * The goal is to evict objects and amalgamate space in rough LRU order. 16962306a36Sopenharmony_ci * Since both active and inactive objects reside on the same list, 17062306a36Sopenharmony_ci * in a mix of creation and last scanned order, as we process the list 17162306a36Sopenharmony_ci * we sort it into inactive/active, which keeps the active portion 17262306a36Sopenharmony_ci * in a rough MRU order. 17362306a36Sopenharmony_ci * 17462306a36Sopenharmony_ci * The retirement sequence is thus: 17562306a36Sopenharmony_ci * 1. Inactive objects (already retired, random order) 17662306a36Sopenharmony_ci * 2. Active objects (will stall on unbinding, oldest scanned first) 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_ci mode = DRM_MM_INSERT_BEST; 17962306a36Sopenharmony_ci if (flags & PIN_HIGH) 18062306a36Sopenharmony_ci mode = DRM_MM_INSERT_HIGH; 18162306a36Sopenharmony_ci if (flags & PIN_MAPPABLE) 18262306a36Sopenharmony_ci mode = DRM_MM_INSERT_LOW; 18362306a36Sopenharmony_ci drm_mm_scan_init_with_range(&scan, &vm->mm, 18462306a36Sopenharmony_ci min_size, alignment, color, 18562306a36Sopenharmony_ci start, end, mode); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci if (i915_is_ggtt(vm)) { 18862306a36Sopenharmony_ci struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci list_for_each_entry(gt, &ggtt->gt_list, ggtt_link) 19162306a36Sopenharmony_ci intel_gt_retire_requests(gt); 19262306a36Sopenharmony_ci } else { 19362306a36Sopenharmony_ci intel_gt_retire_requests(vm->gt); 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cisearch_again: 19762306a36Sopenharmony_ci active = NULL; 19862306a36Sopenharmony_ci INIT_LIST_HEAD(&eviction_list); 19962306a36Sopenharmony_ci list_for_each_entry_safe(vma, next, &vm->bound_list, vm_link) { 20062306a36Sopenharmony_ci if (vma == active) { /* now seen this vma twice */ 20162306a36Sopenharmony_ci if (flags & PIN_NONBLOCK) 20262306a36Sopenharmony_ci break; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci active = ERR_PTR(-EAGAIN); 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* 20862306a36Sopenharmony_ci * We keep this list in a rough least-recently scanned order 20962306a36Sopenharmony_ci * of active elements (inactive elements are cheap to reap). 21062306a36Sopenharmony_ci * New entries are added to the end, and we move anything we 21162306a36Sopenharmony_ci * scan to the end. The assumption is that the working set 21262306a36Sopenharmony_ci * of applications is either steady state (and thanks to the 21362306a36Sopenharmony_ci * userspace bo cache it almost always is) or volatile and 21462306a36Sopenharmony_ci * frequently replaced after a frame, which are self-evicting! 21562306a36Sopenharmony_ci * Given that assumption, the MRU order of the scan list is 21662306a36Sopenharmony_ci * fairly static, and keeping it in least-recently scan order 21762306a36Sopenharmony_ci * is suitable. 21862306a36Sopenharmony_ci * 21962306a36Sopenharmony_ci * To notice when we complete one full cycle, we record the 22062306a36Sopenharmony_ci * first active element seen, before moving it to the tail. 22162306a36Sopenharmony_ci */ 22262306a36Sopenharmony_ci if (active != ERR_PTR(-EAGAIN) && defer_evict(vma)) { 22362306a36Sopenharmony_ci if (!active) 22462306a36Sopenharmony_ci active = vma; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci list_move_tail(&vma->vm_link, &vm->bound_list); 22762306a36Sopenharmony_ci continue; 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci if (mark_free(&scan, ww, vma, flags, &eviction_list)) 23162306a36Sopenharmony_ci goto found; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci /* Nothing found, clean up and bail out! */ 23562306a36Sopenharmony_ci list_for_each_entry_safe(vma, next, &eviction_list, evict_link) { 23662306a36Sopenharmony_ci ret = drm_mm_scan_remove_block(&scan, &vma->node); 23762306a36Sopenharmony_ci BUG_ON(ret); 23862306a36Sopenharmony_ci ungrab_vma(vma); 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci /* 24262306a36Sopenharmony_ci * Can we unpin some objects such as idle hw contents, 24362306a36Sopenharmony_ci * or pending flips? But since only the GGTT has global entries 24462306a36Sopenharmony_ci * such as scanouts, rinbuffers and contexts, we can skip the 24562306a36Sopenharmony_ci * purge when inspecting per-process local address spaces. 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_ci if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK) 24862306a36Sopenharmony_ci return -ENOSPC; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* 25162306a36Sopenharmony_ci * Not everything in the GGTT is tracked via VMA using 25262306a36Sopenharmony_ci * i915_vma_move_to_active(), otherwise we could evict as required 25362306a36Sopenharmony_ci * with minimal stalling. Instead we are forced to idle the GPU and 25462306a36Sopenharmony_ci * explicitly retire outstanding requests which will then remove 25562306a36Sopenharmony_ci * the pinning for active objects such as contexts and ring, 25662306a36Sopenharmony_ci * enabling us to evict them on the next iteration. 25762306a36Sopenharmony_ci * 25862306a36Sopenharmony_ci * To ensure that all user contexts are evictable, we perform 25962306a36Sopenharmony_ci * a switch to the perma-pinned kernel context. This all also gives 26062306a36Sopenharmony_ci * us a termination condition, when the last retired context is 26162306a36Sopenharmony_ci * the kernel's there is no more we can evict. 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ci if (I915_SELFTEST_ONLY(igt_evict_ctl.fail_if_busy)) 26462306a36Sopenharmony_ci return -EBUSY; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci ret = ggtt_flush(vm); 26762306a36Sopenharmony_ci if (ret) 26862306a36Sopenharmony_ci return ret; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci cond_resched(); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci flags |= PIN_NONBLOCK; 27362306a36Sopenharmony_ci goto search_again; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_cifound: 27662306a36Sopenharmony_ci /* drm_mm doesn't allow any other other operations while 27762306a36Sopenharmony_ci * scanning, therefore store to-be-evicted objects on a 27862306a36Sopenharmony_ci * temporary list and take a reference for all before 27962306a36Sopenharmony_ci * calling unbind (which may remove the active reference 28062306a36Sopenharmony_ci * of any of our objects, thus corrupting the list). 28162306a36Sopenharmony_ci */ 28262306a36Sopenharmony_ci list_for_each_entry_safe(vma, next, &eviction_list, evict_link) { 28362306a36Sopenharmony_ci if (drm_mm_scan_remove_block(&scan, &vma->node)) { 28462306a36Sopenharmony_ci __i915_vma_pin(vma); 28562306a36Sopenharmony_ci } else { 28662306a36Sopenharmony_ci list_del(&vma->evict_link); 28762306a36Sopenharmony_ci ungrab_vma(vma); 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci /* Unbinding will emit any required flushes */ 29262306a36Sopenharmony_ci ret = 0; 29362306a36Sopenharmony_ci list_for_each_entry_safe(vma, next, &eviction_list, evict_link) { 29462306a36Sopenharmony_ci __i915_vma_unpin(vma); 29562306a36Sopenharmony_ci if (ret == 0) 29662306a36Sopenharmony_ci ret = __i915_vma_unbind(vma); 29762306a36Sopenharmony_ci ungrab_vma(vma); 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci while (ret == 0 && (node = drm_mm_scan_color_evict(&scan))) { 30162306a36Sopenharmony_ci vma = container_of(node, struct i915_vma, node); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci /* If we find any non-objects (!vma), we cannot evict them */ 30462306a36Sopenharmony_ci if (vma->node.color != I915_COLOR_UNEVICTABLE && 30562306a36Sopenharmony_ci grab_vma(vma, ww)) { 30662306a36Sopenharmony_ci ret = __i915_vma_unbind(vma); 30762306a36Sopenharmony_ci ungrab_vma(vma); 30862306a36Sopenharmony_ci } else { 30962306a36Sopenharmony_ci ret = -ENOSPC; 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci return ret; 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci/** 31762306a36Sopenharmony_ci * i915_gem_evict_for_node - Evict vmas to make room for binding a new one 31862306a36Sopenharmony_ci * @vm: address space to evict from 31962306a36Sopenharmony_ci * @ww: An optional struct i915_gem_ww_ctx. 32062306a36Sopenharmony_ci * @target: range (and color) to evict for 32162306a36Sopenharmony_ci * @flags: additional flags to control the eviction algorithm 32262306a36Sopenharmony_ci * 32362306a36Sopenharmony_ci * This function will try to evict vmas that overlap the target node. 32462306a36Sopenharmony_ci * 32562306a36Sopenharmony_ci * To clarify: This is for freeing up virtual address space, not for freeing 32662306a36Sopenharmony_ci * memory in e.g. the shrinker. 32762306a36Sopenharmony_ci */ 32862306a36Sopenharmony_ciint i915_gem_evict_for_node(struct i915_address_space *vm, 32962306a36Sopenharmony_ci struct i915_gem_ww_ctx *ww, 33062306a36Sopenharmony_ci struct drm_mm_node *target, 33162306a36Sopenharmony_ci unsigned int flags) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci LIST_HEAD(eviction_list); 33462306a36Sopenharmony_ci struct drm_mm_node *node; 33562306a36Sopenharmony_ci u64 start = target->start; 33662306a36Sopenharmony_ci u64 end = start + target->size; 33762306a36Sopenharmony_ci struct i915_vma *vma, *next; 33862306a36Sopenharmony_ci int ret = 0; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci lockdep_assert_held(&vm->mutex); 34162306a36Sopenharmony_ci GEM_BUG_ON(!IS_ALIGNED(start, I915_GTT_PAGE_SIZE)); 34262306a36Sopenharmony_ci GEM_BUG_ON(!IS_ALIGNED(end, I915_GTT_PAGE_SIZE)); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci trace_i915_gem_evict_node(vm, target, flags); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci /* 34762306a36Sopenharmony_ci * Retire before we search the active list. Although we have 34862306a36Sopenharmony_ci * reasonable accuracy in our retirement lists, we may have 34962306a36Sopenharmony_ci * a stray pin (preventing eviction) that can only be resolved by 35062306a36Sopenharmony_ci * retiring. 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_ci if (i915_is_ggtt(vm)) { 35362306a36Sopenharmony_ci struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); 35462306a36Sopenharmony_ci struct intel_gt *gt; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci list_for_each_entry(gt, &ggtt->gt_list, ggtt_link) 35762306a36Sopenharmony_ci intel_gt_retire_requests(gt); 35862306a36Sopenharmony_ci } else { 35962306a36Sopenharmony_ci intel_gt_retire_requests(vm->gt); 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (i915_vm_has_cache_coloring(vm)) { 36362306a36Sopenharmony_ci /* Expand search to cover neighbouring guard pages (or lack!) */ 36462306a36Sopenharmony_ci if (start) 36562306a36Sopenharmony_ci start -= I915_GTT_PAGE_SIZE; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci /* Always look at the page afterwards to avoid the end-of-GTT */ 36862306a36Sopenharmony_ci end += I915_GTT_PAGE_SIZE; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci GEM_BUG_ON(start >= end); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci drm_mm_for_each_node_in_range(node, &vm->mm, start, end) { 37362306a36Sopenharmony_ci /* If we find any non-objects (!vma), we cannot evict them */ 37462306a36Sopenharmony_ci if (node->color == I915_COLOR_UNEVICTABLE) { 37562306a36Sopenharmony_ci ret = -ENOSPC; 37662306a36Sopenharmony_ci break; 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci GEM_BUG_ON(!drm_mm_node_allocated(node)); 38062306a36Sopenharmony_ci vma = container_of(node, typeof(*vma), node); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* 38362306a36Sopenharmony_ci * If we are using coloring to insert guard pages between 38462306a36Sopenharmony_ci * different cache domains within the address space, we have 38562306a36Sopenharmony_ci * to check whether the objects on either side of our range 38662306a36Sopenharmony_ci * abutt and conflict. If they are in conflict, then we evict 38762306a36Sopenharmony_ci * those as well to make room for our guard pages. 38862306a36Sopenharmony_ci */ 38962306a36Sopenharmony_ci if (i915_vm_has_cache_coloring(vm)) { 39062306a36Sopenharmony_ci if (node->start + node->size == target->start) { 39162306a36Sopenharmony_ci if (node->color == target->color) 39262306a36Sopenharmony_ci continue; 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci if (node->start == target->start + target->size) { 39562306a36Sopenharmony_ci if (node->color == target->color) 39662306a36Sopenharmony_ci continue; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci if (i915_vma_is_pinned(vma)) { 40162306a36Sopenharmony_ci ret = -ENOSPC; 40262306a36Sopenharmony_ci break; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (flags & PIN_NONBLOCK && i915_vma_is_active(vma)) { 40662306a36Sopenharmony_ci ret = -ENOSPC; 40762306a36Sopenharmony_ci break; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci if (!grab_vma(vma, ww)) { 41162306a36Sopenharmony_ci ret = -ENOSPC; 41262306a36Sopenharmony_ci break; 41362306a36Sopenharmony_ci } 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci /* 41662306a36Sopenharmony_ci * Never show fear in the face of dragons! 41762306a36Sopenharmony_ci * 41862306a36Sopenharmony_ci * We cannot directly remove this node from within this 41962306a36Sopenharmony_ci * iterator and as with i915_gem_evict_something() we employ 42062306a36Sopenharmony_ci * the vma pin_count in order to prevent the action of 42162306a36Sopenharmony_ci * unbinding one vma from freeing (by dropping its active 42262306a36Sopenharmony_ci * reference) another in our eviction list. 42362306a36Sopenharmony_ci */ 42462306a36Sopenharmony_ci __i915_vma_pin(vma); 42562306a36Sopenharmony_ci list_add(&vma->evict_link, &eviction_list); 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci list_for_each_entry_safe(vma, next, &eviction_list, evict_link) { 42962306a36Sopenharmony_ci __i915_vma_unpin(vma); 43062306a36Sopenharmony_ci if (ret == 0) 43162306a36Sopenharmony_ci ret = __i915_vma_unbind(vma); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci ungrab_vma(vma); 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci return ret; 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci/** 44062306a36Sopenharmony_ci * i915_gem_evict_vm - Evict all idle vmas from a vm 44162306a36Sopenharmony_ci * @vm: Address space to cleanse 44262306a36Sopenharmony_ci * @ww: An optional struct i915_gem_ww_ctx. If not NULL, i915_gem_evict_vm 44362306a36Sopenharmony_ci * will be able to evict vma's locked by the ww as well. 44462306a36Sopenharmony_ci * @busy_bo: Optional pointer to struct drm_i915_gem_object. If not NULL, then 44562306a36Sopenharmony_ci * in the event i915_gem_evict_vm() is unable to trylock an object for eviction, 44662306a36Sopenharmony_ci * then @busy_bo will point to it. -EBUSY is also returned. The caller must drop 44762306a36Sopenharmony_ci * the vm->mutex, before trying again to acquire the contended lock. The caller 44862306a36Sopenharmony_ci * also owns a reference to the object. 44962306a36Sopenharmony_ci * 45062306a36Sopenharmony_ci * This function evicts all vmas from a vm. 45162306a36Sopenharmony_ci * 45262306a36Sopenharmony_ci * This is used by the execbuf code as a last-ditch effort to defragment the 45362306a36Sopenharmony_ci * address space. 45462306a36Sopenharmony_ci * 45562306a36Sopenharmony_ci * To clarify: This is for freeing up virtual address space, not for freeing 45662306a36Sopenharmony_ci * memory in e.g. the shrinker. 45762306a36Sopenharmony_ci */ 45862306a36Sopenharmony_ciint i915_gem_evict_vm(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww, 45962306a36Sopenharmony_ci struct drm_i915_gem_object **busy_bo) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci int ret = 0; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci lockdep_assert_held(&vm->mutex); 46462306a36Sopenharmony_ci trace_i915_gem_evict_vm(vm); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci /* Switch back to the default context in order to unpin 46762306a36Sopenharmony_ci * the existing context objects. However, such objects only 46862306a36Sopenharmony_ci * pin themselves inside the global GTT and performing the 46962306a36Sopenharmony_ci * switch otherwise is ineffective. 47062306a36Sopenharmony_ci */ 47162306a36Sopenharmony_ci if (i915_is_ggtt(vm)) { 47262306a36Sopenharmony_ci ret = ggtt_flush(vm); 47362306a36Sopenharmony_ci if (ret) 47462306a36Sopenharmony_ci return ret; 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci do { 47862306a36Sopenharmony_ci struct i915_vma *vma, *vn; 47962306a36Sopenharmony_ci LIST_HEAD(eviction_list); 48062306a36Sopenharmony_ci LIST_HEAD(locked_eviction_list); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci list_for_each_entry(vma, &vm->bound_list, vm_link) { 48362306a36Sopenharmony_ci if (i915_vma_is_pinned(vma)) 48462306a36Sopenharmony_ci continue; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci /* 48762306a36Sopenharmony_ci * If we already own the lock, trylock fails. In case 48862306a36Sopenharmony_ci * the resv is shared among multiple objects, we still 48962306a36Sopenharmony_ci * need the object ref. 49062306a36Sopenharmony_ci */ 49162306a36Sopenharmony_ci if (!i915_gem_object_get_rcu(vma->obj) || 49262306a36Sopenharmony_ci (ww && (dma_resv_locking_ctx(vma->obj->base.resv) == &ww->ctx))) { 49362306a36Sopenharmony_ci __i915_vma_pin(vma); 49462306a36Sopenharmony_ci list_add(&vma->evict_link, &locked_eviction_list); 49562306a36Sopenharmony_ci continue; 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci if (!i915_gem_object_trylock(vma->obj, ww)) { 49962306a36Sopenharmony_ci if (busy_bo) { 50062306a36Sopenharmony_ci *busy_bo = vma->obj; /* holds ref */ 50162306a36Sopenharmony_ci ret = -EBUSY; 50262306a36Sopenharmony_ci break; 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci i915_gem_object_put(vma->obj); 50562306a36Sopenharmony_ci continue; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci __i915_vma_pin(vma); 50962306a36Sopenharmony_ci list_add(&vma->evict_link, &eviction_list); 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci if (list_empty(&eviction_list) && list_empty(&locked_eviction_list)) 51262306a36Sopenharmony_ci break; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci /* Unbind locked objects first, before unlocking the eviction_list */ 51562306a36Sopenharmony_ci list_for_each_entry_safe(vma, vn, &locked_eviction_list, evict_link) { 51662306a36Sopenharmony_ci __i915_vma_unpin(vma); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci if (ret == 0) { 51962306a36Sopenharmony_ci ret = __i915_vma_unbind(vma); 52062306a36Sopenharmony_ci if (ret != -EINTR) /* "Get me out of here!" */ 52162306a36Sopenharmony_ci ret = 0; 52262306a36Sopenharmony_ci } 52362306a36Sopenharmony_ci if (!dying_vma(vma)) 52462306a36Sopenharmony_ci i915_gem_object_put(vma->obj); 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci list_for_each_entry_safe(vma, vn, &eviction_list, evict_link) { 52862306a36Sopenharmony_ci __i915_vma_unpin(vma); 52962306a36Sopenharmony_ci if (ret == 0) { 53062306a36Sopenharmony_ci ret = __i915_vma_unbind(vma); 53162306a36Sopenharmony_ci if (ret != -EINTR) /* "Get me out of here!" */ 53262306a36Sopenharmony_ci ret = 0; 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci i915_gem_object_unlock(vma->obj); 53662306a36Sopenharmony_ci i915_gem_object_put(vma->obj); 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci } while (ret == 0); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci return ret; 54162306a36Sopenharmony_ci} 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) 54462306a36Sopenharmony_ci#include "selftests/i915_gem_evict.c" 54562306a36Sopenharmony_ci#endif 546