From: Jesse Barnes <jbar...@virtuousgeek.org>

Use David's new IOMMU layer functions for supporting SVM in i915.

TODO:
  error record collection for failing SVM contexts
  callback handling for fatal faults
  scheduling

v2: integrate David's core IOMMU support
    make sure we don't clobber the PASID in the context reg state
v3: fixup for intel-svm.h changes (David)
v4: use fault & halt for now (Jesse)
    fix ring free in error path on context alloc (Julia)
v5: update with new callback struct (Jesse)
v6: fix init svm check per new IOMMU code (Jesse)
v7: drop debug code and obsolete i915_svm.c file (Jesse)
v8: fix !CONFIG_INTEL_IOMMU_SVM init stub (Jesse)
v9: update to new execlist and reg handling bits (Jesse)
    context teardown fix (lrc deferred alloc vs teardown race?) (Jesse)
    check for SVM availability at context create (Jesse)
v10: intel_context_svm_init/fini & rebase
v11: move context specific stuff to i915_gem_context
v12: move addressing to context descriptor
v13: strip out workqueue and mm notifiers
v14: remove fault cb
v15: streamline execlist context pdps update, add asserts
v16: introduce HAS_SVM

Cc: Daniel Vetter <daniel.vet...@ffwll.ch>
Cc: Chris Wilson <ch...@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahti...@linux.intel.com>
Cc: David Woodhouse <dw...@infradead.org>
Signed-off-by: David Woodhouse <david.woodho...@intel.com> (v3)
Signed-off-by: Jesse Barnes <jbar...@virtuousgeek.org> (v9)
Signed-off-by: Mika Kuoppala <mika.kuopp...@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h          |  3 ++
 drivers/gpu/drm/i915/i915_gem_context.c  | 78 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_context.h  | 30 ++++++++++++
 drivers/gpu/drm/i915/i915_reg.h          |  1 +
 drivers/gpu/drm/i915/intel_device_info.c |  6 +++
 drivers/gpu/drm/i915/intel_lrc.c         | 11 ++++-
 include/uapi/drm/i915_drm.h              |  1 +
 7 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 52d01be..ca1eaaf 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -39,6 +39,7 @@
 #include <linux/backlight.h>
 #include <linux/hashtable.h>
 #include <linux/intel-iommu.h>
+#include <linux/intel-svm.h>
 #include <linux/kref.h>
 #include <linux/pm_qos.h>
 #include <linux/reservation.h>
@@ -787,6 +788,7 @@ struct intel_csr {
        func(has_fpga_dbg); \
        func(has_full_ppgtt); \
        func(has_full_48bit_ppgtt); \
+       func(has_svm); \
        func(has_gmbus_irq); \
        func(has_gmch_display); \
        func(has_guc); \
@@ -2784,6 +2786,7 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define USES_PPGTT(dev_priv)           (i915.enable_ppgtt)
 #define USES_FULL_PPGTT(dev_priv)      (i915.enable_ppgtt >= 2)
 #define USES_FULL_48BIT_PPGTT(dev_priv)        (i915.enable_ppgtt == 3)
+#define HAS_SVM(dev_priv)              ((dev_priv)->info.has_svm)
 
 #define HAS_OVERLAY(dev_priv)           ((dev_priv)->info.has_overlay)
 #define OVERLAY_NEEDS_PHYSICAL(dev_priv) \
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c 
b/drivers/gpu/drm/i915/i915_gem_context.c
index dadc845..c0f6c9e 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -134,6 +134,16 @@ static int get_context_size(struct drm_i915_private 
*dev_priv)
        return ret;
 }
 
