drm/i915: Fix up the inverse mapping for default ctx->engines[]
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / i915_gem_gtt.h
index 03ade71..5127448 100644 (file)
 #define __I915_GEM_GTT_H__
 
 #include <linux/io-mapping.h>
+#include <linux/kref.h>
 #include <linux/mm.h>
 #include <linux/pagevec.h>
+#include <linux/workqueue.h>
 
+#include <drm/drm_mm.h>
+
+#include "gt/intel_reset.h"
+#include "i915_gem_fence_reg.h"
 #include "i915_request.h"
-#include "i915_reset.h"
+#include "i915_scatterlist.h"
 #include "i915_selftest.h"
-#include "i915_timeline.h"
+#include "gt/intel_timeline.h"
 
 #define I915_GTT_PAGE_SIZE_4K  BIT_ULL(12)
 #define I915_GTT_PAGE_SIZE_64K BIT_ULL(16)
 #define I915_MAX_NUM_FENCE_BITS 6
 
 struct drm_i915_file_private;
-struct drm_i915_fence_reg;
+struct drm_i915_gem_object;
 struct i915_vma;
+struct intel_gt;
 
 typedef u32 gen6_pte_t;
 typedef u64 gen8_pte_t;
-typedef u64 gen8_pde_t;
-typedef u64 gen8_ppgtt_pdpe_t;
-typedef u64 gen8_ppgtt_pml4e_t;
 
 #define ggtt_total_entries(ggtt) ((ggtt)->vm.total >> PAGE_SHIFT)
 
@@ -111,30 +115,18 @@ typedef u64 gen8_ppgtt_pml4e_t;
 #define HSW_GTT_ADDR_ENCODE(addr)      ((addr) | (((addr) >> 28) & 0x7f0))
 #define HSW_PTE_ADDR_ENCODE(addr)      HSW_GTT_ADDR_ENCODE(addr)
 
-/* GEN8 32b style address is defined as a 3 level page table:
+/*
+ * GEN8 32b style address is defined as a 3 level page table:
  * 31:30 | 29:21 | 20:12 |  11:0
  * PDPE  |  PDE  |  PTE  | offset
  * The difference as compared to normal x86 3 level page table is the PDPEs are
  * programmed via register.
- */
-#define GEN8_3LVL_PDPES                        4
-#define GEN8_PDE_SHIFT                 21
-#define GEN8_PDE_MASK                  0x1ff
-#define GEN8_PTE_SHIFT                 12
-#define GEN8_PTE_MASK                  0x1ff
-#define GEN8_PTES                      I915_PTES(sizeof(gen8_pte_t))
-
-/* GEN8 48b style address is defined as a 4 level page table:
+ *
+ * GEN8 48b style address is defined as a 4 level page table:
  * 47:39 | 38:30 | 29:21 | 20:12 |  11:0
  * PML4E | PDPE  |  PDE  |  PTE  | offset
  */
-#define GEN8_PML4ES_PER_PML4           512
-#define GEN8_PML4E_SHIFT               39
-#define GEN8_PML4E_MASK                        (GEN8_PML4ES_PER_PML4 - 1)
-#define GEN8_PDPE_SHIFT                        30
-/* NB: GEN8_PDPE_MASK is untrue for 32b platforms, but it has no impact on 32b page
- * tables */
-#define GEN8_PDPE_MASK                 0x1ff
+#define GEN8_3LVL_PDPES                        4
 
 #define PPAT_UNCACHED                  (_PAGE_PWT | _PAGE_PCD)
 #define PPAT_CACHED_PDE                        0 /* WB LLC */
@@ -153,21 +145,24 @@ typedef u64 gen8_ppgtt_pml4e_t;
 #define GEN8_PPAT_ELLC_OVERRIDE                (0<<2)
 #define GEN8_PPAT(i, x)                        ((u64)(x) << ((i) * 8))
 
-#define GEN8_PPAT_GET_CA(x) ((x) & 3)
-#define GEN8_PPAT_GET_TC(x) ((x) & (3 << 2))
-#define GEN8_PPAT_GET_AGE(x) ((x) & (3 << 4))
-#define CHV_PPAT_GET_SNOOP(x) ((x) & (1 << 6))
-
 #define GEN8_PDE_IPS_64K BIT(11)
 #define GEN8_PDE_PS_2M   BIT(7)
 
