linux/drivers/gpu/drm/i915/gem/i915_gem_context.c

/*
 * SPDX-License-Identifier: MIT
 *
 * Copyright © 2011-2012 Intel Corporation
 */

/*
 * This file implements HW context support. On gen5+ a HW context consists of an
 * opaque GPU object which is referenced at times of context saves and restores.
 * With RC6 enabled, the context is also referenced as the GPU enters and exists
 * from RC6 (GPU has it's own internal power context, except on gen5). Though
 * something like a context does exist for the media ring, the code only
 * supports contexts for the render ring.
 *
 * In software, there is a distinction between contexts created by the user,
 * and the default HW context. The default HW context is used by GPU clients
 * that do not request setup of their own hardware context. The default
 * context's state is never restored to help prevent programming errors. This
 * would happen if a client ran and piggy-backed off another clients GPU state.
 * The default context only exists to give the GPU some offset to load as the
 * current to invoke a save of the context we actually care about. In fact, the
 * code could likely be constructed, albeit in a more complicated fashion, to
 * never use the default context, though that limits the driver's ability to
 * swap out, and/or destroy other contexts.
 *
 * All other contexts are created as a request by the GPU client. These contexts
 * store GPU state, and thus allow GPU clients to not re-emit state (and
 * potentially query certain state) at any time. The kernel driver makes
 * certain that the appropriate commands are inserted.
 *
 * The context life cycle is semi-complicated in that context BOs may live
 * longer than the context itself because of the way the hardware, and object
 * tracking works. Below is a very crude representation of the state machine
 * describing the context life.
 *                                         refcount     pincount     active
 * S0: initial state                          0            0           0
 * S1: context created                        1            0           0
 * S2: context is currently running           2            1           X
 * S3: GPU referenced, but not current        2            0           1
 * S4: context is current, but destroyed      1            1           0
 * S5: like S3, but destroyed                 1            0           1
 *
 * The most common (but not all) transitions:
 * S0->S1: client creates a context
 * S1->S2: client submits execbuf with context
 * S2->S3: other clients submits execbuf with context
 * S3->S1: context object was retired
 * S3->S2: clients submits another execbuf
 * S2->S4: context destroy called with current context
 * S3->S5->S0: destroy path
 * S4->S5->S0: destroy path on current context
 *
 * There are two confusing terms used above:
 *  The "current context" means the context which is currently running on the
 *  GPU. The GPU has loaded its state already and has stored away the gtt
 *  offset of the BO. The GPU is not actively referencing the data at this
 *  offset, but it will on the next context switch. The only way to avoid this
 *  is to do a GPU reset.
 *
 *  An "active context' is one which was previously the "current context" and is
 *  on the active list waiting for the next context switch to occur. Until this
 *  happens, the object must remain at the same gtt offset. It is therefore
 *  possible to destroy a context, but it is still active.
 *
 */

#include <linux/highmem.h>
#include <linux/log2.h>
#include <linux/nospec.h>

#include <drm/drm_cache.h>
#include <drm/drm_syncobj.h>

#include "gt/gen6_ppgtt.h"
#include "gt/intel_context.h"
#include "gt/intel_context_param.h"
#include "gt/intel_engine_heartbeat.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_gpu_commands.h"
#include "gt/intel_ring.h"
#include "gt/shmem_utils.h"

#include "pxp/intel_pxp.h"

#include "i915_file_private.h"
#include "i915_gem_context.h"
#include "i915_trace.h"
#include "i915_user_extensions.h"

#define ALL_L3_SLICES(dev)

static struct kmem_cache *slab_luts;

struct i915_lut_handle *i915_lut_handle_alloc(void)
{}

void i915_lut_handle_free(struct i915_lut_handle *lut)
{}

static void lut_close(struct i915_gem_context *ctx)
{}

static struct intel_context *
lookup_user_engine(struct i915_gem_context *ctx,
		   unsigned long flags,
		   const struct i915_engine_class_instance *ci)
