@@ -13,6 +13,7 @@
#include "i915_drv.h"
#include "i915_gem_gtt.h"
#include "i915_gem_ioctls.h"
+#include "i915_gem_lmem.h"
#include "i915_gem_object.h"
#include "i915_trace.h"
#include "i915_vma.h"
@@ -235,6 +236,15 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
if (i915_gem_object_is_readonly(obj) && write)
return VM_FAULT_SIGBUS;
+ /* Implicitly migrate BO to SMEM if it is SVM mapped */
+ if (i915_gem_object_svm_mapped(obj) && i915_gem_object_is_lmem(obj)) {
+ u32 regions[] = { REGION_MAP(INTEL_MEMORY_SYSTEM, 0) };
+
+ ret = i915_gem_object_migrate_region(obj, regions, 1);
+ if (ret)
+ goto err;
+ }
+
/* We don't use vmf->pgoff since that has the fake offset */
page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT;
@@ -493,12 +493,17 @@ __region_id(u32 region)
return INTEL_REGION_UNKNOWN;
}
+bool
+i915_gem_object_svm_mapped(struct drm_i915_gem_object *obj)
+{
+ return false;
+}
+
static int i915_gem_object_region_select(struct drm_i915_private *dev_priv,
struct drm_i915_gem_object_param *args,
struct drm_file *file,
struct drm_i915_gem_object *obj)
{
- struct intel_context *ce = dev_priv->engine[BCS0]->kernel_context;
u32 __user *uregions = u64_to_user_ptr(args->data);
u32 uregions_copy[INTEL_REGION_UNKNOWN];
int i, ret;
@@ -518,16 +523,28 @@ static int i915_gem_object_region_select(struct drm_i915_private *dev_priv,
++uregions;
}
+ ret = i915_gem_object_migrate_region(obj, uregions_copy,
+ args->size);
+
+ return ret;
+}
+
+int i915_gem_object_migrate_region(struct drm_i915_gem_object *obj,
+ u32 *regions, int size)
+{
+ struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+ struct intel_context *ce = dev_priv->engine[BCS0]->kernel_context;
+ int i, ret;
+
mutex_lock(&dev_priv->drm.struct_mutex);
ret = i915_gem_object_prepare_move(obj);
if (ret) {
DRM_ERROR("Cannot set memory region, object in use\n");
- goto err;
+ goto err;
}
- for (i = 0; i < args->size; i++) {
- u32 region = uregions_copy[i];
- enum intel_region_id id = __region_id(region);
+ for (i = 0; i < size; i++) {
+ enum intel_region_id id = __region_id(regions[i]);
if (id == INTEL_REGION_UNKNOWN) {
ret = -EINVAL;
@@ -537,7 +554,7 @@ static int i915_gem_object_region_select(struct drm_i915_private *dev_priv,
ret = i915_gem_object_migrate(obj, ce, id);
if (!ret) {
if (!i915_gem_object_has_pages(obj) &&
- MEMORY_TYPE_FROM_REGION(region) ==
+ MEMORY_TYPE_FROM_REGION(regions[i]) ==
INTEL_MEMORY_LOCAL) {
/*
* TODO: this should be part of get_pages(),
@@ -47,6 +47,9 @@ int i915_gem_object_prepare_move(struct drm_i915_gem_object *obj);
int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
struct intel_context *ce,
enum intel_region_id id);
+bool i915_gem_object_svm_mapped(struct drm_i915_gem_object *obj);
+int i915_gem_object_migrate_region(struct drm_i915_gem_object *obj,
+ u32 *uregions, int size);
void i915_gem_flush_free_objects(struct drm_i915_private *i915);
@@ -6,10 +6,6 @@
#include "intel_memory_region.h"
#include "i915_drv.h"
-/* XXX: Hysterical raisins. BIT(inst) needs to just be (inst) at some point. */
-#define REGION_MAP(type, inst) \
- BIT((type) + INTEL_MEMORY_TYPE_SHIFT) | BIT(inst)
-
const u32 intel_region_map[] = {
[INTEL_REGION_SMEM] = REGION_MAP(INTEL_MEMORY_SYSTEM, 0),
[INTEL_REGION_LMEM] = REGION_MAP(INTEL_MEMORY_LOCAL, 0),
@@ -41,6 +41,10 @@ enum intel_region_id {
#define INTEL_MEMORY_TYPE_SHIFT 16
+/* XXX: Hysterical raisins. BIT(inst) needs to just be (inst) at some point. */
+#define REGION_MAP(type, inst) \
+ (BIT((type) + INTEL_MEMORY_TYPE_SHIFT) | BIT(inst))
+
#define MEMORY_TYPE_FROM_REGION(r) (ilog2((r) >> INTEL_MEMORY_TYPE_SHIFT))
#define MEMORY_INSTANCE_FROM_REGION(r) (ilog2((r) & 0xffff))