@@ -77,6 +77,7 @@
#include "i915_gem_context.h"
#include "i915_globals.h"
+#include "i915_svm.h"
#include "i915_trace.h"
#include "i915_user_extensions.h"
#include "i915_gem_ioctls.h"
@@ -961,6 +962,78 @@ int i915_gem_vm_destroy_ioctl(struct drm_device *dev, void *data,
return 0;
}
+static int i915_gem_vm_setparam_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_i915_file_private *file_priv = file->driver_priv;
+ struct drm_i915_gem_vm_param *args = data;
+ struct i915_address_space *vm;
+ int err = 0;
+ u32 id;
+
+ id = args->vm_id;
+ if (!id)
+ return -ENOENT;
+
+ err = mutex_lock_interruptible(&file_priv->vm_idr_lock);
+ if (err)
+ return err;
+
+ vm = idr_find(&file_priv->vm_idr, id);
+
+ mutex_unlock(&file_priv->vm_idr_lock);
+ if (!vm)
+ return -ENOENT;
+
+ switch (lower_32_bits(args->param)) {
+ case I915_GEM_VM_PARAM_SVM:
+ /* FIXME: Ensure ppgtt is empty before switching */
+ if (!i915_has_svm(file_priv->dev_priv))
+ err = -ENOTSUPP;
+ else if (args->value)
+ err = i915_svm_bind_mm(vm);
+ else
+ i915_svm_unbind_mm(vm);
+ break;
+ default:
+ err = -EINVAL;
+ }
+ return err;
+}
+
+static int i915_gem_vm_getparam_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_i915_file_private *file_priv = file->driver_priv;
+ struct drm_i915_gem_vm_param *args = data;
+ struct i915_address_space *vm;
+ int err = 0;
+ u32 id;
+
+ id = args->vm_id;
+ if (!id)
+ return -ENOENT;
+
+ err = mutex_lock_interruptible(&file_priv->vm_idr_lock);
+ if (err)
+ return err;
+
+ vm = idr_find(&file_priv->vm_idr, id);
+
+ mutex_unlock(&file_priv->vm_idr_lock);
+ if (!vm)
+ return -ENOENT;
+
+ switch (lower_32_bits(args->param)) {
+ case I915_GEM_VM_PARAM_SVM:
+ args->value = i915_vm_is_svm_enabled(vm);
+ break;
+ default:
+ err = -EINVAL;
+ }
+ return err;
+}
+
struct context_barrier_task {
struct i915_active base;
void (*task)(void *data);
@@ -2382,6 +2455,21 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
return ret;
}
+int i915_gem_getparam_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_i915_gem_context_param *args = data;
+ u32 class = upper_32_bits(args->param);
+
+ switch (class) {
+ case 0:
+ return i915_gem_context_getparam_ioctl(dev, data, file);
+ case 2:
+ return i915_gem_vm_getparam_ioctl(dev, data, file);
+ }
+ return -EINVAL;
+}
+
int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
@@ -2404,14 +2492,15 @@ int i915_gem_setparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_i915_gem_context_param *args = data;
- u32 object_class = upper_32_bits(args->param);
+ u32 class = upper_32_bits(args->param);
- switch (object_class) {
+ switch (class) {
case 0:
return i915_gem_context_setparam_ioctl(dev, data, file);
case 1:
return i915_gem_object_setparam_ioctl(dev, data, file);
-
+ case 2:
+ return i915_gem_vm_setparam_ioctl(dev, data, file);
}
return -EINVAL;
}
@@ -175,6 +175,8 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+int i915_gem_getparam_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file);
int i915_gem_setparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data,
@@ -129,6 +129,7 @@ struct i915_gem_context {
#define UCONTEXT_BANNABLE 2
#define UCONTEXT_RECOVERABLE 3
#define UCONTEXT_PERSISTENCE 4
+#define UCONTEXT_SVM_ENABLED 5
/**
* @flags: small set of booleans
@@ -25,6 +25,7 @@
#include "i915_gem_clflush.h"
#include "i915_gem_context.h"
#include "i915_gem_ioctls.h"
+#include "i915_svm.h"
#include "i915_trace.h"
enum {
@@ -443,6 +444,11 @@ eb_validate_vma(struct i915_execbuffer *eb,
if (unlikely(entry->alignment && !is_power_of_2(entry->alignment)))
return -EINVAL;
+ /* Only allow user PINNED addresses for SVM enabled contexts */
+ if (unlikely(i915_vm_is_svm_enabled(eb->gem_context->vm) &&
+ !(entry->flags & EXEC_OBJECT_PINNED)))
+ return -EINVAL;
+
/*
* Offset can be used as input (EXEC_OBJECT_PINNED), reject
* any non-page-aligned or non-canonical addresses.
@@ -36,6 +36,7 @@
#include "i915_gem_object_blt.h"
#include "i915_gem_region.h"
#include "i915_globals.h"
+#include "i915_svm.h"
#include "i915_trace.h"
static struct i915_global_object {
@@ -507,6 +508,16 @@ int __init i915_global_objects_init(void)
bool
i915_gem_object_svm_mapped(struct drm_i915_gem_object *obj)
{
+ struct i915_vma *vma;
+
+ spin_lock(&obj->vma.lock);
+ list_for_each_entry(vma, &obj->vma.list, obj_link)
+ if (i915_vm_is_svm_enabled(vma->vm)) {
+ spin_unlock(&obj->vma.lock);
+ return true;
+ }
+
+ spin_unlock(&obj->vma.lock);
return false;
}
@@ -2692,6 +2692,8 @@ static int i915_gem_vm_bind_ioctl(struct drm_device *dev, void *data,
vm = i915_gem_address_space_lookup(file->driver_priv, args->vm_id);
if (unlikely(!vm))
return -ENOENT;
+ if (unlikely(!i915_vm_is_svm_enabled(vm)))
+ return -ENOTSUPP;
switch (args->type) {
case I915_GEM_VM_BIND_SVM_OBJ:
@@ -2756,7 +2758,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_gem_context_reset_stats_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_getparam_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_setparam_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_PERF_OPEN, i915_perf_open_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_PERF_ADD_CONFIG, i915_perf_add_config_ioctl, DRM_RENDER_ALLOW),
@@ -38,6 +38,7 @@
#include <linux/i2c-algo-bit.h>
#include <linux/backlight.h>
#include <linux/hash.h>
+#include <linux/hmm.h>
#include <linux/intel-iommu.h>
#include <linux/kref.h>
#include <linux/mm_types.h>
@@ -1736,6 +1737,15 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
/* Only valid when HAS_DISPLAY() is true */
#define INTEL_DISPLAY_ENABLED(dev_priv) (WARN_ON(!HAS_DISPLAY(dev_priv)), !i915_modparams.disable_display)
+static inline bool i915_has_svm(struct drm_i915_private *dev_priv)
+{
+#ifdef CONFIG_DRM_I915_SVM
+ return INTEL_GEN(dev_priv) >= 8;
+#else
+ return false;
+#endif
+}
+
static inline bool intel_vtd_active(void)
{
#ifdef CONFIG_INTEL_IOMMU
@@ -161,6 +161,9 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
case I915_PARAM_PERF_REVISION:
value = i915_perf_ioctl_version();
break;
+ case I915_PARAM_HAS_SVM:
+ value = i915_has_svm(i915);
+ break;
default:
DRM_DEBUG("Unknown parameter %d\n", param->param);
return -EINVAL;
@@ -360,6 +360,8 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_GEM_VM_CREATE 0x3a
#define DRM_I915_GEM_VM_DESTROY 0x3b
#define DRM_I915_GEM_OBJECT_SETPARAM DRM_I915_GEM_CONTEXT_SETPARAM
+#define DRM_I915_GEM_VM_GETPARAM DRM_I915_GEM_CONTEXT_GETPARAM
+#define DRM_I915_GEM_VM_SETPARAM DRM_I915_GEM_CONTEXT_SETPARAM
#define DRM_I915_GEM_VM_BIND 0x3c
#define DRM_I915_GEM_VM_PREFETCH 0x3d
/* Must be kept compact -- no holes */
@@ -426,6 +428,8 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_VM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_CREATE, struct drm_i915_gem_vm_control)
#define DRM_IOCTL_I915_GEM_VM_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_VM_DESTROY, struct drm_i915_gem_vm_control)
#define DRM_IOCTL_I915_GEM_OBJECT_SETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_OBJECT_SETPARAM, struct drm_i915_gem_object_param)
+#define DRM_IOCTL_I915_GEM_VM_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_GETPARAM, struct drm_i915_gem_vm_param)
+#define DRM_IOCTL_I915_GEM_VM_SETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_SETPARAM, struct drm_i915_gem_vm_param)
#define DRM_IOCTL_I915_GEM_VM_BIND DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_BIND, struct drm_i915_gem_vm_bind)
#define DRM_IOCTL_I915_GEM_VM_PREFETCH DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_PREFETCH, struct drm_i915_gem_vm_prefetch)
@@ -625,6 +629,8 @@ typedef struct drm_i915_irq_wait {
*/
#define I915_PARAM_PERF_REVISION 54
+/* Shared Virtual Memory (SVM) support capability */
+#define I915_PARAM_HAS_SVM 55
/* Must be kept compact -- no holes and well documented */
typedef struct drm_i915_getparam {
@@ -1851,6 +1857,17 @@ struct drm_i915_gem_vm_control {
__u32 vm_id;
};
+struct drm_i915_gem_vm_param {
+ __u32 vm_id;
+ __u32 rsvd;
+
+#define I915_VM_PARAM (2ull << 32)
+#define I915_GEM_VM_PARAM_SVM 0x1
+ __u64 param;
+
+ __u64 value;
+};
+
struct drm_i915_reg_read {
/*
* Register offset.