brintos

brintos / linux-shallow public Read only

0
0
Text · 67.0 KiB · c0543c3 Raw
2730 lines · c
1/*2 * SPDX-License-Identifier: MIT3 *4 * Copyright © 2011-2012 Intel Corporation5 */6 7/*8 * This file implements HW context support. On gen5+ a HW context consists of an9 * opaque GPU object which is referenced at times of context saves and restores.10 * With RC6 enabled, the context is also referenced as the GPU enters and exists11 * from RC6 (GPU has it's own internal power context, except on gen5). Though12 * something like a context does exist for the media ring, the code only13 * supports contexts for the render ring.14 *15 * In software, there is a distinction between contexts created by the user,16 * and the default HW context. The default HW context is used by GPU clients17 * that do not request setup of their own hardware context. The default18 * context's state is never restored to help prevent programming errors. This19 * would happen if a client ran and piggy-backed off another clients GPU state.20 * The default context only exists to give the GPU some offset to load as the21 * current to invoke a save of the context we actually care about. In fact, the22 * code could likely be constructed, albeit in a more complicated fashion, to23 * never use the default context, though that limits the driver's ability to24 * swap out, and/or destroy other contexts.25 *26 * All other contexts are created as a request by the GPU client. These contexts27 * store GPU state, and thus allow GPU clients to not re-emit state (and28 * potentially query certain state) at any time. The kernel driver makes29 * certain that the appropriate commands are inserted.30 *31 * The context life cycle is semi-complicated in that context BOs may live32 * longer than the context itself because of the way the hardware, and object33 * tracking works. Below is a very crude representation of the state machine34 * describing the context life.35 *                                         refcount     pincount     active36 * S0: initial state                          0            0           037 * S1: context created                        1            0           038 * S2: context is currently running           2            1           X39 * S3: GPU referenced, but not current        2            0           140 * S4: context is current, but destroyed      1            1           041 * S5: like S3, but destroyed                 1            0           142 *43 * The most common (but not all) transitions:44 * S0->S1: client creates a context45 * S1->S2: client submits execbuf with context46 * S2->S3: other clients submits execbuf with context47 * S3->S1: context object was retired48 * S3->S2: clients submits another execbuf49 * S2->S4: context destroy called with current context50 * S3->S5->S0: destroy path51 * S4->S5->S0: destroy path on current context52 *53 * There are two confusing terms used above:54 *  The "current context" means the context which is currently running on the55 *  GPU. The GPU has loaded its state already and has stored away the gtt56 *  offset of the BO. The GPU is not actively referencing the data at this57 *  offset, but it will on the next context switch. The only way to avoid this58 *  is to do a GPU reset.59 *60 *  An "active context' is one which was previously the "current context" and is61 *  on the active list waiting for the next context switch to occur. Until this62 *  happens, the object must remain at the same gtt offset. It is therefore63 *  possible to destroy a context, but it is still active.64 *65 */66 67#include <linux/highmem.h>68#include <linux/log2.h>69#include <linux/nospec.h>70 71#include <drm/drm_cache.h>72#include <drm/drm_syncobj.h>73 74#include "gt/gen6_ppgtt.h"75#include "gt/intel_context.h"76#include "gt/intel_context_param.h"77#include "gt/intel_engine_heartbeat.h"78#include "gt/intel_engine_user.h"79#include "gt/intel_gpu_commands.h"80#include "gt/intel_ring.h"81#include "gt/shmem_utils.h"82 83#include "pxp/intel_pxp.h"84 85#include "i915_file_private.h"86#include "i915_gem_context.h"87#include "i915_trace.h"88#include "i915_user_extensions.h"89 90#define ALL_L3_SLICES(dev) (1 << NUM_L3_SLICES(dev)) - 191 92static struct kmem_cache *slab_luts;93 94struct i915_lut_handle *i915_lut_handle_alloc(void)95{96	return kmem_cache_alloc(slab_luts, GFP_KERNEL);97}98 99void i915_lut_handle_free(struct i915_lut_handle *lut)100{101	return kmem_cache_free(slab_luts, lut);102}103 104static void lut_close(struct i915_gem_context *ctx)105{106	struct radix_tree_iter iter;107	void __rcu **slot;108 109	mutex_lock(&ctx->lut_mutex);110	rcu_read_lock();111	radix_tree_for_each_slot(slot, &ctx->handles_vma, &iter, 0) {112		struct i915_vma *vma = rcu_dereference_raw(*slot);113		struct drm_i915_gem_object *obj = vma->obj;114		struct i915_lut_handle *lut;115 116		if (!kref_get_unless_zero(&obj->base.refcount))117			continue;118 119		spin_lock(&obj->lut_lock);120		list_for_each_entry(lut, &obj->lut_list, obj_link) {121			if (lut->ctx != ctx)122				continue;123 124			if (lut->handle != iter.index)125				continue;126 127			list_del(&lut->obj_link);128			break;129		}130		spin_unlock(&obj->lut_lock);131 132		if (&lut->obj_link != &obj->lut_list) {133			i915_lut_handle_free(lut);134			radix_tree_iter_delete(&ctx->handles_vma, &iter, slot);135			i915_vma_close(vma);136			i915_gem_object_put(obj);137		}138 139		i915_gem_object_put(obj);140	}141	rcu_read_unlock();142	mutex_unlock(&ctx->lut_mutex);143}144 145static struct intel_context *146lookup_user_engine(struct i915_gem_context *ctx,147		   unsigned long flags,148		   const struct i915_engine_class_instance *ci)149#define LOOKUP_USER_INDEX BIT(0)150{151	int idx;152 153	if (!!(flags & LOOKUP_USER_INDEX) != i915_gem_context_user_engines(ctx))154		return ERR_PTR(-EINVAL);155 156	if (!i915_gem_context_user_engines(ctx)) {157		struct intel_engine_cs *engine;158 159		engine = intel_engine_lookup_user(ctx->i915,160						  ci->engine_class,161						  ci->engine_instance);162		if (!engine)163			return ERR_PTR(-EINVAL);164 165		idx = engine->legacy_idx;166	} else {167		idx = ci->engine_instance;168	}169 170	return i915_gem_context_get_engine(ctx, idx);171}172 173static int validate_priority(struct drm_i915_private *i915,174			     const struct drm_i915_gem_context_param *args)175{176	s64 priority = args->value;177 178	if (args->size)179		return -EINVAL;180 181	if (!(i915->caps.scheduler & I915_SCHEDULER_CAP_PRIORITY))182		return -ENODEV;183 184	if (priority > I915_CONTEXT_MAX_USER_PRIORITY ||185	    priority < I915_CONTEXT_MIN_USER_PRIORITY)186		return -EINVAL;187 188	if (priority > I915_CONTEXT_DEFAULT_PRIORITY &&189	    !capable(CAP_SYS_NICE))190		return -EPERM;191 192	return 0;193}194 195static void proto_context_close(struct drm_i915_private *i915,196				struct i915_gem_proto_context *pc)197{198	int i;199 200	if (pc->pxp_wakeref)201		intel_runtime_pm_put(&i915->runtime_pm, pc->pxp_wakeref);202	if (pc->vm)203		i915_vm_put(pc->vm);204	if (pc->user_engines) {205		for (i = 0; i < pc->num_user_engines; i++)206			kfree(pc->user_engines[i].siblings);207		kfree(pc->user_engines);208	}209	kfree(pc);210}211 212static int proto_context_set_persistence(struct drm_i915_private *i915,213					 struct i915_gem_proto_context *pc,214					 bool persist)215{216	if (persist) {217		/*218		 * Only contexts that are short-lived [that will expire or be219		 * reset] are allowed to survive past termination. We require220		 * hangcheck to ensure that the persistent requests are healthy.221		 */222		if (!i915->params.enable_hangcheck)223			return -EINVAL;224 225		pc->user_flags |= BIT(UCONTEXT_PERSISTENCE);226	} else {227		/* To cancel a context we use "preempt-to-idle" */228		if (!(i915->caps.scheduler & I915_SCHEDULER_CAP_PREEMPTION))229			return -ENODEV;230 231		/*232		 * If the cancel fails, we then need to reset, cleanly!233		 *234		 * If the per-engine reset fails, all hope is lost! We resort235		 * to a full GPU reset in that unlikely case, but realistically236		 * if the engine could not reset, the full reset does not fare237		 * much better. The damage has been done.238		 *239		 * However, if we cannot reset an engine by itself, we cannot240		 * cleanup a hanging persistent context without causing241		 * colateral damage, and we should not pretend we can by242		 * exposing the interface.243		 */244		if (!intel_has_reset_engine(to_gt(i915)))245			return -ENODEV;246 247		pc->user_flags &= ~BIT(UCONTEXT_PERSISTENCE);248	}249 250	return 0;251}252 253static int proto_context_set_protected(struct drm_i915_private *i915,254				       struct i915_gem_proto_context *pc,255				       bool protected)256{257	int ret = 0;258 259	if (!protected) {260		pc->uses_protected_content = false;261	} else if (!intel_pxp_is_enabled(i915->pxp)) {262		ret = -ENODEV;263	} else if ((pc->user_flags & BIT(UCONTEXT_RECOVERABLE)) ||264		   !(pc->user_flags & BIT(UCONTEXT_BANNABLE))) {265		ret = -EPERM;266	} else {267		pc->uses_protected_content = true;268 269		/*270		 * protected context usage requires the PXP session to be up,271		 * which in turn requires the device to be active.272		 */273		pc->pxp_wakeref = intel_runtime_pm_get(&i915->runtime_pm);274 275		if (!intel_pxp_is_active(i915->pxp))276			ret = intel_pxp_start(i915->pxp);277	}278 279	return ret;280}281 282static struct i915_gem_proto_context *283proto_context_create(struct drm_i915_file_private *fpriv,284		     struct drm_i915_private *i915, unsigned int flags)285{286	struct i915_gem_proto_context *pc, *err;287 288	pc = kzalloc(sizeof(*pc), GFP_KERNEL);289	if (!pc)290		return ERR_PTR(-ENOMEM);291 292	pc->fpriv = fpriv;293	pc->num_user_engines = -1;294	pc->user_engines = NULL;295	pc->user_flags = BIT(UCONTEXT_BANNABLE) |296			 BIT(UCONTEXT_RECOVERABLE);297	if (i915->params.enable_hangcheck)298		pc->user_flags |= BIT(UCONTEXT_PERSISTENCE);299	pc->sched.priority = I915_PRIORITY_NORMAL;300 301	if (flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE) {302		if (!HAS_EXECLISTS(i915)) {303			err = ERR_PTR(-EINVAL);304			goto proto_close;305		}306		pc->single_timeline = true;307	}308 309	return pc;310 311proto_close:312	proto_context_close(i915, pc);313	return err;314}315 316static int proto_context_register_locked(struct drm_i915_file_private *fpriv,317					 struct i915_gem_proto_context *pc,318					 u32 *id)319{320	int ret;321	void *old;322 323	lockdep_assert_held(&fpriv->proto_context_lock);324 325	ret = xa_alloc(&fpriv->context_xa, id, NULL, xa_limit_32b, GFP_KERNEL);326	if (ret)327		return ret;328 329	old = xa_store(&fpriv->proto_context_xa, *id, pc, GFP_KERNEL);330	if (xa_is_err(old)) {331		xa_erase(&fpriv->context_xa, *id);332		return xa_err(old);333	}334	WARN_ON(old);335 336	return 0;337}338 339static int proto_context_register(struct drm_i915_file_private *fpriv,340				  struct i915_gem_proto_context *pc,341				  u32 *id)342{343	int ret;344 345	mutex_lock(&fpriv->proto_context_lock);346	ret = proto_context_register_locked(fpriv, pc, id);347	mutex_unlock(&fpriv->proto_context_lock);348 349	return ret;350}351 352static struct i915_address_space *353i915_gem_vm_lookup(struct drm_i915_file_private *file_priv, u32 id)354{355	struct i915_address_space *vm;356 357	xa_lock(&file_priv->vm_xa);358	vm = xa_load(&file_priv->vm_xa, id);359	if (vm)360		kref_get(&vm->ref);361	xa_unlock(&file_priv->vm_xa);362 363	return vm;364}365 366static int set_proto_ctx_vm(struct drm_i915_file_private *fpriv,367			    struct i915_gem_proto_context *pc,368			    const struct drm_i915_gem_context_param *args)369{370	struct drm_i915_private *i915 = fpriv->i915;371	struct i915_address_space *vm;372 373	if (args->size)374		return -EINVAL;375 376	if (!HAS_FULL_PPGTT(i915))377		return -ENODEV;378 379	if (upper_32_bits(args->value))380		return -ENOENT;381 382	vm = i915_gem_vm_lookup(fpriv, args->value);383	if (!vm)384		return -ENOENT;385 386	if (pc->vm)387		i915_vm_put(pc->vm);388	pc->vm = vm;389 390	return 0;391}392 393struct set_proto_ctx_engines {394	struct drm_i915_private *i915;395	unsigned num_engines;396	struct i915_gem_proto_engine *engines;397};398 399static int400set_proto_ctx_engines_balance(struct i915_user_extension __user *base,401			      void *data)402{403	struct i915_context_engines_load_balance __user *ext =404		container_of_user(base, typeof(*ext), base);405	const struct set_proto_ctx_engines *set = data;406	struct drm_i915_private *i915 = set->i915;407	struct intel_engine_cs **siblings;408	u16 num_siblings, idx;409	unsigned int n;410	int err;411 412	if (!HAS_EXECLISTS(i915))413		return -ENODEV;414 415	if (get_user(idx, &ext->engine_index))416		return -EFAULT;417 418	if (idx >= set->num_engines) {419		drm_dbg(&i915->drm, "Invalid placement value, %d >= %d\n",420			idx, set->num_engines);421		return -EINVAL;422	}423 424	idx = array_index_nospec(idx, set->num_engines);425	if (set->engines[idx].type != I915_GEM_ENGINE_TYPE_INVALID) {426		drm_dbg(&i915->drm,427			"Invalid placement[%d], already occupied\n", idx);428		return -EEXIST;429	}430 431	if (get_user(num_siblings, &ext->num_siblings))432		return -EFAULT;433 434	err = check_user_mbz(&ext->flags);435	if (err)436		return err;437 438	err = check_user_mbz(&ext->mbz64);439	if (err)440		return err;441 442	if (num_siblings == 0)443		return 0;444 445	siblings = kmalloc_array(num_siblings, sizeof(*siblings), GFP_KERNEL);446	if (!siblings)447		return -ENOMEM;448 449	for (n = 0; n < num_siblings; n++) {450		struct i915_engine_class_instance ci;451 452		if (copy_from_user(&ci, &ext->engines[n], sizeof(ci))) {453			err = -EFAULT;454			goto err_siblings;455		}456 457		siblings[n] = intel_engine_lookup_user(i915,458						       ci.engine_class,459						       ci.engine_instance);460		if (!siblings[n]) {461			drm_dbg(&i915->drm,462				"Invalid sibling[%d]: { class:%d, inst:%d }\n",463				n, ci.engine_class, ci.engine_instance);464			err = -EINVAL;465			goto err_siblings;466		}467	}468 469	if (num_siblings == 1) {470		set->engines[idx].type = I915_GEM_ENGINE_TYPE_PHYSICAL;471		set->engines[idx].engine = siblings[0];472		kfree(siblings);473	} else {474		set->engines[idx].type = I915_GEM_ENGINE_TYPE_BALANCED;475		set->engines[idx].num_siblings = num_siblings;476		set->engines[idx].siblings = siblings;477	}478 479	return 0;480 481err_siblings:482	kfree(siblings);483 484	return err;485}486 487static int488set_proto_ctx_engines_bond(struct i915_user_extension __user *base, void *data)489{490	struct i915_context_engines_bond __user *ext =491		container_of_user(base, typeof(*ext), base);492	const struct set_proto_ctx_engines *set = data;493	struct drm_i915_private *i915 = set->i915;494	struct i915_engine_class_instance ci;495	struct intel_engine_cs *master;496	u16 idx, num_bonds;497	int err, n;498 499	if (GRAPHICS_VER(i915) >= 12 && !IS_TIGERLAKE(i915) &&500	    !IS_ROCKETLAKE(i915) && !IS_ALDERLAKE_S(i915)) {501		drm_dbg(&i915->drm,502			"Bonding not supported on this platform\n");503		return -ENODEV;504	}505 506	if (get_user(idx, &ext->virtual_index))507		return -EFAULT;508 509	if (idx >= set->num_engines) {510		drm_dbg(&i915->drm,511			"Invalid index for virtual engine: %d >= %d\n",512			idx, set->num_engines);513		return -EINVAL;514	}515 516	idx = array_index_nospec(idx, set->num_engines);517	if (set->engines[idx].type == I915_GEM_ENGINE_TYPE_INVALID) {518		drm_dbg(&i915->drm, "Invalid engine at %d\n", idx);519		return -EINVAL;520	}521 522	if (set->engines[idx].type != I915_GEM_ENGINE_TYPE_PHYSICAL) {523		drm_dbg(&i915->drm,524			"Bonding with virtual engines not allowed\n");525		return -EINVAL;526	}527 528	err = check_user_mbz(&ext->flags);529	if (err)530		return err;531 532	for (n = 0; n < ARRAY_SIZE(ext->mbz64); n++) {533		err = check_user_mbz(&ext->mbz64[n]);534		if (err)535			return err;536	}537 538	if (copy_from_user(&ci, &ext->master, sizeof(ci)))539		return -EFAULT;540 541	master = intel_engine_lookup_user(i915,542					  ci.engine_class,543					  ci.engine_instance);544	if (!master) {545		drm_dbg(&i915->drm,546			"Unrecognised master engine: { class:%u, instance:%u }\n",547			ci.engine_class, ci.engine_instance);548		return -EINVAL;549	}550 551	if (intel_engine_uses_guc(master)) {552		drm_dbg(&i915->drm, "bonding extension not supported with GuC submission");553		return -ENODEV;554	}555 556	if (get_user(num_bonds, &ext->num_bonds))557		return -EFAULT;558 559	for (n = 0; n < num_bonds; n++) {560		struct intel_engine_cs *bond;561 562		if (copy_from_user(&ci, &ext->engines[n], sizeof(ci)))563			return -EFAULT;564 565		bond = intel_engine_lookup_user(i915,566						ci.engine_class,567						ci.engine_instance);568		if (!bond) {569			drm_dbg(&i915->drm,570				"Unrecognised engine[%d] for bonding: { class:%d, instance: %d }\n",571				n, ci.engine_class, ci.engine_instance);572			return -EINVAL;573		}574	}575 576	return 0;577}578 579static int580set_proto_ctx_engines_parallel_submit(struct i915_user_extension __user *base,581				      void *data)582{583	struct i915_context_engines_parallel_submit __user *ext =584		container_of_user(base, typeof(*ext), base);585	const struct set_proto_ctx_engines *set = data;586	struct drm_i915_private *i915 = set->i915;587	struct i915_engine_class_instance prev_engine;588	u64 flags;589	int err = 0, n, i, j;590	u16 slot, width, num_siblings;591	struct intel_engine_cs **siblings = NULL;592	intel_engine_mask_t prev_mask;593 594	if (get_user(slot, &ext->engine_index))595		return -EFAULT;596 597	if (get_user(width, &ext->width))598		return -EFAULT;599 600	if (get_user(num_siblings, &ext->num_siblings))601		return -EFAULT;602 603	if (!intel_uc_uses_guc_submission(&to_gt(i915)->uc) &&604	    num_siblings != 1) {605		drm_dbg(&i915->drm, "Only 1 sibling (%d) supported in non-GuC mode\n",606			num_siblings);607		return -EINVAL;608	}609 610	if (slot >= set->num_engines) {611		drm_dbg(&i915->drm, "Invalid placement value, %d >= %d\n",612			slot, set->num_engines);613		return -EINVAL;614	}615 616	if (set->engines[slot].type != I915_GEM_ENGINE_TYPE_INVALID) {617		drm_dbg(&i915->drm,618			"Invalid placement[%d], already occupied\n", slot);619		return -EINVAL;620	}621 622	if (get_user(flags, &ext->flags))623		return -EFAULT;624 625	if (flags) {626		drm_dbg(&i915->drm, "Unknown flags 0x%02llx", flags);627		return -EINVAL;628	}629 630	for (n = 0; n < ARRAY_SIZE(ext->mbz64); n++) {631		err = check_user_mbz(&ext->mbz64[n]);632		if (err)633			return err;634	}635 636	if (width < 2) {637		drm_dbg(&i915->drm, "Width (%d) < 2\n", width);638		return -EINVAL;639	}640 641	if (num_siblings < 1) {642		drm_dbg(&i915->drm, "Number siblings (%d) < 1\n",643			num_siblings);644		return -EINVAL;645	}646 647	siblings = kmalloc_array(num_siblings * width,648				 sizeof(*siblings),649				 GFP_KERNEL);650	if (!siblings)651		return -ENOMEM;652 653	/* Create contexts / engines */654	for (i = 0; i < width; ++i) {655		intel_engine_mask_t current_mask = 0;656 657		for (j = 0; j < num_siblings; ++j) {658			struct i915_engine_class_instance ci;659 660			n = i * num_siblings + j;661			if (copy_from_user(&ci, &ext->engines[n], sizeof(ci))) {662				err = -EFAULT;663				goto out_err;664			}665 666			siblings[n] =667				intel_engine_lookup_user(i915, ci.engine_class,668							 ci.engine_instance);669			if (!siblings[n]) {670				drm_dbg(&i915->drm,671					"Invalid sibling[%d]: { class:%d, inst:%d }\n",672					n, ci.engine_class, ci.engine_instance);673				err = -EINVAL;674				goto out_err;675			}676 677			/*678			 * We don't support breadcrumb handshake on these679			 * classes680			 */681			if (siblings[n]->class == RENDER_CLASS ||682			    siblings[n]->class == COMPUTE_CLASS) {683				err = -EINVAL;684				goto out_err;685			}686 687			if (n) {688				if (prev_engine.engine_class !=689				    ci.engine_class) {690					drm_dbg(&i915->drm,691						"Mismatched class %d, %d\n",692						prev_engine.engine_class,693						ci.engine_class);694					err = -EINVAL;695					goto out_err;696				}697			}698 699			prev_engine = ci;700			current_mask |= siblings[n]->logical_mask;701		}702 703		if (i > 0) {704			if (current_mask != prev_mask << 1) {705				drm_dbg(&i915->drm,706					"Non contiguous logical mask 0x%x, 0x%x\n",707					prev_mask, current_mask);708				err = -EINVAL;709				goto out_err;710			}711		}712		prev_mask = current_mask;713	}714 715	set->engines[slot].type = I915_GEM_ENGINE_TYPE_PARALLEL;716	set->engines[slot].num_siblings = num_siblings;717	set->engines[slot].width = width;718	set->engines[slot].siblings = siblings;719 720	return 0;721 722out_err:723	kfree(siblings);724 725	return err;726}727 728static const i915_user_extension_fn set_proto_ctx_engines_extensions[] = {729	[I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE] = set_proto_ctx_engines_balance,730	[I915_CONTEXT_ENGINES_EXT_BOND] = set_proto_ctx_engines_bond,731	[I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT] =732		set_proto_ctx_engines_parallel_submit,733};734 735static int set_proto_ctx_engines(struct drm_i915_file_private *fpriv,736			         struct i915_gem_proto_context *pc,737			         const struct drm_i915_gem_context_param *args)738{739	struct drm_i915_private *i915 = fpriv->i915;740	struct set_proto_ctx_engines set = { .i915 = i915 };741	struct i915_context_param_engines __user *user =742		u64_to_user_ptr(args->value);743	unsigned int n;744	u64 extensions;745	int err;746 747	if (pc->num_user_engines >= 0) {748		drm_dbg(&i915->drm, "Cannot set engines twice");749		return -EINVAL;750	}751 752	if (args->size < sizeof(*user) ||753	    !IS_ALIGNED(args->size - sizeof(*user), sizeof(*user->engines))) {754		drm_dbg(&i915->drm, "Invalid size for engine array: %d\n",755			args->size);756		return -EINVAL;757	}758 759	set.num_engines = (args->size - sizeof(*user)) / sizeof(*user->engines);760	/* RING_MASK has no shift so we can use it directly here */761	if (set.num_engines > I915_EXEC_RING_MASK + 1)762		return -EINVAL;763 764	set.engines = kmalloc_array(set.num_engines, sizeof(*set.engines), GFP_KERNEL);765	if (!set.engines)766		return -ENOMEM;767 768	for (n = 0; n < set.num_engines; n++) {769		struct i915_engine_class_instance ci;770		struct intel_engine_cs *engine;771 772		if (copy_from_user(&ci, &user->engines[n], sizeof(ci))) {773			kfree(set.engines);774			return -EFAULT;775		}776 777		memset(&set.engines[n], 0, sizeof(set.engines[n]));778 779		if (ci.engine_class == (u16)I915_ENGINE_CLASS_INVALID &&780		    ci.engine_instance == (u16)I915_ENGINE_CLASS_INVALID_NONE)781			continue;782 783		engine = intel_engine_lookup_user(i915,784						  ci.engine_class,785						  ci.engine_instance);786		if (!engine) {787			drm_dbg(&i915->drm,788				"Invalid engine[%d]: { class:%d, instance:%d }\n",789				n, ci.engine_class, ci.engine_instance);790			kfree(set.engines);791			return -ENOENT;792		}793 794		set.engines[n].type = I915_GEM_ENGINE_TYPE_PHYSICAL;795		set.engines[n].engine = engine;796	}797 798	err = -EFAULT;799	if (!get_user(extensions, &user->extensions))800		err = i915_user_extensions(u64_to_user_ptr(extensions),801					   set_proto_ctx_engines_extensions,802					   ARRAY_SIZE(set_proto_ctx_engines_extensions),803					   &set);804	if (err) {805		kfree(set.engines);806		return err;807	}808 809	pc->num_user_engines = set.num_engines;810	pc->user_engines = set.engines;811 812	return 0;813}814 815static int set_proto_ctx_sseu(struct drm_i915_file_private *fpriv,816			      struct i915_gem_proto_context *pc,817			      struct drm_i915_gem_context_param *args)818{819	struct drm_i915_private *i915 = fpriv->i915;820	struct drm_i915_gem_context_param_sseu user_sseu;821	struct intel_sseu *sseu;822	int ret;823 824	if (args->size < sizeof(user_sseu))825		return -EINVAL;826 827	if (GRAPHICS_VER(i915) != 11)828		return -ENODEV;829 830	if (copy_from_user(&user_sseu, u64_to_user_ptr(args->value),831			   sizeof(user_sseu)))832		return -EFAULT;833 834	if (user_sseu.rsvd)835		return -EINVAL;836 837	if (user_sseu.flags & ~(I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX))838		return -EINVAL;839 840	if (!!(user_sseu.flags & I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX) != (pc->num_user_engines >= 0))841		return -EINVAL;842 843	if (pc->num_user_engines >= 0) {844		int idx = user_sseu.engine.engine_instance;845		struct i915_gem_proto_engine *pe;846 847		if (idx >= pc->num_user_engines)848			return -EINVAL;849 850		idx = array_index_nospec(idx, pc->num_user_engines);851		pe = &pc->user_engines[idx];852 853		/* Only render engine supports RPCS configuration. */854		if (pe->engine->class != RENDER_CLASS)855			return -EINVAL;856 857		sseu = &pe->sseu;858	} else {859		/* Only render engine supports RPCS configuration. */860		if (user_sseu.engine.engine_class != I915_ENGINE_CLASS_RENDER)861			return -EINVAL;862 863		/* There is only one render engine */864		if (user_sseu.engine.engine_instance != 0)865			return -EINVAL;866 867		sseu = &pc->legacy_rcs_sseu;868	}869 870	ret = i915_gem_user_to_context_sseu(to_gt(i915), &user_sseu, sseu);871	if (ret)872		return ret;873 874	args->size = sizeof(user_sseu);875 876	return 0;877}878 879static int set_proto_ctx_param(struct drm_i915_file_private *fpriv,880			       struct i915_gem_proto_context *pc,881			       struct drm_i915_gem_context_param *args)882{883	struct drm_i915_private *i915 = fpriv->i915;884	int ret = 0;885 886	switch (args->param) {887	case I915_CONTEXT_PARAM_NO_ERROR_CAPTURE:888		if (args->size)889			ret = -EINVAL;890		else if (args->value)891			pc->user_flags |= BIT(UCONTEXT_NO_ERROR_CAPTURE);892		else893			pc->user_flags &= ~BIT(UCONTEXT_NO_ERROR_CAPTURE);894		break;895 896	case I915_CONTEXT_PARAM_BANNABLE:897		if (args->size)898			ret = -EINVAL;899		else if (!capable(CAP_SYS_ADMIN) && !args->value)900			ret = -EPERM;901		else if (args->value)902			pc->user_flags |= BIT(UCONTEXT_BANNABLE);903		else if (pc->uses_protected_content)904			ret = -EPERM;905		else906			pc->user_flags &= ~BIT(UCONTEXT_BANNABLE);907		break;908 909	case I915_CONTEXT_PARAM_LOW_LATENCY:910		if (intel_uc_uses_guc_submission(&to_gt(i915)->uc))911			pc->user_flags |= BIT(UCONTEXT_LOW_LATENCY);912		else913			ret = -EINVAL;914		break;915 916	case I915_CONTEXT_PARAM_RECOVERABLE:917		if (args->size)918			ret = -EINVAL;919		else if (!args->value)920			pc->user_flags &= ~BIT(UCONTEXT_RECOVERABLE);921		else if (pc->uses_protected_content)922			ret = -EPERM;923		else924			pc->user_flags |= BIT(UCONTEXT_RECOVERABLE);925		break;926 927	case I915_CONTEXT_PARAM_PRIORITY:928		ret = validate_priority(fpriv->i915, args);929		if (!ret)930			pc->sched.priority = args->value;931		break;932 933	case I915_CONTEXT_PARAM_SSEU:934		ret = set_proto_ctx_sseu(fpriv, pc, args);935		break;936 937	case I915_CONTEXT_PARAM_VM:938		ret = set_proto_ctx_vm(fpriv, pc, args);939		break;940 941	case I915_CONTEXT_PARAM_ENGINES:942		ret = set_proto_ctx_engines(fpriv, pc, args);943		break;944 945	case I915_CONTEXT_PARAM_PERSISTENCE:946		if (args->size)947			ret = -EINVAL;948		else949			ret = proto_context_set_persistence(fpriv->i915, pc,950							    args->value);951		break;952 953	case I915_CONTEXT_PARAM_PROTECTED_CONTENT:954		ret = proto_context_set_protected(fpriv->i915, pc,955						  args->value);956		break;957 958	case I915_CONTEXT_PARAM_NO_ZEROMAP:959	case I915_CONTEXT_PARAM_BAN_PERIOD:960	case I915_CONTEXT_PARAM_RINGSIZE:961	case I915_CONTEXT_PARAM_CONTEXT_IMAGE:962	default:963		ret = -EINVAL;964		break;965	}966 967	return ret;968}969 970static int intel_context_set_gem(struct intel_context *ce,971				 struct i915_gem_context *ctx,972				 struct intel_sseu sseu)973{974	int ret = 0;975 976	GEM_BUG_ON(rcu_access_pointer(ce->gem_context));977	RCU_INIT_POINTER(ce->gem_context, ctx);978 979	GEM_BUG_ON(intel_context_is_pinned(ce));980 981	if (ce->engine->class == COMPUTE_CLASS)982		ce->ring_size = SZ_512K;983	else984		ce->ring_size = SZ_16K;985 986	i915_vm_put(ce->vm);987	ce->vm = i915_gem_context_get_eb_vm(ctx);988 989	if (ctx->sched.priority >= I915_PRIORITY_NORMAL &&990	    intel_engine_has_timeslices(ce->engine) &&991	    intel_engine_has_semaphores(ce->engine))992		__set_bit(CONTEXT_USE_SEMAPHORES, &ce->flags);993 994	if (CONFIG_DRM_I915_REQUEST_TIMEOUT &&995	    ctx->i915->params.request_timeout_ms) {996		unsigned int timeout_ms = ctx->i915->params.request_timeout_ms;997 998		intel_context_set_watchdog_us(ce, (u64)timeout_ms * 1000);999	}1000 1001	/* A valid SSEU has no zero fields */1002	if (sseu.slice_mask && !WARN_ON(ce->engine->class != RENDER_CLASS))1003		ret = intel_context_reconfigure_sseu(ce, sseu);1004 1005	if (test_bit(UCONTEXT_LOW_LATENCY, &ctx->user_flags))1006		__set_bit(CONTEXT_LOW_LATENCY, &ce->flags);1007 1008	return ret;1009}1010 1011static void __unpin_engines(struct i915_gem_engines *e, unsigned int count)1012{1013	while (count--) {1014		struct intel_context *ce = e->engines[count], *child;1015 1016		if (!ce || !test_bit(CONTEXT_PERMA_PIN, &ce->flags))1017			continue;1018 1019		for_each_child(ce, child)1020			intel_context_unpin(child);1021		intel_context_unpin(ce);1022	}1023}1024 1025static void unpin_engines(struct i915_gem_engines *e)1026{1027	__unpin_engines(e, e->num_engines);1028}1029 1030static void __free_engines(struct i915_gem_engines *e, unsigned int count)1031{1032	while (count--) {1033		if (!e->engines[count])1034			continue;1035 1036		intel_context_put(e->engines[count]);1037	}1038	kfree(e);1039}1040 1041static void free_engines(struct i915_gem_engines *e)1042{1043	__free_engines(e, e->num_engines);1044}1045 1046static void free_engines_rcu(struct rcu_head *rcu)1047{1048	struct i915_gem_engines *engines =1049		container_of(rcu, struct i915_gem_engines, rcu);1050 1051	i915_sw_fence_fini(&engines->fence);1052	free_engines(engines);1053}1054 1055static void accumulate_runtime(struct i915_drm_client *client,1056			       struct i915_gem_engines *engines)1057{1058	struct i915_gem_engines_iter it;1059	struct intel_context *ce;1060 1061	if (!client)1062		return;1063 1064	/* Transfer accumulated runtime to the parent GEM context. */1065	for_each_gem_engine(ce, engines, it) {1066		unsigned int class = ce->engine->uabi_class;1067 1068		GEM_BUG_ON(class >= ARRAY_SIZE(client->past_runtime));1069		atomic64_add(intel_context_get_total_runtime_ns(ce),1070			     &client->past_runtime[class]);1071	}1072}1073 1074static int1075engines_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)1076{1077	struct i915_gem_engines *engines =1078		container_of(fence, typeof(*engines), fence);1079	struct i915_gem_context *ctx = engines->ctx;1080 1081	switch (state) {1082	case FENCE_COMPLETE:1083		if (!list_empty(&engines->link)) {1084			unsigned long flags;1085 1086			spin_lock_irqsave(&ctx->stale.lock, flags);1087			list_del(&engines->link);1088			spin_unlock_irqrestore(&ctx->stale.lock, flags);1089		}1090		accumulate_runtime(ctx->client, engines);1091		i915_gem_context_put(ctx);1092 1093		break;1094 1095	case FENCE_FREE:1096		init_rcu_head(&engines->rcu);1097		call_rcu(&engines->rcu, free_engines_rcu);1098		break;1099	}1100 1101	return NOTIFY_DONE;1102}1103 1104static struct i915_gem_engines *alloc_engines(unsigned int count)1105{1106	struct i915_gem_engines *e;1107 1108	e = kzalloc(struct_size(e, engines, count), GFP_KERNEL);1109	if (!e)1110		return NULL;1111 1112	i915_sw_fence_init(&e->fence, engines_notify);1113	return e;1114}1115 1116static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx,1117						struct intel_sseu rcs_sseu)1118{1119	const unsigned int max = I915_NUM_ENGINES;1120	struct intel_engine_cs *engine;1121	struct i915_gem_engines *e, *err;1122 1123	e = alloc_engines(max);1124	if (!e)1125		return ERR_PTR(-ENOMEM);1126 1127	for_each_uabi_engine(engine, ctx->i915) {1128		struct intel_context *ce;1129		struct intel_sseu sseu = {};1130		int ret;1131 1132		if (engine->legacy_idx == INVALID_ENGINE)1133			continue;1134 1135		GEM_BUG_ON(engine->legacy_idx >= max);1136		GEM_BUG_ON(e->engines[engine->legacy_idx]);1137 1138		ce = intel_context_create(engine);1139		if (IS_ERR(ce)) {1140			err = ERR_CAST(ce);1141			goto free_engines;1142		}1143 1144		e->engines[engine->legacy_idx] = ce;1145		e->num_engines = max(e->num_engines, engine->legacy_idx + 1);1146 1147		if (engine->class == RENDER_CLASS)1148			sseu = rcs_sseu;1149 1150		ret = intel_context_set_gem(ce, ctx, sseu);1151		if (ret) {1152			err = ERR_PTR(ret);1153			goto free_engines;1154		}1155 1156	}1157 1158	return e;1159 1160free_engines:1161	free_engines(e);1162	return err;1163}1164 1165static int perma_pin_contexts(struct intel_context *ce)1166{1167	struct intel_context *child;1168	int i = 0, j = 0, ret;1169 1170	GEM_BUG_ON(!intel_context_is_parent(ce));1171 1172	ret = intel_context_pin(ce);1173	if (unlikely(ret))1174		return ret;1175 1176	for_each_child(ce, child) {1177		ret = intel_context_pin(child);1178		if (unlikely(ret))1179			goto unwind;1180		++i;1181	}1182 1183	set_bit(CONTEXT_PERMA_PIN, &ce->flags);1184 1185	return 0;1186 1187unwind:1188	intel_context_unpin(ce);1189	for_each_child(ce, child) {1190		if (j++ < i)1191			intel_context_unpin(child);1192		else1193			break;1194	}1195 1196	return ret;1197}1198 1199static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,1200					     unsigned int num_engines,1201					     struct i915_gem_proto_engine *pe)1202{1203	struct i915_gem_engines *e, *err;1204	unsigned int n;1205 1206	e = alloc_engines(num_engines);1207	if (!e)1208		return ERR_PTR(-ENOMEM);1209	e->num_engines = num_engines;1210 1211	for (n = 0; n < num_engines; n++) {1212		struct intel_context *ce, *child;1213		int ret;1214 1215		switch (pe[n].type) {1216		case I915_GEM_ENGINE_TYPE_PHYSICAL:1217			ce = intel_context_create(pe[n].engine);1218			break;1219 1220		case I915_GEM_ENGINE_TYPE_BALANCED:1221			ce = intel_engine_create_virtual(pe[n].siblings,1222							 pe[n].num_siblings, 0);1223			break;1224 1225		case I915_GEM_ENGINE_TYPE_PARALLEL:1226			ce = intel_engine_create_parallel(pe[n].siblings,1227							  pe[n].num_siblings,1228							  pe[n].width);1229			break;1230 1231		case I915_GEM_ENGINE_TYPE_INVALID:1232		default:1233			GEM_WARN_ON(pe[n].type != I915_GEM_ENGINE_TYPE_INVALID);1234			continue;1235		}1236 1237		if (IS_ERR(ce)) {1238			err = ERR_CAST(ce);1239			goto free_engines;1240		}1241 1242		e->engines[n] = ce;1243 1244		ret = intel_context_set_gem(ce, ctx, pe->sseu);1245		if (ret) {1246			err = ERR_PTR(ret);1247			goto free_engines;1248		}1249		for_each_child(ce, child) {1250			ret = intel_context_set_gem(child, ctx, pe->sseu);1251			if (ret) {1252				err = ERR_PTR(ret);1253				goto free_engines;1254			}1255		}1256 1257		/*1258		 * XXX: Must be done after calling intel_context_set_gem as that1259		 * function changes the ring size. The ring is allocated when1260		 * the context is pinned. If the ring size is changed after1261		 * allocation we have a mismatch of the ring size and will cause1262		 * the context to hang. Presumably with a bit of reordering we1263		 * could move the perma-pin step to the backend function1264		 * intel_engine_create_parallel.1265		 */1266		if (pe[n].type == I915_GEM_ENGINE_TYPE_PARALLEL) {1267			ret = perma_pin_contexts(ce);1268			if (ret) {1269				err = ERR_PTR(ret);1270				goto free_engines;1271			}1272		}1273	}1274 1275	return e;1276 1277free_engines:1278	free_engines(e);1279	return err;1280}1281 1282static void i915_gem_context_release_work(struct work_struct *work)1283{1284	struct i915_gem_context *ctx = container_of(work, typeof(*ctx),1285						    release_work);1286	struct i915_address_space *vm;1287 1288	trace_i915_context_free(ctx);1289	GEM_BUG_ON(!i915_gem_context_is_closed(ctx));1290 1291	spin_lock(&ctx->i915->gem.contexts.lock);1292	list_del(&ctx->link);1293	spin_unlock(&ctx->i915->gem.contexts.lock);1294 1295	if (ctx->syncobj)1296		drm_syncobj_put(ctx->syncobj);1297 1298	vm = ctx->vm;1299	if (vm)1300		i915_vm_put(vm);1301 1302	if (ctx->pxp_wakeref)1303		intel_runtime_pm_put(&ctx->i915->runtime_pm, ctx->pxp_wakeref);1304 1305	if (ctx->client)1306		i915_drm_client_put(ctx->client);1307 1308	mutex_destroy(&ctx->engines_mutex);1309	mutex_destroy(&ctx->lut_mutex);1310 1311	put_pid(ctx->pid);1312	mutex_destroy(&ctx->mutex);1313 1314	kfree_rcu(ctx, rcu);1315}1316 1317void i915_gem_context_release(struct kref *ref)1318{1319	struct i915_gem_context *ctx = container_of(ref, typeof(*ctx), ref);1320 1321	queue_work(ctx->i915->wq, &ctx->release_work);1322}1323 1324static inline struct i915_gem_engines *1325__context_engines_static(const struct i915_gem_context *ctx)1326{1327	return rcu_dereference_protected(ctx->engines, true);1328}1329 1330static void __reset_context(struct i915_gem_context *ctx,1331			    struct intel_engine_cs *engine)1332{1333	intel_gt_handle_error(engine->gt, engine->mask, 0,1334			      "context closure in %s", ctx->name);1335}1336 1337static bool __cancel_engine(struct intel_engine_cs *engine)1338{1339	/*1340	 * Send a "high priority pulse" down the engine to cause the1341	 * current request to be momentarily preempted. (If it fails to1342	 * be preempted, it will be reset). As we have marked our context1343	 * as banned, any incomplete request, including any running, will1344	 * be skipped following the preemption.1345	 *1346	 * If there is no hangchecking (one of the reasons why we try to1347	 * cancel the context) and no forced preemption, there may be no1348	 * means by which we reset the GPU and evict the persistent hog.1349	 * Ergo if we are unable to inject a preemptive pulse that can1350	 * kill the banned context, we fallback to doing a local reset1351	 * instead.1352	 */1353	return intel_engine_pulse(engine) == 0;1354}1355 1356static struct intel_engine_cs *active_engine(struct intel_context *ce)1357{1358	struct intel_engine_cs *engine = NULL;1359	struct i915_request *rq;1360 1361	if (intel_context_has_inflight(ce))1362		return intel_context_inflight(ce);1363 1364	if (!ce->timeline)1365		return NULL;1366 1367	/*1368	 * rq->link is only SLAB_TYPESAFE_BY_RCU, we need to hold a reference1369	 * to the request to prevent it being transferred to a new timeline1370	 * (and onto a new timeline->requests list).1371	 */1372	rcu_read_lock();1373	list_for_each_entry_reverse(rq, &ce->timeline->requests, link) {1374		bool found;1375 1376		/* timeline is already completed upto this point? */1377		if (!i915_request_get_rcu(rq))1378			break;1379 1380		/* Check with the backend if the request is inflight */1381		found = true;1382		if (likely(rcu_access_pointer(rq->timeline) == ce->timeline))1383			found = i915_request_active_engine(rq, &engine);1384 1385		i915_request_put(rq);1386		if (found)1387			break;1388	}1389	rcu_read_unlock();1390 1391	return engine;1392}1393 1394static void1395kill_engines(struct i915_gem_engines *engines, bool exit, bool persistent)1396{1397	struct i915_gem_engines_iter it;1398	struct intel_context *ce;1399 1400	/*1401	 * Map the user's engine back to the actual engines; one virtual1402	 * engine will be mapped to multiple engines, and using ctx->engine[]1403	 * the same engine may be have multiple instances in the user's map.1404	 * However, we only care about pending requests, so only include1405	 * engines on which there are incomplete requests.1406	 */1407	for_each_gem_engine(ce, engines, it) {1408		struct intel_engine_cs *engine;1409 1410		if ((exit || !persistent) && intel_context_revoke(ce))1411			continue; /* Already marked. */1412 1413		/*1414		 * Check the current active state of this context; if we1415		 * are currently executing on the GPU we need to evict1416		 * ourselves. On the other hand, if we haven't yet been1417		 * submitted to the GPU or if everything is complete,1418		 * we have nothing to do.1419		 */1420		engine = active_engine(ce);1421 1422		/* First attempt to gracefully cancel the context */1423		if (engine && !__cancel_engine(engine) && (exit || !persistent))1424			/*1425			 * If we are unable to send a preemptive pulse to bump1426			 * the context from the GPU, we have to resort to a full1427			 * reset. We hope the collateral damage is worth it.1428			 */1429			__reset_context(engines->ctx, engine);1430	}1431}1432 1433static void kill_context(struct i915_gem_context *ctx)1434{1435	struct i915_gem_engines *pos, *next;1436 1437	spin_lock_irq(&ctx->stale.lock);1438	GEM_BUG_ON(!i915_gem_context_is_closed(ctx));1439	list_for_each_entry_safe(pos, next, &ctx->stale.engines, link) {1440		if (!i915_sw_fence_await(&pos->fence)) {1441			list_del_init(&pos->link);1442			continue;1443		}1444 1445		spin_unlock_irq(&ctx->stale.lock);1446 1447		kill_engines(pos, !ctx->i915->params.enable_hangcheck,1448			     i915_gem_context_is_persistent(ctx));1449 1450		spin_lock_irq(&ctx->stale.lock);1451		GEM_BUG_ON(i915_sw_fence_signaled(&pos->fence));1452		list_safe_reset_next(pos, next, link);1453		list_del_init(&pos->link); /* decouple from FENCE_COMPLETE */1454 1455		i915_sw_fence_complete(&pos->fence);1456	}1457	spin_unlock_irq(&ctx->stale.lock);1458}1459 1460static void engines_idle_release(struct i915_gem_context *ctx,1461				 struct i915_gem_engines *engines)1462{1463	struct i915_gem_engines_iter it;1464	struct intel_context *ce;1465 1466	INIT_LIST_HEAD(&engines->link);1467 1468	engines->ctx = i915_gem_context_get(ctx);1469 1470	for_each_gem_engine(ce, engines, it) {1471		int err;1472 1473		/* serialises with execbuf */1474		intel_context_close(ce);1475		if (!intel_context_pin_if_active(ce))1476			continue;1477 1478		/* Wait until context is finally scheduled out and retired */1479		err = i915_sw_fence_await_active(&engines->fence,1480						 &ce->active,1481						 I915_ACTIVE_AWAIT_BARRIER);1482		intel_context_unpin(ce);1483		if (err)1484			goto kill;1485	}1486 1487	spin_lock_irq(&ctx->stale.lock);1488	if (!i915_gem_context_is_closed(ctx))1489		list_add_tail(&engines->link, &ctx->stale.engines);1490	spin_unlock_irq(&ctx->stale.lock);1491 1492kill:1493	if (list_empty(&engines->link)) /* raced, already closed */1494		kill_engines(engines, true,1495			     i915_gem_context_is_persistent(ctx));1496 1497	i915_sw_fence_commit(&engines->fence);1498}1499 1500static void set_closed_name(struct i915_gem_context *ctx)1501{1502	char *s;1503 1504	/* Replace '[]' with '<>' to indicate closed in debug prints */1505 1506	s = strrchr(ctx->name, '[');1507	if (!s)1508		return;1509 1510	*s = '<';1511 1512	s = strchr(s + 1, ']');1513	if (s)1514		*s = '>';1515}1516 1517static void context_close(struct i915_gem_context *ctx)1518{1519	struct i915_drm_client *client;1520 1521	/* Flush any concurrent set_engines() */1522	mutex_lock(&ctx->engines_mutex);1523	unpin_engines(__context_engines_static(ctx));1524	engines_idle_release(ctx, rcu_replace_pointer(ctx->engines, NULL, 1));1525	i915_gem_context_set_closed(ctx);1526	mutex_unlock(&ctx->engines_mutex);1527 1528	mutex_lock(&ctx->mutex);1529 1530	set_closed_name(ctx);1531 1532	/*1533	 * The LUT uses the VMA as a backpointer to unref the object,1534	 * so we need to clear the LUT before we close all the VMA (inside1535	 * the ppgtt).1536	 */1537	lut_close(ctx);1538 1539	ctx->file_priv = ERR_PTR(-EBADF);1540 1541	client = ctx->client;1542	if (client) {1543		spin_lock(&client->ctx_lock);1544		list_del_rcu(&ctx->client_link);1545		spin_unlock(&client->ctx_lock);1546	}1547 1548	mutex_unlock(&ctx->mutex);1549 1550	/*1551	 * If the user has disabled hangchecking, we can not be sure that1552	 * the batches will ever complete after the context is closed,1553	 * keeping the context and all resources pinned forever. So in this1554	 * case we opt to forcibly kill off all remaining requests on1555	 * context close.1556	 */1557	kill_context(ctx);1558 1559	i915_gem_context_put(ctx);1560}1561 1562static int __context_set_persistence(struct i915_gem_context *ctx, bool state)1563{1564	if (i915_gem_context_is_persistent(ctx) == state)1565		return 0;1566 1567	if (state) {1568		/*1569		 * Only contexts that are short-lived [that will expire or be1570		 * reset] are allowed to survive past termination. We require1571		 * hangcheck to ensure that the persistent requests are healthy.1572		 */1573		if (!ctx->i915->params.enable_hangcheck)1574			return -EINVAL;1575 1576		i915_gem_context_set_persistence(ctx);1577	} else {1578		/* To cancel a context we use "preempt-to-idle" */1579		if (!(ctx->i915->caps.scheduler & I915_SCHEDULER_CAP_PREEMPTION))1580			return -ENODEV;1581 1582		/*1583		 * If the cancel fails, we then need to reset, cleanly!1584		 *1585		 * If the per-engine reset fails, all hope is lost! We resort1586		 * to a full GPU reset in that unlikely case, but realistically1587		 * if the engine could not reset, the full reset does not fare1588		 * much better. The damage has been done.1589		 *1590		 * However, if we cannot reset an engine by itself, we cannot1591		 * cleanup a hanging persistent context without causing1592		 * colateral damage, and we should not pretend we can by1593		 * exposing the interface.1594		 */1595		if (!intel_has_reset_engine(to_gt(ctx->i915)))1596			return -ENODEV;1597 1598		i915_gem_context_clear_persistence(ctx);1599	}1600 1601	return 0;1602}1603 1604static struct i915_gem_context *1605i915_gem_create_context(struct drm_i915_private *i915,1606			const struct i915_gem_proto_context *pc)1607{1608	struct i915_gem_context *ctx;1609	struct i915_address_space *vm = NULL;1610	struct i915_gem_engines *e;1611	int err;1612	int i;1613 1614	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);1615	if (!ctx)1616		return ERR_PTR(-ENOMEM);1617 1618	kref_init(&ctx->ref);1619	ctx->i915 = i915;1620	ctx->sched = pc->sched;1621	mutex_init(&ctx->mutex);1622	INIT_LIST_HEAD(&ctx->link);1623	INIT_WORK(&ctx->release_work, i915_gem_context_release_work);1624 1625	spin_lock_init(&ctx->stale.lock);1626	INIT_LIST_HEAD(&ctx->stale.engines);1627 1628	if (pc->vm) {1629		vm = i915_vm_get(pc->vm);1630	} else if (HAS_FULL_PPGTT(i915)) {1631		struct i915_ppgtt *ppgtt;1632 1633		ppgtt = i915_ppgtt_create(to_gt(i915), 0);1634		if (IS_ERR(ppgtt)) {1635			drm_dbg(&i915->drm, "PPGTT setup failed (%ld)\n",1636				PTR_ERR(ppgtt));1637			err = PTR_ERR(ppgtt);1638			goto err_ctx;1639		}1640		ppgtt->vm.fpriv = pc->fpriv;1641		vm = &ppgtt->vm;1642	}1643	if (vm)1644		ctx->vm = vm;1645 1646	/* Assign early so intel_context_set_gem can access these flags */1647	ctx->user_flags = pc->user_flags;1648 1649	mutex_init(&ctx->engines_mutex);1650	if (pc->num_user_engines >= 0) {1651		i915_gem_context_set_user_engines(ctx);1652		e = user_engines(ctx, pc->num_user_engines, pc->user_engines);1653	} else {1654		i915_gem_context_clear_user_engines(ctx);1655		e = default_engines(ctx, pc->legacy_rcs_sseu);1656	}1657	if (IS_ERR(e)) {1658		err = PTR_ERR(e);1659		goto err_vm;1660	}1661	RCU_INIT_POINTER(ctx->engines, e);1662 1663	INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);1664	mutex_init(&ctx->lut_mutex);1665 1666	/* NB: Mark all slices as needing a remap so that when the context first1667	 * loads it will restore whatever remap state already exists. If there1668	 * is no remap info, it will be a NOP. */1669	ctx->remap_slice = ALL_L3_SLICES(i915);1670 1671	for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++)1672		ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES;1673 1674	if (pc->single_timeline) {1675		err = drm_syncobj_create(&ctx->syncobj,1676					 DRM_SYNCOBJ_CREATE_SIGNALED,1677					 NULL);1678		if (err)1679			goto err_engines;1680	}1681 1682	if (pc->uses_protected_content) {1683		ctx->pxp_wakeref = intel_runtime_pm_get(&i915->runtime_pm);1684		ctx->uses_protected_content = true;1685	}1686 1687	trace_i915_context_create(ctx);1688 1689	return ctx;1690 1691err_engines:1692	free_engines(e);1693err_vm:1694	if (ctx->vm)1695		i915_vm_put(ctx->vm);1696err_ctx:1697	kfree(ctx);1698	return ERR_PTR(err);1699}1700 1701static void init_contexts(struct i915_gem_contexts *gc)1702{1703	spin_lock_init(&gc->lock);1704	INIT_LIST_HEAD(&gc->list);1705}1706 1707void i915_gem_init__contexts(struct drm_i915_private *i915)1708{1709	init_contexts(&i915->gem.contexts);1710}1711 1712/*1713 * Note that this implicitly consumes the ctx reference, by placing1714 * the ctx in the context_xa.1715 */1716static void gem_context_register(struct i915_gem_context *ctx,1717				 struct drm_i915_file_private *fpriv,1718				 u32 id)1719{1720	struct drm_i915_private *i915 = ctx->i915;1721	void *old;1722 1723	ctx->file_priv = fpriv;1724 1725	ctx->pid = get_task_pid(current, PIDTYPE_PID);1726	ctx->client = i915_drm_client_get(fpriv->client);1727 1728	snprintf(ctx->name, sizeof(ctx->name), "%s[%d]",1729		 current->comm, pid_nr(ctx->pid));1730 1731	spin_lock(&ctx->client->ctx_lock);1732	list_add_tail_rcu(&ctx->client_link, &ctx->client->ctx_list);1733	spin_unlock(&ctx->client->ctx_lock);1734 1735	spin_lock(&i915->gem.contexts.lock);1736	list_add_tail(&ctx->link, &i915->gem.contexts.list);1737	spin_unlock(&i915->gem.contexts.lock);1738 1739	/* And finally expose ourselves to userspace via the idr */1740	old = xa_store(&fpriv->context_xa, id, ctx, GFP_KERNEL);1741	WARN_ON(old);1742}1743 1744int i915_gem_context_open(struct drm_i915_private *i915,1745			  struct drm_file *file)1746{1747	struct drm_i915_file_private *file_priv = file->driver_priv;1748	struct i915_gem_proto_context *pc;1749	struct i915_gem_context *ctx;1750	int err;1751 1752	mutex_init(&file_priv->proto_context_lock);1753	xa_init_flags(&file_priv->proto_context_xa, XA_FLAGS_ALLOC);1754 1755	/* 0 reserved for the default context */1756	xa_init_flags(&file_priv->context_xa, XA_FLAGS_ALLOC1);1757 1758	/* 0 reserved for invalid/unassigned ppgtt */1759	xa_init_flags(&file_priv->vm_xa, XA_FLAGS_ALLOC1);1760 1761	pc = proto_context_create(file_priv, i915, 0);1762	if (IS_ERR(pc)) {1763		err = PTR_ERR(pc);1764		goto err;1765	}1766 1767	ctx = i915_gem_create_context(i915, pc);1768	proto_context_close(i915, pc);1769	if (IS_ERR(ctx)) {1770		err = PTR_ERR(ctx);1771		goto err;1772	}1773 1774	gem_context_register(ctx, file_priv, 0);1775 1776	return 0;1777 1778err:1779	xa_destroy(&file_priv->vm_xa);1780	xa_destroy(&file_priv->context_xa);1781	xa_destroy(&file_priv->proto_context_xa);1782	mutex_destroy(&file_priv->proto_context_lock);1783	return err;1784}1785 1786void i915_gem_context_close(struct drm_file *file)1787{1788	struct drm_i915_file_private *file_priv = file->driver_priv;1789	struct i915_gem_proto_context *pc;1790	struct i915_address_space *vm;1791	struct i915_gem_context *ctx;1792	unsigned long idx;1793 1794	xa_for_each(&file_priv->proto_context_xa, idx, pc)1795		proto_context_close(file_priv->i915, pc);1796	xa_destroy(&file_priv->proto_context_xa);1797	mutex_destroy(&file_priv->proto_context_lock);1798 1799	xa_for_each(&file_priv->context_xa, idx, ctx)1800		context_close(ctx);1801	xa_destroy(&file_priv->context_xa);1802 1803	xa_for_each(&file_priv->vm_xa, idx, vm)1804		i915_vm_put(vm);1805	xa_destroy(&file_priv->vm_xa);1806}1807 1808int i915_gem_vm_create_ioctl(struct drm_device *dev, void *data,1809			     struct drm_file *file)1810{1811	struct drm_i915_private *i915 = to_i915(dev);1812	struct drm_i915_gem_vm_control *args = data;1813	struct drm_i915_file_private *file_priv = file->driver_priv;1814	struct i915_ppgtt *ppgtt;1815	u32 id;1816	int err;1817 1818	if (!HAS_FULL_PPGTT(i915))1819		return -ENODEV;1820 1821	if (args->flags)1822		return -EINVAL;1823 1824	ppgtt = i915_ppgtt_create(to_gt(i915), 0);1825	if (IS_ERR(ppgtt))1826		return PTR_ERR(ppgtt);1827 1828	if (args->extensions) {1829		err = i915_user_extensions(u64_to_user_ptr(args->extensions),1830					   NULL, 0,1831					   ppgtt);1832		if (err)1833			goto err_put;1834	}1835 1836	err = xa_alloc(&file_priv->vm_xa, &id, &ppgtt->vm,1837		       xa_limit_32b, GFP_KERNEL);1838	if (err)1839		goto err_put;1840 1841	GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */1842	args->vm_id = id;1843	ppgtt->vm.fpriv = file_priv;1844	return 0;1845 1846err_put:1847	i915_vm_put(&ppgtt->vm);1848	return err;1849}1850 1851int i915_gem_vm_destroy_ioctl(struct drm_device *dev, void *data,1852			      struct drm_file *file)1853{1854	struct drm_i915_file_private *file_priv = file->driver_priv;1855	struct drm_i915_gem_vm_control *args = data;1856	struct i915_address_space *vm;1857 1858	if (args->flags)1859		return -EINVAL;1860 1861	if (args->extensions)1862		return -EINVAL;1863 1864	vm = xa_erase(&file_priv->vm_xa, args->vm_id);1865	if (!vm)1866		return -ENOENT;1867 1868	i915_vm_put(vm);1869	return 0;1870}1871 1872static int get_ppgtt(struct drm_i915_file_private *file_priv,1873		     struct i915_gem_context *ctx,1874		     struct drm_i915_gem_context_param *args)1875{1876	struct i915_address_space *vm;1877	int err;1878	u32 id;1879 1880	if (!i915_gem_context_has_full_ppgtt(ctx))1881		return -ENODEV;1882 1883	vm = ctx->vm;1884	GEM_BUG_ON(!vm);1885 1886	/*1887	 * Get a reference for the allocated handle.  Once the handle is1888	 * visible in the vm_xa table, userspace could try to close it1889	 * from under our feet, so we need to hold the extra reference1890	 * first.1891	 */1892	i915_vm_get(vm);1893 1894	err = xa_alloc(&file_priv->vm_xa, &id, vm, xa_limit_32b, GFP_KERNEL);1895	if (err) {1896		i915_vm_put(vm);1897		return err;1898	}1899 1900	GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */1901	args->value = id;1902	args->size = 0;1903 1904	return err;1905}1906 1907int1908i915_gem_user_to_context_sseu(struct intel_gt *gt,1909			      const struct drm_i915_gem_context_param_sseu *user,1910			      struct intel_sseu *context)1911{1912	const struct sseu_dev_info *device = &gt->info.sseu;1913	struct drm_i915_private *i915 = gt->i915;1914	unsigned int dev_subslice_mask = intel_sseu_get_hsw_subslices(device, 0);1915 1916	/* No zeros in any field. */1917	if (!user->slice_mask || !user->subslice_mask ||1918	    !user->min_eus_per_subslice || !user->max_eus_per_subslice)1919		return -EINVAL;1920 1921	/* Max > min. */1922	if (user->max_eus_per_subslice < user->min_eus_per_subslice)1923		return -EINVAL;1924 1925	/*1926	 * Some future proofing on the types since the uAPI is wider than the1927	 * current internal implementation.1928	 */1929	if (overflows_type(user->slice_mask, context->slice_mask) ||1930	    overflows_type(user->subslice_mask, context->subslice_mask) ||1931	    overflows_type(user->min_eus_per_subslice,1932			   context->min_eus_per_subslice) ||1933	    overflows_type(user->max_eus_per_subslice,1934			   context->max_eus_per_subslice))1935		return -EINVAL;1936 1937	/* Check validity against hardware. */1938	if (user->slice_mask & ~device->slice_mask)1939		return -EINVAL;1940 1941	if (user->subslice_mask & ~dev_subslice_mask)1942		return -EINVAL;1943 1944	if (user->max_eus_per_subslice > device->max_eus_per_subslice)1945		return -EINVAL;1946 1947	context->slice_mask = user->slice_mask;1948	context->subslice_mask = user->subslice_mask;1949	context->min_eus_per_subslice = user->min_eus_per_subslice;1950	context->max_eus_per_subslice = user->max_eus_per_subslice;1951 1952	/* Part specific restrictions. */1953	if (GRAPHICS_VER(i915) == 11) {1954		unsigned int hw_s = hweight8(device->slice_mask);1955		unsigned int hw_ss_per_s = hweight8(dev_subslice_mask);1956		unsigned int req_s = hweight8(context->slice_mask);1957		unsigned int req_ss = hweight8(context->subslice_mask);1958 1959		/*1960		 * Only full subslice enablement is possible if more than one1961		 * slice is turned on.1962		 */1963		if (req_s > 1 && req_ss != hw_ss_per_s)1964			return -EINVAL;1965 1966		/*1967		 * If more than four (SScount bitfield limit) subslices are1968		 * requested then the number has to be even.1969		 */1970		if (req_ss > 4 && (req_ss & 1))1971			return -EINVAL;1972 1973		/*1974		 * If only one slice is enabled and subslice count is below the1975		 * device full enablement, it must be at most half of the all1976		 * available subslices.1977		 */1978		if (req_s == 1 && req_ss < hw_ss_per_s &&1979		    req_ss > (hw_ss_per_s / 2))1980			return -EINVAL;1981 1982		/* ABI restriction - VME use case only. */1983 1984		/* All slices or one slice only. */1985		if (req_s != 1 && req_s != hw_s)1986			return -EINVAL;1987 1988		/*1989		 * Half subslices or full enablement only when one slice is1990		 * enabled.1991		 */1992		if (req_s == 1 &&1993		    (req_ss != hw_ss_per_s && req_ss != (hw_ss_per_s / 2)))1994			return -EINVAL;1995 1996		/* No EU configuration changes. */1997		if ((user->min_eus_per_subslice !=1998		     device->max_eus_per_subslice) ||1999		    (user->max_eus_per_subslice !=2000		     device->max_eus_per_subslice))2001			return -EINVAL;2002	}2003 2004	return 0;2005}2006 2007static int set_sseu(struct i915_gem_context *ctx,2008		    struct drm_i915_gem_context_param *args)2009{2010	struct drm_i915_private *i915 = ctx->i915;2011	struct drm_i915_gem_context_param_sseu user_sseu;2012	struct intel_context *ce;2013	struct intel_sseu sseu;2014	unsigned long lookup;2015	int ret;2016 2017	if (args->size < sizeof(user_sseu))2018		return -EINVAL;2019 2020	if (GRAPHICS_VER(i915) != 11)2021		return -ENODEV;2022 2023	if (copy_from_user(&user_sseu, u64_to_user_ptr(args->value),2024			   sizeof(user_sseu)))2025		return -EFAULT;2026 2027	if (user_sseu.rsvd)2028		return -EINVAL;2029 2030	if (user_sseu.flags & ~(I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX))2031		return -EINVAL;2032 2033	lookup = 0;2034	if (user_sseu.flags & I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX)2035		lookup |= LOOKUP_USER_INDEX;2036 2037	ce = lookup_user_engine(ctx, lookup, &user_sseu.engine);2038	if (IS_ERR(ce))2039		return PTR_ERR(ce);2040 2041	/* Only render engine supports RPCS configuration. */2042	if (ce->engine->class != RENDER_CLASS) {2043		ret = -ENODEV;2044		goto out_ce;2045	}2046 2047	ret = i915_gem_user_to_context_sseu(ce->engine->gt, &user_sseu, &sseu);2048	if (ret)2049		goto out_ce;2050 2051	ret = intel_context_reconfigure_sseu(ce, sseu);2052	if (ret)2053		goto out_ce;2054 2055	args->size = sizeof(user_sseu);2056 2057out_ce:2058	intel_context_put(ce);2059	return ret;2060}2061 2062static int2063set_persistence(struct i915_gem_context *ctx,2064		const struct drm_i915_gem_context_param *args)2065{2066	if (args->size)2067		return -EINVAL;2068 2069	return __context_set_persistence(ctx, args->value);2070}2071 2072static int set_priority(struct i915_gem_context *ctx,2073			const struct drm_i915_gem_context_param *args)2074{2075	struct i915_gem_engines_iter it;2076	struct intel_context *ce;2077	int err;2078 2079	err = validate_priority(ctx->i915, args);2080	if (err)2081		return err;2082 2083	ctx->sched.priority = args->value;2084 2085	for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {2086		if (!intel_engine_has_timeslices(ce->engine))2087			continue;2088 2089		if (ctx->sched.priority >= I915_PRIORITY_NORMAL &&2090		    intel_engine_has_semaphores(ce->engine))2091			intel_context_set_use_semaphores(ce);2092		else2093			intel_context_clear_use_semaphores(ce);2094	}2095	i915_gem_context_unlock_engines(ctx);2096 2097	return 0;2098}2099 2100static int get_protected(struct i915_gem_context *ctx,2101			 struct drm_i915_gem_context_param *args)2102{2103	args->size = 0;2104	args->value = i915_gem_context_uses_protected_content(ctx);2105 2106	return 0;2107}2108 2109static int set_context_image(struct i915_gem_context *ctx,2110			     struct drm_i915_gem_context_param *args)2111{2112	struct i915_gem_context_param_context_image user;2113	struct intel_context *ce;2114	struct file *shmem_state;2115	unsigned long lookup;2116	void *state;2117	int ret = 0;2118 2119	if (!IS_ENABLED(CONFIG_DRM_I915_REPLAY_GPU_HANGS_API))2120		return -EINVAL;2121 2122	if (!ctx->i915->params.enable_debug_only_api)2123		return -EINVAL;2124 2125	if (args->size < sizeof(user))2126		return -EINVAL;2127 2128	if (copy_from_user(&user, u64_to_user_ptr(args->value), sizeof(user)))2129		return -EFAULT;2130 2131	if (user.mbz)2132		return -EINVAL;2133 2134	if (user.flags & ~(I915_CONTEXT_IMAGE_FLAG_ENGINE_INDEX))2135		return -EINVAL;2136 2137	lookup = 0;2138	if (user.flags & I915_CONTEXT_IMAGE_FLAG_ENGINE_INDEX)2139		lookup |= LOOKUP_USER_INDEX;2140 2141	ce = lookup_user_engine(ctx, lookup, &user.engine);2142	if (IS_ERR(ce))2143		return PTR_ERR(ce);2144 2145	if (user.size < ce->engine->context_size) {2146		ret = -EINVAL;2147		goto out_ce;2148	}2149 2150	if (drm_WARN_ON_ONCE(&ctx->i915->drm,2151			     test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) {2152		/*2153		 * This is racy but for a debug only API, if userspace is keen2154		 * to create and configure contexts, while simultaneously using2155		 * them from a second thread, let them suffer by potentially not2156		 * executing with the context image they just raced to apply.2157		 */2158		ret = -EBUSY;2159		goto out_ce;2160	}2161 2162	state = kmalloc(ce->engine->context_size, GFP_KERNEL);2163	if (!state) {2164		ret = -ENOMEM;2165		goto out_ce;2166	}2167 2168	if (copy_from_user(state, u64_to_user_ptr(user.image),2169			   ce->engine->context_size)) {2170		ret = -EFAULT;2171		goto out_state;2172	}2173 2174	shmem_state = shmem_create_from_data(ce->engine->name,2175					     state, ce->engine->context_size);2176	if (IS_ERR(shmem_state)) {2177		ret = PTR_ERR(shmem_state);2178		goto out_state;2179	}2180 2181	if (intel_context_set_own_state(ce)) {2182		ret = -EBUSY;2183		fput(shmem_state);2184		goto out_state;2185	}2186 2187	ce->default_state = shmem_state;2188 2189	args->size = sizeof(user);2190 2191out_state:2192	kfree(state);2193out_ce:2194	intel_context_put(ce);2195	return ret;2196}2197 2198static int ctx_setparam(struct drm_i915_file_private *fpriv,2199			struct i915_gem_context *ctx,2200			struct drm_i915_gem_context_param *args)2201{2202	int ret = 0;2203 2204	switch (args->param) {2205	case I915_CONTEXT_PARAM_NO_ERROR_CAPTURE:2206		if (args->size)2207			ret = -EINVAL;2208		else if (args->value)2209			i915_gem_context_set_no_error_capture(ctx);2210		else2211			i915_gem_context_clear_no_error_capture(ctx);2212		break;2213 2214	case I915_CONTEXT_PARAM_BANNABLE:2215		if (args->size)2216			ret = -EINVAL;2217		else if (!capable(CAP_SYS_ADMIN) && !args->value)2218			ret = -EPERM;2219		else if (args->value)2220			i915_gem_context_set_bannable(ctx);2221		else if (i915_gem_context_uses_protected_content(ctx))2222			ret = -EPERM; /* can't clear this for protected contexts */2223		else2224			i915_gem_context_clear_bannable(ctx);2225		break;2226 2227	case I915_CONTEXT_PARAM_RECOVERABLE:2228		if (args->size)2229			ret = -EINVAL;2230		else if (!args->value)2231			i915_gem_context_clear_recoverable(ctx);2232		else if (i915_gem_context_uses_protected_content(ctx))2233			ret = -EPERM; /* can't set this for protected contexts */2234		else2235			i915_gem_context_set_recoverable(ctx);2236		break;2237 2238	case I915_CONTEXT_PARAM_PRIORITY:2239		ret = set_priority(ctx, args);2240		break;2241 2242	case I915_CONTEXT_PARAM_SSEU:2243		ret = set_sseu(ctx, args);2244		break;2245 2246	case I915_CONTEXT_PARAM_PERSISTENCE:2247		ret = set_persistence(ctx, args);2248		break;2249 2250	case I915_CONTEXT_PARAM_CONTEXT_IMAGE:2251		ret = set_context_image(ctx, args);2252		break;2253 2254	case I915_CONTEXT_PARAM_PROTECTED_CONTENT:2255	case I915_CONTEXT_PARAM_NO_ZEROMAP:2256	case I915_CONTEXT_PARAM_BAN_PERIOD:2257	case I915_CONTEXT_PARAM_RINGSIZE:2258	case I915_CONTEXT_PARAM_VM:2259	case I915_CONTEXT_PARAM_ENGINES:2260	default:2261		ret = -EINVAL;2262		break;2263	}2264 2265	return ret;2266}2267 2268struct create_ext {2269	struct i915_gem_proto_context *pc;2270	struct drm_i915_file_private *fpriv;2271};2272 2273static int create_setparam(struct i915_user_extension __user *ext, void *data)2274{2275	struct drm_i915_gem_context_create_ext_setparam local;2276	const struct create_ext *arg = data;2277 2278	if (copy_from_user(&local, ext, sizeof(local)))2279		return -EFAULT;2280 2281	if (local.param.ctx_id)2282		return -EINVAL;2283 2284	return set_proto_ctx_param(arg->fpriv, arg->pc, &local.param);2285}2286 2287static int invalid_ext(struct i915_user_extension __user *ext, void *data)2288{2289	return -EINVAL;2290}2291 2292static const i915_user_extension_fn create_extensions[] = {2293	[I915_CONTEXT_CREATE_EXT_SETPARAM] = create_setparam,2294	[I915_CONTEXT_CREATE_EXT_CLONE] = invalid_ext,2295};2296 2297static bool client_is_banned(struct drm_i915_file_private *file_priv)2298{2299	return atomic_read(&file_priv->ban_score) >= I915_CLIENT_SCORE_BANNED;2300}2301 2302static inline struct i915_gem_context *2303__context_lookup(struct drm_i915_file_private *file_priv, u32 id)2304{2305	struct i915_gem_context *ctx;2306 2307	rcu_read_lock();2308	ctx = xa_load(&file_priv->context_xa, id);2309	if (ctx && !kref_get_unless_zero(&ctx->ref))2310		ctx = NULL;2311	rcu_read_unlock();2312 2313	return ctx;2314}2315 2316static struct i915_gem_context *2317finalize_create_context_locked(struct drm_i915_file_private *file_priv,2318			       struct i915_gem_proto_context *pc, u32 id)2319{2320	struct i915_gem_context *ctx;2321	void *old;2322 2323	lockdep_assert_held(&file_priv->proto_context_lock);2324 2325	ctx = i915_gem_create_context(file_priv->i915, pc);2326	if (IS_ERR(ctx))2327		return ctx;2328 2329	/*2330	 * One for the xarray and one for the caller.  We need to grab2331	 * the reference *prior* to making the ctx visble to userspace2332	 * in gem_context_register(), as at any point after that2333	 * userspace can try to race us with another thread destroying2334	 * the context under our feet.2335	 */2336	i915_gem_context_get(ctx);2337 2338	gem_context_register(ctx, file_priv, id);2339 2340	old = xa_erase(&file_priv->proto_context_xa, id);2341	GEM_BUG_ON(old != pc);2342	proto_context_close(file_priv->i915, pc);2343 2344	return ctx;2345}2346 2347struct i915_gem_context *2348i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)2349{2350	struct i915_gem_proto_context *pc;2351	struct i915_gem_context *ctx;2352 2353	ctx = __context_lookup(file_priv, id);2354	if (ctx)2355		return ctx;2356 2357	mutex_lock(&file_priv->proto_context_lock);2358	/* Try one more time under the lock */2359	ctx = __context_lookup(file_priv, id);2360	if (!ctx) {2361		pc = xa_load(&file_priv->proto_context_xa, id);2362		if (!pc)2363			ctx = ERR_PTR(-ENOENT);2364		else2365			ctx = finalize_create_context_locked(file_priv, pc, id);2366	}2367	mutex_unlock(&file_priv->proto_context_lock);2368 2369	return ctx;2370}2371 2372int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,2373				  struct drm_file *file)2374{2375	struct drm_i915_private *i915 = to_i915(dev);2376	struct drm_i915_gem_context_create_ext *args = data;2377	struct create_ext ext_data;2378	int ret;2379	u32 id;2380 2381	if (!DRIVER_CAPS(i915)->has_logical_contexts)2382		return -ENODEV;2383 2384	if (args->flags & I915_CONTEXT_CREATE_FLAGS_UNKNOWN)2385		return -EINVAL;2386 2387	ret = intel_gt_terminally_wedged(to_gt(i915));2388	if (ret)2389		return ret;2390 2391	ext_data.fpriv = file->driver_priv;2392	if (client_is_banned(ext_data.fpriv)) {2393		drm_dbg(&i915->drm,2394			"client %s[%d] banned from creating ctx\n",2395			current->comm, task_pid_nr(current));2396		return -EIO;2397	}2398 2399	ext_data.pc = proto_context_create(file->driver_priv, i915,2400					   args->flags);2401	if (IS_ERR(ext_data.pc))2402		return PTR_ERR(ext_data.pc);2403 2404	if (args->flags & I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS) {2405		ret = i915_user_extensions(u64_to_user_ptr(args->extensions),2406					   create_extensions,2407					   ARRAY_SIZE(create_extensions),2408					   &ext_data);2409		if (ret)2410			goto err_pc;2411	}2412 2413	if (GRAPHICS_VER(i915) > 12) {2414		struct i915_gem_context *ctx;2415 2416		/* Get ourselves a context ID */2417		ret = xa_alloc(&ext_data.fpriv->context_xa, &id, NULL,2418			       xa_limit_32b, GFP_KERNEL);2419		if (ret)2420			goto err_pc;2421 2422		ctx = i915_gem_create_context(i915, ext_data.pc);2423		if (IS_ERR(ctx)) {2424			ret = PTR_ERR(ctx);2425			goto err_pc;2426		}2427 2428		proto_context_close(i915, ext_data.pc);2429		gem_context_register(ctx, ext_data.fpriv, id);2430	} else {2431		ret = proto_context_register(ext_data.fpriv, ext_data.pc, &id);2432		if (ret < 0)2433			goto err_pc;2434	}2435 2436	args->ctx_id = id;2437 2438	return 0;2439 2440err_pc:2441	proto_context_close(i915, ext_data.pc);2442	return ret;2443}2444 2445int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,2446				   struct drm_file *file)2447{2448	struct drm_i915_gem_context_destroy *args = data;2449	struct drm_i915_file_private *file_priv = file->driver_priv;2450	struct i915_gem_proto_context *pc;2451	struct i915_gem_context *ctx;2452 2453	if (args->pad != 0)2454		return -EINVAL;2455 2456	if (!args->ctx_id)2457		return -ENOENT;2458 2459	/* We need to hold the proto-context lock here to prevent races2460	 * with finalize_create_context_locked().2461	 */2462	mutex_lock(&file_priv->proto_context_lock);2463	ctx = xa_erase(&file_priv->context_xa, args->ctx_id);2464	pc = xa_erase(&file_priv->proto_context_xa, args->ctx_id);2465	mutex_unlock(&file_priv->proto_context_lock);2466 2467	if (!ctx && !pc)2468		return -ENOENT;2469	GEM_WARN_ON(ctx && pc);2470 2471	if (pc)2472		proto_context_close(file_priv->i915, pc);2473 2474	if (ctx)2475		context_close(ctx);2476 2477	return 0;2478}2479 2480static int get_sseu(struct i915_gem_context *ctx,2481		    struct drm_i915_gem_context_param *args)2482{2483	struct drm_i915_gem_context_param_sseu user_sseu;2484	struct intel_context *ce;2485	unsigned long lookup;2486	int err;2487 2488	if (args->size == 0)2489		goto out;2490	else if (args->size < sizeof(user_sseu))2491		return -EINVAL;2492 2493	if (copy_from_user(&user_sseu, u64_to_user_ptr(args->value),2494			   sizeof(user_sseu)))2495		return -EFAULT;2496 2497	if (user_sseu.rsvd)2498		return -EINVAL;2499 2500	if (user_sseu.flags & ~(I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX))2501		return -EINVAL;2502 2503	lookup = 0;2504	if (user_sseu.flags & I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX)2505		lookup |= LOOKUP_USER_INDEX;2506 2507	ce = lookup_user_engine(ctx, lookup, &user_sseu.engine);2508	if (IS_ERR(ce))2509		return PTR_ERR(ce);2510 2511	err = intel_context_lock_pinned(ce); /* serialises with set_sseu */2512	if (err) {2513		intel_context_put(ce);2514		return err;2515	}2516 2517	user_sseu.slice_mask = ce->sseu.slice_mask;2518	user_sseu.subslice_mask = ce->sseu.subslice_mask;2519	user_sseu.min_eus_per_subslice = ce->sseu.min_eus_per_subslice;2520	user_sseu.max_eus_per_subslice = ce->sseu.max_eus_per_subslice;2521 2522	intel_context_unlock_pinned(ce);2523	intel_context_put(ce);2524 2525	if (copy_to_user(u64_to_user_ptr(args->value), &user_sseu,2526			 sizeof(user_sseu)))2527		return -EFAULT;2528 2529out:2530	args->size = sizeof(user_sseu);2531 2532	return 0;2533}2534 2535int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,2536				    struct drm_file *file)2537{2538	struct drm_i915_file_private *file_priv = file->driver_priv;2539	struct drm_i915_gem_context_param *args = data;2540	struct i915_gem_context *ctx;2541	struct i915_address_space *vm;2542	int ret = 0;2543 2544	ctx = i915_gem_context_lookup(file_priv, args->ctx_id);2545	if (IS_ERR(ctx))2546		return PTR_ERR(ctx);2547 2548	switch (args->param) {2549	case I915_CONTEXT_PARAM_GTT_SIZE:2550		args->size = 0;2551		vm = i915_gem_context_get_eb_vm(ctx);2552		args->value = vm->total;2553		i915_vm_put(vm);2554 2555		break;2556 2557	case I915_CONTEXT_PARAM_NO_ERROR_CAPTURE:2558		args->size = 0;2559		args->value = i915_gem_context_no_error_capture(ctx);2560		break;2561 2562	case I915_CONTEXT_PARAM_BANNABLE:2563		args->size = 0;2564		args->value = i915_gem_context_is_bannable(ctx);2565		break;2566 2567	case I915_CONTEXT_PARAM_RECOVERABLE:2568		args->size = 0;2569		args->value = i915_gem_context_is_recoverable(ctx);2570		break;2571 2572	case I915_CONTEXT_PARAM_PRIORITY:2573		args->size = 0;2574		args->value = ctx->sched.priority;2575		break;2576 2577	case I915_CONTEXT_PARAM_SSEU:2578		ret = get_sseu(ctx, args);2579		break;2580 2581	case I915_CONTEXT_PARAM_VM:2582		ret = get_ppgtt(file_priv, ctx, args);2583		break;2584 2585	case I915_CONTEXT_PARAM_PERSISTENCE:2586		args->size = 0;2587		args->value = i915_gem_context_is_persistent(ctx);2588		break;2589 2590	case I915_CONTEXT_PARAM_PROTECTED_CONTENT:2591		ret = get_protected(ctx, args);2592		break;2593 2594	case I915_CONTEXT_PARAM_NO_ZEROMAP:2595	case I915_CONTEXT_PARAM_BAN_PERIOD:2596	case I915_CONTEXT_PARAM_ENGINES:2597	case I915_CONTEXT_PARAM_RINGSIZE:2598	case I915_CONTEXT_PARAM_CONTEXT_IMAGE:2599	default:2600		ret = -EINVAL;2601		break;2602	}2603 2604	i915_gem_context_put(ctx);2605	return ret;2606}2607 2608int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,2609				    struct drm_file *file)2610{2611	struct drm_i915_file_private *file_priv = file->driver_priv;2612	struct drm_i915_gem_context_param *args = data;2613	struct i915_gem_proto_context *pc;2614	struct i915_gem_context *ctx;2615	int ret = 0;2616 2617	mutex_lock(&file_priv->proto_context_lock);2618	ctx = __context_lookup(file_priv, args->ctx_id);2619	if (!ctx) {2620		pc = xa_load(&file_priv->proto_context_xa, args->ctx_id);2621		if (pc) {2622			/* Contexts should be finalized inside2623			 * GEM_CONTEXT_CREATE starting with graphics2624			 * version 13.2625			 */2626			WARN_ON(GRAPHICS_VER(file_priv->i915) > 12);2627			ret = set_proto_ctx_param(file_priv, pc, args);2628		} else {2629			ret = -ENOENT;2630		}2631	}2632	mutex_unlock(&file_priv->proto_context_lock);2633 2634	if (ctx) {2635		ret = ctx_setparam(file_priv, ctx, args);2636		i915_gem_context_put(ctx);2637	}2638 2639	return ret;2640}2641 2642int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,2643				       void *data, struct drm_file *file)2644{2645	struct drm_i915_private *i915 = to_i915(dev);2646	struct drm_i915_reset_stats *args = data;2647	struct i915_gem_context *ctx;2648 2649	if (args->flags || args->pad)2650		return -EINVAL;2651 2652	ctx = i915_gem_context_lookup(file->driver_priv, args->ctx_id);2653	if (IS_ERR(ctx))2654		return PTR_ERR(ctx);2655 2656	/*2657	 * We opt for unserialised reads here. This may result in tearing2658	 * in the extremely unlikely event of a GPU hang on this context2659	 * as we are querying them. If we need that extra layer of protection,2660	 * we should wrap the hangstats with a seqlock.2661	 */2662 2663	if (capable(CAP_SYS_ADMIN))2664		args->reset_count = i915_reset_count(&i915->gpu_error);2665	else2666		args->reset_count = 0;2667 2668	args->batch_active = atomic_read(&ctx->guilty_count);2669	args->batch_pending = atomic_read(&ctx->active_count);2670 2671	i915_gem_context_put(ctx);2672	return 0;2673}2674 2675/* GEM context-engines iterator: for_each_gem_engine() */2676struct intel_context *2677i915_gem_engines_iter_next(struct i915_gem_engines_iter *it)2678{2679	const struct i915_gem_engines *e = it->engines;2680	struct intel_context *ctx;2681 2682	if (unlikely(!e))2683		return NULL;2684 2685	do {2686		if (it->idx >= e->num_engines)2687			return NULL;2688 2689		ctx = e->engines[it->idx++];2690	} while (!ctx);2691 2692	return ctx;2693}2694 2695#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)2696#include "selftests/mock_context.c"2697#include "selftests/i915_gem_context.c"2698#endif2699 2700void i915_gem_context_module_exit(void)2701{2702	kmem_cache_destroy(slab_luts);2703}2704 2705int __init i915_gem_context_module_init(void)2706{2707	slab_luts = KMEM_CACHE(i915_lut_handle, 0);2708	if (!slab_luts)2709		return -ENOMEM;2710 2711	if (IS_ENABLED(CONFIG_DRM_I915_REPLAY_GPU_HANGS_API)) {2712		pr_notice("**************************************************************\n");2713		pr_notice("**     NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE     **\n");2714		pr_notice("**                                                          **\n");2715		if (i915_modparams.enable_debug_only_api)2716			pr_notice("** i915.enable_debug_only_api is intended to be set         **\n");2717		else2718			pr_notice("** CONFIG_DRM_I915_REPLAY_GPU_HANGS_API builds are intended **\n");2719		pr_notice("** for specific userspace graphics stack developers only!   **\n");2720		pr_notice("**                                                          **\n");2721		pr_notice("** If you are seeing this message please report this to the **\n");2722		pr_notice("** provider of your kernel build.                           **\n");2723		pr_notice("**                                                          **\n");2724		pr_notice("**     NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE     **\n");2725		pr_notice("**************************************************************\n");2726	}2727 2728	return 0;2729}2730