Skip to content

Commit fe14d5f

Browse files
tursulindanvet
authored andcommitted
drm/i915: Infrastructure for supporting different GGTT views per object
Things like reliable GGTT mappings and mirrored 2d-on-3d display will need to map objects into the same address space multiple times. Added a GGTT view concept and linked it with the VMA to distinguish between multiple instances per address space. New objects and GEM functions which do not take this new view as a parameter assume the default of zero (I915_GGTT_VIEW_NORMAL) which preserves the previous behaviour. This now means that objects can have multiple VMA entries so the code which assumed there will only be one also had to be modified. Alternative GGTT views are supposed to borrow DMA addresses from obj->pages which is DMA mapped on first VMA instantiation and unmapped on the last one going away. v2: * Removed per view special casing in i915_gem_ggtt_prepare / finish_object in favour of creating and destroying DMA mappings on first VMA instantiation and last VMA destruction. (Daniel Vetter) * Simplified i915_vma_unbind which does not need to count the GGTT views. (Daniel Vetter) * Also moved obj->map_and_fenceable reset under the same check. * Checkpatch cleanups. v3: * Only retire objects once the last VMA is unbound. v4: * Keep scatter-gather table for alternative views persistent for the lifetime of the VMA. * Propagate binding errors to callers and handle appropriately. v5: * Explicitly look for normal GGTT view in i915_gem_obj_bound to align usage in i915_gem_object_ggtt_unpin. (Michel Thierry) * Change to single if statement in i915_gem_obj_to_ggtt. (Michel Thierry) * Removed stray semi-colon in i915_gem_object_set_cache_level. For: VIZ-4544 Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Michel Thierry <michel.thierry@intel.com> [danvet: Drop hunk from i915_gem_shrink since it's just prettification but upsets a __must_check warning.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
1 parent db5ff4a commit fe14d5f

File tree

8 files changed

+220
-70
lines changed

8 files changed

+220
-70
lines changed

drivers/gpu/drm/i915/i915_debugfs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,9 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
152152
seq_puts(m, " (pp");
153153
else
154154
seq_puts(m, " (g");
155-
seq_printf(m, "gtt offset: %08lx, size: %08lx)",
156-
vma->node.start, vma->node.size);
155+
seq_printf(m, "gtt offset: %08lx, size: %08lx, type: %u)",
156+
vma->node.start, vma->node.size,
157+
vma->ggtt_view.type);
157158
}
158159
if (obj->stolen)
159160
seq_printf(m, " (stolen: %08lx)", obj->stolen->start);

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,10 +2530,23 @@ void i915_gem_vma_destroy(struct i915_vma *vma);
25302530
#define PIN_GLOBAL 0x4
25312531
#define PIN_OFFSET_BIAS 0x8
25322532
#define PIN_OFFSET_MASK (~4095)
2533+
int __must_check i915_gem_object_pin_view(struct drm_i915_gem_object *obj,
2534+
struct i915_address_space *vm,
2535+
uint32_t alignment,
2536+
uint64_t flags,
2537+
const struct i915_ggtt_view *view);
2538+
static inline
25332539
int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
25342540
struct i915_address_space *vm,
25352541
uint32_t alignment,
2536-
uint64_t flags);
2542+
uint64_t flags)
2543+
{
2544+
return i915_gem_object_pin_view(obj, vm, alignment, flags,
2545+
&i915_ggtt_view_normal);
2546+
}
2547+
2548+
int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
2549+
u32 flags);
25372550
int __must_check i915_vma_unbind(struct i915_vma *vma);
25382551
int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
25392552
void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
@@ -2695,18 +2708,51 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
26952708

26962709
void i915_gem_restore_fences(struct drm_device *dev);
26972710

