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
3122 DRM_IOCTL_DEF_DRV(I915_PERF_ADD_CONFIG, i915_perf_add_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),3122 DRM_IOCTL_DEF_DRV(I915_PERF_ADD_CONFIG, i915_perf_add_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
3123 DRM_IOCTL_DEF_DRV(I915_PERF_REMOVE_CONFIG, i915_perf_remove_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),3123 DRM_IOCTL_DEF_DRV(I915_PERF_REMOVE_CONFIG, i915_perf_remove_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
3124 DRM_IOCTL_DEF_DRV(I915_QUERY, i915_query_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),3124 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),
3125};3127};
3126 3128
3127static struct drm_driver driver = {3129static 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
220 struct idr context_idr;220 struct idr context_idr;
221 struct mutex context_idr_lock; /* guards context_idr */221 struct mutex context_idr_lock; /* guards context_idr */
222 222
223 struct idr vm_idr;
224 struct mutex vm_idr_lock; /* guards vm_idr */
225
223 unsigned int bsd_engine;226 unsigned int bsd_engine;
224 227
225/*228/*
drivers/gpu/drm/i915/i915_gem_context.c+318−13
@@ -90,6 +90,7 @@ · 89 unmodified lines
90#include "i915_drv.h"90#include "i915_drv.h"
91#include "i915_globals.h"91#include "i915_globals.h"
92#include "i915_trace.h"92#include "i915_trace.h"
93#include "i915_user_extensions.h"
93#include "intel_lrc_reg.h"94#include "intel_lrc_reg.h"
94#include "intel_workarounds.h"95#include "intel_workarounds.h"
95 96
@@ -120,12 +121,15 @@ static void lut_close(struct i915_gem_context *ctx) · 24 unmodified lines
120 list_del(&lut->obj_link);121 list_del(&lut->obj_link);
121 i915_lut_handle_free(lut);122 i915_lut_handle_free(lut);
122 }123 }
124 INIT_LIST_HEAD(&ctx->handles_list);
123 125
124 rcu_read_lock();126 rcu_read_lock();
125 radix_tree_for_each_slot(slot, &ctx->handles_vma, &iter, 0) {127 radix_tree_for_each_slot(slot, &ctx->handles_vma, &iter, 0) {
126 struct i915_vma *vma = rcu_dereference_raw(*slot);128 struct i915_vma *vma = rcu_dereference_raw(*slot);
127 129
128 radix_tree_iter_delete(&ctx->handles_vma, &iter, slot);130 radix_tree_iter_delete(&ctx->handles_vma, &iter, slot);
131
132 vma->open_count--;
129 __i915_gem_object_release_unless_active(vma->obj);133 __i915_gem_object_release_unless_active(vma->obj);
130 }134 }
131 rcu_read_unlock();135 rcu_read_unlock();
@@ -305,8 +309,6 @@ static void context_close(struct i915_gem_context *ctx) · 173 unmodified lines
305 * the ppgtt).309 * the ppgtt).
306 */310 */
307 lut_close(ctx);311 lut_close(ctx);
308 if (ctx->ppgtt)
309 i915_ppgtt_close(&ctx->ppgtt->vm);
310 312
311 ctx->file_priv = ERR_PTR(-EBADF);313 ctx->file_priv = ERR_PTR(-EBADF);
312 i915_gem_context_put(ctx);314 i915_gem_context_put(ctx);
@@ -378,6 +380,28 @@ __create_context(struct drm_i915_private *dev_priv) · 65 unmodified lines
378 return ctx;380 return ctx;
379}381}
380 382
383static 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
394static 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
381static struct i915_gem_context *405static struct i915_gem_context *
382i915_gem_create_context(struct drm_i915_private *dev_priv)406i915_gem_create_context(struct drm_i915_private *dev_priv)
383{407{
@@ -403,8 +427,8 @@ i915_gem_create_context(struct drm_i915_private *dev_priv) · 19 unmodified lines
403 return ERR_CAST(ppgtt);427 return ERR_CAST(ppgtt);
404 }428 }
405 429
406 ctx->ppgtt = ppgtt;430 __assign_ppgtt(ctx, ppgtt);
407 ctx->desc_template = default_desc_template(dev_priv, ppgtt);431 i915_ppgtt_put(ppgtt);
408 }432 }
409 433
410 trace_i915_context_create(ctx);434 trace_i915_context_create(ctx);
@@ -583,6 +607,12 @@ static int context_idr_cleanup(int id, void *p, void *data) · 172 unmodified lines
583 return 0;607 return 0;
584}608}
585 609
610static int vm_idr_cleanup(int id, void *p, void *data)
611{
612 i915_ppgtt_put(p);
613 return 0;
614}
615
586static int gem_context_register(struct i915_gem_context *ctx,616static int gem_context_register(struct i915_gem_context *ctx,
587 struct drm_i915_file_private *fpriv)617 struct drm_i915_file_private *fpriv)
588{618{
@@ -621,8 +651,11 @@ int i915_gem_context_open(struct drm_i915_private *i915, · 32 unmodified lines
621 struct i915_gem_context *ctx;651 struct i915_gem_context *ctx;
622 int err;652 int err;
623 653
624 idr_init(&file_priv->context_idr);
625 mutex_init(&file_priv->context_idr_lock);654 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);
626 659
627 mutex_lock(&i915->drm.struct_mutex);660 mutex_lock(&i915->drm.struct_mutex);
628 ctx = i915_gem_create_context(i915);661 ctx = i915_gem_create_context(i915);
@@ -646,8 +679,10 @@ err_ctx: · 17 unmodified lines
646 context_close(ctx);679 context_close(ctx);
647 mutex_unlock(&i915->drm.struct_mutex);680 mutex_unlock(&i915->drm.struct_mutex);
648err:681err:
649 mutex_destroy(&file_priv->context_idr_lock);682 idr_destroy(&file_priv->vm_idr);
650 idr_destroy(&file_priv->context_idr);683 idr_destroy(&file_priv->context_idr);
684 mutex_destroy(&file_priv->vm_idr_lock);
685 mutex_destroy(&file_priv->context_idr_lock);
651 return PTR_ERR(ctx);686 return PTR_ERR(ctx);
652}687}
653 688
@@ -660,6 +695,99 @@ void i915_gem_context_close(struct drm_file *file) · 6 unmodified lines
660 idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);695 idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
661 idr_destroy(&file_priv->context_idr);696 idr_destroy(&file_priv->context_idr);
662 mutex_destroy(&file_priv->context_idr_lock);697 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
704int 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
749err_unlock:
750 mutex_unlock(&file_priv->vm_idr_lock);
751err_put:
752 i915_ppgtt_put(ppgtt);
753 return err;
754}
755
756int 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;
663}791}
664 792
665static struct i915_request *793static struct i915_request *
@@ -702,12 +830,13 @@ static void cb_retire(struct i915_active *base) · 36 unmodified lines
702I915_SELFTEST_DECLARE(static unsigned long context_barrier_inject_fault);830I915_SELFTEST_DECLARE(static unsigned long context_barrier_inject_fault);
703static int context_barrier_task(struct i915_gem_context *ctx,831static int context_barrier_task(struct i915_gem_context *ctx,
704 unsigned long engines,832 unsigned long engines,
833 int (*emit)(struct i915_request *rq, void *data),
705 void (*task)(void *data),834 void (*task)(void *data),
706 void *data)835 void *data)
707{836{
708 struct drm_i915_private *i915 = ctx->i915;837 struct drm_i915_private *i915 = ctx->i915;
709 struct context_barrier_task *cb;838 struct context_barrier_task *cb;
710 struct intel_context *ce;839 struct intel_context *ce, *next;
711 intel_wakeref_t wakeref;840 intel_wakeref_t wakeref;
712 int err = 0;841 int err = 0;
713 842
@@ -722,11 +851,11 @@ static int context_barrier_task(struct i915_gem_context *ctx, · 8 unmodified lines
722 i915_active_acquire(&cb->base);851 i915_active_acquire(&cb->base);
723 852
724 wakeref = intel_runtime_pm_get(i915);853 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) {
726 struct intel_engine_cs *engine = ce->engine;855 struct intel_engine_cs *engine = ce->engine;
727 struct i915_request *rq;856 struct i915_request *rq;
728 857
729 if (!(ce->engine->mask & engines))858 if (!(engine->mask & engines))
730 continue;859 continue;
731 860
732 if (I915_SELFTEST_ONLY(context_barrier_inject_fault &861 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
741 break;870 break;
742 }871 }
743 872
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
745 i915_request_add(rq);879 i915_request_add(rq);
746 if (err)880 if (err)
747 break;881 break;
@@ -804,6 +938,170 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915, · 56 unmodified lines
804 return 0;938 return 0;
805}939}
806 940
941static 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;
977err_unlock:
978 mutex_unlock(&file_priv->vm_idr_lock);
979err_put:
980 i915_ppgtt_put(ppgtt);
981 return ret;
982}
983
984static 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
994static 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
1041static 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
1097unlock:
1098 mutex_unlock(&ctx->i915->drm.struct_mutex);
1099
1100out:
1101 i915_ppgtt_put(ppgtt);
1102 return err;
1103}
1104
807static bool client_is_banned(struct drm_i915_file_private *file_priv)1105static bool client_is_banned(struct drm_i915_file_private *file_priv)
808{1106{
809 return atomic_read(&file_priv->ban_score) >= I915_CLIENT_SCORE_BANNED;1107 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
984 case I915_CONTEXT_PARAM_SSEU:1282 case I915_CONTEXT_PARAM_SSEU:
985 ret = get_sseu(ctx, args);1283 ret = get_sseu(ctx, args);
986 break;1284 break;
1285 case I915_CONTEXT_PARAM_VM:
1286 ret = get_ppgtt(ctx, args);
1287 break;
987 default:1288 default:
988 ret = -EINVAL;1289 ret = -EINVAL;
989 break;1290 break;
@@ -1285,9 +1586,6 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, · 295 unmodified lines
1285 return -ENOENT;1586 return -ENOENT;
1286 1587
1287 switch (args->param) {1588 switch (args->param) {
1288 case I915_CONTEXT_PARAM_BAN_PERIOD:
1289 ret = -EINVAL;
1290 break;
1291 case I915_CONTEXT_PARAM_NO_ZEROMAP:1589 case I915_CONTEXT_PARAM_NO_ZEROMAP:
1292 if (args->size)1590 if (args->size)
1293 ret = -EINVAL;1591 ret = -EINVAL;
@@ -1343,9 +1641,16 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, · 49 unmodified lines
1343 I915_USER_PRIORITY(priority);1641 I915_USER_PRIORITY(priority);
1344 }1642 }
1345 break;1643 break;
1644
1346 case I915_CONTEXT_PARAM_SSEU:1645 case I915_CONTEXT_PARAM_SSEU:
1347 ret = set_sseu(ctx, args);1646 ret = set_sseu(ctx, args);
1348 break;1647 break;
1648
1649 case I915_CONTEXT_PARAM_VM:
1650 ret = set_ppgtt(ctx, args);
1651 break;
1652
1653 case I915_CONTEXT_PARAM_BAN_PERIOD:
1349 default:1654 default:
1350 ret = -EINVAL;1655 ret = -EINVAL;
1351 break;1656 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
148struct i915_gem_context *148struct i915_gem_context *
149i915_gem_context_create_gvt(struct drm_device *dev);149i915_gem_context_create_gvt(struct drm_device *dev);
150 150
151int i915_gem_vm_create_ioctl(struct drm_device *dev, void *data,
152 struct drm_file *file);
153int i915_gem_vm_destroy_ioctl(struct drm_device *dev, void *data,
154 struct drm_file *file);
155
151int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,156int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
152 struct drm_file *file);157 struct drm_file *file);
153int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,158int 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
1937 struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base);1937 struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base);
1938 int err;1938 int err;
1939 1939
1940 GEM_BUG_ON(ppgtt->base.vm.closed);
1941
1940 /*1942 /*
1941 * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt1943 * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt
1942 * which will be pinned into every active context.1944 * which will be pinned into every active context.
@@ -1975,6 +1977,17 @@ void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base) · 32 unmodified lines
1975 i915_vma_unpin(ppgtt->vma);1977 i915_vma_unpin(ppgtt->vma);
1976}1978}
1977 1979
1980void 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
1978static struct i915_hw_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915)1991static struct i915_hw_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915)
1979{1992{
1980 struct i915_ggtt * const ggtt = &i915->ggtt;1993 struct i915_ggtt * const ggtt = &i915->ggtt;
@@ -2082,12 +2095,6 @@ i915_ppgtt_create(struct drm_i915_private *i915) · 101 unmodified lines
2082 return ppgtt;2095 return ppgtt;
2083}2096}
2084 2097
2085void i915_ppgtt_close(struct i915_address_space *vm)
2086{
2087 GEM_BUG_ON(vm->closed);
2088 vm->closed = true;
2089}
2090
2091static void ppgtt_destroy_vma(struct i915_address_space *vm)2098static void ppgtt_destroy_vma(struct i915_address_space *vm)
2092{2099{
2093 struct list_head *phases[] = {2100 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
396 struct i915_page_directory_pointer pdp; /* GEN8+ */396 struct i915_page_directory_pointer pdp; /* GEN8+ */
397 struct i915_page_directory pd; /* GEN6-7 */397 struct i915_page_directory pd; /* GEN6-7 */
398 };398 };
399
400 u32 user_handle;
399};401};
400 402
401struct gen6_hw_ppgtt {403struct gen6_hw_ppgtt {
@@ -605,13 +607,12 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv); · 203 unmodified lines
605int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv);607int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv);
606 608
607struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv);609struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv);
608void i915_ppgtt_close(struct i915_address_space *vm);
609void i915_ppgtt_release(struct kref *kref);610void i915_ppgtt_release(struct kref *kref);
610 611
611static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt)612static inline struct i915_hw_ppgtt *i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt)
612{613{
613 if (ppgtt)614 kref_get(&ppgtt->ref);
614 kref_get(&ppgtt->ref);615 return ppgtt;
615}616}
616 617
617static inline void i915_ppgtt_put(struct i915_hw_ppgtt *ppgtt)618static 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
622 623
623int gen6_ppgtt_pin(struct i915_hw_ppgtt *base);624int gen6_ppgtt_pin(struct i915_hw_ppgtt *base);
624void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base);625void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base);
626void gen6_ppgtt_unpin_all(struct i915_hw_ppgtt *base);
625 627
626void i915_check_and_clear_faults(struct drm_i915_private *dev_priv);628void i915_check_and_clear_faults(struct drm_i915_private *dev_priv);
627void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv);629void 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
1732 err = i915_subtests(tests, ppgtt);1732 err = i915_subtests(tests, ppgtt);
1733 1733
1734out_close:1734out_close:
1735 i915_ppgtt_close(&ppgtt->vm);
1736 i915_ppgtt_put(ppgtt);1735 i915_ppgtt_put(ppgtt);
1737 1736
1738out_unlock:1737out_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
373 return 0;373 return 0;
374}374}
375 375
376static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max)376static noinline int cpu_check(struct drm_i915_gem_object *obj,
377 unsigned int idx, unsigned int max)
377{378{
378 unsigned int n, m, needs_flush;379 unsigned int n, m, needs_flush;
379 int err;380 int err;
@@ -391,8 +392,10 @@ static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max) · 11 unmodified lines
391 392
392 for (m = 0; m < max; m++) {393 for (m = 0; m < max; m++) {
393 if (map[m] != m) {394 if (map[m] != m) {
394 pr_err("Invalid value at page %d, offset %d: found %x expected %x\n",395 pr_err("%pS: Invalid value at object %d page %d/%ld, offset %d/%d: found %x expected %x\n",
395 n, m, map[m], m);396 __builtin_return_address(0), idx,
397 n, real_page_count(obj), m, max,
398 map[m], m);
396 err = -EINVAL;399 err = -EINVAL;
397 goto out_unmap;400 goto out_unmap;
398 }401 }
@@ -400,8 +403,9 @@ static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max) · 1 unmodified line
400 403
401 for (; m < DW_PER_PAGE; m++) {404 for (; m < DW_PER_PAGE; m++) {
402 if (map[m] != STACK_MAGIC) {405 if (map[m] != STACK_MAGIC) {
403 pr_err("Invalid value at page %d, offset %d: found %x expected %x\n",406 pr_err("%pS: Invalid value at object %d page %d, offset %d: found %x expected %x (uninitialised)\n",
404 n, m, map[m], STACK_MAGIC);407 __builtin_return_address(0), idx, n, m,
408 map[m], STACK_MAGIC);
405 err = -EINVAL;409 err = -EINVAL;
406 goto out_unmap;410 goto out_unmap;
407 }411 }
@@ -479,12 +483,8 @@ static unsigned long max_dwords(struct drm_i915_gem_object *obj) · 71 unmodified lines
479static int igt_ctx_exec(void *arg)483static int igt_ctx_exec(void *arg)
480{484{
481 struct drm_i915_private *i915 = arg;485 struct drm_i915_private *i915 = arg;
482 struct drm_i915_gem_object *obj = NULL;486 struct intel_engine_cs *engine;
483 unsigned long ncontexts, ndwords, dw;487 enum intel_engine_id id;
484 struct igt_live_test t;
485 struct drm_file *file;
486 IGT_TIMEOUT(end_time);
487 LIST_HEAD(objects);
488 int err = -ENODEV;488 int err = -ENODEV;
489 489
490 /*490 /*
@@ -496,44 +496,167 @@ static int igt_ctx_exec(void *arg) · 5 unmodified lines
496 if (!DRIVER_CAPS(i915)->has_logical_contexts)496 if (!DRIVER_CAPS(i915)->has_logical_contexts)
497 return 0;497 return 0;
498 498
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
578out_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
591static 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
499 file = mock_file(i915);609 file = mock_file(i915);
500 if (IS_ERR(file))610 if (IS_ERR(file))
501 return PTR_ERR(file);611 return PTR_ERR(file);
502 612
503 mutex_lock(&i915->drm.struct_mutex);613 mutex_lock(&i915->drm.struct_mutex);
504 614
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
505 err = igt_live_test_begin(&t, i915, __func__, "");626 err = igt_live_test_begin(&t, i915, __func__, "");
506 if (err)627 if (err)
507 goto out_unlock;628 goto out_unlock;
508 629
509 ncontexts = 0;630 for_each_engine(engine, i915, id) {
510 ndwords = 0;631 unsigned long ncontexts, ndwords, dw;
511 dw = 0;632 struct drm_i915_gem_object *obj = NULL;
512 while (!time_after(jiffies, end_time)) {633 IGT_TIMEOUT(end_time);
513 struct intel_engine_cs *engine;634 LIST_HEAD(objects);
514 struct i915_gem_context *ctx;
515 unsigned int id;
516 635
517 ctx = live_context(i915, file);636 if (!intel_engine_can_store_dword(engine))
518 if (IS_ERR(ctx)) {637 continue;
519 err = PTR_ERR(ctx);
520 goto out_unlock;
521 }
522 638
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;
524 intel_wakeref_t wakeref;644 intel_wakeref_t wakeref;
525 645
526 if (!engine->context_size)646 ctx = kernel_context(i915);
527 continue; /* No logical context support in HW */647 if (IS_ERR(ctx)) {
648 err = PTR_ERR(ctx);
649 goto out_test;
650 }
528 651
529 if (!intel_engine_can_store_dword(engine))652 __assign_ppgtt(ctx, parent->ppgtt);
530 continue;
531 653
532 if (!obj) {654 if (!obj) {
533 obj = create_test_object(ctx, file, &objects);655 obj = create_test_object(parent, file, &objects);
534 if (IS_ERR(obj)) {656 if (IS_ERR(obj)) {
535 err = PTR_ERR(obj);657 err = PTR_ERR(obj);
536 goto out_unlock;658 kernel_context_close(ctx);
659 goto out_test;
537 }660 }
538 }661 }
539 662
@@ -545,35 +668,39 @@ static int igt_ctx_exec(void *arg) · 5 unmodified lines
545 ndwords, dw, max_dwords(obj),668 ndwords, dw, max_dwords(obj),
546 engine->name, ctx->hw_id,669 engine->name, ctx->hw_id,
547 yesno(!!ctx->ppgtt), err);670 yesno(!!ctx->ppgtt), err);
548 goto out_unlock;671 kernel_context_close(ctx);
672 goto out_test;
549 }673 }
550 674
551 if (++dw == max_dwords(obj)) {675 if (++dw == max_dwords(obj)) {
552 obj = NULL;676 obj = NULL;
553 dw = 0;677 dw = 0;
554 }678 }
679
555 ndwords++;680 ndwords++;
681 ncontexts++;
682
683 kernel_context_close(ctx);
556 }684 }
557 ncontexts++;685 pr_info("Submitted %lu contexts to %s, filling %lu dwords\n",
558 }686 ncontexts, engine->name, ndwords);
559 pr_info("Submitted %lu contexts (across %u engines), filling %lu dwords\n",
560 ncontexts, RUNTIME_INFO(i915)->num_engines, ndwords);
561 687
562 dw = 0;688 ncontexts = dw = 0;
563 list_for_each_entry(obj, &objects, st_link) {689 list_for_each_entry(obj, &objects, st_link) {
564 unsigned int rem =690 unsigned int rem =
565 min_t(unsigned int, ndwords - dw, max_dwords(obj));691 min_t(unsigned int, ndwords - dw, max_dwords(obj));
566 692
567 err = cpu_check(obj, rem);693 err = cpu_check(obj, ncontexts++, rem);
568 if (err)694 if (err)
569 break;695 goto out_test;
570 696
571 dw += rem;697 dw += rem;
698 }
572 }699 }
573 700out_test:
574out_unlock:
575 if (igt_live_test_end(&t))701 if (igt_live_test_end(&t))
576 err = -EIO;702 err = -EIO;
703out_unlock:
577 mutex_unlock(&i915->drm.struct_mutex);704 mutex_unlock(&i915->drm.struct_mutex);
578 705
579 mock_file_free(i915, file);706 mock_file_free(i915, file);
@@ -1046,7 +1173,7 @@ static int igt_ctx_readonly(void *arg) · 466 unmodified lines
1046 struct drm_i915_gem_object *obj = NULL;1173 struct drm_i915_gem_object *obj = NULL;
1047 struct i915_gem_context *ctx;1174 struct i915_gem_context *ctx;
1048 struct i915_hw_ppgtt *ppgtt;1175 struct i915_hw_ppgtt *ppgtt;
1049 unsigned long ndwords, dw;1176 unsigned long idx, ndwords, dw;
1050 struct igt_live_test t;1177 struct igt_live_test t;
1051 struct drm_file *file;1178 struct drm_file *file;
1052 I915_RND_STATE(prng);1179 I915_RND_STATE(prng);
@@ -1127,6 +1254,7 @@ static int igt_ctx_readonly(void *arg) · 74 unmodified lines
1127 ndwords, RUNTIME_INFO(i915)->num_engines);1254 ndwords, RUNTIME_INFO(i915)->num_engines);
1128 1255
1129 dw = 0;1256 dw = 0;
1257 idx = 0;
1130 list_for_each_entry(obj, &objects, st_link) {1258 list_for_each_entry(obj, &objects, st_link) {
1131 unsigned int rem =1259 unsigned int rem =
1132 min_t(unsigned int, ndwords - dw, max_dwords(obj));1260 min_t(unsigned int, ndwords - dw, max_dwords(obj));
@@ -1136,7 +1264,7 @@ static int igt_ctx_readonly(void *arg) · 3 unmodified lines
1136 if (i915_gem_object_is_readonly(obj))1264 if (i915_gem_object_is_readonly(obj))
1137 num_writes = 0;1265 num_writes = 0;
1138 1266
1139 err = cpu_check(obj, num_writes);1267 err = cpu_check(obj, idx++, num_writes);
1140 if (err)1268 if (err)
1141 break;1269 break;
1142 1270
@@ -1619,7 +1747,8 @@ static int mock_context_barrier(void *arg) · 476 unmodified lines
1619 }1747 }
1620 1748
1621 counter = 0;1749 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);
1623 if (err) {1752 if (err) {
1624 pr_err("Failed at line %d, err=%d\n", __LINE__, err);1753 pr_err("Failed at line %d, err=%d\n", __LINE__, err);
1625 goto out;1754 goto out;
@@ -1631,8 +1760,8 @@ static int mock_context_barrier(void *arg) · 5 unmodified lines
1631 }1760 }
1632 1761
1633 counter = 0;1762 counter = 0;
1634 err = context_barrier_task(ctx,1763 err = context_barrier_task(ctx, ALL_ENGINES,
1635 ALL_ENGINES, mock_barrier_task, &counter);1764 NULL, mock_barrier_task, &counter);
1636 if (err) {1765 if (err) {
1637 pr_err("Failed at line %d, err=%d\n", __LINE__, err);1766 pr_err("Failed at line %d, err=%d\n", __LINE__, err);
1638 goto out;1767 goto out;
@@ -1655,8 +1784,8 @@ static int mock_context_barrier(void *arg) · 16 unmodified lines
1655 1784
1656 counter = 0;1785 counter = 0;
1657 context_barrier_inject_fault = BIT(RCS0);1786 context_barrier_inject_fault = BIT(RCS0);
1658 err = context_barrier_task(ctx,1787 err = context_barrier_task(ctx, ALL_ENGINES,
1659 ALL_ENGINES, mock_barrier_task, &counter);1788 NULL, mock_barrier_task, &counter);
1660 context_barrier_inject_fault = 0;1789 context_barrier_inject_fault = 0;
1661 if (err == -ENXIO)1790 if (err == -ENXIO)
1662 err = 0;1791 err = 0;
@@ -1670,8 +1799,8 @@ static int mock_context_barrier(void *arg) · 7 unmodified lines
1670 goto out;1799 goto out;
1671 1800
1672 counter = 0;1801 counter = 0;
1673 err = context_barrier_task(ctx,1802 err = context_barrier_task(ctx, ALL_ENGINES,
1674 ALL_ENGINES, mock_barrier_task, &counter);1803 NULL, mock_barrier_task, &counter);
1675 if (err) {1804 if (err) {
1676 pr_err("Failed at line %d, err=%d\n", __LINE__, err);1805 pr_err("Failed at line %d, err=%d\n", __LINE__, err);
1677 goto out;1806 goto out;
@@ -1719,6 +1848,7 @@ int i915_gem_context_live_selftests(struct drm_i915_private *dev_priv) · 41 unmodified lines
1719 SUBTEST(igt_ctx_exec),1848 SUBTEST(igt_ctx_exec),
1720 SUBTEST(igt_ctx_readonly),1849 SUBTEST(igt_ctx_readonly),
1721 SUBTEST(igt_ctx_sseu),1850 SUBTEST(igt_ctx_sseu),
1851 SUBTEST(igt_shared_ctx_exec),
1722 SUBTEST(igt_vm_isolation),1852 SUBTEST(igt_vm_isolation),
1723 };1853 };
1724 1854
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
1020 1020
1021 err = func(dev_priv, &ppgtt->vm, 0, ppgtt->vm.total, end_time);1021 err = func(dev_priv, &ppgtt->vm, 0, ppgtt->vm.total, end_time);
1022 1022
1023 i915_ppgtt_close(&ppgtt->vm);
1024 i915_ppgtt_put(ppgtt);1023 i915_ppgtt_put(ppgtt);
1025out_unlock:1024out_unlock:
1026 mutex_unlock(&dev_priv->drm.struct_mutex);1025 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
54 goto err_handles;54 goto err_handles;
55 55
56 if (name) {56 if (name) {
57 struct i915_hw_ppgtt *ppgtt;
58
57 ctx->name = kstrdup(name, GFP_KERNEL);59 ctx->name = kstrdup(name, GFP_KERNEL);
58 if (!ctx->name)60 if (!ctx->name)
59 goto err_put;61 goto err_put;
60 62
61 ctx->ppgtt = mock_ppgtt(i915, name);63 ppgtt = mock_ppgtt(i915, name);
62 if (!ctx->ppgtt)64 if (!ppgtt)
63 goto err_put;65 goto err_put;
66
67 __set_ppgtt(ctx, ppgtt);
64 }68 }
65 69
66 return ctx;70 return ctx;
include/uapi/drm/i915_drm.h+43−0
@@ -343,6 +343,8 @@ typedef struct _drm_i915_sarea { · 342 unmodified lines
343#define DRM_I915_PERF_ADD_CONFIG 0x37343#define DRM_I915_PERF_ADD_CONFIG 0x37
344#define DRM_I915_PERF_REMOVE_CONFIG 0x38344#define DRM_I915_PERF_REMOVE_CONFIG 0x38
345#define DRM_I915_QUERY 0x39345#define DRM_I915_QUERY 0x39
346#define DRM_I915_GEM_VM_CREATE 0x3a
347#define DRM_I915_GEM_VM_DESTROY 0x3b
346/* Must be kept compact -- no holes */348/* Must be kept compact -- no holes */
347 349
348#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)350#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
402#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)404#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
403#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)405#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
404#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)406#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)
405 409
406/* Allow drivers to submit batchbuffers directly to hardware, relying410/* Allow drivers to submit batchbuffers directly to hardware, relying
407 * on the security mechanisms provided by hardware.411 * on the security mechanisms provided by hardware.
@@ -1453,6 +1457,33 @@ struct drm_i915_gem_context_destroy { · 1045 unmodified lines
1453 __u32 pad;1457 __u32 pad;
1454};1458};
1455 1459
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 */
1481struct drm_i915_gem_vm_control {
1482 __u64 extensions;
1483 __u32 flags;
1484 __u32 vm_id;
1485};
1486
1456struct drm_i915_reg_read {1487struct drm_i915_reg_read {
1457 /*1488 /*
1458 * Register offset.1489 * Register offset.
@@ -1542,7 +1573,19 @@ struct drm_i915_gem_context_param { · 83 unmodified lines
1542 * On creation, all new contexts are marked as recoverable.1573 * On creation, all new contexts are marked as recoverable.
1543 */1574 */
1544#define I915_CONTEXT_PARAM_RECOVERABLE 0x81575#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
1545/* Must be kept compact -- no holes and well documented */1587/* Must be kept compact -- no holes and well documented */
1588
1546 __u64 value;1589 __u64 value;
1547};1590};
1548 1591