-struct sg_table;
+#define for_each_sgt_dma(__dmap, __iter, __sgt) \
+       __for_each_sgt_dma(__dmap, __iter, __sgt, I915_GTT_PAGE_SIZE)
+
+struct intel_remapped_plane_info {
+       /* in gtt pages */
+       unsigned int width, height, stride, offset;
+} __packed;
+
+struct intel_remapped_info {
+       struct intel_remapped_plane_info plane[2];
+       unsigned int unused_mbz;
+} __packed;
 
 struct intel_rotation_info {
-       struct intel_rotation_plane_info {
-               /* tiles */
-               unsigned int width, height, stride, offset;
-       } plane[2];
+       struct intel_remapped_plane_info plane[2];
 } __packed;
 
 struct intel_partial_info {
@@ -179,12 +174,20 @@ enum i915_ggtt_view_type {
        I915_GGTT_VIEW_NORMAL = 0,
        I915_GGTT_VIEW_ROTATED = sizeof(struct intel_rotation_info),
        I915_GGTT_VIEW_PARTIAL = sizeof(struct intel_partial_info),
+       I915_GGTT_VIEW_REMAPPED = sizeof(struct intel_remapped_info),
 };
 
 static inline void assert_i915_gem_gtt_types(void)
 {
        BUILD_BUG_ON(sizeof(struct intel_rotation_info) != 8*sizeof(unsigned int));
        BUILD_BUG_ON(sizeof(struct intel_partial_info) != sizeof(u64) + sizeof(unsigned int));
+       BUILD_BUG_ON(sizeof(struct intel_remapped_info) != 9*sizeof(unsigned int));
+
+       /* Check that rotation/remapped shares offsets for simplicity */
+       BUILD_BUG_ON(offsetof(struct intel_remapped_info, plane[0]) !=
+                    offsetof(struct intel_rotation_info, plane[0]));
+       BUILD_BUG_ON(offsetofend(struct intel_remapped_info, plane[1]) !=
+                    offsetofend(struct intel_rotation_info, plane[1]));
 
        /* As we encode the size of each branch inside the union into its type,
         * we have to be careful that each branch has a unique size.
@@ -193,6 +196,7 @@ static inline void assert_i915_gem_gtt_types(void)
        case I915_GGTT_VIEW_NORMAL:
        case I915_GGTT_VIEW_PARTIAL:
        case I915_GGTT_VIEW_ROTATED:
+       case I915_GGTT_VIEW_REMAPPED:
                /* gcc complains if these are identical cases */
                break;
        }
@@ -204,6 +208,7 @@ struct i915_ggtt_view {
                /* Members need to contain no holes/padding */
                struct intel_partial_info partial;
                struct intel_rotation_info rotated;
+               struct intel_remapped_info remapped;
        };
 };
 