2711+
unsigned long i915_gem_obj_offset_view(struct drm_i915_gem_object *o,
2712+
struct i915_address_space *vm,
2713+
enum i915_ggtt_view_type view);
2714+
static inline
26982715
unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o,
2699-
struct i915_address_space *vm);
2716+
struct i915_address_space *vm)
2717+
{
2718+
return i915_gem_obj_offset_view(o, vm, I915_GGTT_VIEW_NORMAL);
2719+
}
27002720
bool i915_gem_obj_bound_any(struct drm_i915_gem_object *o);
2721+
bool i915_gem_obj_bound_view(struct drm_i915_gem_object *o,
2722+
struct i915_address_space *vm,
2723+
enum i915_ggtt_view_type view);
2724+
static inline
27012725
bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
2702-
struct i915_address_space *vm);
2726+
struct i915_address_space *vm)
2727+
{
2728+
return i915_gem_obj_bound_view(o, vm, I915_GGTT_VIEW_NORMAL);
2729+
}
2730+
27032731
unsigned long i915_gem_obj_size(struct drm_i915_gem_object *o,
27042732
struct i915_address_space *vm);
2733+
struct i915_vma *i915_gem_obj_to_vma_view(struct drm_i915_gem_object *obj,
2734+
struct i915_address_space *vm,
2735+
const struct i915_ggtt_view *view);
2736+
static inline
27052737
struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
2706-
struct i915_address_space *vm);
2738+
struct i915_address_space *vm)
2739+
{
2740+
return i915_gem_obj_to_vma_view(obj, vm, &i915_ggtt_view_normal);
2741+
}
2742+
2743+
struct i915_vma *
2744+
i915_gem_obj_lookup_or_create_vma_view(struct drm_i915_gem_object *obj,
2745+
struct i915_address_space *vm,
2746+
const struct i915_ggtt_view *view);
2747+
2748+
static inline
27072749
struct i915_vma *
27082750
i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
2709-
struct i915_address_space *vm);
2751+
struct i915_address_space *vm)
2752+
{
2753+
return i915_gem_obj_lookup_or_create_vma_view(obj, vm,
2754+
&i915_ggtt_view_normal);
2755+
}
27102756

27112757
struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj);
27122758
static inline bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj) {

drivers/gpu/drm/i915/i915_gem.c

Lines changed: 67 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,17 +2297,14 @@ void i915_vma_move_to_active(struct i915_vma *vma,
22972297
static void
22982298
i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
22992299
{
2300-
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
2301-
struct i915_address_space *vm;
23022300
struct i915_vma *vma;
23032301

23042302
BUG_ON(obj->base.write_domain & ~I915_GEM_GPU_DOMAINS);
23052303
BUG_ON(!obj->active);
23062304

2307-
list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
2308-
vma = i915_gem_obj_to_vma(obj, vm);
2309-
if (vma && !list_empty(&vma->mm_list))
2310-
list_move_tail(&vma->mm_list, &vm->inactive_list);
2305+
list_for_each_entry(vma, &obj->vma_list, vma_link) {
2306+
if (!list_empty(&vma->mm_list))
2307+
list_move_tail(&vma->mm_list, &vma->vm->inactive_list);
23112308
}
23122309

23132310
intel_fb_obj_flush(obj, true);
@@ -3062,10 +3059,8 @@ int i915_vma_unbind(struct i915_vma *vma)
30623059
* cause memory corruption through use-after-free.
30633060
*/
30643061

3065-
/* Throw away the active reference before moving to the unbound list */
3066-
i915_gem_object_retire(obj);
3067-
3068-
if (i915_is_ggtt(vma->vm)) {
3062+
if (i915_is_ggtt(vma->vm) &&
3063+
vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) {
30693064
i915_gem_object_finish_gtt(obj);
30703065

30713066
/* release the fence reg _after_ flushing */
@@ -3079,15 +3074,26 @@ int i915_vma_unbind(struct i915_vma *vma)
30793074
vma->unbind_vma(vma);
30803075

30813076
list_del_init(&vma->mm_list);
3082-
if (i915_is_ggtt(vma->vm))
3083-
obj->map_and_fenceable = false;
3077+
if (i915_is_ggtt(vma->vm)) {
3078+
if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) {
3079+
obj->map_and_fenceable = false;
3080+
} else if (vma->ggtt_view.pages) {
3081+
sg_free_table(vma->ggtt_view.pages);
3082+
kfree(vma->ggtt_view.pages);
3083+
vma->ggtt_view.pages = NULL;
3084+
}
3085+
}
30843086

30853087
drm_mm_remove_node(&vma->node);
30863088
i915_gem_vma_destroy(vma);
30873089

30883090
/* Since the unbound list is global, only move to that list if
30893091
* no more VMAs exist. */
30903092
if (list_empty(&obj->vma_list)) {
3093+
/* Throw away the active reference before
3094+
* moving to the unbound list. */
3095+
i915_gem_object_retire(obj);
3096+
30913097
i915_gem_gtt_finish_object(obj);
30923098
list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
30933099
}
@@ -3498,7 +3504,8 @@ static struct i915_vma *
34983504
i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
34993505
struct i915_address_space *vm,
35003506
unsigned alignment,
3501-
uint64_t flags)
3507+
uint64_t flags,
3508+
const struct i915_ggtt_view *view)
35023509
{
35033510
struct drm_device *dev = obj->base.dev;
35043511
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3548,7 +3555,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
35483555

35493556
i915_gem_object_pin_pages(obj);
35503557

3551-
vma = i915_gem_obj_lookup_or_create_vma(obj, vm);
3558+
vma = i915_gem_obj_lookup_or_create_vma_view(obj, vm, view);
35523559
if (IS_ERR(vma))
35533560
goto err_unpin;
35543561

@@ -3578,15 +3585,19 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
35783585
if (ret)
35793586
goto err_remove_node;
35803587

3588+
trace_i915_vma_bind(vma, flags);
3589+
ret = i915_vma_bind(vma, obj->cache_level,
3590+
flags & PIN_GLOBAL ? GLOBAL_BIND : 0);
3591+
if (ret)
3592+
goto err_finish_gtt;
3593+
35813594
list_move_tail(&obj->global_list, &dev_priv->mm.bound_list);
35823595
list_add_tail(&vma->mm_list, &vm->inactive_list);
35833596

3584-
trace_i915_vma_bind(vma, flags);
3585-
vma->bind_vma(vma, obj->cache_level,
3586-
flags & PIN_GLOBAL ? GLOBAL_BIND : 0);
3587-
35883597
return vma;
35893598

3599+
err_finish_gtt:
3600+
i915_gem_gtt_finish_object(obj);
35903601
err_remove_node:
35913602
drm_mm_remove_node(&vma->node);
35923603
err_free_vma:
@@ -3789,9 +3800,12 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
37893800
}
37903801

37913802
list_for_each_entry(vma, &obj->vma_list, vma_link)
3792-
if (drm_mm_node_allocated(&vma->node))
3793-
vma->bind_vma(vma, cache_level,
3794-
vma->bound & GLOBAL_BIND);
3803+
if (drm_mm_node_allocated(&vma->node)) {
3804+
ret = i915_vma_bind(vma, cache_level,
3805+
vma->bound & GLOBAL_BIND);
3806+
if (ret)
3807+
return ret;
3808+
}
37953809
}
37963810

37973811
list_for_each_entry(vma, &obj->vma_list, vma_link)
@@ -4144,10 +4158,11 @@ i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags)
41444158
}
41454159