+static void i915_gem_context_svm_fini(struct i915_gem_context *ctx)
+{
+       struct device *dev = &ctx->i915->drm.pdev->dev;
+
+       GEM_BUG_ON(!ctx->task);
+
+       intel_svm_unbind_mm(dev, ctx->pasid);
+       put_task_struct(ctx->task);
+}
+
 void i915_gem_context_free(struct kref *ctx_ref)
 {
        struct i915_gem_context *ctx = container_of(ctx_ref, typeof(*ctx), ref);
@@ -143,6 +153,9 @@ void i915_gem_context_free(struct kref *ctx_ref)
        trace_i915_context_free(ctx);
        GEM_BUG_ON(!i915_gem_context_is_closed(ctx));
 
+       if (i915_gem_context_is_svm(ctx))
+               i915_gem_context_svm_fini(ctx);
+
        i915_ppgtt_put(ctx->ppgtt);
 
        for (i = 0; i < I915_NUM_ENGINES; i++) {
@@ -272,6 +285,61 @@ static u32 create_default_ctx_desc(const struct 
drm_i915_private *dev_priv)
        return desc;
 }
 
+static u32 create_svm_ctx_desc(void)
+{
+       /*
+        * Switch to stream once we have a scheduler and can
+        * re-submit contexts.
+        */
+       return GEN8_CTX_VALID |
+               INTEL_ADVANCED_CONTEXT << GEN8_CTX_ADDRESSING_MODE_SHIFT |
+               FAULT_AND_HALT << GEN8_CTX_FAULT_SHIFT;
+}
+
+static int i915_gem_context_svm_init(struct i915_gem_context *ctx)
+{
+       struct device *dev = &ctx->i915->drm.pdev->dev;
+       int ret;
+
+       GEM_BUG_ON(ctx->task);
+
+       if (!HAS_SVM(ctx->i915))
+               return -ENODEV;
+
+       get_task_struct(current);
+
+       ret = intel_svm_bind_mm(dev, &ctx->pasid, 0, NULL);
+       if (ret) {
+               DRM_DEBUG_DRIVER("pasid alloc fail: %d\n", ret);
+               put_task_struct(current);
+               return ret;
+       }
+
+       ctx->task = current;
+       i915_gem_context_set_svm(ctx);
+
+       return 0;
+}
+
+static int i915_gem_context_enable_svm(struct i915_gem_context *ctx)
+{
+       int ret;
+
+       if (!HAS_SVM(ctx->i915))
+               return -ENODEV;
+
+       if (i915_gem_context_is_svm(ctx))
+               return -EINVAL;
+
+       ret = i915_gem_context_svm_init(ctx);
+       if (ret)
+               return ret;
+
+       ctx->desc_template = create_svm_ctx_desc();
+
+       return 0;
+}
+
 static struct i915_gem_context *
 __create_hw_context(struct drm_i915_private *dev_priv,
                    struct drm_i915_file_private *file_priv)
@@ -1071,6 +1139,9 @@ int i915_gem_context_getparam_ioctl(struct drm_device 
*dev, void *data,
        case I915_CONTEXT_PARAM_BANNABLE:
                args->value = i915_gem_context_is_bannable(ctx);
                break;
+       case I915_CONTEXT_PARAM_SVM:
+               args->value = i915_gem_context_is_svm(ctx);
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -1128,6 +1199,13 @@ int i915_gem_context_setparam_ioctl(struct drm_device 
*dev, void *data,
                else
                        i915_gem_context_clear_bannable(ctx);
                break;
+       case I915_CONTEXT_PARAM_SVM:
+               /* There is no coming back once svm is enabled */
+               if (args->value && !args->size)
+                       ret = i915_gem_context_enable_svm(ctx);
+               else
+                       ret = -EINVAL;
+               break;
        default:
                ret = -EINVAL;
                break;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.h 
b/drivers/gpu/drm/i915/i915_gem_context.h
index 0ac750b..2514abb 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/i915_gem_context.h
@@ -108,6 +108,7 @@ struct i915_gem_context {
 #define CONTEXT_BANNABLE               3
 #define CONTEXT_BANNED                 4
 #define CONTEXT_FORCE_SINGLE_SUBMISSION        5
+#define CONTEXT_SVM                    6
 
        /**
         * @hw_id: - unique identifier for the context
@@ -140,6 +141,25 @@ struct i915_gem_context {
         */
        int priority;
 
+       /**
+        * @pasid: process address space identifier
+        *
+        * Unique identifier for the shared address space with cpu.
+        * Used by the gpu to associate context's (ppgtt) address
+        * space with the corresponding process's address space for
+        * Shared Virtual Memory (SVM). 20 bits.
+        */
+       u32 pasid;
+
+       /**
+        * @task: user space task struct for this context
+        *
+        * If this is svm context, @task is the corresponding
+        * user space process with which we share the vm. See
+        * @pasid.
+        */
+       struct task_struct *task;
+
        /** ggtt_alignment: alignment restriction for context objects */
        u32 ggtt_alignment;
        /** ggtt_offset_bias: placement restriction for context objects */
@@ -241,6 +261,16 @@ static inline void 
i915_gem_context_set_force_single_submission(struct i915_gem_
        __set_bit(CONTEXT_FORCE_SINGLE_SUBMISSION, &ctx->flags);
 }
 
+static inline bool i915_gem_context_is_svm(const struct i915_gem_context *ctx)
+{
+       return test_bit(CONTEXT_SVM, &ctx->flags);
+}
+
+static inline void i915_gem_context_set_svm(struct i915_gem_context *ctx)
+{
+       __set_bit(CONTEXT_SVM, &ctx->flags);
+}
+
 static inline bool i915_gem_context_is_default(const struct i915_gem_context 
*c)
 {
        return c->user_handle == DEFAULT_CONTEXT_HANDLE;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 36f4146..eff0eef 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3375,6 +3375,7 @@ enum {
                                INTEL_LEGACY_64B_CONTEXT : \
                                INTEL_LEGACY_32B_CONTEXT)
 
+#define GEN8_CTX_FAULT_SHIFT 6
 #define GEN8_CTX_ID_SHIFT 32
 #define GEN8_CTX_ID_WIDTH 21
 
diff --git a/drivers/gpu/drm/i915/intel_device_info.c 
b/drivers/gpu/drm/i915/intel_device_info.c
index f642f6d..2878bd3 100644
--- a/drivers/gpu/drm/i915/intel_device_info.c
+++ b/drivers/gpu/drm/i915/intel_device_info.c
@@ -414,6 +414,10 @@ void intel_device_info_runtime_init(struct 
drm_i915_private *dev_priv)
        if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
                info->has_snoop = false;
 
+       info->has_svm = INTEL_GEN(dev_priv) >= 9 &&
+               info->has_full_48bit_ppgtt &&
+               intel_svm_available(&dev_priv->drm.pdev->dev);
+
        DRM_DEBUG_DRIVER("slice mask: %04x\n", info->sseu.slice_mask);
        DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask));
        DRM_DEBUG_DRIVER("subslice total: %u\n",
@@ -429,4 +433,6 @@ void intel_device_info_runtime_init(struct drm_i915_private 
*dev_priv)
                         info->sseu.has_subslice_pg ? "y" : "n");
        DRM_DEBUG_DRIVER("has EU power gating: %s\n",
                         info->sseu.has_eu_pg ? "y" : "n");
+       DRM_DEBUG_DRIVER("has svm: %s\n",
+                        info->has_svm ? "y" : "n");
 }
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 06322a5..13c9c56 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -209,6 +209,13 @@
 #define GEN8_CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT       0x17
 #define GEN9_CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT       0x26
 
+#define ASSIGN_CTX_SVM(reg_state, ctx, engine) do { \
+               ASSIGN_CTX_REG(reg_state, CTX_PDP0_UDW, \
+                              GEN8_RING_PDP_UDW((engine), 0), 0); \
+               ASSIGN_CTX_REG(reg_state, CTX_PDP0_LDW, \
+                              GEN8_RING_PDP_LDW((engine), 0), (ctx)->pasid); \
+} while (0)
+
 /* Typical size of the average request (2 pipecontrols and a MI_BB) */
 #define EXECLISTS_REQUEST_SIZE 64 /* bytes */
 
@@ -2084,7 +2091,9 @@ static void execlists_init_reg_state(u32 *reg_state,
        ASSIGN_CTX_REG(reg_state, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(engine, 0),
                       0);
 
-       if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
+       if (i915_gem_context_is_svm(ctx)) {
+               ASSIGN_CTX_SVM(reg_state, ctx, engine);
+       } else if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
                /* 64b PPGTT (48bit canonical)
                 * PDP0_DESCRIPTOR contains the base address to PML4 and
                 * other PDP Descriptors are ignored.
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index da32c2f..5b06ab1 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1227,6 +1227,7 @@ struct drm_i915_gem_context_param {
 #define I915_CONTEXT_PARAM_GTT_SIZE    0x3
 #define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE    0x4
 #define I915_CONTEXT_PARAM_BANNABLE    0x5
+#define I915_CONTEXT_PARAM_SVM         0x6
        __u64 value;
 };
 
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to