#define LOOKUP_USER_INDEX BIT(0)
{}

static int validate_priority(struct drm_i915_private *i915,
			     const struct drm_i915_gem_context_param *args)
{}

static void proto_context_close(struct drm_i915_private *i915,
				struct i915_gem_proto_context *pc)
{}

static int proto_context_set_persistence(struct drm_i915_private *i915,
					 struct i915_gem_proto_context *pc,
					 bool persist)
{}

static int proto_context_set_protected(struct drm_i915_private *i915,
				       struct i915_gem_proto_context *pc,
				       bool protected)
{}

static struct i915_gem_proto_context *
proto_context_create(struct drm_i915_file_private *fpriv,
		     struct drm_i915_private *i915, unsigned int flags)
{}

static int proto_context_register_locked(struct drm_i915_file_private *fpriv,
					 struct i915_gem_proto_context *pc,
					 u32 *id)
{}

static int proto_context_register(struct drm_i915_file_private *fpriv,
				  struct i915_gem_proto_context *pc,
				  u32 *id)
{}

static struct i915_address_space *
i915_gem_vm_lookup(struct drm_i915_file_private *file_priv, u32 id)
{}

static int set_proto_ctx_vm(struct drm_i915_file_private *fpriv,
			    struct i915_gem_proto_context *pc,
			    const struct drm_i915_gem_context_param *args)
{}

struct set_proto_ctx_engines {};

static int
set_proto_ctx_engines_balance(struct i915_user_extension __user *base,
			      void *data)
{}

static int
set_proto_ctx_engines_bond(struct i915_user_extension __user *base, void *data)
{}

static int
set_proto_ctx_engines_parallel_submit(struct i915_user_extension __user *base,
				      void *data)
{}

static const i915_user_extension_fn set_proto_ctx_engines_extensions[] =;

static int set_proto_ctx_engines(struct drm_i915_file_private *fpriv,
			         struct i915_gem_proto_context *pc,
			         const struct drm_i915_gem_context_param *args)
{}

static int set_proto_ctx_sseu(struct drm_i915_file_private *fpriv,
			      struct i915_gem_proto_context *pc,
			      struct drm_i915_gem_context_param *args)
{}

static int set_proto_ctx_param(struct drm_i915_file_private *fpriv,
			       struct i915_gem_proto_context *pc,
			       struct drm_i915_gem_context_param *args)
{}

static int intel_context_set_gem(struct intel_context *ce,
				 struct i915_gem_context *ctx,
				 struct intel_sseu sseu)
{}

static void __unpin_engines(struct i915_gem_engines *e, unsigned int count)
{}

static void unpin_engines(struct i915_gem_engines *e)
{}

static void __free_engines(struct i915_gem_engines *e, unsigned int count)
{}

static void free_engines(struct i915_gem_engines *e)
{}

static void free_engines_rcu(struct rcu_head *rcu)
{}

static void accumulate_runtime(struct i915_drm_client *client,
			       struct i915_gem_engines *engines)
{}

static int
engines_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
{}

static struct i915_gem_engines *alloc_engines(unsigned int count)
{}

static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx,
						struct intel_sseu rcs_sseu)
{}

static int perma_pin_contexts(struct intel_context *ce)
{}

static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,
					     unsigned int num_engines,
					     struct i915_gem_proto_engine *pe)
{}

static void i915_gem_context_release_work(struct work_struct *work)
{}

void i915_gem_context_release(struct kref *ref)
{}

static inline struct i915_gem_engines *
__context_engines_static(const struct i915_gem_context *ctx)
{}

static void __reset_context(struct i915_gem_context *ctx,
			    struct intel_engine_cs *engine)
{}

static bool __cancel_engine(struct intel_engine_cs *engine)
{}

static struct intel_engine_cs *active_engine(struct intel_context *ce)
{}