41464160
int
4147-
i915_gem_object_pin(struct drm_i915_gem_object *obj,
4148-
struct i915_address_space *vm,
4149-
uint32_t alignment,
4150-
uint64_t flags)
4161+
i915_gem_object_pin_view(struct drm_i915_gem_object *obj,
4162+
struct i915_address_space *vm,
4163+
uint32_t alignment,
4164+
uint64_t flags,
4165+
const struct i915_ggtt_view *view)
41514166
{
41524167
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
41534168
struct i915_vma *vma;
@@ -4163,7 +4178,7 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
41634178
if (WARN_ON((flags & (PIN_MAPPABLE | PIN_GLOBAL)) == PIN_MAPPABLE))
41644179
return -EINVAL;
41654180

4166-
vma = i915_gem_obj_to_vma(obj, vm);
4181+
vma = i915_gem_obj_to_vma_view(obj, vm, view);
41674182
if (vma) {
41684183
if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
41694184
return -EBUSY;
@@ -4173,7 +4188,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
41734188
"bo is already pinned with incorrect alignment:"
41744189
" offset=%lx, req.alignment=%x, req.map_and_fenceable=%d,"
41754190
" obj->map_and_fenceable=%d\n",
4176-
i915_gem_obj_offset(obj, vm), alignment,
4191+
i915_gem_obj_offset_view(obj, vm, view->type),
4192+
alignment,
41774193
!!(flags & PIN_MAPPABLE),
41784194
obj->map_and_fenceable);
41794195
ret = i915_vma_unbind(vma);
@@ -4186,13 +4202,17 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
41864202

41874203
bound = vma ? vma->bound : 0;
41884204
if (vma == NULL || !drm_mm_node_allocated(&vma->node)) {
4189-
vma = i915_gem_object_bind_to_vm(obj, vm, alignment, flags);
4205+
vma = i915_gem_object_bind_to_vm(obj, vm, alignment,
4206+
flags, view);
41904207
if (IS_ERR(vma))
41914208
return PTR_ERR(vma);
41924209
}
41934210

4194-
if (flags & PIN_GLOBAL && !(vma->bound & GLOBAL_BIND))
4195-
vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND);
4211+
if (flags & PIN_GLOBAL && !(vma->bound & GLOBAL_BIND)) {
4212+
ret = i915_vma_bind(vma, obj->cache_level, GLOBAL_BIND);
4213+
if (ret)
4214+
return ret;
4215+
}
41964216

41974217
if ((bound ^ vma->bound) & GLOBAL_BIND) {
41984218
bool mappable, fenceable;
@@ -4528,12 +4548,13 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
45284548
intel_runtime_pm_put(dev_priv);
45294549
}
45304550

