2010-11-06 05:23:30 +08:00
|
|
|
/*
|
|
|
|
* Copyright © 2010 Daniel Vetter
|
2014-02-20 14:05:47 +08:00
|
|
|
* Copyright © 2011-2014 Intel Corporation
|
2010-11-06 05:23:30 +08:00
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2014-01-08 23:10:27 +08:00
|
|
|
#include <linux/seq_file.h>
|
2015-10-24 01:43:32 +08:00
|
|
|
#include <linux/stop_machine.h>
|
2012-10-03 01:01:07 +08:00
|
|
|
#include <drm/drmP.h>
|
|
|
|
#include <drm/i915_drm.h>
|
2010-11-06 05:23:30 +08:00
|
|
|
#include "i915_drv.h"
|
2015-02-10 19:05:48 +08:00
|
|
|
#include "i915_vgpu.h"
|
2010-11-06 05:23:30 +08:00
|
|
|
#include "i915_trace.h"
|
|
|
|
#include "intel_drv.h"
|
|
|
|
|
2016-08-22 15:44:31 +08:00
|
|
|
#define I915_GFP_DMA (GFP_KERNEL | __GFP_HIGHMEM)
|
|
|
|
|
2014-12-11 01:27:59 +08:00
|
|
|
/**
|
|
|
|
* DOC: Global GTT views
|
|
|
|
*
|
|
|
|
* Background and previous state
|
|
|
|
*
|
|
|
|
* Historically objects could exists (be bound) in global GTT space only as
|
|
|
|
* singular instances with a view representing all of the object's backing pages
|
|
|
|
* in a linear fashion. This view will be called a normal view.
|
|
|
|
*
|
|
|
|
* To support multiple views of the same object, where the number of mapped
|
|
|
|
* pages is not equal to the backing store, or where the layout of the pages
|
|
|
|
* is not linear, concept of a GGTT view was added.
|
|
|
|
*
|
|
|
|
* One example of an alternative view is a stereo display driven by a single
|
|
|
|
* image. In this case we would have a framebuffer looking like this
|
|
|
|
* (2x2 pages):
|
|
|
|
*
|
|
|
|
* 12
|
|
|
|
* 34
|
|
|
|
*
|
|
|
|
* Above would represent a normal GGTT view as normally mapped for GPU or CPU
|
|
|
|
* rendering. In contrast, fed to the display engine would be an alternative
|
|
|
|
* view which could look something like this:
|
|
|
|
*
|
|
|
|
* 1212
|
|
|
|
* 3434
|
|
|
|
*
|
|
|
|
* In this example both the size and layout of pages in the alternative view is
|
|
|
|
* different from the normal view.
|
|
|
|
*
|
|
|
|
* Implementation and usage
|
|
|
|
*
|
|
|
|
* GGTT views are implemented using VMAs and are distinguished via enum
|
|
|
|
* i915_ggtt_view_type and struct i915_ggtt_view.
|
|
|
|
*
|
|
|
|
* A new flavour of core GEM functions which work with GGTT bound objects were
|
2015-03-16 20:11:13 +08:00
|
|
|
* added with the _ggtt_ infix, and sometimes with _view postfix to avoid
|
|
|
|
* renaming in large amounts of code. They take the struct i915_ggtt_view
|
|
|
|
* parameter encapsulating all metadata required to implement a view.
|
2014-12-11 01:27:59 +08:00
|
|
|
*
|
|
|
|
* As a helper for callers which are only interested in the normal view,
|
|
|
|
* globally const i915_ggtt_view_normal singleton instance exists. All old core
|
|
|
|
* GEM API functions, the ones not taking the view parameter, are operating on,
|
|
|
|
* or with the normal GGTT view.
|
|
|
|
*
|
|
|
|
* Code wanting to add or use a new GGTT view needs to:
|
|
|
|
*
|
|
|
|
* 1. Add a new enum with a suitable name.
|
|
|
|
* 2. Extend the metadata in the i915_ggtt_view structure if required.
|
|
|
|
* 3. Add support to i915_get_vma_pages().
|
|
|
|
*
|
|
|
|
* New views are required to build a scatter-gather table from within the
|
|
|
|
* i915_get_vma_pages function. This table is stored in the vma.ggtt_view and
|
|
|
|
* exists for the lifetime of an VMA.
|
|
|
|
*
|
|
|
|
* Core API is designed to have copy semantics which means that passed in
|
|
|
|
* struct i915_ggtt_view does not need to be persistent (left around after
|
|
|
|
* calling the core API functions).
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-04-28 16:56:38 +08:00
|
|
|
static inline struct i915_ggtt *
|
|
|
|
i915_vm_to_ggtt(struct i915_address_space *vm)
|
|
|
|
{
|
|
|
|
GEM_BUG_ON(!i915_is_ggtt(vm));
|
|
|
|
return container_of(vm, struct i915_ggtt, base);
|
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:27 +08:00
|
|
|
static int
|
|
|
|
i915_get_ggtt_vma_pages(struct i915_vma *vma);
|
|
|
|
|
2016-01-14 21:22:10 +08:00
|
|
|
const struct i915_ggtt_view i915_ggtt_view_normal = {
|
|
|
|
.type = I915_GGTT_VIEW_NORMAL,
|
|
|
|
};
|
2015-03-27 19:09:22 +08:00
|
|
|
const struct i915_ggtt_view i915_ggtt_view_rotated = {
|
2016-01-14 21:22:10 +08:00
|
|
|
.type = I915_GGTT_VIEW_ROTATED,
|
2015-03-27 19:09:22 +08:00
|
|
|
};
|
2014-12-11 01:27:58 +08:00
|
|
|
|
2016-05-06 22:40:21 +08:00
|
|
|
int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
|
|
|
|
int enable_ppgtt)
|
2014-04-29 17:53:58 +08:00
|
|
|
{
|
2014-09-19 18:56:27 +08:00
|
|
|
bool has_aliasing_ppgtt;
|
|
|
|
bool has_full_ppgtt;
|
2015-09-30 22:36:19 +08:00
|
|
|
bool has_full_48bit_ppgtt;
|
2014-09-19 18:56:27 +08:00
|
|
|
|
2016-05-06 22:40:21 +08:00
|
|
|
has_aliasing_ppgtt = INTEL_GEN(dev_priv) >= 6;
|
|
|
|
has_full_ppgtt = INTEL_GEN(dev_priv) >= 7;
|
|
|
|
has_full_48bit_ppgtt =
|
|
|
|
IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9;
|
2014-09-19 18:56:27 +08:00
|
|
|
|
2016-09-06 12:04:12 +08:00
|
|
|
if (intel_vgpu_active(dev_priv)) {
|
|
|
|
/* emulation is too hard */
|
|
|
|
has_full_ppgtt = false;
|
|
|
|
has_full_48bit_ppgtt = false;
|
|
|
|
}
|
2015-02-10 19:05:54 +08:00
|
|
|
|
2016-04-29 20:18:22 +08:00
|
|
|
if (!has_aliasing_ppgtt)
|
|
|
|
return 0;
|
|
|
|
|
2014-11-14 23:05:59 +08:00
|
|
|
/*
|
|
|
|
* We don't allow disabling PPGTT for gen9+ as it's a requirement for
|
|
|
|
* execlists, the sole mechanism available to submit work.
|
|
|
|
*/
|
2016-05-06 22:40:21 +08:00
|
|
|
if (enable_ppgtt == 0 && INTEL_GEN(dev_priv) < 9)
|
2014-04-29 17:53:58 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (enable_ppgtt == 1)
|
|
|
|
return 1;
|
|
|
|
|
2014-09-19 18:56:27 +08:00
|
|
|
if (enable_ppgtt == 2 && has_full_ppgtt)
|
2014-04-29 17:53:58 +08:00
|
|
|
return 2;
|
|
|
|
|
2015-09-30 22:36:19 +08:00
|
|
|
if (enable_ppgtt == 3 && has_full_48bit_ppgtt)
|
|
|
|
return 3;
|
|
|
|
|
drm/i915: Disable full ppgtt by default
There are too many oustanding issues:
- Fence handling in the current code is broken. There's a patch series
from me, but it's blocked on and extended review (which includes
writing the testcases).
- IOMMU mapping handling is broken, we need to properly refcount it -
currently it gets destroyed when the first vma is unbound, so way
too early.
- There's a pending reset issue on snb. Since Mika's reset work and
full ppgtt have been pulled in in separate branches and ended up
intermittingly breaking each another it's unclear who's the exact
culprit here.
- We still have persistent evidince of crazy recursion bugs through
vma_unbind and ppgtt_relase, e.g.
https://bugs.freedesktop.org/show_bug.cgi?id=73383
This issue (and a few others meanwhile resolved) have blocked our
performance measuring/tuning group since 3 months.
- Secure batch dispatching is broken. This is blocking Brad Volkin's
command checker work since 3 months.
All these issues are confirmed to only happen when full ppgtt is
enabled, falling back to aliasing ppgtt resolves them. But even
aliasing ppgtt itself still has a regression:
- We currently unconditionally bind objects into the aliasing ppgtt,
which means all priviledged objects like ringbuffers are visible to
unpriviledged access again. On top of that this also breaks the
command checker for aliasing ppgtt, since it can't hide the
validated batch any more.
Furthermore topic/full-ppgtt has never been reviewed:
- Lifetime rules around vma unbinding/release are unclear, resulting
into this awesome hack called ppgtt_release. Which seems to take the
blame for most of the recursion fallout.
- Context/ring init works different on gpu reset than anywhere else.
Such differeneces have in the past always lead to really hard to
track down bugs.
- Aliasing ppgtt is treated in a bunch of places as a real address
space, but it isn't - the real address space is always the global
gtt in that case. This results in a bit a mess between contexts and
ppgtt object, further complication the context/ppgtt/vma lifetime
rules.
- We don't have any docs describing the overall concepts introduced
with full ppgtt. A short, concise overview describing vmas and some
of the strange bits around them (like the unbound vmas used by
execbuf, or the new binding rules) really is needed.
Note that a lot of the post topic/full-ppgtt merge fallout has already
been addressed, this entire list here of 10 issues really only contains
the still outstanding issues.
Finally the 3.15 merge window is approaching and I think we need to
use the remaining time to ensure that our fallback option of using
aliasing ppgtt is in solid shape. Hence I think it's time to throw the
switch. While at it demote the helper from static inline status
because really.
Cc: Ben Widawsky <ben@bwidawsk.net>
Cc: Dave Airlie <airlied@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-06 16:40:43 +08:00
|
|
|
#ifdef CONFIG_INTEL_IOMMU
|
|
|
|
/* Disable ppgtt on SNB if VT-d is on. */
|
2016-05-06 22:40:21 +08:00
|
|
|
if (IS_GEN6(dev_priv) && intel_iommu_gfx_mapped) {
|
drm/i915: Disable full ppgtt by default
There are too many oustanding issues:
- Fence handling in the current code is broken. There's a patch series
from me, but it's blocked on and extended review (which includes
writing the testcases).
- IOMMU mapping handling is broken, we need to properly refcount it -
currently it gets destroyed when the first vma is unbound, so way
too early.
- There's a pending reset issue on snb. Since Mika's reset work and
full ppgtt have been pulled in in separate branches and ended up
intermittingly breaking each another it's unclear who's the exact
culprit here.
- We still have persistent evidince of crazy recursion bugs through
vma_unbind and ppgtt_relase, e.g.
https://bugs.freedesktop.org/show_bug.cgi?id=73383
This issue (and a few others meanwhile resolved) have blocked our
performance measuring/tuning group since 3 months.
- Secure batch dispatching is broken. This is blocking Brad Volkin's
command checker work since 3 months.
All these issues are confirmed to only happen when full ppgtt is
enabled, falling back to aliasing ppgtt resolves them. But even
aliasing ppgtt itself still has a regression:
- We currently unconditionally bind objects into the aliasing ppgtt,
which means all priviledged objects like ringbuffers are visible to
unpriviledged access again. On top of that this also breaks the
command checker for aliasing ppgtt, since it can't hide the
validated batch any more.
Furthermore topic/full-ppgtt has never been reviewed:
- Lifetime rules around vma unbinding/release are unclear, resulting
into this awesome hack called ppgtt_release. Which seems to take the
blame for most of the recursion fallout.
- Context/ring init works different on gpu reset than anywhere else.
Such differeneces have in the past always lead to really hard to
track down bugs.
- Aliasing ppgtt is treated in a bunch of places as a real address
space, but it isn't - the real address space is always the global
gtt in that case. This results in a bit a mess between contexts and
ppgtt object, further complication the context/ppgtt/vma lifetime
rules.
- We don't have any docs describing the overall concepts introduced
with full ppgtt. A short, concise overview describing vmas and some
of the strange bits around them (like the unbound vmas used by
execbuf, or the new binding rules) really is needed.
Note that a lot of the post topic/full-ppgtt merge fallout has already
been addressed, this entire list here of 10 issues really only contains
the still outstanding issues.
Finally the 3.15 merge window is approaching and I think we need to
use the remaining time to ensure that our fallback option of using
aliasing ppgtt is in solid shape. Hence I think it's time to throw the
switch. While at it demote the helper from static inline status
because really.
Cc: Ben Widawsky <ben@bwidawsk.net>
Cc: Dave Airlie <airlied@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-06 16:40:43 +08:00
|
|
|
DRM_INFO("Disabling PPGTT because VT-d is on\n");
|
2014-04-29 17:53:58 +08:00
|
|
|
return 0;
|
drm/i915: Disable full ppgtt by default
There are too many oustanding issues:
- Fence handling in the current code is broken. There's a patch series
from me, but it's blocked on and extended review (which includes
writing the testcases).
- IOMMU mapping handling is broken, we need to properly refcount it -
currently it gets destroyed when the first vma is unbound, so way
too early.
- There's a pending reset issue on snb. Since Mika's reset work and
full ppgtt have been pulled in in separate branches and ended up
intermittingly breaking each another it's unclear who's the exact
culprit here.
- We still have persistent evidince of crazy recursion bugs through
vma_unbind and ppgtt_relase, e.g.
https://bugs.freedesktop.org/show_bug.cgi?id=73383
This issue (and a few others meanwhile resolved) have blocked our
performance measuring/tuning group since 3 months.
- Secure batch dispatching is broken. This is blocking Brad Volkin's
command checker work since 3 months.
All these issues are confirmed to only happen when full ppgtt is
enabled, falling back to aliasing ppgtt resolves them. But even
aliasing ppgtt itself still has a regression:
- We currently unconditionally bind objects into the aliasing ppgtt,
which means all priviledged objects like ringbuffers are visible to
unpriviledged access again. On top of that this also breaks the
command checker for aliasing ppgtt, since it can't hide the
validated batch any more.
Furthermore topic/full-ppgtt has never been reviewed:
- Lifetime rules around vma unbinding/release are unclear, resulting
into this awesome hack called ppgtt_release. Which seems to take the
blame for most of the recursion fallout.
- Context/ring init works different on gpu reset than anywhere else.
Such differeneces have in the past always lead to really hard to
track down bugs.
- Aliasing ppgtt is treated in a bunch of places as a real address
space, but it isn't - the real address space is always the global
gtt in that case. This results in a bit a mess between contexts and
ppgtt object, further complication the context/ppgtt/vma lifetime
rules.
- We don't have any docs describing the overall concepts introduced
with full ppgtt. A short, concise overview describing vmas and some
of the strange bits around them (like the unbound vmas used by
execbuf, or the new binding rules) really is needed.
Note that a lot of the post topic/full-ppgtt merge fallout has already
been addressed, this entire list here of 10 issues really only contains
the still outstanding issues.
Finally the 3.15 merge window is approaching and I think we need to
use the remaining time to ensure that our fallback option of using
aliasing ppgtt is in solid shape. Hence I think it's time to throw the
switch. While at it demote the helper from static inline status
because really.
Cc: Ben Widawsky <ben@bwidawsk.net>
Cc: Dave Airlie <airlied@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-06 16:40:43 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-06-14 00:28:33 +08:00
|
|
|
/* Early VLV doesn't have this */
|
2016-07-05 17:40:23 +08:00
|
|
|
if (IS_VALLEYVIEW(dev_priv) && dev_priv->drm.pdev->revision < 0xb) {
|
2014-06-14 00:28:33 +08:00
|
|
|
DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-06 12:04:12 +08:00
|
|
|
if (INTEL_GEN(dev_priv) >= 8 && i915.enable_execlists && has_full_ppgtt)
|
2015-09-30 22:36:19 +08:00
|
|
|
return has_full_48bit_ppgtt ? 3 : 2;
|
2014-12-15 22:58:00 +08:00
|
|
|
else
|
|
|
|
return has_aliasing_ppgtt ? 1 : 0;
|
drm/i915: Disable full ppgtt by default
There are too many oustanding issues:
- Fence handling in the current code is broken. There's a patch series
from me, but it's blocked on and extended review (which includes
writing the testcases).
- IOMMU mapping handling is broken, we need to properly refcount it -
currently it gets destroyed when the first vma is unbound, so way
too early.
- There's a pending reset issue on snb. Since Mika's reset work and
full ppgtt have been pulled in in separate branches and ended up
intermittingly breaking each another it's unclear who's the exact
culprit here.
- We still have persistent evidince of crazy recursion bugs through
vma_unbind and ppgtt_relase, e.g.
https://bugs.freedesktop.org/show_bug.cgi?id=73383
This issue (and a few others meanwhile resolved) have blocked our
performance measuring/tuning group since 3 months.
- Secure batch dispatching is broken. This is blocking Brad Volkin's
command checker work since 3 months.
All these issues are confirmed to only happen when full ppgtt is
enabled, falling back to aliasing ppgtt resolves them. But even
aliasing ppgtt itself still has a regression:
- We currently unconditionally bind objects into the aliasing ppgtt,
which means all priviledged objects like ringbuffers are visible to
unpriviledged access again. On top of that this also breaks the
command checker for aliasing ppgtt, since it can't hide the
validated batch any more.
Furthermore topic/full-ppgtt has never been reviewed:
- Lifetime rules around vma unbinding/release are unclear, resulting
into this awesome hack called ppgtt_release. Which seems to take the
blame for most of the recursion fallout.
- Context/ring init works different on gpu reset than anywhere else.
Such differeneces have in the past always lead to really hard to
track down bugs.
- Aliasing ppgtt is treated in a bunch of places as a real address
space, but it isn't - the real address space is always the global
gtt in that case. This results in a bit a mess between contexts and
ppgtt object, further complication the context/ppgtt/vma lifetime
rules.
- We don't have any docs describing the overall concepts introduced
with full ppgtt. A short, concise overview describing vmas and some
of the strange bits around them (like the unbound vmas used by
execbuf, or the new binding rules) really is needed.
Note that a lot of the post topic/full-ppgtt merge fallout has already
been addressed, this entire list here of 10 issues really only contains
the still outstanding issues.
Finally the 3.15 merge window is approaching and I think we need to
use the remaining time to ensure that our fallback option of using
aliasing ppgtt is in solid shape. Hence I think it's time to throw the
switch. While at it demote the helper from static inline status
because really.
Cc: Ben Widawsky <ben@bwidawsk.net>
Cc: Dave Airlie <airlied@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-06 16:40:43 +08:00
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:27 +08:00
|
|
|
static int ppgtt_bind_vma(struct i915_vma *vma,
|
|
|
|
enum i915_cache_level cache_level,
|
|
|
|
u32 unused)
|
2015-04-14 23:35:24 +08:00
|
|
|
{
|
|
|
|
u32 pte_flags = 0;
|
|
|
|
|
2016-08-15 17:48:47 +08:00
|
|
|
vma->pages = vma->obj->pages;
|
|
|
|
|
2015-04-14 23:35:24 +08:00
|
|
|
/* Currently applicable only to VLV */
|
|
|
|
if (vma->obj->gt_ro)
|
|
|
|
pte_flags |= PTE_READ_ONLY;
|
|
|
|
|
2016-08-15 17:48:47 +08:00
|
|
|
vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start,
|
2015-04-14 23:35:24 +08:00
|
|
|
cache_level, pte_flags);
|
2015-04-14 23:35:27 +08:00
|
|
|
|
|
|
|
return 0;
|
2015-04-14 23:35:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ppgtt_unbind_vma(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
vma->vm->clear_range(vma->vm,
|
|
|
|
vma->node.start,
|
2016-10-13 20:02:40 +08:00
|
|
|
vma->size);
|
2015-04-14 23:35:24 +08:00
|
|
|
}
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
|
2015-04-14 23:35:26 +08:00
|
|
|
static gen8_pte_t gen8_pte_encode(dma_addr_t addr,
|
2016-10-13 20:02:40 +08:00
|
|
|
enum i915_cache_level level)
|
2013-11-03 12:07:18 +08:00
|
|
|
{
|
2016-10-13 20:02:40 +08:00
|
|
|
gen8_pte_t pte = _PAGE_PRESENT | _PAGE_RW;
|
2013-11-03 12:07:18 +08:00
|
|
|
pte |= addr;
|
2014-04-19 05:04:27 +08:00
|
|
|
|
|
|
|
switch (level) {
|
|
|
|
case I915_CACHE_NONE:
|
2013-11-05 11:56:49 +08:00
|
|
|
pte |= PPAT_UNCACHED_INDEX;
|
2014-04-19 05:04:27 +08:00
|
|
|
break;
|
|
|
|
case I915_CACHE_WT:
|
|
|
|
pte |= PPAT_DISPLAY_ELLC_INDEX;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pte |= PPAT_CACHED_INDEX;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-11-03 12:07:18 +08:00
|
|
|
return pte;
|
|
|
|
}
|
|
|
|
|
2015-06-25 23:35:16 +08:00
|
|
|
static gen8_pde_t gen8_pde_encode(const dma_addr_t addr,
|
|
|
|
const enum i915_cache_level level)
|
2013-11-05 13:20:14 +08:00
|
|
|
{
|
2015-03-17 00:00:54 +08:00
|
|
|
gen8_pde_t pde = _PAGE_PRESENT | _PAGE_RW;
|
2013-11-05 13:20:14 +08:00
|
|
|
pde |= addr;
|
|
|
|
if (level != I915_CACHE_NONE)
|
|
|
|
pde |= PPAT_CACHED_PDE_INDEX;
|
|
|
|
else
|
|
|
|
pde |= PPAT_UNCACHED_INDEX;
|
|
|
|
return pde;
|
|
|
|
}
|
|
|
|
|
2015-07-30 18:05:29 +08:00
|
|
|
#define gen8_pdpe_encode gen8_pde_encode
|
|
|
|
#define gen8_pml4e_encode gen8_pde_encode
|
|
|
|
|
2015-03-17 00:00:54 +08:00
|
|
|
static gen6_pte_t snb_pte_encode(dma_addr_t addr,
|
|
|
|
enum i915_cache_level level,
|
2016-10-13 20:02:40 +08:00
|
|
|
u32 unused)
|
2012-09-25 07:44:32 +08:00
|
|
|
{
|
2016-10-13 20:02:40 +08:00
|
|
|
gen6_pte_t pte = GEN6_PTE_VALID;
|
2012-09-25 07:44:32 +08:00
|
|
|
pte |= GEN6_PTE_ADDR_ENCODE(addr);
|
2012-10-20 00:33:22 +08:00
|
|
|
|
|
|
|
switch (level) {
|
2013-08-06 20:17:02 +08:00
|
|
|
case I915_CACHE_L3_LLC:
|
|
|
|
case I915_CACHE_LLC:
|
|
|
|
pte |= GEN6_PTE_CACHE_LLC;
|
|
|
|
break;
|
|
|
|
case I915_CACHE_NONE:
|
|
|
|
pte |= GEN6_PTE_UNCACHED;
|
|
|
|
break;
|
|
|
|
default:
|
2014-12-08 23:40:10 +08:00
|
|
|
MISSING_CASE(level);
|
2013-08-06 20:17:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return pte;
|
|
|
|
}
|
|
|
|
|
2015-03-17 00:00:54 +08:00
|
|
|
static gen6_pte_t ivb_pte_encode(dma_addr_t addr,
|
|
|
|
enum i915_cache_level level,
|
2016-10-13 20:02:40 +08:00
|
|
|
u32 unused)
|
2013-08-06 20:17:02 +08:00
|
|
|
{
|
2016-10-13 20:02:40 +08:00
|
|
|
gen6_pte_t pte = GEN6_PTE_VALID;
|
2013-08-06 20:17:02 +08:00
|
|
|
pte |= GEN6_PTE_ADDR_ENCODE(addr);
|
|
|
|
|
|
|
|
switch (level) {
|
|
|
|
case I915_CACHE_L3_LLC:
|
|
|
|
pte |= GEN7_PTE_CACHE_L3_LLC;
|
2012-10-20 00:33:22 +08:00
|
|
|
break;
|
|
|
|
case I915_CACHE_LLC:
|
|
|
|
pte |= GEN6_PTE_CACHE_LLC;
|
|
|
|
break;
|
|
|
|
case I915_CACHE_NONE:
|
2013-04-22 15:53:51 +08:00
|
|
|
pte |= GEN6_PTE_UNCACHED;
|
2012-10-20 00:33:22 +08:00
|
|
|
break;
|
|
|
|
default:
|
2014-12-08 23:40:10 +08:00
|
|
|
MISSING_CASE(level);
|
2012-10-20 00:33:22 +08:00
|
|
|
}
|
|
|
|
|
2012-09-25 07:44:32 +08:00
|
|
|
return pte;
|
|
|
|
}
|
|
|
|
|
2015-03-17 00:00:54 +08:00
|
|
|
static gen6_pte_t byt_pte_encode(dma_addr_t addr,
|
|
|
|
enum i915_cache_level level,
|
2016-10-13 20:02:40 +08:00
|
|
|
u32 flags)
|
2013-04-22 15:53:50 +08:00
|
|
|
{
|
2016-10-13 20:02:40 +08:00
|
|
|
gen6_pte_t pte = GEN6_PTE_VALID;
|
2013-04-22 15:53:50 +08:00
|
|
|
pte |= GEN6_PTE_ADDR_ENCODE(addr);
|
|
|
|
|
2014-06-17 13:29:42 +08:00
|
|
|
if (!(flags & PTE_READ_ONLY))
|
|
|
|
pte |= BYT_PTE_WRITEABLE;
|
2013-04-22 15:53:50 +08:00
|
|
|
|
|
|
|
if (level != I915_CACHE_NONE)
|
|
|
|
pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES;
|
|
|
|
|
|
|
|
return pte;
|
|
|
|
}
|
|
|
|
|
2015-03-17 00:00:54 +08:00
|
|
|
static gen6_pte_t hsw_pte_encode(dma_addr_t addr,
|
|
|
|
enum i915_cache_level level,
|
2016-10-13 20:02:40 +08:00
|
|
|
u32 unused)
|
2013-04-22 15:53:51 +08:00
|
|
|
{
|
2016-10-13 20:02:40 +08:00
|
|
|
gen6_pte_t pte = GEN6_PTE_VALID;
|
2013-07-05 02:02:03 +08:00
|
|
|
pte |= HSW_PTE_ADDR_ENCODE(addr);
|
2013-04-22 15:53:51 +08:00
|
|
|
|
|
|
|
if (level != I915_CACHE_NONE)
|
2013-08-05 14:47:29 +08:00
|
|
|
pte |= HSW_WB_LLC_AGE3;
|
2013-04-22 15:53:51 +08:00
|
|
|
|
|
|
|
return pte;
|
|
|
|
}
|
|
|
|
|
2015-03-17 00:00:54 +08:00
|
|
|
static gen6_pte_t iris_pte_encode(dma_addr_t addr,
|
|
|
|
enum i915_cache_level level,
|
2016-10-13 20:02:40 +08:00
|
|
|
u32 unused)
|
2013-07-05 02:02:06 +08:00
|
|
|
{
|
2016-10-13 20:02:40 +08:00
|
|
|
gen6_pte_t pte = GEN6_PTE_VALID;
|
2013-07-05 02:02:06 +08:00
|
|
|
pte |= HSW_PTE_ADDR_ENCODE(addr);
|
|
|
|
|
2013-08-08 21:41:10 +08:00
|
|
|
switch (level) {
|
|
|
|
case I915_CACHE_NONE:
|
|
|
|
break;
|
|
|
|
case I915_CACHE_WT:
|
2013-11-22 18:37:53 +08:00
|
|
|
pte |= HSW_WT_ELLC_LLC_AGE3;
|
2013-08-08 21:41:10 +08:00
|
|
|
break;
|
|
|
|
default:
|
2013-11-22 18:37:53 +08:00
|
|
|
pte |= HSW_WB_ELLC_LLC_AGE3;
|
2013-08-08 21:41:10 +08:00
|
|
|
break;
|
|
|
|
}
|
2013-07-05 02:02:06 +08:00
|
|
|
|
|
|
|
return pte;
|
|
|
|
}
|
|
|
|
|
2015-06-25 23:35:13 +08:00
|
|
|
static int __setup_page_dma(struct drm_device *dev,
|
|
|
|
struct i915_page_dma *p, gfp_t flags)
|
2015-03-17 00:00:56 +08:00
|
|
|
{
|
2016-08-22 18:32:42 +08:00
|
|
|
struct device *kdev = &dev->pdev->dev;
|
2015-03-17 00:00:56 +08:00
|
|
|
|
2015-06-25 23:35:13 +08:00
|
|
|
p->page = alloc_page(flags);
|
2015-06-25 23:35:07 +08:00
|
|
|
if (!p->page)
|
|
|
|
return -ENOMEM;
|
2015-03-17 00:00:56 +08:00
|
|
|
|
2016-08-22 18:32:42 +08:00
|
|
|
p->daddr = dma_map_page(kdev,
|
2015-06-25 23:35:07 +08:00
|
|
|
p->page, 0, 4096, PCI_DMA_BIDIRECTIONAL);
|
2015-03-17 00:00:56 +08:00
|
|
|
|
2016-08-22 18:32:42 +08:00
|
|
|
if (dma_mapping_error(kdev, p->daddr)) {
|
2015-06-25 23:35:07 +08:00
|
|
|
__free_page(p->page);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2015-03-25 01:06:33 +08:00
|
|
|
|
|
|
|
return 0;
|
2015-03-17 00:00:56 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 23:35:13 +08:00
|
|
|
static int setup_page_dma(struct drm_device *dev, struct i915_page_dma *p)
|
|
|
|
{
|
2016-08-22 15:44:31 +08:00
|
|
|
return __setup_page_dma(dev, p, I915_GFP_DMA);
|
2015-06-25 23:35:13 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 23:35:07 +08:00
|
|
|
static void cleanup_page_dma(struct drm_device *dev, struct i915_page_dma *p)
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
{
|
2016-08-22 18:32:44 +08:00
|
|
|
struct pci_dev *pdev = dev->pdev;
|
|
|
|
|
2015-06-25 23:35:07 +08:00
|
|
|
if (WARN_ON(!p->page))
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
return;
|
2015-03-17 00:00:56 +08:00
|
|
|
|
2016-08-22 18:32:44 +08:00
|
|
|
dma_unmap_page(&pdev->dev, p->daddr, 4096, PCI_DMA_BIDIRECTIONAL);
|
2015-06-25 23:35:07 +08:00
|
|
|
__free_page(p->page);
|
|
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
}
|
|
|
|
|
2015-06-25 23:35:11 +08:00
|
|
|
static void *kmap_page_dma(struct i915_page_dma *p)
|
2015-06-25 23:35:10 +08:00
|
|
|
{
|
2015-06-25 23:35:11 +08:00
|
|
|
return kmap_atomic(p->page);
|
|
|
|
}
|
2015-06-25 23:35:10 +08:00
|
|
|
|
2015-06-25 23:35:11 +08:00
|
|
|
/* We use the flushing unmap only with ppgtt structures:
|
|
|
|
* page directories, page tables and scratch pages.
|
|
|
|
*/
|
2016-10-13 18:03:04 +08:00
|
|
|
static void kunmap_page_dma(struct drm_i915_private *dev_priv, void *vaddr)
|
2015-06-25 23:35:11 +08:00
|
|
|
{
|
2015-06-25 23:35:10 +08:00
|
|
|
/* There are only few exceptions for gen >=6. chv and bxt.
|
|
|
|
* And we are not sure about the latter so play safe for now.
|
|
|
|
*/
|
2016-10-13 18:03:04 +08:00
|
|
|
if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv))
|
2015-06-25 23:35:10 +08:00
|
|
|
drm_clflush_virt_range(vaddr, PAGE_SIZE);
|
|
|
|
|
|
|
|
kunmap_atomic(vaddr);
|
|
|
|
}
|
|
|
|
|
2015-06-25 23:35:12 +08:00
|
|
|
#define kmap_px(px) kmap_page_dma(px_base(px))
|
2016-10-13 18:03:04 +08:00
|
|
|
#define kunmap_px(ppgtt, vaddr) \
|
|
|
|
kunmap_page_dma(to_i915((ppgtt)->base.dev), (vaddr))
|
2015-06-25 23:35:11 +08:00
|
|
|
|
2015-06-25 23:35:12 +08:00
|
|
|
#define setup_px(dev, px) setup_page_dma((dev), px_base(px))
|
|
|
|
#define cleanup_px(dev, px) cleanup_page_dma((dev), px_base(px))
|
2016-10-13 18:03:04 +08:00
|
|
|
#define fill_px(dev_priv, px, v) fill_page_dma((dev_priv), px_base(px), (v))
|
|
|
|
#define fill32_px(dev_priv, px, v) \
|
|
|
|
fill_page_dma_32((dev_priv), px_base(px), (v))
|
2015-06-25 23:35:12 +08:00
|
|
|
|
2016-10-13 18:03:04 +08:00
|
|
|
static void fill_page_dma(struct drm_i915_private *dev_priv,
|
|
|
|
struct i915_page_dma *p, const uint64_t val)
|
2015-06-25 23:35:11 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
uint64_t * const vaddr = kmap_page_dma(p);
|
|
|
|
|
|
|
|
for (i = 0; i < 512; i++)
|
|
|
|
vaddr[i] = val;
|
|
|
|
|
2016-10-13 18:03:04 +08:00
|
|
|
kunmap_page_dma(dev_priv, vaddr);
|
2015-06-25 23:35:11 +08:00
|
|
|
}
|
|
|
|
|
2016-10-13 18:03:04 +08:00
|
|
|
static void fill_page_dma_32(struct drm_i915_private *dev_priv,
|
|
|
|
struct i915_page_dma *p, const uint32_t val32)
|
2015-06-25 23:35:10 +08:00
|
|
|
{
|
|
|
|
uint64_t v = val32;
|
|
|
|
|
|
|
|
v = v << 32 | val32;
|
|
|
|
|
2016-10-13 18:03:04 +08:00
|
|
|
fill_page_dma(dev_priv, p, v);
|
2015-06-25 23:35:10 +08:00
|
|
|
}
|
|
|
|
|
2016-08-22 15:44:30 +08:00
|
|
|
static int
|
2016-08-22 15:44:31 +08:00
|
|
|
setup_scratch_page(struct drm_device *dev,
|
|
|
|
struct i915_page_dma *scratch,
|
|
|
|
gfp_t gfp)
|
2015-06-30 23:16:39 +08:00
|
|
|
{
|
2016-08-22 15:44:31 +08:00
|
|
|
return __setup_page_dma(dev, scratch, gfp | __GFP_ZERO);
|
2015-06-30 23:16:39 +08:00
|
|
|
}
|
|
|
|
|
2016-08-22 15:44:30 +08:00
|
|
|
static void cleanup_scratch_page(struct drm_device *dev,
|
|
|
|
struct i915_page_dma *scratch)
|
2015-06-30 23:16:39 +08:00
|
|
|
{
|
2016-08-22 15:44:30 +08:00
|
|
|
cleanup_page_dma(dev, scratch);
|
2015-06-30 23:16:39 +08:00
|
|
|
}
|
|
|
|
|
2015-05-23 01:04:59 +08:00
|
|
|
static struct i915_page_table *alloc_pt(struct drm_device *dev)
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
{
|
2015-04-08 19:13:23 +08:00
|
|
|
struct i915_page_table *pt;
|
2015-03-17 00:00:56 +08:00
|
|
|
const size_t count = INTEL_INFO(dev)->gen >= 8 ?
|
|
|
|
GEN8_PTES : GEN6_PTES;
|
|
|
|
int ret = -ENOMEM;
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
|
|
|
|
pt = kzalloc(sizeof(*pt), GFP_KERNEL);
|
|
|
|
if (!pt)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
2015-03-17 00:00:56 +08:00
|
|
|
pt->used_ptes = kcalloc(BITS_TO_LONGS(count), sizeof(*pt->used_ptes),
|
|
|
|
GFP_KERNEL);
|
|
|
|
|
|
|
|
if (!pt->used_ptes)
|
|
|
|
goto fail_bitmap;
|
|
|
|
|
2015-06-25 23:35:12 +08:00
|
|
|
ret = setup_px(dev, pt);
|
2015-03-17 00:00:56 +08:00
|
|
|
if (ret)
|
2015-06-25 23:35:07 +08:00
|
|
|
goto fail_page_m;
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
|
|
|
|
return pt;
|
2015-03-17 00:00:56 +08:00
|
|
|
|
2015-06-25 23:35:07 +08:00
|
|
|
fail_page_m:
|
2015-03-17 00:00:56 +08:00
|
|
|
kfree(pt->used_ptes);
|
|
|
|
fail_bitmap:
|
|
|
|
kfree(pt);
|
|
|
|
|
|
|
|
return ERR_PTR(ret);
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 23:16:37 +08:00
|
|
|
static void free_pt(struct drm_device *dev, struct i915_page_table *pt)
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
{
|
2015-06-30 23:16:37 +08:00
|
|
|
cleanup_px(dev, pt);
|
|
|
|
kfree(pt->used_ptes);
|
|
|
|
kfree(pt);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void gen8_initialize_pt(struct i915_address_space *vm,
|
|
|
|
struct i915_page_table *pt)
|
|
|
|
{
|
|
|
|
gen8_pte_t scratch_pte;
|
|
|
|
|
2016-08-22 15:44:30 +08:00
|
|
|
scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
|
2016-10-13 20:02:40 +08:00
|
|
|
I915_CACHE_LLC);
|
2015-06-30 23:16:37 +08:00
|
|
|
|
2016-10-13 18:03:04 +08:00
|
|
|
fill_px(to_i915(vm->dev), pt, scratch_pte);
|
2015-06-30 23:16:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void gen6_initialize_pt(struct i915_address_space *vm,
|
|
|
|
struct i915_page_table *pt)
|
|
|
|
{
|
|
|
|
gen6_pte_t scratch_pte;
|
|
|
|
|
2016-08-22 15:44:30 +08:00
|
|
|
WARN_ON(vm->scratch_page.daddr == 0);
|
2015-06-30 23:16:37 +08:00
|
|
|
|
2016-08-22 15:44:30 +08:00
|
|
|
scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
|
2016-10-13 20:02:40 +08:00
|
|
|
I915_CACHE_LLC, 0);
|
2015-06-30 23:16:37 +08:00
|
|
|
|
2016-10-13 18:03:04 +08:00
|
|
|
fill32_px(to_i915(vm->dev), pt, scratch_pte);
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
}
|
|
|
|
|
2015-05-23 01:04:59 +08:00
|
|
|
static struct i915_page_directory *alloc_pd(struct drm_device *dev)
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
{
|
2015-04-08 19:13:23 +08:00
|
|
|
struct i915_page_directory *pd;
|
2015-04-08 19:13:33 +08:00
|
|
|
int ret = -ENOMEM;
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
|
|
|
|
pd = kzalloc(sizeof(*pd), GFP_KERNEL);
|
|
|
|
if (!pd)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
2015-04-08 19:13:33 +08:00
|
|
|
pd->used_pdes = kcalloc(BITS_TO_LONGS(I915_PDES),
|
|
|
|
sizeof(*pd->used_pdes), GFP_KERNEL);
|
|
|
|
if (!pd->used_pdes)
|
2015-06-25 23:35:08 +08:00
|
|
|
goto fail_bitmap;
|
2015-04-08 19:13:33 +08:00
|
|
|
|
2015-06-25 23:35:12 +08:00
|
|
|
ret = setup_px(dev, pd);
|
2015-04-08 19:13:33 +08:00
|
|
|
if (ret)
|
2015-06-25 23:35:08 +08:00
|
|
|
goto fail_page_m;
|
2015-04-08 19:13:32 +08:00
|
|
|
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
return pd;
|
2015-04-08 19:13:33 +08:00
|
|
|
|
2015-06-25 23:35:08 +08:00
|
|
|
fail_page_m:
|
2015-04-08 19:13:33 +08:00
|
|
|
kfree(pd->used_pdes);
|
2015-06-25 23:35:08 +08:00
|
|
|
fail_bitmap:
|
2015-04-08 19:13:33 +08:00
|
|
|
kfree(pd);
|
|
|
|
|
|
|
|
return ERR_PTR(ret);
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 23:16:37 +08:00
|
|
|
static void free_pd(struct drm_device *dev, struct i915_page_directory *pd)
|
|
|
|
{
|
|
|
|
if (px_page(pd)) {
|
|
|
|
cleanup_px(dev, pd);
|
|
|
|
kfree(pd->used_pdes);
|
|
|
|
kfree(pd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void gen8_initialize_pd(struct i915_address_space *vm,
|
|
|
|
struct i915_page_directory *pd)
|
|
|
|
{
|
|
|
|
gen8_pde_t scratch_pde;
|
|
|
|
|
|
|
|
scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC);
|
|
|
|
|
2016-10-13 18:03:04 +08:00
|
|
|
fill_px(to_i915(vm->dev), pd, scratch_pde);
|
2015-06-30 23:16:37 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 00:23:46 +08:00
|
|
|
static int __pdp_init(struct drm_device *dev,
|
|
|
|
struct i915_page_directory_pointer *pdp)
|
|
|
|
{
|
|
|
|
size_t pdpes = I915_PDPES_PER_PDP(dev);
|
|
|
|
|
|
|
|
pdp->used_pdpes = kcalloc(BITS_TO_LONGS(pdpes),
|
|
|
|
sizeof(unsigned long),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!pdp->used_pdpes)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
pdp->page_directory = kcalloc(pdpes, sizeof(*pdp->page_directory),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!pdp->page_directory) {
|
|
|
|
kfree(pdp->used_pdpes);
|
|
|
|
/* the PDP might be the statically allocated top level. Keep it
|
|
|
|
* as clean as possible */
|
|
|
|
pdp->used_pdpes = NULL;
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __pdp_fini(struct i915_page_directory_pointer *pdp)
|
|
|
|
{
|
|
|
|
kfree(pdp->used_pdpes);
|
|
|
|
kfree(pdp->page_directory);
|
|
|
|
pdp->page_directory = NULL;
|
|
|
|
}
|
|
|
|
|
2015-07-30 18:05:29 +08:00
|
|
|
static struct
|
|
|
|
i915_page_directory_pointer *alloc_pdp(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct i915_page_directory_pointer *pdp;
|
|
|
|
int ret = -ENOMEM;
|
|
|
|
|
|
|
|
WARN_ON(!USES_FULL_48BIT_PPGTT(dev));
|
|
|
|
|
|
|
|
pdp = kzalloc(sizeof(*pdp), GFP_KERNEL);
|
|
|
|
if (!pdp)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
ret = __pdp_init(dev, pdp);
|
|
|
|
if (ret)
|
|
|
|
goto fail_bitmap;
|
|
|
|
|
|
|
|
ret = setup_px(dev, pdp);
|
|
|
|
if (ret)
|
|
|
|
goto fail_page_m;
|
|
|
|
|
|
|
|
return pdp;
|
|
|
|
|
|
|
|
fail_page_m:
|
|
|
|
__pdp_fini(pdp);
|
|
|
|
fail_bitmap:
|
|
|
|
kfree(pdp);
|
|
|
|
|
|
|
|
return ERR_PTR(ret);
|
|
|
|
}
|
|
|
|
|
2015-07-30 00:23:46 +08:00
|
|
|
static void free_pdp(struct drm_device *dev,
|
|
|
|
struct i915_page_directory_pointer *pdp)
|
|
|
|
{
|
|
|
|
__pdp_fini(pdp);
|
2015-07-30 18:05:29 +08:00
|
|
|
if (USES_FULL_48BIT_PPGTT(dev)) {
|
|
|
|
cleanup_px(dev, pdp);
|
|
|
|
kfree(pdp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-30 00:23:55 +08:00
|
|
|
static void gen8_initialize_pdp(struct i915_address_space *vm,
|
|
|
|
struct i915_page_directory_pointer *pdp)
|
|
|
|
{
|
|
|
|
gen8_ppgtt_pdpe_t scratch_pdpe;
|
|
|
|
|
|
|
|
scratch_pdpe = gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC);
|
|
|
|
|
2016-10-13 18:03:04 +08:00
|
|
|
fill_px(to_i915(vm->dev), pdp, scratch_pdpe);
|
2015-07-30 00:23:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void gen8_initialize_pml4(struct i915_address_space *vm,
|
|
|
|
struct i915_pml4 *pml4)
|
|
|
|
{
|
|
|
|
gen8_ppgtt_pml4e_t scratch_pml4e;
|
|
|
|
|
|
|
|
scratch_pml4e = gen8_pml4e_encode(px_dma(vm->scratch_pdp),
|
|
|
|
I915_CACHE_LLC);
|
|
|
|
|
2016-10-13 18:03:04 +08:00
|
|
|
fill_px(to_i915(vm->dev), pml4, scratch_pml4e);
|
2015-07-30 00:23:55 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 18:05:29 +08:00
|
|
|
static void
|
|
|
|
gen8_setup_page_directory(struct i915_hw_ppgtt *ppgtt,
|
|
|
|
struct i915_page_directory_pointer *pdp,
|
|
|
|
struct i915_page_directory *pd,
|
|
|
|
int index)
|
|
|
|
{
|
|
|
|
gen8_ppgtt_pdpe_t *page_directorypo;
|
|
|
|
|
|
|
|
if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
|
|
|
|
return;
|
|
|
|
|
|
|
|
page_directorypo = kmap_px(pdp);
|
|
|
|
page_directorypo[index] = gen8_pdpe_encode(px_dma(pd), I915_CACHE_LLC);
|
|
|
|
kunmap_px(ppgtt, page_directorypo);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gen8_setup_page_directory_pointer(struct i915_hw_ppgtt *ppgtt,
|
|
|
|
struct i915_pml4 *pml4,
|
|
|
|
struct i915_page_directory_pointer *pdp,
|
|
|
|
int index)
|
|
|
|
{
|
|
|
|
gen8_ppgtt_pml4e_t *pagemap = kmap_px(pml4);
|
|
|
|
|
|
|
|
WARN_ON(!USES_FULL_48BIT_PPGTT(ppgtt->base.dev));
|
|
|
|
pagemap[index] = gen8_pml4e_encode(px_dma(pdp), I915_CACHE_LLC);
|
|
|
|
kunmap_px(ppgtt, pagemap);
|
2015-07-30 00:23:46 +08:00
|
|
|
}
|
|
|
|
|
2013-11-05 14:29:36 +08:00
|
|
|
/* Broadwell Page Directory Pointer Descriptors */
|
2015-05-30 00:43:56 +08:00
|
|
|
static int gen8_write_pdp(struct drm_i915_gem_request *req,
|
2015-04-08 19:13:29 +08:00
|
|
|
unsigned entry,
|
|
|
|
dma_addr_t addr)
|
2013-11-05 14:29:36 +08:00
|
|
|
{
|
2016-08-03 05:50:21 +08:00
|
|
|
struct intel_ring *ring = req->ring;
|
2016-03-16 19:00:38 +08:00
|
|
|
struct intel_engine_cs *engine = req->engine;
|
2013-11-05 14:29:36 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
BUG_ON(entry >= 4);
|
|
|
|
|
2015-05-30 00:44:07 +08:00
|
|
|
ret = intel_ring_begin(req, 6);
|
2013-11-05 14:29:36 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2016-08-03 05:50:18 +08:00
|
|
|
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
|
|
|
intel_ring_emit_reg(ring, GEN8_RING_PDP_UDW(engine, entry));
|
|
|
|
intel_ring_emit(ring, upper_32_bits(addr));
|
|
|
|
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
|
|
|
intel_ring_emit_reg(ring, GEN8_RING_PDP_LDW(engine, entry));
|
|
|
|
intel_ring_emit(ring, lower_32_bits(addr));
|
|
|
|
intel_ring_advance(ring);
|
2013-11-05 14:29:36 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-30 18:06:23 +08:00
|
|
|
static int gen8_legacy_mm_switch(struct i915_hw_ppgtt *ppgtt,
|
|
|
|
struct drm_i915_gem_request *req)
|
2013-11-05 14:29:36 +08:00
|
|
|
{
|
2013-12-07 06:11:10 +08:00
|
|
|
int i, ret;
|
2013-11-05 14:29:36 +08:00
|
|
|
|
2015-04-08 19:13:29 +08:00
|
|
|
for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) {
|
2015-06-25 23:35:06 +08:00
|
|
|
const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
|
|
|
|
|
2015-05-30 00:43:56 +08:00
|
|
|
ret = gen8_write_pdp(req, i, pd_daddr);
|
2013-12-07 06:11:10 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2013-11-05 14:29:36 +08:00
|
|
|
}
|
2013-11-26 01:54:32 +08:00
|
|
|
|
2013-12-07 06:11:10 +08:00
|
|
|
return 0;
|
2013-11-05 14:29:36 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 18:06:23 +08:00
|
|
|
static int gen8_48b_mm_switch(struct i915_hw_ppgtt *ppgtt,
|
|
|
|
struct drm_i915_gem_request *req)
|
|
|
|
{
|
|
|
|
return gen8_write_pdp(req, 0, px_dma(&ppgtt->pml4));
|
|
|
|
}
|
|
|
|
|
2016-10-13 20:02:42 +08:00
|
|
|
/* Removes entries from a single page table, releasing it if it's empty.
|
|
|
|
* Caller can use the return value to update higher-level entries.
|
|
|
|
*/
|
|
|
|
static bool gen8_ppgtt_clear_pt(struct i915_address_space *vm,
|
2016-10-13 20:02:41 +08:00
|
|
|
struct i915_page_table *pt,
|
|
|
|
uint64_t start,
|
|
|
|
uint64_t length)
|
2013-11-03 12:07:23 +08:00
|
|
|
{
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2016-10-13 20:02:41 +08:00
|
|
|
unsigned int pte_start = gen8_pte_index(start);
|
|
|
|
unsigned int num_entries = gen8_pte_count(start, length);
|
|
|
|
uint64_t pte;
|
2015-07-30 18:02:49 +08:00
|
|
|
gen8_pte_t *pt_vaddr;
|
2016-10-13 20:02:41 +08:00
|
|
|
gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
|
|
|
|
I915_CACHE_LLC);
|
2013-11-03 12:07:23 +08:00
|
|
|
|
2016-10-13 20:02:41 +08:00
|
|
|
if (WARN_ON(!px_page(pt)))
|
2016-10-13 20:02:42 +08:00
|
|
|
return false;
|
2013-11-03 12:07:23 +08:00
|
|
|
|
2016-10-13 20:02:41 +08:00
|
|
|
bitmap_clear(pt->used_ptes, pte_start, num_entries);
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
|
2016-10-13 20:02:42 +08:00
|
|
|
if (bitmap_empty(pt->used_ptes, GEN8_PTES)) {
|
|
|
|
free_pt(vm->dev, pt);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-10-13 20:02:41 +08:00
|
|
|
pt_vaddr = kmap_px(pt);
|
|
|
|
|
|
|
|
for (pte = pte_start; pte < num_entries; pte++)
|
|
|
|
pt_vaddr[pte] = scratch_pte;
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
|
2016-10-13 20:02:41 +08:00
|
|
|
kunmap_px(ppgtt, pt_vaddr);
|
2016-10-13 20:02:42 +08:00
|
|
|
|
|
|
|
return false;
|
2016-10-13 20:02:41 +08:00
|
|
|
}
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
|
2016-10-13 20:02:42 +08:00
|
|
|
/* Removes entries from a single page dir, releasing it if it's empty.
|
|
|
|
* Caller can use the return value to update higher-level entries
|
|
|
|
*/
|
|
|
|
static bool gen8_ppgtt_clear_pd(struct i915_address_space *vm,
|
2016-10-13 20:02:41 +08:00
|
|
|
struct i915_page_directory *pd,
|
|
|
|
uint64_t start,
|
|
|
|
uint64_t length)
|
|
|
|
{
|
2016-10-13 20:02:42 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2016-10-13 20:02:41 +08:00
|
|
|
struct i915_page_table *pt;
|
|
|
|
uint64_t pde;
|
2016-10-13 20:02:42 +08:00
|
|
|
gen8_pde_t *pde_vaddr;
|
|
|
|
gen8_pde_t scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt),
|
|
|
|
I915_CACHE_LLC);
|
2016-10-13 20:02:41 +08:00
|
|
|
|
|
|
|
gen8_for_each_pde(pt, pd, start, length, pde) {
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
if (WARN_ON(!pd->page_table[pde]))
|
2015-06-25 19:59:38 +08:00
|
|
|
break;
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
|
2016-10-13 20:02:42 +08:00
|
|
|
if (gen8_ppgtt_clear_pt(vm, pt, start, length)) {
|
|
|
|
__clear_bit(pde, pd->used_pdes);
|
|
|
|
pde_vaddr = kmap_px(pd);
|
|
|
|
pde_vaddr[pde] = scratch_pde;
|
|
|
|
kunmap_px(ppgtt, pde_vaddr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bitmap_empty(pd->used_pdes, I915_PDES)) {
|
|
|
|
free_pd(vm->dev, pd);
|
|
|
|
return true;
|
2016-10-13 20:02:41 +08:00
|
|
|
}
|
2016-10-13 20:02:42 +08:00
|
|
|
|
|
|
|
return false;
|
2016-10-13 20:02:41 +08:00
|
|
|
}
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
|
2016-10-13 20:02:42 +08:00
|
|
|
/* Removes entries from a single page dir pointer, releasing it if it's empty.
|
|
|
|
* Caller can use the return value to update higher-level entries
|
|
|
|
*/
|
|
|
|
static bool gen8_ppgtt_clear_pdp(struct i915_address_space *vm,
|
2016-10-13 20:02:41 +08:00
|
|
|
struct i915_page_directory_pointer *pdp,
|
|
|
|
uint64_t start,
|
|
|
|
uint64_t length)
|
|
|
|
{
|
2016-10-13 20:02:42 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2016-10-13 20:02:41 +08:00
|
|
|
struct i915_page_directory *pd;
|
|
|
|
uint64_t pdpe;
|
2016-10-13 20:02:42 +08:00
|
|
|
gen8_ppgtt_pdpe_t *pdpe_vaddr;
|
|
|
|
gen8_ppgtt_pdpe_t scratch_pdpe =
|
|
|
|
gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC);
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
|
2016-10-13 20:02:41 +08:00
|
|
|
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
|
|
|
if (WARN_ON(!pdp->page_directory[pdpe]))
|
|
|
|
break;
|
2013-11-03 12:07:23 +08:00
|
|
|
|
2016-10-13 20:02:42 +08:00
|
|
|
if (gen8_ppgtt_clear_pd(vm, pd, start, length)) {
|
|
|
|
__clear_bit(pdpe, pdp->used_pdpes);
|
|
|
|
if (USES_FULL_48BIT_PPGTT(vm->dev)) {
|
|
|
|
pdpe_vaddr = kmap_px(pdp);
|
|
|
|
pdpe_vaddr[pdpe] = scratch_pdpe;
|
|
|
|
kunmap_px(ppgtt, pdpe_vaddr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (USES_FULL_48BIT_PPGTT(vm->dev) &&
|
|
|
|
bitmap_empty(pdp->used_pdpes, I915_PDPES_PER_PDP(vm->dev))) {
|
|
|
|
free_pdp(vm->dev, pdp);
|
|
|
|
return true;
|
2016-10-13 20:02:41 +08:00
|
|
|
}
|
2016-10-13 20:02:42 +08:00
|
|
|
|
|
|
|
return false;
|
2016-10-13 20:02:41 +08:00
|
|
|
}
|
2013-11-03 12:07:23 +08:00
|
|
|
|
2016-10-13 20:02:42 +08:00
|
|
|
/* Removes entries from a single pml4.
|
|
|
|
* This is the top-level structure in 4-level page tables used on gen8+.
|
|
|
|
* Empty entries are always scratch pml4e.
|
|
|
|
*/
|
2016-10-13 20:02:41 +08:00
|
|
|
static void gen8_ppgtt_clear_pml4(struct i915_address_space *vm,
|
|
|
|
struct i915_pml4 *pml4,
|
|
|
|
uint64_t start,
|
|
|
|
uint64_t length)
|
|
|
|
{
|
2016-10-13 20:02:42 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2016-10-13 20:02:41 +08:00
|
|
|
struct i915_page_directory_pointer *pdp;
|
|
|
|
uint64_t pml4e;
|
2016-10-13 20:02:42 +08:00
|
|
|
gen8_ppgtt_pml4e_t *pml4e_vaddr;
|
|
|
|
gen8_ppgtt_pml4e_t scratch_pml4e =
|
|
|
|
gen8_pml4e_encode(px_dma(vm->scratch_pdp), I915_CACHE_LLC);
|
|
|
|
|
|
|
|
GEM_BUG_ON(!USES_FULL_48BIT_PPGTT(vm->dev));
|
2013-11-03 12:07:23 +08:00
|
|
|
|
2016-10-13 20:02:41 +08:00
|
|
|
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
|
|
|
|
if (WARN_ON(!pml4->pdps[pml4e]))
|
|
|
|
break;
|
2013-11-03 12:07:23 +08:00
|
|
|
|
2016-10-13 20:02:42 +08:00
|
|
|
if (gen8_ppgtt_clear_pdp(vm, pdp, start, length)) {
|
|
|
|
__clear_bit(pml4e, pml4->used_pml4es);
|
|
|
|
pml4e_vaddr = kmap_px(pml4);
|
|
|
|
pml4e_vaddr[pml4e] = scratch_pml4e;
|
|
|
|
kunmap_px(ppgtt, pml4e_vaddr);
|
|
|
|
}
|
2013-11-03 12:07:23 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-30 18:02:49 +08:00
|
|
|
static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
|
2016-10-13 20:02:40 +08:00
|
|
|
uint64_t start, uint64_t length)
|
2013-11-03 12:07:24 +08:00
|
|
|
{
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2015-07-30 18:02:49 +08:00
|
|
|
|
2016-10-13 20:02:41 +08:00
|
|
|
if (USES_FULL_48BIT_PPGTT(vm->dev))
|
|
|
|
gen8_ppgtt_clear_pml4(vm, &ppgtt->pml4, start, length);
|
|
|
|
else
|
|
|
|
gen8_ppgtt_clear_pdp(vm, &ppgtt->pdp, start, length);
|
2015-07-30 18:02:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm,
|
|
|
|
struct i915_page_directory_pointer *pdp,
|
2015-08-03 16:52:47 +08:00
|
|
|
struct sg_page_iter *sg_iter,
|
2015-07-30 18:02:49 +08:00
|
|
|
uint64_t start,
|
|
|
|
enum i915_cache_level cache_level)
|
|
|
|
{
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2015-03-17 00:00:54 +08:00
|
|
|
gen8_pte_t *pt_vaddr;
|
2015-08-03 16:53:27 +08:00
|
|
|
unsigned pdpe = gen8_pdpe_index(start);
|
|
|
|
unsigned pde = gen8_pde_index(start);
|
|
|
|
unsigned pte = gen8_pte_index(start);
|
2013-11-03 12:07:24 +08:00
|
|
|
|
2013-12-31 23:50:31 +08:00
|
|
|
pt_vaddr = NULL;
|
drm/i915/bdw: Reorganize PT allocations
The previous allocation mechanism would get 2 contiguous allocations,
one for the page directories, and one for the page tables. As each page
table is 1 page, and there are 512 of these per page directory, this
goes to 2MB. An unfriendly request at best. Worse still, our HW now
supports 4 page directories, and a 2MB allocation is not allowed.
In order to fix this, this patch attempts to split up each page table
allocation into a single, discrete allocation. There is nothing really
fancy about the patch itself, it just has to manage an extra pointer
indirection, and have a fancier bit of logic to free up the pages.
To accommodate some of the added complexity, two new helpers are
introduced to allocate, and free the page table pages.
NOTE: I really wanted to split the way we do allocations, and the way in
which we identify the page table/page directory being used. I found
splitting this functionality up to be too unwieldy. I apologize in
advance to the reviewer. I'd recommend looking at the result, rather
than the diff.
v2/NOTE2: This patch predated commit:
6f1cc993518462ccf039e195fabd47e7aa5bfd13
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue Dec 31 15:50:31 2013 +0000
drm/i915: Avoid dereference past end of page arr
It fixed the same issue as that patch, but because of the limbo state of
PPGTT, Chris patch was merged instead. The excess churn is a result of
my using my original patch, which has my preferred naming. Primarily
act_* is changed to which_*, but it's mostly the same otherwise. I've
kept the convention Chris used for the pte wrap (I had something
slightly different, and broken - but fixable)
v3: Rename which_p[..]e to drop which_ (Chris)
Remove BUG_ON in inner loop (Chris)
Redo the pde/pdpe wrap logic (Chris)
v4: s/1MB/2MB in commit message (Imre)
Plug leaking gen8_pt_pages in both the error path, as well as general
free case (Imre)
v5: Rename leftover "which_" variables (Imre)
Add the pde = 0 wrap that was missed from v3 (Imre)
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
[danvet: Squash in fixup from Ben.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-02-21 03:51:21 +08:00
|
|
|
|
2015-08-03 16:52:47 +08:00
|
|
|
while (__sg_page_iter_next(sg_iter)) {
|
2015-02-25 00:22:34 +08:00
|
|
|
if (pt_vaddr == NULL) {
|
2015-07-30 18:02:03 +08:00
|
|
|
struct i915_page_directory *pd = pdp->page_directory[pdpe];
|
2015-04-08 19:13:23 +08:00
|
|
|
struct i915_page_table *pt = pd->page_table[pde];
|
2015-06-25 23:35:11 +08:00
|
|
|
pt_vaddr = kmap_px(pt);
|
2015-02-25 00:22:34 +08:00
|
|
|
}
|
2013-11-03 12:07:24 +08:00
|
|
|
|
drm/i915/bdw: Reorganize PT allocations
The previous allocation mechanism would get 2 contiguous allocations,
one for the page directories, and one for the page tables. As each page
table is 1 page, and there are 512 of these per page directory, this
goes to 2MB. An unfriendly request at best. Worse still, our HW now
supports 4 page directories, and a 2MB allocation is not allowed.
In order to fix this, this patch attempts to split up each page table
allocation into a single, discrete allocation. There is nothing really
fancy about the patch itself, it just has to manage an extra pointer
indirection, and have a fancier bit of logic to free up the pages.
To accommodate some of the added complexity, two new helpers are
introduced to allocate, and free the page table pages.
NOTE: I really wanted to split the way we do allocations, and the way in
which we identify the page table/page directory being used. I found
splitting this functionality up to be too unwieldy. I apologize in
advance to the reviewer. I'd recommend looking at the result, rather
than the diff.
v2/NOTE2: This patch predated commit:
6f1cc993518462ccf039e195fabd47e7aa5bfd13
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue Dec 31 15:50:31 2013 +0000
drm/i915: Avoid dereference past end of page arr
It fixed the same issue as that patch, but because of the limbo state of
PPGTT, Chris patch was merged instead. The excess churn is a result of
my using my original patch, which has my preferred naming. Primarily
act_* is changed to which_*, but it's mostly the same otherwise. I've
kept the convention Chris used for the pte wrap (I had something
slightly different, and broken - but fixable)
v3: Rename which_p[..]e to drop which_ (Chris)
Remove BUG_ON in inner loop (Chris)
Redo the pde/pdpe wrap logic (Chris)
v4: s/1MB/2MB in commit message (Imre)
Plug leaking gen8_pt_pages in both the error path, as well as general
free case (Imre)
v5: Rename leftover "which_" variables (Imre)
Add the pde = 0 wrap that was missed from v3 (Imre)
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
[danvet: Squash in fixup from Ben.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-02-21 03:51:21 +08:00
|
|
|
pt_vaddr[pte] =
|
2015-08-03 16:52:47 +08:00
|
|
|
gen8_pte_encode(sg_page_iter_dma_address(sg_iter),
|
2016-10-13 20:02:40 +08:00
|
|
|
cache_level);
|
2015-03-17 00:00:54 +08:00
|
|
|
if (++pte == GEN8_PTES) {
|
2015-06-25 23:35:11 +08:00
|
|
|
kunmap_px(ppgtt, pt_vaddr);
|
2013-12-31 23:50:31 +08:00
|
|
|
pt_vaddr = NULL;
|
2015-03-17 00:00:54 +08:00
|
|
|
if (++pde == I915_PDES) {
|
2015-08-03 16:53:27 +08:00
|
|
|
if (++pdpe == I915_PDPES_PER_PDP(vm->dev))
|
|
|
|
break;
|
drm/i915/bdw: Reorganize PT allocations
The previous allocation mechanism would get 2 contiguous allocations,
one for the page directories, and one for the page tables. As each page
table is 1 page, and there are 512 of these per page directory, this
goes to 2MB. An unfriendly request at best. Worse still, our HW now
supports 4 page directories, and a 2MB allocation is not allowed.
In order to fix this, this patch attempts to split up each page table
allocation into a single, discrete allocation. There is nothing really
fancy about the patch itself, it just has to manage an extra pointer
indirection, and have a fancier bit of logic to free up the pages.
To accommodate some of the added complexity, two new helpers are
introduced to allocate, and free the page table pages.
NOTE: I really wanted to split the way we do allocations, and the way in
which we identify the page table/page directory being used. I found
splitting this functionality up to be too unwieldy. I apologize in
advance to the reviewer. I'd recommend looking at the result, rather
than the diff.
v2/NOTE2: This patch predated commit:
6f1cc993518462ccf039e195fabd47e7aa5bfd13
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue Dec 31 15:50:31 2013 +0000
drm/i915: Avoid dereference past end of page arr
It fixed the same issue as that patch, but because of the limbo state of
PPGTT, Chris patch was merged instead. The excess churn is a result of
my using my original patch, which has my preferred naming. Primarily
act_* is changed to which_*, but it's mostly the same otherwise. I've
kept the convention Chris used for the pte wrap (I had something
slightly different, and broken - but fixable)
v3: Rename which_p[..]e to drop which_ (Chris)
Remove BUG_ON in inner loop (Chris)
Redo the pde/pdpe wrap logic (Chris)
v4: s/1MB/2MB in commit message (Imre)
Plug leaking gen8_pt_pages in both the error path, as well as general
free case (Imre)
v5: Rename leftover "which_" variables (Imre)
Add the pde = 0 wrap that was missed from v3 (Imre)
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
[danvet: Squash in fixup from Ben.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-02-21 03:51:21 +08:00
|
|
|
pde = 0;
|
|
|
|
}
|
|
|
|
pte = 0;
|
2013-11-03 12:07:24 +08:00
|
|
|
}
|
|
|
|
}
|
2015-06-25 23:35:11 +08:00
|
|
|
|
|
|
|
if (pt_vaddr)
|
|
|
|
kunmap_px(ppgtt, pt_vaddr);
|
2013-11-03 12:07:24 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 18:02:49 +08:00
|
|
|
static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
|
|
|
|
struct sg_table *pages,
|
|
|
|
uint64_t start,
|
|
|
|
enum i915_cache_level cache_level,
|
|
|
|
u32 unused)
|
|
|
|
{
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2015-08-03 16:52:47 +08:00
|
|
|
struct sg_page_iter sg_iter;
|
2015-07-30 18:02:49 +08:00
|
|
|
|
2015-08-03 16:52:47 +08:00
|
|
|
__sg_page_iter_start(&sg_iter, pages->sgl, sg_nents(pages->sgl), 0);
|
2015-08-03 16:53:27 +08:00
|
|
|
|
|
|
|
if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
|
|
|
|
gen8_ppgtt_insert_pte_entries(vm, &ppgtt->pdp, &sg_iter, start,
|
|
|
|
cache_level);
|
|
|
|
} else {
|
|
|
|
struct i915_page_directory_pointer *pdp;
|
2015-12-08 21:30:51 +08:00
|
|
|
uint64_t pml4e;
|
2015-08-03 16:53:27 +08:00
|
|
|
uint64_t length = (uint64_t)pages->orig_nents << PAGE_SHIFT;
|
|
|
|
|
2015-12-08 21:30:51 +08:00
|
|
|
gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
|
2015-08-03 16:53:27 +08:00
|
|
|
gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter,
|
|
|
|
start, cache_level);
|
|
|
|
}
|
|
|
|
}
|
2015-07-30 18:02:49 +08:00
|
|
|
}
|
|
|
|
|
2015-06-11 00:46:39 +08:00
|
|
|
static void gen8_free_page_tables(struct drm_device *dev,
|
|
|
|
struct i915_page_directory *pd)
|
drm/i915/bdw: Reorganize PT allocations
The previous allocation mechanism would get 2 contiguous allocations,
one for the page directories, and one for the page tables. As each page
table is 1 page, and there are 512 of these per page directory, this
goes to 2MB. An unfriendly request at best. Worse still, our HW now
supports 4 page directories, and a 2MB allocation is not allowed.
In order to fix this, this patch attempts to split up each page table
allocation into a single, discrete allocation. There is nothing really
fancy about the patch itself, it just has to manage an extra pointer
indirection, and have a fancier bit of logic to free up the pages.
To accommodate some of the added complexity, two new helpers are
introduced to allocate, and free the page table pages.
NOTE: I really wanted to split the way we do allocations, and the way in
which we identify the page table/page directory being used. I found
splitting this functionality up to be too unwieldy. I apologize in
advance to the reviewer. I'd recommend looking at the result, rather
than the diff.
v2/NOTE2: This patch predated commit:
6f1cc993518462ccf039e195fabd47e7aa5bfd13
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue Dec 31 15:50:31 2013 +0000
drm/i915: Avoid dereference past end of page arr
It fixed the same issue as that patch, but because of the limbo state of
PPGTT, Chris patch was merged instead. The excess churn is a result of
my using my original patch, which has my preferred naming. Primarily
act_* is changed to which_*, but it's mostly the same otherwise. I've
kept the convention Chris used for the pte wrap (I had something
slightly different, and broken - but fixable)
v3: Rename which_p[..]e to drop which_ (Chris)
Remove BUG_ON in inner loop (Chris)
Redo the pde/pdpe wrap logic (Chris)
v4: s/1MB/2MB in commit message (Imre)
Plug leaking gen8_pt_pages in both the error path, as well as general
free case (Imre)
v5: Rename leftover "which_" variables (Imre)
Add the pde = 0 wrap that was missed from v3 (Imre)
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
[danvet: Squash in fixup from Ben.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-02-21 03:51:21 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2015-06-25 23:35:12 +08:00
|
|
|
if (!px_page(pd))
|
drm/i915/bdw: Reorganize PT allocations
The previous allocation mechanism would get 2 contiguous allocations,
one for the page directories, and one for the page tables. As each page
table is 1 page, and there are 512 of these per page directory, this
goes to 2MB. An unfriendly request at best. Worse still, our HW now
supports 4 page directories, and a 2MB allocation is not allowed.
In order to fix this, this patch attempts to split up each page table
allocation into a single, discrete allocation. There is nothing really
fancy about the patch itself, it just has to manage an extra pointer
indirection, and have a fancier bit of logic to free up the pages.
To accommodate some of the added complexity, two new helpers are
introduced to allocate, and free the page table pages.
NOTE: I really wanted to split the way we do allocations, and the way in
which we identify the page table/page directory being used. I found
splitting this functionality up to be too unwieldy. I apologize in
advance to the reviewer. I'd recommend looking at the result, rather
than the diff.
v2/NOTE2: This patch predated commit:
6f1cc993518462ccf039e195fabd47e7aa5bfd13
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue Dec 31 15:50:31 2013 +0000
drm/i915: Avoid dereference past end of page arr
It fixed the same issue as that patch, but because of the limbo state of
PPGTT, Chris patch was merged instead. The excess churn is a result of
my using my original patch, which has my preferred naming. Primarily
act_* is changed to which_*, but it's mostly the same otherwise. I've
kept the convention Chris used for the pte wrap (I had something
slightly different, and broken - but fixable)
v3: Rename which_p[..]e to drop which_ (Chris)
Remove BUG_ON in inner loop (Chris)
Redo the pde/pdpe wrap logic (Chris)
v4: s/1MB/2MB in commit message (Imre)
Plug leaking gen8_pt_pages in both the error path, as well as general
free case (Imre)
v5: Rename leftover "which_" variables (Imre)
Add the pde = 0 wrap that was missed from v3 (Imre)
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
[danvet: Squash in fixup from Ben.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-02-21 03:51:21 +08:00
|
|
|
return;
|
|
|
|
|
2015-04-08 19:13:33 +08:00
|
|
|
for_each_set_bit(i, pd->used_pdes, I915_PDES) {
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
if (WARN_ON(!pd->page_table[i]))
|
|
|
|
continue;
|
drm/i915/bdw: Reorganize PT allocations
The previous allocation mechanism would get 2 contiguous allocations,
one for the page directories, and one for the page tables. As each page
table is 1 page, and there are 512 of these per page directory, this
goes to 2MB. An unfriendly request at best. Worse still, our HW now
supports 4 page directories, and a 2MB allocation is not allowed.
In order to fix this, this patch attempts to split up each page table
allocation into a single, discrete allocation. There is nothing really
fancy about the patch itself, it just has to manage an extra pointer
indirection, and have a fancier bit of logic to free up the pages.
To accommodate some of the added complexity, two new helpers are
introduced to allocate, and free the page table pages.
NOTE: I really wanted to split the way we do allocations, and the way in
which we identify the page table/page directory being used. I found
splitting this functionality up to be too unwieldy. I apologize in
advance to the reviewer. I'd recommend looking at the result, rather
than the diff.
v2/NOTE2: This patch predated commit:
6f1cc993518462ccf039e195fabd47e7aa5bfd13
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue Dec 31 15:50:31 2013 +0000
drm/i915: Avoid dereference past end of page arr
It fixed the same issue as that patch, but because of the limbo state of
PPGTT, Chris patch was merged instead. The excess churn is a result of
my using my original patch, which has my preferred naming. Primarily
act_* is changed to which_*, but it's mostly the same otherwise. I've
kept the convention Chris used for the pte wrap (I had something
slightly different, and broken - but fixable)
v3: Rename which_p[..]e to drop which_ (Chris)
Remove BUG_ON in inner loop (Chris)
Redo the pde/pdpe wrap logic (Chris)
v4: s/1MB/2MB in commit message (Imre)
Plug leaking gen8_pt_pages in both the error path, as well as general
free case (Imre)
v5: Rename leftover "which_" variables (Imre)
Add the pde = 0 wrap that was missed from v3 (Imre)
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
[danvet: Squash in fixup from Ben.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-02-21 03:51:21 +08:00
|
|
|
|
2015-06-25 23:35:08 +08:00
|
|
|
free_pt(dev, pd->page_table[i]);
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
pd->page_table[i] = NULL;
|
|
|
|
}
|
2015-02-25 00:22:34 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 23:16:40 +08:00
|
|
|
static int gen8_init_scratch(struct i915_address_space *vm)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = vm->dev;
|
2016-04-27 20:19:25 +08:00
|
|
|
int ret;
|
2015-06-30 23:16:40 +08:00
|
|
|
|
2016-08-22 15:44:31 +08:00
|
|
|
ret = setup_scratch_page(dev, &vm->scratch_page, I915_GFP_DMA);
|
2016-08-22 15:44:30 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2015-06-30 23:16:40 +08:00
|
|
|
|
|
|
|
vm->scratch_pt = alloc_pt(dev);
|
|
|
|
if (IS_ERR(vm->scratch_pt)) {
|
2016-04-27 20:19:25 +08:00
|
|
|
ret = PTR_ERR(vm->scratch_pt);
|
|
|
|
goto free_scratch_page;
|
2015-06-30 23:16:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
vm->scratch_pd = alloc_pd(dev);
|
|
|
|
if (IS_ERR(vm->scratch_pd)) {
|
2016-04-27 20:19:25 +08:00
|
|
|
ret = PTR_ERR(vm->scratch_pd);
|
|
|
|
goto free_pt;
|
2015-06-30 23:16:40 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 00:23:55 +08:00
|
|
|
if (USES_FULL_48BIT_PPGTT(dev)) {
|
|
|
|
vm->scratch_pdp = alloc_pdp(dev);
|
|
|
|
if (IS_ERR(vm->scratch_pdp)) {
|
2016-04-27 20:19:25 +08:00
|
|
|
ret = PTR_ERR(vm->scratch_pdp);
|
|
|
|
goto free_pd;
|
2015-07-30 00:23:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-30 23:16:40 +08:00
|
|
|
gen8_initialize_pt(vm, vm->scratch_pt);
|
|
|
|
gen8_initialize_pd(vm, vm->scratch_pd);
|
2015-07-30 00:23:55 +08:00
|
|
|
if (USES_FULL_48BIT_PPGTT(dev))
|
|
|
|
gen8_initialize_pdp(vm, vm->scratch_pdp);
|
2015-06-30 23:16:40 +08:00
|
|
|
|
|
|
|
return 0;
|
2016-04-27 20:19:25 +08:00
|
|
|
|
|
|
|
free_pd:
|
|
|
|
free_pd(dev, vm->scratch_pd);
|
|
|
|
free_pt:
|
|
|
|
free_pt(dev, vm->scratch_pt);
|
|
|
|
free_scratch_page:
|
2016-08-22 15:44:30 +08:00
|
|
|
cleanup_scratch_page(dev, &vm->scratch_page);
|
2016-04-27 20:19:25 +08:00
|
|
|
|
|
|
|
return ret;
|
2015-06-30 23:16:40 +08:00
|
|
|
}
|
|
|
|
|
2015-08-28 15:41:18 +08:00
|
|
|
static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create)
|
|
|
|
{
|
|
|
|
enum vgt_g2v_type msg;
|
2016-04-22 19:09:25 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
|
2015-08-28 15:41:18 +08:00
|
|
|
int i;
|
|
|
|
|
2016-04-22 19:09:25 +08:00
|
|
|
if (USES_FULL_48BIT_PPGTT(dev_priv)) {
|
2015-08-28 15:41:18 +08:00
|
|
|
u64 daddr = px_dma(&ppgtt->pml4);
|
|
|
|
|
2015-11-05 05:20:12 +08:00
|
|
|
I915_WRITE(vgtif_reg(pdp[0].lo), lower_32_bits(daddr));
|
|
|
|
I915_WRITE(vgtif_reg(pdp[0].hi), upper_32_bits(daddr));
|
2015-08-28 15:41:18 +08:00
|
|
|
|
|
|
|
msg = (create ? VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE :
|
|
|
|
VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY);
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < GEN8_LEGACY_PDPES; i++) {
|
|
|
|
u64 daddr = i915_page_dir_dma_addr(ppgtt, i);
|
|
|
|
|
2015-11-05 05:20:12 +08:00
|
|
|
I915_WRITE(vgtif_reg(pdp[i].lo), lower_32_bits(daddr));
|
|
|
|
I915_WRITE(vgtif_reg(pdp[i].hi), upper_32_bits(daddr));
|
2015-08-28 15:41:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
msg = (create ? VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE :
|
|
|
|
VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY);
|
|
|
|
}
|
|
|
|
|
|
|
|
I915_WRITE(vgtif_reg(g2v_notify), msg);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-06-30 23:16:40 +08:00
|
|
|
static void gen8_free_scratch(struct i915_address_space *vm)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = vm->dev;
|
|
|
|
|
2015-07-30 00:23:55 +08:00
|
|
|
if (USES_FULL_48BIT_PPGTT(dev))
|
|
|
|
free_pdp(dev, vm->scratch_pdp);
|
2015-06-30 23:16:40 +08:00
|
|
|
free_pd(dev, vm->scratch_pd);
|
|
|
|
free_pt(dev, vm->scratch_pt);
|
2016-08-22 15:44:30 +08:00
|
|
|
cleanup_scratch_page(dev, &vm->scratch_page);
|
2015-06-30 23:16:40 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 18:05:29 +08:00
|
|
|
static void gen8_ppgtt_cleanup_3lvl(struct drm_device *dev,
|
|
|
|
struct i915_page_directory_pointer *pdp)
|
2014-02-13 06:28:44 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2015-07-30 18:02:03 +08:00
|
|
|
for_each_set_bit(i, pdp->used_pdpes, I915_PDPES_PER_PDP(dev)) {
|
|
|
|
if (WARN_ON(!pdp->page_directory[i]))
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
continue;
|
|
|
|
|
2015-07-30 18:02:03 +08:00
|
|
|
gen8_free_page_tables(dev, pdp->page_directory[i]);
|
|
|
|
free_pd(dev, pdp->page_directory[i]);
|
drm/i915/bdw: Reorganize PT allocations
The previous allocation mechanism would get 2 contiguous allocations,
one for the page directories, and one for the page tables. As each page
table is 1 page, and there are 512 of these per page directory, this
goes to 2MB. An unfriendly request at best. Worse still, our HW now
supports 4 page directories, and a 2MB allocation is not allowed.
In order to fix this, this patch attempts to split up each page table
allocation into a single, discrete allocation. There is nothing really
fancy about the patch itself, it just has to manage an extra pointer
indirection, and have a fancier bit of logic to free up the pages.
To accommodate some of the added complexity, two new helpers are
introduced to allocate, and free the page table pages.
NOTE: I really wanted to split the way we do allocations, and the way in
which we identify the page table/page directory being used. I found
splitting this functionality up to be too unwieldy. I apologize in
advance to the reviewer. I'd recommend looking at the result, rather
than the diff.
v2/NOTE2: This patch predated commit:
6f1cc993518462ccf039e195fabd47e7aa5bfd13
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue Dec 31 15:50:31 2013 +0000
drm/i915: Avoid dereference past end of page arr
It fixed the same issue as that patch, but because of the limbo state of
PPGTT, Chris patch was merged instead. The excess churn is a result of
my using my original patch, which has my preferred naming. Primarily
act_* is changed to which_*, but it's mostly the same otherwise. I've
kept the convention Chris used for the pte wrap (I had something
slightly different, and broken - but fixable)
v3: Rename which_p[..]e to drop which_ (Chris)
Remove BUG_ON in inner loop (Chris)
Redo the pde/pdpe wrap logic (Chris)
v4: s/1MB/2MB in commit message (Imre)
Plug leaking gen8_pt_pages in both the error path, as well as general
free case (Imre)
v5: Rename leftover "which_" variables (Imre)
Add the pde = 0 wrap that was missed from v3 (Imre)
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
[danvet: Squash in fixup from Ben.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-02-21 03:51:21 +08:00
|
|
|
}
|
2015-04-08 19:13:27 +08:00
|
|
|
|
2015-07-30 18:02:03 +08:00
|
|
|
free_pdp(dev, pdp);
|
2015-07-30 18:05:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void gen8_ppgtt_cleanup_4lvl(struct i915_hw_ppgtt *ppgtt)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for_each_set_bit(i, ppgtt->pml4.used_pml4es, GEN8_PML4ES_PER_PML4) {
|
|
|
|
if (WARN_ON(!ppgtt->pml4.pdps[i]))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, ppgtt->pml4.pdps[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup_px(ppgtt->base.dev, &ppgtt->pml4);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
|
|
|
|
{
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2015-07-30 18:05:29 +08:00
|
|
|
|
2016-05-06 22:40:21 +08:00
|
|
|
if (intel_vgpu_active(to_i915(vm->dev)))
|
2015-08-28 15:41:18 +08:00
|
|
|
gen8_ppgtt_notify_vgt(ppgtt, false);
|
|
|
|
|
2015-07-30 18:05:29 +08:00
|
|
|
if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
|
|
|
|
gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, &ppgtt->pdp);
|
|
|
|
else
|
|
|
|
gen8_ppgtt_cleanup_4lvl(ppgtt);
|
2015-07-30 18:02:03 +08:00
|
|
|
|
2015-06-30 23:16:40 +08:00
|
|
|
gen8_free_scratch(vm);
|
2014-02-13 06:28:44 +08:00
|
|
|
}
|
|
|
|
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
/**
|
|
|
|
* gen8_ppgtt_alloc_pagetabs() - Allocate page tables for VA range.
|
2015-07-30 18:02:03 +08:00
|
|
|
* @vm: Master vm structure.
|
|
|
|
* @pd: Page directory for this address range.
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
* @start: Starting virtual address to begin allocations.
|
2015-07-30 18:02:03 +08:00
|
|
|
* @length: Size of the allocations.
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
* @new_pts: Bitmap set by function with new allocations. Likely used by the
|
|
|
|
* caller to free on error.
|
|
|
|
*
|
|
|
|
* Allocate the required number of page tables. Extremely similar to
|
|
|
|
* gen8_ppgtt_alloc_page_directories(). The main difference is here we are limited by
|
|
|
|
* the page directory boundary (instead of the page directory pointer). That
|
|
|
|
* boundary is 1GB virtual. Therefore, unlike gen8_ppgtt_alloc_page_directories(), it is
|
|
|
|
* possible, and likely that the caller will need to use multiple calls of this
|
|
|
|
* function to achieve the appropriate allocation.
|
|
|
|
*
|
|
|
|
* Return: 0 if success; negative error code otherwise.
|
|
|
|
*/
|
2015-07-30 18:02:03 +08:00
|
|
|
static int gen8_ppgtt_alloc_pagetabs(struct i915_address_space *vm,
|
2015-04-08 19:13:32 +08:00
|
|
|
struct i915_page_directory *pd,
|
2015-04-08 19:13:28 +08:00
|
|
|
uint64_t start,
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
uint64_t length,
|
|
|
|
unsigned long *new_pts)
|
2014-02-20 14:05:43 +08:00
|
|
|
{
|
2015-07-30 18:02:03 +08:00
|
|
|
struct drm_device *dev = vm->dev;
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
struct i915_page_table *pt;
|
2015-04-08 19:13:28 +08:00
|
|
|
uint32_t pde;
|
2014-02-20 14:05:43 +08:00
|
|
|
|
2015-12-08 21:30:51 +08:00
|
|
|
gen8_for_each_pde(pt, pd, start, length, pde) {
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
/* Don't reallocate page tables */
|
2015-07-30 00:23:46 +08:00
|
|
|
if (test_bit(pde, pd->used_pdes)) {
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
/* Scratch is never allocated this way */
|
2015-07-30 18:02:03 +08:00
|
|
|
WARN_ON(pt == vm->scratch_pt);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-05-23 01:04:59 +08:00
|
|
|
pt = alloc_pt(dev);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
if (IS_ERR(pt))
|
2015-04-08 19:13:28 +08:00
|
|
|
goto unwind_out;
|
|
|
|
|
2015-07-30 18:02:03 +08:00
|
|
|
gen8_initialize_pt(vm, pt);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
pd->page_table[pde] = pt;
|
2015-06-25 23:35:19 +08:00
|
|
|
__set_bit(pde, new_pts);
|
2015-07-30 00:23:49 +08:00
|
|
|
trace_i915_page_table_entry_alloc(vm, pde, start, GEN8_PDE_SHIFT);
|
drm/i915/bdw: Reorganize PT allocations
The previous allocation mechanism would get 2 contiguous allocations,
one for the page directories, and one for the page tables. As each page
table is 1 page, and there are 512 of these per page directory, this
goes to 2MB. An unfriendly request at best. Worse still, our HW now
supports 4 page directories, and a 2MB allocation is not allowed.
In order to fix this, this patch attempts to split up each page table
allocation into a single, discrete allocation. There is nothing really
fancy about the patch itself, it just has to manage an extra pointer
indirection, and have a fancier bit of logic to free up the pages.
To accommodate some of the added complexity, two new helpers are
introduced to allocate, and free the page table pages.
NOTE: I really wanted to split the way we do allocations, and the way in
which we identify the page table/page directory being used. I found
splitting this functionality up to be too unwieldy. I apologize in
advance to the reviewer. I'd recommend looking at the result, rather
than the diff.
v2/NOTE2: This patch predated commit:
6f1cc993518462ccf039e195fabd47e7aa5bfd13
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue Dec 31 15:50:31 2013 +0000
drm/i915: Avoid dereference past end of page arr
It fixed the same issue as that patch, but because of the limbo state of
PPGTT, Chris patch was merged instead. The excess churn is a result of
my using my original patch, which has my preferred naming. Primarily
act_* is changed to which_*, but it's mostly the same otherwise. I've
kept the convention Chris used for the pte wrap (I had something
slightly different, and broken - but fixable)
v3: Rename which_p[..]e to drop which_ (Chris)
Remove BUG_ON in inner loop (Chris)
Redo the pde/pdpe wrap logic (Chris)
v4: s/1MB/2MB in commit message (Imre)
Plug leaking gen8_pt_pages in both the error path, as well as general
free case (Imre)
v5: Rename leftover "which_" variables (Imre)
Add the pde = 0 wrap that was missed from v3 (Imre)
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
[danvet: Squash in fixup from Ben.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-02-21 03:51:21 +08:00
|
|
|
}
|
|
|
|
|
2014-02-20 14:05:43 +08:00
|
|
|
return 0;
|
drm/i915/bdw: Reorganize PT allocations
The previous allocation mechanism would get 2 contiguous allocations,
one for the page directories, and one for the page tables. As each page
table is 1 page, and there are 512 of these per page directory, this
goes to 2MB. An unfriendly request at best. Worse still, our HW now
supports 4 page directories, and a 2MB allocation is not allowed.
In order to fix this, this patch attempts to split up each page table
allocation into a single, discrete allocation. There is nothing really
fancy about the patch itself, it just has to manage an extra pointer
indirection, and have a fancier bit of logic to free up the pages.
To accommodate some of the added complexity, two new helpers are
introduced to allocate, and free the page table pages.
NOTE: I really wanted to split the way we do allocations, and the way in
which we identify the page table/page directory being used. I found
splitting this functionality up to be too unwieldy. I apologize in
advance to the reviewer. I'd recommend looking at the result, rather
than the diff.
v2/NOTE2: This patch predated commit:
6f1cc993518462ccf039e195fabd47e7aa5bfd13
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue Dec 31 15:50:31 2013 +0000
drm/i915: Avoid dereference past end of page arr
It fixed the same issue as that patch, but because of the limbo state of
PPGTT, Chris patch was merged instead. The excess churn is a result of
my using my original patch, which has my preferred naming. Primarily
act_* is changed to which_*, but it's mostly the same otherwise. I've
kept the convention Chris used for the pte wrap (I had something
slightly different, and broken - but fixable)
v3: Rename which_p[..]e to drop which_ (Chris)
Remove BUG_ON in inner loop (Chris)
Redo the pde/pdpe wrap logic (Chris)
v4: s/1MB/2MB in commit message (Imre)
Plug leaking gen8_pt_pages in both the error path, as well as general
free case (Imre)
v5: Rename leftover "which_" variables (Imre)
Add the pde = 0 wrap that was missed from v3 (Imre)
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
[danvet: Squash in fixup from Ben.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-02-21 03:51:21 +08:00
|
|
|
|
|
|
|
unwind_out:
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
for_each_set_bit(pde, new_pts, I915_PDES)
|
2015-06-25 23:35:08 +08:00
|
|
|
free_pt(dev, pd->page_table[pde]);
|
drm/i915/bdw: Reorganize PT allocations
The previous allocation mechanism would get 2 contiguous allocations,
one for the page directories, and one for the page tables. As each page
table is 1 page, and there are 512 of these per page directory, this
goes to 2MB. An unfriendly request at best. Worse still, our HW now
supports 4 page directories, and a 2MB allocation is not allowed.
In order to fix this, this patch attempts to split up each page table
allocation into a single, discrete allocation. There is nothing really
fancy about the patch itself, it just has to manage an extra pointer
indirection, and have a fancier bit of logic to free up the pages.
To accommodate some of the added complexity, two new helpers are
introduced to allocate, and free the page table pages.
NOTE: I really wanted to split the way we do allocations, and the way in
which we identify the page table/page directory being used. I found
splitting this functionality up to be too unwieldy. I apologize in
advance to the reviewer. I'd recommend looking at the result, rather
than the diff.
v2/NOTE2: This patch predated commit:
6f1cc993518462ccf039e195fabd47e7aa5bfd13
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue Dec 31 15:50:31 2013 +0000
drm/i915: Avoid dereference past end of page arr
It fixed the same issue as that patch, but because of the limbo state of
PPGTT, Chris patch was merged instead. The excess churn is a result of
my using my original patch, which has my preferred naming. Primarily
act_* is changed to which_*, but it's mostly the same otherwise. I've
kept the convention Chris used for the pte wrap (I had something
slightly different, and broken - but fixable)
v3: Rename which_p[..]e to drop which_ (Chris)
Remove BUG_ON in inner loop (Chris)
Redo the pde/pdpe wrap logic (Chris)
v4: s/1MB/2MB in commit message (Imre)
Plug leaking gen8_pt_pages in both the error path, as well as general
free case (Imre)
v5: Rename leftover "which_" variables (Imre)
Add the pde = 0 wrap that was missed from v3 (Imre)
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
[danvet: Squash in fixup from Ben.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-02-21 03:51:21 +08:00
|
|
|
|
2015-02-25 00:22:34 +08:00
|
|
|
return -ENOMEM;
|
2014-02-20 14:05:43 +08:00
|
|
|
}
|
|
|
|
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
/**
|
|
|
|
* gen8_ppgtt_alloc_page_directories() - Allocate page directories for VA range.
|
2015-07-30 18:02:03 +08:00
|
|
|
* @vm: Master vm structure.
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
* @pdp: Page directory pointer for this address range.
|
|
|
|
* @start: Starting virtual address to begin allocations.
|
2015-07-30 18:02:03 +08:00
|
|
|
* @length: Size of the allocations.
|
|
|
|
* @new_pds: Bitmap set by function with new allocations. Likely used by the
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
* caller to free on error.
|
|
|
|
*
|
|
|
|
* Allocate the required number of page directories starting at the pde index of
|
|
|
|
* @start, and ending at the pde index @start + @length. This function will skip
|
|
|
|
* over already allocated page directories within the range, and only allocate
|
|
|
|
* new ones, setting the appropriate pointer within the pdp as well as the
|
|
|
|
* correct position in the bitmap @new_pds.
|
|
|
|
*
|
|
|
|
* The function will only allocate the pages within the range for a give page
|
|
|
|
* directory pointer. In other words, if @start + @length straddles a virtually
|
|
|
|
* addressed PDP boundary (512GB for 4k pages), there will be more allocations
|
|
|
|
* required by the caller, This is not currently possible, and the BUG in the
|
|
|
|
* code will prevent it.
|
|
|
|
*
|
|
|
|
* Return: 0 if success; negative error code otherwise.
|
|
|
|
*/
|
2015-07-30 18:02:03 +08:00
|
|
|
static int
|
|
|
|
gen8_ppgtt_alloc_page_directories(struct i915_address_space *vm,
|
|
|
|
struct i915_page_directory_pointer *pdp,
|
|
|
|
uint64_t start,
|
|
|
|
uint64_t length,
|
|
|
|
unsigned long *new_pds)
|
2014-02-20 14:05:43 +08:00
|
|
|
{
|
2015-07-30 18:02:03 +08:00
|
|
|
struct drm_device *dev = vm->dev;
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
struct i915_page_directory *pd;
|
2015-04-08 19:13:27 +08:00
|
|
|
uint32_t pdpe;
|
2015-07-30 00:23:46 +08:00
|
|
|
uint32_t pdpes = I915_PDPES_PER_PDP(dev);
|
2015-04-08 19:13:27 +08:00
|
|
|
|
2015-07-30 00:23:46 +08:00
|
|
|
WARN_ON(!bitmap_empty(new_pds, pdpes));
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
|
2015-12-08 21:30:51 +08:00
|
|
|
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
2015-07-30 00:23:46 +08:00
|
|
|
if (test_bit(pdpe, pdp->used_pdpes))
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
continue;
|
2015-04-08 19:13:33 +08:00
|
|
|
|
2015-05-23 01:04:59 +08:00
|
|
|
pd = alloc_pd(dev);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
if (IS_ERR(pd))
|
2015-02-25 00:22:34 +08:00
|
|
|
goto unwind_out;
|
2015-04-08 19:13:27 +08:00
|
|
|
|
2015-07-30 18:02:03 +08:00
|
|
|
gen8_initialize_pd(vm, pd);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
pdp->page_directory[pdpe] = pd;
|
2015-06-25 23:35:19 +08:00
|
|
|
__set_bit(pdpe, new_pds);
|
2015-07-30 00:23:49 +08:00
|
|
|
trace_i915_page_directory_entry_alloc(vm, pdpe, start, GEN8_PDPE_SHIFT);
|
2015-02-25 00:22:34 +08:00
|
|
|
}
|
|
|
|
|
2014-02-20 14:05:43 +08:00
|
|
|
return 0;
|
2015-02-25 00:22:34 +08:00
|
|
|
|
|
|
|
unwind_out:
|
2015-07-30 00:23:46 +08:00
|
|
|
for_each_set_bit(pdpe, new_pds, pdpes)
|
2015-06-25 23:35:08 +08:00
|
|
|
free_pd(dev, pdp->page_directory[pdpe]);
|
2015-02-25 00:22:34 +08:00
|
|
|
|
|
|
|
return -ENOMEM;
|
2014-02-20 14:05:43 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 18:05:29 +08:00
|
|
|
/**
|
|
|
|
* gen8_ppgtt_alloc_page_dirpointers() - Allocate pdps for VA range.
|
|
|
|
* @vm: Master vm structure.
|
|
|
|
* @pml4: Page map level 4 for this address range.
|
|
|
|
* @start: Starting virtual address to begin allocations.
|
|
|
|
* @length: Size of the allocations.
|
|
|
|
* @new_pdps: Bitmap set by function with new allocations. Likely used by the
|
|
|
|
* caller to free on error.
|
|
|
|
*
|
|
|
|
* Allocate the required number of page directory pointers. Extremely similar to
|
|
|
|
* gen8_ppgtt_alloc_page_directories() and gen8_ppgtt_alloc_pagetabs().
|
|
|
|
* The main difference is here we are limited by the pml4 boundary (instead of
|
|
|
|
* the page directory pointer).
|
|
|
|
*
|
|
|
|
* Return: 0 if success; negative error code otherwise.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
gen8_ppgtt_alloc_page_dirpointers(struct i915_address_space *vm,
|
|
|
|
struct i915_pml4 *pml4,
|
|
|
|
uint64_t start,
|
|
|
|
uint64_t length,
|
|
|
|
unsigned long *new_pdps)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = vm->dev;
|
|
|
|
struct i915_page_directory_pointer *pdp;
|
|
|
|
uint32_t pml4e;
|
|
|
|
|
|
|
|
WARN_ON(!bitmap_empty(new_pdps, GEN8_PML4ES_PER_PML4));
|
|
|
|
|
2015-12-08 21:30:51 +08:00
|
|
|
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
|
2015-07-30 18:05:29 +08:00
|
|
|
if (!test_bit(pml4e, pml4->used_pml4es)) {
|
|
|
|
pdp = alloc_pdp(dev);
|
|
|
|
if (IS_ERR(pdp))
|
|
|
|
goto unwind_out;
|
|
|
|
|
2015-07-30 00:23:55 +08:00
|
|
|
gen8_initialize_pdp(vm, pdp);
|
2015-07-30 18:05:29 +08:00
|
|
|
pml4->pdps[pml4e] = pdp;
|
|
|
|
__set_bit(pml4e, new_pdps);
|
|
|
|
trace_i915_page_directory_pointer_entry_alloc(vm,
|
|
|
|
pml4e,
|
|
|
|
start,
|
|
|
|
GEN8_PML4E_SHIFT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
unwind_out:
|
|
|
|
for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4)
|
|
|
|
free_pdp(dev, pml4->pdps[pml4e]);
|
|
|
|
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
static void
|
2015-09-04 01:22:18 +08:00
|
|
|
free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long *new_pts)
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
{
|
|
|
|
kfree(new_pts);
|
|
|
|
kfree(new_pds);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fills in the page directory bitmap, and the array of page tables bitmap. Both
|
|
|
|
* of these are based on the number of PDPEs in the system.
|
|
|
|
*/
|
|
|
|
static
|
|
|
|
int __must_check alloc_gen8_temp_bitmaps(unsigned long **new_pds,
|
2015-09-04 01:22:18 +08:00
|
|
|
unsigned long **new_pts,
|
2015-07-30 00:23:46 +08:00
|
|
|
uint32_t pdpes)
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
{
|
|
|
|
unsigned long *pds;
|
2015-09-04 01:22:18 +08:00
|
|
|
unsigned long *pts;
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
|
2015-09-04 01:22:18 +08:00
|
|
|
pds = kcalloc(BITS_TO_LONGS(pdpes), sizeof(unsigned long), GFP_TEMPORARY);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
if (!pds)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2015-09-04 01:22:18 +08:00
|
|
|
pts = kcalloc(pdpes, BITS_TO_LONGS(I915_PDES) * sizeof(unsigned long),
|
|
|
|
GFP_TEMPORARY);
|
|
|
|
if (!pts)
|
|
|
|
goto err_out;
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
|
|
|
|
*new_pds = pds;
|
|
|
|
*new_pts = pts;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_out:
|
2015-09-04 01:22:18 +08:00
|
|
|
free_gen8_temp_bitmaps(pds, pts);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2015-06-25 23:35:03 +08:00
|
|
|
/* PDE TLBs are a pain to invalidate on GEN8+. When we modify
|
|
|
|
* the page table structures, we mark them dirty so that
|
|
|
|
* context switching/execlist queuing code takes extra steps
|
|
|
|
* to ensure that tlbs are flushed.
|
|
|
|
*/
|
|
|
|
static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt)
|
|
|
|
{
|
|
|
|
ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask;
|
|
|
|
}
|
|
|
|
|
2015-07-30 18:05:29 +08:00
|
|
|
static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
|
|
|
|
struct i915_page_directory_pointer *pdp,
|
|
|
|
uint64_t start,
|
|
|
|
uint64_t length)
|
2014-02-20 14:05:43 +08:00
|
|
|
{
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2015-09-04 01:22:18 +08:00
|
|
|
unsigned long *new_page_dirs, *new_page_tables;
|
2015-07-30 18:02:03 +08:00
|
|
|
struct drm_device *dev = vm->dev;
|
2015-04-08 19:13:28 +08:00
|
|
|
struct i915_page_directory *pd;
|
2015-04-08 19:13:33 +08:00
|
|
|
const uint64_t orig_start = start;
|
|
|
|
const uint64_t orig_length = length;
|
2015-04-08 19:13:28 +08:00
|
|
|
uint32_t pdpe;
|
2015-07-30 18:02:03 +08:00
|
|
|
uint32_t pdpes = I915_PDPES_PER_PDP(dev);
|
2014-02-20 14:05:43 +08:00
|
|
|
int ret;
|
|
|
|
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
/* Wrap is never okay since we can only represent 48b, and we don't
|
|
|
|
* actually use the other side of the canonical address space.
|
|
|
|
*/
|
|
|
|
if (WARN_ON(start + length < start))
|
2015-06-25 23:35:04 +08:00
|
|
|
return -ENODEV;
|
|
|
|
|
2015-07-30 18:02:03 +08:00
|
|
|
if (WARN_ON(start + length > vm->total))
|
2015-06-25 23:35:04 +08:00
|
|
|
return -ENODEV;
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
|
2015-07-30 00:23:46 +08:00
|
|
|
ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables, pdpes);
|
2014-02-20 14:05:43 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
/* Do the allocations first so we can easily bail out */
|
2015-07-30 18:02:03 +08:00
|
|
|
ret = gen8_ppgtt_alloc_page_directories(vm, pdp, start, length,
|
|
|
|
new_page_dirs);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
if (ret) {
|
2015-09-04 01:22:18 +08:00
|
|
|
free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* For every page directory referenced, allocate page tables */
|
2015-12-08 21:30:51 +08:00
|
|
|
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
2015-07-30 18:02:03 +08:00
|
|
|
ret = gen8_ppgtt_alloc_pagetabs(vm, pd, start, length,
|
2015-09-04 01:22:18 +08:00
|
|
|
new_page_tables + pdpe * BITS_TO_LONGS(I915_PDES));
|
2015-04-08 19:13:28 +08:00
|
|
|
if (ret)
|
|
|
|
goto err_out;
|
|
|
|
}
|
|
|
|
|
2015-04-08 19:13:33 +08:00
|
|
|
start = orig_start;
|
|
|
|
length = orig_length;
|
|
|
|
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
/* Allocations have completed successfully, so set the bitmaps, and do
|
|
|
|
* the mappings. */
|
2015-12-08 21:30:51 +08:00
|
|
|
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
2015-06-25 23:35:11 +08:00
|
|
|
gen8_pde_t *const page_directory = kmap_px(pd);
|
2015-04-08 19:13:33 +08:00
|
|
|
struct i915_page_table *pt;
|
2015-07-30 00:23:45 +08:00
|
|
|
uint64_t pd_len = length;
|
2015-04-08 19:13:33 +08:00
|
|
|
uint64_t pd_start = start;
|
|
|
|
uint32_t pde;
|
|
|
|
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
/* Every pd should be allocated, we just did that above. */
|
|
|
|
WARN_ON(!pd);
|
|
|
|
|
2015-12-08 21:30:51 +08:00
|
|
|
gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) {
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
/* Same reasoning as pd */
|
|
|
|
WARN_ON(!pt);
|
|
|
|
WARN_ON(!pd_len);
|
|
|
|
WARN_ON(!gen8_pte_count(pd_start, pd_len));
|
|
|
|
|
|
|
|
/* Set our used ptes within the page table */
|
|
|
|
bitmap_set(pt->used_ptes,
|
|
|
|
gen8_pte_index(pd_start),
|
|
|
|
gen8_pte_count(pd_start, pd_len));
|
|
|
|
|
|
|
|
/* Our pde is now pointing to the pagetable, pt */
|
2015-06-25 23:35:19 +08:00
|
|
|
__set_bit(pde, pd->used_pdes);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
|
|
|
|
/* Map the PDE to the page table */
|
2015-06-25 23:35:16 +08:00
|
|
|
page_directory[pde] = gen8_pde_encode(px_dma(pt),
|
|
|
|
I915_CACHE_LLC);
|
2015-07-30 00:23:49 +08:00
|
|
|
trace_i915_page_table_entry_map(&ppgtt->base, pde, pt,
|
|
|
|
gen8_pte_index(start),
|
|
|
|
gen8_pte_count(start, length),
|
|
|
|
GEN8_PTES);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
|
|
|
|
/* NB: We haven't yet mapped ptes to pages. At this
|
|
|
|
* point we're still relying on insert_entries() */
|
2015-04-08 19:13:33 +08:00
|
|
|
}
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
|
2015-06-25 23:35:11 +08:00
|
|
|
kunmap_px(ppgtt, page_directory);
|
2015-07-30 18:02:03 +08:00
|
|
|
__set_bit(pdpe, pdp->used_pdpes);
|
2015-07-30 18:05:29 +08:00
|
|
|
gen8_setup_page_directory(ppgtt, pdp, pd, pdpe);
|
2015-04-08 19:13:33 +08:00
|
|
|
}
|
|
|
|
|
2015-09-04 01:22:18 +08:00
|
|
|
free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
|
2015-06-25 23:35:03 +08:00
|
|
|
mark_tlbs_dirty(ppgtt);
|
2015-02-25 00:22:34 +08:00
|
|
|
return 0;
|
2014-02-20 14:05:43 +08:00
|
|
|
|
2015-02-25 00:22:34 +08:00
|
|
|
err_out:
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
while (pdpe--) {
|
2015-12-08 21:30:51 +08:00
|
|
|
unsigned long temp;
|
|
|
|
|
2015-09-04 01:22:18 +08:00
|
|
|
for_each_set_bit(temp, new_page_tables + pdpe *
|
|
|
|
BITS_TO_LONGS(I915_PDES), I915_PDES)
|
2015-07-30 18:02:03 +08:00
|
|
|
free_pt(dev, pdp->page_directory[pdpe]->page_table[temp]);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 00:23:46 +08:00
|
|
|
for_each_set_bit(pdpe, new_page_dirs, pdpes)
|
2015-07-30 18:02:03 +08:00
|
|
|
free_pd(dev, pdp->page_directory[pdpe]);
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
|
2015-09-04 01:22:18 +08:00
|
|
|
free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
|
2015-06-25 23:35:03 +08:00
|
|
|
mark_tlbs_dirty(ppgtt);
|
2014-02-20 14:05:43 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-07-30 18:05:29 +08:00
|
|
|
static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm,
|
|
|
|
struct i915_pml4 *pml4,
|
|
|
|
uint64_t start,
|
|
|
|
uint64_t length)
|
|
|
|
{
|
|
|
|
DECLARE_BITMAP(new_pdps, GEN8_PML4ES_PER_PML4);
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2015-07-30 18:05:29 +08:00
|
|
|
struct i915_page_directory_pointer *pdp;
|
2015-12-08 21:30:51 +08:00
|
|
|
uint64_t pml4e;
|
2015-07-30 18:05:29 +08:00
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
/* Do the pml4 allocations first, so we don't need to track the newly
|
|
|
|
* allocated tables below the pdp */
|
|
|
|
bitmap_zero(new_pdps, GEN8_PML4ES_PER_PML4);
|
|
|
|
|
|
|
|
/* The pagedirectory and pagetable allocations are done in the shared 3
|
|
|
|
* and 4 level code. Just allocate the pdps.
|
|
|
|
*/
|
|
|
|
ret = gen8_ppgtt_alloc_page_dirpointers(vm, pml4, start, length,
|
|
|
|
new_pdps);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
WARN(bitmap_weight(new_pdps, GEN8_PML4ES_PER_PML4) > 2,
|
|
|
|
"The allocation has spanned more than 512GB. "
|
|
|
|
"It is highly likely this is incorrect.");
|
|
|
|
|
2015-12-08 21:30:51 +08:00
|
|
|
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
|
2015-07-30 18:05:29 +08:00
|
|
|
WARN_ON(!pdp);
|
|
|
|
|
|
|
|
ret = gen8_alloc_va_range_3lvl(vm, pdp, start, length);
|
|
|
|
if (ret)
|
|
|
|
goto err_out;
|
|
|
|
|
|
|
|
gen8_setup_page_directory_pointer(ppgtt, pml4, pdp, pml4e);
|
|
|
|
}
|
|
|
|
|
|
|
|
bitmap_or(pml4->used_pml4es, new_pdps, pml4->used_pml4es,
|
|
|
|
GEN8_PML4ES_PER_PML4);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_out:
|
|
|
|
for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4)
|
|
|
|
gen8_ppgtt_cleanup_3lvl(vm->dev, pml4->pdps[pml4e]);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int gen8_alloc_va_range(struct i915_address_space *vm,
|
|
|
|
uint64_t start, uint64_t length)
|
|
|
|
{
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2015-07-30 18:05:29 +08:00
|
|
|
|
|
|
|
if (USES_FULL_48BIT_PPGTT(vm->dev))
|
|
|
|
return gen8_alloc_va_range_4lvl(vm, &ppgtt->pml4, start, length);
|
|
|
|
else
|
|
|
|
return gen8_alloc_va_range_3lvl(vm, &ppgtt->pdp, start, length);
|
|
|
|
}
|
|
|
|
|
2015-07-30 00:23:57 +08:00
|
|
|
static void gen8_dump_pdp(struct i915_page_directory_pointer *pdp,
|
|
|
|
uint64_t start, uint64_t length,
|
|
|
|
gen8_pte_t scratch_pte,
|
|
|
|
struct seq_file *m)
|
|
|
|
{
|
|
|
|
struct i915_page_directory *pd;
|
|
|
|
uint32_t pdpe;
|
|
|
|
|
2015-12-08 21:30:51 +08:00
|
|
|
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
2015-07-30 00:23:57 +08:00
|
|
|
struct i915_page_table *pt;
|
|
|
|
uint64_t pd_len = length;
|
|
|
|
uint64_t pd_start = start;
|
|
|
|
uint32_t pde;
|
|
|
|
|
|
|
|
if (!test_bit(pdpe, pdp->used_pdpes))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
seq_printf(m, "\tPDPE #%d\n", pdpe);
|
2015-12-08 21:30:51 +08:00
|
|
|
gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) {
|
2015-07-30 00:23:57 +08:00
|
|
|
uint32_t pte;
|
|
|
|
gen8_pte_t *pt_vaddr;
|
|
|
|
|
|
|
|
if (!test_bit(pde, pd->used_pdes))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pt_vaddr = kmap_px(pt);
|
|
|
|
for (pte = 0; pte < GEN8_PTES; pte += 4) {
|
|
|
|
uint64_t va =
|
|
|
|
(pdpe << GEN8_PDPE_SHIFT) |
|
|
|
|
(pde << GEN8_PDE_SHIFT) |
|
|
|
|
(pte << GEN8_PTE_SHIFT);
|
|
|
|
int i;
|
|
|
|
bool found = false;
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
if (pt_vaddr[pte + i] != scratch_pte)
|
|
|
|
found = true;
|
|
|
|
if (!found)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
seq_printf(m, "\t\t0x%llx [%03d,%03d,%04d]: =", va, pdpe, pde, pte);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
if (pt_vaddr[pte + i] != scratch_pte)
|
|
|
|
seq_printf(m, " %llx", pt_vaddr[pte + i]);
|
|
|
|
else
|
|
|
|
seq_puts(m, " SCRATCH ");
|
|
|
|
}
|
|
|
|
seq_puts(m, "\n");
|
|
|
|
}
|
|
|
|
/* don't use kunmap_px, it could trigger
|
|
|
|
* an unnecessary flush.
|
|
|
|
*/
|
|
|
|
kunmap_atomic(pt_vaddr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
|
|
|
|
{
|
|
|
|
struct i915_address_space *vm = &ppgtt->base;
|
|
|
|
uint64_t start = ppgtt->base.start;
|
|
|
|
uint64_t length = ppgtt->base.total;
|
2016-08-22 15:44:30 +08:00
|
|
|
gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
|
2016-10-13 20:02:40 +08:00
|
|
|
I915_CACHE_LLC);
|
2015-07-30 00:23:57 +08:00
|
|
|
|
|
|
|
if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
|
|
|
|
gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m);
|
|
|
|
} else {
|
2015-12-08 21:30:51 +08:00
|
|
|
uint64_t pml4e;
|
2015-07-30 00:23:57 +08:00
|
|
|
struct i915_pml4 *pml4 = &ppgtt->pml4;
|
|
|
|
struct i915_page_directory_pointer *pdp;
|
|
|
|
|
2015-12-08 21:30:51 +08:00
|
|
|
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
|
2015-07-30 00:23:57 +08:00
|
|
|
if (!test_bit(pml4e, pml4->used_pml4es))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
seq_printf(m, " PML4E #%llu\n", pml4e);
|
|
|
|
gen8_dump_pdp(pdp, start, length, scratch_pte, m);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-28 15:41:14 +08:00
|
|
|
static int gen8_preallocate_top_level_pdps(struct i915_hw_ppgtt *ppgtt)
|
|
|
|
{
|
2015-09-04 01:22:18 +08:00
|
|
|
unsigned long *new_page_dirs, *new_page_tables;
|
2015-08-28 15:41:14 +08:00
|
|
|
uint32_t pdpes = I915_PDPES_PER_PDP(dev);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* We allocate temp bitmap for page tables for no gain
|
|
|
|
* but as this is for init only, lets keep the things simple
|
|
|
|
*/
|
|
|
|
ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables, pdpes);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
/* Allocate for all pdps regardless of how the ppgtt
|
|
|
|
* was defined.
|
|
|
|
*/
|
|
|
|
ret = gen8_ppgtt_alloc_page_directories(&ppgtt->base, &ppgtt->pdp,
|
|
|
|
0, 1ULL << 32,
|
|
|
|
new_page_dirs);
|
|
|
|
if (!ret)
|
|
|
|
*ppgtt->pdp.used_pdpes = *new_page_dirs;
|
|
|
|
|
2015-09-04 01:22:18 +08:00
|
|
|
free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
|
2015-08-28 15:41:14 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-03-18 21:47:59 +08:00
|
|
|
/*
|
2014-02-20 14:05:42 +08:00
|
|
|
* GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
|
|
|
|
* with a net effect resembling a 2-level page table in normal x86 terms. Each
|
|
|
|
* PDP represents 1GB of memory 4 * 512 * 512 * 4096 = 4GB legacy 32b address
|
|
|
|
* space.
|
2013-11-05 12:47:32 +08:00
|
|
|
*
|
2014-02-20 14:05:42 +08:00
|
|
|
*/
|
2015-04-14 23:35:14 +08:00
|
|
|
static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
|
2013-11-05 12:47:32 +08:00
|
|
|
{
|
2015-06-30 23:16:40 +08:00
|
|
|
int ret;
|
2015-04-08 19:13:29 +08:00
|
|
|
|
2015-06-30 23:16:40 +08:00
|
|
|
ret = gen8_init_scratch(&ppgtt->base);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2015-04-08 19:13:27 +08:00
|
|
|
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
ppgtt->base.start = 0;
|
|
|
|
ppgtt->base.cleanup = gen8_ppgtt_cleanup;
|
2015-04-14 23:35:14 +08:00
|
|
|
ppgtt->base.allocate_va_range = gen8_alloc_va_range;
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
|
2015-04-14 23:35:11 +08:00
|
|
|
ppgtt->base.clear_range = gen8_ppgtt_clear_range;
|
2015-04-14 23:35:12 +08:00
|
|
|
ppgtt->base.unbind_vma = ppgtt_unbind_vma;
|
|
|
|
ppgtt->base.bind_vma = ppgtt_bind_vma;
|
2015-07-30 00:23:57 +08:00
|
|
|
ppgtt->debug_dump = gen8_dump_ppgtt;
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
|
2015-07-30 18:05:29 +08:00
|
|
|
if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
|
|
|
|
ret = setup_px(ppgtt->base.dev, &ppgtt->pml4);
|
|
|
|
if (ret)
|
|
|
|
goto free_scratch;
|
2015-07-30 00:23:46 +08:00
|
|
|
|
2015-07-30 00:23:55 +08:00
|
|
|
gen8_initialize_pml4(&ppgtt->base, &ppgtt->pml4);
|
|
|
|
|
2015-07-30 18:05:29 +08:00
|
|
|
ppgtt->base.total = 1ULL << 48;
|
2015-07-30 18:06:23 +08:00
|
|
|
ppgtt->switch_mm = gen8_48b_mm_switch;
|
2015-07-30 18:05:29 +08:00
|
|
|
} else {
|
2015-08-08 00:40:19 +08:00
|
|
|
ret = __pdp_init(ppgtt->base.dev, &ppgtt->pdp);
|
2015-08-03 16:52:01 +08:00
|
|
|
if (ret)
|
|
|
|
goto free_scratch;
|
|
|
|
|
|
|
|
ppgtt->base.total = 1ULL << 32;
|
2015-07-30 18:06:23 +08:00
|
|
|
ppgtt->switch_mm = gen8_legacy_mm_switch;
|
2015-07-30 18:05:29 +08:00
|
|
|
trace_i915_page_directory_pointer_entry_alloc(&ppgtt->base,
|
|
|
|
0, 0,
|
|
|
|
GEN8_PML4E_SHIFT);
|
2015-08-28 15:41:14 +08:00
|
|
|
|
2016-05-06 22:40:21 +08:00
|
|
|
if (intel_vgpu_active(to_i915(ppgtt->base.dev))) {
|
2015-08-28 15:41:14 +08:00
|
|
|
ret = gen8_preallocate_top_level_pdps(ppgtt);
|
|
|
|
if (ret)
|
|
|
|
goto free_scratch;
|
|
|
|
}
|
2015-08-03 16:52:01 +08:00
|
|
|
}
|
2015-07-30 00:23:46 +08:00
|
|
|
|
2016-05-06 22:40:21 +08:00
|
|
|
if (intel_vgpu_active(to_i915(ppgtt->base.dev)))
|
2015-08-28 15:41:18 +08:00
|
|
|
gen8_ppgtt_notify_vgt(ppgtt, true);
|
|
|
|
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
return 0;
|
2015-07-30 00:23:46 +08:00
|
|
|
|
|
|
|
free_scratch:
|
|
|
|
gen8_free_scratch(&ppgtt->base);
|
|
|
|
return ret;
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
}
|
|
|
|
|
2013-12-07 06:11:29 +08:00
|
|
|
static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
|
|
|
|
{
|
|
|
|
struct i915_address_space *vm = &ppgtt->base;
|
2015-04-08 19:13:30 +08:00
|
|
|
struct i915_page_table *unused;
|
2015-03-17 00:00:54 +08:00
|
|
|
gen6_pte_t scratch_pte;
|
2013-12-07 06:11:29 +08:00
|
|
|
uint32_t pd_entry;
|
2016-06-25 02:37:46 +08:00
|
|
|
uint32_t pte, pde;
|
2015-04-08 19:13:30 +08:00
|
|
|
uint32_t start = ppgtt->base.start, length = ppgtt->base.total;
|
2013-12-07 06:11:29 +08:00
|
|
|
|
2016-08-22 15:44:30 +08:00
|
|
|
scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
|
2016-10-13 20:02:40 +08:00
|
|
|
I915_CACHE_LLC, 0);
|
2013-12-07 06:11:29 +08:00
|
|
|
|
2016-06-25 02:37:46 +08:00
|
|
|
gen6_for_each_pde(unused, &ppgtt->pd, start, length, pde) {
|
2013-12-07 06:11:29 +08:00
|
|
|
u32 expected;
|
2015-03-17 00:00:54 +08:00
|
|
|
gen6_pte_t *pt_vaddr;
|
2015-06-25 23:35:12 +08:00
|
|
|
const dma_addr_t pt_addr = px_dma(ppgtt->pd.page_table[pde]);
|
2015-04-08 19:13:30 +08:00
|
|
|
pd_entry = readl(ppgtt->pd_addr + pde);
|
2013-12-07 06:11:29 +08:00
|
|
|
expected = (GEN6_PDE_ADDR_ENCODE(pt_addr) | GEN6_PDE_VALID);
|
|
|
|
|
|
|
|
if (pd_entry != expected)
|
|
|
|
seq_printf(m, "\tPDE #%d mismatch: Actual PDE: %x Expected PDE: %x\n",
|
|
|
|
pde,
|
|
|
|
pd_entry,
|
|
|
|
expected);
|
|
|
|
seq_printf(m, "\tPDE: %x\n", pd_entry);
|
|
|
|
|
2015-06-25 23:35:11 +08:00
|
|
|
pt_vaddr = kmap_px(ppgtt->pd.page_table[pde]);
|
|
|
|
|
2015-03-17 00:00:54 +08:00
|
|
|
for (pte = 0; pte < GEN6_PTES; pte+=4) {
|
2013-12-07 06:11:29 +08:00
|
|
|
unsigned long va =
|
2015-03-17 00:00:54 +08:00
|
|
|
(pde * PAGE_SIZE * GEN6_PTES) +
|
2013-12-07 06:11:29 +08:00
|
|
|
(pte * PAGE_SIZE);
|
|
|
|
int i;
|
|
|
|
bool found = false;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
if (pt_vaddr[pte + i] != scratch_pte)
|
|
|
|
found = true;
|
|
|
|
if (!found)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
seq_printf(m, "\t\t0x%lx [%03d,%04d]: =", va, pde, pte);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
if (pt_vaddr[pte + i] != scratch_pte)
|
|
|
|
seq_printf(m, " %08x", pt_vaddr[pte + i]);
|
|
|
|
else
|
|
|
|
seq_puts(m, " SCRATCH ");
|
|
|
|
}
|
|
|
|
seq_puts(m, "\n");
|
|
|
|
}
|
2015-06-25 23:35:11 +08:00
|
|
|
kunmap_px(ppgtt, pt_vaddr);
|
2013-12-07 06:11:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-17 00:00:56 +08:00
|
|
|
/* Write pde (index) from the page directory @pd to the page table @pt */
|
2015-04-08 19:13:23 +08:00
|
|
|
static void gen6_write_pde(struct i915_page_directory *pd,
|
|
|
|
const int pde, struct i915_page_table *pt)
|
2013-04-09 09:43:54 +08:00
|
|
|
{
|
2015-03-17 00:00:56 +08:00
|
|
|
/* Caller needs to make sure the write completes if necessary */
|
|
|
|
struct i915_hw_ppgtt *ppgtt =
|
|
|
|
container_of(pd, struct i915_hw_ppgtt, pd);
|
|
|
|
u32 pd_entry;
|
2013-04-09 09:43:54 +08:00
|
|
|
|
2015-06-25 23:35:12 +08:00
|
|
|
pd_entry = GEN6_PDE_ADDR_ENCODE(px_dma(pt));
|
2015-03-17 00:00:56 +08:00
|
|
|
pd_entry |= GEN6_PDE_VALID;
|
2013-04-09 09:43:54 +08:00
|
|
|
|
2015-03-17 00:00:56 +08:00
|
|
|
writel(pd_entry, ppgtt->pd_addr + pde);
|
|
|
|
}
|
2013-04-09 09:43:54 +08:00
|
|
|
|
2015-03-17 00:00:56 +08:00
|
|
|
/* Write all the page tables found in the ppgtt structure to incrementing page
|
|
|
|
* directories. */
|
|
|
|
static void gen6_write_page_range(struct drm_i915_private *dev_priv,
|
2015-04-08 19:13:23 +08:00
|
|
|
struct i915_page_directory *pd,
|
2015-03-17 00:00:56 +08:00
|
|
|
uint32_t start, uint32_t length)
|
|
|
|
{
|
2016-03-30 21:57:10 +08:00
|
|
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
2015-04-08 19:13:23 +08:00
|
|
|
struct i915_page_table *pt;
|
2016-06-25 02:37:46 +08:00
|
|
|
uint32_t pde;
|
2015-03-17 00:00:56 +08:00
|
|
|
|
2016-06-25 02:37:46 +08:00
|
|
|
gen6_for_each_pde(pt, pd, start, length, pde)
|
2015-03-17 00:00:56 +08:00
|
|
|
gen6_write_pde(pd, pde, pt);
|
|
|
|
|
|
|
|
/* Make sure write is complete before other code can use this page
|
|
|
|
* table. Also require for WC mapped PTEs */
|
2016-03-30 21:57:10 +08:00
|
|
|
readl(ggtt->gsm);
|
2013-04-24 14:15:32 +08:00
|
|
|
}
|
|
|
|
|
2013-12-07 06:11:09 +08:00
|
|
|
static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt)
|
2013-04-24 14:15:32 +08:00
|
|
|
{
|
2015-06-25 23:35:07 +08:00
|
|
|
BUG_ON(ppgtt->pd.base.ggtt_offset & 0x3f);
|
2013-12-07 06:11:09 +08:00
|
|
|
|
2015-06-25 23:35:07 +08:00
|
|
|
return (ppgtt->pd.base.ggtt_offset / 64) << 16;
|
2013-12-07 06:11:09 +08:00
|
|
|
}
|
|
|
|
|
2013-12-07 06:11:12 +08:00
|
|
|
static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt,
|
2015-05-30 00:43:56 +08:00
|
|
|
struct drm_i915_gem_request *req)
|
2013-12-07 06:11:12 +08:00
|
|
|
{
|
2016-08-03 05:50:21 +08:00
|
|
|
struct intel_ring *ring = req->ring;
|
2016-03-16 19:00:38 +08:00
|
|
|
struct intel_engine_cs *engine = req->engine;
|
2013-12-07 06:11:12 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* NB: TLBs must be flushed and invalidated before a switch */
|
2016-08-03 05:50:25 +08:00
|
|
|
ret = engine->emit_flush(req, EMIT_INVALIDATE | EMIT_FLUSH);
|
2013-12-07 06:11:12 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2015-05-30 00:44:07 +08:00
|
|
|
ret = intel_ring_begin(req, 6);
|
2013-12-07 06:11:12 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2016-08-03 05:50:18 +08:00
|
|
|
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
|
|
|
|
intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(engine));
|
|
|
|
intel_ring_emit(ring, PP_DIR_DCLV_2G);
|
|
|
|
intel_ring_emit_reg(ring, RING_PP_DIR_BASE(engine));
|
|
|
|
intel_ring_emit(ring, get_pd_offset(ppgtt));
|
|
|
|
intel_ring_emit(ring, MI_NOOP);
|
|
|
|
intel_ring_advance(ring);
|
2013-12-07 06:11:12 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-12-07 06:11:11 +08:00
|
|
|
static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
|
2015-05-30 00:43:56 +08:00
|
|
|
struct drm_i915_gem_request *req)
|
2013-12-07 06:11:11 +08:00
|
|
|
{
|
2016-08-03 05:50:21 +08:00
|
|
|
struct intel_ring *ring = req->ring;
|
2016-03-16 19:00:38 +08:00
|
|
|
struct intel_engine_cs *engine = req->engine;
|
2013-12-07 06:11:11 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* NB: TLBs must be flushed and invalidated before a switch */
|
2016-08-03 05:50:25 +08:00
|
|
|
ret = engine->emit_flush(req, EMIT_INVALIDATE | EMIT_FLUSH);
|
2013-12-07 06:11:11 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2015-05-30 00:44:07 +08:00
|
|
|
ret = intel_ring_begin(req, 6);
|
2013-12-07 06:11:11 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2016-08-03 05:50:18 +08:00
|
|
|
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
|
|
|
|
intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(engine));
|
|
|
|
intel_ring_emit(ring, PP_DIR_DCLV_2G);
|
|
|
|
intel_ring_emit_reg(ring, RING_PP_DIR_BASE(engine));
|
|
|
|
intel_ring_emit(ring, get_pd_offset(ppgtt));
|
|
|
|
intel_ring_emit(ring, MI_NOOP);
|
|
|
|
intel_ring_advance(ring);
|
2013-12-07 06:11:11 +08:00
|
|
|
|
2013-12-07 06:11:12 +08:00
|
|
|
/* XXX: RCS is the only one to auto invalidate the TLBs? */
|
2016-03-16 19:00:36 +08:00
|
|
|
if (engine->id != RCS) {
|
2016-08-03 05:50:25 +08:00
|
|
|
ret = engine->emit_flush(req, EMIT_INVALIDATE | EMIT_FLUSH);
|
2013-12-07 06:11:12 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-12-07 06:11:11 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-12-07 06:11:10 +08:00
|
|
|
static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt,
|
2015-05-30 00:43:56 +08:00
|
|
|
struct drm_i915_gem_request *req)
|
2013-12-07 06:11:10 +08:00
|
|
|
{
|
2016-03-16 19:00:38 +08:00
|
|
|
struct intel_engine_cs *engine = req->engine;
|
2016-07-04 15:48:31 +08:00
|
|
|
struct drm_i915_private *dev_priv = req->i915;
|
2013-12-07 06:11:11 +08:00
|
|
|
|
2016-03-16 19:00:36 +08:00
|
|
|
I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G);
|
|
|
|
I915_WRITE(RING_PP_DIR_BASE(engine), get_pd_offset(ppgtt));
|
2013-12-07 06:11:10 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-07 02:19:53 +08:00
|
|
|
static void gen8_ppgtt_enable(struct drm_device *dev)
|
2013-12-07 06:11:10 +08:00
|
|
|
{
|
2016-07-04 18:34:36 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
2016-03-16 19:00:36 +08:00
|
|
|
struct intel_engine_cs *engine;
|
drm/i915: Allocate intel_engine_cs structure only for the enabled engines
With the possibility of addition of many more number of rings in future,
the drm_i915_private structure could bloat as an array, of type
intel_engine_cs, is embedded inside it.
struct intel_engine_cs engine[I915_NUM_ENGINES];
Though this is still fine as generally there is only a single instance of
drm_i915_private structure used, but not all of the possible rings would be
enabled or active on most of the platforms. Some memory can be saved by
allocating intel_engine_cs structure only for the enabled/active engines.
Currently the engine/ring ID is kept static and dev_priv->engine[] is simply
indexed using the enums defined in intel_engine_id.
To save memory and continue using the static engine/ring IDs, 'engine' is
defined as an array of pointers.
struct intel_engine_cs *engine[I915_NUM_ENGINES];
dev_priv->engine[engine_ID] will be NULL for disabled engine instances.
There is a text size reduction of 928 bytes, from 1028200 to 1027272, for
i915.o file (but for i915.ko file text size remain same as 1193131 bytes).
v2:
- Remove the engine iterator field added in drm_i915_private structure,
instead pass a local iterator variable to the for_each_engine**
macros. (Chris)
- Do away with intel_engine_initialized() and instead directly use the
NULL pointer check on engine pointer. (Chris)
v3:
- Remove for_each_engine_id() macro, as the updated macro for_each_engine()
can be used in place of it. (Chris)
- Protect the access to Render engine Fault register with a NULL check, as
engine specific init is done later in Driver load sequence.
v4:
- Use !!dev_priv->engine[VCS] style for the engine check in getparam. (Chris)
- Kill the superfluous init_engine_lists().
v5:
- Cleanup the intel_engines_init() & intel_engines_setup(), with respect to
allocation of intel_engine_cs structure. (Chris)
v6:
- Rebase.
v7:
- Optimize the for_each_engine_masked() macro. (Chris)
- Change the type of 'iter' local variable to enum intel_engine_id. (Chris)
- Rebase.
v8: Rebase.
v9: Rebase.
v10:
- For index calculation use engine ID instead of pointer based arithmetic in
intel_engine_sync_index() as engine pointers are not contiguous now (Chris)
- For appropriateness, rename local enum variable 'iter' to 'id'. (Joonas)
- Use for_each_engine macro for cleanup in intel_engines_init() and remove
check for NULL engine pointer in cleanup() routines. (Joonas)
v11: Rebase.
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1476378888-7372-1-git-send-email-akash.goel@intel.com
2016-10-14 01:14:48 +08:00
|
|
|
enum intel_engine_id id;
|
2013-04-24 14:15:32 +08:00
|
|
|
|
drm/i915: Allocate intel_engine_cs structure only for the enabled engines
With the possibility of addition of many more number of rings in future,
the drm_i915_private structure could bloat as an array, of type
intel_engine_cs, is embedded inside it.
struct intel_engine_cs engine[I915_NUM_ENGINES];
Though this is still fine as generally there is only a single instance of
drm_i915_private structure used, but not all of the possible rings would be
enabled or active on most of the platforms. Some memory can be saved by
allocating intel_engine_cs structure only for the enabled/active engines.
Currently the engine/ring ID is kept static and dev_priv->engine[] is simply
indexed using the enums defined in intel_engine_id.
To save memory and continue using the static engine/ring IDs, 'engine' is
defined as an array of pointers.
struct intel_engine_cs *engine[I915_NUM_ENGINES];
dev_priv->engine[engine_ID] will be NULL for disabled engine instances.
There is a text size reduction of 928 bytes, from 1028200 to 1027272, for
i915.o file (but for i915.ko file text size remain same as 1193131 bytes).
v2:
- Remove the engine iterator field added in drm_i915_private structure,
instead pass a local iterator variable to the for_each_engine**
macros. (Chris)
- Do away with intel_engine_initialized() and instead directly use the
NULL pointer check on engine pointer. (Chris)
v3:
- Remove for_each_engine_id() macro, as the updated macro for_each_engine()
can be used in place of it. (Chris)
- Protect the access to Render engine Fault register with a NULL check, as
engine specific init is done later in Driver load sequence.
v4:
- Use !!dev_priv->engine[VCS] style for the engine check in getparam. (Chris)
- Kill the superfluous init_engine_lists().
v5:
- Cleanup the intel_engines_init() & intel_engines_setup(), with respect to
allocation of intel_engine_cs structure. (Chris)
v6:
- Rebase.
v7:
- Optimize the for_each_engine_masked() macro. (Chris)
- Change the type of 'iter' local variable to enum intel_engine_id. (Chris)
- Rebase.
v8: Rebase.
v9: Rebase.
v10:
- For index calculation use engine ID instead of pointer based arithmetic in
intel_engine_sync_index() as engine pointers are not contiguous now (Chris)
- For appropriateness, rename local enum variable 'iter' to 'id'. (Joonas)
- Use for_each_engine macro for cleanup in intel_engines_init() and remove
check for NULL engine pointer in cleanup() routines. (Joonas)
v11: Rebase.
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1476378888-7372-1-git-send-email-akash.goel@intel.com
2016-10-14 01:14:48 +08:00
|
|
|
for_each_engine(engine, dev_priv, id) {
|
2015-07-30 18:06:23 +08:00
|
|
|
u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0;
|
2016-03-16 19:00:36 +08:00
|
|
|
I915_WRITE(RING_MODE_GEN7(engine),
|
2015-07-30 18:06:23 +08:00
|
|
|
_MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level));
|
2013-12-07 06:11:10 +08:00
|
|
|
}
|
|
|
|
}
|
2013-04-09 09:43:54 +08:00
|
|
|
|
2014-08-07 02:19:53 +08:00
|
|
|
static void gen7_ppgtt_enable(struct drm_device *dev)
|
2013-04-24 14:15:32 +08:00
|
|
|
{
|
2016-07-04 18:34:36 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
2016-03-16 19:00:36 +08:00
|
|
|
struct intel_engine_cs *engine;
|
2013-12-07 06:11:09 +08:00
|
|
|
uint32_t ecochk, ecobits;
|
drm/i915: Allocate intel_engine_cs structure only for the enabled engines
With the possibility of addition of many more number of rings in future,
the drm_i915_private structure could bloat as an array, of type
intel_engine_cs, is embedded inside it.
struct intel_engine_cs engine[I915_NUM_ENGINES];
Though this is still fine as generally there is only a single instance of
drm_i915_private structure used, but not all of the possible rings would be
enabled or active on most of the platforms. Some memory can be saved by
allocating intel_engine_cs structure only for the enabled/active engines.
Currently the engine/ring ID is kept static and dev_priv->engine[] is simply
indexed using the enums defined in intel_engine_id.
To save memory and continue using the static engine/ring IDs, 'engine' is
defined as an array of pointers.
struct intel_engine_cs *engine[I915_NUM_ENGINES];
dev_priv->engine[engine_ID] will be NULL for disabled engine instances.
There is a text size reduction of 928 bytes, from 1028200 to 1027272, for
i915.o file (but for i915.ko file text size remain same as 1193131 bytes).
v2:
- Remove the engine iterator field added in drm_i915_private structure,
instead pass a local iterator variable to the for_each_engine**
macros. (Chris)
- Do away with intel_engine_initialized() and instead directly use the
NULL pointer check on engine pointer. (Chris)
v3:
- Remove for_each_engine_id() macro, as the updated macro for_each_engine()
can be used in place of it. (Chris)
- Protect the access to Render engine Fault register with a NULL check, as
engine specific init is done later in Driver load sequence.
v4:
- Use !!dev_priv->engine[VCS] style for the engine check in getparam. (Chris)
- Kill the superfluous init_engine_lists().
v5:
- Cleanup the intel_engines_init() & intel_engines_setup(), with respect to
allocation of intel_engine_cs structure. (Chris)
v6:
- Rebase.
v7:
- Optimize the for_each_engine_masked() macro. (Chris)
- Change the type of 'iter' local variable to enum intel_engine_id. (Chris)
- Rebase.
v8: Rebase.
v9: Rebase.
v10:
- For index calculation use engine ID instead of pointer based arithmetic in
intel_engine_sync_index() as engine pointers are not contiguous now (Chris)
- For appropriateness, rename local enum variable 'iter' to 'id'. (Joonas)
- Use for_each_engine macro for cleanup in intel_engines_init() and remove
check for NULL engine pointer in cleanup() routines. (Joonas)
v11: Rebase.
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1476378888-7372-1-git-send-email-akash.goel@intel.com
2016-10-14 01:14:48 +08:00
|
|
|
enum intel_engine_id id;
|
2013-04-09 09:43:54 +08:00
|
|
|
|
2013-12-07 06:11:09 +08:00
|
|
|
ecobits = I915_READ(GAC_ECO_BITS);
|
|
|
|
I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
|
2013-04-04 20:13:41 +08:00
|
|
|
|
2013-12-07 06:11:09 +08:00
|
|
|
ecochk = I915_READ(GAM_ECOCHK);
|
2016-10-13 18:03:01 +08:00
|
|
|
if (IS_HASWELL(dev_priv)) {
|
2013-12-07 06:11:09 +08:00
|
|
|
ecochk |= ECOCHK_PPGTT_WB_HSW;
|
|
|
|
} else {
|
|
|
|
ecochk |= ECOCHK_PPGTT_LLC_IVB;
|
|
|
|
ecochk &= ~ECOCHK_PPGTT_GFDT_IVB;
|
|
|
|
}
|
|
|
|
I915_WRITE(GAM_ECOCHK, ecochk);
|
2013-04-04 20:13:41 +08:00
|
|
|
|
drm/i915: Allocate intel_engine_cs structure only for the enabled engines
With the possibility of addition of many more number of rings in future,
the drm_i915_private structure could bloat as an array, of type
intel_engine_cs, is embedded inside it.
struct intel_engine_cs engine[I915_NUM_ENGINES];
Though this is still fine as generally there is only a single instance of
drm_i915_private structure used, but not all of the possible rings would be
enabled or active on most of the platforms. Some memory can be saved by
allocating intel_engine_cs structure only for the enabled/active engines.
Currently the engine/ring ID is kept static and dev_priv->engine[] is simply
indexed using the enums defined in intel_engine_id.
To save memory and continue using the static engine/ring IDs, 'engine' is
defined as an array of pointers.
struct intel_engine_cs *engine[I915_NUM_ENGINES];
dev_priv->engine[engine_ID] will be NULL for disabled engine instances.
There is a text size reduction of 928 bytes, from 1028200 to 1027272, for
i915.o file (but for i915.ko file text size remain same as 1193131 bytes).
v2:
- Remove the engine iterator field added in drm_i915_private structure,
instead pass a local iterator variable to the for_each_engine**
macros. (Chris)
- Do away with intel_engine_initialized() and instead directly use the
NULL pointer check on engine pointer. (Chris)
v3:
- Remove for_each_engine_id() macro, as the updated macro for_each_engine()
can be used in place of it. (Chris)
- Protect the access to Render engine Fault register with a NULL check, as
engine specific init is done later in Driver load sequence.
v4:
- Use !!dev_priv->engine[VCS] style for the engine check in getparam. (Chris)
- Kill the superfluous init_engine_lists().
v5:
- Cleanup the intel_engines_init() & intel_engines_setup(), with respect to
allocation of intel_engine_cs structure. (Chris)
v6:
- Rebase.
v7:
- Optimize the for_each_engine_masked() macro. (Chris)
- Change the type of 'iter' local variable to enum intel_engine_id. (Chris)
- Rebase.
v8: Rebase.
v9: Rebase.
v10:
- For index calculation use engine ID instead of pointer based arithmetic in
intel_engine_sync_index() as engine pointers are not contiguous now (Chris)
- For appropriateness, rename local enum variable 'iter' to 'id'. (Joonas)
- Use for_each_engine macro for cleanup in intel_engines_init() and remove
check for NULL engine pointer in cleanup() routines. (Joonas)
v11: Rebase.
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1476378888-7372-1-git-send-email-akash.goel@intel.com
2016-10-14 01:14:48 +08:00
|
|
|
for_each_engine(engine, dev_priv, id) {
|
2013-04-09 09:43:54 +08:00
|
|
|
/* GFX_MODE is per-ring on gen7+ */
|
2016-03-16 19:00:36 +08:00
|
|
|
I915_WRITE(RING_MODE_GEN7(engine),
|
2013-12-07 06:11:09 +08:00
|
|
|
_MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
|
2013-04-09 09:43:54 +08:00
|
|
|
}
|
2013-12-07 06:11:09 +08:00
|
|
|
}
|
2013-04-09 09:43:54 +08:00
|
|
|
|
2014-08-07 02:19:53 +08:00
|
|
|
static void gen6_ppgtt_enable(struct drm_device *dev)
|
2013-12-07 06:11:09 +08:00
|
|
|
{
|
2016-07-04 18:34:36 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
2013-12-07 06:11:09 +08:00
|
|
|
uint32_t ecochk, gab_ctl, ecobits;
|
2013-04-04 20:13:41 +08:00
|
|
|
|
2013-12-07 06:11:09 +08:00
|
|
|
ecobits = I915_READ(GAC_ECO_BITS);
|
|
|
|
I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_SNB_BIT |
|
|
|
|
ECOBITS_PPGTT_CACHE64B);
|
2013-04-09 09:43:54 +08:00
|
|
|
|
2013-12-07 06:11:09 +08:00
|
|
|
gab_ctl = I915_READ(GAB_CTL);
|
|
|
|
I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT);
|
|
|
|
|
|
|
|
ecochk = I915_READ(GAM_ECOCHK);
|
|
|
|
I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | ECOCHK_PPGTT_CACHE64B);
|
|
|
|
|
|
|
|
I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
|
2013-04-09 09:43:54 +08:00
|
|
|
}
|
|
|
|
|
2012-02-10 00:15:46 +08:00
|
|
|
/* PPGTT support for Sandybdrige/Gen6 and later */
|
2013-07-17 07:50:05 +08:00
|
|
|
static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
|
2014-02-21 03:50:33 +08:00
|
|
|
uint64_t start,
|
2016-10-13 20:02:40 +08:00
|
|
|
uint64_t length)
|
2012-02-10 00:15:46 +08:00
|
|
|
{
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2015-03-17 00:00:54 +08:00
|
|
|
gen6_pte_t *pt_vaddr, scratch_pte;
|
2014-02-21 03:50:33 +08:00
|
|
|
unsigned first_entry = start >> PAGE_SHIFT;
|
|
|
|
unsigned num_entries = length >> PAGE_SHIFT;
|
2015-03-17 00:00:54 +08:00
|
|
|
unsigned act_pt = first_entry / GEN6_PTES;
|
|
|
|
unsigned first_pte = first_entry % GEN6_PTES;
|
2012-02-10 00:15:47 +08:00
|
|
|
unsigned last_pte, i;
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2016-08-22 15:44:30 +08:00
|
|
|
scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
|
2016-10-13 20:02:40 +08:00
|
|
|
I915_CACHE_LLC, 0);
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2012-02-10 00:15:47 +08:00
|
|
|
while (num_entries) {
|
|
|
|
last_pte = first_pte + num_entries;
|
2015-03-17 00:00:54 +08:00
|
|
|
if (last_pte > GEN6_PTES)
|
|
|
|
last_pte = GEN6_PTES;
|
2012-02-10 00:15:47 +08:00
|
|
|
|
2015-06-25 23:35:11 +08:00
|
|
|
pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]);
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2012-02-10 00:15:47 +08:00
|
|
|
for (i = first_pte; i < last_pte; i++)
|
|
|
|
pt_vaddr[i] = scratch_pte;
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2015-06-25 23:35:11 +08:00
|
|
|
kunmap_px(ppgtt, pt_vaddr);
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2012-02-10 00:15:47 +08:00
|
|
|
num_entries -= last_pte - first_pte;
|
|
|
|
first_pte = 0;
|
2013-03-20 06:48:39 +08:00
|
|
|
act_pt++;
|
2012-02-10 00:15:47 +08:00
|
|
|
}
|
2012-02-10 00:15:46 +08:00
|
|
|
}
|
|
|
|
|
2013-07-17 07:50:05 +08:00
|
|
|
static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
|
2013-01-25 06:44:56 +08:00
|
|
|
struct sg_table *pages,
|
2014-02-21 03:50:33 +08:00
|
|
|
uint64_t start,
|
2014-06-17 13:29:42 +08:00
|
|
|
enum i915_cache_level cache_level, u32 flags)
|
2013-01-25 06:44:56 +08:00
|
|
|
{
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2014-02-21 03:50:33 +08:00
|
|
|
unsigned first_entry = start >> PAGE_SHIFT;
|
2015-03-17 00:00:54 +08:00
|
|
|
unsigned act_pt = first_entry / GEN6_PTES;
|
|
|
|
unsigned act_pte = first_entry % GEN6_PTES;
|
2016-05-20 18:54:06 +08:00
|
|
|
gen6_pte_t *pt_vaddr = NULL;
|
|
|
|
struct sgt_iter sgt_iter;
|
|
|
|
dma_addr_t addr;
|
2013-02-19 01:28:04 +08:00
|
|
|
|
2016-05-20 18:54:06 +08:00
|
|
|
for_each_sgt_dma(addr, sgt_iter, pages) {
|
2013-12-31 23:50:30 +08:00
|
|
|
if (pt_vaddr == NULL)
|
2015-06-25 23:35:11 +08:00
|
|
|
pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]);
|
2013-02-19 01:28:04 +08:00
|
|
|
|
2013-12-31 23:50:30 +08:00
|
|
|
pt_vaddr[act_pte] =
|
2016-10-13 20:02:40 +08:00
|
|
|
vm->pte_encode(addr, cache_level, flags);
|
2014-06-17 13:29:42 +08:00
|
|
|
|
2015-03-17 00:00:54 +08:00
|
|
|
if (++act_pte == GEN6_PTES) {
|
2015-06-25 23:35:11 +08:00
|
|
|
kunmap_px(ppgtt, pt_vaddr);
|
2013-12-31 23:50:30 +08:00
|
|
|
pt_vaddr = NULL;
|
2013-03-20 06:48:39 +08:00
|
|
|
act_pt++;
|
2013-02-19 01:28:04 +08:00
|
|
|
act_pte = 0;
|
2013-01-25 06:44:56 +08:00
|
|
|
}
|
|
|
|
}
|
2016-05-20 18:54:06 +08:00
|
|
|
|
2013-12-31 23:50:30 +08:00
|
|
|
if (pt_vaddr)
|
2015-06-25 23:35:11 +08:00
|
|
|
kunmap_px(ppgtt, pt_vaddr);
|
2013-01-25 06:44:56 +08:00
|
|
|
}
|
|
|
|
|
2015-03-17 00:00:56 +08:00
|
|
|
static int gen6_alloc_va_range(struct i915_address_space *vm,
|
2015-06-25 23:35:04 +08:00
|
|
|
uint64_t start_in, uint64_t length_in)
|
2015-03-17 00:00:56 +08:00
|
|
|
{
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
DECLARE_BITMAP(new_page_tables, I915_PDES);
|
|
|
|
struct drm_device *dev = vm->dev;
|
2016-03-30 21:57:10 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2015-04-08 19:13:23 +08:00
|
|
|
struct i915_page_table *pt;
|
2015-06-25 23:35:04 +08:00
|
|
|
uint32_t start, length, start_save, length_save;
|
2016-06-25 02:37:46 +08:00
|
|
|
uint32_t pde;
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
int ret;
|
|
|
|
|
2015-06-25 23:35:04 +08:00
|
|
|
if (WARN_ON(start_in + length_in > ppgtt->base.total))
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
start = start_save = start_in;
|
|
|
|
length = length_save = length_in;
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
|
|
|
|
bitmap_zero(new_page_tables, I915_PDES);
|
|
|
|
|
|
|
|
/* The allocation is done in two stages so that we can bail out with
|
|
|
|
* minimal amount of pain. The first stage finds new page tables that
|
|
|
|
* need allocation. The second stage marks use ptes within the page
|
|
|
|
* tables.
|
|
|
|
*/
|
2016-06-25 02:37:46 +08:00
|
|
|
gen6_for_each_pde(pt, &ppgtt->pd, start, length, pde) {
|
2015-06-25 23:35:17 +08:00
|
|
|
if (pt != vm->scratch_pt) {
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
WARN_ON(bitmap_empty(pt->used_ptes, GEN6_PTES));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We've already allocated a page table */
|
|
|
|
WARN_ON(!bitmap_empty(pt->used_ptes, GEN6_PTES));
|
|
|
|
|
2015-05-23 01:04:59 +08:00
|
|
|
pt = alloc_pt(dev);
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
if (IS_ERR(pt)) {
|
|
|
|
ret = PTR_ERR(pt);
|
|
|
|
goto unwind_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
gen6_initialize_pt(vm, pt);
|
|
|
|
|
|
|
|
ppgtt->pd.page_table[pde] = pt;
|
2015-06-25 23:35:19 +08:00
|
|
|
__set_bit(pde, new_page_tables);
|
2015-03-24 23:46:23 +08:00
|
|
|
trace_i915_page_table_entry_alloc(vm, pde, start, GEN6_PDE_SHIFT);
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
start = start_save;
|
|
|
|
length = length_save;
|
2015-03-17 00:00:56 +08:00
|
|
|
|
2016-06-25 02:37:46 +08:00
|
|
|
gen6_for_each_pde(pt, &ppgtt->pd, start, length, pde) {
|
2015-03-17 00:00:56 +08:00
|
|
|
DECLARE_BITMAP(tmp_bitmap, GEN6_PTES);
|
|
|
|
|
|
|
|
bitmap_zero(tmp_bitmap, GEN6_PTES);
|
|
|
|
bitmap_set(tmp_bitmap, gen6_pte_index(start),
|
|
|
|
gen6_pte_count(start, length));
|
|
|
|
|
2015-06-25 23:35:19 +08:00
|
|
|
if (__test_and_clear_bit(pde, new_page_tables))
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
gen6_write_pde(&ppgtt->pd, pde, pt);
|
|
|
|
|
2015-03-24 23:46:23 +08:00
|
|
|
trace_i915_page_table_entry_map(vm, pde, pt,
|
|
|
|
gen6_pte_index(start),
|
|
|
|
gen6_pte_count(start, length),
|
|
|
|
GEN6_PTES);
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
bitmap_or(pt->used_ptes, tmp_bitmap, pt->used_ptes,
|
2015-03-17 00:00:56 +08:00
|
|
|
GEN6_PTES);
|
|
|
|
}
|
|
|
|
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
WARN_ON(!bitmap_empty(new_page_tables, I915_PDES));
|
|
|
|
|
|
|
|
/* Make sure write is complete before other code can use this page
|
|
|
|
* table. Also require for WC mapped PTEs */
|
2016-03-30 21:57:10 +08:00
|
|
|
readl(ggtt->gsm);
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
|
drm/i915: Track page table reload need
This patch was formerly known as, "Force pd restore when PDEs change,
gen6-7." I had to change the name because it is needed for GEN8 too.
The real issue this is trying to solve is when a new object is mapped
into the current address space. The GPU does not snoop the new mapping
so we must do the gen specific action to reload the page tables.
GEN8 and GEN7 do differ in the way they load page tables for the RCS.
GEN8 does so with the context restore, while GEN7 requires the proper
load commands in the command streamer. Non-render is similar for both.
Caveat for GEN7
The docs say you cannot change the PDEs of a currently running context.
We never map new PDEs of a running context, and expect them to be
present - so I think this is okay. (We can unmap, but this should also
be okay since we only unmap unreferenced objects that the GPU shouldn't
be tryingto va->pa xlate.) The MI_SET_CONTEXT command does have a flag
to signal that even if the context is the same, force a reload. It's
unclear exactly what this does, but I have a hunch it's the right thing
to do.
The logic assumes that we always emit a context switch after mapping new
PDEs, and before we submit a batch. This is the case today, and has been
the case since the inception of hardware contexts. A note in the comment
let's the user know.
It's not just for gen8. If the current context has mappings change, we
need a context reload to switch
v2: Rebased after ppgtt clean up patches. Split the warning for aliasing
and true ppgtt options. And do not break aliasing ppgtt, where to->ppgtt
is always null.
v3: Invalidate PPGTT TLBs inside alloc_va_range.
v4: Rename ppgtt_invalidate_tlbs to mark_tlbs_dirty and move
pd_dirty_rings from i915_address_space to i915_hw_ppgtt. Fixes when
neither ctx->ppgtt and aliasing_ppgtt exist.
v5: Removed references to teardown_va_range.
v6: Updated needs_pd_load_pre/post.
v7: Fix pd_dirty_rings check in needs_pd_load_post, and update/move
comment about updated PDEs to object_pin/bind (Mika).
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-19 20:53:28 +08:00
|
|
|
mark_tlbs_dirty(ppgtt);
|
2015-03-17 00:00:56 +08:00
|
|
|
return 0;
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
|
|
|
|
unwind_out:
|
|
|
|
for_each_set_bit(pde, new_page_tables, I915_PDES) {
|
2015-04-08 19:13:23 +08:00
|
|
|
struct i915_page_table *pt = ppgtt->pd.page_table[pde];
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
|
2015-06-25 23:35:17 +08:00
|
|
|
ppgtt->pd.page_table[pde] = vm->scratch_pt;
|
2015-06-25 23:35:08 +08:00
|
|
|
free_pt(vm->dev, pt);
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
mark_tlbs_dirty(ppgtt);
|
|
|
|
return ret;
|
2015-03-17 00:00:56 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 23:16:40 +08:00
|
|
|
static int gen6_init_scratch(struct i915_address_space *vm)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = vm->dev;
|
2016-08-22 15:44:30 +08:00
|
|
|
int ret;
|
2015-06-30 23:16:40 +08:00
|
|
|
|
2016-08-22 15:44:31 +08:00
|
|
|
ret = setup_scratch_page(dev, &vm->scratch_page, I915_GFP_DMA);
|
2016-08-22 15:44:30 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2015-06-30 23:16:40 +08:00
|
|
|
|
|
|
|
vm->scratch_pt = alloc_pt(dev);
|
|
|
|
if (IS_ERR(vm->scratch_pt)) {
|
2016-08-22 15:44:30 +08:00
|
|
|
cleanup_scratch_page(dev, &vm->scratch_page);
|
2015-06-30 23:16:40 +08:00
|
|
|
return PTR_ERR(vm->scratch_pt);
|
|
|
|
}
|
|
|
|
|
|
|
|
gen6_initialize_pt(vm, vm->scratch_pt);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void gen6_free_scratch(struct i915_address_space *vm)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = vm->dev;
|
|
|
|
|
|
|
|
free_pt(dev, vm->scratch_pt);
|
2016-08-22 15:44:30 +08:00
|
|
|
cleanup_scratch_page(dev, &vm->scratch_page);
|
2015-06-30 23:16:40 +08:00
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:13 +08:00
|
|
|
static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
|
2014-02-20 14:05:48 +08:00
|
|
|
{
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
|
2016-06-25 02:37:46 +08:00
|
|
|
struct i915_page_directory *pd = &ppgtt->pd;
|
|
|
|
struct drm_device *dev = vm->dev;
|
2015-04-08 19:13:30 +08:00
|
|
|
struct i915_page_table *pt;
|
|
|
|
uint32_t pde;
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
|
2015-04-14 23:35:13 +08:00
|
|
|
drm_mm_remove_node(&ppgtt->node);
|
|
|
|
|
2016-06-25 02:37:46 +08:00
|
|
|
gen6_for_all_pdes(pt, pd, pde)
|
2015-06-25 23:35:17 +08:00
|
|
|
if (pt != vm->scratch_pt)
|
2016-06-25 02:37:46 +08:00
|
|
|
free_pt(dev, pt);
|
drm/i915: Create page table allocators
As we move toward dynamic page table allocation, it becomes much easier
to manage our data structures if break do things less coarsely by
breaking up all of our actions into individual tasks. This makes the
code easier to write, read, and verify.
Aside from the dissection of the allocation functions, the patch
statically allocates the page table structures without a page directory.
This remains the same for all platforms,
The patch itself should not have much functional difference. The primary
noticeable difference is the fact that page tables are no longer
allocated, but rather statically declared as part of the page directory.
This has non-zero overhead, but things gain additional complexity as a
result.
This patch exists for a few reasons:
1. Splitting out the functions allows easily combining GEN6 and GEN8
code. Page tables have no difference based on GEN8. As we'll see in a
future patch when we add the DMA mappings to the allocations, it
requires only one small change to make work, and error handling should
just fall into place.
2. Unless we always want to allocate all page tables under a given PDE,
we'll have to eventually break this up into an array of pointers (or
pointer to pointer).
3. Having the discrete functions is easier to review, and understand.
All allocations and frees now take place in just a couple of locations.
Reviewing, and catching leaks should be easy.
4. Less important: the GFP flags are confined to one location, which
makes playing around with such things trivial.
v2: Updated commit message to explain why this patch exists
v3: For lrc, s/pdp.page_directory[i].daddr/pdp.page_directory[i]->daddr/
v4: Renamed free_pt/pd_single functions to unmap_and_free_pt/pd (Daniel)
v5: Added additional safety checks in gen8 clear/free/unmap.
v6: Use WARN_ON and return -EINVAL in alloc_pt_range (Mika).
v7: Make err_out loop symmetrical to the way we allocate in
alloc_pt_range. Also s/page_tables/page_table and correct commit
message (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v3+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-02-25 00:22:36 +08:00
|
|
|
|
2015-06-30 23:16:40 +08:00
|
|
|
gen6_free_scratch(vm);
|
2013-01-25 05:49:56 +08:00
|
|
|
}
|
|
|
|
|
2014-02-20 14:05:49 +08:00
|
|
|
static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
|
2013-01-25 05:49:56 +08:00
|
|
|
{
|
2015-06-30 23:16:40 +08:00
|
|
|
struct i915_address_space *vm = &ppgtt->base;
|
2013-07-17 07:50:05 +08:00
|
|
|
struct drm_device *dev = ppgtt->base.dev;
|
2016-03-30 21:57:10 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
2013-12-07 06:11:08 +08:00
|
|
|
bool retried = false;
|
2014-02-20 14:05:49 +08:00
|
|
|
int ret;
|
2012-02-10 00:15:46 +08:00
|
|
|
|
drm/i915: Use drm_mm for PPGTT PDEs
When PPGTT support was originally enabled, it was only designed to
support 1 PPGTT. It therefore made sense to simply hide the GGTT space
required to enable this from the drm_mm allocator.
Since we intend to support full PPGTT, which means more than 1, and they
can be created and destroyed ad hoc it will be required to use the
proper allocation techniques we already have.
The first step here is to make the existing single PPGTT use the
allocator.
The astute observer will notice that we are reserving space in the GGTT
for the PDEs for the lifetime of the address space, and would be right
to question whether or not this is a good idea. It does not make a
difference with this current patch only the aliasing PPGTT (indeed the
PDEs should still be hidden from the shrinker). For the future, we are
allocating from top to bottom to avoid using the precious "gtt
space" The GGTT space at that point should only be used for scanout, HW
contexts, ringbuffers, HWSP, PDEs, and a couple of other small buffers
(potentially) used by the kernel. Everything else should be mapped into
a PPGTT. To put the consumption in more tangible terms, it takes
approximately 4 sets of PDEs to equal one 19x10 framebuffer (with no
fancy stride or alignment constraints). 3/4 of the total [average] GGTT
can be used for PDEs, and hopefully never touch the 1/4 that the
framebuffer needs.
The astute, and persistent observer might ask about the page tables
which are also pinned for the address space. This waste is unfortunate.
We use 2MB of memory per address space. We leave wrapping the PDEs as a
real GEM object as a TODO.
v2: Align PDEs to 64b in GTT
Allocate the node dynamically so we can use drm_mm_put_block
Now tested on IGT
Allocate node at the top to avoid fragmentation (Chris)
v3: Use Chris' top down allocator
v4: Embed drm_mm_node into ppgtt struct (Jesse)
Remove hunks which didn't belong (Jesse)
v5: Don't subtract guard page since we now killed the guard page prior
to this patch. (Ben)
v6: Rebased and removed guard page stuff.
Added a chunk to the commit message
Allow adding a context to mappable region
v7: Undo v3, so we can make the drm patch last in the series
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v4)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
squash: drm/i915: allow PPGTT to use mappable
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:11:07 +08:00
|
|
|
/* PPGTT PDEs reside in the GGTT and consists of 512 entries. The
|
|
|
|
* allocator works in address space sizes, so it's multiplied by page
|
|
|
|
* size. We allocate at the top of the GTT to avoid fragmentation.
|
|
|
|
*/
|
2016-03-30 21:57:10 +08:00
|
|
|
BUG_ON(!drm_mm_initialized(&ggtt->base.mm));
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
|
2015-06-30 23:16:40 +08:00
|
|
|
ret = gen6_init_scratch(vm);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
|
2013-12-07 06:11:08 +08:00
|
|
|
alloc:
|
2016-03-30 21:57:10 +08:00
|
|
|
ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm,
|
drm/i915: Use drm_mm for PPGTT PDEs
When PPGTT support was originally enabled, it was only designed to
support 1 PPGTT. It therefore made sense to simply hide the GGTT space
required to enable this from the drm_mm allocator.
Since we intend to support full PPGTT, which means more than 1, and they
can be created and destroyed ad hoc it will be required to use the
proper allocation techniques we already have.
The first step here is to make the existing single PPGTT use the
allocator.
The astute observer will notice that we are reserving space in the GGTT
for the PDEs for the lifetime of the address space, and would be right
to question whether or not this is a good idea. It does not make a
difference with this current patch only the aliasing PPGTT (indeed the
PDEs should still be hidden from the shrinker). For the future, we are
allocating from top to bottom to avoid using the precious "gtt
space" The GGTT space at that point should only be used for scanout, HW
contexts, ringbuffers, HWSP, PDEs, and a couple of other small buffers
(potentially) used by the kernel. Everything else should be mapped into
a PPGTT. To put the consumption in more tangible terms, it takes
approximately 4 sets of PDEs to equal one 19x10 framebuffer (with no
fancy stride or alignment constraints). 3/4 of the total [average] GGTT
can be used for PDEs, and hopefully never touch the 1/4 that the
framebuffer needs.
The astute, and persistent observer might ask about the page tables
which are also pinned for the address space. This waste is unfortunate.
We use 2MB of memory per address space. We leave wrapping the PDEs as a
real GEM object as a TODO.
v2: Align PDEs to 64b in GTT
Allocate the node dynamically so we can use drm_mm_put_block
Now tested on IGT
Allocate node at the top to avoid fragmentation (Chris)
v3: Use Chris' top down allocator
v4: Embed drm_mm_node into ppgtt struct (Jesse)
Remove hunks which didn't belong (Jesse)
v5: Don't subtract guard page since we now killed the guard page prior
to this patch. (Ben)
v6: Rebased and removed guard page stuff.
Added a chunk to the commit message
Allow adding a context to mappable region
v7: Undo v3, so we can make the drm patch last in the series
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v4)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
squash: drm/i915: allow PPGTT to use mappable
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:11:07 +08:00
|
|
|
&ppgtt->node, GEN6_PD_SIZE,
|
|
|
|
GEN6_PD_ALIGN, 0,
|
2016-03-30 21:57:10 +08:00
|
|
|
0, ggtt->base.total,
|
2014-05-07 13:21:30 +08:00
|
|
|
DRM_MM_TOPDOWN);
|
2013-12-07 06:11:08 +08:00
|
|
|
if (ret == -ENOSPC && !retried) {
|
2016-08-04 23:32:18 +08:00
|
|
|
ret = i915_gem_evict_something(&ggtt->base,
|
2013-12-07 06:11:08 +08:00
|
|
|
GEN6_PD_SIZE, GEN6_PD_ALIGN,
|
drm/i915: Prevent negative relocation deltas from wrapping
This is pure evil. Userspace, I'm looking at you SNA, repacks batch
buffers on the fly after generation as they are being passed to the
kernel for execution. These batches also contain self-referenced
relocations as a single buffer encompasses the state commands, kernels,
vertices and sampler. During generation the buffers are placed at known
offsets within the full batch, and then the relocation deltas (as passed
to the kernel) are tweaked as the batch is repacked into a smaller buffer.
This means that userspace is passing negative relocations deltas, which
subsequently wrap to large values if the batch is at a low address. The
GPU hangs when it then tries to use the large value as a base for its
address offsets, rather than wrapping back to the real value (as one
would hope). As the GPU uses positive offsets from the base, we can
treat the relocation address as the minimum address read by the GPU.
For the upper bound, we trust that userspace will not read beyond the
end of the buffer.
So, how do we fix negative relocations from wrapping? We can either
check that every relocation looks valid when we write it, and then
position each object such that we prevent the offset wraparound, or we
just special-case the self-referential behaviour of SNA and force all
batches to be above 256k. Daniel prefers the latter approach.
This fixes a GPU hang when it tries to use an address (relocation +
offset) greater than the GTT size. The issue would occur quite easily
with full-ppgtt as each fd gets its own VM space, so low offsets would
often be handed out. However, with the rearrangement of the low GTT due
to capturing the BIOS framebuffer, it is already affecting kernels 3.15
onwards. I think only IVB+ is susceptible to this bug, but the workaround
should only kick in rarely, so it seems sensible to always apply it.
v3: Use a bias for batch buffers to prevent small negative delta relocations
from wrapping.
v4 from Daniel:
- s/BIAS/BATCH_OFFSET_BIAS/
- Extract eb_vma_misplaced/i915_vma_misplaced since the conditions
were growing rather cumbersome.
- Add a comment to eb_get_batch explaining why we do this.
- Apply the batch offset bias everywhere but mention that we've only
observed it on gen7 gpus.
- Drop PIN_OFFSET_FIX for now, that slipped in from a feature patch.
v5: Add static to eb_get_batch, spotted by 0-day tester.
Testcase: igt/gem_bad_reloc
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=78533
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> (v3)
Cc: stable@vger.kernel.org
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-05-23 14:48:08 +08:00
|
|
|
I915_CACHE_NONE,
|
2016-03-30 21:57:10 +08:00
|
|
|
0, ggtt->base.total,
|
drm/i915: Prevent negative relocation deltas from wrapping
This is pure evil. Userspace, I'm looking at you SNA, repacks batch
buffers on the fly after generation as they are being passed to the
kernel for execution. These batches also contain self-referenced
relocations as a single buffer encompasses the state commands, kernels,
vertices and sampler. During generation the buffers are placed at known
offsets within the full batch, and then the relocation deltas (as passed
to the kernel) are tweaked as the batch is repacked into a smaller buffer.
This means that userspace is passing negative relocations deltas, which
subsequently wrap to large values if the batch is at a low address. The
GPU hangs when it then tries to use the large value as a base for its
address offsets, rather than wrapping back to the real value (as one
would hope). As the GPU uses positive offsets from the base, we can
treat the relocation address as the minimum address read by the GPU.
For the upper bound, we trust that userspace will not read beyond the
end of the buffer.
So, how do we fix negative relocations from wrapping? We can either
check that every relocation looks valid when we write it, and then
position each object such that we prevent the offset wraparound, or we
just special-case the self-referential behaviour of SNA and force all
batches to be above 256k. Daniel prefers the latter approach.
This fixes a GPU hang when it tries to use an address (relocation +
offset) greater than the GTT size. The issue would occur quite easily
with full-ppgtt as each fd gets its own VM space, so low offsets would
often be handed out. However, with the rearrangement of the low GTT due
to capturing the BIOS framebuffer, it is already affecting kernels 3.15
onwards. I think only IVB+ is susceptible to this bug, but the workaround
should only kick in rarely, so it seems sensible to always apply it.
v3: Use a bias for batch buffers to prevent small negative delta relocations
from wrapping.
v4 from Daniel:
- s/BIAS/BATCH_OFFSET_BIAS/
- Extract eb_vma_misplaced/i915_vma_misplaced since the conditions
were growing rather cumbersome.
- Add a comment to eb_get_batch explaining why we do this.
- Apply the batch offset bias everywhere but mention that we've only
observed it on gen7 gpus.
- Drop PIN_OFFSET_FIX for now, that slipped in from a feature patch.
v5: Add static to eb_get_batch, spotted by 0-day tester.
Testcase: igt/gem_bad_reloc
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=78533
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> (v3)
Cc: stable@vger.kernel.org
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-05-23 14:48:08 +08:00
|
|
|
0);
|
2013-12-07 06:11:08 +08:00
|
|
|
if (ret)
|
2015-03-17 00:00:56 +08:00
|
|
|
goto err_out;
|
2013-12-07 06:11:08 +08:00
|
|
|
|
|
|
|
retried = true;
|
|
|
|
goto alloc;
|
|
|
|
}
|
drm/i915: Use drm_mm for PPGTT PDEs
When PPGTT support was originally enabled, it was only designed to
support 1 PPGTT. It therefore made sense to simply hide the GGTT space
required to enable this from the drm_mm allocator.
Since we intend to support full PPGTT, which means more than 1, and they
can be created and destroyed ad hoc it will be required to use the
proper allocation techniques we already have.
The first step here is to make the existing single PPGTT use the
allocator.
The astute observer will notice that we are reserving space in the GGTT
for the PDEs for the lifetime of the address space, and would be right
to question whether or not this is a good idea. It does not make a
difference with this current patch only the aliasing PPGTT (indeed the
PDEs should still be hidden from the shrinker). For the future, we are
allocating from top to bottom to avoid using the precious "gtt
space" The GGTT space at that point should only be used for scanout, HW
contexts, ringbuffers, HWSP, PDEs, and a couple of other small buffers
(potentially) used by the kernel. Everything else should be mapped into
a PPGTT. To put the consumption in more tangible terms, it takes
approximately 4 sets of PDEs to equal one 19x10 framebuffer (with no
fancy stride or alignment constraints). 3/4 of the total [average] GGTT
can be used for PDEs, and hopefully never touch the 1/4 that the
framebuffer needs.
The astute, and persistent observer might ask about the page tables
which are also pinned for the address space. This waste is unfortunate.
We use 2MB of memory per address space. We leave wrapping the PDEs as a
real GEM object as a TODO.
v2: Align PDEs to 64b in GTT
Allocate the node dynamically so we can use drm_mm_put_block
Now tested on IGT
Allocate node at the top to avoid fragmentation (Chris)
v3: Use Chris' top down allocator
v4: Embed drm_mm_node into ppgtt struct (Jesse)
Remove hunks which didn't belong (Jesse)
v5: Don't subtract guard page since we now killed the guard page prior
to this patch. (Ben)
v6: Rebased and removed guard page stuff.
Added a chunk to the commit message
Allow adding a context to mappable region
v7: Undo v3, so we can make the drm patch last in the series
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v4)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
squash: drm/i915: allow PPGTT to use mappable
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:11:07 +08:00
|
|
|
|
2015-01-23 01:01:25 +08:00
|
|
|
if (ret)
|
2015-03-17 00:00:56 +08:00
|
|
|
goto err_out;
|
|
|
|
|
2015-01-23 01:01:25 +08:00
|
|
|
|
2016-03-30 21:57:10 +08:00
|
|
|
if (ppgtt->node.start < ggtt->mappable_end)
|
drm/i915: Use drm_mm for PPGTT PDEs
When PPGTT support was originally enabled, it was only designed to
support 1 PPGTT. It therefore made sense to simply hide the GGTT space
required to enable this from the drm_mm allocator.
Since we intend to support full PPGTT, which means more than 1, and they
can be created and destroyed ad hoc it will be required to use the
proper allocation techniques we already have.
The first step here is to make the existing single PPGTT use the
allocator.
The astute observer will notice that we are reserving space in the GGTT
for the PDEs for the lifetime of the address space, and would be right
to question whether or not this is a good idea. It does not make a
difference with this current patch only the aliasing PPGTT (indeed the
PDEs should still be hidden from the shrinker). For the future, we are
allocating from top to bottom to avoid using the precious "gtt
space" The GGTT space at that point should only be used for scanout, HW
contexts, ringbuffers, HWSP, PDEs, and a couple of other small buffers
(potentially) used by the kernel. Everything else should be mapped into
a PPGTT. To put the consumption in more tangible terms, it takes
approximately 4 sets of PDEs to equal one 19x10 framebuffer (with no
fancy stride or alignment constraints). 3/4 of the total [average] GGTT
can be used for PDEs, and hopefully never touch the 1/4 that the
framebuffer needs.
The astute, and persistent observer might ask about the page tables
which are also pinned for the address space. This waste is unfortunate.
We use 2MB of memory per address space. We leave wrapping the PDEs as a
real GEM object as a TODO.
v2: Align PDEs to 64b in GTT
Allocate the node dynamically so we can use drm_mm_put_block
Now tested on IGT
Allocate node at the top to avoid fragmentation (Chris)
v3: Use Chris' top down allocator
v4: Embed drm_mm_node into ppgtt struct (Jesse)
Remove hunks which didn't belong (Jesse)
v5: Don't subtract guard page since we now killed the guard page prior
to this patch. (Ben)
v6: Rebased and removed guard page stuff.
Added a chunk to the commit message
Allow adding a context to mappable region
v7: Undo v3, so we can make the drm patch last in the series
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v4)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
squash: drm/i915: allow PPGTT to use mappable
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:11:07 +08:00
|
|
|
DRM_DEBUG("Forced to use aperture for PDEs\n");
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2015-01-23 01:01:25 +08:00
|
|
|
return 0;
|
2015-03-17 00:00:56 +08:00
|
|
|
|
|
|
|
err_out:
|
2015-06-30 23:16:40 +08:00
|
|
|
gen6_free_scratch(vm);
|
2015-03-17 00:00:56 +08:00
|
|
|
return ret;
|
2014-02-20 14:05:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int gen6_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt)
|
|
|
|
{
|
2015-03-27 19:26:35 +08:00
|
|
|
return gen6_ppgtt_allocate_page_directories(ppgtt);
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
}
|
2015-02-25 00:22:37 +08:00
|
|
|
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
static void gen6_scratch_va_range(struct i915_hw_ppgtt *ppgtt,
|
|
|
|
uint64_t start, uint64_t length)
|
|
|
|
{
|
2015-04-08 19:13:23 +08:00
|
|
|
struct i915_page_table *unused;
|
2016-06-25 02:37:46 +08:00
|
|
|
uint32_t pde;
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2016-06-25 02:37:46 +08:00
|
|
|
gen6_for_each_pde(unused, &ppgtt->pd, start, length, pde)
|
2015-06-25 23:35:17 +08:00
|
|
|
ppgtt->pd.page_table[pde] = ppgtt->base.scratch_pt;
|
2014-02-20 14:05:49 +08:00
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:14 +08:00
|
|
|
static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
|
2014-02-20 14:05:49 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = ppgtt->base.dev;
|
2016-03-30 21:57:10 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
2014-02-20 14:05:49 +08:00
|
|
|
int ret;
|
|
|
|
|
2016-03-30 21:57:10 +08:00
|
|
|
ppgtt->base.pte_encode = ggtt->base.pte_encode;
|
2016-10-13 18:03:10 +08:00
|
|
|
if (intel_vgpu_active(dev_priv) || IS_GEN6(dev_priv))
|
2014-02-20 14:05:49 +08:00
|
|
|
ppgtt->switch_mm = gen6_mm_switch;
|
2016-10-13 18:03:01 +08:00
|
|
|
else if (IS_HASWELL(dev_priv))
|
2014-02-20 14:05:49 +08:00
|
|
|
ppgtt->switch_mm = hsw_mm_switch;
|
2016-10-13 18:03:10 +08:00
|
|
|
else if (IS_GEN7(dev_priv))
|
2014-02-20 14:05:49 +08:00
|
|
|
ppgtt->switch_mm = gen7_mm_switch;
|
2016-07-04 15:48:31 +08:00
|
|
|
else
|
2014-02-20 14:05:49 +08:00
|
|
|
BUG();
|
|
|
|
|
|
|
|
ret = gen6_ppgtt_alloc(ppgtt);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2015-04-14 23:35:14 +08:00
|
|
|
ppgtt->base.allocate_va_range = gen6_alloc_va_range;
|
2014-02-20 14:05:49 +08:00
|
|
|
ppgtt->base.clear_range = gen6_ppgtt_clear_range;
|
|
|
|
ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
|
2015-04-14 23:35:12 +08:00
|
|
|
ppgtt->base.unbind_vma = ppgtt_unbind_vma;
|
|
|
|
ppgtt->base.bind_vma = ppgtt_bind_vma;
|
2014-02-20 14:05:49 +08:00
|
|
|
ppgtt->base.cleanup = gen6_ppgtt_cleanup;
|
|
|
|
ppgtt->base.start = 0;
|
2015-04-08 19:13:30 +08:00
|
|
|
ppgtt->base.total = I915_PDES * GEN6_PTES * PAGE_SIZE;
|
2013-12-07 06:11:29 +08:00
|
|
|
ppgtt->debug_dump = gen6_dump_ppgtt;
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2015-06-25 23:35:07 +08:00
|
|
|
ppgtt->pd.base.ggtt_offset =
|
2015-03-17 00:00:54 +08:00
|
|
|
ppgtt->node.start / PAGE_SIZE * sizeof(gen6_pte_t);
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2016-03-30 21:57:10 +08:00
|
|
|
ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm +
|
2015-06-25 23:35:07 +08:00
|
|
|
ppgtt->pd.base.ggtt_offset / sizeof(gen6_pte_t);
|
2015-03-17 00:00:56 +08:00
|
|
|
|
2015-04-14 23:35:14 +08:00
|
|
|
gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total);
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2015-03-17 00:00:56 +08:00
|
|
|
gen6_write_page_range(dev_priv, &ppgtt->pd, 0, ppgtt->base.total);
|
|
|
|
|
2015-01-23 16:05:06 +08:00
|
|
|
DRM_DEBUG_DRIVER("Allocated pde space (%lldM) at GTT entry: %llx\n",
|
2014-02-20 14:05:49 +08:00
|
|
|
ppgtt->node.size >> 20,
|
|
|
|
ppgtt->node.start / PAGE_SIZE);
|
2013-01-25 05:49:56 +08:00
|
|
|
|
2014-08-07 02:19:54 +08:00
|
|
|
DRM_DEBUG("Adding PPGTT at offset %x\n",
|
2015-06-25 23:35:07 +08:00
|
|
|
ppgtt->pd.base.ggtt_offset << 10);
|
2014-08-07 02:19:54 +08:00
|
|
|
|
2014-02-20 14:05:49 +08:00
|
|
|
return 0;
|
2013-01-25 05:49:56 +08:00
|
|
|
}
|
|
|
|
|
2016-08-04 14:52:25 +08:00
|
|
|
static int __hw_ppgtt_init(struct i915_hw_ppgtt *ppgtt,
|
|
|
|
struct drm_i915_private *dev_priv)
|
2013-01-25 05:49:56 +08:00
|
|
|
{
|
2016-08-04 14:52:25 +08:00
|
|
|
ppgtt->base.dev = &dev_priv->drm;
|
2013-01-25 05:49:56 +08:00
|
|
|
|
2016-08-04 14:52:25 +08:00
|
|
|
if (INTEL_INFO(dev_priv)->gen < 8)
|
2015-04-14 23:35:14 +08:00
|
|
|
return gen6_ppgtt_init(ppgtt);
|
2013-04-09 09:43:53 +08:00
|
|
|
else
|
drm/i915/gen8: Dynamic page table allocations
This finishes off the dynamic page tables allocations, in the legacy 3
level style that already exists. Most everything has already been setup
to this point, the patch finishes off the enabling by setting the
appropriate function pointers.
In LRC mode, contexts need to know the PDPs when they are populated. With
dynamic page table allocations, these PDPs may not exist yet. Check if
PDPs have been allocated and use the scratch page if they do not exist yet.
Before submission, update the PDPs in the logic ring context as PDPs
have been allocated.
v2: Update aliasing/true ppgtt allocate/teardown/clear functions for
gen 6 & 7.
v3: Rebase.
v4: Remove BUG() from ppgtt_unbind_vma, but keep checking that either
teardown_va_range or clear_range functions exist (Daniel).
v5: Similar to gen6, in init, gen8_ppgtt_clear_range call is only needed
for aliasing ppgtt. Zombie tracking was originally added for teardown
function and is no longer required.
v6: Update err_out case in gen8_alloc_va_range (missed from lastest
rebase).
v7: Rebase after s/page_tables/page_table/.
v8: Updated scratch_pt check after scratch flag was removed in previous
patch.
v9: Note that lrc mode needs to be updated to support init state without
any PDP.
v10: Unmap correct page_table in gen8_alloc_va_range's error case, clean-up
gen8_aliasing_ppgtt_init (remove duplicated map), and initialize PTs
during page table allocation.
v11: Squashed LRC enabling commit, otherwise LRC mode would be left broken
until it was updated to handle the init case without any PDP.
v12: Do not overallocate new_pts bitmap, make alloc_gen8_temp_bitmaps
static and don't abuse of inline functions. (Mika)
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v2+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-08 19:13:34 +08:00
|
|
|
return gen8_ppgtt_init(ppgtt);
|
2014-08-07 02:19:54 +08:00
|
|
|
}
|
2015-06-25 23:35:13 +08:00
|
|
|
|
2015-09-16 17:49:00 +08:00
|
|
|
static void i915_address_space_init(struct i915_address_space *vm,
|
|
|
|
struct drm_i915_private *dev_priv)
|
|
|
|
{
|
|
|
|
drm_mm_init(&vm->mm, vm->start, vm->total);
|
|
|
|
INIT_LIST_HEAD(&vm->active_list);
|
|
|
|
INIT_LIST_HEAD(&vm->inactive_list);
|
2016-08-04 14:52:46 +08:00
|
|
|
INIT_LIST_HEAD(&vm->unbound_list);
|
2015-09-16 17:49:00 +08:00
|
|
|
list_add_tail(&vm->global_link, &dev_priv->vm_list);
|
|
|
|
}
|
|
|
|
|
2016-02-04 19:49:34 +08:00
|
|
|
static void gtt_write_workarounds(struct drm_device *dev)
|
|
|
|
{
|
2016-07-04 18:34:36 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
2016-02-04 19:49:34 +08:00
|
|
|
|
|
|
|
/* This function is for gtt related workarounds. This function is
|
|
|
|
* called on driver load and after a GPU reset, so you can place
|
|
|
|
* workarounds here even if they get overwritten by GPU reset.
|
|
|
|
*/
|
|
|
|
/* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt */
|
2016-10-13 18:03:00 +08:00
|
|
|
if (IS_BROADWELL(dev_priv))
|
2016-02-04 19:49:34 +08:00
|
|
|
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW);
|
2016-10-14 17:13:44 +08:00
|
|
|
else if (IS_CHERRYVIEW(dev_priv))
|
2016-02-04 19:49:34 +08:00
|
|
|
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV);
|
2016-10-13 18:03:03 +08:00
|
|
|
else if (IS_SKYLAKE(dev_priv))
|
2016-02-04 19:49:34 +08:00
|
|
|
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL);
|
2016-10-13 18:03:04 +08:00
|
|
|
else if (IS_BROXTON(dev_priv))
|
2016-02-04 19:49:34 +08:00
|
|
|
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT);
|
|
|
|
}
|
|
|
|
|
2016-08-04 14:52:25 +08:00
|
|
|
static int i915_ppgtt_init(struct i915_hw_ppgtt *ppgtt,
|
|
|
|
struct drm_i915_private *dev_priv,
|
|
|
|
struct drm_i915_file_private *file_priv)
|
2014-08-07 02:19:54 +08:00
|
|
|
{
|
2016-08-04 14:52:25 +08:00
|
|
|
int ret;
|
2013-04-09 09:43:53 +08:00
|
|
|
|
2016-08-04 14:52:25 +08:00
|
|
|
ret = __hw_ppgtt_init(ppgtt, dev_priv);
|
2014-08-07 02:19:54 +08:00
|
|
|
if (ret == 0) {
|
drm/i915: Add VM to context
Pretty straightforward so far except for the bit about the refcounting.
The PPGTT will potentially be shared amongst multiple contexts. Because
contexts themselves have a refcounted lifecycle, the easiest way to
manage this will be to refcount the PPGTT. To acheive this, we piggy
back off of the existing context refcount, and will increment and
decrement the PPGTT refcount with context creation, and destruction.
To put it more clearly, if context A, and context B both use PPGTT 0, we
can't free the PPGTT until both A, and B are destroyed.
Note that because the PPGTT is permanently pinned (for now), it really
just matters for the PPGTT destruction, as opposed to making space under
memory pressure.
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:11:15 +08:00
|
|
|
kref_init(&ppgtt->ref);
|
2015-09-16 17:49:00 +08:00
|
|
|
i915_address_space_init(&ppgtt->base, dev_priv);
|
2016-08-04 14:52:25 +08:00
|
|
|
ppgtt->base.file = file_priv;
|
2013-07-17 07:50:06 +08:00
|
|
|
}
|
2012-02-10 00:15:46 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-08-07 02:19:53 +08:00
|
|
|
int i915_ppgtt_init_hw(struct drm_device *dev)
|
|
|
|
{
|
2016-10-13 18:03:10 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
|
2016-02-04 19:49:34 +08:00
|
|
|
gtt_write_workarounds(dev);
|
|
|
|
|
2014-08-20 23:24:50 +08:00
|
|
|
/* In the case of execlists, PPGTT is enabled by the context descriptor
|
|
|
|
* and the PDPs are contained within the context itself. We don't
|
|
|
|
* need to do anything here. */
|
|
|
|
if (i915.enable_execlists)
|
|
|
|
return 0;
|
|
|
|
|
2014-08-07 02:19:53 +08:00
|
|
|
if (!USES_PPGTT(dev))
|
|
|
|
return 0;
|
|
|
|
|
2016-10-13 18:03:10 +08:00
|
|
|
if (IS_GEN6(dev_priv))
|
2014-08-07 02:19:53 +08:00
|
|
|
gen6_ppgtt_enable(dev);
|
2016-10-13 18:03:10 +08:00
|
|
|
else if (IS_GEN7(dev_priv))
|
2014-08-07 02:19:53 +08:00
|
|
|
gen7_ppgtt_enable(dev);
|
|
|
|
else if (INTEL_INFO(dev)->gen >= 8)
|
|
|
|
gen8_ppgtt_enable(dev);
|
|
|
|
else
|
2014-12-08 23:40:10 +08:00
|
|
|
MISSING_CASE(INTEL_INFO(dev)->gen);
|
2014-08-07 02:19:53 +08:00
|
|
|
|
2015-06-18 20:11:20 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2014-08-06 21:04:47 +08:00
|
|
|
struct i915_hw_ppgtt *
|
2016-08-04 14:52:25 +08:00
|
|
|
i915_ppgtt_create(struct drm_i915_private *dev_priv,
|
|
|
|
struct drm_i915_file_private *fpriv)
|
2014-08-06 21:04:47 +08:00
|
|
|
{
|
|
|
|
struct i915_hw_ppgtt *ppgtt;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
|
|
|
|
if (!ppgtt)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
2016-08-04 14:52:25 +08:00
|
|
|
ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv);
|
2014-08-06 21:04:47 +08:00
|
|
|
if (ret) {
|
|
|
|
kfree(ppgtt);
|
|
|
|
return ERR_PTR(ret);
|
|
|
|
}
|
|
|
|
|
2014-11-10 21:44:31 +08:00
|
|
|
trace_i915_ppgtt_create(&ppgtt->base);
|
|
|
|
|
2014-08-06 21:04:47 +08:00
|
|
|
return ppgtt;
|
|
|
|
}
|
|
|
|
|
2014-08-06 21:04:45 +08:00
|
|
|
void i915_ppgtt_release(struct kref *kref)
|
|
|
|
{
|
|
|
|
struct i915_hw_ppgtt *ppgtt =
|
|
|
|
container_of(kref, struct i915_hw_ppgtt, ref);
|
|
|
|
|
2014-11-10 21:44:31 +08:00
|
|
|
trace_i915_ppgtt_release(&ppgtt->base);
|
|
|
|
|
2016-08-04 14:52:46 +08:00
|
|
|
/* vmas should already be unbound and destroyed */
|
2014-08-06 21:04:45 +08:00
|
|
|
WARN_ON(!list_empty(&ppgtt->base.active_list));
|
|
|
|
WARN_ON(!list_empty(&ppgtt->base.inactive_list));
|
2016-08-04 14:52:46 +08:00
|
|
|
WARN_ON(!list_empty(&ppgtt->base.unbound_list));
|
2014-08-06 21:04:45 +08:00
|
|
|
|
2014-08-06 21:04:55 +08:00
|
|
|
list_del(&ppgtt->base.global_link);
|
|
|
|
drm_mm_takedown(&ppgtt->base.mm);
|
|
|
|
|
2014-08-06 21:04:45 +08:00
|
|
|
ppgtt->base.cleanup(&ppgtt->base);
|
|
|
|
kfree(ppgtt);
|
|
|
|
}
|
2012-02-10 00:15:46 +08:00
|
|
|
|
2013-01-19 04:30:31 +08:00
|
|
|
/* Certain Gen5 chipsets require require idling the GPU before
|
|
|
|
* unmapping anything from the GTT when VT-d is enabled.
|
|
|
|
*/
|
2016-08-04 14:52:22 +08:00
|
|
|
static bool needs_idle_maps(struct drm_i915_private *dev_priv)
|
2013-01-19 04:30:31 +08:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_INTEL_IOMMU
|
|
|
|
/* Query intel_iommu to see if we need the workaround. Presumably that
|
|
|
|
* was loaded first.
|
|
|
|
*/
|
2016-08-04 14:52:22 +08:00
|
|
|
if (IS_GEN5(dev_priv) && IS_MOBILE(dev_priv) && intel_iommu_gfx_mapped)
|
2013-01-19 04:30:31 +08:00
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-05-10 21:10:04 +08:00
|
|
|
void i915_check_and_clear_faults(struct drm_i915_private *dev_priv)
|
2013-10-17 00:21:30 +08:00
|
|
|
{
|
2016-03-16 19:00:36 +08:00
|
|
|
struct intel_engine_cs *engine;
|
drm/i915: Allocate intel_engine_cs structure only for the enabled engines
With the possibility of addition of many more number of rings in future,
the drm_i915_private structure could bloat as an array, of type
intel_engine_cs, is embedded inside it.
struct intel_engine_cs engine[I915_NUM_ENGINES];
Though this is still fine as generally there is only a single instance of
drm_i915_private structure used, but not all of the possible rings would be
enabled or active on most of the platforms. Some memory can be saved by
allocating intel_engine_cs structure only for the enabled/active engines.
Currently the engine/ring ID is kept static and dev_priv->engine[] is simply
indexed using the enums defined in intel_engine_id.
To save memory and continue using the static engine/ring IDs, 'engine' is
defined as an array of pointers.
struct intel_engine_cs *engine[I915_NUM_ENGINES];
dev_priv->engine[engine_ID] will be NULL for disabled engine instances.
There is a text size reduction of 928 bytes, from 1028200 to 1027272, for
i915.o file (but for i915.ko file text size remain same as 1193131 bytes).
v2:
- Remove the engine iterator field added in drm_i915_private structure,
instead pass a local iterator variable to the for_each_engine**
macros. (Chris)
- Do away with intel_engine_initialized() and instead directly use the
NULL pointer check on engine pointer. (Chris)
v3:
- Remove for_each_engine_id() macro, as the updated macro for_each_engine()
can be used in place of it. (Chris)
- Protect the access to Render engine Fault register with a NULL check, as
engine specific init is done later in Driver load sequence.
v4:
- Use !!dev_priv->engine[VCS] style for the engine check in getparam. (Chris)
- Kill the superfluous init_engine_lists().
v5:
- Cleanup the intel_engines_init() & intel_engines_setup(), with respect to
allocation of intel_engine_cs structure. (Chris)
v6:
- Rebase.
v7:
- Optimize the for_each_engine_masked() macro. (Chris)
- Change the type of 'iter' local variable to enum intel_engine_id. (Chris)
- Rebase.
v8: Rebase.
v9: Rebase.
v10:
- For index calculation use engine ID instead of pointer based arithmetic in
intel_engine_sync_index() as engine pointers are not contiguous now (Chris)
- For appropriateness, rename local enum variable 'iter' to 'id'. (Joonas)
- Use for_each_engine macro for cleanup in intel_engines_init() and remove
check for NULL engine pointer in cleanup() routines. (Joonas)
v11: Rebase.
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1476378888-7372-1-git-send-email-akash.goel@intel.com
2016-10-14 01:14:48 +08:00
|
|
|
enum intel_engine_id id;
|
2013-10-17 00:21:30 +08:00
|
|
|
|
2016-05-10 21:10:04 +08:00
|
|
|
if (INTEL_INFO(dev_priv)->gen < 6)
|
2013-10-17 00:21:30 +08:00
|
|
|
return;
|
|
|
|
|
drm/i915: Allocate intel_engine_cs structure only for the enabled engines
With the possibility of addition of many more number of rings in future,
the drm_i915_private structure could bloat as an array, of type
intel_engine_cs, is embedded inside it.
struct intel_engine_cs engine[I915_NUM_ENGINES];
Though this is still fine as generally there is only a single instance of
drm_i915_private structure used, but not all of the possible rings would be
enabled or active on most of the platforms. Some memory can be saved by
allocating intel_engine_cs structure only for the enabled/active engines.
Currently the engine/ring ID is kept static and dev_priv->engine[] is simply
indexed using the enums defined in intel_engine_id.
To save memory and continue using the static engine/ring IDs, 'engine' is
defined as an array of pointers.
struct intel_engine_cs *engine[I915_NUM_ENGINES];
dev_priv->engine[engine_ID] will be NULL for disabled engine instances.
There is a text size reduction of 928 bytes, from 1028200 to 1027272, for
i915.o file (but for i915.ko file text size remain same as 1193131 bytes).
v2:
- Remove the engine iterator field added in drm_i915_private structure,
instead pass a local iterator variable to the for_each_engine**
macros. (Chris)
- Do away with intel_engine_initialized() and instead directly use the
NULL pointer check on engine pointer. (Chris)
v3:
- Remove for_each_engine_id() macro, as the updated macro for_each_engine()
can be used in place of it. (Chris)
- Protect the access to Render engine Fault register with a NULL check, as
engine specific init is done later in Driver load sequence.
v4:
- Use !!dev_priv->engine[VCS] style for the engine check in getparam. (Chris)
- Kill the superfluous init_engine_lists().
v5:
- Cleanup the intel_engines_init() & intel_engines_setup(), with respect to
allocation of intel_engine_cs structure. (Chris)
v6:
- Rebase.
v7:
- Optimize the for_each_engine_masked() macro. (Chris)
- Change the type of 'iter' local variable to enum intel_engine_id. (Chris)
- Rebase.
v8: Rebase.
v9: Rebase.
v10:
- For index calculation use engine ID instead of pointer based arithmetic in
intel_engine_sync_index() as engine pointers are not contiguous now (Chris)
- For appropriateness, rename local enum variable 'iter' to 'id'. (Joonas)
- Use for_each_engine macro for cleanup in intel_engines_init() and remove
check for NULL engine pointer in cleanup() routines. (Joonas)
v11: Rebase.
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1476378888-7372-1-git-send-email-akash.goel@intel.com
2016-10-14 01:14:48 +08:00
|
|
|
for_each_engine(engine, dev_priv, id) {
|
2013-10-17 00:21:30 +08:00
|
|
|
u32 fault_reg;
|
2016-03-16 19:00:36 +08:00
|
|
|
fault_reg = I915_READ(RING_FAULT_REG(engine));
|
2013-10-17 00:21:30 +08:00
|
|
|
if (fault_reg & RING_FAULT_VALID) {
|
|
|
|
DRM_DEBUG_DRIVER("Unexpected fault\n"
|
2014-10-31 01:52:45 +08:00
|
|
|
"\tAddr: 0x%08lx\n"
|
2013-10-17 00:21:30 +08:00
|
|
|
"\tAddress space: %s\n"
|
|
|
|
"\tSource ID: %d\n"
|
|
|
|
"\tType: %d\n",
|
|
|
|
fault_reg & PAGE_MASK,
|
|
|
|
fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT",
|
|
|
|
RING_FAULT_SRCID(fault_reg),
|
|
|
|
RING_FAULT_FAULT_TYPE(fault_reg));
|
2016-03-16 19:00:36 +08:00
|
|
|
I915_WRITE(RING_FAULT_REG(engine),
|
2013-10-17 00:21:30 +08:00
|
|
|
fault_reg & ~RING_FAULT_VALID);
|
|
|
|
}
|
|
|
|
}
|
drm/i915: Allocate intel_engine_cs structure only for the enabled engines
With the possibility of addition of many more number of rings in future,
the drm_i915_private structure could bloat as an array, of type
intel_engine_cs, is embedded inside it.
struct intel_engine_cs engine[I915_NUM_ENGINES];
Though this is still fine as generally there is only a single instance of
drm_i915_private structure used, but not all of the possible rings would be
enabled or active on most of the platforms. Some memory can be saved by
allocating intel_engine_cs structure only for the enabled/active engines.
Currently the engine/ring ID is kept static and dev_priv->engine[] is simply
indexed using the enums defined in intel_engine_id.
To save memory and continue using the static engine/ring IDs, 'engine' is
defined as an array of pointers.
struct intel_engine_cs *engine[I915_NUM_ENGINES];
dev_priv->engine[engine_ID] will be NULL for disabled engine instances.
There is a text size reduction of 928 bytes, from 1028200 to 1027272, for
i915.o file (but for i915.ko file text size remain same as 1193131 bytes).
v2:
- Remove the engine iterator field added in drm_i915_private structure,
instead pass a local iterator variable to the for_each_engine**
macros. (Chris)
- Do away with intel_engine_initialized() and instead directly use the
NULL pointer check on engine pointer. (Chris)
v3:
- Remove for_each_engine_id() macro, as the updated macro for_each_engine()
can be used in place of it. (Chris)
- Protect the access to Render engine Fault register with a NULL check, as
engine specific init is done later in Driver load sequence.
v4:
- Use !!dev_priv->engine[VCS] style for the engine check in getparam. (Chris)
- Kill the superfluous init_engine_lists().
v5:
- Cleanup the intel_engines_init() & intel_engines_setup(), with respect to
allocation of intel_engine_cs structure. (Chris)
v6:
- Rebase.
v7:
- Optimize the for_each_engine_masked() macro. (Chris)
- Change the type of 'iter' local variable to enum intel_engine_id. (Chris)
- Rebase.
v8: Rebase.
v9: Rebase.
v10:
- For index calculation use engine ID instead of pointer based arithmetic in
intel_engine_sync_index() as engine pointers are not contiguous now (Chris)
- For appropriateness, rename local enum variable 'iter' to 'id'. (Joonas)
- Use for_each_engine macro for cleanup in intel_engines_init() and remove
check for NULL engine pointer in cleanup() routines. (Joonas)
v11: Rebase.
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1476378888-7372-1-git-send-email-akash.goel@intel.com
2016-10-14 01:14:48 +08:00
|
|
|
|
|
|
|
/* Engine specific init may not have been done till this point. */
|
|
|
|
if (dev_priv->engine[RCS])
|
|
|
|
POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS]));
|
2013-10-17 00:21:30 +08:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:13:12 +08:00
|
|
|
static void i915_ggtt_flush(struct drm_i915_private *dev_priv)
|
|
|
|
{
|
2016-04-07 16:08:05 +08:00
|
|
|
if (INTEL_INFO(dev_priv)->gen < 6) {
|
2014-09-25 17:13:12 +08:00
|
|
|
intel_gtt_chipset_flush();
|
|
|
|
} else {
|
|
|
|
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
|
|
|
|
POSTING_READ(GFX_FLSH_CNTL_GEN6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-17 00:21:30 +08:00
|
|
|
void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
|
|
|
|
{
|
2016-03-30 21:57:10 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
2013-10-17 00:21:30 +08:00
|
|
|
|
|
|
|
/* Don't bother messing with faults pre GEN6 as we have little
|
|
|
|
* documentation supporting that it's a good idea.
|
|
|
|
*/
|
|
|
|
if (INTEL_INFO(dev)->gen < 6)
|
|
|
|
return;
|
|
|
|
|
2016-05-10 21:10:04 +08:00
|
|
|
i915_check_and_clear_faults(dev_priv);
|
2013-10-17 00:21:30 +08:00
|
|
|
|
2016-10-13 20:02:40 +08:00
|
|
|
ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total);
|
2014-09-25 17:13:12 +08:00
|
|
|
|
|
|
|
i915_ggtt_flush(dev_priv);
|
2013-10-17 00:21:30 +08:00
|
|
|
}
|
|
|
|
|
2012-02-16 06:50:21 +08:00
|
|
|
int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
|
2010-11-06 17:10:47 +08:00
|
|
|
{
|
2012-06-01 22:20:22 +08:00
|
|
|
if (!dma_map_sg(&obj->base.dev->pdev->dev,
|
|
|
|
obj->pages->sgl, obj->pages->nents,
|
|
|
|
PCI_DMA_BIDIRECTIONAL))
|
|
|
|
return -ENOSPC;
|
|
|
|
|
|
|
|
return 0;
|
2010-11-06 17:10:47 +08:00
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:26 +08:00
|
|
|
static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
|
2013-11-03 12:07:18 +08:00
|
|
|
{
|
|
|
|
writeq(pte, addr);
|
|
|
|
}
|
|
|
|
|
2016-06-10 16:52:59 +08:00
|
|
|
static void gen8_ggtt_insert_page(struct i915_address_space *vm,
|
|
|
|
dma_addr_t addr,
|
|
|
|
uint64_t offset,
|
|
|
|
enum i915_cache_level level,
|
|
|
|
u32 unused)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = to_i915(vm->dev);
|
|
|
|
gen8_pte_t __iomem *pte =
|
|
|
|
(gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
|
|
|
|
(offset >> PAGE_SHIFT);
|
|
|
|
int rpm_atomic_seq;
|
|
|
|
|
|
|
|
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
|
|
|
|
2016-10-13 20:02:40 +08:00
|
|
|
gen8_set_pte(pte, gen8_pte_encode(addr, level));
|
2016-06-10 16:52:59 +08:00
|
|
|
|
|
|
|
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
|
|
|
|
POSTING_READ(GFX_FLSH_CNTL_GEN6);
|
|
|
|
|
|
|
|
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
|
|
|
}
|
|
|
|
|
2013-11-03 12:07:18 +08:00
|
|
|
static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
|
|
|
|
struct sg_table *st,
|
2014-02-21 03:50:33 +08:00
|
|
|
uint64_t start,
|
2014-06-17 13:29:42 +08:00
|
|
|
enum i915_cache_level level, u32 unused)
|
2013-11-03 12:07:18 +08:00
|
|
|
{
|
2016-03-30 21:57:10 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(vm->dev);
|
2016-04-28 16:56:38 +08:00
|
|
|
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
|
2016-05-20 18:54:06 +08:00
|
|
|
struct sgt_iter sgt_iter;
|
|
|
|
gen8_pte_t __iomem *gtt_entries;
|
|
|
|
gen8_pte_t gtt_entry;
|
|
|
|
dma_addr_t addr;
|
2015-12-16 02:10:38 +08:00
|
|
|
int rpm_atomic_seq;
|
2016-05-20 18:54:06 +08:00
|
|
|
int i = 0;
|
2015-12-16 02:10:38 +08:00
|
|
|
|
|
|
|
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
2013-11-03 12:07:18 +08:00
|
|
|
|
2016-05-20 18:54:06 +08:00
|
|
|
gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT);
|
|
|
|
|
|
|
|
for_each_sgt_dma(addr, sgt_iter, st) {
|
2016-10-13 20:02:40 +08:00
|
|
|
gtt_entry = gen8_pte_encode(addr, level);
|
2016-05-20 18:54:06 +08:00
|
|
|
gen8_set_pte(>t_entries[i++], gtt_entry);
|
2013-11-03 12:07:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX: This serves as a posting read to make sure that the PTE has
|
|
|
|
* actually been updated. There is some concern that even though
|
|
|
|
* registers and PTEs are within the same BAR that they are potentially
|
|
|
|
* of NUMA access patterns. Therefore, even with the way we assume
|
|
|
|
* hardware should work, we must keep this posting read for paranoia.
|
|
|
|
*/
|
|
|
|
if (i != 0)
|
2016-05-20 18:54:06 +08:00
|
|
|
WARN_ON(readq(>t_entries[i-1]) != gtt_entry);
|
2013-11-03 12:07:18 +08:00
|
|
|
|
|
|
|
/* This next bit makes the above posting read even more important. We
|
|
|
|
* want to flush the TLBs only after we're certain all the PTE updates
|
|
|
|
* have finished.
|
|
|
|
*/
|
|
|
|
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
|
|
|
|
POSTING_READ(GFX_FLSH_CNTL_GEN6);
|
2015-12-16 02:10:38 +08:00
|
|
|
|
|
|
|
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
2013-11-03 12:07:18 +08:00
|
|
|
}
|
|
|
|
|
2015-11-18 23:19:39 +08:00
|
|
|
struct insert_entries {
|
|
|
|
struct i915_address_space *vm;
|
|
|
|
struct sg_table *st;
|
|
|
|
uint64_t start;
|
|
|
|
enum i915_cache_level level;
|
|
|
|
u32 flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int gen8_ggtt_insert_entries__cb(void *_arg)
|
|
|
|
{
|
|
|
|
struct insert_entries *arg = _arg;
|
|
|
|
gen8_ggtt_insert_entries(arg->vm, arg->st,
|
|
|
|
arg->start, arg->level, arg->flags);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void gen8_ggtt_insert_entries__BKL(struct i915_address_space *vm,
|
|
|
|
struct sg_table *st,
|
|
|
|
uint64_t start,
|
|
|
|
enum i915_cache_level level,
|
|
|
|
u32 flags)
|
|
|
|
{
|
|
|
|
struct insert_entries arg = { vm, st, start, level, flags };
|
|
|
|
stop_machine(gen8_ggtt_insert_entries__cb, &arg, NULL);
|
|
|
|
}
|
|
|
|
|
2016-06-10 16:52:59 +08:00
|
|
|
static void gen6_ggtt_insert_page(struct i915_address_space *vm,
|
|
|
|
dma_addr_t addr,
|
|
|
|
uint64_t offset,
|
|
|
|
enum i915_cache_level level,
|
|
|
|
u32 flags)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = to_i915(vm->dev);
|
|
|
|
gen6_pte_t __iomem *pte =
|
|
|
|
(gen6_pte_t __iomem *)dev_priv->ggtt.gsm +
|
|
|
|
(offset >> PAGE_SHIFT);
|
|
|
|
int rpm_atomic_seq;
|
|
|
|
|
|
|
|
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
|
|
|
|
2016-10-13 20:02:40 +08:00
|
|
|
iowrite32(vm->pte_encode(addr, level, flags), pte);
|
2016-06-10 16:52:59 +08:00
|
|
|
|
|
|
|
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
|
|
|
|
POSTING_READ(GFX_FLSH_CNTL_GEN6);
|
|
|
|
|
|
|
|
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
|
|
|
}
|
|
|
|
|
2012-11-05 01:21:27 +08:00
|
|
|
/*
|
|
|
|
* Binds an object into the global gtt with the specified cache level. The object
|
|
|
|
* will be accessible to the GPU via commands whose operands reference offsets
|
|
|
|
* within the global GTT as well as accessible by the GPU through the GMADR
|
|
|
|
* mapped BAR (dev_priv->mm.gtt->gtt).
|
|
|
|
*/
|
2013-07-17 07:50:05 +08:00
|
|
|
static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
|
2013-01-25 06:44:55 +08:00
|
|
|
struct sg_table *st,
|
2014-02-21 03:50:33 +08:00
|
|
|
uint64_t start,
|
2014-06-17 13:29:42 +08:00
|
|
|
enum i915_cache_level level, u32 flags)
|
2012-11-05 01:21:27 +08:00
|
|
|
{
|
2016-03-30 21:57:10 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(vm->dev);
|
2016-04-28 16:56:38 +08:00
|
|
|
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
|
2016-05-20 18:54:06 +08:00
|
|
|
struct sgt_iter sgt_iter;
|
|
|
|
gen6_pte_t __iomem *gtt_entries;
|
|
|
|
gen6_pte_t gtt_entry;
|
|
|
|
dma_addr_t addr;
|
2015-12-16 02:10:38 +08:00
|
|
|
int rpm_atomic_seq;
|
2016-05-20 18:54:06 +08:00
|
|
|
int i = 0;
|
2015-12-16 02:10:38 +08:00
|
|
|
|
|
|
|
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
2012-11-05 01:21:27 +08:00
|
|
|
|
2016-05-20 18:54:06 +08:00
|
|
|
gtt_entries = (gen6_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT);
|
|
|
|
|
|
|
|
for_each_sgt_dma(addr, sgt_iter, st) {
|
2016-10-13 20:02:40 +08:00
|
|
|
gtt_entry = vm->pte_encode(addr, level, flags);
|
2016-05-20 18:54:06 +08:00
|
|
|
iowrite32(gtt_entry, >t_entries[i++]);
|
2012-11-05 01:21:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: This serves as a posting read to make sure that the PTE has
|
|
|
|
* actually been updated. There is some concern that even though
|
|
|
|
* registers and PTEs are within the same BAR that they are potentially
|
|
|
|
* of NUMA access patterns. Therefore, even with the way we assume
|
|
|
|
* hardware should work, we must keep this posting read for paranoia.
|
|
|
|
*/
|
2016-05-20 18:54:06 +08:00
|
|
|
if (i != 0)
|
|
|
|
WARN_ON(readl(>t_entries[i-1]) != gtt_entry);
|
2012-11-05 01:21:30 +08:00
|
|
|
|
|
|
|
/* This next bit makes the above posting read even more important. We
|
|
|
|
* want to flush the TLBs only after we're certain all the PTE updates
|
|
|
|
* have finished.
|
|
|
|
*/
|
|
|
|
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
|
|
|
|
POSTING_READ(GFX_FLSH_CNTL_GEN6);
|
2015-12-16 02:10:38 +08:00
|
|
|
|
|
|
|
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
2012-11-05 01:21:27 +08:00
|
|
|
}
|
|
|
|
|
2016-05-14 14:26:35 +08:00
|
|
|
static void nop_clear_range(struct i915_address_space *vm,
|
2016-10-13 20:02:40 +08:00
|
|
|
uint64_t start, uint64_t length)
|
2016-05-14 14:26:35 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-11-03 12:07:18 +08:00
|
|
|
static void gen8_ggtt_clear_range(struct i915_address_space *vm,
|
2016-10-13 20:02:40 +08:00
|
|
|
uint64_t start, uint64_t length)
|
2013-11-03 12:07:18 +08:00
|
|
|
{
|
2016-03-30 21:57:10 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(vm->dev);
|
2016-04-28 16:56:38 +08:00
|
|
|
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
|
2014-02-21 03:50:33 +08:00
|
|
|
unsigned first_entry = start >> PAGE_SHIFT;
|
|
|
|
unsigned num_entries = length >> PAGE_SHIFT;
|
2015-03-17 00:00:54 +08:00
|
|
|
gen8_pte_t scratch_pte, __iomem *gtt_base =
|
2016-03-30 21:57:10 +08:00
|
|
|
(gen8_pte_t __iomem *)ggtt->gsm + first_entry;
|
|
|
|
const int max_entries = ggtt_total_entries(ggtt) - first_entry;
|
2013-11-03 12:07:18 +08:00
|
|
|
int i;
|
2015-12-16 02:10:38 +08:00
|
|
|
int rpm_atomic_seq;
|
|
|
|
|
|
|
|
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
2013-11-03 12:07:18 +08:00
|
|
|
|
|
|
|
if (WARN(num_entries > max_entries,
|
|
|
|
"First entry = %d; Num entries = %d (max=%d)\n",
|
|
|
|
first_entry, num_entries, max_entries))
|
|
|
|
num_entries = max_entries;
|
|
|
|
|
2016-08-22 15:44:30 +08:00
|
|
|
scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
|
2016-10-13 20:02:40 +08:00
|
|
|
I915_CACHE_LLC);
|
2013-11-03 12:07:18 +08:00
|
|
|
for (i = 0; i < num_entries; i++)
|
|
|
|
gen8_set_pte(>t_base[i], scratch_pte);
|
|
|
|
readl(gtt_base);
|
2015-12-16 02:10:38 +08:00
|
|
|
|
|
|
|
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
2013-11-03 12:07:18 +08:00
|
|
|
}
|
|
|
|
|
2013-07-17 07:50:05 +08:00
|
|
|
static void gen6_ggtt_clear_range(struct i915_address_space *vm,
|
2014-02-21 03:50:33 +08:00
|
|
|
uint64_t start,
|
2016-10-13 20:02:40 +08:00
|
|
|
uint64_t length)
|
2013-01-25 06:44:55 +08:00
|
|
|
{
|
2016-03-30 21:57:10 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(vm->dev);
|
2016-04-28 16:56:38 +08:00
|
|
|
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
|
2014-02-21 03:50:33 +08:00
|
|
|
unsigned first_entry = start >> PAGE_SHIFT;
|
|
|
|
unsigned num_entries = length >> PAGE_SHIFT;
|
2015-03-17 00:00:54 +08:00
|
|
|
gen6_pte_t scratch_pte, __iomem *gtt_base =
|
2016-03-30 21:57:10 +08:00
|
|
|
(gen6_pte_t __iomem *)ggtt->gsm + first_entry;
|
|
|
|
const int max_entries = ggtt_total_entries(ggtt) - first_entry;
|
2013-01-25 06:44:55 +08:00
|
|
|
int i;
|
2015-12-16 02:10:38 +08:00
|
|
|
int rpm_atomic_seq;
|
|
|
|
|
|
|
|
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
2013-01-25 06:44:55 +08:00
|
|
|
|
|
|
|
if (WARN(num_entries > max_entries,
|
|
|
|
"First entry = %d; Num entries = %d (max=%d)\n",
|
|
|
|
first_entry, num_entries, max_entries))
|
|
|
|
num_entries = max_entries;
|
|
|
|
|
2016-08-22 15:44:30 +08:00
|
|
|
scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
|
2016-10-13 20:02:40 +08:00
|
|
|
I915_CACHE_LLC, 0);
|
2013-10-17 00:21:30 +08:00
|
|
|
|
2013-01-25 06:44:55 +08:00
|
|
|
for (i = 0; i < num_entries; i++)
|
|
|
|
iowrite32(scratch_pte, >t_base[i]);
|
|
|
|
readl(gtt_base);
|
2015-12-16 02:10:38 +08:00
|
|
|
|
|
|
|
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
2013-01-25 06:44:55 +08:00
|
|
|
}
|
|
|
|
|
2016-06-10 16:52:59 +08:00
|
|
|
static void i915_ggtt_insert_page(struct i915_address_space *vm,
|
|
|
|
dma_addr_t addr,
|
|
|
|
uint64_t offset,
|
|
|
|
enum i915_cache_level cache_level,
|
|
|
|
u32 unused)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = to_i915(vm->dev);
|
|
|
|
unsigned int flags = (cache_level == I915_CACHE_NONE) ?
|
|
|
|
AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
|
|
|
|
int rpm_atomic_seq;
|
|
|
|
|
|
|
|
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
|
|
|
|
|
|
|
intel_gtt_insert_page(addr, offset >> PAGE_SHIFT, flags);
|
|
|
|
|
|
|
|
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:25 +08:00
|
|
|
static void i915_ggtt_insert_entries(struct i915_address_space *vm,
|
|
|
|
struct sg_table *pages,
|
|
|
|
uint64_t start,
|
|
|
|
enum i915_cache_level cache_level, u32 unused)
|
2013-01-25 06:44:55 +08:00
|
|
|
{
|
2016-07-04 18:34:36 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(vm->dev);
|
2013-01-25 06:44:55 +08:00
|
|
|
unsigned int flags = (cache_level == I915_CACHE_NONE) ?
|
|
|
|
AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
|
2015-12-16 02:10:38 +08:00
|
|
|
int rpm_atomic_seq;
|
|
|
|
|
|
|
|
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
2013-01-25 06:44:55 +08:00
|
|
|
|
2015-04-14 23:35:25 +08:00
|
|
|
intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags);
|
2015-04-21 00:04:05 +08:00
|
|
|
|
2015-12-16 02:10:38 +08:00
|
|
|
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
|
|
|
|
2013-01-25 06:44:55 +08:00
|
|
|
}
|
|
|
|
|
2013-07-17 07:50:05 +08:00
|
|
|
static void i915_ggtt_clear_range(struct i915_address_space *vm,
|
2014-02-21 03:50:33 +08:00
|
|
|
uint64_t start,
|
2016-10-13 20:02:40 +08:00
|
|
|
uint64_t length)
|
2013-01-25 06:44:55 +08:00
|
|
|
{
|
2016-07-04 18:34:36 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(vm->dev);
|
2014-02-21 03:50:33 +08:00
|
|
|
unsigned first_entry = start >> PAGE_SHIFT;
|
|
|
|
unsigned num_entries = length >> PAGE_SHIFT;
|
2015-12-16 02:10:38 +08:00
|
|
|
int rpm_atomic_seq;
|
|
|
|
|
|
|
|
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
|
|
|
|
2013-01-25 06:44:55 +08:00
|
|
|
intel_gtt_clear_range(first_entry, num_entries);
|
2015-12-16 02:10:38 +08:00
|
|
|
|
|
|
|
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
2013-01-25 06:44:55 +08:00
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:27 +08:00
|
|
|
static int ggtt_bind_vma(struct i915_vma *vma,
|
|
|
|
enum i915_cache_level cache_level,
|
|
|
|
u32 flags)
|
2015-10-15 20:23:01 +08:00
|
|
|
{
|
|
|
|
struct drm_i915_gem_object *obj = vma->obj;
|
|
|
|
u32 pte_flags = 0;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = i915_get_ggtt_vma_pages(vma);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
/* Currently applicable only to VLV */
|
|
|
|
if (obj->gt_ro)
|
|
|
|
pte_flags |= PTE_READ_ONLY;
|
|
|
|
|
2016-08-15 17:48:47 +08:00
|
|
|
vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start,
|
2015-10-15 20:23:01 +08:00
|
|
|
cache_level, pte_flags);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Without aliasing PPGTT there's no difference between
|
|
|
|
* GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
|
|
|
|
* upgrade to both bound if we bind either to avoid double-binding.
|
|
|
|
*/
|
2016-08-04 23:32:32 +08:00
|
|
|
vma->flags |= I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
|
2015-10-15 20:23:01 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aliasing_gtt_bind_vma(struct i915_vma *vma,
|
|
|
|
enum i915_cache_level cache_level,
|
|
|
|
u32 flags)
|
2011-04-14 13:48:26 +08:00
|
|
|
{
|
2015-11-20 18:27:18 +08:00
|
|
|
u32 pte_flags;
|
2015-04-14 23:35:27 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = i915_get_ggtt_vma_pages(vma);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2013-01-25 06:44:55 +08:00
|
|
|
|
2014-06-17 13:29:42 +08:00
|
|
|
/* Currently applicable only to VLV */
|
2015-11-20 18:27:18 +08:00
|
|
|
pte_flags = 0;
|
|
|
|
if (vma->obj->gt_ro)
|
2015-04-14 23:35:15 +08:00
|
|
|
pte_flags |= PTE_READ_ONLY;
|
2014-06-17 13:29:42 +08:00
|
|
|
|
2015-03-16 20:11:13 +08:00
|
|
|
|
2016-08-04 23:32:32 +08:00
|
|
|
if (flags & I915_VMA_GLOBAL_BIND) {
|
2015-11-20 18:27:18 +08:00
|
|
|
vma->vm->insert_entries(vma->vm,
|
2016-08-15 17:48:47 +08:00
|
|
|
vma->pages, vma->node.start,
|
2015-04-21 00:04:05 +08:00
|
|
|
cache_level, pte_flags);
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
}
|
2011-04-14 13:48:26 +08:00
|
|
|
|
2016-08-04 23:32:32 +08:00
|
|
|
if (flags & I915_VMA_LOCAL_BIND) {
|
2015-11-20 18:27:18 +08:00
|
|
|
struct i915_hw_ppgtt *appgtt =
|
|
|
|
to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
|
|
|
|
appgtt->base.insert_entries(&appgtt->base,
|
2016-08-15 17:48:47 +08:00
|
|
|
vma->pages, vma->node.start,
|
2015-04-14 23:35:15 +08:00
|
|
|
cache_level, pte_flags);
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
}
|
2015-04-14 23:35:27 +08:00
|
|
|
|
|
|
|
return 0;
|
2011-04-14 13:48:26 +08:00
|
|
|
}
|
|
|
|
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
static void ggtt_unbind_vma(struct i915_vma *vma)
|
2012-02-16 06:50:21 +08:00
|
|
|
{
|
2016-08-04 23:32:29 +08:00
|
|
|
struct i915_hw_ppgtt *appgtt = to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
|
|
|
|
const u64 size = min(vma->size, vma->node.size);
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
|
2016-08-04 23:32:32 +08:00
|
|
|
if (vma->flags & I915_VMA_GLOBAL_BIND)
|
2014-02-21 03:50:33 +08:00
|
|
|
vma->vm->clear_range(vma->vm,
|
2016-10-13 20:02:40 +08:00
|
|
|
vma->node.start, size);
|
2015-04-24 20:09:03 +08:00
|
|
|
|
2016-08-04 23:32:32 +08:00
|
|
|
if (vma->flags & I915_VMA_LOCAL_BIND && appgtt)
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
appgtt->base.clear_range(&appgtt->base,
|
2016-10-13 20:02:40 +08:00
|
|
|
vma->node.start, size);
|
2012-02-16 06:50:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
|
2010-11-06 17:10:47 +08:00
|
|
|
{
|
2016-08-22 18:32:44 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
|
|
|
|
struct device *kdev = &dev_priv->drm.pdev->dev;
|
2016-08-05 17:14:12 +08:00
|
|
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
2011-10-18 06:51:55 +08:00
|
|
|
|
2016-08-05 17:14:12 +08:00
|
|
|
if (unlikely(ggtt->do_idle_maps)) {
|
2016-09-09 21:11:50 +08:00
|
|
|
if (i915_gem_wait_for_idle(dev_priv, I915_WAIT_LOCKED)) {
|
2016-08-05 17:14:12 +08:00
|
|
|
DRM_ERROR("Failed to wait for idle; VT'd may hang.\n");
|
|
|
|
/* Wait a bit, in hopes it avoids the hang */
|
|
|
|
udelay(10);
|
|
|
|
}
|
|
|
|
}
|
2011-10-18 06:51:55 +08:00
|
|
|
|
2016-08-22 18:32:44 +08:00
|
|
|
dma_unmap_sg(kdev, obj->pages->sgl, obj->pages->nents,
|
2015-07-09 00:18:59 +08:00
|
|
|
PCI_DMA_BIDIRECTIONAL);
|
2010-11-06 17:10:47 +08:00
|
|
|
}
|
2012-03-26 15:45:40 +08:00
|
|
|
|
2012-07-26 18:49:32 +08:00
|
|
|
static void i915_gtt_color_adjust(struct drm_mm_node *node,
|
|
|
|
unsigned long color,
|
2015-01-23 16:05:06 +08:00
|
|
|
u64 *start,
|
|
|
|
u64 *end)
|
2012-07-26 18:49:32 +08:00
|
|
|
{
|
|
|
|
if (node->color != color)
|
|
|
|
*start += 4096;
|
|
|
|
|
2016-07-26 19:01:51 +08:00
|
|
|
node = list_first_entry_or_null(&node->node_list,
|
|
|
|
struct drm_mm_node,
|
|
|
|
node_list);
|
|
|
|
if (node && node->allocated && node->color != color)
|
|
|
|
*end -= 4096;
|
2012-07-26 18:49:32 +08:00
|
|
|
}
|
2013-11-05 11:56:49 +08:00
|
|
|
|
2016-08-04 14:52:23 +08:00
|
|
|
int i915_gem_init_ggtt(struct drm_i915_private *dev_priv)
|
2012-03-26 15:45:40 +08:00
|
|
|
{
|
2013-01-26 08:41:04 +08:00
|
|
|
/* Let GEM Manage all of the aperture.
|
|
|
|
*
|
|
|
|
* However, leave one page at the end still bound to the scratch page.
|
|
|
|
* There are a number of places where the hardware apparently prefetches
|
|
|
|
* past the end of the object, and we've seen multiple hangs with the
|
|
|
|
* GPU head pointer stuck in a batchbuffer bound at the last page of the
|
|
|
|
* aperture. One page should be enough to keep any prefetching inside
|
|
|
|
* of the aperture.
|
|
|
|
*/
|
2016-03-30 21:57:10 +08:00
|
|
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
2012-11-15 19:32:19 +08:00
|
|
|
unsigned long hole_start, hole_end;
|
2016-10-12 17:05:20 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt;
|
2016-08-04 14:52:23 +08:00
|
|
|
struct drm_mm_node *entry;
|
2014-08-07 02:19:54 +08:00
|
|
|
int ret;
|
2012-03-26 15:45:40 +08:00
|
|
|
|
2016-06-16 20:06:59 +08:00
|
|
|
ret = intel_vgt_balloon(dev_priv);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2015-02-10 19:05:48 +08:00
|
|
|
|
2016-10-12 17:05:20 +08:00
|
|
|
/* Reserve a mappable slot for our lockless error capture */
|
|
|
|
ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm,
|
|
|
|
&ggtt->error_capture,
|
|
|
|
4096, 0, -1,
|
|
|
|
0, ggtt->mappable_end,
|
|
|
|
0, 0);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2012-11-15 19:32:19 +08:00
|
|
|
/* Clear any non-preallocated blocks */
|
2016-03-30 21:57:10 +08:00
|
|
|
drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) {
|
2012-11-15 19:32:19 +08:00
|
|
|
DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
|
|
|
|
hole_start, hole_end);
|
2016-03-30 21:57:10 +08:00
|
|
|
ggtt->base.clear_range(&ggtt->base, hole_start,
|
2016-10-13 20:02:40 +08:00
|
|
|
hole_end - hole_start);
|
2012-11-15 19:32:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* And finally clear the reserved guard page */
|
2016-08-04 14:52:23 +08:00
|
|
|
ggtt->base.clear_range(&ggtt->base,
|
2016-10-13 20:02:40 +08:00
|
|
|
ggtt->base.total - PAGE_SIZE, PAGE_SIZE);
|
2014-08-06 21:04:50 +08:00
|
|
|
|
2016-08-04 14:52:22 +08:00
|
|
|
if (USES_PPGTT(dev_priv) && !USES_FULL_PPGTT(dev_priv)) {
|
2014-08-07 02:19:54 +08:00
|
|
|
ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
|
2016-10-12 17:05:20 +08:00
|
|
|
if (!ppgtt) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto err;
|
|
|
|
}
|
2014-08-07 02:19:54 +08:00
|
|
|
|
2016-08-04 14:52:25 +08:00
|
|
|
ret = __hw_ppgtt_init(ppgtt, dev_priv);
|
2016-10-12 17:05:20 +08:00
|
|
|
if (ret)
|
|
|
|
goto err_ppgtt;
|
2015-04-14 23:35:14 +08:00
|
|
|
|
2016-10-12 17:05:20 +08:00
|
|
|
if (ppgtt->base.allocate_va_range) {
|
2015-04-14 23:35:14 +08:00
|
|
|
ret = ppgtt->base.allocate_va_range(&ppgtt->base, 0,
|
|
|
|
ppgtt->base.total);
|
2016-10-12 17:05:20 +08:00
|
|
|
if (ret)
|
|
|
|
goto err_ppgtt_cleanup;
|
drm/i915: Finish gen6/7 dynamic page table allocation
This patch continues on the idea from "Track GEN6 page table usage".
From here on, in the steady state, PDEs are all pointing to the scratch
page table (as recommended in the spec). When an object is allocated in
the VA range, the code will determine if we need to allocate a page for
the page table. Similarly when the object is destroyed, we will remove,
and free the page table pointing the PDE back to the scratch page.
Following patches will work to unify the code a bit as we bring in GEN8
support. GEN6 and GEN8 are different enough that I had a hard time to
get to this point with as much common code as I do.
The aliasing PPGTT must pre-allocate all of the page tables. There are a
few reasons for this. Two trivial ones: aliasing ppgtt goes through the
ggtt paths, so it's hard to maintain, we currently do not restore the
default context (assuming the previous force reload is indeed
necessary). Most importantly though, the only way (it seems from
empirical evidence) to invalidate the CS TLBs on non-render ring is to
either use ring sync (which requires actually stopping the rings in
order to synchronize when the sync completes vs. where you are in
execution), or to reload DCLV. Since without full PPGTT we do not ever
reload the DCLV register, there is no good way to achieve this. The
simplest solution is just to not support dynamic page table
creation/destruction in the aliasing PPGTT.
We could always reload DCLV, but this seems like quite a bit of excess
overhead only to save at most 2MB-4k of memory for the aliasing PPGTT
page tables.
v2: Make the page table bitmap declared inside the function (Chris)
Simplify the way scratching address space works.
Move the alloc/teardown tracepoints up a level in the call stack so that
both all implementations get the trace.
v3: Updated trace event to spit out a name
v4: Aliasing ppgtt is now initialized differently (in setup global gtt)
v5: Rebase to latest code. Also removed unnecessary aliasing ppgtt check
for trace, as it is no longer possible after the PPGTT cleanup patch series
of a couple of months ago (Daniel).
v6: Implement changes from code review (Daniel):
- allocate/teardown_va_range calls added.
- Add a scratch page allocation helper (only need the address).
- Move trace events to a new patch.
- Use updated mark_tlbs_dirty.
- Moved pt preallocation for aliasing ppgtt into gen6_ppgtt_init.
v7: teardown_va_range removed (Daniel).
In init, gen6_ppgtt_clear_range call is only needed for aliasing ppgtt.
v8: Rebase after s/page_tables/page_table/.
v9: Remove unnecessary scratch flag in page_table struct, future patches
can just compare against ppgtt->scratch_pt, and alloc_pt_scratch becomes
redundant. Initialize scratch_pt and pt. (Mika)
v10: Clean up aliasing ppgtt init error path and prevent leaking the
ppgtt obj when init fails. (Mika)
Updated commit author. (Daniel)
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Michel Thierry <michel.thierry@intel.com> (v4+)
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-03-24 23:46:22 +08:00
|
|
|
}
|
2014-08-07 02:19:54 +08:00
|
|
|
|
2015-04-14 23:35:14 +08:00
|
|
|
ppgtt->base.clear_range(&ppgtt->base,
|
|
|
|
ppgtt->base.start,
|
2016-10-13 20:02:40 +08:00
|
|
|
ppgtt->base.total);
|
2015-04-14 23:35:14 +08:00
|
|
|
|
2014-08-07 02:19:54 +08:00
|
|
|
dev_priv->mm.aliasing_ppgtt = ppgtt;
|
2016-03-30 21:57:10 +08:00
|
|
|
WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma);
|
|
|
|
ggtt->base.bind_vma = aliasing_gtt_bind_vma;
|
2014-08-07 02:19:54 +08:00
|
|
|
}
|
|
|
|
|
2014-08-06 21:04:50 +08:00
|
|
|
return 0;
|
2016-10-12 17:05:20 +08:00
|
|
|
|
|
|
|
err_ppgtt_cleanup:
|
|
|
|
ppgtt->base.cleanup(&ppgtt->base);
|
|
|
|
err_ppgtt:
|
|
|
|
kfree(ppgtt);
|
|
|
|
err:
|
|
|
|
drm_mm_remove_node(&ggtt->error_capture);
|
|
|
|
return ret;
|
2012-11-05 01:21:27 +08:00
|
|
|
}
|
|
|
|
|
2016-03-24 22:47:46 +08:00
|
|
|
/**
|
|
|
|
* i915_ggtt_cleanup_hw - Clean up GGTT hardware initialization
|
2016-08-04 14:52:22 +08:00
|
|
|
* @dev_priv: i915 device
|
2016-03-24 22:47:46 +08:00
|
|
|
*/
|
2016-08-04 14:52:22 +08:00
|
|
|
void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv)
|
2014-08-06 21:04:56 +08:00
|
|
|
{
|
2016-03-30 21:57:10 +08:00
|
|
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
2014-08-06 21:04:56 +08:00
|
|
|
|
2014-08-06 21:04:57 +08:00
|
|
|
if (dev_priv->mm.aliasing_ppgtt) {
|
|
|
|
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
|
|
|
|
ppgtt->base.cleanup(&ppgtt->base);
|
2016-08-06 02:04:40 +08:00
|
|
|
kfree(ppgtt);
|
2014-08-06 21:04:57 +08:00
|
|
|
}
|
|
|
|
|
2016-08-04 14:52:22 +08:00
|
|
|
i915_gem_cleanup_stolen(&dev_priv->drm);
|
2016-01-19 21:26:32 +08:00
|
|
|
|
2016-10-12 17:05:20 +08:00
|
|
|
if (drm_mm_node_allocated(&ggtt->error_capture))
|
|
|
|
drm_mm_remove_node(&ggtt->error_capture);
|
|
|
|
|
2016-03-30 21:57:10 +08:00
|
|
|
if (drm_mm_initialized(&ggtt->base.mm)) {
|
2016-06-16 20:06:59 +08:00
|
|
|
intel_vgt_deballoon(dev_priv);
|
2015-02-10 19:05:48 +08:00
|
|
|
|
2016-03-30 21:57:10 +08:00
|
|
|
drm_mm_takedown(&ggtt->base.mm);
|
|
|
|
list_del(&ggtt->base.global_link);
|
2014-08-06 21:04:56 +08:00
|
|
|
}
|
|
|
|
|
2016-03-30 21:57:10 +08:00
|
|
|
ggtt->base.cleanup(&ggtt->base);
|
2016-08-04 14:52:23 +08:00
|
|
|
|
|
|
|
arch_phys_wc_del(ggtt->mtrr);
|
2016-08-19 23:54:27 +08:00
|
|
|
io_mapping_fini(&ggtt->mappable);
|
2014-08-06 21:04:56 +08:00
|
|
|
}
|
2014-08-06 21:04:57 +08:00
|
|
|
|
2015-04-14 23:35:26 +08:00
|
|
|
static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl)
|
2012-11-05 01:21:27 +08:00
|
|
|
{
|
|
|
|
snb_gmch_ctl >>= SNB_GMCH_GGMS_SHIFT;
|
|
|
|
snb_gmch_ctl &= SNB_GMCH_GGMS_MASK;
|
|
|
|
return snb_gmch_ctl << 20;
|
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:26 +08:00
|
|
|
static unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl)
|
2013-11-04 08:53:55 +08:00
|
|
|
{
|
|
|
|
bdw_gmch_ctl >>= BDW_GMCH_GGMS_SHIFT;
|
|
|
|
bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK;
|
|
|
|
if (bdw_gmch_ctl)
|
|
|
|
bdw_gmch_ctl = 1 << bdw_gmch_ctl;
|
2014-05-28 07:53:08 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_X86_32
|
|
|
|
/* Limit 32b platforms to a 2GB GGTT: 4 << 20 / pte size * PAGE_SIZE */
|
|
|
|
if (bdw_gmch_ctl > 4)
|
|
|
|
bdw_gmch_ctl = 4;
|
|
|
|
#endif
|
|
|
|
|
2013-11-04 08:53:55 +08:00
|
|
|
return bdw_gmch_ctl << 20;
|
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:26 +08:00
|
|
|
static unsigned int chv_get_total_gtt_size(u16 gmch_ctrl)
|
2014-05-09 03:19:40 +08:00
|
|
|
{
|
|
|
|
gmch_ctrl >>= SNB_GMCH_GGMS_SHIFT;
|
|
|
|
gmch_ctrl &= SNB_GMCH_GGMS_MASK;
|
|
|
|
|
|
|
|
if (gmch_ctrl)
|
|
|
|
return 1 << (20 + gmch_ctrl);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:26 +08:00
|
|
|
static size_t gen6_get_stolen_size(u16 snb_gmch_ctl)
|
2012-11-05 01:21:27 +08:00
|
|
|
{
|
|
|
|
snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT;
|
|
|
|
snb_gmch_ctl &= SNB_GMCH_GMS_MASK;
|
|
|
|
return snb_gmch_ctl << 25; /* 32 MB units */
|
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:26 +08:00
|
|
|
static size_t gen8_get_stolen_size(u16 bdw_gmch_ctl)
|
2013-11-04 08:53:55 +08:00
|
|
|
{
|
|
|
|
bdw_gmch_ctl >>= BDW_GMCH_GMS_SHIFT;
|
|
|
|
bdw_gmch_ctl &= BDW_GMCH_GMS_MASK;
|
|
|
|
return bdw_gmch_ctl << 25; /* 32 MB units */
|
|
|
|
}
|
|
|
|
|
2014-05-09 03:19:40 +08:00
|
|
|
static size_t chv_get_stolen_size(u16 gmch_ctrl)
|
|
|
|
{
|
|
|
|
gmch_ctrl >>= SNB_GMCH_GMS_SHIFT;
|
|
|
|
gmch_ctrl &= SNB_GMCH_GMS_MASK;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 0x0 to 0x10: 32MB increments starting at 0MB
|
|
|
|
* 0x11 to 0x16: 4MB increments starting at 8MB
|
|
|
|
* 0x17 to 0x1d: 4MB increments start at 36MB
|
|
|
|
*/
|
|
|
|
if (gmch_ctrl < 0x11)
|
|
|
|
return gmch_ctrl << 25;
|
|
|
|
else if (gmch_ctrl < 0x17)
|
|
|
|
return (gmch_ctrl - 0x11 + 2) << 22;
|
|
|
|
else
|
|
|
|
return (gmch_ctrl - 0x17 + 9) << 22;
|
|
|
|
}
|
|
|
|
|
2014-01-10 02:02:46 +08:00
|
|
|
static size_t gen9_get_stolen_size(u16 gen9_gmch_ctl)
|
|
|
|
{
|
|
|
|
gen9_gmch_ctl >>= BDW_GMCH_GMS_SHIFT;
|
|
|
|
gen9_gmch_ctl &= BDW_GMCH_GMS_MASK;
|
|
|
|
|
|
|
|
if (gen9_gmch_ctl < 0xf0)
|
|
|
|
return gen9_gmch_ctl << 25; /* 32 MB units */
|
|
|
|
else
|
|
|
|
/* 4MB increments starting at 0xf0 for 4MB */
|
|
|
|
return (gen9_gmch_ctl - 0xf0 + 1) << 22;
|
|
|
|
}
|
|
|
|
|
2016-08-04 14:52:24 +08:00
|
|
|
static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
|
2013-11-05 11:32:22 +08:00
|
|
|
{
|
2016-08-04 14:52:24 +08:00
|
|
|
struct pci_dev *pdev = ggtt->base.dev->pdev;
|
|
|
|
phys_addr_t phys_addr;
|
2016-08-22 15:44:30 +08:00
|
|
|
int ret;
|
2013-11-05 11:32:22 +08:00
|
|
|
|
|
|
|
/* For Modern GENs the PTEs and register space are split in the BAR */
|
2016-08-04 14:52:24 +08:00
|
|
|
phys_addr = pci_resource_start(pdev, 0) + pci_resource_len(pdev, 0) / 2;
|
2013-11-05 11:32:22 +08:00
|
|
|
|
2015-03-27 19:07:33 +08:00
|
|
|
/*
|
|
|
|
* On BXT writes larger than 64 bit to the GTT pagetable range will be
|
|
|
|
* dropped. For WC mappings in general we have 64 byte burst writes
|
|
|
|
* when the WC buffer is flushed, so we can't use it, but have to
|
|
|
|
* resort to an uncached mapping. The WC issue is easily caught by the
|
|
|
|
* readback check when writing GTT PTE entries.
|
|
|
|
*/
|
2016-10-13 18:03:04 +08:00
|
|
|
if (IS_BROXTON(to_i915(ggtt->base.dev)))
|
2016-08-04 14:52:24 +08:00
|
|
|
ggtt->gsm = ioremap_nocache(phys_addr, size);
|
2015-03-27 19:07:33 +08:00
|
|
|
else
|
2016-08-04 14:52:24 +08:00
|
|
|
ggtt->gsm = ioremap_wc(phys_addr, size);
|
2016-03-30 21:57:10 +08:00
|
|
|
if (!ggtt->gsm) {
|
2016-08-04 14:52:24 +08:00
|
|
|
DRM_ERROR("Failed to map the ggtt page table\n");
|
2013-11-05 11:32:22 +08:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2016-08-22 15:44:31 +08:00
|
|
|
ret = setup_scratch_page(ggtt->base.dev,
|
|
|
|
&ggtt->base.scratch_page,
|
|
|
|
GFP_DMA32);
|
2016-08-22 15:44:30 +08:00
|
|
|
if (ret) {
|
2013-11-05 11:32:22 +08:00
|
|
|
DRM_ERROR("Scratch setup failed\n");
|
|
|
|
/* iounmap will also get called at remove, but meh */
|
2016-03-30 21:57:10 +08:00
|
|
|
iounmap(ggtt->gsm);
|
2016-08-22 15:44:30 +08:00
|
|
|
return ret;
|
2013-11-05 11:32:22 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 23:16:39 +08:00
|
|
|
return 0;
|
2013-11-05 11:32:22 +08:00
|
|
|
}
|
|
|
|
|
2013-11-05 11:56:49 +08:00
|
|
|
/* The GGTT and PPGTT need a private PPAT setup in order to handle cacheability
|
|
|
|
* bits. When using advanced contexts each context stores its own PAT, but
|
|
|
|
* writing this data shouldn't be harmful even in those cases. */
|
2014-04-09 18:28:01 +08:00
|
|
|
static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv)
|
2013-11-05 11:56:49 +08:00
|
|
|
{
|
|
|
|
uint64_t pat;
|
|
|
|
|
|
|
|
pat = GEN8_PPAT(0, GEN8_PPAT_WB | GEN8_PPAT_LLC) | /* for normal objects, no eLLC */
|
|
|
|
GEN8_PPAT(1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC) | /* for something pointing to ptes? */
|
|
|
|
GEN8_PPAT(2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC) | /* for scanout with eLLC */
|
|
|
|
GEN8_PPAT(3, GEN8_PPAT_UC) | /* Uncached objects, mostly for scanout */
|
|
|
|
GEN8_PPAT(4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)) |
|
|
|
|
GEN8_PPAT(5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)) |
|
|
|
|
GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) |
|
|
|
|
GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3));
|
|
|
|
|
2016-04-07 16:08:05 +08:00
|
|
|
if (!USES_PPGTT(dev_priv))
|
2014-11-06 08:56:36 +08:00
|
|
|
/* Spec: "For GGTT, there is NO pat_sel[2:0] from the entry,
|
|
|
|
* so RTL will always use the value corresponding to
|
|
|
|
* pat_sel = 000".
|
|
|
|
* So let's disable cache for GGTT to avoid screen corruptions.
|
|
|
|
* MOCS still can be used though.
|
|
|
|
* - System agent ggtt writes (i.e. cpu gtt mmaps) already work
|
|
|
|
* before this patch, i.e. the same uncached + snooping access
|
|
|
|
* like on gen6/7 seems to be in effect.
|
|
|
|
* - So this just fixes blitter/render access. Again it looks
|
|
|
|
* like it's not just uncached access, but uncached + snooping.
|
|
|
|
* So we can still hold onto all our assumptions wrt cpu
|
|
|
|
* clflushing on LLC machines.
|
|
|
|
*/
|
|
|
|
pat = GEN8_PPAT(0, GEN8_PPAT_UC);
|
|
|
|
|
2013-11-05 11:56:49 +08:00
|
|
|
/* XXX: spec defines this as 2 distinct registers. It's unclear if a 64b
|
|
|
|
* write would work. */
|
2015-09-19 01:03:25 +08:00
|
|
|
I915_WRITE(GEN8_PRIVATE_PAT_LO, pat);
|
|
|
|
I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32);
|
2013-11-05 11:56:49 +08:00
|
|
|
}
|
|
|
|
|
2014-04-09 18:28:01 +08:00
|
|
|
static void chv_setup_private_ppat(struct drm_i915_private *dev_priv)
|
|
|
|
{
|
|
|
|
uint64_t pat;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Map WB on BDW to snooped on CHV.
|
|
|
|
*
|
|
|
|
* Only the snoop bit has meaning for CHV, the rest is
|
|
|
|
* ignored.
|
|
|
|
*
|
2014-11-15 03:02:44 +08:00
|
|
|
* The hardware will never snoop for certain types of accesses:
|
|
|
|
* - CPU GTT (GMADR->GGTT->no snoop->memory)
|
|
|
|
* - PPGTT page tables
|
|
|
|
* - some other special cycles
|
|
|
|
*
|
|
|
|
* As with BDW, we also need to consider the following for GT accesses:
|
|
|
|
* "For GGTT, there is NO pat_sel[2:0] from the entry,
|
|
|
|
* so RTL will always use the value corresponding to
|
|
|
|
* pat_sel = 000".
|
|
|
|
* Which means we must set the snoop bit in PAT entry 0
|
|
|
|
* in order to keep the global status page working.
|
2014-04-09 18:28:01 +08:00
|
|
|
*/
|
|
|
|
pat = GEN8_PPAT(0, CHV_PPAT_SNOOP) |
|
|
|
|
GEN8_PPAT(1, 0) |
|
|
|
|
GEN8_PPAT(2, 0) |
|
|
|
|
GEN8_PPAT(3, 0) |
|
|
|
|
GEN8_PPAT(4, CHV_PPAT_SNOOP) |
|
|
|
|
GEN8_PPAT(5, CHV_PPAT_SNOOP) |
|
|
|
|
GEN8_PPAT(6, CHV_PPAT_SNOOP) |
|
|
|
|
GEN8_PPAT(7, CHV_PPAT_SNOOP);
|
|
|
|
|
2015-09-19 01:03:25 +08:00
|
|
|
I915_WRITE(GEN8_PRIVATE_PAT_LO, pat);
|
|
|
|
I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32);
|
2014-04-09 18:28:01 +08:00
|
|
|
}
|
|
|
|
|
2016-08-04 14:52:24 +08:00
|
|
|
static void gen6_gmch_remove(struct i915_address_space *vm)
|
|
|
|
{
|
|
|
|
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
|
|
|
|
|
|
|
|
iounmap(ggtt->gsm);
|
2016-08-22 15:44:30 +08:00
|
|
|
cleanup_scratch_page(vm->dev, &vm->scratch_page);
|
2016-08-04 14:52:24 +08:00
|
|
|
}
|
|
|
|
|
2016-03-18 16:42:58 +08:00
|
|
|
static int gen8_gmch_probe(struct i915_ggtt *ggtt)
|
2013-11-05 11:32:22 +08:00
|
|
|
{
|
2016-08-04 14:52:22 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(ggtt->base.dev);
|
|
|
|
struct pci_dev *pdev = dev_priv->drm.pdev;
|
2016-08-04 14:52:24 +08:00
|
|
|
unsigned int size;
|
2013-11-05 11:32:22 +08:00
|
|
|
u16 snb_gmch_ctl;
|
|
|
|
|
|
|
|
/* TODO: We're not aware of mappable constraints on gen8 yet */
|
2016-08-04 14:52:22 +08:00
|
|
|
ggtt->mappable_base = pci_resource_start(pdev, 2);
|
|
|
|
ggtt->mappable_end = pci_resource_len(pdev, 2);
|
2013-11-05 11:32:22 +08:00
|
|
|
|
2016-08-04 14:52:22 +08:00
|
|
|
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(39)))
|
|
|
|
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(39));
|
2013-11-05 11:32:22 +08:00
|
|
|
|
2016-08-04 14:52:22 +08:00
|
|
|
pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
|
2013-11-05 11:32:22 +08:00
|
|
|
|
2016-08-04 14:52:22 +08:00
|
|
|
if (INTEL_GEN(dev_priv) >= 9) {
|
2016-03-18 16:42:58 +08:00
|
|
|
ggtt->stolen_size = gen9_get_stolen_size(snb_gmch_ctl);
|
2016-08-04 14:52:24 +08:00
|
|
|
size = gen8_get_total_gtt_size(snb_gmch_ctl);
|
2016-08-04 14:52:22 +08:00
|
|
|
} else if (IS_CHERRYVIEW(dev_priv)) {
|
2016-03-18 16:42:58 +08:00
|
|
|
ggtt->stolen_size = chv_get_stolen_size(snb_gmch_ctl);
|
2016-08-04 14:52:24 +08:00
|
|
|
size = chv_get_total_gtt_size(snb_gmch_ctl);
|
2014-05-09 03:19:40 +08:00
|
|
|
} else {
|
2016-03-18 16:42:58 +08:00
|
|
|
ggtt->stolen_size = gen8_get_stolen_size(snb_gmch_ctl);
|
2016-08-04 14:52:24 +08:00
|
|
|
size = gen8_get_total_gtt_size(snb_gmch_ctl);
|
2014-05-09 03:19:40 +08:00
|
|
|
}
|
2013-11-05 11:32:22 +08:00
|
|
|
|
2016-08-04 14:52:24 +08:00
|
|
|
ggtt->base.total = (size / sizeof(gen8_pte_t)) << PAGE_SHIFT;
|
2013-11-05 11:32:22 +08:00
|
|
|
|
2016-08-04 14:52:22 +08:00
|
|
|
if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv))
|
2014-04-09 18:28:01 +08:00
|
|
|
chv_setup_private_ppat(dev_priv);
|
|
|
|
else
|
|
|
|
bdw_setup_private_ppat(dev_priv);
|
2013-11-05 11:56:49 +08:00
|
|
|
|
2016-08-04 14:52:24 +08:00
|
|
|
ggtt->base.cleanup = gen6_gmch_remove;
|
2016-03-18 16:42:58 +08:00
|
|
|
ggtt->base.bind_vma = ggtt_bind_vma;
|
|
|
|
ggtt->base.unbind_vma = ggtt_unbind_vma;
|
2016-06-10 16:52:59 +08:00
|
|
|
ggtt->base.insert_page = gen8_ggtt_insert_page;
|
2016-05-14 14:26:35 +08:00
|
|
|
ggtt->base.clear_range = nop_clear_range;
|
2016-06-24 21:07:14 +08:00
|
|
|
if (!USES_FULL_PPGTT(dev_priv) || intel_scanout_needs_vtd_wa(dev_priv))
|
2016-05-14 14:26:35 +08:00
|
|
|
ggtt->base.clear_range = gen8_ggtt_clear_range;
|
|
|
|
|
|
|
|
ggtt->base.insert_entries = gen8_ggtt_insert_entries;
|
|
|
|
if (IS_CHERRYVIEW(dev_priv))
|
|
|
|
ggtt->base.insert_entries = gen8_ggtt_insert_entries__BKL;
|
|
|
|
|
2016-08-04 14:52:24 +08:00
|
|
|
return ggtt_probe_common(ggtt, size);
|
2013-11-05 11:32:22 +08:00
|
|
|
}
|
|
|
|
|
2016-03-18 16:42:58 +08:00
|
|
|
static int gen6_gmch_probe(struct i915_ggtt *ggtt)
|
2012-11-05 01:21:27 +08:00
|
|
|
{
|
2016-08-04 14:52:22 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(ggtt->base.dev);
|
|
|
|
struct pci_dev *pdev = dev_priv->drm.pdev;
|
2016-08-04 14:52:24 +08:00
|
|
|
unsigned int size;
|
2012-11-05 01:21:27 +08:00
|
|
|
u16 snb_gmch_ctl;
|
|
|
|
|
2016-08-04 14:52:22 +08:00
|
|
|
ggtt->mappable_base = pci_resource_start(pdev, 2);
|
|
|
|
ggtt->mappable_end = pci_resource_len(pdev, 2);
|
2013-02-09 03:32:47 +08:00
|
|
|
|
2013-01-25 05:49:57 +08:00
|
|
|
/* 64/512MB is the current min/max we actually know of, but this is just
|
|
|
|
* a coarse sanity check.
|
2012-11-05 01:21:27 +08:00
|
|
|
*/
|
2016-08-04 14:52:24 +08:00
|
|
|
if (ggtt->mappable_end < (64<<20) || ggtt->mappable_end > (512<<20)) {
|
2016-03-18 16:42:58 +08:00
|
|
|
DRM_ERROR("Unknown GMADR size (%llx)\n", ggtt->mappable_end);
|
2013-01-25 05:49:57 +08:00
|
|
|
return -ENXIO;
|
2012-11-05 01:21:27 +08:00
|
|
|
}
|
|
|
|
|
2016-08-04 14:52:22 +08:00
|
|
|
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(40)))
|
|
|
|
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40));
|
|
|
|
pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
|
2012-11-05 01:21:27 +08:00
|
|
|
|
2016-03-18 16:42:58 +08:00
|
|
|
ggtt->stolen_size = gen6_get_stolen_size(snb_gmch_ctl);
|
2012-11-05 01:21:27 +08:00
|
|
|
|
2016-08-04 14:52:24 +08:00
|
|
|
size = gen6_get_total_gtt_size(snb_gmch_ctl);
|
|
|
|
ggtt->base.total = (size / sizeof(gen6_pte_t)) << PAGE_SHIFT;
|
2012-11-05 01:21:27 +08:00
|
|
|
|
2016-03-18 16:42:58 +08:00
|
|
|
ggtt->base.clear_range = gen6_ggtt_clear_range;
|
2016-06-10 16:52:59 +08:00
|
|
|
ggtt->base.insert_page = gen6_ggtt_insert_page;
|
2016-03-18 16:42:58 +08:00
|
|
|
ggtt->base.insert_entries = gen6_ggtt_insert_entries;
|
|
|
|
ggtt->base.bind_vma = ggtt_bind_vma;
|
|
|
|
ggtt->base.unbind_vma = ggtt_unbind_vma;
|
2016-08-04 14:52:24 +08:00
|
|
|
ggtt->base.cleanup = gen6_gmch_remove;
|
|
|
|
|
|
|
|
if (HAS_EDRAM(dev_priv))
|
|
|
|
ggtt->base.pte_encode = iris_pte_encode;
|
|
|
|
else if (IS_HASWELL(dev_priv))
|
|
|
|
ggtt->base.pte_encode = hsw_pte_encode;
|
|
|
|
else if (IS_VALLEYVIEW(dev_priv))
|
|
|
|
ggtt->base.pte_encode = byt_pte_encode;
|
|
|
|
else if (INTEL_GEN(dev_priv) >= 7)
|
|
|
|
ggtt->base.pte_encode = ivb_pte_encode;
|
|
|
|
else
|
|
|
|
ggtt->base.pte_encode = snb_pte_encode;
|
2013-01-25 06:44:55 +08:00
|
|
|
|
2016-08-04 14:52:24 +08:00
|
|
|
return ggtt_probe_common(ggtt, size);
|
2012-11-05 01:21:27 +08:00
|
|
|
}
|
|
|
|
|
2016-08-04 14:52:24 +08:00
|
|
|
static void i915_gmch_remove(struct i915_address_space *vm)
|
2012-11-05 01:21:27 +08:00
|
|
|
{
|
2016-08-04 14:52:24 +08:00
|
|
|
intel_gmch_remove();
|
2012-03-26 15:45:40 +08:00
|
|
|
}
|
2013-01-25 05:49:57 +08:00
|
|
|
|
2016-03-18 16:42:58 +08:00
|
|
|
static int i915_gmch_probe(struct i915_ggtt *ggtt)
|
2013-01-25 05:49:57 +08:00
|
|
|
{
|
2016-08-04 14:52:22 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(ggtt->base.dev);
|
2013-01-25 05:49:57 +08:00
|
|
|
int ret;
|
|
|
|
|
2016-07-05 17:40:23 +08:00
|
|
|
ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->drm.pdev, NULL);
|
2013-01-25 05:49:57 +08:00
|
|
|
if (!ret) {
|
|
|
|
DRM_ERROR("failed to set up gmch\n");
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
2016-03-18 16:42:58 +08:00
|
|
|
intel_gtt_get(&ggtt->base.total, &ggtt->stolen_size,
|
|
|
|
&ggtt->mappable_base, &ggtt->mappable_end);
|
2013-01-25 05:49:57 +08:00
|
|
|
|
2016-08-04 14:52:22 +08:00
|
|
|
ggtt->do_idle_maps = needs_idle_maps(dev_priv);
|
2016-06-10 16:52:59 +08:00
|
|
|
ggtt->base.insert_page = i915_ggtt_insert_page;
|
2016-03-18 16:42:58 +08:00
|
|
|
ggtt->base.insert_entries = i915_ggtt_insert_entries;
|
|
|
|
ggtt->base.clear_range = i915_ggtt_clear_range;
|
|
|
|
ggtt->base.bind_vma = ggtt_bind_vma;
|
|
|
|
ggtt->base.unbind_vma = ggtt_unbind_vma;
|
2016-08-04 14:52:24 +08:00
|
|
|
ggtt->base.cleanup = i915_gmch_remove;
|
2013-01-25 05:49:57 +08:00
|
|
|
|
2016-03-18 16:42:58 +08:00
|
|
|
if (unlikely(ggtt->do_idle_maps))
|
2013-12-30 20:16:15 +08:00
|
|
|
DRM_INFO("applying Ironlake quirks for intel_iommu\n");
|
|
|
|
|
2013-01-25 05:49:57 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-24 22:47:46 +08:00
|
|
|
/**
|
2016-08-04 14:52:21 +08:00
|
|
|
* i915_ggtt_probe_hw - Probe GGTT hardware location
|
2016-08-04 14:52:22 +08:00
|
|
|
* @dev_priv: i915 device
|
2016-03-24 22:47:46 +08:00
|
|
|
*/
|
2016-08-04 14:52:22 +08:00
|
|
|
int i915_ggtt_probe_hw(struct drm_i915_private *dev_priv)
|
2013-01-25 05:49:57 +08:00
|
|
|
{
|
2016-03-18 16:42:57 +08:00
|
|
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
2013-01-25 05:49:57 +08:00
|
|
|
int ret;
|
|
|
|
|
2016-08-04 14:52:22 +08:00
|
|
|
ggtt->base.dev = &dev_priv->drm;
|
2015-06-25 23:35:13 +08:00
|
|
|
|
2016-08-04 14:52:24 +08:00
|
|
|
if (INTEL_GEN(dev_priv) <= 5)
|
|
|
|
ret = i915_gmch_probe(ggtt);
|
|
|
|
else if (INTEL_GEN(dev_priv) < 8)
|
|
|
|
ret = gen6_gmch_probe(ggtt);
|
|
|
|
else
|
|
|
|
ret = gen8_gmch_probe(ggtt);
|
2013-01-25 06:45:00 +08:00
|
|
|
if (ret)
|
2013-01-25 05:49:57 +08:00
|
|
|
return ret;
|
|
|
|
|
2016-03-18 16:42:59 +08:00
|
|
|
if ((ggtt->base.total - 1) >> 32) {
|
|
|
|
DRM_ERROR("We never expected a Global GTT with more than 32bits"
|
2016-08-04 14:52:23 +08:00
|
|
|
" of address space! Found %lldM!\n",
|
2016-03-18 16:42:59 +08:00
|
|
|
ggtt->base.total >> 20);
|
|
|
|
ggtt->base.total = 1ULL << 32;
|
|
|
|
ggtt->mappable_end = min(ggtt->mappable_end, ggtt->base.total);
|
|
|
|
}
|
|
|
|
|
2016-08-04 14:52:23 +08:00
|
|
|
if (ggtt->mappable_end > ggtt->base.total) {
|
|
|
|
DRM_ERROR("mappable aperture extends past end of GGTT,"
|
|
|
|
" aperture=%llx, total=%llx\n",
|
|
|
|
ggtt->mappable_end, ggtt->base.total);
|
|
|
|
ggtt->mappable_end = ggtt->base.total;
|
|
|
|
}
|
|
|
|
|
2013-01-25 05:49:57 +08:00
|
|
|
/* GMADR is the PCI mmio aperture into the global GTT. */
|
2015-06-25 23:35:05 +08:00
|
|
|
DRM_INFO("Memory usable by graphics device = %lluM\n",
|
2016-03-18 16:42:57 +08:00
|
|
|
ggtt->base.total >> 20);
|
|
|
|
DRM_DEBUG_DRIVER("GMADR size = %lldM\n", ggtt->mappable_end >> 20);
|
|
|
|
DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", ggtt->stolen_size >> 20);
|
2014-03-31 22:23:04 +08:00
|
|
|
#ifdef CONFIG_INTEL_IOMMU
|
|
|
|
if (intel_iommu_gfx_mapped)
|
|
|
|
DRM_INFO("VT-d active for gfx access\n");
|
|
|
|
#endif
|
2013-01-25 05:49:57 +08:00
|
|
|
|
|
|
|
return 0;
|
2016-08-04 14:52:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* i915_ggtt_init_hw - Initialize GGTT hardware
|
2016-08-04 14:52:22 +08:00
|
|
|
* @dev_priv: i915 device
|
2016-08-04 14:52:21 +08:00
|
|
|
*/
|
2016-08-04 14:52:22 +08:00
|
|
|
int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)
|
2016-08-04 14:52:21 +08:00
|
|
|
{
|
|
|
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
|
|
|
int ret;
|
|
|
|
|
2016-08-04 14:52:23 +08:00
|
|
|
INIT_LIST_HEAD(&dev_priv->vm_list);
|
|
|
|
|
|
|
|
/* Subtract the guard page before address space initialization to
|
|
|
|
* shrink the range used by drm_mm.
|
|
|
|
*/
|
|
|
|
ggtt->base.total -= PAGE_SIZE;
|
|
|
|
i915_address_space_init(&ggtt->base, dev_priv);
|
|
|
|
ggtt->base.total += PAGE_SIZE;
|
|
|
|
if (!HAS_LLC(dev_priv))
|
|
|
|
ggtt->base.mm.color_adjust = i915_gtt_color_adjust;
|
|
|
|
|
2016-08-19 23:54:27 +08:00
|
|
|
if (!io_mapping_init_wc(&dev_priv->ggtt.mappable,
|
|
|
|
dev_priv->ggtt.mappable_base,
|
|
|
|
dev_priv->ggtt.mappable_end)) {
|
2016-08-04 14:52:23 +08:00
|
|
|
ret = -EIO;
|
|
|
|
goto out_gtt_cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ggtt->mtrr = arch_phys_wc_add(ggtt->mappable_base, ggtt->mappable_end);
|
|
|
|
|
2016-08-04 14:52:21 +08:00
|
|
|
/*
|
|
|
|
* Initialise stolen early so that we may reserve preallocated
|
|
|
|
* objects for the BIOS to KMS transition.
|
|
|
|
*/
|
2016-08-04 14:52:22 +08:00
|
|
|
ret = i915_gem_init_stolen(&dev_priv->drm);
|
2016-08-04 14:52:21 +08:00
|
|
|
if (ret)
|
|
|
|
goto out_gtt_cleanup;
|
|
|
|
|
|
|
|
return 0;
|
2016-01-19 21:26:32 +08:00
|
|
|
|
|
|
|
out_gtt_cleanup:
|
2016-03-30 21:57:10 +08:00
|
|
|
ggtt->base.cleanup(&ggtt->base);
|
2016-01-19 21:26:32 +08:00
|
|
|
return ret;
|
2013-01-25 05:49:57 +08:00
|
|
|
}
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
|
2016-08-04 14:52:22 +08:00
|
|
|
int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv)
|
2016-05-07 02:35:55 +08:00
|
|
|
{
|
2016-08-04 14:52:22 +08:00
|
|
|
if (INTEL_GEN(dev_priv) < 6 && !intel_enable_gtt())
|
2016-05-07 02:35:55 +08:00
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:23 +08:00
|
|
|
void i915_gem_restore_gtt_mappings(struct drm_device *dev)
|
|
|
|
{
|
2016-03-30 21:57:10 +08:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
2016-09-10 04:19:57 +08:00
|
|
|
struct drm_i915_gem_object *obj, *on;
|
2015-04-14 23:35:23 +08:00
|
|
|
|
2016-05-10 21:10:04 +08:00
|
|
|
i915_check_and_clear_faults(dev_priv);
|
2015-04-14 23:35:23 +08:00
|
|
|
|
|
|
|
/* First fill our portion of the GTT with scratch pages */
|
2016-10-13 20:02:40 +08:00
|
|
|
ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total);
|
2015-04-14 23:35:23 +08:00
|
|
|
|
2016-09-10 04:19:57 +08:00
|
|
|
ggtt->base.closed = true; /* skip rewriting PTE on VMA unbind */
|
|
|
|
|
|
|
|
/* clflush objects bound into the GGTT and rebind them. */
|
|
|
|
list_for_each_entry_safe(obj, on,
|
|
|
|
&dev_priv->mm.bound_list, global_list) {
|
|
|
|
bool ggtt_bound = false;
|
|
|
|
struct i915_vma *vma;
|
|
|
|
|
2016-02-26 19:03:19 +08:00
|
|
|
list_for_each_entry(vma, &obj->vma_list, obj_link) {
|
2016-03-30 21:57:10 +08:00
|
|
|
if (vma->vm != &ggtt->base)
|
2015-07-06 22:15:01 +08:00
|
|
|
continue;
|
2015-04-14 23:35:23 +08:00
|
|
|
|
2016-09-10 04:19:57 +08:00
|
|
|
if (!i915_vma_unbind(vma))
|
|
|
|
continue;
|
|
|
|
|
2015-07-06 22:15:01 +08:00
|
|
|
WARN_ON(i915_vma_bind(vma, obj->cache_level,
|
|
|
|
PIN_UPDATE));
|
2016-09-10 04:19:57 +08:00
|
|
|
ggtt_bound = true;
|
2015-07-06 22:15:01 +08:00
|
|
|
}
|
|
|
|
|
2016-09-10 04:19:57 +08:00
|
|
|
if (ggtt_bound)
|
2016-05-14 14:26:34 +08:00
|
|
|
WARN_ON(i915_gem_object_set_to_gtt_domain(obj, false));
|
2015-07-06 22:15:01 +08:00
|
|
|
}
|
2015-04-14 23:35:23 +08:00
|
|
|
|
2016-09-10 04:19:57 +08:00
|
|
|
ggtt->base.closed = false;
|
|
|
|
|
2015-04-14 23:35:23 +08:00
|
|
|
if (INTEL_INFO(dev)->gen >= 8) {
|
2016-10-13 18:03:04 +08:00
|
|
|
if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv))
|
2015-04-14 23:35:23 +08:00
|
|
|
chv_setup_private_ppat(dev_priv);
|
|
|
|
else
|
|
|
|
bdw_setup_private_ppat(dev_priv);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (USES_PPGTT(dev)) {
|
2016-03-30 21:57:10 +08:00
|
|
|
struct i915_address_space *vm;
|
|
|
|
|
2015-04-14 23:35:23 +08:00
|
|
|
list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
|
|
|
|
/* TODO: Perhaps it shouldn't be gen6 specific */
|
|
|
|
|
2016-04-07 16:08:03 +08:00
|
|
|
struct i915_hw_ppgtt *ppgtt;
|
2015-04-14 23:35:23 +08:00
|
|
|
|
2016-08-04 14:52:25 +08:00
|
|
|
if (i915_is_ggtt(vm))
|
2015-04-14 23:35:23 +08:00
|
|
|
ppgtt = dev_priv->mm.aliasing_ppgtt;
|
2016-04-07 16:08:03 +08:00
|
|
|
else
|
|
|
|
ppgtt = i915_vm_to_ppgtt(vm);
|
2015-04-14 23:35:23 +08:00
|
|
|
|
|
|
|
gen6_write_page_range(dev_priv, &ppgtt->pd,
|
|
|
|
0, ppgtt->base.total);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
i915_ggtt_flush(dev_priv);
|
|
|
|
}
|
|
|
|
|
2016-08-04 14:52:44 +08:00
|
|
|
static void
|
|
|
|
i915_vma_retire(struct i915_gem_active *active,
|
|
|
|
struct drm_i915_gem_request *rq)
|
|
|
|
{
|
|
|
|
const unsigned int idx = rq->engine->id;
|
|
|
|
struct i915_vma *vma =
|
|
|
|
container_of(active, struct i915_vma, last_read[idx]);
|
|
|
|
|
|
|
|
GEM_BUG_ON(!i915_vma_has_active_engine(vma, idx));
|
|
|
|
|
|
|
|
i915_vma_clear_active(vma, idx);
|
|
|
|
if (i915_vma_is_active(vma))
|
|
|
|
return;
|
|
|
|
|
|
|
|
list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
|
2016-08-04 23:32:32 +08:00
|
|
|
if (unlikely(i915_vma_is_closed(vma) && !i915_vma_is_pinned(vma)))
|
2016-08-04 14:52:45 +08:00
|
|
|
WARN_ON(i915_vma_unbind(vma));
|
|
|
|
}
|
|
|
|
|
|
|
|
void i915_vma_destroy(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
GEM_BUG_ON(vma->node.allocated);
|
|
|
|
GEM_BUG_ON(i915_vma_is_active(vma));
|
2016-08-04 23:32:32 +08:00
|
|
|
GEM_BUG_ON(!i915_vma_is_closed(vma));
|
2016-08-19 00:17:00 +08:00
|
|
|
GEM_BUG_ON(vma->fence);
|
2016-08-04 14:52:45 +08:00
|
|
|
|
|
|
|
list_del(&vma->vm_link);
|
2016-08-04 23:32:32 +08:00
|
|
|
if (!i915_vma_is_ggtt(vma))
|
2016-08-04 14:52:45 +08:00
|
|
|
i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm));
|
|
|
|
|
|
|
|
kmem_cache_free(to_i915(vma->obj->base.dev)->vmas, vma);
|
|
|
|
}
|
|
|
|
|
|
|
|
void i915_vma_close(struct i915_vma *vma)
|
|
|
|
{
|
2016-08-04 23:32:32 +08:00
|
|
|
GEM_BUG_ON(i915_vma_is_closed(vma));
|
|
|
|
vma->flags |= I915_VMA_CLOSED;
|
2016-08-04 14:52:45 +08:00
|
|
|
|
|
|
|
list_del_init(&vma->obj_link);
|
2016-08-04 23:32:30 +08:00
|
|
|
if (!i915_vma_is_active(vma) && !i915_vma_is_pinned(vma))
|
2016-08-04 14:52:47 +08:00
|
|
|
WARN_ON(i915_vma_unbind(vma));
|
2016-08-04 14:52:44 +08:00
|
|
|
}
|
|
|
|
|
2015-03-16 20:11:13 +08:00
|
|
|
static struct i915_vma *
|
2016-08-15 17:49:06 +08:00
|
|
|
__i915_vma_create(struct drm_i915_gem_object *obj,
|
|
|
|
struct i915_address_space *vm,
|
|
|
|
const struct i915_ggtt_view *view)
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
{
|
2015-03-18 16:21:58 +08:00
|
|
|
struct i915_vma *vma;
|
2016-08-04 14:52:44 +08:00
|
|
|
int i;
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
|
2016-08-04 14:52:46 +08:00
|
|
|
GEM_BUG_ON(vm->closed);
|
|
|
|
|
2015-04-07 23:20:58 +08:00
|
|
|
vma = kmem_cache_zalloc(to_i915(obj->base.dev)->vmas, GFP_KERNEL);
|
2015-03-18 16:21:58 +08:00
|
|
|
if (vma == NULL)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
2015-03-16 20:11:13 +08:00
|
|
|
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
INIT_LIST_HEAD(&vma->exec_list);
|
2016-08-04 14:52:44 +08:00
|
|
|
for (i = 0; i < ARRAY_SIZE(vma->last_read); i++)
|
|
|
|
init_request_active(&vma->last_read[i], i915_vma_retire);
|
2016-08-19 00:17:00 +08:00
|
|
|
init_request_active(&vma->last_fence, NULL);
|
2016-08-04 14:52:46 +08:00
|
|
|
list_add(&vma->vm_link, &vm->unbound_list);
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
vma->vm = vm;
|
|
|
|
vma->obj = obj;
|
2016-08-04 23:32:29 +08:00
|
|
|
vma->size = obj->base.size;
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
|
2016-08-15 17:49:06 +08:00
|
|
|
if (view) {
|
2016-08-04 23:32:29 +08:00
|
|
|
vma->ggtt_view = *view;
|
|
|
|
if (view->type == I915_GGTT_VIEW_PARTIAL) {
|
|
|
|
vma->size = view->params.partial.size;
|
|
|
|
vma->size <<= PAGE_SHIFT;
|
|
|
|
} else if (view->type == I915_GGTT_VIEW_ROTATED) {
|
|
|
|
vma->size =
|
|
|
|
intel_rotation_info_size(&view->params.rotated);
|
|
|
|
vma->size <<= PAGE_SHIFT;
|
|
|
|
}
|
2016-08-15 17:49:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (i915_is_ggtt(vm)) {
|
|
|
|
vma->flags |= I915_VMA_GGTT;
|
2016-08-04 23:32:29 +08:00
|
|
|
} else {
|
2016-02-26 19:03:20 +08:00
|
|
|
i915_ppgtt_get(i915_vm_to_ppgtt(vm));
|
2016-08-04 23:32:29 +08:00
|
|
|
}
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
|
2016-02-26 19:03:19 +08:00
|
|
|
list_add_tail(&vma->obj_link, &obj->vma_list);
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
return vma;
|
|
|
|
}
|
|
|
|
|
2016-08-15 17:49:06 +08:00
|
|
|
static inline bool vma_matches(struct i915_vma *vma,
|
|
|
|
struct i915_address_space *vm,
|
|
|
|
const struct i915_ggtt_view *view)
|
|
|
|
{
|
|
|
|
if (vma->vm != vm)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!i915_vma_is_ggtt(vma))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (!view)
|
|
|
|
return vma->ggtt_view.type == 0;
|
|
|
|
|
|
|
|
if (vma->ggtt_view.type != view->type)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return memcmp(&vma->ggtt_view.params,
|
|
|
|
&view->params,
|
|
|
|
sizeof(view->params)) == 0;
|
|
|
|
}
|
|
|
|
|
2016-08-15 17:48:48 +08:00
|
|
|
struct i915_vma *
|
|
|
|
i915_vma_create(struct drm_i915_gem_object *obj,
|
|
|
|
struct i915_address_space *vm,
|
|
|
|
const struct i915_ggtt_view *view)
|
|
|
|
{
|
|
|
|
GEM_BUG_ON(view && !i915_is_ggtt(vm));
|
2016-08-15 17:49:06 +08:00
|
|
|
GEM_BUG_ON(i915_gem_obj_to_vma(obj, vm, view));
|
2016-08-15 17:48:48 +08:00
|
|
|
|
2016-08-15 17:49:06 +08:00
|
|
|
return __i915_vma_create(obj, vm, view);
|
2016-08-15 17:48:48 +08:00
|
|
|
}
|
|
|
|
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
struct i915_vma *
|
2016-08-15 17:49:06 +08:00
|
|
|
i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
|
|
|
|
struct i915_address_space *vm,
|
|
|
|
const struct i915_ggtt_view *view)
|
2015-03-16 20:11:13 +08:00
|
|
|
{
|
|
|
|
struct i915_vma *vma;
|
|
|
|
|
2016-08-15 17:49:06 +08:00
|
|
|
list_for_each_entry_reverse(vma, &obj->vma_list, obj_link)
|
|
|
|
if (vma_matches(vma, vm, view))
|
|
|
|
return vma;
|
2015-03-16 20:11:13 +08:00
|
|
|
|
2016-08-15 17:49:06 +08:00
|
|
|
return NULL;
|
2015-03-16 20:11:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct i915_vma *
|
2016-08-15 17:49:06 +08:00
|
|
|
i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
|
|
|
|
struct i915_address_space *vm,
|
|
|
|
const struct i915_ggtt_view *view)
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
{
|
2016-08-15 17:49:06 +08:00
|
|
|
struct i915_vma *vma;
|
2015-03-16 20:11:13 +08:00
|
|
|
|
2016-08-15 17:49:06 +08:00
|
|
|
GEM_BUG_ON(view && !i915_is_ggtt(vm));
|
2016-08-04 23:32:34 +08:00
|
|
|
|
2016-08-15 17:49:06 +08:00
|
|
|
vma = i915_gem_obj_to_vma(obj, vm, view);
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
if (!vma)
|
2016-08-15 17:49:06 +08:00
|
|
|
vma = __i915_vma_create(obj, vm, view);
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
|
2016-08-04 23:32:32 +08:00
|
|
|
GEM_BUG_ON(i915_vma_is_closed(vma));
|
drm/i915: Create bind/unbind abstraction for VMAs
To sum up what goes on here, we abstract the vma binding, similarly to
the previous object binding. This helps for distinguishing legacy
binding, versus modern binding. To keep the code churn as minimal as
possible, I am leaving in insert_entries(). It serves as the per
platform pte writing basically. bind_vma and insert_entries do share a
lot of similarities, and I did have designs to combine the two, but as
mentioned already... too much churn in an already massive patchset.
What follows are the 3 commits which existed discretely in the original
submissions. Upon rebasing on Broadwell support, it became clear that
separation was not good, and only made for more error prone code. Below
are the 3 commit messages with all their history.
drm/i915: Add bind/unbind object functions to VMA
drm/i915: Use the new vm [un]bind functions
drm/i915: reduce vm->insert_entries() usage
drm/i915: Add bind/unbind object functions to VMA
As we plumb the code with more VM information, it has become more
obvious that the easiest way to deal with bind and unbind is to simply
put the function pointers in the vm, and let those choose the correct
way to handle the page table updates. This change allows many places in
the code to simply be vm->bind, and not have to worry about
distinguishing PPGTT vs GGTT.
Notice that this patch has no impact on functionality. I've decided to
save the actual change until the next patch because I think it's easier
to review that way. I'm happy to squash the two, or let Daniel do it on
merge.
v2:
Make ggtt handle the quirky aliasing ppgtt
Add flags to bind object to support above
Don't ever call bind/unbind directly for PPGTT until we have real, full
PPGTT (use NULLs to assert this)
Make sure we rebind the ggtt if there already is a ggtt binding. This
happens on set cache levels.
Use VMA for bind/unbind (Daniel, Ben)
v3: Reorganize ggtt_vma_bind to be more concise and easier to read
(Ville). Change logic in unbind to only unbind ggtt when there is a
global mapping, and to remove a redundant check if the aliasing ppgtt
exists.
v4: Make the bind function a bit smarter about the cache levels to avoid
unnecessary multiple remaps. "I accept it is a wart, I think unifying
the pin_vma / bind_vma could be unified later" (Chris)
Removed the git notes, and put version info here. (Daniel)
v5: Update the comment to not suck (Chris)
v6:
Move bind/unbind to the VMA. It makes more sense in the VMA structure
(always has, but I was previously lazy). With this change, it will allow
us to keep a distinct insert_entries.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: Use the new vm [un]bind functions
Building on the last patch which created the new function pointers in
the VM for bind/unbind, here we actually put those new function pointers
to use.
Split out as a separate patch to aid in review. I'm fine with squashing
into the previous patch if people request it.
v2: Updated to address the smart ggtt which can do aliasing as needed
Make sure we bind to global gtt when mappable and fenceable. I thought
we could get away without this initialy, but we cannot.
v3: Make the global GTT binding explicitly use the ggtt VM for
bind_vma(). While at it, use the new ggtt_vma helper (Chris)
At this point the original mailing list thread diverges. ie.
v4^:
use target_obj instead of obj for gen6 relocate_entry
vma->bind_vma() can be called safely during pin. So simply do that
instead of the complicated conditionals.
Don't restore PPGTT bound objects on resume path
Bug fix in resume path for globally bound Bos
Properly handle secure dispatch
Rebased on vma bind/unbind conversion
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
drm/i915: reduce vm->insert_entries() usage
FKA: drm/i915: eliminate vm->insert_entries()
With bind/unbind function pointers in place, we no longer need
insert_entries. We could, and want, to remove clear_range, however it's
not totally easy at this point. Since it's used in a couple of place
still that don't only deal in objects: setup, ppgtt init, and restore
gtt mappings.
v2: Don't actually remove insert_entries, just limit its usage. It will
be useful when we introduce gen8. It will always be called from the vma
bind/unbind.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-12-07 06:10:56 +08:00
|
|
|
return vma;
|
|
|
|
}
|
2014-12-11 01:27:58 +08:00
|
|
|
|
2015-09-21 17:45:33 +08:00
|
|
|
static struct scatterlist *
|
2016-01-14 21:22:11 +08:00
|
|
|
rotate_pages(const dma_addr_t *in, unsigned int offset,
|
2015-09-21 17:45:33 +08:00
|
|
|
unsigned int width, unsigned int height,
|
2016-01-21 03:05:23 +08:00
|
|
|
unsigned int stride,
|
2015-09-21 17:45:33 +08:00
|
|
|
struct sg_table *st, struct scatterlist *sg)
|
2015-03-23 19:10:36 +08:00
|
|
|
{
|
|
|
|
unsigned int column, row;
|
|
|
|
unsigned int src_idx;
|
|
|
|
|
|
|
|
for (column = 0; column < width; column++) {
|
2016-01-21 03:05:23 +08:00
|
|
|
src_idx = stride * (height - 1) + column;
|
2015-03-23 19:10:36 +08:00
|
|
|
for (row = 0; row < height; row++) {
|
|
|
|
st->nents++;
|
|
|
|
/* We don't need the pages, but need to initialize
|
|
|
|
* the entries so the sg list can be happily traversed.
|
|
|
|
* The only thing we need are DMA addresses.
|
|
|
|
*/
|
|
|
|
sg_set_page(sg, NULL, PAGE_SIZE, 0);
|
2015-09-21 17:45:33 +08:00
|
|
|
sg_dma_address(sg) = in[offset + src_idx];
|
2015-03-23 19:10:36 +08:00
|
|
|
sg_dma_len(sg) = PAGE_SIZE;
|
|
|
|
sg = sg_next(sg);
|
2016-01-21 03:05:23 +08:00
|
|
|
src_idx -= stride;
|
2015-03-23 19:10:36 +08:00
|
|
|
}
|
|
|
|
}
|
2015-09-21 17:45:33 +08:00
|
|
|
|
|
|
|
return sg;
|
2015-03-23 19:10:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct sg_table *
|
drm/i915: Rewrite fb rotation GTT handling
Redo the fb rotation handling in order to:
- eliminate the NV12 special casing
- handle fb->offsets[] properly
- make the rotation handling easier for the plane code
To achieve these goals we reduce intel_rotation_info to only contain
(for each plane) the rotated view width,height,stride in tile units,
and the page offset into the object where the plane starts. Each plane
is handled exactly the same way, no special casing for NV12 or other
formats. We then store the computed rotation_info under
intel_framebuffer so that we don't have to recompute it again.
To handle fb->offsets[] we treat them as a linear offsets and convert
them to x/y offsets from the start of the relevant GTT mapping (either
normal or rotated). We store the x/y offsets under intel_framebuffer,
and for some extra convenience we also store the rotated pitch (ie.
tile aligned plane height). So for each plane we have the normal
x/y offsets, rotated x/y offsets, and the rotated pitch. The normal
pitch is available already in fb->pitches[].
While we're gathering up all that extra information, we can also easily
compute the storage requirements for the framebuffer, so that we can
check that the object is big enough to hold it.
When it comes time to deal with the plane source coordinates, we first
rotate the clipped src coordinates to match the relevant GTT view
orientation, then add to them the fb x/y offsets. Next we compute
the aligned surface page offset, and as a result we're left with some
residual x/y offsets. Finally, if required by the hardware, we convert
the remaining x/y offsets into a linear offset.
For gen2/3 we simply skip computing the final page offset, and just
convert the src+fb x/y offsets directly into a linear offset since
that's what the hardware wants.
After this all platforms, incluing SKL+, compute these things in exactly
the same way (excluding alignemnt differences).
v2: Use BIT(DRM_ROTATE_270) instead of ROTATE_270 when rotating
plane src coordinates
Drop some spurious changes that got left behind during
development
v3: Split out more changes to prep patches (Daniel)
s/intel_fb->plane[].foo.bar/intel_fb->foo[].bar/ for brevity
Rename intel_surf_gtt_offset to intel_fb_gtt_offset
Kill the pointless 'plane' parameter from intel_fb_gtt_offset()
v4: Fix alignment vs. alignment-1 when calling
_intel_compute_tile_offset() from intel_fill_fb_info()
Pass the pitch in tiles in
stad of pixels to intel_adjust_tile_offset() from intel_fill_fb_info()
Pass the full width/height of the rotated area to
drm_rect_rotate() for clarity
Use u32 for more offsets
v5: Preserve the upper_32_bits()/lower_32_bits() handling for the
fb ggtt offset (Sivakumar)
v6: Rebase due to drm_plane_state src/dst rects
Cc: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1470821001-25272-2-git-send-email-ville.syrjala@linux.intel.com
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-09-15 18:16:41 +08:00
|
|
|
intel_rotate_fb_obj_pages(const struct intel_rotation_info *rot_info,
|
2015-03-23 19:10:36 +08:00
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
|
{
|
2016-05-20 18:54:06 +08:00
|
|
|
const size_t n_pages = obj->base.size / PAGE_SIZE;
|
drm/i915: Rewrite fb rotation GTT handling
Redo the fb rotation handling in order to:
- eliminate the NV12 special casing
- handle fb->offsets[] properly
- make the rotation handling easier for the plane code
To achieve these goals we reduce intel_rotation_info to only contain
(for each plane) the rotated view width,height,stride in tile units,
and the page offset into the object where the plane starts. Each plane
is handled exactly the same way, no special casing for NV12 or other
formats. We then store the computed rotation_info under
intel_framebuffer so that we don't have to recompute it again.
To handle fb->offsets[] we treat them as a linear offsets and convert
them to x/y offsets from the start of the relevant GTT mapping (either
normal or rotated). We store the x/y offsets under intel_framebuffer,
and for some extra convenience we also store the rotated pitch (ie.
tile aligned plane height). So for each plane we have the normal
x/y offsets, rotated x/y offsets, and the rotated pitch. The normal
pitch is available already in fb->pitches[].
While we're gathering up all that extra information, we can also easily
compute the storage requirements for the framebuffer, so that we can
check that the object is big enough to hold it.
When it comes time to deal with the plane source coordinates, we first
rotate the clipped src coordinates to match the relevant GTT view
orientation, then add to them the fb x/y offsets. Next we compute
the aligned surface page offset, and as a result we're left with some
residual x/y offsets. Finally, if required by the hardware, we convert
the remaining x/y offsets into a linear offset.
For gen2/3 we simply skip computing the final page offset, and just
convert the src+fb x/y offsets directly into a linear offset since
that's what the hardware wants.
After this all platforms, incluing SKL+, compute these things in exactly
the same way (excluding alignemnt differences).
v2: Use BIT(DRM_ROTATE_270) instead of ROTATE_270 when rotating
plane src coordinates
Drop some spurious changes that got left behind during
development
v3: Split out more changes to prep patches (Daniel)
s/intel_fb->plane[].foo.bar/intel_fb->foo[].bar/ for brevity
Rename intel_surf_gtt_offset to intel_fb_gtt_offset
Kill the pointless 'plane' parameter from intel_fb_gtt_offset()
v4: Fix alignment vs. alignment-1 when calling
_intel_compute_tile_offset() from intel_fill_fb_info()
Pass the pitch in tiles in
stad of pixels to intel_adjust_tile_offset() from intel_fill_fb_info()
Pass the full width/height of the rotated area to
drm_rect_rotate() for clarity
Use u32 for more offsets
v5: Preserve the upper_32_bits()/lower_32_bits() handling for the
fb ggtt offset (Sivakumar)
v6: Rebase due to drm_plane_state src/dst rects
Cc: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1470821001-25272-2-git-send-email-ville.syrjala@linux.intel.com
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-09-15 18:16:41 +08:00
|
|
|
unsigned int size = intel_rotation_info_size(rot_info);
|
2016-05-20 18:54:06 +08:00
|
|
|
struct sgt_iter sgt_iter;
|
|
|
|
dma_addr_t dma_addr;
|
2015-03-23 19:10:36 +08:00
|
|
|
unsigned long i;
|
|
|
|
dma_addr_t *page_addr_list;
|
|
|
|
struct sg_table *st;
|
2015-09-21 17:45:34 +08:00
|
|
|
struct scatterlist *sg;
|
2015-03-25 18:15:26 +08:00
|
|
|
int ret = -ENOMEM;
|
2015-03-23 19:10:36 +08:00
|
|
|
|
|
|
|
/* Allocate a temporary list of source pages for random access. */
|
2016-05-20 18:54:06 +08:00
|
|
|
page_addr_list = drm_malloc_gfp(n_pages,
|
2016-04-08 19:11:13 +08:00
|
|
|
sizeof(dma_addr_t),
|
|
|
|
GFP_TEMPORARY);
|
2015-03-23 19:10:36 +08:00
|
|
|
if (!page_addr_list)
|
|
|
|
return ERR_PTR(ret);
|
|
|
|
|
|
|
|
/* Allocate target SG list. */
|
|
|
|
st = kmalloc(sizeof(*st), GFP_KERNEL);
|
|
|
|
if (!st)
|
|
|
|
goto err_st_alloc;
|
|
|
|
|
drm/i915: Rewrite fb rotation GTT handling
Redo the fb rotation handling in order to:
- eliminate the NV12 special casing
- handle fb->offsets[] properly
- make the rotation handling easier for the plane code
To achieve these goals we reduce intel_rotation_info to only contain
(for each plane) the rotated view width,height,stride in tile units,
and the page offset into the object where the plane starts. Each plane
is handled exactly the same way, no special casing for NV12 or other
formats. We then store the computed rotation_info under
intel_framebuffer so that we don't have to recompute it again.
To handle fb->offsets[] we treat them as a linear offsets and convert
them to x/y offsets from the start of the relevant GTT mapping (either
normal or rotated). We store the x/y offsets under intel_framebuffer,
and for some extra convenience we also store the rotated pitch (ie.
tile aligned plane height). So for each plane we have the normal
x/y offsets, rotated x/y offsets, and the rotated pitch. The normal
pitch is available already in fb->pitches[].
While we're gathering up all that extra information, we can also easily
compute the storage requirements for the framebuffer, so that we can
check that the object is big enough to hold it.
When it comes time to deal with the plane source coordinates, we first
rotate the clipped src coordinates to match the relevant GTT view
orientation, then add to them the fb x/y offsets. Next we compute
the aligned surface page offset, and as a result we're left with some
residual x/y offsets. Finally, if required by the hardware, we convert
the remaining x/y offsets into a linear offset.
For gen2/3 we simply skip computing the final page offset, and just
convert the src+fb x/y offsets directly into a linear offset since
that's what the hardware wants.
After this all platforms, incluing SKL+, compute these things in exactly
the same way (excluding alignemnt differences).
v2: Use BIT(DRM_ROTATE_270) instead of ROTATE_270 when rotating
plane src coordinates
Drop some spurious changes that got left behind during
development
v3: Split out more changes to prep patches (Daniel)
s/intel_fb->plane[].foo.bar/intel_fb->foo[].bar/ for brevity
Rename intel_surf_gtt_offset to intel_fb_gtt_offset
Kill the pointless 'plane' parameter from intel_fb_gtt_offset()
v4: Fix alignment vs. alignment-1 when calling
_intel_compute_tile_offset() from intel_fill_fb_info()
Pass the pitch in tiles in
stad of pixels to intel_adjust_tile_offset() from intel_fill_fb_info()
Pass the full width/height of the rotated area to
drm_rect_rotate() for clarity
Use u32 for more offsets
v5: Preserve the upper_32_bits()/lower_32_bits() handling for the
fb ggtt offset (Sivakumar)
v6: Rebase due to drm_plane_state src/dst rects
Cc: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1470821001-25272-2-git-send-email-ville.syrjala@linux.intel.com
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-09-15 18:16:41 +08:00
|
|
|
ret = sg_alloc_table(st, size, GFP_KERNEL);
|
2015-03-23 19:10:36 +08:00
|
|
|
if (ret)
|
|
|
|
goto err_sg_alloc;
|
|
|
|
|
|
|
|
/* Populate source page list from the object. */
|
|
|
|
i = 0;
|
2016-05-20 18:54:06 +08:00
|
|
|
for_each_sgt_dma(dma_addr, sgt_iter, obj->pages)
|
|
|
|
page_addr_list[i++] = dma_addr;
|
2015-03-23 19:10:36 +08:00
|
|
|
|
2016-05-20 18:54:06 +08:00
|
|
|
GEM_BUG_ON(i != n_pages);
|
2016-02-16 04:54:46 +08:00
|
|
|
st->nents = 0;
|
|
|
|
sg = st->sgl;
|
|
|
|
|
drm/i915: Rewrite fb rotation GTT handling
Redo the fb rotation handling in order to:
- eliminate the NV12 special casing
- handle fb->offsets[] properly
- make the rotation handling easier for the plane code
To achieve these goals we reduce intel_rotation_info to only contain
(for each plane) the rotated view width,height,stride in tile units,
and the page offset into the object where the plane starts. Each plane
is handled exactly the same way, no special casing for NV12 or other
formats. We then store the computed rotation_info under
intel_framebuffer so that we don't have to recompute it again.
To handle fb->offsets[] we treat them as a linear offsets and convert
them to x/y offsets from the start of the relevant GTT mapping (either
normal or rotated). We store the x/y offsets under intel_framebuffer,
and for some extra convenience we also store the rotated pitch (ie.
tile aligned plane height). So for each plane we have the normal
x/y offsets, rotated x/y offsets, and the rotated pitch. The normal
pitch is available already in fb->pitches[].
While we're gathering up all that extra information, we can also easily
compute the storage requirements for the framebuffer, so that we can
check that the object is big enough to hold it.
When it comes time to deal with the plane source coordinates, we first
rotate the clipped src coordinates to match the relevant GTT view
orientation, then add to them the fb x/y offsets. Next we compute
the aligned surface page offset, and as a result we're left with some
residual x/y offsets. Finally, if required by the hardware, we convert
the remaining x/y offsets into a linear offset.
For gen2/3 we simply skip computing the final page offset, and just
convert the src+fb x/y offsets directly into a linear offset since
that's what the hardware wants.
After this all platforms, incluing SKL+, compute these things in exactly
the same way (excluding alignemnt differences).
v2: Use BIT(DRM_ROTATE_270) instead of ROTATE_270 when rotating
plane src coordinates
Drop some spurious changes that got left behind during
development
v3: Split out more changes to prep patches (Daniel)
s/intel_fb->plane[].foo.bar/intel_fb->foo[].bar/ for brevity
Rename intel_surf_gtt_offset to intel_fb_gtt_offset
Kill the pointless 'plane' parameter from intel_fb_gtt_offset()
v4: Fix alignment vs. alignment-1 when calling
_intel_compute_tile_offset() from intel_fill_fb_info()
Pass the pitch in tiles in
stad of pixels to intel_adjust_tile_offset() from intel_fill_fb_info()
Pass the full width/height of the rotated area to
drm_rect_rotate() for clarity
Use u32 for more offsets
v5: Preserve the upper_32_bits()/lower_32_bits() handling for the
fb ggtt offset (Sivakumar)
v6: Rebase due to drm_plane_state src/dst rects
Cc: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1470821001-25272-2-git-send-email-ville.syrjala@linux.intel.com
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-09-15 18:16:41 +08:00
|
|
|
for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++) {
|
|
|
|
sg = rotate_pages(page_addr_list, rot_info->plane[i].offset,
|
|
|
|
rot_info->plane[i].width, rot_info->plane[i].height,
|
|
|
|
rot_info->plane[i].stride, st, sg);
|
2015-09-21 17:45:34 +08:00
|
|
|
}
|
|
|
|
|
drm/i915: Rewrite fb rotation GTT handling
Redo the fb rotation handling in order to:
- eliminate the NV12 special casing
- handle fb->offsets[] properly
- make the rotation handling easier for the plane code
To achieve these goals we reduce intel_rotation_info to only contain
(for each plane) the rotated view width,height,stride in tile units,
and the page offset into the object where the plane starts. Each plane
is handled exactly the same way, no special casing for NV12 or other
formats. We then store the computed rotation_info under
intel_framebuffer so that we don't have to recompute it again.
To handle fb->offsets[] we treat them as a linear offsets and convert
them to x/y offsets from the start of the relevant GTT mapping (either
normal or rotated). We store the x/y offsets under intel_framebuffer,
and for some extra convenience we also store the rotated pitch (ie.
tile aligned plane height). So for each plane we have the normal
x/y offsets, rotated x/y offsets, and the rotated pitch. The normal
pitch is available already in fb->pitches[].
While we're gathering up all that extra information, we can also easily
compute the storage requirements for the framebuffer, so that we can
check that the object is big enough to hold it.
When it comes time to deal with the plane source coordinates, we first
rotate the clipped src coordinates to match the relevant GTT view
orientation, then add to them the fb x/y offsets. Next we compute
the aligned surface page offset, and as a result we're left with some
residual x/y offsets. Finally, if required by the hardware, we convert
the remaining x/y offsets into a linear offset.
For gen2/3 we simply skip computing the final page offset, and just
convert the src+fb x/y offsets directly into a linear offset since
that's what the hardware wants.
After this all platforms, incluing SKL+, compute these things in exactly
the same way (excluding alignemnt differences).
v2: Use BIT(DRM_ROTATE_270) instead of ROTATE_270 when rotating
plane src coordinates
Drop some spurious changes that got left behind during
development
v3: Split out more changes to prep patches (Daniel)
s/intel_fb->plane[].foo.bar/intel_fb->foo[].bar/ for brevity
Rename intel_surf_gtt_offset to intel_fb_gtt_offset
Kill the pointless 'plane' parameter from intel_fb_gtt_offset()
v4: Fix alignment vs. alignment-1 when calling
_intel_compute_tile_offset() from intel_fill_fb_info()
Pass the pitch in tiles in
stad of pixels to intel_adjust_tile_offset() from intel_fill_fb_info()
Pass the full width/height of the rotated area to
drm_rect_rotate() for clarity
Use u32 for more offsets
v5: Preserve the upper_32_bits()/lower_32_bits() handling for the
fb ggtt offset (Sivakumar)
v6: Rebase due to drm_plane_state src/dst rects
Cc: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1470821001-25272-2-git-send-email-ville.syrjala@linux.intel.com
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-09-15 18:16:41 +08:00
|
|
|
DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages)\n",
|
|
|
|
obj->base.size, rot_info->plane[0].width, rot_info->plane[0].height, size);
|
2015-03-23 19:10:36 +08:00
|
|
|
|
|
|
|
drm_free_large(page_addr_list);
|
|
|
|
|
|
|
|
return st;
|
|
|
|
|
|
|
|
err_sg_alloc:
|
|
|
|
kfree(st);
|
|
|
|
err_st_alloc:
|
|
|
|
drm_free_large(page_addr_list);
|
|
|
|
|
drm/i915: Rewrite fb rotation GTT handling
Redo the fb rotation handling in order to:
- eliminate the NV12 special casing
- handle fb->offsets[] properly
- make the rotation handling easier for the plane code
To achieve these goals we reduce intel_rotation_info to only contain
(for each plane) the rotated view width,height,stride in tile units,
and the page offset into the object where the plane starts. Each plane
is handled exactly the same way, no special casing for NV12 or other
formats. We then store the computed rotation_info under
intel_framebuffer so that we don't have to recompute it again.
To handle fb->offsets[] we treat them as a linear offsets and convert
them to x/y offsets from the start of the relevant GTT mapping (either
normal or rotated). We store the x/y offsets under intel_framebuffer,
and for some extra convenience we also store the rotated pitch (ie.
tile aligned plane height). So for each plane we have the normal
x/y offsets, rotated x/y offsets, and the rotated pitch. The normal
pitch is available already in fb->pitches[].
While we're gathering up all that extra information, we can also easily
compute the storage requirements for the framebuffer, so that we can
check that the object is big enough to hold it.
When it comes time to deal with the plane source coordinates, we first
rotate the clipped src coordinates to match the relevant GTT view
orientation, then add to them the fb x/y offsets. Next we compute
the aligned surface page offset, and as a result we're left with some
residual x/y offsets. Finally, if required by the hardware, we convert
the remaining x/y offsets into a linear offset.
For gen2/3 we simply skip computing the final page offset, and just
convert the src+fb x/y offsets directly into a linear offset since
that's what the hardware wants.
After this all platforms, incluing SKL+, compute these things in exactly
the same way (excluding alignemnt differences).
v2: Use BIT(DRM_ROTATE_270) instead of ROTATE_270 when rotating
plane src coordinates
Drop some spurious changes that got left behind during
development
v3: Split out more changes to prep patches (Daniel)
s/intel_fb->plane[].foo.bar/intel_fb->foo[].bar/ for brevity
Rename intel_surf_gtt_offset to intel_fb_gtt_offset
Kill the pointless 'plane' parameter from intel_fb_gtt_offset()
v4: Fix alignment vs. alignment-1 when calling
_intel_compute_tile_offset() from intel_fill_fb_info()
Pass the pitch in tiles in
stad of pixels to intel_adjust_tile_offset() from intel_fill_fb_info()
Pass the full width/height of the rotated area to
drm_rect_rotate() for clarity
Use u32 for more offsets
v5: Preserve the upper_32_bits()/lower_32_bits() handling for the
fb ggtt offset (Sivakumar)
v6: Rebase due to drm_plane_state src/dst rects
Cc: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1470821001-25272-2-git-send-email-ville.syrjala@linux.intel.com
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-09-15 18:16:41 +08:00
|
|
|
DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! (%ux%u tiles, %u pages)\n",
|
|
|
|
obj->base.size, rot_info->plane[0].width, rot_info->plane[0].height, size);
|
|
|
|
|
2015-03-23 19:10:36 +08:00
|
|
|
return ERR_PTR(ret);
|
|
|
|
}
|
2015-03-16 20:11:13 +08:00
|
|
|
|
2015-05-06 19:35:38 +08:00
|
|
|
static struct sg_table *
|
|
|
|
intel_partial_pages(const struct i915_ggtt_view *view,
|
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
|
{
|
|
|
|
struct sg_table *st;
|
|
|
|
struct scatterlist *sg;
|
|
|
|
struct sg_page_iter obj_sg_iter;
|
|
|
|
int ret = -ENOMEM;
|
|
|
|
|
|
|
|
st = kmalloc(sizeof(*st), GFP_KERNEL);
|
|
|
|
if (!st)
|
|
|
|
goto err_st_alloc;
|
|
|
|
|
|
|
|
ret = sg_alloc_table(st, view->params.partial.size, GFP_KERNEL);
|
|
|
|
if (ret)
|
|
|
|
goto err_sg_alloc;
|
|
|
|
|
|
|
|
sg = st->sgl;
|
|
|
|
st->nents = 0;
|
|
|
|
for_each_sg_page(obj->pages->sgl, &obj_sg_iter, obj->pages->nents,
|
|
|
|
view->params.partial.offset)
|
|
|
|
{
|
|
|
|
if (st->nents >= view->params.partial.size)
|
|
|
|
break;
|
|
|
|
|
|
|
|
sg_set_page(sg, NULL, PAGE_SIZE, 0);
|
|
|
|
sg_dma_address(sg) = sg_page_iter_dma_address(&obj_sg_iter);
|
|
|
|
sg_dma_len(sg) = PAGE_SIZE;
|
|
|
|
|
|
|
|
sg = sg_next(sg);
|
|
|
|
st->nents++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return st;
|
|
|
|
|
|
|
|
err_sg_alloc:
|
|
|
|
kfree(st);
|
|
|
|
err_st_alloc:
|
|
|
|
return ERR_PTR(ret);
|
|
|
|
}
|
|
|
|
|
2015-04-14 23:35:27 +08:00
|
|
|
static int
|
2015-03-23 19:10:36 +08:00
|
|
|
i915_get_ggtt_vma_pages(struct i915_vma *vma)
|
2014-12-11 01:27:58 +08:00
|
|
|
{
|
2015-03-23 19:10:36 +08:00
|
|
|
int ret = 0;
|
|
|
|
|
2016-08-15 17:48:47 +08:00
|
|
|
if (vma->pages)
|
2014-12-11 01:27:58 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL)
|
2016-08-15 17:48:47 +08:00
|
|
|
vma->pages = vma->obj->pages;
|
2015-03-23 19:10:36 +08:00
|
|
|
else if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED)
|
2016-08-15 17:48:47 +08:00
|
|
|
vma->pages =
|
2016-01-21 03:05:24 +08:00
|
|
|
intel_rotate_fb_obj_pages(&vma->ggtt_view.params.rotated, vma->obj);
|
2015-05-06 19:35:38 +08:00
|
|
|
else if (vma->ggtt_view.type == I915_GGTT_VIEW_PARTIAL)
|
2016-08-15 17:48:47 +08:00
|
|
|
vma->pages = intel_partial_pages(&vma->ggtt_view, vma->obj);
|
2014-12-11 01:27:58 +08:00
|
|
|
else
|
|
|
|
WARN_ONCE(1, "GGTT view %u not implemented!\n",
|
|
|
|
vma->ggtt_view.type);
|
|
|
|
|
2016-08-15 17:48:47 +08:00
|
|
|
if (!vma->pages) {
|
2015-03-16 20:11:13 +08:00
|
|
|
DRM_ERROR("Failed to get pages for GGTT view type %u!\n",
|
2014-12-11 01:27:58 +08:00
|
|
|
vma->ggtt_view.type);
|
2015-03-23 19:10:36 +08:00
|
|
|
ret = -EINVAL;
|
2016-08-15 17:48:47 +08:00
|
|
|
} else if (IS_ERR(vma->pages)) {
|
|
|
|
ret = PTR_ERR(vma->pages);
|
|
|
|
vma->pages = NULL;
|
2015-03-23 19:10:36 +08:00
|
|
|
DRM_ERROR("Failed to get pages for VMA view type %u (%d)!\n",
|
|
|
|
vma->ggtt_view.type, ret);
|
2014-12-11 01:27:58 +08:00
|
|
|
}
|
|
|
|
|
2015-03-23 19:10:36 +08:00
|
|
|
return ret;
|
2014-12-11 01:27:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* i915_vma_bind - Sets up PTEs for an VMA in it's corresponding address space.
|
|
|
|
* @vma: VMA to map
|
|
|
|
* @cache_level: mapping cache level
|
|
|
|
* @flags: flags like global or local mapping
|
|
|
|
*
|
|
|
|
* DMA addresses are taken from the scatter-gather table of this object (or of
|
|
|
|
* this VMA in case of non-default GGTT views) and PTE entries set up.
|
|
|
|
* Note that DMA addresses are also the only part of the SG table we care about.
|
|
|
|
*/
|
|
|
|
int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
|
|
|
|
u32 flags)
|
|
|
|
{
|
2015-04-28 22:56:17 +08:00
|
|
|
u32 bind_flags;
|
2016-08-04 23:32:32 +08:00
|
|
|
u32 vma_flags;
|
|
|
|
int ret;
|
2015-04-10 20:54:58 +08:00
|
|
|
|
2015-04-28 22:56:17 +08:00
|
|
|
if (WARN_ON(flags == 0))
|
|
|
|
return -EINVAL;
|
2015-04-10 20:54:58 +08:00
|
|
|
|
2015-04-28 22:56:17 +08:00
|
|
|
bind_flags = 0;
|
2015-04-21 00:04:05 +08:00
|
|
|
if (flags & PIN_GLOBAL)
|
2016-08-04 23:32:32 +08:00
|
|
|
bind_flags |= I915_VMA_GLOBAL_BIND;
|
2015-04-21 00:04:05 +08:00
|
|
|
if (flags & PIN_USER)
|
2016-08-04 23:32:32 +08:00
|
|
|
bind_flags |= I915_VMA_LOCAL_BIND;
|
2015-04-21 00:04:05 +08:00
|
|
|
|
2016-08-04 23:32:32 +08:00
|
|
|
vma_flags = vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
|
2015-04-21 00:04:05 +08:00
|
|
|
if (flags & PIN_UPDATE)
|
2016-08-04 23:32:32 +08:00
|
|
|
bind_flags |= vma_flags;
|
2015-04-21 00:04:05 +08:00
|
|
|
else
|
2016-08-04 23:32:32 +08:00
|
|
|
bind_flags &= ~vma_flags;
|
2015-04-28 22:56:17 +08:00
|
|
|
if (bind_flags == 0)
|
|
|
|
return 0;
|
|
|
|
|
2016-08-04 23:32:32 +08:00
|
|
|
if (vma_flags == 0 && vma->vm->allocate_va_range) {
|
2016-02-26 19:03:20 +08:00
|
|
|
trace_i915_va_alloc(vma);
|
2015-04-28 22:56:17 +08:00
|
|
|
ret = vma->vm->allocate_va_range(vma->vm,
|
|
|
|
vma->node.start,
|
|
|
|
vma->node.size);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = vma->vm->bind_vma(vma, cache_level, bind_flags);
|
2015-04-14 23:35:27 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2015-04-21 00:04:05 +08:00
|
|
|
|
2016-08-04 23:32:32 +08:00
|
|
|
vma->flags |= bind_flags;
|
2014-12-11 01:27:58 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2015-05-06 19:33:58 +08:00
|
|
|
|
2016-04-28 16:56:39 +08:00
|
|
|
void __iomem *i915_vma_pin_iomap(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
void __iomem *ptr;
|
|
|
|
|
2016-08-15 17:48:56 +08:00
|
|
|
/* Access through the GTT requires the device to be awake. */
|
|
|
|
assert_rpm_wakelock_held(to_i915(vma->vm->dev));
|
|
|
|
|
2016-04-28 16:56:39 +08:00
|
|
|
lockdep_assert_held(&vma->vm->dev->struct_mutex);
|
2016-08-19 00:16:55 +08:00
|
|
|
if (WARN_ON(!i915_vma_is_map_and_fenceable(vma)))
|
2016-07-20 20:31:55 +08:00
|
|
|
return IO_ERR_PTR(-ENODEV);
|
2016-04-28 16:56:39 +08:00
|
|
|
|
2016-08-04 23:32:32 +08:00
|
|
|
GEM_BUG_ON(!i915_vma_is_ggtt(vma));
|
|
|
|
GEM_BUG_ON((vma->flags & I915_VMA_GLOBAL_BIND) == 0);
|
2016-04-28 16:56:39 +08:00
|
|
|
|
|
|
|
ptr = vma->iomap;
|
|
|
|
if (ptr == NULL) {
|
2016-08-19 23:54:27 +08:00
|
|
|
ptr = io_mapping_map_wc(&i915_vm_to_ggtt(vma->vm)->mappable,
|
2016-04-28 16:56:39 +08:00
|
|
|
vma->node.start,
|
|
|
|
vma->node.size);
|
|
|
|
if (ptr == NULL)
|
2016-07-20 20:31:55 +08:00
|
|
|
return IO_ERR_PTR(-ENOMEM);
|
2016-04-28 16:56:39 +08:00
|
|
|
|
|
|
|
vma->iomap = ptr;
|
|
|
|
}
|
|
|
|
|
2016-08-04 23:32:30 +08:00
|
|
|
__i915_vma_pin(vma);
|
2016-04-28 16:56:39 +08:00
|
|
|
return ptr;
|
|
|
|
}
|
2016-08-15 17:49:05 +08:00
|
|
|
|
|
|
|
void i915_vma_unpin_and_release(struct i915_vma **p_vma)
|
|
|
|
{
|
|
|
|
struct i915_vma *vma;
|
|
|
|
|
|
|
|
vma = fetch_and_zero(p_vma);
|
|
|
|
if (!vma)
|
|
|
|
return;
|
|
|
|
|
|
|
|
i915_vma_unpin(vma);
|
|
|
|
i915_vma_put(vma);
|
|
|
|
}
|