drm/i915/gtt: Add read only pages to gen8_pte_encode
authorJon Bloomfield <jon.bloomfield@intel.com>
Thu, 12 Jul 2018 18:53:10 +0000 (19:53 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 12 Nov 2019 18:13:31 +0000 (19:13 +0100)
commit 25dda4dabeeb12af5209b0183c788ef2a88dabbe upstream.

We can set a bit inside the ppGTT PTE to indicate a page is read-only;
writes from the GPU will be discarded. We can use this to protect pages
and in particular support read-only userptr mappings (necessary for
importing PROT_READ vma).

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-1-chris@chris-wilson.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/gpu/drm/i915/i915_gem_gtt.c

index b37fe0df743e79948fdaaf808406b1773ef5dd55..272b03b4f1ec18a146fcf9697fef165a22ecec54 100644 (file)
@@ -172,11 +172,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 +463,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 +760,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,
@@ -799,7 +803,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, 0);
                if (++pte == GEN8_PTES) {
                        kunmap_px(ppgtt, pt_vaddr);
                        pt_vaddr = NULL;
@@ -1447,7 +1451,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);
@@ -2357,7 +2361,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(&gtt_entries[i],
-                            gen8_pte_encode(addr, level, true));
+                            gen8_pte_encode(addr, level, true, 0));
                i++;
        }
 
@@ -2370,7 +2374,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
         */
        if (i != 0)
                WARN_ON(readq(&gtt_entries[i-1])
-                       != gen8_pte_encode(addr, level, true));
+                       != gen8_pte_encode(addr, level, true, 0));
 
        /* 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 +2448,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(&gtt_base[i], scratch_pte);
        readl(gtt_base);