diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_gtt.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index b37fe0df743e..65a53ee398b8 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -119,7 +119,8 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) (enable_ppgtt == 0 || !has_aliasing_ppgtt)) return 0; - if (enable_ppgtt == 1) + /* Full PPGTT is required by the Gen9 cmdparser */ + if (enable_ppgtt == 1 && INTEL_INFO(dev)->gen != 9) return 1; if (enable_ppgtt == 2 && has_full_ppgtt) @@ -152,7 +153,8 @@ static int ppgtt_bind_vma(struct i915_vma *vma, { u32 pte_flags = 0; - /* Currently applicable only to VLV */ + /* Applicable to VLV, and gen8+ */ + pte_flags = 0; if (vma->obj->gt_ro) pte_flags |= PTE_READ_ONLY; @@ -172,11 +174,14 @@ static void ppgtt_unbind_vma(struct i915_vma *vma) static gen8_pte_t gen8_pte_encode(dma_addr_t addr, enum i915_cache_level level, - bool valid) + bool valid, u32 flags) { gen8_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0; pte |= addr; + if (unlikely(flags & PTE_READ_ONLY)) + pte &= ~_PAGE_RW; + switch (level) { case I915_CACHE_NONE: pte |= PPAT_UNCACHED_INDEX; @@ -460,7 +465,7 @@ static void gen8_initialize_pt(struct i915_address_space *vm, gen8_pte_t scratch_pte; scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), - I915_CACHE_LLC, true); + I915_CACHE_LLC, true, 0); fill_px(vm->dev, pt, scratch_pte); } @@ -757,8 +762,9 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm, { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); - gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), - I915_CACHE_LLC, use_scratch); + gen8_pte_t scratch_pte = + gen8_pte_encode(px_dma(vm->scratch_page), + I915_CACHE_LLC, use_scratch, 0); if (!USES_FULL_48BIT_PPGTT(vm->dev)) { gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length, @@ -779,7 +785,8 @@ gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, struct i915_page_directory_pointer *pdp, struct sg_page_iter *sg_iter, uint64_t start, - enum i915_cache_level cache_level) + enum i915_cache_level cache_level, + u32 flags) { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); @@ -799,7 +806,7 @@ gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, pt_vaddr[pte] = gen8_pte_encode(sg_page_iter_dma_address(sg_iter), - cache_level, true); + cache_level, true, flags); if (++pte == GEN8_PTES) { kunmap_px(ppgtt, pt_vaddr); pt_vaddr = NULL; @@ -820,7 +827,7 @@ 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) + u32 flags) { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); @@ -830,7 +837,7 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, if (!USES_FULL_48BIT_PPGTT(vm->dev)) { gen8_ppgtt_insert_pte_entries(vm, &ppgtt->pdp, &sg_iter, start, - cache_level); + cache_level, flags); } else { struct i915_page_directory_pointer *pdp; uint64_t templ4, pml4e; @@ -838,7 +845,7 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) { gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter, - start, cache_level); + start, cache_level, flags); } } } @@ -1447,7 +1454,7 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) uint64_t start = ppgtt->base.start; uint64_t length = ppgtt->base.total; gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), - I915_CACHE_LLC, true); + I915_CACHE_LLC, true, 0); if (!USES_FULL_48BIT_PPGTT(vm->dev)) { gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m); @@ -1515,6 +1522,14 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->base.clear_range = gen8_ppgtt_clear_range; ppgtt->base.unbind_vma = ppgtt_unbind_vma; ppgtt->base.bind_vma = ppgtt_bind_vma; + + /* + * From bdw, there is support for read-only pages in the PPGTT. + * + * XXX GVT is not honouring the lack of RW in the PTE bits. + */ + ppgtt->base.has_read_only = !intel_vgpu_active(ppgtt->base.dev); + ppgtt->debug_dump = gen8_dump_ppgtt; if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { @@ -2343,7 +2358,7 @@ static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte) static void gen8_ggtt_insert_entries(struct i915_address_space *vm, struct sg_table *st, uint64_t start, - enum i915_cache_level level, u32 unused) + enum i915_cache_level level, u32 flags) { struct drm_i915_private *dev_priv = vm->dev->dev_private; unsigned first_entry = start >> PAGE_SHIFT; @@ -2357,7 +2372,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, addr = sg_dma_address(sg_iter.sg) + (sg_iter.sg_pgoffset << PAGE_SHIFT); gen8_set_pte(>t_entries[i], - gen8_pte_encode(addr, level, true)); + gen8_pte_encode(addr, level, true, flags)); i++; } @@ -2370,7 +2385,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, */ if (i != 0) WARN_ON(readq(>t_entries[i-1]) - != gen8_pte_encode(addr, level, true)); + != gen8_pte_encode(addr, level, true, flags)); /* 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 @@ -2444,7 +2459,7 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), I915_CACHE_LLC, - use_scratch); + use_scratch, 0); for (i = 0; i < num_entries; i++) gen8_set_pte(>t_base[i], scratch_pte); readl(gtt_base); @@ -2510,7 +2525,8 @@ static int ggtt_bind_vma(struct i915_vma *vma, if (ret) 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; @@ -2653,6 +2669,9 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, i915_address_space_init(ggtt_vm, dev_priv); ggtt_vm->total += PAGE_SIZE; + /* Only VLV supports read-only GGTT mappings */ + ggtt_vm->has_read_only = IS_VALLEYVIEW(dev_priv); + if (intel_vgpu_active(dev)) { ret = intel_vgt_balloon(dev); if (ret) |