4531-
struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
4532-
struct i915_address_space *vm)
4551+
struct i915_vma *i915_gem_obj_to_vma_view(struct drm_i915_gem_object *obj,
4552+
struct i915_address_space *vm,
4553+
const struct i915_ggtt_view *view)
45334554
{
45344555
struct i915_vma *vma;
45354556
list_for_each_entry(vma, &obj->vma_list, vma_link)
4536-
if (vma->vm == vm)
4557+
if (vma->vm == vm && vma->ggtt_view.type == view->type)
45374558
return vma;
45384559

45394560
return NULL;
@@ -5145,16 +5166,17 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
51455166
}
51465167

51475168
/* All the new VM stuff */
5148-
unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o,
5149-
struct i915_address_space *vm)
5169+
unsigned long i915_gem_obj_offset_view(struct drm_i915_gem_object *o,
5170+
struct i915_address_space *vm,
5171+
enum i915_ggtt_view_type view)
51505172
{
51515173
struct drm_i915_private *dev_priv = o->base.dev->dev_private;
51525174
struct i915_vma *vma;
51535175

51545176
WARN_ON(vm == &dev_priv->mm.aliasing_ppgtt->base);
51555177

51565178
list_for_each_entry(vma, &o->vma_list, vma_link) {
5157-
if (vma->vm == vm)
5179+
if (vma->vm == vm && vma->ggtt_view.type == view)
51585180
return vma->node.start;
51595181

51605182
}
@@ -5163,13 +5185,16 @@ unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o,
51635185
return -1;
51645186
}
51655187

5166-
bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
5167-
struct i915_address_space *vm)
5188+
bool i915_gem_obj_bound_view(struct drm_i915_gem_object *o,
5189+
struct i915_address_space *vm,
5190+
enum i915_ggtt_view_type view)
51685191
{
51695192
struct i915_vma *vma;
51705193

51715194
list_for_each_entry(vma, &o->vma_list, vma_link)
5172-
if (vma->vm == vm && drm_mm_node_allocated(&vma->node))
5195+
if (vma->vm == vm &&
5196+
vma->ggtt_view.type == view &&
5197+
drm_mm_node_allocated(&vma->node))
51735198
return true;
51745199

51755200
return false;
@@ -5304,10 +5329,10 @@ struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj)
53045329
struct i915_address_space *ggtt = i915_obj_to_ggtt(obj);
53055330
struct i915_vma *vma;
53065331

5307-
list_for_each_entry(vma, &obj->vma_list, vma_link) {
5308-
if (vma->vm == ggtt)
5332+
list_for_each_entry(vma, &obj->vma_list, vma_link)
5333+
if (vma->vm == ggtt &&
5334+
vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL)
53095335
return vma;
5310-
}
53115336

53125337
return NULL;
53135338
}

drivers/gpu/drm/i915/i915_gem_context.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -590,9 +590,14 @@ static int do_switch(struct intel_engine_cs *ring,
590590
goto unpin_out;
591591

592592
vma = i915_gem_obj_to_ggtt(to->legacy_hw_ctx.rcs_state);
593-
if (!(vma->bound & GLOBAL_BIND))
594-
vma->bind_vma(vma, to->legacy_hw_ctx.rcs_state->cache_level,
595-
GLOBAL_BIND);
593+
if (!(vma->bound & GLOBAL_BIND)) {
594+
ret = i915_vma_bind(vma,
595+
to->legacy_hw_ctx.rcs_state->cache_level,
596+
GLOBAL_BIND);
597+
/* This shouldn't ever fail. */
598+
if (WARN_ONCE(ret, "GGTT context bind failed!"))
599+
goto unpin_out;
600+
}
596601

597602
if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to))
598603
hw_flags |= MI_RESTORE_INHIBIT;

drivers/gpu/drm/i915/i915_gem_execbuffer.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,12 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
360360
* through the ppgtt for non_secure batchbuffers. */
361361
if (unlikely(IS_GEN6(dev) &&
362362
reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION &&
363-
!(target_vma->bound & GLOBAL_BIND)))
364-
target_vma->bind_vma(target_vma, target_i915_obj->cache_level,
365-
GLOBAL_BIND);
363+
!(target_vma->bound & GLOBAL_BIND))) {
364+
ret = i915_vma_bind(target_vma, target_i915_obj->cache_level,
365+
GLOBAL_BIND);
366+
if (WARN_ONCE(ret, "Unexpected failure to bind target VMA!"))
367+
return ret;
368+
}
366369

367370
/* Validate that the target is in a valid r/w GPU domain */
368371
if (unlikely(reloc->write_domain & (reloc->write_domain - 1))) {

0 commit comments

Comments
 (0)