History

drm/i915: Create/destroy VM (ppGTT) for use with contexts

In preparation to making the ppGTT binding for a context explicit (to facilitate reusing the same ppGTT between different contexts), allow the user to create and destroy named ppGTT. v2: Replace global barrier for swapping over the ppgtt and tlbs with a local context barrier (Tvrtko) v3: serialise with struct_mutex; it's lazy but required dammit v4: Rewrite igt_ctx_shared_exec to be more different (aimed to be more similarly, turned out different!) v5: Fix up test unwind for aliasing-ppgtt (snb) v6: Tighten language for uapi struct drm_i915_gem_vm_control. v7: Patch the context image for runtime ppgtt switching!

Chris Wilson committed 7 years ago

Commit e0695db1 parent 9d1305e11 files · +580 −81Browse files

Unified · Split

11 files
  1. drivers/gpu/drm/i915/i915_drv.c +2 −0
  2. drivers/gpu/drm/i915/i915_drv.h +3 −0
  3. drivers/gpu/drm/i915/i915_gem_context.c +318 −13
  4. drivers/gpu/drm/i915/i915_gem_context.h +5 −0
  5. drivers/gpu/drm/i915/i915_gem_gtt.c +13 −6
  6. drivers/gpu/drm/i915/i915_gem_gtt.h +6 −4
  7. drivers/gpu/drm/i915/selftests/huge_pages.c +0 −1
  8. drivers/gpu/drm/i915/selftests/i915_gem_context.c +184 −54
  9. drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +0 −1
  10. drivers/gpu/drm/i915/selftests/mock_context.c +6 −2
  11. include/uapi/drm/i915_drm.h +43 −0
