drm/i915/gtt: Read-only pages for insert_entries on bdw+

commit 250f8c8140ac0a5e5acb91891d6813f12778b224 upstream.

Hook up the flags to allow read-only ppGTT mappings for gen8+

v2: Include a selftest to check that writes to a readonly PTE are
dropped
v3: Don't duplicate cpu_check() as we can just reuse it, and even worse
don't wholesale copy the theory-of-operation comment from igt_ctx_exec
without changing it to explain the intention behind the new test!
v4: Joonas really likes magic mystery values

Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Matthew Auld <matthew.william.auld@gmail.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Matthew Auld <matthew.william.auld@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180712185315.3288-2-chris@chris-wilson.co.uk
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Vivi, Rodrigo 2018-08-06 14:10:48 -07:00 committed by Greg Kroah-Hartman
parent b8fa42e6cf
commit 0a41eb61a2
3 changed files with 38 additions and 17 deletions

View File

@ -207,7 +207,7 @@ static int ppgtt_bind_vma(struct i915_vma *vma,
vma->pages = vma->obj->mm.pages;
/* Currently applicable only to VLV */
/* Applicable to VLV, and gen8+ */
pte_flags = 0;
if (vma->obj->gt_ro)
pte_flags |= PTE_READ_ONLY;
@ -866,10 +866,11 @@ gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt,
struct i915_page_directory_pointer *pdp,
struct sgt_dma *iter,
struct gen8_insert_pte *idx,
enum i915_cache_level cache_level)
enum i915_cache_level cache_level,
u32 flags)
{
struct i915_page_directory *pd;
const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level, 0);
const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level, flags);
gen8_pte_t *vaddr;
bool ret;
@ -920,20 +921,20 @@ gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt,
static void gen8_ppgtt_insert_3lvl(struct i915_address_space *vm,
struct i915_vma *vma,
enum i915_cache_level cache_level,
u32 unused)
u32 flags)
{
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
struct sgt_dma iter = sgt_dma(vma);
struct gen8_insert_pte idx = gen8_insert_pte(vma->node.start);
gen8_ppgtt_insert_pte_entries(ppgtt, &ppgtt->pdp, &iter, &idx,
cache_level);
cache_level, flags);
}
static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
struct i915_vma *vma,
enum i915_cache_level cache_level,
u32 unused)
u32 flags)
{
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
struct sgt_dma iter = sgt_dma(vma);
@ -941,7 +942,7 @@ static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
struct gen8_insert_pte idx = gen8_insert_pte(vma->node.start);
while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[idx.pml4e++], &iter,
&idx, cache_level))
&idx, cache_level, flags))
GEM_BUG_ON(idx.pml4e >= GEN8_PML4ES_PER_PML4);
}
@ -1342,6 +1343,9 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
return ret;
}
/* From bdw, there is support for read-only pages in the PPGTT */
ppgtt->base.has_read_only = true;
/* There are only few exceptions for gen >=6. chv and bxt.
* And we are not sure about the latter so play safe for now.
*/
@ -2089,7 +2093,7 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm,
static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
struct i915_vma *vma,
enum i915_cache_level level,
u32 unused)
u32 flags)
{
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
struct sgt_iter sgt_iter;
@ -2097,6 +2101,9 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
const gen8_pte_t pte_encode = gen8_pte_encode(0, level, 0);
dma_addr_t addr;
/* The GTT does not support read-only mappings */
GEM_BUG_ON(flags & PTE_READ_ONLY);
gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm;
gtt_entries += vma->node.start >> PAGE_SHIFT;
for_each_sgt_dma(addr, sgt_iter, vma->pages)
@ -2226,13 +2233,14 @@ struct insert_entries {
struct i915_address_space *vm;
struct i915_vma *vma;
enum i915_cache_level level;
u32 flags;
};
static int bxt_vtd_ggtt_insert_entries__cb(void *_arg)
{
struct insert_entries *arg = _arg;
gen8_ggtt_insert_entries(arg->vm, arg->vma, arg->level, 0);
gen8_ggtt_insert_entries(arg->vm, arg->vma, arg->level, arg->flags);
bxt_vtd_ggtt_wa(arg->vm);
return 0;
@ -2241,9 +2249,9 @@ static int bxt_vtd_ggtt_insert_entries__cb(void *_arg)
static void bxt_vtd_ggtt_insert_entries__BKL(struct i915_address_space *vm,
struct i915_vma *vma,
enum i915_cache_level level,
u32 unused)
u32 flags)
{
struct insert_entries arg = { vm, vma, level };
struct insert_entries arg = { vm, vma, level, flags };
stop_machine(bxt_vtd_ggtt_insert_entries__cb, &arg, NULL);
}
@ -2340,7 +2348,7 @@ static int ggtt_bind_vma(struct i915_vma *vma,
return ret;
}
/* Currently applicable only to VLV */
/* Applicable to VLV (gen8+ do not support RO in the GGTT) */
pte_flags = 0;
if (obj->gt_ro)
pte_flags |= PTE_READ_ONLY;
@ -3066,6 +3074,10 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)
*/
mutex_lock(&dev_priv->drm.struct_mutex);
i915_address_space_init(&ggtt->base, dev_priv, "[global]");
/* Only VLV supports read-only GGTT mappings */
ggtt->base.has_read_only = IS_VALLEYVIEW(dev_priv);
if (!HAS_LLC(dev_priv) && !USES_PPGTT(dev_priv))
ggtt->base.mm.color_adjust = i915_gtt_color_adjust;
mutex_unlock(&dev_priv->drm.struct_mutex);
@ -3098,7 +3110,6 @@ int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv)
{
if (INTEL_GEN(dev_priv) < 6 && !intel_enable_gtt())
return -EIO;
return 0;
}

View File

@ -295,7 +295,12 @@ struct i915_address_space {
struct list_head unbound_list;
struct pagevec free_pages;
bool pt_kmap_wc;
/* Some systems require uncached updates of the page directories */
bool pt_kmap_wc:1;
/* Some systems support read-only mappings for GGTT and/or PPGTT */
bool has_read_only:1;
/* FIXME: Need a more generic return type */
gen6_pte_t (*pte_encode)(dma_addr_t addr,

View File

@ -1358,6 +1358,7 @@ void intel_ring_unpin(struct intel_ring *ring)
static struct i915_vma *
intel_ring_create_vma(struct drm_i915_private *dev_priv, int size)
{
struct i915_address_space *vm = &dev_priv->ggtt.base;
struct drm_i915_gem_object *obj;
struct i915_vma *vma;
@ -1367,10 +1368,14 @@ intel_ring_create_vma(struct drm_i915_private *dev_priv, int size)
if (IS_ERR(obj))
return ERR_CAST(obj);
/* mark ring buffers as read-only from GPU side by default */
obj->gt_ro = 1;
/*
* Mark ring buffers as read-only from GPU side (so no stray overwrites)
* if supported by the platform's GGTT.
*/
if (vm->has_read_only)
obj->gt_ro = 1;
vma = i915_vma_instance(obj, &dev_priv->ggtt.base, NULL);
vma = i915_vma_instance(obj, vm, NULL);
if (IS_ERR(vma))
goto err;