[Intel-gfx] [PATCH 33/40] drm/i915: Extend CREATE_CONTEXT to allow inheritance ala clone()

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Mon Sep 24 17:22:43 UTC 2018


On 19/09/2018 20:55, Chris Wilson wrote:
> A context encompasses the driver's view of process related state, and
> encapsulates the logical GPU state where available. Each context is
> currently equivalent to a process in CPU terms. Like with processes,
> sometimes the user wants a lighter encapsulation that shares some state
> with the parent process, for example two threads have unique register
> state but share the virtual memory mappings. We can support exactly the
> same principle using contexts where we may share the GTT but keep the
> logical GPU state distinct. This allows quicker switching between those
> contexts, and for userspace to allocate a single offset in the GTT and
> use it across multiple contexts. Like with clone(), in the future we may
> wish to allow userspace to select more features to copy across from the
> parent, but for now we only allow sharing of the GTT.
> 
> Note that if full per-process GTT is not supported on the harder, the

s/harder/hardware/

> GTT are already implicitly shared between contexts, and this request
> to create contexts with shared GTT fails. With full ppGTT, every fd
> (i.e. every process) is allocated a unique GTT so this request cannot be
> used to share GTT between processes/fds, it can only share GTT belonging
> to this fd.
> 
> Testcase: igt/gem_ctx_shared
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> Cc: Mika Kuoppala <mika.kuoppala at linux.intel.com>
> Cc: MichaƂ Winiarski <michal.winiarski at intel.com>
> ---
>   drivers/gpu/drm/i915/i915_gem_context.c       |  62 ++++-
>   drivers/gpu/drm/i915/i915_gem_gtt.c           |  19 +-
>   drivers/gpu/drm/i915/i915_gem_gtt.h           |  14 +-
>   drivers/gpu/drm/i915/selftests/huge_pages.c   |   1 -
>   .../gpu/drm/i915/selftests/i915_gem_context.c | 252 +++++++++++++-----
>   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c |   1 -
>   drivers/gpu/drm/i915/selftests/mock_context.c |   2 +-
>   drivers/gpu/drm/i915/selftests/mock_gtt.c     |   2 +
>   include/uapi/drm/i915_drm.h                   |  11 +-
>   9 files changed, 279 insertions(+), 85 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
> index 150d7a6b2bd3..da2ac10f8e8a 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/i915_gem_context.c
> @@ -110,6 +110,8 @@ static void lut_close(struct i915_gem_context *ctx)
>   		struct i915_vma *vma = rcu_dereference_raw(*slot);
>   
>   		radix_tree_iter_delete(&ctx->handles_vma, &iter, slot);
> +
> +		vma->open_count--;
>   		__i915_gem_object_release_unless_active(vma->obj);
>   	}
>   	rcu_read_unlock();
> @@ -292,7 +294,7 @@ static void context_close(struct i915_gem_context *ctx)
>   	 */
>   	lut_close(ctx);
>   	if (ctx->ppgtt)
> -		i915_ppgtt_close(&ctx->ppgtt->vm);
> +		i915_ppgtt_close(ctx->ppgtt);
>   
>   	ctx->file_priv = ERR_PTR(-EBADF);
>   	i915_gem_context_put(ctx);
> @@ -399,9 +401,12 @@ static void __destroy_hw_context(struct i915_gem_context *ctx,
>   	context_close(ctx);
>   }
>   
> +#define CREATE_VM BIT(0)
> +
>   static struct i915_gem_context *
>   i915_gem_create_context(struct drm_i915_private *dev_priv,
> -			struct drm_i915_file_private *file_priv)
> +			struct drm_i915_file_private *file_priv,
> +			unsigned int flags)
>   {
>   	struct i915_gem_context *ctx;
>   
> @@ -414,7 +419,7 @@ i915_gem_create_context(struct drm_i915_private *dev_priv,
>   	if (IS_ERR(ctx))
>   		return ctx;
>   
> -	if (USES_FULL_PPGTT(dev_priv)) {
> +	if (flags & CREATE_VM && USES_FULL_PPGTT(dev_priv)) {
>   		struct i915_hw_ppgtt *ppgtt;
>   
>   		ppgtt = i915_ppgtt_create(dev_priv, file_priv);
> @@ -493,7 +498,7 @@ i915_gem_context_create_kernel(struct drm_i915_private *i915, int prio)
>   	struct i915_gem_context *ctx;
>   	int err;
>   
> -	ctx = i915_gem_create_context(i915, NULL);
> +	ctx = i915_gem_create_context(i915, NULL, CREATE_VM);
>   	if (IS_ERR(ctx))
>   		return ctx;
>   
> @@ -620,7 +625,7 @@ int i915_gem_context_open(struct drm_i915_private *i915,
>   	idr_init(&file_priv->context_idr);
>   
>   	mutex_lock(&i915->drm.struct_mutex);
> -	ctx = i915_gem_create_context(i915, file_priv);
> +	ctx = i915_gem_create_context(i915, file_priv, CREATE_VM);
>   	mutex_unlock(&i915->drm.struct_mutex);
>   	if (IS_ERR(ctx)) {
>   		idr_destroy(&file_priv->context_idr);
> @@ -778,10 +783,12 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
>   				  struct drm_file *file)
>   {
>   	struct drm_i915_private *dev_priv = to_i915(dev);
> -	struct drm_i915_gem_context_create *args = data;
> +	struct drm_i915_gem_context_create_v2 *args = data;
>   	struct drm_i915_file_private *file_priv = file->driver_priv;
> +	struct i915_gem_context *share = NULL;
>   	struct i915_gem_context *ctx;
> -	int ret;
> +	unsigned int flags = CREATE_VM;
> +	int err;
>   
>   	if (!DRIVER_CAPS(dev_priv)->has_logical_contexts)
>   		return -ENODEV;
> @@ -789,6 +796,9 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
>   	if (args->pad != 0)
>   		return -EINVAL;
>   
> +	if (args->flags & ~I915_GEM_CONTEXT_SHARE_GTT)
> +		return -EINVAL;
> +
>   	if (client_is_banned(file_priv)) {
>   		DRM_DEBUG("client %s[%d] banned from creating ctx\n",
>   			  current->comm,
> @@ -797,21 +807,45 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
>   		return -EIO;
>   	}
>   
> -	ret = i915_mutex_lock_interruptible(dev);
> -	if (ret)
> -		return ret;
> +	if (args->flags & I915_GEM_CONTEXT_SHARE_GTT) {
> +		share = i915_gem_context_lookup(file_priv, args->share_ctx);
> +		if (!share)
> +			return -ENOENT;
> +
> +		if (!share->ppgtt) {
> +			err = -ENODEV;
> +			goto out;
> +		}
> +
> +		flags &= ~CREATE_VM;
> +	}
>   
> -	ctx = i915_gem_create_context(dev_priv, file_priv);
> +	err = i915_mutex_lock_interruptible(dev);
> +	if (err)
> +		goto out;
> +
> +	ctx = i915_gem_create_context(dev_priv, file_priv, flags);
>   	mutex_unlock(&dev->struct_mutex);
> -	if (IS_ERR(ctx))
> -		return PTR_ERR(ctx);
> +	if (IS_ERR(ctx)) {
> +		err = PTR_ERR(ctx);
> +		goto out;
> +	}
> +
> +	if (!(flags & CREATE_VM)) {
> +		ctx->desc_template = share->desc_template;
> +		ctx->ppgtt = i915_ppgtt_get(share->ppgtt);
> +		i915_ppgtt_open(ctx->ppgtt);

i915_ppgtt_open/close are guarded by struct mutex?

As such it looks open_count can drop to zero between the context lookup 
and here. In which case the assert in i915_ppgtt_open would trigger.

Is it acceptable that you have something like i915_ppgtt_try_open?

> +	}
>   
>   	GEM_BUG_ON(i915_gem_context_is_kernel(ctx));
>   
>   	args->ctx_id = ctx->user_handle;
>   	DRM_DEBUG("HW context %d created\n", args->ctx_id);
>   
> -	return 0;
> +out:
> +	if (share)
> +		i915_gem_context_put(share);
> +	return err;
>   }
>   
>   int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index d1ca67459bc2..caf48a1a1c97 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -1644,6 +1644,7 @@ static struct i915_hw_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)
>   		return ERR_PTR(-ENOMEM);
>   
>   	kref_init(&ppgtt->ref);
> +	ppgtt->open_count = 1;
>   
>   	ppgtt->vm.i915 = i915;
>   	ppgtt->vm.dma = &i915->drm.pdev->dev;
> @@ -2160,6 +2161,7 @@ static struct i915_hw_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915)
>   		return ERR_PTR(-ENOMEM);
>   
>   	kref_init(&ppgtt->base.ref);
> +	ppgtt->base.open_count = 1;
>   
>   	ppgtt->base.vm.i915 = i915;
>   	ppgtt->base.vm.dma = &i915->drm.pdev->dev;
> @@ -2285,10 +2287,21 @@ i915_ppgtt_create(struct drm_i915_private *i915,
>   	return ppgtt;
>   }
>   
> -void i915_ppgtt_close(struct i915_address_space *vm)
> +void i915_ppgtt_open(struct i915_hw_ppgtt *ppgtt)
>   {
> -	GEM_BUG_ON(vm->closed);
> -	vm->closed = true;
> +	GEM_BUG_ON(ppgtt->vm.closed);
> +
> +	ppgtt->open_count++;
> +}
> +
> +void i915_ppgtt_close(struct i915_hw_ppgtt *ppgtt)
> +{
> +	GEM_BUG_ON(!ppgtt->open_count);
> +	if (--ppgtt->open_count)
> +		return;
> +
> +	GEM_BUG_ON(ppgtt->vm.closed);
> +	ppgtt->vm.closed = true;
>   }
>   
>   static void ppgtt_destroy_vma(struct i915_address_space *vm)
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> index 849a1f67b037..512a5a0ab820 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> @@ -408,6 +408,8 @@ struct i915_hw_ppgtt {
>   	struct kref ref;
>   
>   	unsigned long pd_dirty_rings;
> +	unsigned int open_count;
> +
>   	union {
>   		struct i915_pml4 pml4;		/* GEN8+ & 48b PPGTT */
>   		struct i915_page_directory_pointer pdp;	/* GEN8+ */
> @@ -626,12 +628,16 @@ int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv);
>   void i915_ppgtt_release(struct kref *kref);
>   struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv,
>   					struct drm_i915_file_private *fpriv);
> -void i915_ppgtt_close(struct i915_address_space *vm);
> -static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt)
> +
> +void i915_ppgtt_open(struct i915_hw_ppgtt *ppgtt);
> +void i915_ppgtt_close(struct i915_hw_ppgtt *ppgtt);
> +
> +static inline struct i915_hw_ppgtt *i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt)
>   {
> -	if (ppgtt)
> -		kref_get(&ppgtt->ref);
> +	kref_get(&ppgtt->ref);
> +	return ppgtt;
>   }
> +
>   static inline void i915_ppgtt_put(struct i915_hw_ppgtt *ppgtt)
>   {
>   	if (ppgtt)
> diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c
> index 4ab98db946c8..ad25860a3336 100644
> --- a/drivers/gpu/drm/i915/selftests/huge_pages.c
> +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c
> @@ -1724,7 +1724,6 @@ int i915_gem_huge_page_mock_selftests(void)
>   	err = i915_subtests(tests, ppgtt);
>   
>   out_close:
> -	i915_ppgtt_close(&ppgtt->vm);
>   	i915_ppgtt_put(ppgtt);
>   
>   out_unlock:
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
> index c7c891a287f5..7ef3f9a3b727 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
> @@ -131,7 +131,9 @@ static int live_nop_switch(void *arg)
>   	}
>   
>   	for (n = 0; n < nctx; n++) {
> -		ctx[n] = i915_gem_create_context(i915, file->driver_priv);
> +		ctx[n] = i915_gem_create_context(i915,
> +						 file->driver_priv,
> +						 CREATE_VM);
>   		if (IS_ERR(ctx[n])) {
>   			err = PTR_ERR(ctx[n]);
>   			goto out_unlock;
> @@ -317,10 +319,6 @@ static int gpu_fill(struct drm_i915_gem_object *obj,
>   	if (IS_ERR(vma))
>   		return PTR_ERR(vma);
>   
> -	err = i915_gem_object_set_to_gtt_domain(obj, false);
> -	if (err)
> -		return err;
> -

Unrelated hunk?

>   	err = i915_vma_pin(vma, 0, 0, PIN_HIGH | PIN_USER);
>   	if (err)
>   		return err;
> @@ -415,7 +413,8 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
>   	return 0;
>   }
>   
> -static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max)
> +static noinline int cpu_check(struct drm_i915_gem_object *obj,
> +			      unsigned int idx, unsigned int max)
>   {
>   	unsigned int n, m, needs_flush;
>   	int err;
> @@ -433,8 +432,8 @@ static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max)
>   
>   		for (m = 0; m < max; m++) {
>   			if (map[m] != m) {
> -				pr_err("Invalid value at page %d, offset %d: found %x expected %x\n",
> -				       n, m, map[m], m);
> +				pr_err("%pS: Invalid value at object %d page %d, offset %d: found %x expected %x\n",
> +				       __builtin_return_address(0), idx, n, m, map[m], m);
>   				err = -EINVAL;
>   				goto out_unmap;
>   			}
> @@ -442,8 +441,9 @@ static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max)
>   
>   		for (; m < DW_PER_PAGE; m++) {
>   			if (map[m] != STACK_MAGIC) {
> -				pr_err("Invalid value at page %d, offset %d: found %x expected %x\n",
> -				       n, m, map[m], STACK_MAGIC);
> +				pr_err("%pS: Invalid value at object %d page %d, offset %d: found %x expected %x\n",
> +				       __builtin_return_address(0), idx, n, m,
> +				       map[m], STACK_MAGIC);
>   				err = -EINVAL;
>   				goto out_unmap;
>   			}
> @@ -506,6 +506,10 @@ create_test_object(struct i915_gem_context *ctx,
>   		return ERR_PTR(err);
>   	}
>   
> +	err = i915_gem_object_set_to_gtt_domain(obj, false);
> +	if (err)
> +		return ERR_PTR(err);
> +

And these ones unrelated as well?

>   	list_add_tail(&obj->st_link, objects);
>   	return obj;
>   }
> @@ -521,12 +525,8 @@ static unsigned long max_dwords(struct drm_i915_gem_object *obj)
>   static int igt_ctx_exec(void *arg)
>   {
>   	struct drm_i915_private *i915 = arg;
> -	struct drm_i915_gem_object *obj = NULL;
> -	struct drm_file *file;
> -	IGT_TIMEOUT(end_time);
> -	LIST_HEAD(objects);
> -	unsigned long ncontexts, ndwords, dw;
> -	bool first_shared_gtt = true;
> +	struct intel_engine_cs *engine;
> +	enum intel_engine_id id;
>   	int err = -ENODEV;
>   
>   	/*
> @@ -538,42 +538,169 @@ static int igt_ctx_exec(void *arg)
>   	if (!DRIVER_CAPS(i915)->has_logical_contexts)
>   		return 0;
>   
> -	file = mock_file(i915);
> -	if (IS_ERR(file))
> -		return PTR_ERR(file);
> +	for_each_engine(engine, i915, id) {
> +		struct drm_i915_gem_object *obj = NULL;
> +		struct drm_file *file;
> +		IGT_TIMEOUT(end_time);
> +		LIST_HEAD(objects);
> +		unsigned long ncontexts, ndwords, dw;
> +		bool first_shared_gtt = true;
> +
> +		if (!intel_engine_can_store_dword(engine))
> +			continue;
>   
> -	mutex_lock(&i915->drm.struct_mutex);
> +		if (!engine->context_size)
> +			continue; /* No logical context support in HW */
>   
> -	ncontexts = 0;
> -	ndwords = 0;
> -	dw = 0;
> -	while (!time_after(jiffies, end_time)) {
> -		struct intel_engine_cs *engine;
> -		struct i915_gem_context *ctx;
> -		unsigned int id;
>   
> -		if (first_shared_gtt) {
> -			ctx = __create_hw_context(i915, file->driver_priv);
> -			first_shared_gtt = false;
> -		} else {
> -			ctx = i915_gem_create_context(i915, file->driver_priv);
> +		file = mock_file(i915);
> +		if (IS_ERR(file))
> +			return PTR_ERR(file);
> +
> +		mutex_lock(&i915->drm.struct_mutex);
> +
> +		ncontexts = 0;
> +		ndwords = 0;
> +		dw = 0;
> +		while (!time_after(jiffies, end_time)) {
> +			struct i915_gem_context *ctx;
> +			intel_wakeref_t wakeref;
> +
> +			if (first_shared_gtt) {
> +				ctx = __create_hw_context(i915, file->driver_priv);
> +				first_shared_gtt = false;
> +			} else {
> +				ctx = i915_gem_create_context(i915,
> +							      file->driver_priv,
> +							      CREATE_VM);
> +			}
> +			if (IS_ERR(ctx)) {
> +				err = PTR_ERR(ctx);
> +				goto out_unlock;
> +			}
> +
> +			if (!obj) {
> +				obj = create_test_object(ctx, file, &objects);
> +				if (IS_ERR(obj)) {
> +					err = PTR_ERR(obj);
> +					goto out_unlock;
> +				}
> +			}
> +
> +			wakeref = intel_runtime_pm_get(i915);
> +			err = gpu_fill(obj, ctx, engine, dw);
> +			intel_runtime_pm_put(i915, wakeref);
> +			if (err) {
> +				pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
> +				       ndwords, dw, max_dwords(obj),
> +				       engine->name, ctx->hw_id,
> +				       yesno(!!ctx->ppgtt), err);
> +				goto out_unlock;
> +			}
> +
> +			if (++dw == max_dwords(obj)) {
> +				obj = NULL;
> +				dw = 0;
> +			}
> +
> +			ndwords++;
> +			ncontexts++;
>   		}
> -		if (IS_ERR(ctx)) {
> -			err = PTR_ERR(ctx);
> +
> +		pr_info("Submitted %lu contexts to %s, filling %lu dwords\n",
> +			ncontexts, engine->name, ndwords);
> +
> +		ncontexts = dw = 0;
> +		list_for_each_entry(obj, &objects, st_link) {
> +			unsigned int rem =
> +				min_t(unsigned int, ndwords - dw, max_dwords(obj));
> +
> +			err = cpu_check(obj, ncontexts++, rem);
> +			if (err)
> +				break;
> +
> +			dw += rem;
> +		}
> +
> +out_unlock:
> +		i915_gem_wait_for_idle(i915,
> +				       I915_WAIT_LOCKED,
> +				       MAX_SCHEDULE_TIMEOUT);
> +		mutex_unlock(&i915->drm.struct_mutex);
> +
> +		mock_file_free(i915, file);
> +		if (err)
> +			return err;
> +	}
> +
> +	return 0;
> +}
> +
> +static int igt_shared_ctx_exec(void *arg)
> +{
> +	struct drm_i915_private *i915 = arg;
> +	struct intel_engine_cs *engine;
> +	enum intel_engine_id id;
> +	int err = -ENODEV;
> +
> +	/*
> +	 * Create a few different contexts with the same mm and write
> +	 * through each ctx using the GPU making sure those writes end
> +	 * up in the expected pages of our obj.
> +	 */
> +
> +	for_each_engine(engine, i915, id) {
> +		IGT_TIMEOUT(end_time);
> +		LIST_HEAD(objects);
> +		unsigned long ncontexts, ndwords, dw;
> +		struct drm_i915_gem_object *obj = NULL;
> +		struct drm_file *file;
> +		struct i915_gem_context *parent;
> +
> +		if (!intel_engine_can_store_dword(engine))
> +			continue;
> +
> +		file = mock_file(i915);
> +		if (IS_ERR(file))
> +			return PTR_ERR(file);
> +
> +		mutex_lock(&i915->drm.struct_mutex);
> +
> +		parent = i915_gem_create_context(i915, file->driver_priv,
> +						 CREATE_VM);
> +		if (IS_ERR(parent)) {
> +			err = PTR_ERR(parent);
> +			if (err == -ENODEV) /* no logical ctx support */
> +				err = 0;
>   			goto out_unlock;
>   		}
>   
> -		for_each_engine(engine, i915, id) {
> +		if (!parent->ppgtt) {
> +			err = 0;
> +			goto out_unlock;
> +		}
> +
> +		ncontexts = 0;
> +		ndwords = 0;
> +		dw = 0;
> +		while (!time_after(jiffies, end_time)) {
> +			struct i915_gem_context *ctx;
>   			intel_wakeref_t wakeref;
>   
> -			if (!engine->context_size)
> -				continue; /* No logical context support in HW */
> +			ctx = i915_gem_create_context(i915,
> +						      file->driver_priv,
> +						      0);
> +			if (IS_ERR(ctx)) {
> +				err = PTR_ERR(ctx);
> +				goto out_unlock;
> +			}
>   
> -			if (!intel_engine_can_store_dword(engine))
> -				continue;
> +			i915_ppgtt_open(parent->ppgtt);
> +			ctx->ppgtt = i915_ppgtt_get(parent->ppgtt);
> +			ctx->desc_template = parent->desc_template;
>   
>   			if (!obj) {
> -				obj = create_test_object(ctx, file, &objects);
> +				obj = create_test_object(parent, file, &objects);
>   				if (IS_ERR(obj)) {
>   					err = PTR_ERR(obj);
>   					goto out_unlock;
> @@ -595,32 +722,36 @@ static int igt_ctx_exec(void *arg)
>   				obj = NULL;
>   				dw = 0;
>   			}
> +
>   			ndwords++;
> +			ncontexts++;
>   		}
> -		ncontexts++;
> -	}
> -	pr_info("Submitted %lu contexts (across %u engines), filling %lu dwords\n",
> -		ncontexts, INTEL_INFO(i915)->num_rings, ndwords);
> +		pr_info("Submitted %lu contexts to %s, filling %lu dwords\n",
> +			ncontexts, engine->name, ndwords);
>   
> -	dw = 0;
> -	list_for_each_entry(obj, &objects, st_link) {
> -		unsigned int rem =
> -			min_t(unsigned int, ndwords - dw, max_dwords(obj));
> +		ncontexts = dw = 0;
> +		list_for_each_entry(obj, &objects, st_link) {
> +			unsigned int rem =
> +				min_t(unsigned int, ndwords - dw, max_dwords(obj));
>   
> -		err = cpu_check(obj, rem);
> -		if (err)
> -			break;
> +			err = cpu_check(obj, ncontexts++, rem);
> +			if (err)
> +				break;
>   
> -		dw += rem;
> -	}
> +			dw += rem;
> +		}
>   
>   out_unlock:
> -	if (igt_flush_test(i915, I915_WAIT_LOCKED))
> -		err = -EIO;
> -	mutex_unlock(&i915->drm.struct_mutex);
> +		if (igt_flush_test(i915, I915_WAIT_LOCKED))
> +			err = -EIO;
> +		mutex_unlock(&i915->drm.struct_mutex);
>   
> -	mock_file_free(i915, file);
> -	return err;
> +		mock_file_free(i915, file);
> +		if (err)
> +			return err;
> +	}
> +
> +	return 0;
>   }
>   
>   static int igt_ctx_readonly(void *arg)
> @@ -648,7 +779,7 @@ static int igt_ctx_readonly(void *arg)
>   
>   	mutex_lock(&i915->drm.struct_mutex);
>   
> -	ctx = i915_gem_create_context(i915, file->driver_priv);
> +	ctx = i915_gem_create_context(i915, file->driver_priv, 0);
>   	if (IS_ERR(ctx)) {
>   		err = PTR_ERR(ctx);
>   		goto out_unlock;
> @@ -714,7 +845,7 @@ static int igt_ctx_readonly(void *arg)
>   		if (i915_gem_object_is_readonly(obj))
>   			num_writes = 0;
>   
> -		err = cpu_check(obj, num_writes);
> +		err = cpu_check(obj, 0, num_writes);
>   		if (err)
>   			break;
>   
> @@ -913,6 +1044,7 @@ int i915_gem_context_live_selftests(struct drm_i915_private *dev_priv)
>   		SUBTEST(live_nop_switch),
>   		SUBTEST(igt_ctx_exec),
>   		SUBTEST(igt_ctx_readonly),
> +		SUBTEST(igt_shared_ctx_exec),
>   	};
>   	bool fake_alias = false;
>   	int err;
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
> index 38414558e18b..0e0fc7eedba3 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
> @@ -1020,7 +1020,6 @@ static int exercise_ppgtt(struct drm_i915_private *dev_priv,
>   
>   	err = func(dev_priv, &ppgtt->vm, 0, ppgtt->vm.total, end_time);
>   
> -	i915_ppgtt_close(&ppgtt->vm);
>   	i915_ppgtt_put(ppgtt);
>   out_unlock:
>   	mutex_unlock(&dev_priv->drm.struct_mutex);
> diff --git a/drivers/gpu/drm/i915/selftests/mock_context.c b/drivers/gpu/drm/i915/selftests/mock_context.c
> index d937bdff26f9..a7511ba98342 100644
> --- a/drivers/gpu/drm/i915/selftests/mock_context.c
> +++ b/drivers/gpu/drm/i915/selftests/mock_context.c
> @@ -92,7 +92,7 @@ live_context(struct drm_i915_private *i915, struct drm_file *file)
>   {
>   	lockdep_assert_held(&i915->drm.struct_mutex);
>   
> -	return i915_gem_create_context(i915, file->driver_priv);
> +	return i915_gem_create_context(i915, file->driver_priv, CREATE_VM);
>   }
>   
>   struct i915_gem_context *
> diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c
> index 976c862b3842..e0880d2c498a 100644
> --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c
> +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c
> @@ -66,6 +66,8 @@ mock_ppgtt(struct drm_i915_private *i915,
>   		return NULL;
>   
>   	kref_init(&ppgtt->ref);
> +	ppgtt->open_count = 1;
> +
>   	ppgtt->vm.i915 = i915;
>   	ppgtt->vm.total = round_down(U64_MAX, PAGE_SIZE);
>   	ppgtt->vm.file = ERR_PTR(-ENODEV);
> diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
> index 4fa7e54501cc..dc1c52f95cab 100644
> --- a/include/uapi/drm/i915_drm.h
> +++ b/include/uapi/drm/i915_drm.h
> @@ -386,7 +386,7 @@ typedef struct _drm_i915_sarea {
>   #define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
>   #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
>   #define DRM_IOCTL_I915_GEM_WAIT		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
> -#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
> +#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create_v2)
>   #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
>   #define DRM_IOCTL_I915_REG_READ			DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
>   #define DRM_IOCTL_I915_GET_RESET_STATS		DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
> @@ -1429,6 +1429,15 @@ struct drm_i915_gem_context_create {
>   	__u32 pad;
>   };
>   
> +struct drm_i915_gem_context_create_v2 {
> +	/*  output: id of new context*/
> +	__u32 ctx_id;
> +	__u32 flags;
> +#define I915_GEM_CONTEXT_SHARE_GTT 0x1
> +	__u32 share_ctx;
> +	__u32 pad;
> +};

Or

__u32 ctx_id;
__u32 share_ctx;
__u64 flags;

for no padding needed and double amount of flags? :)

Regards,

Tvrtko

> +
>   struct drm_i915_gem_context_destroy {
>   	__u32 ctx_id;
>   	__u32 pad;
> 


More information about the Intel-gfx mailing list