drivers/gpu/drm/i915/i915_drv.c+2−0
@@ -3122,6 +3122,8 @@ static const struct drm_ioctl_desc i915_ioctls[] = { · 3121 unmodified lines
31223122 DRM_IOCTL_DEF_DRV(I915_PERF_ADD_CONFIG, i915_perf_add_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
31233123 DRM_IOCTL_DEF_DRV(I915_PERF_REMOVE_CONFIG, i915_perf_remove_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
31243124 DRM_IOCTL_DEF_DRV(I915_QUERY, i915_query_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
3125+ DRM_IOCTL_DEF_DRV(I915_GEM_VM_CREATE, i915_gem_vm_create_ioctl, DRM_RENDER_ALLOW),
3126+ DRM_IOCTL_DEF_DRV(I915_GEM_VM_DESTROY, i915_gem_vm_destroy_ioctl, DRM_RENDER_ALLOW),
31253127 };
31263128
31273129 static struct drm_driver driver = {
drivers/gpu/drm/i915/i915_drv.h+3−0
@@ -220,6 +220,9 @@ struct drm_i915_file_private { · 219 unmodified lines
220220 struct idr context_idr;
221221 struct mutex context_idr_lock; /* guards context_idr */
222222
223+ struct idr vm_idr;
224+ struct mutex vm_idr_lock; /* guards vm_idr */
225+
223226 unsigned int bsd_engine;
224227
225228 /*
drivers/gpu/drm/i915/i915_gem_context.c+318−13
@@ -90,6 +90,7 @@ · 89 unmodified lines
9090 #include "i915_drv.h"
9191 #include "i915_globals.h"
9292 #include "i915_trace.h"
93+#include "i915_user_extensions.h"
9394 #include "intel_lrc_reg.h"
9495 #include "intel_workarounds.h"
9596
@@ -120,12 +121,15 @@ static void lut_close(struct i915_gem_context *ctx) · 24 unmodified lines
120121 list_del(&lut->obj_link);
121122 i915_lut_handle_free(lut);
122123 }
124+ INIT_LIST_HEAD(&ctx->handles_list);
123125
124126 rcu_read_lock();
125127 radix_tree_for_each_slot(slot, &ctx->handles_vma, &iter, 0) {
126128 struct i915_vma *vma = rcu_dereference_raw(*slot);
127129
128130 radix_tree_iter_delete(&ctx->handles_vma, &iter, slot);
131+
132+ vma->open_count--;
129133 __i915_gem_object_release_unless_active(vma->obj);
130134 }
131135 rcu_read_unlock();
@@ -305,8 +309,6 @@ static void context_close(struct i915_gem_context *ctx) · 173 unmodified lines
305309 * the ppgtt).
306310 */
307311 lut_close(ctx);
308− if (ctx->ppgtt)
309− i915_ppgtt_close(&ctx->ppgtt->vm);
310312
311313 ctx->file_priv = ERR_PTR(-EBADF);
312314 i915_gem_context_put(ctx);
@@ -378,6 +380,28 @@ __create_context(struct drm_i915_private *dev_priv) · 65 unmodified lines
378380 return ctx;
379381 }
380382
383+static struct i915_hw_ppgtt *
384+__set_ppgtt(struct i915_gem_context *ctx, struct i915_hw_ppgtt *ppgtt)
385+{
386+ struct i915_hw_ppgtt *old = ctx->ppgtt;
387+
388+ ctx->ppgtt = i915_ppgtt_get(ppgtt);
389+ ctx->desc_template = default_desc_template(ctx->i915, ppgtt);
390+
391+ return old;
392+}
393+
394+static void __assign_ppgtt(struct i915_gem_context *ctx,
395+ struct i915_hw_ppgtt *ppgtt)
396+{
397+ if (ppgtt == ctx->ppgtt)
398+ return;
399+
400+ ppgtt = __set_ppgtt(ctx, ppgtt);
401+ if (ppgtt)
402+ i915_ppgtt_put(ppgtt);
403+}
404+
381405 static struct i915_gem_context *
382406 i915_gem_create_context(struct drm_i915_private *dev_priv)
383407 {
@@ -403,8 +427,8 @@ i915_gem_create_context(struct drm_i915_private *dev_priv) · 19 unmodified lines
403427 return ERR_CAST(ppgtt);
404428 }
405429
406− ctx->ppgtt = ppgtt;
407− ctx->desc_template = default_desc_template(dev_priv, ppgtt);
430+ __assign_ppgtt(ctx, ppgtt);
431+ i915_ppgtt_put(ppgtt);
408432 }
409433
410434 trace_i915_context_create(ctx);
@@ -583,6 +607,12 @@ static int context_idr_cleanup(int id, void *p, void *data) · 172 unmodified lines
583607 return 0;
584608 }
585609
610+static int vm_idr_cleanup(int id, void *p, void *data)
611+{
612+ i915_ppgtt_put(p);
613+ return 0;
614+}
615+
586616 static int gem_context_register(struct i915_gem_context *ctx,
587617 struct drm_i915_file_private *fpriv)
588618 {
@@ -621,8 +651,11 @@ int i915_gem_context_open(struct drm_i915_private *i915, · 32 unmodified lines
621651 struct i915_gem_context *ctx;
622652 int err;
623653
624− idr_init(&file_priv->context_idr);
625654 mutex_init(&file_priv->context_idr_lock);
655+ mutex_init(&file_priv->vm_idr_lock);
656+
657+ idr_init(&file_priv->context_idr);
658+ idr_init_base(&file_priv->vm_idr, 1);
626659
627660 mutex_lock(&i915->drm.struct_mutex);
628661 ctx = i915_gem_create_context(i915);
@@ -646,8 +679,10 @@ err_ctx: · 17 unmodified lines
646679 context_close(ctx);
647680 mutex_unlock(&i915->drm.struct_mutex);
648681 err:
649− mutex_destroy(&file_priv->context_idr_lock);
682+ idr_destroy(&file_priv->vm_idr);
650683 idr_destroy(&file_priv->context_idr);
684+ mutex_destroy(&file_priv->vm_idr_lock);
685+ mutex_destroy(&file_priv->context_idr_lock);
651686 return PTR_ERR(ctx);
652687 }
653688
@@ -660,6 +695,99 @@ void i915_gem_context_close(struct drm_file *file) · 6 unmodified lines
660695 idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
661696 idr_destroy(&file_priv->context_idr);
662697 mutex_destroy(&file_priv->context_idr_lock);
698+
699+ idr_for_each(&file_priv->vm_idr, vm_idr_cleanup, NULL);
700+ idr_destroy(&file_priv->vm_idr);
701+ mutex_destroy(&file_priv->vm_idr_lock);
702+}
703+
704+int i915_gem_vm_create_ioctl(struct drm_device *dev, void *data,
705+ struct drm_file *file)
706+{
707+ struct drm_i915_private *i915 = to_i915(dev);
708+ struct drm_i915_gem_vm_control *args = data;
709+ struct drm_i915_file_private *file_priv = file->driver_priv;
710+ struct i915_hw_ppgtt *ppgtt;
711+ int err;
712+
713+ if (!HAS_FULL_PPGTT(i915))
714+ return -ENODEV;
715+
716+ if (args->flags)
717+ return -EINVAL;
718+
719+ ppgtt = i915_ppgtt_create(i915);
720+ if (IS_ERR(ppgtt))
721+ return PTR_ERR(ppgtt);
722+
723+ ppgtt->vm.file = file_priv;
724+
725+ if (args->extensions) {
726+ err = i915_user_extensions(u64_to_user_ptr(args->extensions),
727+ NULL, 0,
728+ ppgtt);
729+ if (err)
730+ goto err_put;
731+ }
732+
733+ err = mutex_lock_interruptible(&file_priv->vm_idr_lock);
734+ if (err)
735+ goto err_put;
736+
737+ err = idr_alloc(&file_priv->vm_idr, ppgtt, 0, 0, GFP_KERNEL);
738+ if (err < 0)
739+ goto err_unlock;
740+
741+ GEM_BUG_ON(err == 0); /* reserved for default/unassigned ppgtt */
742+ ppgtt->user_handle = err;
743+
744+ mutex_unlock(&file_priv->vm_idr_lock);
745+
746+ args->vm_id = err;
747+ return 0;
748+
749+err_unlock:
750+ mutex_unlock(&file_priv->vm_idr_lock);
751+err_put:
752+ i915_ppgtt_put(ppgtt);
753+ return err;
754+}
755+
756+int i915_gem_vm_destroy_ioctl(struct drm_device *dev, void *data,
757+ struct drm_file *file)
758+{
759+ struct drm_i915_file_private *file_priv = file->driver_priv;
760+ struct drm_i915_gem_vm_control *args = data;
761+ struct i915_hw_ppgtt *ppgtt;
762+ int err;
763+ u32 id;
764+
765+ if (args->flags)
766+ return -EINVAL;
767+
768+ if (args->extensions)
769+ return -EINVAL;
770+
771+ id = args->vm_id;
772+ if (!id)
773+ return -ENOENT;
774+
775+ err = mutex_lock_interruptible(&file_priv->vm_idr_lock);
776+ if (err)
777+ return err;
778+
779+ ppgtt = idr_remove(&file_priv->vm_idr, id);
780+ if (ppgtt) {
781+ GEM_BUG_ON(ppgtt->user_handle != id);
782+ ppgtt->user_handle = 0;
783+ }
784+
785+ mutex_unlock(&file_priv->vm_idr_lock);
786+ if (!ppgtt)
787+ return -ENOENT;
788+
789+ i915_ppgtt_put(ppgtt);
790+ return 0;
663791 }
664792
665793 static struct i915_request *
@@ -702,12 +830,13 @@ static void cb_retire(struct i915_active *base) · 36 unmodified lines
702830 I915_SELFTEST_DECLARE(static unsigned long context_barrier_inject_fault);
703831 static int context_barrier_task(struct i915_gem_context *ctx,
704832 unsigned long engines,
833+ int (*emit)(struct i915_request *rq, void *data),
705834 void (*task)(void *data),
706835 void *data)
707836 {
708837 struct drm_i915_private *i915 = ctx->i915;
709838 struct context_barrier_task *cb;
710− struct intel_context *ce;
839+ struct intel_context *ce, *next;
711840 intel_wakeref_t wakeref;
712841 int err = 0;
713842
@@ -722,11 +851,11 @@ static int context_barrier_task(struct i915_gem_context *ctx, · 8 unmodified lines
722851 i915_active_acquire(&cb->base);
723852
724853 wakeref = intel_runtime_pm_get(i915);
725− list_for_each_entry(ce, &ctx->active_engines, active_link) {
854+ rbtree_postorder_for_each_entry_safe(ce, next, &ctx->hw_contexts, node) {
726855 struct intel_engine_cs *engine = ce->engine;
727856 struct i915_request *rq;
728857
729− if (!(ce->engine->mask & engines))
858+ if (!(engine->mask & engines))
730859 continue;
731860
732861 if (I915_SELFTEST_ONLY(context_barrier_inject_fault &
@@ -741,7 +870,12 @@ static int context_barrier_task(struct i915_gem_context *ctx, · 8 unmodified lines
741870 break;
742871 }
743872
744− err = i915_active_ref(&cb->base, rq->fence.context, rq);
873+ err = 0;
874+ if (emit)
875+ err = emit(rq, data);
876+ if (err == 0)
877+ err = i915_active_ref(&cb->base, rq->fence.context, rq);
878+
745879 i915_request_add(rq);
746880 if (err)
747881 break;
@@ -804,6 +938,170 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915, · 56 unmodified lines
804938 return 0;
805939 }
806940
941+static int get_ppgtt(struct i915_gem_context *ctx,
942+ struct drm_i915_gem_context_param *args)
943+{
944+ struct drm_i915_file_private *file_priv = ctx->file_priv;
945+ struct i915_hw_ppgtt *ppgtt;
946+ int ret;
947+
948+ if (!ctx->ppgtt)
949+ return -ENODEV;
950+
951+ /* XXX rcu acquire? */
952+ ret = mutex_lock_interruptible(&ctx->i915->drm.struct_mutex);
953+ if (ret)
954+ return ret;
955+
956+ ppgtt = i915_ppgtt_get(ctx->ppgtt);
957+ mutex_unlock(&ctx->i915->drm.struct_mutex);
958+
959+ ret = mutex_lock_interruptible(&file_priv->vm_idr_lock);
960+ if (ret)
961+ goto err_put;
962+
963+ if (!ppgtt->user_handle) {
964+ ret = idr_alloc(&file_priv->vm_idr, ppgtt, 0, 0, GFP_KERNEL);
965+ GEM_BUG_ON(!ret);
966+ if (ret < 0)
967+ goto err_unlock;
968+
969+ ppgtt->user_handle = ret;
970+ i915_ppgtt_get(ppgtt);
971+ }
972+
973+ args->size = 0;
974+ args->value = ppgtt->user_handle;
975+
976+ ret = 0;
977+err_unlock:
978+ mutex_unlock(&file_priv->vm_idr_lock);
979+err_put:
980+ i915_ppgtt_put(ppgtt);
981+ return ret;
982+}
983+
984+static void set_ppgtt_barrier(void *data)
985+{
986+ struct i915_hw_ppgtt *old = data;
987+
988+ if (INTEL_GEN(old->vm.i915) < 8)
989+ gen6_ppgtt_unpin_all(old);
990+
991+ i915_ppgtt_put(old);
992+}
993+
994+static int emit_ppgtt_update(struct i915_request *rq, void *data)
995+{
996+ struct i915_hw_ppgtt *ppgtt = rq->gem_context->ppgtt;
997+ struct intel_engine_cs *engine = rq->engine;
998+ u32 *cs;
999+ int i;
1000+
1001+ if (i915_vm_is_4lvl(&ppgtt->vm)) {
1002+ const dma_addr_t pd_daddr = px_dma(&ppgtt->pml4);
1003+
1004+ cs = intel_ring_begin(rq, 6);
1005+ if (IS_ERR(cs))
1006+ return PTR_ERR(cs);
1007+
1008+ *cs++ = MI_LOAD_REGISTER_IMM(2);
1009+
1010+ *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(engine, 0));
1011+ *cs++ = upper_32_bits(pd_daddr);
1012+ *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(engine, 0));
1013+ *cs++ = lower_32_bits(pd_daddr);
1014+
1015+ *cs++ = MI_NOOP;
1016+ intel_ring_advance(rq, cs);
1017+ } else if (HAS_LOGICAL_RING_CONTEXTS(engine->i915)) {
1018+ cs = intel_ring_begin(rq, 4 * GEN8_3LVL_PDPES + 2);
1019+ if (IS_ERR(cs))
1020+ return PTR_ERR(cs);
1021+
1022+ *cs++ = MI_LOAD_REGISTER_IMM(2 * GEN8_3LVL_PDPES);
1023+ for (i = GEN8_3LVL_PDPES; i--; ) {
1024+ const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
1025+
1026+ *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(engine, i));
1027+ *cs++ = upper_32_bits(pd_daddr);
1028+ *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(engine, i));
1029+ *cs++ = lower_32_bits(pd_daddr);
1030+ }
1031+ *cs++ = MI_NOOP;
1032+ intel_ring_advance(rq, cs);
1033+ } else {
1034+ /* ppGTT is not part of the legacy context image */
1035+ gen6_ppgtt_pin(ppgtt);
1036+ }
1037+
1038+ return 0;
1039+}
1040+
1041+static int set_ppgtt(struct i915_gem_context *ctx,
1042+ struct drm_i915_gem_context_param *args)
1043+{
1044+ struct drm_i915_file_private *file_priv = ctx->file_priv;
1045+ struct i915_hw_ppgtt *ppgtt, *old;
1046+ int err;
1047+
1048+ if (args->size)
1049+ return -EINVAL;
1050+
1051+ if (!ctx->ppgtt)
1052+ return -ENODEV;
1053+
1054+ if (upper_32_bits(args->value))
1055+ return -ENOENT;
1056+
1057+ err = mutex_lock_interruptible(&file_priv->vm_idr_lock);
1058+ if (err)
1059+ return err;
1060+
1061+ ppgtt = idr_find(&file_priv->vm_idr, args->value);
1062+ if (ppgtt) {
1063+ GEM_BUG_ON(ppgtt->user_handle != args->value);
1064+ i915_ppgtt_get(ppgtt);
1065+ }
1066+ mutex_unlock(&file_priv->vm_idr_lock);
1067+ if (!ppgtt)
1068+ return -ENOENT;
1069+
1070+ err = mutex_lock_interruptible(&ctx->i915->drm.struct_mutex);
1071+ if (err)
1072+ goto out;
1073+
1074+ if (ppgtt == ctx->ppgtt)
1075+ goto unlock;
1076+
1077+ /* Teardown the existing obj:vma cache, it will have to be rebuilt. */
1078+ lut_close(ctx);
1079+
1080+ old = __set_ppgtt(ctx, ppgtt);
1081+
1082+ /*
1083+ * We need to flush any requests using the current ppgtt before
1084+ * we release it as the requests do not hold a reference themselves,
1085+ * only indirectly through the context.
1086+ */
1087+ err = context_barrier_task(ctx, ALL_ENGINES,
1088+ emit_ppgtt_update,
1089+ set_ppgtt_barrier,
1090+ old);
1091+ if (err) {
1092+ ctx->ppgtt = old;
1093+ ctx->desc_template = default_desc_template(ctx->i915, old);
1094+ i915_ppgtt_put(ppgtt);
1095+ }
1096+
1097+unlock:
1098+ mutex_unlock(&ctx->i915->drm.struct_mutex);
1099+
1100+out:
1101+ i915_ppgtt_put(ppgtt);
1102+ return err;
1103+}
1104+
8071105 static bool client_is_banned(struct drm_i915_file_private *file_priv)
8081106 {
8091107 return atomic_read(&file_priv->ban_score) >= I915_CLIENT_SCORE_BANNED;
@@ -984,6 +1282,9 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, · 174 unmodified lines
9841282 case I915_CONTEXT_PARAM_SSEU:
9851283 ret = get_sseu(ctx, args);
9861284 break;
1285+ case I915_CONTEXT_PARAM_VM:
1286+ ret = get_ppgtt(ctx, args);
1287+ break;
9871288 default:
9881289 ret = -EINVAL;
9891290 break;
@@ -1285,9 +1586,6 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, · 295 unmodified lines
12851586 return -ENOENT;
12861587
12871588 switch (args->param) {
1288− case I915_CONTEXT_PARAM_BAN_PERIOD:
1289− ret = -EINVAL;
1290− break;
12911589 case I915_CONTEXT_PARAM_NO_ZEROMAP:
12921590 if (args->size)
12931591 ret = -EINVAL;
@@ -1343,9 +1641,16 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, · 49 unmodified lines
13431641 I915_USER_PRIORITY(priority);
13441642 }
13451643 break;
1644+
13461645 case I915_CONTEXT_PARAM_SSEU:
13471646 ret = set_sseu(ctx, args);
13481647 break;
1648+
1649+ case I915_CONTEXT_PARAM_VM:
1650+ ret = set_ppgtt(ctx, args);
1651+ break;
1652+
1653+ case I915_CONTEXT_PARAM_BAN_PERIOD:
13491654 default:
13501655 ret = -EINVAL;
13511656 break;
drivers/gpu/drm/i915/i915_gem_context.h+5−0
@@ -148,6 +148,11 @@ void i915_gem_context_release(struct kref *ctx_ref); · 147 unmodified lines
148148 struct i915_gem_context *
149149 i915_gem_context_create_gvt(struct drm_device *dev);
150150
151+int i915_gem_vm_create_ioctl(struct drm_device *dev, void *data,
152+ struct drm_file *file);
153+int i915_gem_vm_destroy_ioctl(struct drm_device *dev, void *data,
154+ struct drm_file *file);
155+
151156 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
152157 struct drm_file *file);
153158 int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
drivers/gpu/drm/i915/i915_gem_gtt.c+13−6
@@ -1937,6 +1937,8 @@ int gen6_ppgtt_pin(struct i915_hw_ppgtt *base) · 1936 unmodified lines
19371937 struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base);
19381938 int err;
19391939
1940+ GEM_BUG_ON(ppgtt->base.vm.closed);
1941+
19401942 /*
19411943 * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt
19421944 * which will be pinned into every active context.
@@ -1975,6 +1977,17 @@ void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base) · 32 unmodified lines
19751977 i915_vma_unpin(ppgtt->vma);
19761978 }
19771979
1980+void gen6_ppgtt_unpin_all(struct i915_hw_ppgtt *base)
1981+{
1982+ struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base);
1983+
1984+ if (!ppgtt->pin_count)
1985+ return;
1986+
1987+ ppgtt->pin_count = 0;
1988+ i915_vma_unpin(ppgtt->vma);
1989+}
1990+
19781991 static struct i915_hw_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915)
19791992 {
19801993 struct i915_ggtt * const ggtt = &i915->ggtt;
@@ -2082,12 +2095,6 @@ i915_ppgtt_create(struct drm_i915_private *i915) · 101 unmodified lines
20822095 return ppgtt;
20832096 }
20842097
2085−void i915_ppgtt_close(struct i915_address_space *vm)
2086−{
2087− GEM_BUG_ON(vm->closed);
2088− vm->closed = true;
2089−}
2090−
20912098 static void ppgtt_destroy_vma(struct i915_address_space *vm)
20922099 {
20932100 struct list_head *phases[] = {
drivers/gpu/drm/i915/i915_gem_gtt.h+6−4
@@ -396,6 +396,8 @@ struct i915_hw_ppgtt { · 395 unmodified lines
396396 struct i915_page_directory_pointer pdp; /* GEN8+ */
397397 struct i915_page_directory pd; /* GEN6-7 */
398398 };
399+
400+ u32 user_handle;
399401 };
400402
401403 struct gen6_hw_ppgtt {
@@ -605,13 +607,12 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv); · 203 unmodified lines
605607 int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv);
606608
607609 struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv);
608−void i915_ppgtt_close(struct i915_address_space *vm);
609610 void i915_ppgtt_release(struct kref *kref);
610611
611−static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt)
612+static inline struct i915_hw_ppgtt *i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt)
612613 {
613− if (ppgtt)
614− kref_get(&ppgtt->ref);
614+ kref_get(&ppgtt->ref);
615+ return ppgtt;
615616 }
616617
617618 static inline void i915_ppgtt_put(struct i915_hw_ppgtt *ppgtt)
@@ -622,6 +623,7 @@ static inline void i915_ppgtt_put(struct i915_hw_ppgtt *ppgtt) · 4 unmodified lines
622623
623624 int gen6_ppgtt_pin(struct i915_hw_ppgtt *base);
624625 void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base);
626+void gen6_ppgtt_unpin_all(struct i915_hw_ppgtt *base);
625627
626628 void i915_check_and_clear_faults(struct drm_i915_private *dev_priv);
627629 void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv);
drivers/gpu/drm/i915/selftests/huge_pages.c+0−1
@@ -1732,7 +1732,6 @@ int i915_gem_huge_page_mock_selftests(void) · 1731 unmodified lines
17321732 err = i915_subtests(tests, ppgtt);
17331733
17341734 out_close:
1735− i915_ppgtt_close(&ppgtt->vm);
17361735 i915_ppgtt_put(ppgtt);
17371736
17381737 out_unlock:
drivers/gpu/drm/i915/selftests/i915_gem_context.c+184−54
@@ -373,7 +373,8 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value) · 372 unmodified lines
373373 return 0;
374374 }
375375
376−static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max)
376+static noinline int cpu_check(struct drm_i915_gem_object *obj,
377+ unsigned int idx, unsigned int max)
377378 {
378379 unsigned int n, m, needs_flush;
379380 int err;
@@ -391,8 +392,10 @@ static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max) · 11 unmodified lines
391392
392393 for (m = 0; m < max; m++) {
393394 if (map[m] != m) {
394− pr_err("Invalid value at page %d, offset %d: found %x expected %x\n",
395− n, m, map[m], m);
395+ pr_err("%pS: Invalid value at object %d page %d/%ld, offset %d/%d: found %x expected %x\n",
396+ __builtin_return_address(0), idx,
397+ n, real_page_count(obj), m, max,
398+ map[m], m);
396399 err = -EINVAL;
397400 goto out_unmap;
398401 }
@@ -400,8 +403,9 @@ static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max) · 1 unmodified line
400403
401404 for (; m < DW_PER_PAGE; m++) {
402405 if (map[m] != STACK_MAGIC) {
403− pr_err("Invalid value at page %d, offset %d: found %x expected %x\n",
404− n, m, map[m], STACK_MAGIC);
406+ pr_err("%pS: Invalid value at object %d page %d, offset %d: found %x expected %x (uninitialised)\n",
407+ __builtin_return_address(0), idx, n, m,
408+ map[m], STACK_MAGIC);
405409 err = -EINVAL;
406410 goto out_unmap;
407411 }
@@ -479,12 +483,8 @@ static unsigned long max_dwords(struct drm_i915_gem_object *obj) · 71 unmodified lines
479483 static int igt_ctx_exec(void *arg)
480484 {
481485 struct drm_i915_private *i915 = arg;
482− struct drm_i915_gem_object *obj = NULL;
483− unsigned long ncontexts, ndwords, dw;
484− struct igt_live_test t;
485− struct drm_file *file;
486− IGT_TIMEOUT(end_time);
487− LIST_HEAD(objects);
486+ struct intel_engine_cs *engine;
487+ enum intel_engine_id id;
488488 int err = -ENODEV;
489489
490490 /*
@@ -496,44 +496,167 @@ static int igt_ctx_exec(void *arg) · 5 unmodified lines
496496 if (!DRIVER_CAPS(i915)->has_logical_contexts)
497497 return 0;
498498
499+ for_each_engine(engine, i915, id) {
500+ struct drm_i915_gem_object *obj = NULL;
501+ unsigned long ncontexts, ndwords, dw;
502+ struct igt_live_test t;
503+ struct drm_file *file;
504+ IGT_TIMEOUT(end_time);
505+ LIST_HEAD(objects);
506+
507+ if (!intel_engine_can_store_dword(engine))
508+ continue;
509+
510+ if (!engine->context_size)
511+ continue; /* No logical context support in HW */
512+
513+ file = mock_file(i915);
514+ if (IS_ERR(file))
515+ return PTR_ERR(file);
516+
517+ mutex_lock(&i915->drm.struct_mutex);
518+
519+ err = igt_live_test_begin(&t, i915, __func__, engine->name);
520+ if (err)
521+ goto out_unlock;
522+
523+ ncontexts = 0;
524+ ndwords = 0;
525+ dw = 0;
526+ while (!time_after(jiffies, end_time)) {
527+ struct i915_gem_context *ctx;
528+ intel_wakeref_t wakeref;
529+
530+ ctx = live_context(i915, file);
531+ if (IS_ERR(ctx)) {
532+ err = PTR_ERR(ctx);
533+ goto out_unlock;
534+ }
535+
536+ if (!obj) {
537+ obj = create_test_object(ctx, file, &objects);
538+ if (IS_ERR(obj)) {
539+ err = PTR_ERR(obj);
540+ goto out_unlock;
541+ }
542+ }
543+
544+ with_intel_runtime_pm(i915, wakeref)
545+ err = gpu_fill(obj, ctx, engine, dw);
546+ if (err) {
547+ pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
548+ ndwords, dw, max_dwords(obj),
549+ engine->name, ctx->hw_id,
550+ yesno(!!ctx->ppgtt), err);
551+ goto out_unlock;
552+ }
553+
554+ if (++dw == max_dwords(obj)) {
555+ obj = NULL;
556+ dw = 0;
557+ }
558+
559+ ndwords++;
560+ ncontexts++;
561+ }
562+
563+ pr_info("Submitted %lu contexts to %s, filling %lu dwords\n",
564+ ncontexts, engine->name, ndwords);
565+
566+ ncontexts = dw = 0;
567+ list_for_each_entry(obj, &objects, st_link) {
568+ unsigned int rem =
569+ min_t(unsigned int, ndwords - dw, max_dwords(obj));
570+
571+ err = cpu_check(obj, ncontexts++, rem);
572+ if (err)
573+ break;
574+
575+ dw += rem;
576+ }
577+
578+out_unlock:
579+ if (igt_live_test_end(&t))
580+ err = -EIO;
581+ mutex_unlock(&i915->drm.struct_mutex);
582+
583+ mock_file_free(i915, file);
584+ if (err)
585+ return err;
586+ }
587+
588+ return 0;
589+}
590+
591+static int igt_shared_ctx_exec(void *arg)
592+{
593+ struct drm_i915_private *i915 = arg;
594+ struct i915_gem_context *parent;
595+ struct intel_engine_cs *engine;
596+ enum intel_engine_id id;
597+ struct igt_live_test t;
598+ struct drm_file *file;
599+ int err = 0;
600+
601+ /*
602+ * Create a few different contexts with the same mm and write
603+ * through each ctx using the GPU making sure those writes end
604+ * up in the expected pages of our obj.
605+ */
606+ if (!DRIVER_CAPS(i915)->has_logical_contexts)
607+ return 0;
608+
499609 file = mock_file(i915);
500610 if (IS_ERR(file))
501611 return PTR_ERR(file);
502612
503613 mutex_lock(&i915->drm.struct_mutex);
504614
615+ parent = live_context(i915, file);
616+ if (IS_ERR(parent)) {
617+ err = PTR_ERR(parent);
618+ goto out_unlock;
619+ }
620+
621+ if (!parent->ppgtt) { /* not full-ppgtt; nothing to share */
622+ err = 0;
623+ goto out_unlock;
624+ }
625+
505626 err = igt_live_test_begin(&t, i915, __func__, "");
506627 if (err)
507628 goto out_unlock;
508629
509− ncontexts = 0;
510− ndwords = 0;
511− dw = 0;
512− while (!time_after(jiffies, end_time)) {
513− struct intel_engine_cs *engine;
514− struct i915_gem_context *ctx;
515− unsigned int id;
630+ for_each_engine(engine, i915, id) {
631+ unsigned long ncontexts, ndwords, dw;
632+ struct drm_i915_gem_object *obj = NULL;
633+ IGT_TIMEOUT(end_time);
634+ LIST_HEAD(objects);
516635
517− ctx = live_context(i915, file);
518− if (IS_ERR(ctx)) {
519− err = PTR_ERR(ctx);
520− goto out_unlock;
521− }
636+ if (!intel_engine_can_store_dword(engine))
637+ continue;
522638
523− for_each_engine(engine, i915, id) {
639+ dw = 0;
640+ ndwords = 0;
641+ ncontexts = 0;
642+ while (!time_after(jiffies, end_time)) {
643+ struct i915_gem_context *ctx;
524644 intel_wakeref_t wakeref;
525645
526− if (!engine->context_size)
527− continue; /* No logical context support in HW */
646+ ctx = kernel_context(i915);
647+ if (IS_ERR(ctx)) {
648+ err = PTR_ERR(ctx);
649+ goto out_test;
650+ }
528651
529− if (!intel_engine_can_store_dword(engine))
530− continue;
652+ __assign_ppgtt(ctx, parent->ppgtt);
531653
532654 if (!obj) {
533− obj = create_test_object(ctx, file, &objects);
655+ obj = create_test_object(parent, file, &objects);
534656 if (IS_ERR(obj)) {
535657 err = PTR_ERR(obj);
536− goto out_unlock;
658+ kernel_context_close(ctx);
659+ goto out_test;
537660 }
538661 }
539662
@@ -545,35 +668,39 @@ static int igt_ctx_exec(void *arg) · 5 unmodified lines
545668 ndwords, dw, max_dwords(obj),
546669 engine->name, ctx->hw_id,
547670 yesno(!!ctx->ppgtt), err);
548− goto out_unlock;
671+ kernel_context_close(ctx);
672+ goto out_test;
549673 }
550674
551675 if (++dw == max_dwords(obj)) {
552676 obj = NULL;
553677 dw = 0;
554678 }
679+
555680 ndwords++;
681+ ncontexts++;
682+
683+ kernel_context_close(ctx);
556684 }
557− ncontexts++;
558− }
559− pr_info("Submitted %lu contexts (across %u engines), filling %lu dwords\n",
560− ncontexts, RUNTIME_INFO(i915)->num_engines, ndwords);
685+ pr_info("Submitted %lu contexts to %s, filling %lu dwords\n",
686+ ncontexts, engine->name, ndwords);
561687
562− dw = 0;
563− list_for_each_entry(obj, &objects, st_link) {
564− unsigned int rem =
565− min_t(unsigned int, ndwords - dw, max_dwords(obj));
688+ ncontexts = dw = 0;
689+ list_for_each_entry(obj, &objects, st_link) {
690+ unsigned int rem =
691+ min_t(unsigned int, ndwords - dw, max_dwords(obj));
566692
567− err = cpu_check(obj, rem);
568− if (err)
569− break;
693+ err = cpu_check(obj, ncontexts++, rem);
694+ if (err)
695+ goto out_test;
570696
571− dw += rem;
697+ dw += rem;
698+ }
572699 }
573−
574−out_unlock:
700+out_test:
575701 if (igt_live_test_end(&t))
576702 err = -EIO;
703+out_unlock:
577704 mutex_unlock(&i915->drm.struct_mutex);
578705
579706 mock_file_free(i915, file);
@@ -1046,7 +1173,7 @@ static int igt_ctx_readonly(void *arg) · 466 unmodified lines
10461173 struct drm_i915_gem_object *obj = NULL;
10471174 struct i915_gem_context *ctx;
10481175 struct i915_hw_ppgtt *ppgtt;
1049− unsigned long ndwords, dw;
1176+ unsigned long idx, ndwords, dw;
10501177 struct igt_live_test t;
10511178 struct drm_file *file;
10521179 I915_RND_STATE(prng);
@@ -1127,6 +1254,7 @@ static int igt_ctx_readonly(void *arg) · 74 unmodified lines
11271254 ndwords, RUNTIME_INFO(i915)->num_engines);
11281255
11291256 dw = 0;
1257+ idx = 0;
11301258 list_for_each_entry(obj, &objects, st_link) {
11311259 unsigned int rem =
11321260 min_t(unsigned int, ndwords - dw, max_dwords(obj));
@@ -1136,7 +1264,7 @@ static int igt_ctx_readonly(void *arg) · 3 unmodified lines
11361264 if (i915_gem_object_is_readonly(obj))
11371265 num_writes = 0;
11381266
1139− err = cpu_check(obj, num_writes);
1267+ err = cpu_check(obj, idx++, num_writes);
11401268 if (err)
11411269 break;
11421270
@@ -1619,7 +1747,8 @@ static int mock_context_barrier(void *arg) · 476 unmodified lines
16191747 }
16201748
16211749 counter = 0;
1622− err = context_barrier_task(ctx, 0, mock_barrier_task, &counter);
1750+ err = context_barrier_task(ctx, 0,
1751+ NULL, mock_barrier_task, &counter);
16231752 if (err) {
16241753 pr_err("Failed at line %d, err=%d\n", __LINE__, err);
16251754 goto out;
@@ -1631,8 +1760,8 @@ static int mock_context_barrier(void *arg) · 5 unmodified lines
16311760 }
16321761
16331762 counter = 0;
1634− err = context_barrier_task(ctx,
1635− ALL_ENGINES, mock_barrier_task, &counter);
1763+ err = context_barrier_task(ctx, ALL_ENGINES,
1764+ NULL, mock_barrier_task, &counter);
16361765 if (err) {
16371766 pr_err("Failed at line %d, err=%d\n", __LINE__, err);
16381767 goto out;
@@ -1655,8 +1784,8 @@ static int mock_context_barrier(void *arg) · 16 unmodified lines
16551784
16561785 counter = 0;
16571786 context_barrier_inject_fault = BIT(RCS0);
1658− err = context_barrier_task(ctx,
1659− ALL_ENGINES, mock_barrier_task, &counter);
1787+ err = context_barrier_task(ctx, ALL_ENGINES,
1788+ NULL, mock_barrier_task, &counter);
16601789 context_barrier_inject_fault = 0;
16611790 if (err == -ENXIO)
16621791 err = 0;
@@ -1670,8 +1799,8 @@ static int mock_context_barrier(void *arg) · 7 unmodified lines
16701799 goto out;
16711800
16721801 counter = 0;
1673− err = context_barrier_task(ctx,
1674− ALL_ENGINES, mock_barrier_task, &counter);
1802+ err = context_barrier_task(ctx, ALL_ENGINES,
1803+ NULL, mock_barrier_task, &counter);
16751804 if (err) {
16761805 pr_err("Failed at line %d, err=%d\n", __LINE__, err);
16771806 goto out;
@@ -1719,6 +1848,7 @@ int i915_gem_context_live_selftests(struct drm_i915_private *dev_priv) · 41 unmodified lines
17191848 SUBTEST(igt_ctx_exec),
17201849 SUBTEST(igt_ctx_readonly),
17211850 SUBTEST(igt_ctx_sseu),
1851+ SUBTEST(igt_shared_ctx_exec),
17221852 SUBTEST(igt_vm_isolation),
17231853 };
17241854
drivers/gpu/drm/i915/selftests/i915_gem_gtt.c+0−1
@@ -1020,7 +1020,6 @@ static int exercise_ppgtt(struct drm_i915_private *dev_priv, · 1019 unmodified lines
10201020
10211021 err = func(dev_priv, &ppgtt->vm, 0, ppgtt->vm.total, end_time);
10221022
1023− i915_ppgtt_close(&ppgtt->vm);
10241023 i915_ppgtt_put(ppgtt);
10251024 out_unlock:
10261025 mutex_unlock(&dev_priv->drm.struct_mutex);
drivers/gpu/drm/i915/selftests/mock_context.c+6−2
@@ -54,13 +54,17 @@ mock_context(struct drm_i915_private *i915, · 53 unmodified lines
5454 goto err_handles;
5555
5656 if (name) {
57+ struct i915_hw_ppgtt *ppgtt;
58+
5759 ctx->name = kstrdup(name, GFP_KERNEL);
5860 if (!ctx->name)
5961 goto err_put;
6062
61− ctx->ppgtt = mock_ppgtt(i915, name);
62− if (!ctx->ppgtt)
63+ ppgtt = mock_ppgtt(i915, name);
64+ if (!ppgtt)
6365 goto err_put;
66+
67+ __set_ppgtt(ctx, ppgtt);
6468 }
6569
6670 return ctx;
include/uapi/drm/i915_drm.h+43−0
@@ -343,6 +343,8 @@ typedef struct _drm_i915_sarea { · 342 unmodified lines
343343 #define DRM_I915_PERF_ADD_CONFIG 0x37
344344 #define DRM_I915_PERF_REMOVE_CONFIG 0x38
345345 #define DRM_I915_QUERY 0x39
346+#define DRM_I915_GEM_VM_CREATE 0x3a
347+#define DRM_I915_GEM_VM_DESTROY 0x3b
346348 /* Must be kept compact -- no holes */
347349
348350 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
@@ -402,6 +404,8 @@ typedef struct _drm_i915_sarea { · 53 unmodified lines
402404 #define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
403405 #define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
404406 #define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
407+#define DRM_IOCTL_I915_GEM_VM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_CREATE, struct drm_i915_gem_vm_control)
408+#define DRM_IOCTL_I915_GEM_VM_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_VM_DESTROY, struct drm_i915_gem_vm_control)
405409
406410 /* Allow drivers to submit batchbuffers directly to hardware, relying
407411 * on the security mechanisms provided by hardware.
@@ -1453,6 +1457,33 @@ struct drm_i915_gem_context_destroy { · 1045 unmodified lines
14531457 __u32 pad;
14541458 };
14551459
1460+/*
1461+ * DRM_I915_GEM_VM_CREATE -
1462+ *
1463+ * Create a new virtual memory address space (ppGTT) for use within a context
1464+ * on the same file. Extensions can be provided to configure exactly how the
1465+ * address space is setup upon creation.
1466+ *
1467+ * The id of new VM (bound to the fd) for use with I915_CONTEXT_PARAM_VM is
1468+ * returned in the outparam @vm_id.
1469+ *
1470+ * No flags are defined, with all bits reserved and must be zero.
1471+ *
1472+ * An extension chain maybe provided, starting with @extensions, and terminated
1473+ * by the @next_extension being 0. Currently, no extensions are defined.
1474+ *
1475+ * DRM_I915_GEM_VM_DESTROY -
1476+ *
1477+ * Destroys a previously created VM id, specified in @vm_id.
1478+ *
1479+ * No extensions or flags are allowed currently, and so must be zero.
1480+ */
1481+struct drm_i915_gem_vm_control {
1482+ __u64 extensions;
1483+ __u32 flags;
1484+ __u32 vm_id;
1485+};
1486+
14561487 struct drm_i915_reg_read {
14571488 /*
14581489 * Register offset.
@@ -1542,7 +1573,19 @@ struct drm_i915_gem_context_param { · 83 unmodified lines
15421573 * On creation, all new contexts are marked as recoverable.
15431574 */
15441575 #define I915_CONTEXT_PARAM_RECOVERABLE 0x8
1576+
1577+ /*
1578+ * The id of the associated virtual memory address space (ppGTT) of
1579+ * this context. Can be retrieved and passed to another context
1580+ * (on the same fd) for both to use the same ppGTT and so share
1581+ * address layouts, and avoid reloading the page tables on context
1582+ * switches between themselves.
1583+ *
1584+ * See DRM_I915_GEM_VM_CREATE and DRM_I915_GEM_VM_DESTROY.
1585+ */
1586+#define I915_CONTEXT_PARAM_VM 0x9
15451587 /* Must be kept compact -- no holes and well documented */
1588+
15461589 __u64 value;
15471590 };
15481591