@@ -213,7 +218,6 @@ struct i915_vma;
 
 struct i915_page_dma {
        struct page *page;
-       int order;
        union {
                dma_addr_t daddr;
 
@@ -224,31 +228,42 @@ struct i915_page_dma {
        };
 };
 
-#define px_base(px) (&(px)->base)
-#define px_dma(px) (px_base(px)->daddr)
+struct i915_page_scratch {
+       struct i915_page_dma base;
+       u64 encode;
+};
 
 struct i915_page_table {
        struct i915_page_dma base;
-       unsigned int used_ptes;
+       atomic_t used;
 };
 
 struct i915_page_directory {
-       struct i915_page_dma base;
-
-       struct i915_page_table *page_table[I915_PDES]; /* PDEs */
-       unsigned int used_pdes;
+       struct i915_page_table pt;
+       spinlock_t lock;
+       void *entry[512];
 };
 
-struct i915_page_directory_pointer {
-       struct i915_page_dma base;
-       struct i915_page_directory **page_directory;
-       unsigned int used_pdpes;
-};
+#define __px_choose_expr(x, type, expr, other) \
+       __builtin_choose_expr( \
+       __builtin_types_compatible_p(typeof(x), type) || \
+       __builtin_types_compatible_p(typeof(x), const type), \
+       ({ type __x = (type)(x); expr; }), \
+       other)
+
+#define px_base(px) \
+       __px_choose_expr(px, struct i915_page_dma *, __x, \
+       __px_choose_expr(px, struct i915_page_scratch *, &__x->base, \
+       __px_choose_expr(px, struct i915_page_table *, &__x->base, \
+       __px_choose_expr(px, struct i915_page_directory *, &__x->pt.base, \
+       (void)0))))
+#define px_dma(px) (px_base(px)->daddr)
 
-struct i915_pml4 {
-       struct i915_page_dma base;
-       struct i915_page_directory_pointer *pdps[GEN8_PML4ES_PER_PML4];
-};
+#define px_pt(px) \
+       __px_choose_expr(px, struct i915_page_table *, __x, \
+       __px_choose_expr(px, struct i915_page_directory *, &__x->pt, \
+       (void)0))
+#define px_used(px) (&px_pt(px)->used)
 
 struct i915_vma_ops {
        /* Map an object into an address space with the given cache flags. */
@@ -271,7 +286,11 @@ struct pagestash {
 };
 
 struct i915_address_space {
+       struct kref ref;
+       struct rcu_work rcu;
+
        struct drm_mm mm;
+       struct intel_gt *gt;
        struct drm_i915_private *i915;
        struct device *dma;
        /* Every address space belongs to a struct file - except for the global
@@ -292,11 +311,9 @@ struct i915_address_space {
 #define VM_CLASS_GGTT 0
 #define VM_CLASS_PPGTT 1
 
-       u64 scratch_pte;
-       struct i915_page_dma scratch_page;
-       struct i915_page_table *scratch_pt;
-       struct i915_page_directory *scratch_pd;
-       struct i915_page_directory_pointer *scratch_pdp; /* GEN8+ & 48b PPGTT */
+       struct i915_page_scratch scratch[4];
+       unsigned int scratch_order;
+       unsigned int top;
 
        /**
         * List of vma currently bound.
@@ -348,7 +365,7 @@ struct i915_address_space {
 #define i915_is_ggtt(vm) ((vm)->is_ggtt)
 
 static inline bool
-i915_vm_is_48bit(const struct i915_address_space *vm)
+i915_vm_is_4lvl(const struct i915_address_space *vm)
 {
        return (vm->total - 1) >> 32;
 }
@@ -356,7 +373,7 @@ i915_vm_is_48bit(const struct i915_address_space *vm)
 static inline bool
 i915_vm_has_scratch_64K(struct i915_address_space *vm)
 {
-       return vm->scratch_page.order == get_order(I915_GTT_PAGE_SIZE_64K);
+       return vm->scratch_order == get_order(I915_GTT_PAGE_SIZE_64K);
 }
 
 /* The Graphics Translation Table is the way in which GEN hardware translates a
@@ -375,7 +392,10 @@ struct i915_ggtt {
 
        /** "Graphics Stolen Memory" holds the global PTEs */
        void __iomem *gsm;
-       void (*invalidate)(struct drm_i915_private *dev_priv);
+       void (*invalidate)(struct i915_ggtt *ggtt);
+
+       /** PPGTT used for aliasing the PPGTT with the GTT */
+       struct i915_ppgtt *alias;
 
        bool do_idle_maps;
 
@@ -383,23 +403,31 @@ struct i915_ggtt {
 
        u32 pin_bias;
 
+       unsigned int num_fences;
+       struct i915_fence_reg fence_regs[I915_MAX_NUM_FENCES];
+       struct list_head fence_list;
+
+       /** List of all objects in gtt_space, currently mmaped by userspace.
+        * All objects within this list must also be on bound_list.
+        */
+       struct list_head userfault_list;
+
+       /* Manual runtime pm autosuspend delay for user GGTT mmaps */
+       struct intel_wakeref_auto userfault_wakeref;
+
        struct drm_mm_node error_capture;
+       struct drm_mm_node uc_fw;
 };
 
-struct i915_hw_ppgtt {
+struct i915_ppgtt {
        struct i915_address_space vm;
-       struct kref ref;
 
-       unsigned long pd_dirty_rings;
-       union {
-               struct i915_pml4 pml4;          /* GEN8+ & 48b PPGTT */
-               struct i915_page_directory_pointer pdp; /* GEN8+ */
-               struct i915_page_directory pd;          /* GEN6-7 */
-       };
+       intel_engine_mask_t pd_dirty_engines;
+       struct i915_page_directory *pd;
 };
 
-struct gen6_hw_ppgtt {
-       struct i915_hw_ppgtt base;
+struct gen6_ppgtt {
+       struct i915_ppgtt base;
 
        struct i915_vma *vma;
        gen6_pte_t __iomem *pd_addr;
@@ -408,11 +436,11 @@ struct gen6_hw_ppgtt {
        bool scan_for_unused_pt;
 };
 
-#define __to_gen6_ppgtt(base) container_of(base, struct gen6_hw_ppgtt, base)
+#define __to_gen6_ppgtt(base) container_of(base, struct gen6_ppgtt, base)
 
-static inline struct gen6_hw_ppgtt *to_gen6_ppgtt(struct i915_hw_ppgtt *base)
+static inline struct gen6_ppgtt *to_gen6_ppgtt(struct i915_ppgtt *base)
 {
-       BUILD_BUG_ON(offsetof(struct gen6_hw_ppgtt, base));
+       BUILD_BUG_ON(offsetof(struct gen6_ppgtt, base));
        return __to_gen6_ppgtt(base);
 }
 
@@ -427,7 +455,7 @@ static inline struct gen6_hw_ppgtt *to_gen6_ppgtt(struct i915_hw_ppgtt *base)
 #define gen6_for_each_pde(pt, pd, start, length, iter)                 \
        for (iter = gen6_pde_index(start);                              \
             length > 0 && iter < I915_PDES &&                          \
-               (pt = (pd)->page_table[iter], true);                    \
+                    (pt = i915_pt_entry(pd, iter), true);              \
             ({ u32 temp = ALIGN(start+1, 1 << GEN6_PDE_SHIFT);         \
                    temp = min(temp - start, length);                   \
                    start += temp, length -= temp; }), ++iter)
@@ -435,7 +463,7 @@ static inline struct gen6_hw_ppgtt *to_gen6_ppgtt(struct i915_hw_ppgtt *base)
 #define gen6_for_all_pdes(pt, pd, iter)                                        \
        for (iter = 0;                                                  \
             iter < I915_PDES &&                                        \
-               (pt = (pd)->page_table[iter], true);                    \
+                    (pt = i915_pt_entry(pd, iter), true);              \
             ++iter)
 
 static inline u32 i915_pte_index(u64 address, unsigned int pde_shift)
@@ -485,143 +513,74 @@ static inline u32 gen6_pde_index(u32 addr)
        return i915_pde_index(addr, GEN6_PDE_SHIFT);
 }
 
-static inline unsigned int
-i915_pdpes_per_pdp(const struct i915_address_space *vm)
-{
-       if (i915_vm_is_48bit(vm))
-               return GEN8_PML4ES_PER_PML4;
-
-       return GEN8_3LVL_PDPES;
-}
-
-/* Equivalent to the gen6 version, For each pde iterates over every pde
- * between from start until start + length. On gen8+ it simply iterates
- * over every page directory entry in a page directory.
- */
-#define gen8_for_each_pde(pt, pd, start, length, iter)                 \
-       for (iter = gen8_pde_index(start);                              \
-            length > 0 && iter < I915_PDES &&                          \
-               (pt = (pd)->page_table[iter], true);                    \
-            ({ u64 temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT);         \
-                   temp = min(temp - start, length);                   \
-                   start += temp, length -= temp; }), ++iter)
-
-#define gen8_for_each_pdpe(pd, pdp, start, length, iter)               \
-       for (iter = gen8_pdpe_index(start);                             \
-            length > 0 && iter < i915_pdpes_per_pdp(vm) &&             \
-               (pd = (pdp)->page_directory[iter], true);               \
-            ({ u64 temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT);        \
-                   temp = min(temp - start, length);                   \
-                   start += temp, length -= temp; }), ++iter)
-
-#define gen8_for_each_pml4e(pdp, pml4, start, length, iter)            \
-       for (iter = gen8_pml4e_index(start);                            \
-            length > 0 && iter < GEN8_PML4ES_PER_PML4 &&               \
-               (pdp = (pml4)->pdps[iter], true);                       \
-            ({ u64 temp = ALIGN(start+1, 1ULL << GEN8_PML4E_SHIFT);    \
-                   temp = min(temp - start, length);                   \
-                   start += temp, length -= temp; }), ++iter)
-
-static inline u32 gen8_pte_index(u64 address)
-{
-       return i915_pte_index(address, GEN8_PDE_SHIFT);
-}
-
-static inline u32 gen8_pde_index(u64 address)
-{
-       return i915_pde_index(address, GEN8_PDE_SHIFT);
-}
-
-static inline u32 gen8_pdpe_index(u64 address)
+static inline struct i915_page_table *
+i915_pt_entry(const struct i915_page_directory * const pd,
+             const unsigned short n)
 {
-       return (address >> GEN8_PDPE_SHIFT) & GEN8_PDPE_MASK;
+       return pd->entry[n];
 }
 
-static inline u32 gen8_pml4e_index(u64 address)
+static inline struct i915_page_directory *
+i915_pd_entry(const struct i915_page_directory * const pdp,
+             const unsigned short n)
 {
-       return (address >> GEN8_PML4E_SHIFT) & GEN8_PML4E_MASK;
-}
-
-static inline u64 gen8_pte_count(u64 address, u64 length)
-{
-       return i915_pte_count(address, length, GEN8_PDE_SHIFT);
+       return pdp->entry[n];
 }
 
 static inline dma_addr_t
-i915_page_dir_dma_addr(const struct i915_hw_ppgtt *ppgtt, const unsigned n)
+i915_page_dir_dma_addr(const struct i915_ppgtt *ppgtt, const unsigned int n)
 {
-       return px_dma(ppgtt->pdp.page_directory[n]);
+       struct i915_page_dma *pt = ppgtt->pd->entry[n];
+
+       return px_dma(pt ?: px_base(&ppgtt->vm.scratch[ppgtt->vm.top]));
 }
 
 static inline struct i915_ggtt *
 i915_vm_to_ggtt(struct i915_address_space *vm)
 {
+       BUILD_BUG_ON(offsetof(struct i915_ggtt, vm));
        GEM_BUG_ON(!i915_is_ggtt(vm));
        return container_of(vm, struct i915_ggtt, vm);
 }
 
-#define INTEL_MAX_PPAT_ENTRIES 8
-#define INTEL_PPAT_PERFECT_MATCH (~0U)
-
-struct intel_ppat;
-
-struct intel_ppat_entry {
-       struct intel_ppat *ppat;
-       struct kref ref;
-       u8 value;
-};
-
-struct intel_ppat {
-       struct intel_ppat_entry entries[INTEL_MAX_PPAT_ENTRIES];
-       DECLARE_BITMAP(used, INTEL_MAX_PPAT_ENTRIES);
-       DECLARE_BITMAP(dirty, INTEL_MAX_PPAT_ENTRIES);
-       unsigned int max_entries;
-       u8 clear_value;
-       /*
-        * Return a score to show how two PPAT values match,
-        * a INTEL_PPAT_PERFECT_MATCH indicates a perfect match
-        */
-       unsigned int (*match)(u8 src, u8 dst);
-       void (*update_hw)(struct drm_i915_private *i915);
-
-       struct drm_i915_private *i915;
-};
-
-const struct intel_ppat_entry *
-intel_ppat_get(struct drm_i915_private *i915, u8 value);
-void intel_ppat_put(const struct intel_ppat_entry *entry);
-
-int i915_gem_init_aliasing_ppgtt(struct drm_i915_private *i915);
-void i915_gem_fini_aliasing_ppgtt(struct drm_i915_private *i915);
+static inline struct i915_ppgtt *
+i915_vm_to_ppgtt(struct i915_address_space *vm)
+{
+       BUILD_BUG_ON(offsetof(struct i915_ppgtt, vm));
+       GEM_BUG_ON(i915_is_ggtt(vm));
+       return container_of(vm, struct i915_ppgtt, vm);
+}
 
 int i915_ggtt_probe_hw(struct drm_i915_private *dev_priv);
 int i915_ggtt_init_hw(struct drm_i915_private *dev_priv);
 int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv);
-void i915_ggtt_enable_guc(struct drm_i915_private *i915);
-void i915_ggtt_disable_guc(struct drm_i915_private *i915);
-int i915_gem_init_ggtt(struct drm_i915_private *dev_priv);
-void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv);
-
-int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv);
-void i915_ppgtt_release(struct kref *kref);
-struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv,
-                                       struct drm_i915_file_private *fpriv);
-void i915_ppgtt_close(struct i915_address_space *vm);
-static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt)
+void i915_ggtt_enable_guc(struct i915_ggtt *ggtt);
+void i915_ggtt_disable_guc(struct i915_ggtt *ggtt);
+int i915_init_ggtt(struct drm_i915_private *dev_priv);
+void i915_ggtt_driver_release(struct drm_i915_private *dev_priv);
+
+int i915_ppgtt_init_hw(struct intel_gt *gt);
+
+struct i915_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv);
+
+static inline struct i915_address_space *
+i915_vm_get(struct i915_address_space *vm)
 {
-       if (ppgtt)
-               kref_get(&ppgtt->ref);
+       kref_get(&vm->ref);
+       return vm;
 }
-static inline void i915_ppgtt_put(struct i915_hw_ppgtt *ppgtt)
+
+void i915_vm_release(struct kref *kref);
+
+static inline void i915_vm_put(struct i915_address_space *vm)
 {
-       if (ppgtt)
-               kref_put(&ppgtt->ref, i915_ppgtt_release);
+       kref_put(&vm->ref, i915_vm_release);
 }
 
-int gen6_ppgtt_pin(struct i915_hw_ppgtt *base);
-void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base);
+int gen6_ppgtt_pin(struct i915_ppgtt *base);
+void gen6_ppgtt_unpin(struct i915_ppgtt *base);
+void gen6_ppgtt_unpin_all(struct i915_ppgtt *base);
 
-void i915_check_and_clear_faults(struct drm_i915_private *dev_priv);
 void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv);
 void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv);