diff options
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 92 |
1 files changed, 47 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c60ca32f65d2..dea9ac069851 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -3128,6 +3128,21 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
| 3128 | } | 3128 | } |
| 3129 | target_obj_priv = target_obj->driver_private; | 3129 | target_obj_priv = target_obj->driver_private; |
| 3130 | 3130 | ||
| 3131 | #if WATCH_RELOC | ||
| 3132 | DRM_INFO("%s: obj %p offset %08x target %d " | ||
| 3133 | "read %08x write %08x gtt %08x " | ||
| 3134 | "presumed %08x delta %08x\n", | ||
| 3135 | __func__, | ||
| 3136 | obj, | ||
| 3137 | (int) reloc->offset, | ||
| 3138 | (int) reloc->target_handle, | ||
| 3139 | (int) reloc->read_domains, | ||
| 3140 | (int) reloc->write_domain, | ||
| 3141 | (int) target_obj_priv->gtt_offset, | ||
| 3142 | (int) reloc->presumed_offset, | ||
| 3143 | reloc->delta); | ||
| 3144 | #endif | ||
| 3145 | |||
| 3131 | /* The target buffer should have appeared before us in the | 3146 | /* The target buffer should have appeared before us in the |
| 3132 | * exec_object list, so it should have a GTT space bound by now. | 3147 | * exec_object list, so it should have a GTT space bound by now. |
| 3133 | */ | 3148 | */ |
| @@ -3139,35 +3154,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
| 3139 | return -EINVAL; | 3154 | return -EINVAL; |
| 3140 | } | 3155 | } |
| 3141 | 3156 | ||
| 3142 | if (reloc->offset > obj->size - 4) { | 3157 | /* Validate that the target is in a valid r/w GPU domain */ |
| 3143 | DRM_ERROR("Relocation beyond object bounds: " | ||
| 3144 | "obj %p target %d offset %d size %d.\n", | ||
| 3145 | obj, reloc->target_handle, | ||
| 3146 | (int) reloc->offset, (int) obj->size); | ||
| 3147 | drm_gem_object_unreference(target_obj); | ||
| 3148 | i915_gem_object_unpin(obj); | ||
| 3149 | return -EINVAL; | ||
| 3150 | } | ||
| 3151 | if (reloc->offset & 3) { | ||
| 3152 | DRM_ERROR("Relocation not 4-byte aligned: " | ||
| 3153 | "obj %p target %d offset %d.\n", | ||
| 3154 | obj, reloc->target_handle, | ||
| 3155 | (int) reloc->offset); | ||
| 3156 | drm_gem_object_unreference(target_obj); | ||
| 3157 | i915_gem_object_unpin(obj); | ||
| 3158 | return -EINVAL; | ||
| 3159 | } | ||
| 3160 | |||
| 3161 | if (reloc->delta >= target_obj->size) { | ||
| 3162 | DRM_ERROR("Relocation beyond target object bounds: " | ||
| 3163 | "obj %p target %d delta %d size %d.\n", | ||
| 3164 | obj, reloc->target_handle, | ||
| 3165 | (int) reloc->delta, (int) target_obj->size); | ||
| 3166 | drm_gem_object_unreference(target_obj); | ||
| 3167 | i915_gem_object_unpin(obj); | ||
| 3168 | return -EINVAL; | ||
| 3169 | } | ||
| 3170 | |||
| 3171 | if (reloc->write_domain & I915_GEM_DOMAIN_CPU || | 3158 | if (reloc->write_domain & I915_GEM_DOMAIN_CPU || |
| 3172 | reloc->read_domains & I915_GEM_DOMAIN_CPU) { | 3159 | reloc->read_domains & I915_GEM_DOMAIN_CPU) { |
| 3173 | DRM_ERROR("reloc with read/write CPU domains: " | 3160 | DRM_ERROR("reloc with read/write CPU domains: " |
| @@ -3181,7 +3168,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
| 3181 | i915_gem_object_unpin(obj); | 3168 | i915_gem_object_unpin(obj); |
| 3182 | return -EINVAL; | 3169 | return -EINVAL; |
| 3183 | } | 3170 | } |
| 3184 | |||
| 3185 | if (reloc->write_domain && target_obj->pending_write_domain && | 3171 | if (reloc->write_domain && target_obj->pending_write_domain && |
| 3186 | reloc->write_domain != target_obj->pending_write_domain) { | 3172 | reloc->write_domain != target_obj->pending_write_domain) { |
| 3187 | DRM_ERROR("Write domain conflict: " | 3173 | DRM_ERROR("Write domain conflict: " |
| @@ -3196,21 +3182,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
| 3196 | return -EINVAL; | 3182 | return -EINVAL; |
| 3197 | } | 3183 | } |
| 3198 | 3184 | ||
| 3199 | #if WATCH_RELOC | ||
| 3200 | DRM_INFO("%s: obj %p offset %08x target %d " | ||
| 3201 | "read %08x write %08x gtt %08x " | ||
| 3202 | "presumed %08x delta %08x\n", | ||
| 3203 | __func__, | ||
| 3204 | obj, | ||
| 3205 | (int) reloc->offset, | ||
| 3206 | (int) reloc->target_handle, | ||
| 3207 | (int) reloc->read_domains, | ||
| 3208 | (int) reloc->write_domain, | ||
| 3209 | (int) target_obj_priv->gtt_offset, | ||
| 3210 | (int) reloc->presumed_offset, | ||
| 3211 | reloc->delta); | ||
| 3212 | #endif | ||
| 3213 | |||
| 3214 | target_obj->pending_read_domains |= reloc->read_domains; | 3185 | target_obj->pending_read_domains |= reloc->read_domains; |
| 3215 | target_obj->pending_write_domain |= reloc->write_domain; | 3186 | target_obj->pending_write_domain |= reloc->write_domain; |
| 3216 | 3187 | ||
| @@ -3222,6 +3193,37 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
| 3222 | continue; | 3193 | continue; |
| 3223 | } | 3194 | } |
| 3224 | 3195 | ||
| 3196 | /* Check that the relocation address is valid... */ | ||
| 3197 | if (reloc->offset > obj->size - 4) { | ||
| 3198 | DRM_ERROR("Relocation beyond object bounds: " | ||
| 3199 | "obj %p target %d offset %d size %d.\n", | ||
| 3200 | obj, reloc->target_handle, | ||
| 3201 | (int) reloc->offset, (int) obj->size); | ||
| 3202 | drm_gem_object_unreference(target_obj); | ||
| 3203 | i915_gem_object_unpin(obj); | ||
| 3204 | return -EINVAL; | ||
| 3205 | } | ||
| 3206 | if (reloc->offset & 3) { | ||
| 3207 | DRM_ERROR("Relocation not 4-byte aligned: " | ||
| 3208 | "obj %p target %d offset %d.\n", | ||
| 3209 | obj, reloc->target_handle, | ||
| 3210 | (int) reloc->offset); | ||
| 3211 | drm_gem_object_unreference(target_obj); | ||
| 3212 | i915_gem_object_unpin(obj); | ||
| 3213 | return -EINVAL; | ||
| 3214 | } | ||
| 3215 | |||
| 3216 | /* and points to somewhere within the target object. */ | ||
| 3217 | if (reloc->delta >= target_obj->size) { | ||
| 3218 | DRM_ERROR("Relocation beyond target object bounds: " | ||
| 3219 | "obj %p target %d delta %d size %d.\n", | ||
| 3220 | obj, reloc->target_handle, | ||
| 3221 | (int) reloc->delta, (int) target_obj->size); | ||
| 3222 | drm_gem_object_unreference(target_obj); | ||
| 3223 | i915_gem_object_unpin(obj); | ||
| 3224 | return -EINVAL; | ||
| 3225 | } | ||
| 3226 | |||
| 3225 | ret = i915_gem_object_set_to_gtt_domain(obj, 1); | 3227 | ret = i915_gem_object_set_to_gtt_domain(obj, 1); |
| 3226 | if (ret != 0) { | 3228 | if (ret != 0) { |
| 3227 | drm_gem_object_unreference(target_obj); | 3229 | drm_gem_object_unreference(target_obj); |