static void
kill_engines(struct i915_gem_engines *engines, bool exit, bool persistent)
{}

static void kill_context(struct i915_gem_context *ctx)
{}

static void engines_idle_release(struct i915_gem_context *ctx,
				 struct i915_gem_engines *engines)
{}

static void set_closed_name(struct i915_gem_context *ctx)
{}

static void context_close(struct i915_gem_context *ctx)
{}

static int __context_set_persistence(struct i915_gem_context *ctx, bool state)
{}

static struct i915_gem_context *
i915_gem_create_context(struct drm_i915_private *i915,
			const struct i915_gem_proto_context *pc)
{}

static void init_contexts(struct i915_gem_contexts *gc)
{}

void i915_gem_init__contexts(struct drm_i915_private *i915)
{}

/*
 * Note that this implicitly consumes the ctx reference, by placing
 * the ctx in the context_xa.
 */
static void gem_context_register(struct i915_gem_context *ctx,
				 struct drm_i915_file_private *fpriv,
				 u32 id)
{}

int i915_gem_context_open(struct drm_i915_private *i915,
			  struct drm_file *file)
{}

void i915_gem_context_close(struct drm_file *file)
{}

int i915_gem_vm_create_ioctl(struct drm_device *dev, void *data,
			     struct drm_file *file)
{}

int i915_gem_vm_destroy_ioctl(struct drm_device *dev, void *data,
			      struct drm_file *file)
{}

static int get_ppgtt(struct drm_i915_file_private *file_priv,
		     struct i915_gem_context *ctx,
		     struct drm_i915_gem_context_param *args)
{}

int
i915_gem_user_to_context_sseu(struct intel_gt *gt,
			      const struct drm_i915_gem_context_param_sseu *user,
			      struct intel_sseu *context)
{}

static int set_sseu(struct i915_gem_context *ctx,
		    struct drm_i915_gem_context_param *args)
{}

static int
set_persistence(struct i915_gem_context *ctx,
		const struct drm_i915_gem_context_param *args)
{}

static int set_priority(struct i915_gem_context *ctx,
			const struct drm_i915_gem_context_param *args)
{}

static int get_protected(struct i915_gem_context *ctx,
			 struct drm_i915_gem_context_param *args)
{}

static int set_context_image(struct i915_gem_context *ctx,
			     struct drm_i915_gem_context_param *args)
{}

static int ctx_setparam(struct drm_i915_file_private *fpriv,
			struct i915_gem_context *ctx,
			struct drm_i915_gem_context_param *args)
{}

struct create_ext {};

static int create_setparam(struct i915_user_extension __user *ext, void *data)
{}

static int invalid_ext(struct i915_user_extension __user *ext, void *data)
{}

static const i915_user_extension_fn create_extensions[] =;

static bool client_is_banned(struct drm_i915_file_private *file_priv)
{}

static inline struct i915_gem_context *
__context_lookup(struct drm_i915_file_private *file_priv, u32 id)
{}

static struct i915_gem_context *
finalize_create_context_locked(struct drm_i915_file_private *file_priv,
			       struct i915_gem_proto_context *pc, u32 id)
{}

struct i915_gem_context *
i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
{}

int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
				  struct drm_file *file)
{}

int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
				   struct drm_file *file)
{}

static int get_sseu(struct i915_gem_context *ctx,
		    struct drm_i915_gem_context_param *args)
{}

int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
				    struct drm_file *file)
{}

int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
				    struct drm_file *file)
{}

int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
				       void *data, struct drm_file *file)
{}

/* GEM context-engines iterator: for_each_gem_engine() */
struct intel_context *
i915_gem_engines_iter_next(struct i915_gem_engines_iter *it)
{}

#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/mock_context.c"
#include "selftests/i915_gem_context.c"
#endif

void i915_gem_context_module_exit(void)
{}

int __init i915_gem_context_module_init(void)
{}