[Intel-gfx] [PATCH v2 1/3] drm/i915/guc: keep GuC objects mapped in kernel
Chris Wilson
chris at chris-wilson.co.uk
Mon Apr 18 11:37:56 UTC 2016
On Mon, Apr 18, 2016 at 12:28:43PM +0100, Dave Gordon wrote:
> On 18/04/16 11:25, Chris Wilson wrote:
> >On Mon, Apr 18, 2016 at 11:15:07AM +0100, Dave Gordon wrote:
> >>With the new i915_gem_obj_pin_map() interface, it makes sense to keep
> >>GuC objects (which are always pinned in memory and in the GGTT anyway)
> >>mapped into kernel address space, rather than mapping and unmapping them
> >>on each access.
> >>
> >>This preliminary patch sets up the pin-and-map for all GuC-specific
> >>objects, and updates the various setup/shutdown functions to use these
> >>long-term mappings rather than doing their own kmap_atomic() calls.
> >>
> >>v2:
> >> Invent & use accessor function i915_object_mapped_address() rather
> >> than accessing obj->mapping directly (Tvrtko Ursulin)
> >> Use IS_ERR() rather than checking for NULL (Tvrtko Ursulin)
> >> Added big comment about struct i915_guc_client & usage of the GEM
> >> object that it describes
> >>
> >>Cc: <tvrtko.ursulin at intel.com>
> >>Signed-off-by: Alex Dai <yu.dai at intel.com>
> >>Signed-off-by: Dave Gordon <david.s.gordon at intel.com>
> >>---
> >> drivers/gpu/drm/i915/i915_drv.h | 12 ++++++++++
> >> drivers/gpu/drm/i915/i915_guc_submission.c | 38 +++++++++++-------------------
> >> drivers/gpu/drm/i915/intel_guc.h | 24 +++++++++++++++++++
> >> 3 files changed, 50 insertions(+), 24 deletions(-)
> >>
> >>diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> >>index 85102ad..439f149 100644
> >>--- a/drivers/gpu/drm/i915/i915_drv.h
> >>+++ b/drivers/gpu/drm/i915/i915_drv.h
> >>@@ -3025,6 +3025,18 @@ static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
> >> void *__must_check i915_gem_object_pin_map(struct drm_i915_gem_object *obj);
> >>
> >> /**
> >>+ * i915_object_mapped_address - address at which a GEM object is mapped
> >>+ * @obj - the object (presumably already mapped into kernel address space)
> >>+ *
> >>+ * Returns the address at which an object has been mapped by a call to
> >>+ * i915_gem_object_pin_map() above, or NULL if not currently mapped and pinned
> >>+ */
> >>+static inline void *i915_object_mapped_address(struct drm_i915_gem_object *obj)
> >>+{
> >>+ return obj->pages_pin_count == 0 ? NULL : obj->mapping;
> >>+}
> >
> >No.
>
> The kernel address at which an object is pinned is just as much a
> property of the object as its GGTT address, so should have a similar
> function for retrieving it.
An object doesn't have a GGTT, a vma does. The object has vma. To use
the vma, you must pin it.
> The pages_pin_count check is there because once that goes to zero,
> the object doesn't logically /have/ a memory address, even if
> 'mapping' is still set.
>
> Or was it just the name you objected to?
Name and function. obj->mapping is tied into the shinker which can and
will run at any time, stealing all locks. Using obj->mapping which
holding an actual page reference for yourself is broken.
>
> >>@@ -649,6 +639,9 @@ static void gem_release_guc_obj(struct drm_i915_gem_object *obj)
> >> if (i915_gem_obj_is_pinned(obj))
> >> i915_gem_object_ggtt_unpin(obj);
> >>
> >>+ if (i915_object_mapped_address(obj))
> >>+ i915_gem_object_unpin_map(obj);
> >
> >Eh? If you aren't tracking your pin, you can't just randomly free
> >someone elses.
>
> The GuC code exclusively owns this object, so it can't be "someone
> else's". The pages_pin count here will always be 1 (at present).
> This was to allow for the possibility that we already chose to
> release the pin-and-map while leaving the object in the GGTT, in
> which case the pages_pin_count will be 0. (We don't do this, at
> present, but see below).
That is bad justification for adding unsafe code.
> >> drm_gem_object_unreference(&obj->base);
> >> }
> >>
> >>@@ -729,6 +722,8 @@ static struct i915_guc_client *guc_client_alloc(struct drm_device *dev,
> >> goto err;
> >>
> >> client->client_obj = obj;
> >>+ client->client_base = i915_object_mapped_address(obj);
> >>+ WARN_ON(!client->client_base);
> >> client->wq_offset = GUC_DB_SIZE;
> >> client->wq_size = GUC_WQ_SIZE;
> >>
> >>@@ -841,7 +836,6 @@ static void guc_create_ads(struct intel_guc *guc)
> >> struct guc_policies *policies;
> >> struct guc_mmio_reg_state *reg_state;
> >> struct intel_engine_cs *engine;
> >>- struct page *page;
> >> u32 size;
> >>
> >> /* The ads obj includes the struct itself and buffers passed to GuC */
> >>@@ -857,9 +851,7 @@ static void guc_create_ads(struct intel_guc *guc)
> >>
> >> guc->ads_obj = obj;
> >> }
> >>-
> >>- page = i915_gem_object_get_page(obj, 0);
> >>- ads = kmap(page);
> >>+ ads = i915_object_mapped_address(obj);
> >
> >You need to explicitly aknowlege that you are using the memory tracked
> >by the object otherwise it *will* be removed by the shrinker.
> >So what is wrong with using i915_gem_object_pin_map()?
> >-Chris
>
> The object is pinned-and-mapped just once, when it's created, and
> kept that way until it's destroyed. Calling pin-and-map here would
> give it a pin count of two, which would be redundant, and require us
> to unpin-and-map it again at the end of the function - which just
> seems a waste of time.
Considering the alternative is an unsound API. Just do it, or pass
around the mapping in a local you have already pinned.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
More information about the Intel-gfx
mailing list