[Intel-gfx] [PATCH 08/39] drm/i915: Create/destroy VM (ppGTT) for use with contexts
Chris Wilson
chris at chris-wilson.co.uk
Thu Mar 14 16:46:17 UTC 2019
Quoting Tvrtko Ursulin (2019-03-14 16:07:17)
> On 13/03/2019 14:43, Chris Wilson wrote:
> > In preparation to making the ppGTT binding for a context explicit (to
> > facilitate reusing the same ppGTT between different contexts), allow the
> > user to create and destroy named ppGTT.
> >
> > v2: Replace global barrier for swapping over the ppgtt and tlbs with a
> > local context barrier (Tvrtko)
> > v3: serialise with struct_mutex; it's lazy but required dammit
> > v4: Rewrite igt_ctx_shared_exec to be more different (aimed to be more
> > similarly, turned out different!)
> >
> > v2: Fix up test unwind for aliasing-ppgtt (snb)
> > v3: Tighten language for uapi struct drm_i915_gem_vm_control.
> > v4: Patch the context image for runtime ppgtt switching!
>
> -ECHANGELOGNOTMONOTONIC :))
I shall randomly delete half of them. Thanos rules.
> > +static void set_ppgtt_barrier(void *data)
> > +{
> > + struct i915_hw_ppgtt *old = data;
> > +
> > + if (INTEL_GEN(old->vm.i915) < 8)
> > + gen6_ppgtt_unpin_all(old);
>
> Is ppgtt sharing interesting for aliasing ppgtt? Ah HSW now has proper..
>
> > +
> > + i915_ppgtt_close(old);
> > + i915_ppgtt_put(old);
> > +}
> > +
> > +static int emit_ppgtt_update(struct i915_request *rq, void *data)
> > +{
> > + struct i915_hw_ppgtt *ppgtt = rq->gem_context->ppgtt;
> > + struct intel_engine_cs *engine = rq->engine;
> > + u32 *cs;
> > + int i;
> > +
> > + if (i915_vm_is_48bit(&ppgtt->vm)) {
> > + const dma_addr_t pd_daddr = px_dma(&ppgtt->pml4);
> > +
> > + cs = intel_ring_begin(rq, 6);
> > + if (IS_ERR(cs))
> > + return PTR_ERR(cs);
> > +
> > + *cs++ = MI_LOAD_REGISTER_IMM(2);
> > +
> > + *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(engine, 0));
> > + *cs++ = upper_32_bits(pd_daddr);
> > + *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(engine, 0));
> > + *cs++ = lower_32_bits(pd_daddr);
>
> Only one out of four these beasties needs to be updated? (In contrast to
> virtual_update_register_offsets.) As you can see I am not too familiar
> with pgtable management.
Our notes say that the HW ignores 1..3, so I was wondering if we could
condense these two into one with a bit of jiggery pokery to pluck the
right dma address. Might also simplify execlists_init_reg_state() that
tiny bit.
> > +
> > + *cs++ = MI_NOOP;
> > + intel_ring_advance(rq, cs);
> > + } else if (HAS_LOGICAL_RING_CONTEXTS(engine->i915)) {
> > + cs = intel_ring_begin(rq, 4 * GEN8_3LVL_PDPES + 2);
> > + if (IS_ERR(cs))
> > + return PTR_ERR(cs);
> > +
> > + *cs++ = MI_LOAD_REGISTER_IMM(2 * GEN8_3LVL_PDPES);
> > + for (i = GEN8_3LVL_PDPES; i--; ) {
> > + const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
> > +
> > + *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(engine, i));
> > + *cs++ = upper_32_bits(pd_daddr);
> > + *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(engine, i));
> > + *cs++ = lower_32_bits(pd_daddr);
> > + }
> > + *cs++ = MI_NOOP;
> > + intel_ring_advance(rq, cs);
>
> So a running context will update it's own context image. And it doesn't
> get overwritten on context save?
Indeed. It is how we update PD at runtime.
> Are there tests which hit this path?
Yes. As always a serendipitous discovery. :)
The simplest of
gem_execbuf();
gem_context_set_param(NEW_VM);
gem_execbuf();
thankfully had a very recognisable GPU hang.
> > + } else {
> > + /* ppGTT is not part of the legacy context image */
> > + gen6_ppgtt_pin(ppgtt);
>
> What is happening on this path - why is the pin needed here only to be
> unpinned in the barrier callback? This is not handled by normal request
> flow?
It's because we pin the ppgtt as part of pinning the context (for
gen6/gen7). Since the context is already pinned, we don't notice the new
ctx->ppgtt. Hence we have to manually acquire a pin on ctx->ppgtt and
discard the old pins.
-Chris
More information about the Intel-gfx
mailing list