xref: /dflybsd-src/sys/dev/drm/i915/i915_gem_gtt.c (revision 71f41f3eaecc1bac4c44cc81622db5b5dddc7dc4)
1e3adcf8fSFrançois Tigeot /*
2e3adcf8fSFrançois Tigeot  * Copyright © 2010 Daniel Vetter
3ba55f2f5SFrançois Tigeot  * Copyright © 2011-2014 Intel Corporation
4e3adcf8fSFrançois Tigeot  *
5e3adcf8fSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
6e3adcf8fSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
7e3adcf8fSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
8e3adcf8fSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9e3adcf8fSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
10e3adcf8fSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
11e3adcf8fSFrançois Tigeot  *
12e3adcf8fSFrançois Tigeot  * The above copyright notice and this permission notice (including the next
13e3adcf8fSFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
14e3adcf8fSFrançois Tigeot  * Software.
15e3adcf8fSFrançois Tigeot  *
16e3adcf8fSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17e3adcf8fSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18e3adcf8fSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19e3adcf8fSFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20e3adcf8fSFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21e3adcf8fSFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22e3adcf8fSFrançois Tigeot  * IN THE SOFTWARE.
23e3adcf8fSFrançois Tigeot  *
24e3adcf8fSFrançois Tigeot  */
25e3adcf8fSFrançois Tigeot 
26ba55f2f5SFrançois Tigeot #include <linux/seq_file.h>
2745a22cb3SFrançois Tigeot #include <linux/stop_machine.h>
2818e26a6dSFrançois Tigeot #include <drm/drmP.h>
295c6c6f23SFrançois Tigeot #include <drm/i915_drm.h>
30e3adcf8fSFrançois Tigeot #include "i915_drv.h"
31477eb7f9SFrançois Tigeot #include "i915_vgpu.h"
32477eb7f9SFrançois Tigeot #include "i915_trace.h"
33e3adcf8fSFrançois Tigeot #include "intel_drv.h"
34e3adcf8fSFrançois Tigeot 
352c9916cdSFrançois Tigeot /**
362c9916cdSFrançois Tigeot  * DOC: Global GTT views
372c9916cdSFrançois Tigeot  *
382c9916cdSFrançois Tigeot  * Background and previous state
392c9916cdSFrançois Tigeot  *
402c9916cdSFrançois Tigeot  * Historically objects could exists (be bound) in global GTT space only as
412c9916cdSFrançois Tigeot  * singular instances with a view representing all of the object's backing pages
422c9916cdSFrançois Tigeot  * in a linear fashion. This view will be called a normal view.
432c9916cdSFrançois Tigeot  *
442c9916cdSFrançois Tigeot  * To support multiple views of the same object, where the number of mapped
452c9916cdSFrançois Tigeot  * pages is not equal to the backing store, or where the layout of the pages
462c9916cdSFrançois Tigeot  * is not linear, concept of a GGTT view was added.
472c9916cdSFrançois Tigeot  *
482c9916cdSFrançois Tigeot  * One example of an alternative view is a stereo display driven by a single
492c9916cdSFrançois Tigeot  * image. In this case we would have a framebuffer looking like this
502c9916cdSFrançois Tigeot  * (2x2 pages):
512c9916cdSFrançois Tigeot  *
522c9916cdSFrançois Tigeot  *    12
532c9916cdSFrançois Tigeot  *    34
542c9916cdSFrançois Tigeot  *
552c9916cdSFrançois Tigeot  * Above would represent a normal GGTT view as normally mapped for GPU or CPU
562c9916cdSFrançois Tigeot  * rendering. In contrast, fed to the display engine would be an alternative
572c9916cdSFrançois Tigeot  * view which could look something like this:
582c9916cdSFrançois Tigeot  *
592c9916cdSFrançois Tigeot  *   1212
602c9916cdSFrançois Tigeot  *   3434
612c9916cdSFrançois Tigeot  *
622c9916cdSFrançois Tigeot  * In this example both the size and layout of pages in the alternative view is
632c9916cdSFrançois Tigeot  * different from the normal view.
642c9916cdSFrançois Tigeot  *
652c9916cdSFrançois Tigeot  * Implementation and usage
662c9916cdSFrançois Tigeot  *
672c9916cdSFrançois Tigeot  * GGTT views are implemented using VMAs and are distinguished via enum
682c9916cdSFrançois Tigeot  * i915_ggtt_view_type and struct i915_ggtt_view.
692c9916cdSFrançois Tigeot  *
702c9916cdSFrançois Tigeot  * A new flavour of core GEM functions which work with GGTT bound objects were
71477eb7f9SFrançois Tigeot  * added with the _ggtt_ infix, and sometimes with _view postfix to avoid
72477eb7f9SFrançois Tigeot  * renaming  in large amounts of code. They take the struct i915_ggtt_view
73477eb7f9SFrançois Tigeot  * parameter encapsulating all metadata required to implement a view.
742c9916cdSFrançois Tigeot  *
752c9916cdSFrançois Tigeot  * As a helper for callers which are only interested in the normal view,
762c9916cdSFrançois Tigeot  * globally const i915_ggtt_view_normal singleton instance exists. All old core
772c9916cdSFrançois Tigeot  * GEM API functions, the ones not taking the view parameter, are operating on,
782c9916cdSFrançois Tigeot  * or with the normal GGTT view.
792c9916cdSFrançois Tigeot  *
802c9916cdSFrançois Tigeot  * Code wanting to add or use a new GGTT view needs to:
812c9916cdSFrançois Tigeot  *
822c9916cdSFrançois Tigeot  * 1. Add a new enum with a suitable name.
832c9916cdSFrançois Tigeot  * 2. Extend the metadata in the i915_ggtt_view structure if required.
842c9916cdSFrançois Tigeot  * 3. Add support to i915_get_vma_pages().
852c9916cdSFrançois Tigeot  *
862c9916cdSFrançois Tigeot  * New views are required to build a scatter-gather table from within the
872c9916cdSFrançois Tigeot  * i915_get_vma_pages function. This table is stored in the vma.ggtt_view and
882c9916cdSFrançois Tigeot  * exists for the lifetime of an VMA.
892c9916cdSFrançois Tigeot  *
902c9916cdSFrançois Tigeot  * Core API is designed to have copy semantics which means that passed in
912c9916cdSFrançois Tigeot  * struct i915_ggtt_view does not need to be persistent (left around after
922c9916cdSFrançois Tigeot  * calling the core API functions).
932c9916cdSFrançois Tigeot  *
942c9916cdSFrançois Tigeot  */
952c9916cdSFrançois Tigeot 
961487f786SFrançois Tigeot static inline struct i915_ggtt *
971487f786SFrançois Tigeot i915_vm_to_ggtt(struct i915_address_space *vm)
981487f786SFrançois Tigeot {
991487f786SFrançois Tigeot 	GEM_BUG_ON(!i915_is_ggtt(vm));
1001487f786SFrançois Tigeot 	return container_of(vm, struct i915_ggtt, base);
1011487f786SFrançois Tigeot }
1021487f786SFrançois Tigeot 
10319c468b4SFrançois Tigeot static int
10419c468b4SFrançois Tigeot i915_get_ggtt_vma_pages(struct i915_vma *vma);
10519c468b4SFrançois Tigeot 
106c0e85e96SFrançois Tigeot const struct i915_ggtt_view i915_ggtt_view_normal = {
107c0e85e96SFrançois Tigeot 	.type = I915_GGTT_VIEW_NORMAL,
108c0e85e96SFrançois Tigeot };
109477eb7f9SFrançois Tigeot const struct i915_ggtt_view i915_ggtt_view_rotated = {
110c0e85e96SFrançois Tigeot 	.type = I915_GGTT_VIEW_ROTATED,
111477eb7f9SFrançois Tigeot };
1122c9916cdSFrançois Tigeot 
1131487f786SFrançois Tigeot int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
1141487f786SFrançois Tigeot 			       	int enable_ppgtt)
11524edb884SFrançois Tigeot {
1162c9916cdSFrançois Tigeot 	bool has_aliasing_ppgtt;
1172c9916cdSFrançois Tigeot 	bool has_full_ppgtt;
118aee94f86SFrançois Tigeot 	bool has_full_48bit_ppgtt;
1192c9916cdSFrançois Tigeot 
1201487f786SFrançois Tigeot 	has_aliasing_ppgtt = INTEL_GEN(dev_priv) >= 6;
1211487f786SFrançois Tigeot 	has_full_ppgtt = INTEL_GEN(dev_priv) >= 7;
1221487f786SFrançois Tigeot 	has_full_48bit_ppgtt =
1231487f786SFrançois Tigeot 	       	IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9;
1242c9916cdSFrançois Tigeot 
125*71f41f3eSFrançois Tigeot 	if (intel_vgpu_active(dev_priv))
126*71f41f3eSFrançois Tigeot 		has_full_ppgtt = false; /* emulation is too hard */
127477eb7f9SFrançois Tigeot 
1281487f786SFrançois Tigeot 	if (!has_aliasing_ppgtt)
1291487f786SFrançois Tigeot 		return 0;
1301487f786SFrançois Tigeot 
1312c9916cdSFrançois Tigeot 	/*
1322c9916cdSFrançois Tigeot 	 * We don't allow disabling PPGTT for gen9+ as it's a requirement for
1332c9916cdSFrançois Tigeot 	 * execlists, the sole mechanism available to submit work.
1342c9916cdSFrançois Tigeot 	 */
1351487f786SFrançois Tigeot 	if (enable_ppgtt == 0 && INTEL_GEN(dev_priv) < 9)
13624edb884SFrançois Tigeot 		return 0;
13724edb884SFrançois Tigeot 
13824edb884SFrançois Tigeot 	if (enable_ppgtt == 1)
13924edb884SFrançois Tigeot 		return 1;
14024edb884SFrançois Tigeot 
1412c9916cdSFrançois Tigeot 	if (enable_ppgtt == 2 && has_full_ppgtt)
14224edb884SFrançois Tigeot 		return 2;
14324edb884SFrançois Tigeot 
144aee94f86SFrançois Tigeot 	if (enable_ppgtt == 3 && has_full_48bit_ppgtt)
145aee94f86SFrançois Tigeot 		return 3;
146aee94f86SFrançois Tigeot 
147ba55f2f5SFrançois Tigeot #ifdef CONFIG_INTEL_IOMMU
148ba55f2f5SFrançois Tigeot 	/* Disable ppgtt on SNB if VT-d is on. */
1491487f786SFrançois Tigeot 	if (IS_GEN6(dev_priv) && intel_iommu_gfx_mapped) {
150ba55f2f5SFrançois Tigeot 		DRM_INFO("Disabling PPGTT because VT-d is on\n");
15124edb884SFrançois Tigeot 		return 0;
152ba55f2f5SFrançois Tigeot 	}
153ba55f2f5SFrançois Tigeot #endif
154f4e1c372SFrançois Tigeot 
15524edb884SFrançois Tigeot 	/* Early VLV doesn't have this */
156303bf270SFrançois Tigeot 	if (IS_VALLEYVIEW(dev_priv) && dev_priv->drm.pdev->revision < 0xb) {
15724edb884SFrançois Tigeot 		DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n");
15824edb884SFrançois Tigeot 		return 0;
15924edb884SFrançois Tigeot 	}
16024edb884SFrançois Tigeot 
161*71f41f3eSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8 && i915.enable_execlists)
162aee94f86SFrançois Tigeot 		return has_full_48bit_ppgtt ? 3 : 2;
1632c9916cdSFrançois Tigeot 	else
1642c9916cdSFrançois Tigeot 		return has_aliasing_ppgtt ? 1 : 0;
165ba55f2f5SFrançois Tigeot }
1669edbd4a0SFrançois Tigeot 
16719c468b4SFrançois Tigeot static int ppgtt_bind_vma(struct i915_vma *vma,
168ba55f2f5SFrançois Tigeot 			  enum i915_cache_level cache_level,
16919c468b4SFrançois Tigeot 			  u32 unused)
17019c468b4SFrançois Tigeot {
17119c468b4SFrançois Tigeot 	u32 pte_flags = 0;
1729edbd4a0SFrançois Tigeot 
17319c468b4SFrançois Tigeot 	/* Currently applicable only to VLV */
17419c468b4SFrançois Tigeot 	if (vma->obj->gt_ro)
17519c468b4SFrançois Tigeot 		pte_flags |= PTE_READ_ONLY;
17619c468b4SFrançois Tigeot 
17719c468b4SFrançois Tigeot 	vma->vm->insert_entries(vma->vm, vma->obj->pages, vma->node.start,
17819c468b4SFrançois Tigeot 				cache_level, pte_flags);
17919c468b4SFrançois Tigeot 
18019c468b4SFrançois Tigeot 	return 0;
18119c468b4SFrançois Tigeot }
18219c468b4SFrançois Tigeot 
18319c468b4SFrançois Tigeot static void ppgtt_unbind_vma(struct i915_vma *vma)
18419c468b4SFrançois Tigeot {
18519c468b4SFrançois Tigeot 	vma->vm->clear_range(vma->vm,
18619c468b4SFrançois Tigeot 			     vma->node.start,
187*71f41f3eSFrançois Tigeot 			     vma->size,
18819c468b4SFrançois Tigeot 			     true);
18919c468b4SFrançois Tigeot }
19019c468b4SFrançois Tigeot 
19119c468b4SFrançois Tigeot static gen8_pte_t gen8_pte_encode(dma_addr_t addr,
1929edbd4a0SFrançois Tigeot 				  enum i915_cache_level level,
1939edbd4a0SFrançois Tigeot 				  bool valid)
1949edbd4a0SFrançois Tigeot {
195477eb7f9SFrançois Tigeot 	gen8_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0;
1969edbd4a0SFrançois Tigeot 	pte |= addr;
197ba55f2f5SFrançois Tigeot 
198ba55f2f5SFrançois Tigeot 	switch (level) {
199ba55f2f5SFrançois Tigeot 	case I915_CACHE_NONE:
2009edbd4a0SFrançois Tigeot 		pte |= PPAT_UNCACHED_INDEX;
201ba55f2f5SFrançois Tigeot 		break;
202ba55f2f5SFrançois Tigeot 	case I915_CACHE_WT:
203ba55f2f5SFrançois Tigeot 		pte |= PPAT_DISPLAY_ELLC_INDEX;
204ba55f2f5SFrançois Tigeot 		break;
205ba55f2f5SFrançois Tigeot 	default:
206ba55f2f5SFrançois Tigeot 		pte |= PPAT_CACHED_INDEX;
207ba55f2f5SFrançois Tigeot 		break;
208ba55f2f5SFrançois Tigeot 	}
209ba55f2f5SFrançois Tigeot 
2109edbd4a0SFrançois Tigeot 	return pte;
2119edbd4a0SFrançois Tigeot }
2129edbd4a0SFrançois Tigeot 
213a05eeebfSFrançois Tigeot static gen8_pde_t gen8_pde_encode(const dma_addr_t addr,
214a05eeebfSFrançois Tigeot 				  const enum i915_cache_level level)
215e3adcf8fSFrançois Tigeot {
216477eb7f9SFrançois Tigeot 	gen8_pde_t pde = _PAGE_PRESENT | _PAGE_RW;
2179edbd4a0SFrançois Tigeot 	pde |= addr;
2189edbd4a0SFrançois Tigeot 	if (level != I915_CACHE_NONE)
2199edbd4a0SFrançois Tigeot 		pde |= PPAT_CACHED_PDE_INDEX;
2209edbd4a0SFrançois Tigeot 	else
2219edbd4a0SFrançois Tigeot 		pde |= PPAT_UNCACHED_INDEX;
2229edbd4a0SFrançois Tigeot 	return pde;
2239edbd4a0SFrançois Tigeot }
2249edbd4a0SFrançois Tigeot 
225352ff8bdSFrançois Tigeot #define gen8_pdpe_encode gen8_pde_encode
226352ff8bdSFrançois Tigeot #define gen8_pml4e_encode gen8_pde_encode
227352ff8bdSFrançois Tigeot 
228477eb7f9SFrançois Tigeot static gen6_pte_t snb_pte_encode(dma_addr_t addr,
2299edbd4a0SFrançois Tigeot 				 enum i915_cache_level level,
23024edb884SFrançois Tigeot 				 bool valid, u32 unused)
2319edbd4a0SFrançois Tigeot {
232477eb7f9SFrançois Tigeot 	gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
233f4e1c372SFrançois Tigeot 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
234f4e1c372SFrançois Tigeot 
235f4e1c372SFrançois Tigeot 	switch (level) {
2369edbd4a0SFrançois Tigeot 	case I915_CACHE_L3_LLC:
2379edbd4a0SFrançois Tigeot 	case I915_CACHE_LLC:
2389edbd4a0SFrançois Tigeot 		pte |= GEN6_PTE_CACHE_LLC;
2399edbd4a0SFrançois Tigeot 		break;
2409edbd4a0SFrançois Tigeot 	case I915_CACHE_NONE:
2419edbd4a0SFrançois Tigeot 		pte |= GEN6_PTE_UNCACHED;
2429edbd4a0SFrançois Tigeot 		break;
2439edbd4a0SFrançois Tigeot 	default:
2442c9916cdSFrançois Tigeot 		MISSING_CASE(level);
2459edbd4a0SFrançois Tigeot 	}
2469edbd4a0SFrançois Tigeot 
2479edbd4a0SFrançois Tigeot 	return pte;
2489edbd4a0SFrançois Tigeot }
2499edbd4a0SFrançois Tigeot 
250477eb7f9SFrançois Tigeot static gen6_pte_t ivb_pte_encode(dma_addr_t addr,
2519edbd4a0SFrançois Tigeot 				 enum i915_cache_level level,
25224edb884SFrançois Tigeot 				 bool valid, u32 unused)
2539edbd4a0SFrançois Tigeot {
254477eb7f9SFrançois Tigeot 	gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
2559edbd4a0SFrançois Tigeot 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
2569edbd4a0SFrançois Tigeot 
2579edbd4a0SFrançois Tigeot 	switch (level) {
2589edbd4a0SFrançois Tigeot 	case I915_CACHE_L3_LLC:
2599edbd4a0SFrançois Tigeot 		pte |= GEN7_PTE_CACHE_L3_LLC;
260f4e1c372SFrançois Tigeot 		break;
261f4e1c372SFrançois Tigeot 	case I915_CACHE_LLC:
262f4e1c372SFrançois Tigeot 		pte |= GEN6_PTE_CACHE_LLC;
263f4e1c372SFrançois Tigeot 		break;
264f4e1c372SFrançois Tigeot 	case I915_CACHE_NONE:
265f4e1c372SFrançois Tigeot 		pte |= GEN6_PTE_UNCACHED;
266f4e1c372SFrançois Tigeot 		break;
267f4e1c372SFrançois Tigeot 	default:
2682c9916cdSFrançois Tigeot 		MISSING_CASE(level);
269f4e1c372SFrançois Tigeot 	}
270f4e1c372SFrançois Tigeot 
271f4e1c372SFrançois Tigeot 	return pte;
272f4e1c372SFrançois Tigeot }
273f4e1c372SFrançois Tigeot 
274477eb7f9SFrançois Tigeot static gen6_pte_t byt_pte_encode(dma_addr_t addr,
2759edbd4a0SFrançois Tigeot 				 enum i915_cache_level level,
27624edb884SFrançois Tigeot 				 bool valid, u32 flags)
2775d0b1887SFrançois Tigeot {
278477eb7f9SFrançois Tigeot 	gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
2795d0b1887SFrançois Tigeot 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
2805d0b1887SFrançois Tigeot 
28124edb884SFrançois Tigeot 	if (!(flags & PTE_READ_ONLY))
2825d0b1887SFrançois Tigeot 		pte |= BYT_PTE_WRITEABLE;
2835d0b1887SFrançois Tigeot 
2845d0b1887SFrançois Tigeot 	if (level != I915_CACHE_NONE)
2855d0b1887SFrançois Tigeot 		pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES;
2865d0b1887SFrançois Tigeot 
2875d0b1887SFrançois Tigeot 	return pte;
2885d0b1887SFrançois Tigeot }
2895d0b1887SFrançois Tigeot 
290477eb7f9SFrançois Tigeot static gen6_pte_t hsw_pte_encode(dma_addr_t addr,
2919edbd4a0SFrançois Tigeot 				 enum i915_cache_level level,
29224edb884SFrançois Tigeot 				 bool valid, u32 unused)
2935d0b1887SFrançois Tigeot {
294477eb7f9SFrançois Tigeot 	gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
2959edbd4a0SFrançois Tigeot 	pte |= HSW_PTE_ADDR_ENCODE(addr);
2965d0b1887SFrançois Tigeot 
2975d0b1887SFrançois Tigeot 	if (level != I915_CACHE_NONE)
2989edbd4a0SFrançois Tigeot 		pte |= HSW_WB_LLC_AGE3;
2995d0b1887SFrançois Tigeot 
3005d0b1887SFrançois Tigeot 	return pte;
3015d0b1887SFrançois Tigeot }
3025d0b1887SFrançois Tigeot 
303477eb7f9SFrançois Tigeot static gen6_pte_t iris_pte_encode(dma_addr_t addr,
3049edbd4a0SFrançois Tigeot 				  enum i915_cache_level level,
30524edb884SFrançois Tigeot 				  bool valid, u32 unused)
3069edbd4a0SFrançois Tigeot {
307477eb7f9SFrançois Tigeot 	gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
3089edbd4a0SFrançois Tigeot 	pte |= HSW_PTE_ADDR_ENCODE(addr);
3099edbd4a0SFrançois Tigeot 
3109edbd4a0SFrançois Tigeot 	switch (level) {
3119edbd4a0SFrançois Tigeot 	case I915_CACHE_NONE:
3129edbd4a0SFrançois Tigeot 		break;
3139edbd4a0SFrançois Tigeot 	case I915_CACHE_WT:
3149edbd4a0SFrançois Tigeot 		pte |= HSW_WT_ELLC_LLC_AGE3;
3159edbd4a0SFrançois Tigeot 		break;
3169edbd4a0SFrançois Tigeot 	default:
3179edbd4a0SFrançois Tigeot 		pte |= HSW_WB_ELLC_LLC_AGE3;
3189edbd4a0SFrançois Tigeot 		break;
3199edbd4a0SFrançois Tigeot 	}
3209edbd4a0SFrançois Tigeot 
3219edbd4a0SFrançois Tigeot 	return pte;
3229edbd4a0SFrançois Tigeot }
3239edbd4a0SFrançois Tigeot 
324a05eeebfSFrançois Tigeot static int __setup_page_dma(struct drm_device *dev,
325a05eeebfSFrançois Tigeot 			    struct i915_page_dma *p, gfp_t flags)
326477eb7f9SFrançois Tigeot {
327aee94f86SFrançois Tigeot 	struct device *device = &dev->pdev->dev;
328477eb7f9SFrançois Tigeot 
329a05eeebfSFrançois Tigeot 	p->page = alloc_page(flags);
330a05eeebfSFrançois Tigeot 	if (!p->page)
331477eb7f9SFrançois Tigeot 		return -ENOMEM;
332477eb7f9SFrançois Tigeot 
333a05eeebfSFrançois Tigeot 	p->daddr = dma_map_page(device,
334a05eeebfSFrançois Tigeot 				p->page, 0, 4096, PCI_DMA_BIDIRECTIONAL);
335a05eeebfSFrançois Tigeot 
336a05eeebfSFrançois Tigeot 	if (dma_mapping_error(device, p->daddr)) {
337a05eeebfSFrançois Tigeot 		__free_page(p->page);
338a05eeebfSFrançois Tigeot 		return -EINVAL;
339a05eeebfSFrançois Tigeot 	}
340a05eeebfSFrançois Tigeot 
341477eb7f9SFrançois Tigeot 	return 0;
342477eb7f9SFrançois Tigeot }
343477eb7f9SFrançois Tigeot 
344a05eeebfSFrançois Tigeot static int setup_page_dma(struct drm_device *dev, struct i915_page_dma *p)
345477eb7f9SFrançois Tigeot {
346a05eeebfSFrançois Tigeot 	return __setup_page_dma(dev, p, GFP_KERNEL);
347a05eeebfSFrançois Tigeot }
348a05eeebfSFrançois Tigeot 
349a05eeebfSFrançois Tigeot static void cleanup_page_dma(struct drm_device *dev, struct i915_page_dma *p)
350a05eeebfSFrançois Tigeot {
351a05eeebfSFrançois Tigeot 	if (WARN_ON(!p->page))
352477eb7f9SFrançois Tigeot 		return;
353477eb7f9SFrançois Tigeot 
354fb572d17SFrançois Tigeot 	dma_unmap_page(&dev->pdev->dev, p->daddr, 4096, PCI_DMA_BIDIRECTIONAL);
355a05eeebfSFrançois Tigeot 	__free_page(p->page);
356a05eeebfSFrançois Tigeot 	memset(p, 0, sizeof(*p));
357477eb7f9SFrançois Tigeot }
358477eb7f9SFrançois Tigeot 
359a05eeebfSFrançois Tigeot static void *kmap_page_dma(struct i915_page_dma *p)
360477eb7f9SFrançois Tigeot {
361a05eeebfSFrançois Tigeot 	return kmap_atomic(p->page);
36219c468b4SFrançois Tigeot }
36319c468b4SFrançois Tigeot 
364a05eeebfSFrançois Tigeot /* We use the flushing unmap only with ppgtt structures:
365a05eeebfSFrançois Tigeot  * page directories, page tables and scratch pages.
366a05eeebfSFrançois Tigeot  */
367a05eeebfSFrançois Tigeot static void kunmap_page_dma(struct drm_device *dev, void *vaddr)
368a05eeebfSFrançois Tigeot {
369a05eeebfSFrançois Tigeot 	/* There are only few exceptions for gen >=6. chv and bxt.
370a05eeebfSFrançois Tigeot 	 * And we are not sure about the latter so play safe for now.
371a05eeebfSFrançois Tigeot 	 */
372a05eeebfSFrançois Tigeot 	if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev))
373a05eeebfSFrançois Tigeot 		drm_clflush_virt_range(vaddr, PAGE_SIZE);
374a05eeebfSFrançois Tigeot 
375a05eeebfSFrançois Tigeot 	kunmap_atomic(vaddr);
376a05eeebfSFrançois Tigeot }
377a05eeebfSFrançois Tigeot 
378a05eeebfSFrançois Tigeot #define kmap_px(px) kmap_page_dma(px_base(px))
379a05eeebfSFrançois Tigeot #define kunmap_px(ppgtt, vaddr) kunmap_page_dma((ppgtt)->base.dev, (vaddr))
380a05eeebfSFrançois Tigeot 
381a05eeebfSFrançois Tigeot #define setup_px(dev, px) setup_page_dma((dev), px_base(px))
382a05eeebfSFrançois Tigeot #define cleanup_px(dev, px) cleanup_page_dma((dev), px_base(px))
383a05eeebfSFrançois Tigeot #define fill_px(dev, px, v) fill_page_dma((dev), px_base(px), (v))
384a05eeebfSFrançois Tigeot #define fill32_px(dev, px, v) fill_page_dma_32((dev), px_base(px), (v))
385a05eeebfSFrançois Tigeot 
386a05eeebfSFrançois Tigeot static void fill_page_dma(struct drm_device *dev, struct i915_page_dma *p,
387a05eeebfSFrançois Tigeot 			  const uint64_t val)
388a05eeebfSFrançois Tigeot {
389a05eeebfSFrançois Tigeot 	int i;
390a05eeebfSFrançois Tigeot 	uint64_t * const vaddr = kmap_page_dma(p);
391a05eeebfSFrançois Tigeot 
392a05eeebfSFrançois Tigeot 	for (i = 0; i < 512; i++)
393a05eeebfSFrançois Tigeot 		vaddr[i] = val;
394a05eeebfSFrançois Tigeot 
395a05eeebfSFrançois Tigeot 	kunmap_page_dma(dev, vaddr);
396a05eeebfSFrançois Tigeot }
397a05eeebfSFrançois Tigeot 
398a05eeebfSFrançois Tigeot static void fill_page_dma_32(struct drm_device *dev, struct i915_page_dma *p,
399a05eeebfSFrançois Tigeot 			     const uint32_t val32)
400a05eeebfSFrançois Tigeot {
401a05eeebfSFrançois Tigeot 	uint64_t v = val32;
402a05eeebfSFrançois Tigeot 
403a05eeebfSFrançois Tigeot 	v = v << 32 | val32;
404a05eeebfSFrançois Tigeot 
405a05eeebfSFrançois Tigeot 	fill_page_dma(dev, p, v);
406a05eeebfSFrançois Tigeot }
407a05eeebfSFrançois Tigeot 
408a05eeebfSFrançois Tigeot static struct i915_page_scratch *alloc_scratch_page(struct drm_device *dev)
409a05eeebfSFrançois Tigeot {
410a05eeebfSFrançois Tigeot 	struct i915_page_scratch *sp;
411a05eeebfSFrançois Tigeot 	int ret;
412a05eeebfSFrançois Tigeot 
413a05eeebfSFrançois Tigeot 	sp = kzalloc(sizeof(*sp), GFP_KERNEL);
414a05eeebfSFrançois Tigeot 	if (sp == NULL)
415a05eeebfSFrançois Tigeot 		return ERR_PTR(-ENOMEM);
416a05eeebfSFrançois Tigeot 
417a05eeebfSFrançois Tigeot 	ret = __setup_page_dma(dev, px_base(sp), GFP_DMA32 | __GFP_ZERO);
418a05eeebfSFrançois Tigeot 	if (ret) {
419a05eeebfSFrançois Tigeot 		kfree(sp);
420a05eeebfSFrançois Tigeot 		return ERR_PTR(ret);
421a05eeebfSFrançois Tigeot 	}
422a05eeebfSFrançois Tigeot 
423a05eeebfSFrançois Tigeot 	set_pages_uc(px_page(sp), 1);
424a05eeebfSFrançois Tigeot 
425a05eeebfSFrançois Tigeot 	return sp;
426a05eeebfSFrançois Tigeot }
427a05eeebfSFrançois Tigeot 
428a05eeebfSFrançois Tigeot static void free_scratch_page(struct drm_device *dev,
429a05eeebfSFrançois Tigeot 			      struct i915_page_scratch *sp)
430a05eeebfSFrançois Tigeot {
431a05eeebfSFrançois Tigeot 	set_pages_wb(px_page(sp), 1);
432a05eeebfSFrançois Tigeot 
433a05eeebfSFrançois Tigeot 	cleanup_px(dev, sp);
434a05eeebfSFrançois Tigeot 	kfree(sp);
435a05eeebfSFrançois Tigeot }
436a05eeebfSFrançois Tigeot 
437a05eeebfSFrançois Tigeot static struct i915_page_table *alloc_pt(struct drm_device *dev)
43819c468b4SFrançois Tigeot {
43919c468b4SFrançois Tigeot 	struct i915_page_table *pt;
440477eb7f9SFrançois Tigeot 	const size_t count = INTEL_INFO(dev)->gen >= 8 ?
441477eb7f9SFrançois Tigeot 		GEN8_PTES : GEN6_PTES;
442477eb7f9SFrançois Tigeot 	int ret = -ENOMEM;
443477eb7f9SFrançois Tigeot 
444477eb7f9SFrançois Tigeot 	pt = kzalloc(sizeof(*pt), GFP_KERNEL);
445477eb7f9SFrançois Tigeot 	if (!pt)
446477eb7f9SFrançois Tigeot 		return ERR_PTR(-ENOMEM);
447477eb7f9SFrançois Tigeot 
448477eb7f9SFrançois Tigeot 	pt->used_ptes = kcalloc(BITS_TO_LONGS(count), sizeof(*pt->used_ptes),
449477eb7f9SFrançois Tigeot 				GFP_KERNEL);
450477eb7f9SFrançois Tigeot 
451477eb7f9SFrançois Tigeot 	if (!pt->used_ptes)
452477eb7f9SFrançois Tigeot 		goto fail_bitmap;
453477eb7f9SFrançois Tigeot 
454a05eeebfSFrançois Tigeot 	ret = setup_px(dev, pt);
455477eb7f9SFrançois Tigeot 	if (ret)
456a05eeebfSFrançois Tigeot 		goto fail_page_m;
457477eb7f9SFrançois Tigeot 
458477eb7f9SFrançois Tigeot 	return pt;
459477eb7f9SFrançois Tigeot 
460a05eeebfSFrançois Tigeot fail_page_m:
461477eb7f9SFrançois Tigeot 	kfree(pt->used_ptes);
462477eb7f9SFrançois Tigeot fail_bitmap:
463477eb7f9SFrançois Tigeot 	kfree(pt);
464477eb7f9SFrançois Tigeot 
465477eb7f9SFrançois Tigeot 	return ERR_PTR(ret);
466477eb7f9SFrançois Tigeot }
467477eb7f9SFrançois Tigeot 
468a05eeebfSFrançois Tigeot static void free_pt(struct drm_device *dev, struct i915_page_table *pt)
469a05eeebfSFrançois Tigeot {
470a05eeebfSFrançois Tigeot 	cleanup_px(dev, pt);
471a05eeebfSFrançois Tigeot 	kfree(pt->used_ptes);
472a05eeebfSFrançois Tigeot 	kfree(pt);
473a05eeebfSFrançois Tigeot }
474a05eeebfSFrançois Tigeot 
475a05eeebfSFrançois Tigeot static void gen8_initialize_pt(struct i915_address_space *vm,
476a05eeebfSFrançois Tigeot 			       struct i915_page_table *pt)
477477eb7f9SFrançois Tigeot {
478a05eeebfSFrançois Tigeot 	gen8_pte_t scratch_pte;
479a05eeebfSFrançois Tigeot 
480a05eeebfSFrançois Tigeot 	scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
481a05eeebfSFrançois Tigeot 				      I915_CACHE_LLC, true);
482a05eeebfSFrançois Tigeot 
483a05eeebfSFrançois Tigeot 	fill_px(vm->dev, pt, scratch_pte);
484477eb7f9SFrançois Tigeot }
485477eb7f9SFrançois Tigeot 
486a05eeebfSFrançois Tigeot static void gen6_initialize_pt(struct i915_address_space *vm,
487a05eeebfSFrançois Tigeot 			       struct i915_page_table *pt)
488a05eeebfSFrançois Tigeot {
489a05eeebfSFrançois Tigeot 	gen6_pte_t scratch_pte;
490a05eeebfSFrançois Tigeot 
491a05eeebfSFrançois Tigeot 	WARN_ON(px_dma(vm->scratch_page) == 0);
492a05eeebfSFrançois Tigeot 
493a05eeebfSFrançois Tigeot 	scratch_pte = vm->pte_encode(px_dma(vm->scratch_page),
494a05eeebfSFrançois Tigeot 				     I915_CACHE_LLC, true, 0);
495a05eeebfSFrançois Tigeot 
496a05eeebfSFrançois Tigeot 	fill32_px(vm->dev, pt, scratch_pte);
497a05eeebfSFrançois Tigeot }
498a05eeebfSFrançois Tigeot 
499a05eeebfSFrançois Tigeot static struct i915_page_directory *alloc_pd(struct drm_device *dev)
500477eb7f9SFrançois Tigeot {
50119c468b4SFrançois Tigeot 	struct i915_page_directory *pd;
50219c468b4SFrançois Tigeot 	int ret = -ENOMEM;
503477eb7f9SFrançois Tigeot 
504477eb7f9SFrançois Tigeot 	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
505477eb7f9SFrançois Tigeot 	if (!pd)
506477eb7f9SFrançois Tigeot 		return ERR_PTR(-ENOMEM);
507477eb7f9SFrançois Tigeot 
50819c468b4SFrançois Tigeot 	pd->used_pdes = kcalloc(BITS_TO_LONGS(I915_PDES),
50919c468b4SFrançois Tigeot 				sizeof(*pd->used_pdes), GFP_KERNEL);
51019c468b4SFrançois Tigeot 	if (!pd->used_pdes)
511a05eeebfSFrançois Tigeot 		goto fail_bitmap;
51219c468b4SFrançois Tigeot 
513a05eeebfSFrançois Tigeot 	ret = setup_px(dev, pd);
51419c468b4SFrançois Tigeot 	if (ret)
515a05eeebfSFrançois Tigeot 		goto fail_page_m;
516477eb7f9SFrançois Tigeot 
517477eb7f9SFrançois Tigeot 	return pd;
51819c468b4SFrançois Tigeot 
519a05eeebfSFrançois Tigeot fail_page_m:
52019c468b4SFrançois Tigeot 	kfree(pd->used_pdes);
521a05eeebfSFrançois Tigeot fail_bitmap:
52219c468b4SFrançois Tigeot 	kfree(pd);
52319c468b4SFrançois Tigeot 
52419c468b4SFrançois Tigeot 	return ERR_PTR(ret);
525477eb7f9SFrançois Tigeot }
526477eb7f9SFrançois Tigeot 
527a05eeebfSFrançois Tigeot static void free_pd(struct drm_device *dev, struct i915_page_directory *pd)
528a05eeebfSFrançois Tigeot {
529a05eeebfSFrançois Tigeot 	if (px_page(pd)) {
530a05eeebfSFrançois Tigeot 		cleanup_px(dev, pd);
531a05eeebfSFrançois Tigeot 		kfree(pd->used_pdes);
532a05eeebfSFrançois Tigeot 		kfree(pd);
533a05eeebfSFrançois Tigeot 	}
534a05eeebfSFrançois Tigeot }
535a05eeebfSFrançois Tigeot 
536a05eeebfSFrançois Tigeot static void gen8_initialize_pd(struct i915_address_space *vm,
537a05eeebfSFrançois Tigeot 			       struct i915_page_directory *pd)
538a05eeebfSFrançois Tigeot {
539a05eeebfSFrançois Tigeot 	gen8_pde_t scratch_pde;
540a05eeebfSFrançois Tigeot 
541a05eeebfSFrançois Tigeot 	scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC);
542a05eeebfSFrançois Tigeot 
543a05eeebfSFrançois Tigeot 	fill_px(vm->dev, pd, scratch_pde);
544a05eeebfSFrançois Tigeot }
545a05eeebfSFrançois Tigeot 
546352ff8bdSFrançois Tigeot static int __pdp_init(struct drm_device *dev,
547352ff8bdSFrançois Tigeot 		      struct i915_page_directory_pointer *pdp)
548352ff8bdSFrançois Tigeot {
549352ff8bdSFrançois Tigeot 	size_t pdpes = I915_PDPES_PER_PDP(dev);
550352ff8bdSFrançois Tigeot 
551352ff8bdSFrançois Tigeot 	pdp->used_pdpes = kcalloc(BITS_TO_LONGS(pdpes),
552352ff8bdSFrançois Tigeot 				  sizeof(unsigned long),
553352ff8bdSFrançois Tigeot 				  GFP_KERNEL);
554352ff8bdSFrançois Tigeot 	if (!pdp->used_pdpes)
555352ff8bdSFrançois Tigeot 		return -ENOMEM;
556352ff8bdSFrançois Tigeot 
557352ff8bdSFrançois Tigeot 	pdp->page_directory = kcalloc(pdpes, sizeof(*pdp->page_directory),
558352ff8bdSFrançois Tigeot 				      GFP_KERNEL);
559352ff8bdSFrançois Tigeot 	if (!pdp->page_directory) {
560352ff8bdSFrançois Tigeot 		kfree(pdp->used_pdpes);
561352ff8bdSFrançois Tigeot 		/* the PDP might be the statically allocated top level. Keep it
562352ff8bdSFrançois Tigeot 		 * as clean as possible */
563352ff8bdSFrançois Tigeot 		pdp->used_pdpes = NULL;
564352ff8bdSFrançois Tigeot 		return -ENOMEM;
565352ff8bdSFrançois Tigeot 	}
566352ff8bdSFrançois Tigeot 
567352ff8bdSFrançois Tigeot 	return 0;
568352ff8bdSFrançois Tigeot }
569352ff8bdSFrançois Tigeot 
570352ff8bdSFrançois Tigeot static void __pdp_fini(struct i915_page_directory_pointer *pdp)
571352ff8bdSFrançois Tigeot {
572352ff8bdSFrançois Tigeot 	kfree(pdp->used_pdpes);
573352ff8bdSFrançois Tigeot 	kfree(pdp->page_directory);
574352ff8bdSFrançois Tigeot 	pdp->page_directory = NULL;
575352ff8bdSFrançois Tigeot }
576352ff8bdSFrançois Tigeot 
577352ff8bdSFrançois Tigeot static struct
578352ff8bdSFrançois Tigeot i915_page_directory_pointer *alloc_pdp(struct drm_device *dev)
579352ff8bdSFrançois Tigeot {
580352ff8bdSFrançois Tigeot 	struct i915_page_directory_pointer *pdp;
581352ff8bdSFrançois Tigeot 	int ret = -ENOMEM;
582352ff8bdSFrançois Tigeot 
583352ff8bdSFrançois Tigeot 	WARN_ON(!USES_FULL_48BIT_PPGTT(dev));
584352ff8bdSFrançois Tigeot 
585352ff8bdSFrançois Tigeot 	pdp = kzalloc(sizeof(*pdp), GFP_KERNEL);
586352ff8bdSFrançois Tigeot 	if (!pdp)
587352ff8bdSFrançois Tigeot 		return ERR_PTR(-ENOMEM);
588352ff8bdSFrançois Tigeot 
589352ff8bdSFrançois Tigeot 	ret = __pdp_init(dev, pdp);
590352ff8bdSFrançois Tigeot 	if (ret)
591352ff8bdSFrançois Tigeot 		goto fail_bitmap;
592352ff8bdSFrançois Tigeot 
593352ff8bdSFrançois Tigeot 	ret = setup_px(dev, pdp);
594352ff8bdSFrançois Tigeot 	if (ret)
595352ff8bdSFrançois Tigeot 		goto fail_page_m;
596352ff8bdSFrançois Tigeot 
597352ff8bdSFrançois Tigeot 	return pdp;
598352ff8bdSFrançois Tigeot 
599352ff8bdSFrançois Tigeot fail_page_m:
600352ff8bdSFrançois Tigeot 	__pdp_fini(pdp);
601352ff8bdSFrançois Tigeot fail_bitmap:
602352ff8bdSFrançois Tigeot 	kfree(pdp);
603352ff8bdSFrançois Tigeot 
604352ff8bdSFrançois Tigeot 	return ERR_PTR(ret);
605352ff8bdSFrançois Tigeot }
606352ff8bdSFrançois Tigeot 
607352ff8bdSFrançois Tigeot static void free_pdp(struct drm_device *dev,
608352ff8bdSFrançois Tigeot 		     struct i915_page_directory_pointer *pdp)
609352ff8bdSFrançois Tigeot {
610352ff8bdSFrançois Tigeot 	__pdp_fini(pdp);
611352ff8bdSFrançois Tigeot 	if (USES_FULL_48BIT_PPGTT(dev)) {
612352ff8bdSFrançois Tigeot 		cleanup_px(dev, pdp);
613352ff8bdSFrançois Tigeot 		kfree(pdp);
614352ff8bdSFrançois Tigeot 	}
615352ff8bdSFrançois Tigeot }
616352ff8bdSFrançois Tigeot 
617352ff8bdSFrançois Tigeot static void gen8_initialize_pdp(struct i915_address_space *vm,
618352ff8bdSFrançois Tigeot 				struct i915_page_directory_pointer *pdp)
619352ff8bdSFrançois Tigeot {
620352ff8bdSFrançois Tigeot 	gen8_ppgtt_pdpe_t scratch_pdpe;
621352ff8bdSFrançois Tigeot 
622352ff8bdSFrançois Tigeot 	scratch_pdpe = gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC);
623352ff8bdSFrançois Tigeot 
624352ff8bdSFrançois Tigeot 	fill_px(vm->dev, pdp, scratch_pdpe);
625352ff8bdSFrançois Tigeot }
626352ff8bdSFrançois Tigeot 
627352ff8bdSFrançois Tigeot static void gen8_initialize_pml4(struct i915_address_space *vm,
628352ff8bdSFrançois Tigeot 				 struct i915_pml4 *pml4)
629352ff8bdSFrançois Tigeot {
630352ff8bdSFrançois Tigeot 	gen8_ppgtt_pml4e_t scratch_pml4e;
631352ff8bdSFrançois Tigeot 
632352ff8bdSFrançois Tigeot 	scratch_pml4e = gen8_pml4e_encode(px_dma(vm->scratch_pdp),
633352ff8bdSFrançois Tigeot 					  I915_CACHE_LLC);
634352ff8bdSFrançois Tigeot 
635352ff8bdSFrançois Tigeot 	fill_px(vm->dev, pml4, scratch_pml4e);
636352ff8bdSFrançois Tigeot }
637352ff8bdSFrançois Tigeot 
638352ff8bdSFrançois Tigeot static void
639352ff8bdSFrançois Tigeot gen8_setup_page_directory(struct i915_hw_ppgtt *ppgtt,
640352ff8bdSFrançois Tigeot 			  struct i915_page_directory_pointer *pdp,
641352ff8bdSFrançois Tigeot 			  struct i915_page_directory *pd,
642352ff8bdSFrançois Tigeot 			  int index)
643352ff8bdSFrançois Tigeot {
644352ff8bdSFrançois Tigeot 	gen8_ppgtt_pdpe_t *page_directorypo;
645352ff8bdSFrançois Tigeot 
646352ff8bdSFrançois Tigeot 	if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
647352ff8bdSFrançois Tigeot 		return;
648352ff8bdSFrançois Tigeot 
649352ff8bdSFrançois Tigeot 	page_directorypo = kmap_px(pdp);
650352ff8bdSFrançois Tigeot 	page_directorypo[index] = gen8_pdpe_encode(px_dma(pd), I915_CACHE_LLC);
651352ff8bdSFrançois Tigeot 	kunmap_px(ppgtt, page_directorypo);
652352ff8bdSFrançois Tigeot }
653352ff8bdSFrançois Tigeot 
654352ff8bdSFrançois Tigeot static void
655352ff8bdSFrançois Tigeot gen8_setup_page_directory_pointer(struct i915_hw_ppgtt *ppgtt,
656352ff8bdSFrançois Tigeot 				  struct i915_pml4 *pml4,
657352ff8bdSFrançois Tigeot 				  struct i915_page_directory_pointer *pdp,
658352ff8bdSFrançois Tigeot 				  int index)
659352ff8bdSFrançois Tigeot {
660352ff8bdSFrançois Tigeot 	gen8_ppgtt_pml4e_t *pagemap = kmap_px(pml4);
661352ff8bdSFrançois Tigeot 
662352ff8bdSFrançois Tigeot 	WARN_ON(!USES_FULL_48BIT_PPGTT(ppgtt->base.dev));
663352ff8bdSFrançois Tigeot 	pagemap[index] = gen8_pml4e_encode(px_dma(pdp), I915_CACHE_LLC);
664352ff8bdSFrançois Tigeot 	kunmap_px(ppgtt, pagemap);
665352ff8bdSFrançois Tigeot }
666352ff8bdSFrançois Tigeot 
6679edbd4a0SFrançois Tigeot /* Broadwell Page Directory Pointer Descriptors */
668a05eeebfSFrançois Tigeot static int gen8_write_pdp(struct drm_i915_gem_request *req,
66919c468b4SFrançois Tigeot 			  unsigned entry,
67019c468b4SFrançois Tigeot 			  dma_addr_t addr)
6719edbd4a0SFrançois Tigeot {
672*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
6738621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
6749edbd4a0SFrançois Tigeot 	int ret;
6759edbd4a0SFrançois Tigeot 
6769edbd4a0SFrançois Tigeot 	BUG_ON(entry >= 4);
6779edbd4a0SFrançois Tigeot 
678a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
6799edbd4a0SFrançois Tigeot 	if (ret)
6809edbd4a0SFrançois Tigeot 		return ret;
6819edbd4a0SFrançois Tigeot 
682*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
683*71f41f3eSFrançois Tigeot 	intel_ring_emit_reg(ring, GEN8_RING_PDP_UDW(engine, entry));
684*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, upper_32_bits(addr));
685*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
686*71f41f3eSFrançois Tigeot 	intel_ring_emit_reg(ring, GEN8_RING_PDP_LDW(engine, entry));
687*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, lower_32_bits(addr));
688*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
6899edbd4a0SFrançois Tigeot 
6909edbd4a0SFrançois Tigeot 	return 0;
6919edbd4a0SFrançois Tigeot }
6929edbd4a0SFrançois Tigeot 
693352ff8bdSFrançois Tigeot static int gen8_legacy_mm_switch(struct i915_hw_ppgtt *ppgtt,
694a05eeebfSFrançois Tigeot 				 struct drm_i915_gem_request *req)
6959edbd4a0SFrançois Tigeot {
696ba55f2f5SFrançois Tigeot 	int i, ret;
6979edbd4a0SFrançois Tigeot 
69819c468b4SFrançois Tigeot 	for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) {
699a05eeebfSFrançois Tigeot 		const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
700a05eeebfSFrançois Tigeot 
701a05eeebfSFrançois Tigeot 		ret = gen8_write_pdp(req, i, pd_daddr);
7029edbd4a0SFrançois Tigeot 		if (ret)
7039edbd4a0SFrançois Tigeot 			return ret;
7049edbd4a0SFrançois Tigeot 	}
7059edbd4a0SFrançois Tigeot 
706ba55f2f5SFrançois Tigeot 	return 0;
707ba55f2f5SFrançois Tigeot }
708ba55f2f5SFrançois Tigeot 
709352ff8bdSFrançois Tigeot static int gen8_48b_mm_switch(struct i915_hw_ppgtt *ppgtt,
710352ff8bdSFrançois Tigeot 			      struct drm_i915_gem_request *req)
711352ff8bdSFrançois Tigeot {
712352ff8bdSFrançois Tigeot 	return gen8_write_pdp(req, 0, px_dma(&ppgtt->pml4));
713352ff8bdSFrançois Tigeot }
714352ff8bdSFrançois Tigeot 
715352ff8bdSFrançois Tigeot static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm,
716352ff8bdSFrançois Tigeot 				       struct i915_page_directory_pointer *pdp,
717ba55f2f5SFrançois Tigeot 				       uint64_t start,
718ba55f2f5SFrançois Tigeot 				       uint64_t length,
719352ff8bdSFrançois Tigeot 				       gen8_pte_t scratch_pte)
7209edbd4a0SFrançois Tigeot {
7218621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
722352ff8bdSFrançois Tigeot 	gen8_pte_t *pt_vaddr;
723352ff8bdSFrançois Tigeot 	unsigned pdpe = gen8_pdpe_index(start);
724352ff8bdSFrançois Tigeot 	unsigned pde = gen8_pde_index(start);
725352ff8bdSFrançois Tigeot 	unsigned pte = gen8_pte_index(start);
726ba55f2f5SFrançois Tigeot 	unsigned num_entries = length >> PAGE_SHIFT;
7279edbd4a0SFrançois Tigeot 	unsigned last_pte, i;
7289edbd4a0SFrançois Tigeot 
729352ff8bdSFrançois Tigeot 	if (WARN_ON(!pdp))
730352ff8bdSFrançois Tigeot 		return;
7319edbd4a0SFrançois Tigeot 
7329edbd4a0SFrançois Tigeot 	while (num_entries) {
73319c468b4SFrançois Tigeot 		struct i915_page_directory *pd;
73419c468b4SFrançois Tigeot 		struct i915_page_table *pt;
735477eb7f9SFrançois Tigeot 
736352ff8bdSFrançois Tigeot 		if (WARN_ON(!pdp->page_directory[pdpe]))
737352ff8bdSFrançois Tigeot 			break;
738477eb7f9SFrançois Tigeot 
739352ff8bdSFrançois Tigeot 		pd = pdp->page_directory[pdpe];
740477eb7f9SFrançois Tigeot 
741477eb7f9SFrançois Tigeot 		if (WARN_ON(!pd->page_table[pde]))
742352ff8bdSFrançois Tigeot 			break;
743477eb7f9SFrançois Tigeot 
744477eb7f9SFrançois Tigeot 		pt = pd->page_table[pde];
745477eb7f9SFrançois Tigeot 
746a05eeebfSFrançois Tigeot 		if (WARN_ON(!px_page(pt)))
747352ff8bdSFrançois Tigeot 			break;
7489edbd4a0SFrançois Tigeot 
749ba55f2f5SFrançois Tigeot 		last_pte = pte + num_entries;
750477eb7f9SFrançois Tigeot 		if (last_pte > GEN8_PTES)
751477eb7f9SFrançois Tigeot 			last_pte = GEN8_PTES;
7529edbd4a0SFrançois Tigeot 
753a05eeebfSFrançois Tigeot 		pt_vaddr = kmap_px(pt);
7549edbd4a0SFrançois Tigeot 
755ba55f2f5SFrançois Tigeot 		for (i = pte; i < last_pte; i++) {
7569edbd4a0SFrançois Tigeot 			pt_vaddr[i] = scratch_pte;
757ba55f2f5SFrançois Tigeot 			num_entries--;
758ba55f2f5SFrançois Tigeot 		}
7599edbd4a0SFrançois Tigeot 
7608621f407SFrançois Tigeot 		kunmap_px(ppgtt, pt_vaddr);
7619edbd4a0SFrançois Tigeot 
762ba55f2f5SFrançois Tigeot 		pte = 0;
763477eb7f9SFrançois Tigeot 		if (++pde == I915_PDES) {
764352ff8bdSFrançois Tigeot 			if (++pdpe == I915_PDPES_PER_PDP(vm->dev))
765352ff8bdSFrançois Tigeot 				break;
766ba55f2f5SFrançois Tigeot 			pde = 0;
767ba55f2f5SFrançois Tigeot 		}
7689edbd4a0SFrançois Tigeot 	}
7699edbd4a0SFrançois Tigeot }
7709edbd4a0SFrançois Tigeot 
771352ff8bdSFrançois Tigeot static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
772ba55f2f5SFrançois Tigeot 				   uint64_t start,
773352ff8bdSFrançois Tigeot 				   uint64_t length,
774352ff8bdSFrançois Tigeot 				   bool use_scratch)
775352ff8bdSFrançois Tigeot {
7768621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
777352ff8bdSFrançois Tigeot 	gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
778352ff8bdSFrançois Tigeot 						 I915_CACHE_LLC, use_scratch);
779352ff8bdSFrançois Tigeot 
780352ff8bdSFrançois Tigeot 	if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
781352ff8bdSFrançois Tigeot 		gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length,
782352ff8bdSFrançois Tigeot 					   scratch_pte);
783352ff8bdSFrançois Tigeot 	} else {
784aee94f86SFrançois Tigeot 		uint64_t pml4e;
785352ff8bdSFrançois Tigeot 		struct i915_page_directory_pointer *pdp;
786352ff8bdSFrançois Tigeot 
787aee94f86SFrançois Tigeot 		gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
788352ff8bdSFrançois Tigeot 			gen8_ppgtt_clear_pte_range(vm, pdp, start, length,
789352ff8bdSFrançois Tigeot 						   scratch_pte);
790352ff8bdSFrançois Tigeot 		}
791352ff8bdSFrançois Tigeot 	}
792352ff8bdSFrançois Tigeot }
793352ff8bdSFrançois Tigeot 
794352ff8bdSFrançois Tigeot static void
795352ff8bdSFrançois Tigeot gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm,
796352ff8bdSFrançois Tigeot 			      struct i915_page_directory_pointer *pdp,
797352ff8bdSFrançois Tigeot 			      struct sg_page_iter *sg_iter,
798352ff8bdSFrançois Tigeot 			      uint64_t start,
799352ff8bdSFrançois Tigeot 			      enum i915_cache_level cache_level)
8009edbd4a0SFrançois Tigeot {
8018621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
802477eb7f9SFrançois Tigeot 	gen8_pte_t *pt_vaddr;
803352ff8bdSFrançois Tigeot 	unsigned pdpe = gen8_pdpe_index(start);
804352ff8bdSFrançois Tigeot 	unsigned pde = gen8_pde_index(start);
805352ff8bdSFrançois Tigeot 	unsigned pte = gen8_pte_index(start);
8069edbd4a0SFrançois Tigeot 
8079edbd4a0SFrançois Tigeot 	pt_vaddr = NULL;
8089edbd4a0SFrançois Tigeot 
809352ff8bdSFrançois Tigeot 	while (__sg_page_iter_next(sg_iter)) {
810477eb7f9SFrançois Tigeot 		if (pt_vaddr == NULL) {
811352ff8bdSFrançois Tigeot 			struct i915_page_directory *pd = pdp->page_directory[pdpe];
81219c468b4SFrançois Tigeot 			struct i915_page_table *pt = pd->page_table[pde];
813a05eeebfSFrançois Tigeot 			pt_vaddr = kmap_px(pt);
814477eb7f9SFrançois Tigeot 		}
815ba55f2f5SFrançois Tigeot 
816ba55f2f5SFrançois Tigeot 		pt_vaddr[pte] =
817352ff8bdSFrançois Tigeot 			gen8_pte_encode(sg_page_iter_dma_address(sg_iter),
8189edbd4a0SFrançois Tigeot 					cache_level, true);
819477eb7f9SFrançois Tigeot 		if (++pte == GEN8_PTES) {
820a05eeebfSFrançois Tigeot 			kunmap_px(ppgtt, pt_vaddr);
8219edbd4a0SFrançois Tigeot 			pt_vaddr = NULL;
822477eb7f9SFrançois Tigeot 			if (++pde == I915_PDES) {
823352ff8bdSFrançois Tigeot 				if (++pdpe == I915_PDPES_PER_PDP(vm->dev))
824352ff8bdSFrançois Tigeot 					break;
825ba55f2f5SFrançois Tigeot 				pde = 0;
826ba55f2f5SFrançois Tigeot 			}
827ba55f2f5SFrançois Tigeot 			pte = 0;
8289edbd4a0SFrançois Tigeot 		}
8299edbd4a0SFrançois Tigeot 	}
830a05eeebfSFrançois Tigeot 
831a05eeebfSFrançois Tigeot 	if (pt_vaddr)
832a05eeebfSFrançois Tigeot 		kunmap_px(ppgtt, pt_vaddr);
833ba55f2f5SFrançois Tigeot }
834ba55f2f5SFrançois Tigeot 
835352ff8bdSFrançois Tigeot static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
836352ff8bdSFrançois Tigeot 				      struct sg_table *pages,
837352ff8bdSFrançois Tigeot 				      uint64_t start,
838352ff8bdSFrançois Tigeot 				      enum i915_cache_level cache_level,
839352ff8bdSFrançois Tigeot 				      u32 unused)
840352ff8bdSFrançois Tigeot {
8418621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
842352ff8bdSFrançois Tigeot 	struct sg_page_iter sg_iter;
843352ff8bdSFrançois Tigeot 
844352ff8bdSFrançois Tigeot 	__sg_page_iter_start(&sg_iter, pages->sgl, sg_nents(pages->sgl), 0);
845352ff8bdSFrançois Tigeot 
846352ff8bdSFrançois Tigeot 	if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
847352ff8bdSFrançois Tigeot 		gen8_ppgtt_insert_pte_entries(vm, &ppgtt->pdp, &sg_iter, start,
848352ff8bdSFrançois Tigeot 					      cache_level);
849352ff8bdSFrançois Tigeot 	} else {
850352ff8bdSFrançois Tigeot 		struct i915_page_directory_pointer *pdp;
851aee94f86SFrançois Tigeot 		uint64_t pml4e;
852352ff8bdSFrançois Tigeot 		uint64_t length = (uint64_t)pages->orig_nents << PAGE_SHIFT;
853352ff8bdSFrançois Tigeot 
854aee94f86SFrançois Tigeot 		gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
855352ff8bdSFrançois Tigeot 			gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter,
856352ff8bdSFrançois Tigeot 						      start, cache_level);
857352ff8bdSFrançois Tigeot 		}
858352ff8bdSFrançois Tigeot 	}
859352ff8bdSFrançois Tigeot }
860352ff8bdSFrançois Tigeot 
861a05eeebfSFrançois Tigeot static void gen8_free_page_tables(struct drm_device *dev,
86219c468b4SFrançois Tigeot 				  struct i915_page_directory *pd)
86319c468b4SFrançois Tigeot {
86419c468b4SFrançois Tigeot 	int i;
86519c468b4SFrançois Tigeot 
866a05eeebfSFrançois Tigeot 	if (!px_page(pd))
867ba55f2f5SFrançois Tigeot 		return;
868ba55f2f5SFrançois Tigeot 
86919c468b4SFrançois Tigeot 	for_each_set_bit(i, pd->used_pdes, I915_PDES) {
870477eb7f9SFrançois Tigeot 		if (WARN_ON(!pd->page_table[i]))
871477eb7f9SFrançois Tigeot 			continue;
872477eb7f9SFrançois Tigeot 
873a05eeebfSFrançois Tigeot 		free_pt(dev, pd->page_table[i]);
874477eb7f9SFrançois Tigeot 		pd->page_table[i] = NULL;
875477eb7f9SFrançois Tigeot 	}
876ba55f2f5SFrançois Tigeot }
877ba55f2f5SFrançois Tigeot 
878a05eeebfSFrançois Tigeot static int gen8_init_scratch(struct i915_address_space *vm)
879a05eeebfSFrançois Tigeot {
880a05eeebfSFrançois Tigeot 	struct drm_device *dev = vm->dev;
8811487f786SFrançois Tigeot 	int ret;
882a05eeebfSFrançois Tigeot 
883a05eeebfSFrançois Tigeot 	vm->scratch_page = alloc_scratch_page(dev);
884a05eeebfSFrançois Tigeot 	if (IS_ERR(vm->scratch_page))
885a05eeebfSFrançois Tigeot 		return PTR_ERR(vm->scratch_page);
886a05eeebfSFrançois Tigeot 
887a05eeebfSFrançois Tigeot 	vm->scratch_pt = alloc_pt(dev);
888a05eeebfSFrançois Tigeot 	if (IS_ERR(vm->scratch_pt)) {
8891487f786SFrançois Tigeot 		ret = PTR_ERR(vm->scratch_pt);
8901487f786SFrançois Tigeot 		goto free_scratch_page;
891a05eeebfSFrançois Tigeot 	}
892a05eeebfSFrançois Tigeot 
893a05eeebfSFrançois Tigeot 	vm->scratch_pd = alloc_pd(dev);
894a05eeebfSFrançois Tigeot 	if (IS_ERR(vm->scratch_pd)) {
8951487f786SFrançois Tigeot 		ret = PTR_ERR(vm->scratch_pd);
8961487f786SFrançois Tigeot 		goto free_pt;
897a05eeebfSFrançois Tigeot 	}
898a05eeebfSFrançois Tigeot 
899352ff8bdSFrançois Tigeot 	if (USES_FULL_48BIT_PPGTT(dev)) {
900352ff8bdSFrançois Tigeot 		vm->scratch_pdp = alloc_pdp(dev);
901352ff8bdSFrançois Tigeot 		if (IS_ERR(vm->scratch_pdp)) {
9021487f786SFrançois Tigeot 			ret = PTR_ERR(vm->scratch_pdp);
9031487f786SFrançois Tigeot 			goto free_pd;
904352ff8bdSFrançois Tigeot 		}
905352ff8bdSFrançois Tigeot 	}
906352ff8bdSFrançois Tigeot 
907a05eeebfSFrançois Tigeot 	gen8_initialize_pt(vm, vm->scratch_pt);
908a05eeebfSFrançois Tigeot 	gen8_initialize_pd(vm, vm->scratch_pd);
909352ff8bdSFrançois Tigeot 	if (USES_FULL_48BIT_PPGTT(dev))
910352ff8bdSFrançois Tigeot 		gen8_initialize_pdp(vm, vm->scratch_pdp);
911352ff8bdSFrançois Tigeot 
912352ff8bdSFrançois Tigeot 	return 0;
9131487f786SFrançois Tigeot 
9141487f786SFrançois Tigeot free_pd:
9151487f786SFrançois Tigeot 	free_pd(dev, vm->scratch_pd);
9161487f786SFrançois Tigeot free_pt:
9171487f786SFrançois Tigeot 	free_pt(dev, vm->scratch_pt);
9181487f786SFrançois Tigeot free_scratch_page:
9191487f786SFrançois Tigeot 	free_scratch_page(dev, vm->scratch_page);
9201487f786SFrançois Tigeot 
9211487f786SFrançois Tigeot 	return ret;
922352ff8bdSFrançois Tigeot }
923352ff8bdSFrançois Tigeot 
924352ff8bdSFrançois Tigeot static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create)
925352ff8bdSFrançois Tigeot {
926352ff8bdSFrançois Tigeot 	enum vgt_g2v_type msg;
9278621f407SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
928352ff8bdSFrançois Tigeot 	int i;
929352ff8bdSFrançois Tigeot 
9308621f407SFrançois Tigeot 	if (USES_FULL_48BIT_PPGTT(dev_priv)) {
931352ff8bdSFrançois Tigeot 		u64 daddr = px_dma(&ppgtt->pml4);
932352ff8bdSFrançois Tigeot 
933aee94f86SFrançois Tigeot 		I915_WRITE(vgtif_reg(pdp[0].lo), lower_32_bits(daddr));
934aee94f86SFrançois Tigeot 		I915_WRITE(vgtif_reg(pdp[0].hi), upper_32_bits(daddr));
935352ff8bdSFrançois Tigeot 
936352ff8bdSFrançois Tigeot 		msg = (create ? VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE :
937352ff8bdSFrançois Tigeot 				VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY);
938352ff8bdSFrançois Tigeot 	} else {
939352ff8bdSFrançois Tigeot 		for (i = 0; i < GEN8_LEGACY_PDPES; i++) {
940352ff8bdSFrançois Tigeot 			u64 daddr = i915_page_dir_dma_addr(ppgtt, i);
941352ff8bdSFrançois Tigeot 
942aee94f86SFrançois Tigeot 			I915_WRITE(vgtif_reg(pdp[i].lo), lower_32_bits(daddr));
943aee94f86SFrançois Tigeot 			I915_WRITE(vgtif_reg(pdp[i].hi), upper_32_bits(daddr));
944352ff8bdSFrançois Tigeot 		}
945352ff8bdSFrançois Tigeot 
946352ff8bdSFrançois Tigeot 		msg = (create ? VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE :
947352ff8bdSFrançois Tigeot 				VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY);
948352ff8bdSFrançois Tigeot 	}
949352ff8bdSFrançois Tigeot 
950352ff8bdSFrançois Tigeot 	I915_WRITE(vgtif_reg(g2v_notify), msg);
951a05eeebfSFrançois Tigeot 
952a05eeebfSFrançois Tigeot 	return 0;
953a05eeebfSFrançois Tigeot }
954a05eeebfSFrançois Tigeot 
955a05eeebfSFrançois Tigeot static void gen8_free_scratch(struct i915_address_space *vm)
956a05eeebfSFrançois Tigeot {
957a05eeebfSFrançois Tigeot 	struct drm_device *dev = vm->dev;
958a05eeebfSFrançois Tigeot 
959352ff8bdSFrançois Tigeot 	if (USES_FULL_48BIT_PPGTT(dev))
960352ff8bdSFrançois Tigeot 		free_pdp(dev, vm->scratch_pdp);
961a05eeebfSFrançois Tigeot 	free_pd(dev, vm->scratch_pd);
962a05eeebfSFrançois Tigeot 	free_pt(dev, vm->scratch_pt);
963a05eeebfSFrançois Tigeot 	free_scratch_page(dev, vm->scratch_page);
964a05eeebfSFrançois Tigeot }
965a05eeebfSFrançois Tigeot 
966352ff8bdSFrançois Tigeot static void gen8_ppgtt_cleanup_3lvl(struct drm_device *dev,
967352ff8bdSFrançois Tigeot 				    struct i915_page_directory_pointer *pdp)
968352ff8bdSFrançois Tigeot {
969352ff8bdSFrançois Tigeot 	int i;
970352ff8bdSFrançois Tigeot 
971352ff8bdSFrançois Tigeot 	for_each_set_bit(i, pdp->used_pdpes, I915_PDPES_PER_PDP(dev)) {
972352ff8bdSFrançois Tigeot 		if (WARN_ON(!pdp->page_directory[i]))
973352ff8bdSFrançois Tigeot 			continue;
974352ff8bdSFrançois Tigeot 
975352ff8bdSFrançois Tigeot 		gen8_free_page_tables(dev, pdp->page_directory[i]);
976352ff8bdSFrançois Tigeot 		free_pd(dev, pdp->page_directory[i]);
977352ff8bdSFrançois Tigeot 	}
978352ff8bdSFrançois Tigeot 
979352ff8bdSFrançois Tigeot 	free_pdp(dev, pdp);
980352ff8bdSFrançois Tigeot }
981352ff8bdSFrançois Tigeot 
982352ff8bdSFrançois Tigeot static void gen8_ppgtt_cleanup_4lvl(struct i915_hw_ppgtt *ppgtt)
983352ff8bdSFrançois Tigeot {
984352ff8bdSFrançois Tigeot 	int i;
985352ff8bdSFrançois Tigeot 
986352ff8bdSFrançois Tigeot 	for_each_set_bit(i, ppgtt->pml4.used_pml4es, GEN8_PML4ES_PER_PML4) {
987352ff8bdSFrançois Tigeot 		if (WARN_ON(!ppgtt->pml4.pdps[i]))
988352ff8bdSFrançois Tigeot 			continue;
989352ff8bdSFrançois Tigeot 
990352ff8bdSFrançois Tigeot 		gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, ppgtt->pml4.pdps[i]);
991352ff8bdSFrançois Tigeot 	}
992352ff8bdSFrançois Tigeot 
993352ff8bdSFrançois Tigeot 	cleanup_px(ppgtt->base.dev, &ppgtt->pml4);
994352ff8bdSFrançois Tigeot }
995352ff8bdSFrançois Tigeot 
9969edbd4a0SFrançois Tigeot static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
9979edbd4a0SFrançois Tigeot {
9988621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
9999edbd4a0SFrançois Tigeot 
10001487f786SFrançois Tigeot 	if (intel_vgpu_active(to_i915(vm->dev)))
1001352ff8bdSFrançois Tigeot 		gen8_ppgtt_notify_vgt(ppgtt, false);
100219c468b4SFrançois Tigeot 
1003352ff8bdSFrançois Tigeot 	if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
1004352ff8bdSFrançois Tigeot 		gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, &ppgtt->pdp);
1005352ff8bdSFrançois Tigeot 	else
1006352ff8bdSFrançois Tigeot 		gen8_ppgtt_cleanup_4lvl(ppgtt);
10079edbd4a0SFrançois Tigeot 
1008a05eeebfSFrançois Tigeot 	gen8_free_scratch(vm);
100919c468b4SFrançois Tigeot }
1010ba55f2f5SFrançois Tigeot 
101119c468b4SFrançois Tigeot /**
101219c468b4SFrançois Tigeot  * gen8_ppgtt_alloc_pagetabs() - Allocate page tables for VA range.
1013352ff8bdSFrançois Tigeot  * @vm:	Master vm structure.
101419c468b4SFrançois Tigeot  * @pd:	Page directory for this address range.
101519c468b4SFrançois Tigeot  * @start:	Starting virtual address to begin allocations.
1016352ff8bdSFrançois Tigeot  * @length:	Size of the allocations.
101719c468b4SFrançois Tigeot  * @new_pts:	Bitmap set by function with new allocations. Likely used by the
101819c468b4SFrançois Tigeot  *		caller to free on error.
101919c468b4SFrançois Tigeot  *
102019c468b4SFrançois Tigeot  * Allocate the required number of page tables. Extremely similar to
102119c468b4SFrançois Tigeot  * gen8_ppgtt_alloc_page_directories(). The main difference is here we are limited by
102219c468b4SFrançois Tigeot  * the page directory boundary (instead of the page directory pointer). That
102319c468b4SFrançois Tigeot  * boundary is 1GB virtual. Therefore, unlike gen8_ppgtt_alloc_page_directories(), it is
102419c468b4SFrançois Tigeot  * possible, and likely that the caller will need to use multiple calls of this
102519c468b4SFrançois Tigeot  * function to achieve the appropriate allocation.
102619c468b4SFrançois Tigeot  *
102719c468b4SFrançois Tigeot  * Return: 0 if success; negative error code otherwise.
102819c468b4SFrançois Tigeot  */
1029352ff8bdSFrançois Tigeot static int gen8_ppgtt_alloc_pagetabs(struct i915_address_space *vm,
103019c468b4SFrançois Tigeot 				     struct i915_page_directory *pd,
103119c468b4SFrançois Tigeot 				     uint64_t start,
103219c468b4SFrançois Tigeot 				     uint64_t length,
103319c468b4SFrançois Tigeot 				     unsigned long *new_pts)
103419c468b4SFrançois Tigeot {
1035352ff8bdSFrançois Tigeot 	struct drm_device *dev = vm->dev;
103619c468b4SFrançois Tigeot 	struct i915_page_table *pt;
103719c468b4SFrançois Tigeot 	uint32_t pde;
103819c468b4SFrançois Tigeot 
1039aee94f86SFrançois Tigeot 	gen8_for_each_pde(pt, pd, start, length, pde) {
104019c468b4SFrançois Tigeot 		/* Don't reallocate page tables */
1041352ff8bdSFrançois Tigeot 		if (test_bit(pde, pd->used_pdes)) {
104219c468b4SFrançois Tigeot 			/* Scratch is never allocated this way */
1043352ff8bdSFrançois Tigeot 			WARN_ON(pt == vm->scratch_pt);
104419c468b4SFrançois Tigeot 			continue;
104519c468b4SFrançois Tigeot 		}
104619c468b4SFrançois Tigeot 
1047a05eeebfSFrançois Tigeot 		pt = alloc_pt(dev);
104819c468b4SFrançois Tigeot 		if (IS_ERR(pt))
1049ba55f2f5SFrançois Tigeot 			goto unwind_out;
105019c468b4SFrançois Tigeot 
1051352ff8bdSFrançois Tigeot 		gen8_initialize_pt(vm, pt);
105219c468b4SFrançois Tigeot 		pd->page_table[pde] = pt;
1053a05eeebfSFrançois Tigeot 		__set_bit(pde, new_pts);
1054352ff8bdSFrançois Tigeot 		trace_i915_page_table_entry_alloc(vm, pde, start, GEN8_PDE_SHIFT);
1055ba55f2f5SFrançois Tigeot 	}
1056ba55f2f5SFrançois Tigeot 
1057ba55f2f5SFrançois Tigeot 	return 0;
1058ba55f2f5SFrançois Tigeot 
1059ba55f2f5SFrançois Tigeot unwind_out:
106019c468b4SFrançois Tigeot 	for_each_set_bit(pde, new_pts, I915_PDES)
1061a05eeebfSFrançois Tigeot 		free_pt(dev, pd->page_table[pde]);
1062ba55f2f5SFrançois Tigeot 
1063ba55f2f5SFrançois Tigeot 	return -ENOMEM;
1064ba55f2f5SFrançois Tigeot }
1065ba55f2f5SFrançois Tigeot 
106619c468b4SFrançois Tigeot /**
106719c468b4SFrançois Tigeot  * gen8_ppgtt_alloc_page_directories() - Allocate page directories for VA range.
1068352ff8bdSFrançois Tigeot  * @vm:	Master vm structure.
106919c468b4SFrançois Tigeot  * @pdp:	Page directory pointer for this address range.
107019c468b4SFrançois Tigeot  * @start:	Starting virtual address to begin allocations.
1071352ff8bdSFrançois Tigeot  * @length:	Size of the allocations.
1072352ff8bdSFrançois Tigeot  * @new_pds:	Bitmap set by function with new allocations. Likely used by the
107319c468b4SFrançois Tigeot  *		caller to free on error.
107419c468b4SFrançois Tigeot  *
107519c468b4SFrançois Tigeot  * Allocate the required number of page directories starting at the pde index of
107619c468b4SFrançois Tigeot  * @start, and ending at the pde index @start + @length. This function will skip
107719c468b4SFrançois Tigeot  * over already allocated page directories within the range, and only allocate
107819c468b4SFrançois Tigeot  * new ones, setting the appropriate pointer within the pdp as well as the
107919c468b4SFrançois Tigeot  * correct position in the bitmap @new_pds.
108019c468b4SFrançois Tigeot  *
108119c468b4SFrançois Tigeot  * The function will only allocate the pages within the range for a give page
108219c468b4SFrançois Tigeot  * directory pointer. In other words, if @start + @length straddles a virtually
108319c468b4SFrançois Tigeot  * addressed PDP boundary (512GB for 4k pages), there will be more allocations
108419c468b4SFrançois Tigeot  * required by the caller, This is not currently possible, and the BUG in the
108519c468b4SFrançois Tigeot  * code will prevent it.
108619c468b4SFrançois Tigeot  *
108719c468b4SFrançois Tigeot  * Return: 0 if success; negative error code otherwise.
108819c468b4SFrançois Tigeot  */
1089352ff8bdSFrançois Tigeot static int
1090352ff8bdSFrançois Tigeot gen8_ppgtt_alloc_page_directories(struct i915_address_space *vm,
109119c468b4SFrançois Tigeot 				  struct i915_page_directory_pointer *pdp,
109219c468b4SFrançois Tigeot 				  uint64_t start,
109319c468b4SFrançois Tigeot 				  uint64_t length,
109419c468b4SFrançois Tigeot 				  unsigned long *new_pds)
109519c468b4SFrançois Tigeot {
1096352ff8bdSFrançois Tigeot 	struct drm_device *dev = vm->dev;
109719c468b4SFrançois Tigeot 	struct i915_page_directory *pd;
109819c468b4SFrançois Tigeot 	uint32_t pdpe;
1099352ff8bdSFrançois Tigeot 	uint32_t pdpes = I915_PDPES_PER_PDP(dev);
110019c468b4SFrançois Tigeot 
1101352ff8bdSFrançois Tigeot 	WARN_ON(!bitmap_empty(new_pds, pdpes));
110219c468b4SFrançois Tigeot 
1103aee94f86SFrançois Tigeot 	gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
1104352ff8bdSFrançois Tigeot 		if (test_bit(pdpe, pdp->used_pdpes))
110519c468b4SFrançois Tigeot 			continue;
110619c468b4SFrançois Tigeot 
1107a05eeebfSFrançois Tigeot 		pd = alloc_pd(dev);
110819c468b4SFrançois Tigeot 		if (IS_ERR(pd))
110919c468b4SFrançois Tigeot 			goto unwind_out;
111019c468b4SFrançois Tigeot 
1111352ff8bdSFrançois Tigeot 		gen8_initialize_pd(vm, pd);
111219c468b4SFrançois Tigeot 		pdp->page_directory[pdpe] = pd;
1113a05eeebfSFrançois Tigeot 		__set_bit(pdpe, new_pds);
1114352ff8bdSFrançois Tigeot 		trace_i915_page_directory_entry_alloc(vm, pdpe, start, GEN8_PDPE_SHIFT);
111519c468b4SFrançois Tigeot 	}
111619c468b4SFrançois Tigeot 
111719c468b4SFrançois Tigeot 	return 0;
111819c468b4SFrançois Tigeot 
111919c468b4SFrançois Tigeot unwind_out:
1120352ff8bdSFrançois Tigeot 	for_each_set_bit(pdpe, new_pds, pdpes)
1121a05eeebfSFrançois Tigeot 		free_pd(dev, pdp->page_directory[pdpe]);
112219c468b4SFrançois Tigeot 
112319c468b4SFrançois Tigeot 	return -ENOMEM;
112419c468b4SFrançois Tigeot }
112519c468b4SFrançois Tigeot 
1126352ff8bdSFrançois Tigeot /**
1127352ff8bdSFrançois Tigeot  * gen8_ppgtt_alloc_page_dirpointers() - Allocate pdps for VA range.
1128352ff8bdSFrançois Tigeot  * @vm:	Master vm structure.
1129352ff8bdSFrançois Tigeot  * @pml4:	Page map level 4 for this address range.
1130352ff8bdSFrançois Tigeot  * @start:	Starting virtual address to begin allocations.
1131352ff8bdSFrançois Tigeot  * @length:	Size of the allocations.
1132352ff8bdSFrançois Tigeot  * @new_pdps:	Bitmap set by function with new allocations. Likely used by the
1133352ff8bdSFrançois Tigeot  *		caller to free on error.
1134352ff8bdSFrançois Tigeot  *
1135352ff8bdSFrançois Tigeot  * Allocate the required number of page directory pointers. Extremely similar to
1136352ff8bdSFrançois Tigeot  * gen8_ppgtt_alloc_page_directories() and gen8_ppgtt_alloc_pagetabs().
1137352ff8bdSFrançois Tigeot  * The main difference is here we are limited by the pml4 boundary (instead of
1138352ff8bdSFrançois Tigeot  * the page directory pointer).
1139352ff8bdSFrançois Tigeot  *
1140352ff8bdSFrançois Tigeot  * Return: 0 if success; negative error code otherwise.
1141352ff8bdSFrançois Tigeot  */
1142352ff8bdSFrançois Tigeot static int
1143352ff8bdSFrançois Tigeot gen8_ppgtt_alloc_page_dirpointers(struct i915_address_space *vm,
1144352ff8bdSFrançois Tigeot 				  struct i915_pml4 *pml4,
1145352ff8bdSFrançois Tigeot 				  uint64_t start,
1146352ff8bdSFrançois Tigeot 				  uint64_t length,
1147352ff8bdSFrançois Tigeot 				  unsigned long *new_pdps)
1148ba55f2f5SFrançois Tigeot {
1149352ff8bdSFrançois Tigeot 	struct drm_device *dev = vm->dev;
1150352ff8bdSFrançois Tigeot 	struct i915_page_directory_pointer *pdp;
1151352ff8bdSFrançois Tigeot 	uint32_t pml4e;
11529edbd4a0SFrançois Tigeot 
1153352ff8bdSFrançois Tigeot 	WARN_ON(!bitmap_empty(new_pdps, GEN8_PML4ES_PER_PML4));
1154352ff8bdSFrançois Tigeot 
1155aee94f86SFrançois Tigeot 	gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
1156352ff8bdSFrançois Tigeot 		if (!test_bit(pml4e, pml4->used_pml4es)) {
1157352ff8bdSFrançois Tigeot 			pdp = alloc_pdp(dev);
1158352ff8bdSFrançois Tigeot 			if (IS_ERR(pdp))
1159352ff8bdSFrançois Tigeot 				goto unwind_out;
1160352ff8bdSFrançois Tigeot 
1161352ff8bdSFrançois Tigeot 			gen8_initialize_pdp(vm, pdp);
1162352ff8bdSFrançois Tigeot 			pml4->pdps[pml4e] = pdp;
1163352ff8bdSFrançois Tigeot 			__set_bit(pml4e, new_pdps);
1164352ff8bdSFrançois Tigeot 			trace_i915_page_directory_pointer_entry_alloc(vm,
1165352ff8bdSFrançois Tigeot 								      pml4e,
1166352ff8bdSFrançois Tigeot 								      start,
1167352ff8bdSFrançois Tigeot 								      GEN8_PML4E_SHIFT);
1168352ff8bdSFrançois Tigeot 		}
1169352ff8bdSFrançois Tigeot 	}
1170352ff8bdSFrançois Tigeot 
1171352ff8bdSFrançois Tigeot 	return 0;
1172352ff8bdSFrançois Tigeot 
1173352ff8bdSFrançois Tigeot unwind_out:
1174352ff8bdSFrançois Tigeot 	for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4)
1175352ff8bdSFrançois Tigeot 		free_pdp(dev, pml4->pdps[pml4e]);
1176352ff8bdSFrançois Tigeot 
1177352ff8bdSFrançois Tigeot 	return -ENOMEM;
1178352ff8bdSFrançois Tigeot }
1179352ff8bdSFrançois Tigeot 
1180352ff8bdSFrançois Tigeot static void
1181352ff8bdSFrançois Tigeot free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long *new_pts)
1182352ff8bdSFrançois Tigeot {
118319c468b4SFrançois Tigeot 	kfree(new_pts);
118419c468b4SFrançois Tigeot 	kfree(new_pds);
1185477eb7f9SFrançois Tigeot }
1186477eb7f9SFrançois Tigeot 
118719c468b4SFrançois Tigeot /* Fills in the page directory bitmap, and the array of page tables bitmap. Both
118819c468b4SFrançois Tigeot  * of these are based on the number of PDPEs in the system.
118919c468b4SFrançois Tigeot  */
119019c468b4SFrançois Tigeot static
119119c468b4SFrançois Tigeot int __must_check alloc_gen8_temp_bitmaps(unsigned long **new_pds,
1192352ff8bdSFrançois Tigeot 					 unsigned long **new_pts,
1193352ff8bdSFrançois Tigeot 					 uint32_t pdpes)
119419c468b4SFrançois Tigeot {
119519c468b4SFrançois Tigeot 	unsigned long *pds;
1196352ff8bdSFrançois Tigeot 	unsigned long *pts;
11979edbd4a0SFrançois Tigeot 
1198352ff8bdSFrançois Tigeot 	pds = kcalloc(BITS_TO_LONGS(pdpes), sizeof(unsigned long), GFP_TEMPORARY);
119919c468b4SFrançois Tigeot 	if (!pds)
120019c468b4SFrançois Tigeot 		return -ENOMEM;
1201477eb7f9SFrançois Tigeot 
1202352ff8bdSFrançois Tigeot 	pts = kcalloc(pdpes, BITS_TO_LONGS(I915_PDES) * sizeof(unsigned long),
1203352ff8bdSFrançois Tigeot 		      GFP_TEMPORARY);
1204352ff8bdSFrançois Tigeot 	if (!pts)
1205477eb7f9SFrançois Tigeot 		goto err_out;
1206ba55f2f5SFrançois Tigeot 
120719c468b4SFrançois Tigeot 	*new_pds = pds;
120819c468b4SFrançois Tigeot 	*new_pts = pts;
1209477eb7f9SFrançois Tigeot 
1210477eb7f9SFrançois Tigeot 	return 0;
1211477eb7f9SFrançois Tigeot 
1212477eb7f9SFrançois Tigeot err_out:
121319c468b4SFrançois Tigeot 	free_gen8_temp_bitmaps(pds, pts);
121419c468b4SFrançois Tigeot 	return -ENOMEM;
1215ba55f2f5SFrançois Tigeot }
1216ba55f2f5SFrançois Tigeot 
1217a05eeebfSFrançois Tigeot /* PDE TLBs are a pain to invalidate on GEN8+. When we modify
1218a05eeebfSFrançois Tigeot  * the page table structures, we mark them dirty so that
1219a05eeebfSFrançois Tigeot  * context switching/execlist queuing code takes extra steps
1220a05eeebfSFrançois Tigeot  * to ensure that tlbs are flushed.
1221a05eeebfSFrançois Tigeot  */
1222a05eeebfSFrançois Tigeot static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt)
1223a05eeebfSFrançois Tigeot {
1224a05eeebfSFrançois Tigeot 	ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask;
1225a05eeebfSFrançois Tigeot }
1226a05eeebfSFrançois Tigeot 
1227352ff8bdSFrançois Tigeot static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
1228352ff8bdSFrançois Tigeot 				    struct i915_page_directory_pointer *pdp,
122919c468b4SFrançois Tigeot 				    uint64_t start,
123019c468b4SFrançois Tigeot 				    uint64_t length)
1231ba55f2f5SFrançois Tigeot {
12328621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
1233352ff8bdSFrançois Tigeot 	unsigned long *new_page_dirs, *new_page_tables;
1234352ff8bdSFrançois Tigeot 	struct drm_device *dev = vm->dev;
123519c468b4SFrançois Tigeot 	struct i915_page_directory *pd;
123619c468b4SFrançois Tigeot 	const uint64_t orig_start = start;
123719c468b4SFrançois Tigeot 	const uint64_t orig_length = length;
123819c468b4SFrançois Tigeot 	uint32_t pdpe;
1239352ff8bdSFrançois Tigeot 	uint32_t pdpes = I915_PDPES_PER_PDP(dev);
1240ba55f2f5SFrançois Tigeot 	int ret;
1241ba55f2f5SFrançois Tigeot 
124219c468b4SFrançois Tigeot 	/* Wrap is never okay since we can only represent 48b, and we don't
124319c468b4SFrançois Tigeot 	 * actually use the other side of the canonical address space.
124419c468b4SFrançois Tigeot 	 */
124519c468b4SFrançois Tigeot 	if (WARN_ON(start + length < start))
1246a05eeebfSFrançois Tigeot 		return -ENODEV;
1247a05eeebfSFrançois Tigeot 
1248352ff8bdSFrançois Tigeot 	if (WARN_ON(start + length > vm->total))
1249a05eeebfSFrançois Tigeot 		return -ENODEV;
1250ba55f2f5SFrançois Tigeot 
1251352ff8bdSFrançois Tigeot 	ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables, pdpes);
1252ba55f2f5SFrançois Tigeot 	if (ret)
1253ba55f2f5SFrançois Tigeot 		return ret;
1254ba55f2f5SFrançois Tigeot 
125519c468b4SFrançois Tigeot 	/* Do the allocations first so we can easily bail out */
1256352ff8bdSFrançois Tigeot 	ret = gen8_ppgtt_alloc_page_directories(vm, pdp, start, length,
125719c468b4SFrançois Tigeot 						new_page_dirs);
125819c468b4SFrançois Tigeot 	if (ret) {
125919c468b4SFrançois Tigeot 		free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
126019c468b4SFrançois Tigeot 		return ret;
126119c468b4SFrançois Tigeot 	}
126219c468b4SFrançois Tigeot 
126319c468b4SFrançois Tigeot 	/* For every page directory referenced, allocate page tables */
1264aee94f86SFrançois Tigeot 	gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
1265352ff8bdSFrançois Tigeot 		ret = gen8_ppgtt_alloc_pagetabs(vm, pd, start, length,
1266352ff8bdSFrançois Tigeot 						new_page_tables + pdpe * BITS_TO_LONGS(I915_PDES));
126719c468b4SFrançois Tigeot 		if (ret)
126819c468b4SFrançois Tigeot 			goto err_out;
126919c468b4SFrançois Tigeot 	}
127019c468b4SFrançois Tigeot 
127119c468b4SFrançois Tigeot 	start = orig_start;
127219c468b4SFrançois Tigeot 	length = orig_length;
127319c468b4SFrançois Tigeot 
127419c468b4SFrançois Tigeot 	/* Allocations have completed successfully, so set the bitmaps, and do
127519c468b4SFrançois Tigeot 	 * the mappings. */
1276aee94f86SFrançois Tigeot 	gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
1277a05eeebfSFrançois Tigeot 		gen8_pde_t *const page_directory = kmap_px(pd);
127819c468b4SFrançois Tigeot 		struct i915_page_table *pt;
1279352ff8bdSFrançois Tigeot 		uint64_t pd_len = length;
128019c468b4SFrançois Tigeot 		uint64_t pd_start = start;
128119c468b4SFrançois Tigeot 		uint32_t pde;
128219c468b4SFrançois Tigeot 
128319c468b4SFrançois Tigeot 		/* Every pd should be allocated, we just did that above. */
128419c468b4SFrançois Tigeot 		WARN_ON(!pd);
128519c468b4SFrançois Tigeot 
1286aee94f86SFrançois Tigeot 		gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) {
128719c468b4SFrançois Tigeot 			/* Same reasoning as pd */
128819c468b4SFrançois Tigeot 			WARN_ON(!pt);
128919c468b4SFrançois Tigeot 			WARN_ON(!pd_len);
129019c468b4SFrançois Tigeot 			WARN_ON(!gen8_pte_count(pd_start, pd_len));
129119c468b4SFrançois Tigeot 
129219c468b4SFrançois Tigeot 			/* Set our used ptes within the page table */
129319c468b4SFrançois Tigeot 			bitmap_set(pt->used_ptes,
129419c468b4SFrançois Tigeot 				   gen8_pte_index(pd_start),
129519c468b4SFrançois Tigeot 				   gen8_pte_count(pd_start, pd_len));
129619c468b4SFrançois Tigeot 
129719c468b4SFrançois Tigeot 			/* Our pde is now pointing to the pagetable, pt */
1298a05eeebfSFrançois Tigeot 			__set_bit(pde, pd->used_pdes);
129919c468b4SFrançois Tigeot 
130019c468b4SFrançois Tigeot 			/* Map the PDE to the page table */
1301a05eeebfSFrançois Tigeot 			page_directory[pde] = gen8_pde_encode(px_dma(pt),
1302a05eeebfSFrançois Tigeot 							      I915_CACHE_LLC);
1303352ff8bdSFrançois Tigeot 			trace_i915_page_table_entry_map(&ppgtt->base, pde, pt,
1304352ff8bdSFrançois Tigeot 							gen8_pte_index(start),
1305352ff8bdSFrançois Tigeot 							gen8_pte_count(start, length),
1306352ff8bdSFrançois Tigeot 							GEN8_PTES);
130719c468b4SFrançois Tigeot 
130819c468b4SFrançois Tigeot 			/* NB: We haven't yet mapped ptes to pages. At this
130919c468b4SFrançois Tigeot 			 * point we're still relying on insert_entries() */
131019c468b4SFrançois Tigeot 		}
131119c468b4SFrançois Tigeot 
1312a05eeebfSFrançois Tigeot 		kunmap_px(ppgtt, page_directory);
1313352ff8bdSFrançois Tigeot 		__set_bit(pdpe, pdp->used_pdpes);
1314352ff8bdSFrançois Tigeot 		gen8_setup_page_directory(ppgtt, pdp, pd, pdpe);
131519c468b4SFrançois Tigeot 	}
131619c468b4SFrançois Tigeot 
131719c468b4SFrançois Tigeot 	free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
1318a05eeebfSFrançois Tigeot 	mark_tlbs_dirty(ppgtt);
131919c468b4SFrançois Tigeot 	return 0;
132019c468b4SFrançois Tigeot 
132119c468b4SFrançois Tigeot err_out:
132219c468b4SFrançois Tigeot 	while (pdpe--) {
1323aee94f86SFrançois Tigeot 		unsigned long temp;
1324aee94f86SFrançois Tigeot 
1325352ff8bdSFrançois Tigeot 		for_each_set_bit(temp, new_page_tables + pdpe *
1326352ff8bdSFrançois Tigeot 				BITS_TO_LONGS(I915_PDES), I915_PDES)
1327352ff8bdSFrançois Tigeot 			free_pt(dev, pdp->page_directory[pdpe]->page_table[temp]);
132819c468b4SFrançois Tigeot 	}
132919c468b4SFrançois Tigeot 
1330352ff8bdSFrançois Tigeot 	for_each_set_bit(pdpe, new_page_dirs, pdpes)
1331352ff8bdSFrançois Tigeot 		free_pd(dev, pdp->page_directory[pdpe]);
133219c468b4SFrançois Tigeot 
133319c468b4SFrançois Tigeot 	free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
1334a05eeebfSFrançois Tigeot 	mark_tlbs_dirty(ppgtt);
133519c468b4SFrançois Tigeot 	return ret;
133619c468b4SFrançois Tigeot }
133719c468b4SFrançois Tigeot 
1338352ff8bdSFrançois Tigeot static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm,
1339352ff8bdSFrançois Tigeot 				    struct i915_pml4 *pml4,
1340352ff8bdSFrançois Tigeot 				    uint64_t start,
1341352ff8bdSFrançois Tigeot 				    uint64_t length)
1342352ff8bdSFrançois Tigeot {
1343352ff8bdSFrançois Tigeot 	DECLARE_BITMAP(new_pdps, GEN8_PML4ES_PER_PML4);
13448621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
1345352ff8bdSFrançois Tigeot 	struct i915_page_directory_pointer *pdp;
1346aee94f86SFrançois Tigeot 	uint64_t pml4e;
1347352ff8bdSFrançois Tigeot 	int ret = 0;
1348352ff8bdSFrançois Tigeot 
1349352ff8bdSFrançois Tigeot 	/* Do the pml4 allocations first, so we don't need to track the newly
1350352ff8bdSFrançois Tigeot 	 * allocated tables below the pdp */
1351352ff8bdSFrançois Tigeot 	bitmap_zero(new_pdps, GEN8_PML4ES_PER_PML4);
1352352ff8bdSFrançois Tigeot 
1353352ff8bdSFrançois Tigeot 	/* The pagedirectory and pagetable allocations are done in the shared 3
1354352ff8bdSFrançois Tigeot 	 * and 4 level code. Just allocate the pdps.
1355352ff8bdSFrançois Tigeot 	 */
1356352ff8bdSFrançois Tigeot 	ret = gen8_ppgtt_alloc_page_dirpointers(vm, pml4, start, length,
1357352ff8bdSFrançois Tigeot 						new_pdps);
1358352ff8bdSFrançois Tigeot 	if (ret)
1359352ff8bdSFrançois Tigeot 		return ret;
1360352ff8bdSFrançois Tigeot 
1361352ff8bdSFrançois Tigeot 	WARN(bitmap_weight(new_pdps, GEN8_PML4ES_PER_PML4) > 2,
1362352ff8bdSFrançois Tigeot 	     "The allocation has spanned more than 512GB. "
1363352ff8bdSFrançois Tigeot 	     "It is highly likely this is incorrect.");
1364352ff8bdSFrançois Tigeot 
1365aee94f86SFrançois Tigeot 	gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
1366352ff8bdSFrançois Tigeot 		WARN_ON(!pdp);
1367352ff8bdSFrançois Tigeot 
1368352ff8bdSFrançois Tigeot 		ret = gen8_alloc_va_range_3lvl(vm, pdp, start, length);
1369352ff8bdSFrançois Tigeot 		if (ret)
1370352ff8bdSFrançois Tigeot 			goto err_out;
1371352ff8bdSFrançois Tigeot 
1372352ff8bdSFrançois Tigeot 		gen8_setup_page_directory_pointer(ppgtt, pml4, pdp, pml4e);
1373352ff8bdSFrançois Tigeot 	}
1374352ff8bdSFrançois Tigeot 
1375352ff8bdSFrançois Tigeot 	bitmap_or(pml4->used_pml4es, new_pdps, pml4->used_pml4es,
1376352ff8bdSFrançois Tigeot 		  GEN8_PML4ES_PER_PML4);
1377352ff8bdSFrançois Tigeot 
1378352ff8bdSFrançois Tigeot 	return 0;
1379352ff8bdSFrançois Tigeot 
1380352ff8bdSFrançois Tigeot err_out:
1381352ff8bdSFrançois Tigeot 	for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4)
1382352ff8bdSFrançois Tigeot 		gen8_ppgtt_cleanup_3lvl(vm->dev, pml4->pdps[pml4e]);
1383352ff8bdSFrançois Tigeot 
1384352ff8bdSFrançois Tigeot 	return ret;
1385352ff8bdSFrançois Tigeot }
1386352ff8bdSFrançois Tigeot 
1387352ff8bdSFrançois Tigeot static int gen8_alloc_va_range(struct i915_address_space *vm,
1388352ff8bdSFrançois Tigeot 			       uint64_t start, uint64_t length)
1389352ff8bdSFrançois Tigeot {
13908621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
1391352ff8bdSFrançois Tigeot 
1392352ff8bdSFrançois Tigeot 	if (USES_FULL_48BIT_PPGTT(vm->dev))
1393352ff8bdSFrançois Tigeot 		return gen8_alloc_va_range_4lvl(vm, &ppgtt->pml4, start, length);
1394352ff8bdSFrançois Tigeot 	else
1395352ff8bdSFrançois Tigeot 		return gen8_alloc_va_range_3lvl(vm, &ppgtt->pdp, start, length);
1396352ff8bdSFrançois Tigeot }
1397352ff8bdSFrançois Tigeot 
1398352ff8bdSFrançois Tigeot static void gen8_dump_pdp(struct i915_page_directory_pointer *pdp,
1399352ff8bdSFrançois Tigeot 			  uint64_t start, uint64_t length,
1400352ff8bdSFrançois Tigeot 			  gen8_pte_t scratch_pte,
1401352ff8bdSFrançois Tigeot 			  struct seq_file *m)
1402352ff8bdSFrançois Tigeot {
1403352ff8bdSFrançois Tigeot 	struct i915_page_directory *pd;
1404352ff8bdSFrançois Tigeot 	uint32_t pdpe;
1405352ff8bdSFrançois Tigeot 
1406aee94f86SFrançois Tigeot 	gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
1407352ff8bdSFrançois Tigeot 		struct i915_page_table *pt;
1408352ff8bdSFrançois Tigeot 		uint64_t pd_len = length;
1409352ff8bdSFrançois Tigeot 		uint64_t pd_start = start;
1410352ff8bdSFrançois Tigeot 		uint32_t pde;
1411352ff8bdSFrançois Tigeot 
1412352ff8bdSFrançois Tigeot 		if (!test_bit(pdpe, pdp->used_pdpes))
1413352ff8bdSFrançois Tigeot 			continue;
1414352ff8bdSFrançois Tigeot 
1415352ff8bdSFrançois Tigeot 		seq_printf(m, "\tPDPE #%d\n", pdpe);
1416aee94f86SFrançois Tigeot 		gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) {
1417352ff8bdSFrançois Tigeot 			uint32_t  pte;
1418352ff8bdSFrançois Tigeot 			gen8_pte_t *pt_vaddr;
1419352ff8bdSFrançois Tigeot 
1420352ff8bdSFrançois Tigeot 			if (!test_bit(pde, pd->used_pdes))
1421352ff8bdSFrançois Tigeot 				continue;
1422352ff8bdSFrançois Tigeot 
1423352ff8bdSFrançois Tigeot 			pt_vaddr = kmap_px(pt);
1424352ff8bdSFrançois Tigeot 			for (pte = 0; pte < GEN8_PTES; pte += 4) {
1425352ff8bdSFrançois Tigeot 				uint64_t va =
1426352ff8bdSFrançois Tigeot 					(pdpe << GEN8_PDPE_SHIFT) |
1427352ff8bdSFrançois Tigeot 					(pde << GEN8_PDE_SHIFT) |
1428352ff8bdSFrançois Tigeot 					(pte << GEN8_PTE_SHIFT);
1429352ff8bdSFrançois Tigeot 				int i;
1430352ff8bdSFrançois Tigeot 				bool found = false;
1431352ff8bdSFrançois Tigeot 
1432352ff8bdSFrançois Tigeot 				for (i = 0; i < 4; i++)
1433352ff8bdSFrançois Tigeot 					if (pt_vaddr[pte + i] != scratch_pte)
1434352ff8bdSFrançois Tigeot 						found = true;
1435352ff8bdSFrançois Tigeot 				if (!found)
1436352ff8bdSFrançois Tigeot 					continue;
1437352ff8bdSFrançois Tigeot 
1438352ff8bdSFrançois Tigeot 				seq_printf(m, "\t\t0x%lx [%03d,%03d,%04d]: =", va, pdpe, pde, pte);
1439352ff8bdSFrançois Tigeot 				for (i = 0; i < 4; i++) {
1440352ff8bdSFrançois Tigeot 					if (pt_vaddr[pte + i] != scratch_pte)
1441352ff8bdSFrançois Tigeot 						seq_printf(m, " %lx", pt_vaddr[pte + i]);
1442352ff8bdSFrançois Tigeot 					else
1443352ff8bdSFrançois Tigeot 						seq_puts(m, "  SCRATCH ");
1444352ff8bdSFrançois Tigeot 				}
1445352ff8bdSFrançois Tigeot 				seq_puts(m, "\n");
1446352ff8bdSFrançois Tigeot 			}
1447352ff8bdSFrançois Tigeot 			/* don't use kunmap_px, it could trigger
1448352ff8bdSFrançois Tigeot 			 * an unnecessary flush.
1449352ff8bdSFrançois Tigeot 			 */
1450352ff8bdSFrançois Tigeot 			kunmap_atomic(pt_vaddr);
1451352ff8bdSFrançois Tigeot 		}
1452352ff8bdSFrançois Tigeot 	}
1453352ff8bdSFrançois Tigeot }
1454352ff8bdSFrançois Tigeot 
1455352ff8bdSFrançois Tigeot static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
1456352ff8bdSFrançois Tigeot {
1457352ff8bdSFrançois Tigeot 	struct i915_address_space *vm = &ppgtt->base;
1458352ff8bdSFrançois Tigeot 	uint64_t start = ppgtt->base.start;
1459352ff8bdSFrançois Tigeot 	uint64_t length = ppgtt->base.total;
1460352ff8bdSFrançois Tigeot 	gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
1461352ff8bdSFrançois Tigeot 						 I915_CACHE_LLC, true);
1462352ff8bdSFrançois Tigeot 
1463352ff8bdSFrançois Tigeot 	if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
1464352ff8bdSFrançois Tigeot 		gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m);
1465352ff8bdSFrançois Tigeot 	} else {
1466aee94f86SFrançois Tigeot 		uint64_t pml4e;
1467352ff8bdSFrançois Tigeot 		struct i915_pml4 *pml4 = &ppgtt->pml4;
1468352ff8bdSFrançois Tigeot 		struct i915_page_directory_pointer *pdp;
1469352ff8bdSFrançois Tigeot 
1470aee94f86SFrançois Tigeot 		gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
1471352ff8bdSFrançois Tigeot 			if (!test_bit(pml4e, pml4->used_pml4es))
1472352ff8bdSFrançois Tigeot 				continue;
1473352ff8bdSFrançois Tigeot 
1474352ff8bdSFrançois Tigeot 			seq_printf(m, "    PML4E #%lu\n", pml4e);
1475352ff8bdSFrançois Tigeot 			gen8_dump_pdp(pdp, start, length, scratch_pte, m);
1476352ff8bdSFrançois Tigeot 		}
1477352ff8bdSFrançois Tigeot 	}
1478352ff8bdSFrançois Tigeot }
1479352ff8bdSFrançois Tigeot 
1480352ff8bdSFrançois Tigeot static int gen8_preallocate_top_level_pdps(struct i915_hw_ppgtt *ppgtt)
1481352ff8bdSFrançois Tigeot {
1482352ff8bdSFrançois Tigeot 	unsigned long *new_page_dirs, *new_page_tables;
1483352ff8bdSFrançois Tigeot 	uint32_t pdpes = I915_PDPES_PER_PDP(dev);
1484352ff8bdSFrançois Tigeot 	int ret;
1485352ff8bdSFrançois Tigeot 
1486352ff8bdSFrançois Tigeot 	/* We allocate temp bitmap for page tables for no gain
1487352ff8bdSFrançois Tigeot 	 * but as this is for init only, lets keep the things simple
1488352ff8bdSFrançois Tigeot 	 */
1489352ff8bdSFrançois Tigeot 	ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables, pdpes);
1490352ff8bdSFrançois Tigeot 	if (ret)
1491352ff8bdSFrançois Tigeot 		return ret;
1492352ff8bdSFrançois Tigeot 
1493352ff8bdSFrançois Tigeot 	/* Allocate for all pdps regardless of how the ppgtt
1494352ff8bdSFrançois Tigeot 	 * was defined.
1495352ff8bdSFrançois Tigeot 	 */
1496352ff8bdSFrançois Tigeot 	ret = gen8_ppgtt_alloc_page_directories(&ppgtt->base, &ppgtt->pdp,
1497352ff8bdSFrançois Tigeot 						0, 1ULL << 32,
1498352ff8bdSFrançois Tigeot 						new_page_dirs);
1499352ff8bdSFrançois Tigeot 	if (!ret)
1500352ff8bdSFrançois Tigeot 		*ppgtt->pdp.used_pdpes = *new_page_dirs;
1501352ff8bdSFrançois Tigeot 
1502352ff8bdSFrançois Tigeot 	free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
1503352ff8bdSFrançois Tigeot 
1504352ff8bdSFrançois Tigeot 	return ret;
1505352ff8bdSFrançois Tigeot }
1506352ff8bdSFrançois Tigeot 
150719c468b4SFrançois Tigeot /*
150819c468b4SFrançois Tigeot  * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
150919c468b4SFrançois Tigeot  * with a net effect resembling a 2-level page table in normal x86 terms. Each
151019c468b4SFrançois Tigeot  * PDP represents 1GB of memory 4 * 512 * 512 * 4096 = 4GB legacy 32b address
151119c468b4SFrançois Tigeot  * space.
151219c468b4SFrançois Tigeot  *
151319c468b4SFrançois Tigeot  */
151419c468b4SFrançois Tigeot static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
1515ba55f2f5SFrançois Tigeot {
1516a05eeebfSFrançois Tigeot 	int ret;
1517ba55f2f5SFrançois Tigeot 
1518a05eeebfSFrançois Tigeot 	ret = gen8_init_scratch(&ppgtt->base);
1519a05eeebfSFrançois Tigeot 	if (ret)
1520a05eeebfSFrançois Tigeot 		return ret;
152119c468b4SFrançois Tigeot 
152219c468b4SFrançois Tigeot 	ppgtt->base.start = 0;
152319c468b4SFrançois Tigeot 	ppgtt->base.cleanup = gen8_ppgtt_cleanup;
152419c468b4SFrançois Tigeot 	ppgtt->base.allocate_va_range = gen8_alloc_va_range;
152519c468b4SFrançois Tigeot 	ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
152619c468b4SFrançois Tigeot 	ppgtt->base.clear_range = gen8_ppgtt_clear_range;
152719c468b4SFrançois Tigeot 	ppgtt->base.unbind_vma = ppgtt_unbind_vma;
152819c468b4SFrançois Tigeot 	ppgtt->base.bind_vma = ppgtt_bind_vma;
1529352ff8bdSFrançois Tigeot 	ppgtt->debug_dump = gen8_dump_ppgtt;
15309edbd4a0SFrançois Tigeot 
1531352ff8bdSFrançois Tigeot 	if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
1532352ff8bdSFrançois Tigeot 		ret = setup_px(ppgtt->base.dev, &ppgtt->pml4);
1533352ff8bdSFrançois Tigeot 		if (ret)
1534352ff8bdSFrançois Tigeot 			goto free_scratch;
1535352ff8bdSFrançois Tigeot 
1536352ff8bdSFrançois Tigeot 		gen8_initialize_pml4(&ppgtt->base, &ppgtt->pml4);
1537352ff8bdSFrançois Tigeot 
1538352ff8bdSFrançois Tigeot 		ppgtt->base.total = 1ULL << 48;
1539352ff8bdSFrançois Tigeot 		ppgtt->switch_mm = gen8_48b_mm_switch;
1540352ff8bdSFrançois Tigeot 	} else {
1541352ff8bdSFrançois Tigeot 		ret = __pdp_init(ppgtt->base.dev, &ppgtt->pdp);
1542352ff8bdSFrançois Tigeot 		if (ret)
1543352ff8bdSFrançois Tigeot 			goto free_scratch;
1544352ff8bdSFrançois Tigeot 
1545352ff8bdSFrançois Tigeot 		ppgtt->base.total = 1ULL << 32;
1546352ff8bdSFrançois Tigeot 		ppgtt->switch_mm = gen8_legacy_mm_switch;
1547352ff8bdSFrançois Tigeot 		trace_i915_page_directory_pointer_entry_alloc(&ppgtt->base,
1548352ff8bdSFrançois Tigeot 							      0, 0,
1549352ff8bdSFrançois Tigeot 							      GEN8_PML4E_SHIFT);
1550352ff8bdSFrançois Tigeot 
15511487f786SFrançois Tigeot 		if (intel_vgpu_active(to_i915(ppgtt->base.dev))) {
1552352ff8bdSFrançois Tigeot 			ret = gen8_preallocate_top_level_pdps(ppgtt);
1553352ff8bdSFrançois Tigeot 			if (ret)
1554352ff8bdSFrançois Tigeot 				goto free_scratch;
1555352ff8bdSFrançois Tigeot 		}
1556352ff8bdSFrançois Tigeot 	}
1557352ff8bdSFrançois Tigeot 
15581487f786SFrançois Tigeot 	if (intel_vgpu_active(to_i915(ppgtt->base.dev)))
1559352ff8bdSFrançois Tigeot 		gen8_ppgtt_notify_vgt(ppgtt, true);
1560ba55f2f5SFrançois Tigeot 
15619edbd4a0SFrançois Tigeot 	return 0;
1562352ff8bdSFrançois Tigeot 
1563352ff8bdSFrançois Tigeot free_scratch:
1564352ff8bdSFrançois Tigeot 	gen8_free_scratch(&ppgtt->base);
1565352ff8bdSFrançois Tigeot 	return ret;
15669edbd4a0SFrançois Tigeot }
15679edbd4a0SFrançois Tigeot 
1568ba55f2f5SFrançois Tigeot static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
1569ba55f2f5SFrançois Tigeot {
1570ba55f2f5SFrançois Tigeot 	struct i915_address_space *vm = &ppgtt->base;
157119c468b4SFrançois Tigeot 	struct i915_page_table *unused;
1572477eb7f9SFrançois Tigeot 	gen6_pte_t scratch_pte;
1573ba55f2f5SFrançois Tigeot 	uint32_t pd_entry;
15741487f786SFrançois Tigeot 	uint32_t  pte, pde;
157519c468b4SFrançois Tigeot 	uint32_t start = ppgtt->base.start, length = ppgtt->base.total;
1576ba55f2f5SFrançois Tigeot 
1577a05eeebfSFrançois Tigeot 	scratch_pte = vm->pte_encode(px_dma(vm->scratch_page),
1578a05eeebfSFrançois Tigeot 				     I915_CACHE_LLC, true, 0);
1579ba55f2f5SFrançois Tigeot 
15801487f786SFrançois Tigeot 	gen6_for_each_pde(unused, &ppgtt->pd, start, length, pde) {
1581ba55f2f5SFrançois Tigeot 		u32 expected;
1582477eb7f9SFrançois Tigeot 		gen6_pte_t *pt_vaddr;
1583a05eeebfSFrançois Tigeot 		const dma_addr_t pt_addr = px_dma(ppgtt->pd.page_table[pde]);
158419c468b4SFrançois Tigeot 		pd_entry = readl(ppgtt->pd_addr + pde);
1585ba55f2f5SFrançois Tigeot 		expected = (GEN6_PDE_ADDR_ENCODE(pt_addr) | GEN6_PDE_VALID);
1586ba55f2f5SFrançois Tigeot 
1587ba55f2f5SFrançois Tigeot 		if (pd_entry != expected)
1588ba55f2f5SFrançois Tigeot 			seq_printf(m, "\tPDE #%d mismatch: Actual PDE: %x Expected PDE: %x\n",
1589ba55f2f5SFrançois Tigeot 				   pde,
1590ba55f2f5SFrançois Tigeot 				   pd_entry,
1591ba55f2f5SFrançois Tigeot 				   expected);
1592ba55f2f5SFrançois Tigeot 		seq_printf(m, "\tPDE: %x\n", pd_entry);
1593ba55f2f5SFrançois Tigeot 
1594a05eeebfSFrançois Tigeot 		pt_vaddr = kmap_px(ppgtt->pd.page_table[pde]);
1595a05eeebfSFrançois Tigeot 
1596477eb7f9SFrançois Tigeot 		for (pte = 0; pte < GEN6_PTES; pte+=4) {
1597ba55f2f5SFrançois Tigeot 			unsigned long va =
1598477eb7f9SFrançois Tigeot 				(pde * PAGE_SIZE * GEN6_PTES) +
1599ba55f2f5SFrançois Tigeot 				(pte * PAGE_SIZE);
1600ba55f2f5SFrançois Tigeot 			int i;
1601ba55f2f5SFrançois Tigeot 			bool found = false;
1602ba55f2f5SFrançois Tigeot 			for (i = 0; i < 4; i++)
1603ba55f2f5SFrançois Tigeot 				if (pt_vaddr[pte + i] != scratch_pte)
1604ba55f2f5SFrançois Tigeot 					found = true;
1605ba55f2f5SFrançois Tigeot 			if (!found)
1606ba55f2f5SFrançois Tigeot 				continue;
1607ba55f2f5SFrançois Tigeot 
1608ba55f2f5SFrançois Tigeot 			seq_printf(m, "\t\t0x%lx [%03d,%04d]: =", va, pde, pte);
1609ba55f2f5SFrançois Tigeot 			for (i = 0; i < 4; i++) {
1610ba55f2f5SFrançois Tigeot 				if (pt_vaddr[pte + i] != scratch_pte)
1611ba55f2f5SFrançois Tigeot 					seq_printf(m, " %08x", pt_vaddr[pte + i]);
1612ba55f2f5SFrançois Tigeot 				else
1613477eb7f9SFrançois Tigeot 					seq_puts(m, "  SCRATCH ");
1614ba55f2f5SFrançois Tigeot 			}
1615477eb7f9SFrançois Tigeot 			seq_puts(m, "\n");
1616ba55f2f5SFrançois Tigeot 		}
1617a05eeebfSFrançois Tigeot 		kunmap_px(ppgtt, pt_vaddr);
1618ba55f2f5SFrançois Tigeot 	}
1619ba55f2f5SFrançois Tigeot }
1620ba55f2f5SFrançois Tigeot 
1621477eb7f9SFrançois Tigeot /* Write pde (index) from the page directory @pd to the page table @pt */
162219c468b4SFrançois Tigeot static void gen6_write_pde(struct i915_page_directory *pd,
162319c468b4SFrançois Tigeot 			    const int pde, struct i915_page_table *pt)
16249edbd4a0SFrançois Tigeot {
1625477eb7f9SFrançois Tigeot 	/* Caller needs to make sure the write completes if necessary */
1626477eb7f9SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt =
1627477eb7f9SFrançois Tigeot 		container_of(pd, struct i915_hw_ppgtt, pd);
1628477eb7f9SFrançois Tigeot 	u32 pd_entry;
16299edbd4a0SFrançois Tigeot 
1630a05eeebfSFrançois Tigeot 	pd_entry = GEN6_PDE_ADDR_ENCODE(px_dma(pt));
16319edbd4a0SFrançois Tigeot 	pd_entry |= GEN6_PDE_VALID;
16329edbd4a0SFrançois Tigeot 
1633477eb7f9SFrançois Tigeot 	writel(pd_entry, ppgtt->pd_addr + pde);
16349edbd4a0SFrançois Tigeot }
1635477eb7f9SFrançois Tigeot 
1636477eb7f9SFrançois Tigeot /* Write all the page tables found in the ppgtt structure to incrementing page
1637477eb7f9SFrançois Tigeot  * directories. */
1638477eb7f9SFrançois Tigeot static void gen6_write_page_range(struct drm_i915_private *dev_priv,
163919c468b4SFrançois Tigeot 				  struct i915_page_directory *pd,
1640477eb7f9SFrançois Tigeot 				  uint32_t start, uint32_t length)
1641477eb7f9SFrançois Tigeot {
16428621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
164319c468b4SFrançois Tigeot 	struct i915_page_table *pt;
16441487f786SFrançois Tigeot 	uint32_t pde;
1645477eb7f9SFrançois Tigeot 
16461487f786SFrançois Tigeot 	gen6_for_each_pde(pt, pd, start, length, pde)
1647477eb7f9SFrançois Tigeot 		gen6_write_pde(pd, pde, pt);
1648477eb7f9SFrançois Tigeot 
1649477eb7f9SFrançois Tigeot 	/* Make sure write is complete before other code can use this page
1650477eb7f9SFrançois Tigeot 	 * table. Also require for WC mapped PTEs */
16518621f407SFrançois Tigeot 	readl(ggtt->gsm);
16529edbd4a0SFrançois Tigeot }
16539edbd4a0SFrançois Tigeot 
1654ba55f2f5SFrançois Tigeot static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt)
16558e26cdf6SFrançois Tigeot {
1656a05eeebfSFrançois Tigeot 	BUG_ON(ppgtt->pd.base.ggtt_offset & 0x3f);
16575d0b1887SFrançois Tigeot 
1658a05eeebfSFrançois Tigeot 	return (ppgtt->pd.base.ggtt_offset / 64) << 16;
1659ba55f2f5SFrançois Tigeot }
16608e26cdf6SFrançois Tigeot 
1661ba55f2f5SFrançois Tigeot static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt,
1662a05eeebfSFrançois Tigeot 			 struct drm_i915_gem_request *req)
1663ba55f2f5SFrançois Tigeot {
1664*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
16658621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
1666ba55f2f5SFrançois Tigeot 	int ret;
16678e26cdf6SFrançois Tigeot 
1668ba55f2f5SFrançois Tigeot 	/* NB: TLBs must be flushed and invalidated before a switch */
1669*71f41f3eSFrançois Tigeot 	ret = engine->emit_flush(req, EMIT_INVALIDATE | EMIT_FLUSH);
1670ba55f2f5SFrançois Tigeot 	if (ret)
1671ba55f2f5SFrançois Tigeot 		return ret;
16728e26cdf6SFrançois Tigeot 
1673a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
1674ba55f2f5SFrançois Tigeot 	if (ret)
1675ba55f2f5SFrançois Tigeot 		return ret;
16768e26cdf6SFrançois Tigeot 
1677*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
1678*71f41f3eSFrançois Tigeot 	intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(engine));
1679*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, PP_DIR_DCLV_2G);
1680*71f41f3eSFrançois Tigeot 	intel_ring_emit_reg(ring, RING_PP_DIR_BASE(engine));
1681*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, get_pd_offset(ppgtt));
1682*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
1683*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1684ba55f2f5SFrançois Tigeot 
1685ba55f2f5SFrançois Tigeot 	return 0;
1686ba55f2f5SFrançois Tigeot }
1687ba55f2f5SFrançois Tigeot 
1688ba55f2f5SFrançois Tigeot static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
1689a05eeebfSFrançois Tigeot 			  struct drm_i915_gem_request *req)
1690ba55f2f5SFrançois Tigeot {
1691*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
16928621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
1693ba55f2f5SFrançois Tigeot 	int ret;
1694ba55f2f5SFrançois Tigeot 
1695ba55f2f5SFrançois Tigeot 	/* NB: TLBs must be flushed and invalidated before a switch */
1696*71f41f3eSFrançois Tigeot 	ret = engine->emit_flush(req, EMIT_INVALIDATE | EMIT_FLUSH);
1697ba55f2f5SFrançois Tigeot 	if (ret)
1698ba55f2f5SFrançois Tigeot 		return ret;
1699ba55f2f5SFrançois Tigeot 
1700a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
1701ba55f2f5SFrançois Tigeot 	if (ret)
1702ba55f2f5SFrançois Tigeot 		return ret;
1703ba55f2f5SFrançois Tigeot 
1704*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
1705*71f41f3eSFrançois Tigeot 	intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(engine));
1706*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, PP_DIR_DCLV_2G);
1707*71f41f3eSFrançois Tigeot 	intel_ring_emit_reg(ring, RING_PP_DIR_BASE(engine));
1708*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, get_pd_offset(ppgtt));
1709*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
1710*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1711ba55f2f5SFrançois Tigeot 
1712ba55f2f5SFrançois Tigeot 	/* XXX: RCS is the only one to auto invalidate the TLBs? */
17138621f407SFrançois Tigeot 	if (engine->id != RCS) {
1714*71f41f3eSFrançois Tigeot 		ret = engine->emit_flush(req, EMIT_INVALIDATE | EMIT_FLUSH);
1715ba55f2f5SFrançois Tigeot 		if (ret)
1716ba55f2f5SFrançois Tigeot 			return ret;
1717ba55f2f5SFrançois Tigeot 	}
1718ba55f2f5SFrançois Tigeot 
1719ba55f2f5SFrançois Tigeot 	return 0;
1720ba55f2f5SFrançois Tigeot }
1721ba55f2f5SFrançois Tigeot 
1722ba55f2f5SFrançois Tigeot static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt,
1723a05eeebfSFrançois Tigeot 			  struct drm_i915_gem_request *req)
1724ba55f2f5SFrançois Tigeot {
17258621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
1726303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
1727ba55f2f5SFrançois Tigeot 
17288621f407SFrançois Tigeot 	I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G);
17298621f407SFrançois Tigeot 	I915_WRITE(RING_PP_DIR_BASE(engine), get_pd_offset(ppgtt));
1730ba55f2f5SFrançois Tigeot 	return 0;
1731ba55f2f5SFrançois Tigeot }
1732ba55f2f5SFrançois Tigeot 
17331b13d190SFrançois Tigeot static void gen8_ppgtt_enable(struct drm_device *dev)
1734ba55f2f5SFrançois Tigeot {
1735303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
17368621f407SFrançois Tigeot 	struct intel_engine_cs *engine;
1737ba55f2f5SFrançois Tigeot 
17388621f407SFrançois Tigeot 	for_each_engine(engine, dev_priv) {
1739352ff8bdSFrançois Tigeot 		u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0;
17408621f407SFrançois Tigeot 		I915_WRITE(RING_MODE_GEN7(engine),
1741352ff8bdSFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level));
17421b13d190SFrançois Tigeot 	}
1743ba55f2f5SFrançois Tigeot }
1744ba55f2f5SFrançois Tigeot 
17451b13d190SFrançois Tigeot static void gen7_ppgtt_enable(struct drm_device *dev)
1746ba55f2f5SFrançois Tigeot {
1747303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
17488621f407SFrançois Tigeot 	struct intel_engine_cs *engine;
17498e26cdf6SFrançois Tigeot 	uint32_t ecochk, ecobits;
17508e26cdf6SFrançois Tigeot 
17518e26cdf6SFrançois Tigeot 	ecobits = I915_READ(GAC_ECO_BITS);
17528e26cdf6SFrançois Tigeot 	I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
17538e26cdf6SFrançois Tigeot 
17548e26cdf6SFrançois Tigeot 	ecochk = I915_READ(GAM_ECOCHK);
17558e26cdf6SFrançois Tigeot 	if (IS_HASWELL(dev)) {
17568e26cdf6SFrançois Tigeot 		ecochk |= ECOCHK_PPGTT_WB_HSW;
17578e26cdf6SFrançois Tigeot 	} else {
17588e26cdf6SFrançois Tigeot 		ecochk |= ECOCHK_PPGTT_LLC_IVB;
17598e26cdf6SFrançois Tigeot 		ecochk &= ~ECOCHK_PPGTT_GFDT_IVB;
17608e26cdf6SFrançois Tigeot 	}
17618e26cdf6SFrançois Tigeot 	I915_WRITE(GAM_ECOCHK, ecochk);
17628e26cdf6SFrançois Tigeot 
17638621f407SFrançois Tigeot 	for_each_engine(engine, dev_priv) {
1764ba55f2f5SFrançois Tigeot 		/* GFX_MODE is per-ring on gen7+ */
17658621f407SFrançois Tigeot 		I915_WRITE(RING_MODE_GEN7(engine),
17668e26cdf6SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
17671b13d190SFrançois Tigeot 	}
17688e26cdf6SFrançois Tigeot }
1769ba55f2f5SFrançois Tigeot 
17701b13d190SFrançois Tigeot static void gen6_ppgtt_enable(struct drm_device *dev)
1771ba55f2f5SFrançois Tigeot {
1772303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
1773ba55f2f5SFrançois Tigeot 	uint32_t ecochk, gab_ctl, ecobits;
1774ba55f2f5SFrançois Tigeot 
1775ba55f2f5SFrançois Tigeot 	ecobits = I915_READ(GAC_ECO_BITS);
1776ba55f2f5SFrançois Tigeot 	I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_SNB_BIT |
1777ba55f2f5SFrançois Tigeot 		   ECOBITS_PPGTT_CACHE64B);
1778ba55f2f5SFrançois Tigeot 
1779ba55f2f5SFrançois Tigeot 	gab_ctl = I915_READ(GAB_CTL);
1780ba55f2f5SFrançois Tigeot 	I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT);
1781ba55f2f5SFrançois Tigeot 
1782ba55f2f5SFrançois Tigeot 	ecochk = I915_READ(GAM_ECOCHK);
1783ba55f2f5SFrançois Tigeot 	I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | ECOCHK_PPGTT_CACHE64B);
1784ba55f2f5SFrançois Tigeot 
1785ba55f2f5SFrançois Tigeot 	I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
17868e26cdf6SFrançois Tigeot }
17878e26cdf6SFrançois Tigeot 
1788f4e1c372SFrançois Tigeot /* PPGTT support for Sandybdrige/Gen6 and later */
17899edbd4a0SFrançois Tigeot static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
1790ba55f2f5SFrançois Tigeot 				   uint64_t start,
1791ba55f2f5SFrançois Tigeot 				   uint64_t length,
17929edbd4a0SFrançois Tigeot 				   bool use_scratch)
1793f4e1c372SFrançois Tigeot {
17948621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
1795477eb7f9SFrançois Tigeot 	gen6_pte_t *pt_vaddr, scratch_pte;
1796ba55f2f5SFrançois Tigeot 	unsigned first_entry = start >> PAGE_SHIFT;
1797ba55f2f5SFrançois Tigeot 	unsigned num_entries = length >> PAGE_SHIFT;
1798477eb7f9SFrançois Tigeot 	unsigned act_pt = first_entry / GEN6_PTES;
1799477eb7f9SFrançois Tigeot 	unsigned first_pte = first_entry % GEN6_PTES;
1800f4e1c372SFrançois Tigeot 	unsigned last_pte, i;
1801e3adcf8fSFrançois Tigeot 
1802a05eeebfSFrançois Tigeot 	scratch_pte = vm->pte_encode(px_dma(vm->scratch_page),
1803a05eeebfSFrançois Tigeot 				     I915_CACHE_LLC, true, 0);
1804e3adcf8fSFrançois Tigeot 
1805e3adcf8fSFrançois Tigeot 	while (num_entries) {
1806e3adcf8fSFrançois Tigeot 		last_pte = first_pte + num_entries;
1807477eb7f9SFrançois Tigeot 		if (last_pte > GEN6_PTES)
1808477eb7f9SFrançois Tigeot 			last_pte = GEN6_PTES;
1809e3adcf8fSFrançois Tigeot 
1810a05eeebfSFrançois Tigeot 		pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]);
1811e3adcf8fSFrançois Tigeot 
1812e3adcf8fSFrançois Tigeot 		for (i = first_pte; i < last_pte; i++)
1813e3adcf8fSFrançois Tigeot 			pt_vaddr[i] = scratch_pte;
1814e3adcf8fSFrançois Tigeot 
1815a05eeebfSFrançois Tigeot 		kunmap_px(ppgtt, pt_vaddr);
1816e3adcf8fSFrançois Tigeot 
1817e3adcf8fSFrançois Tigeot 		num_entries -= last_pte - first_pte;
1818e3adcf8fSFrançois Tigeot 		first_pte = 0;
18198e26cdf6SFrançois Tigeot 		act_pt++;
1820e3adcf8fSFrançois Tigeot 	}
1821e3adcf8fSFrançois Tigeot }
1822e3adcf8fSFrançois Tigeot 
18239edbd4a0SFrançois Tigeot static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
18247ec9f8e5SFrançois Tigeot 				      struct sg_table *pages,
1825ba55f2f5SFrançois Tigeot 				      uint64_t start,
182624edb884SFrançois Tigeot 				      enum i915_cache_level cache_level, u32 flags)
1827e3adcf8fSFrançois Tigeot {
18288621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
1829ba55f2f5SFrançois Tigeot 	unsigned first_entry = start >> PAGE_SHIFT;
1830477eb7f9SFrançois Tigeot 	unsigned act_pt = first_entry / GEN6_PTES;
1831477eb7f9SFrançois Tigeot 	unsigned act_pte = first_entry % GEN6_PTES;
18321487f786SFrançois Tigeot 	gen6_pte_t *pt_vaddr = NULL;
18331487f786SFrançois Tigeot 	struct sgt_iter sgt_iter;
18341487f786SFrançois Tigeot 	dma_addr_t addr;
1835a2fdbec6SFrançois Tigeot 
18361487f786SFrançois Tigeot 	for_each_sgt_dma(addr, sgt_iter, pages) {
18379edbd4a0SFrançois Tigeot 		if (pt_vaddr == NULL)
1838a05eeebfSFrançois Tigeot 			pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]);
1839a2fdbec6SFrançois Tigeot 
18409edbd4a0SFrançois Tigeot 		pt_vaddr[act_pte] =
18411487f786SFrançois Tigeot 			vm->pte_encode(addr, cache_level, true, flags);
1842477eb7f9SFrançois Tigeot 
1843477eb7f9SFrançois Tigeot 		if (++act_pte == GEN6_PTES) {
1844a05eeebfSFrançois Tigeot 			kunmap_px(ppgtt, pt_vaddr);
18459edbd4a0SFrançois Tigeot 			pt_vaddr = NULL;
18468e26cdf6SFrançois Tigeot 			act_pt++;
18479edbd4a0SFrançois Tigeot 			act_pte = 0;
1848a2fdbec6SFrançois Tigeot 		}
1849a2fdbec6SFrançois Tigeot 	}
18501487f786SFrançois Tigeot 
18519edbd4a0SFrançois Tigeot 	if (pt_vaddr)
1852a05eeebfSFrançois Tigeot 		kunmap_px(ppgtt, pt_vaddr);
1853a2fdbec6SFrançois Tigeot }
1854477eb7f9SFrançois Tigeot 
1855477eb7f9SFrançois Tigeot static int gen6_alloc_va_range(struct i915_address_space *vm,
1856a05eeebfSFrançois Tigeot 			       uint64_t start_in, uint64_t length_in)
1857477eb7f9SFrançois Tigeot {
1858477eb7f9SFrançois Tigeot 	DECLARE_BITMAP(new_page_tables, I915_PDES);
1859477eb7f9SFrançois Tigeot 	struct drm_device *dev = vm->dev;
18608621f407SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
18618621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
18628621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
186319c468b4SFrançois Tigeot 	struct i915_page_table *pt;
1864a05eeebfSFrançois Tigeot 	uint32_t start, length, start_save, length_save;
18651487f786SFrançois Tigeot 	uint32_t pde;
1866477eb7f9SFrançois Tigeot 	int ret;
1867477eb7f9SFrançois Tigeot 
1868a05eeebfSFrançois Tigeot 	if (WARN_ON(start_in + length_in > ppgtt->base.total))
1869a05eeebfSFrançois Tigeot 		return -ENODEV;
1870a05eeebfSFrançois Tigeot 
1871a05eeebfSFrançois Tigeot 	start = start_save = start_in;
1872a05eeebfSFrançois Tigeot 	length = length_save = length_in;
1873477eb7f9SFrançois Tigeot 
1874477eb7f9SFrançois Tigeot 	bitmap_zero(new_page_tables, I915_PDES);
1875477eb7f9SFrançois Tigeot 
1876477eb7f9SFrançois Tigeot 	/* The allocation is done in two stages so that we can bail out with
1877477eb7f9SFrançois Tigeot 	 * minimal amount of pain. The first stage finds new page tables that
1878477eb7f9SFrançois Tigeot 	 * need allocation. The second stage marks use ptes within the page
1879477eb7f9SFrançois Tigeot 	 * tables.
1880477eb7f9SFrançois Tigeot 	 */
18811487f786SFrançois Tigeot 	gen6_for_each_pde(pt, &ppgtt->pd, start, length, pde) {
1882a05eeebfSFrançois Tigeot 		if (pt != vm->scratch_pt) {
1883056b1c44SFrançois Tigeot 			WARN_ON(bitmap_empty(pt->used_ptes, GEN6_PTES));
1884477eb7f9SFrançois Tigeot 			continue;
1885477eb7f9SFrançois Tigeot 		}
1886477eb7f9SFrançois Tigeot 
1887477eb7f9SFrançois Tigeot 		/* We've already allocated a page table */
1888477eb7f9SFrançois Tigeot 		WARN_ON(!bitmap_empty(pt->used_ptes, GEN6_PTES));
1889477eb7f9SFrançois Tigeot 
1890a05eeebfSFrançois Tigeot 		pt = alloc_pt(dev);
1891477eb7f9SFrançois Tigeot 		if (IS_ERR(pt)) {
1892477eb7f9SFrançois Tigeot 			ret = PTR_ERR(pt);
1893477eb7f9SFrançois Tigeot 			goto unwind_out;
1894477eb7f9SFrançois Tigeot 		}
1895477eb7f9SFrançois Tigeot 
1896477eb7f9SFrançois Tigeot 		gen6_initialize_pt(vm, pt);
1897477eb7f9SFrançois Tigeot 
1898477eb7f9SFrançois Tigeot 		ppgtt->pd.page_table[pde] = pt;
1899a05eeebfSFrançois Tigeot 		__set_bit(pde, new_page_tables);
1900477eb7f9SFrançois Tigeot 		trace_i915_page_table_entry_alloc(vm, pde, start, GEN6_PDE_SHIFT);
1901477eb7f9SFrançois Tigeot 	}
1902477eb7f9SFrançois Tigeot 
1903477eb7f9SFrançois Tigeot 	start = start_save;
1904477eb7f9SFrançois Tigeot 	length = length_save;
1905477eb7f9SFrançois Tigeot 
19061487f786SFrançois Tigeot 	gen6_for_each_pde(pt, &ppgtt->pd, start, length, pde) {
1907477eb7f9SFrançois Tigeot 		DECLARE_BITMAP(tmp_bitmap, GEN6_PTES);
1908477eb7f9SFrançois Tigeot 
1909477eb7f9SFrançois Tigeot 		bitmap_zero(tmp_bitmap, GEN6_PTES);
1910477eb7f9SFrançois Tigeot 		bitmap_set(tmp_bitmap, gen6_pte_index(start),
1911477eb7f9SFrançois Tigeot 			   gen6_pte_count(start, length));
1912477eb7f9SFrançois Tigeot 
1913a05eeebfSFrançois Tigeot 		if (__test_and_clear_bit(pde, new_page_tables))
1914477eb7f9SFrançois Tigeot 			gen6_write_pde(&ppgtt->pd, pde, pt);
1915477eb7f9SFrançois Tigeot 
1916477eb7f9SFrançois Tigeot 		trace_i915_page_table_entry_map(vm, pde, pt,
1917477eb7f9SFrançois Tigeot 					 gen6_pte_index(start),
1918477eb7f9SFrançois Tigeot 					 gen6_pte_count(start, length),
1919477eb7f9SFrançois Tigeot 					 GEN6_PTES);
1920477eb7f9SFrançois Tigeot 		bitmap_or(pt->used_ptes, tmp_bitmap, pt->used_ptes,
1921477eb7f9SFrançois Tigeot 				GEN6_PTES);
1922477eb7f9SFrançois Tigeot 	}
1923477eb7f9SFrançois Tigeot 
1924477eb7f9SFrançois Tigeot 	WARN_ON(!bitmap_empty(new_page_tables, I915_PDES));
1925477eb7f9SFrançois Tigeot 
1926477eb7f9SFrançois Tigeot 	/* Make sure write is complete before other code can use this page
1927477eb7f9SFrançois Tigeot 	 * table. Also require for WC mapped PTEs */
19288621f407SFrançois Tigeot 	readl(ggtt->gsm);
1929477eb7f9SFrançois Tigeot 
1930477eb7f9SFrançois Tigeot 	mark_tlbs_dirty(ppgtt);
1931477eb7f9SFrançois Tigeot 	return 0;
1932477eb7f9SFrançois Tigeot 
1933477eb7f9SFrançois Tigeot unwind_out:
1934477eb7f9SFrançois Tigeot 	for_each_set_bit(pde, new_page_tables, I915_PDES) {
193519c468b4SFrançois Tigeot 		struct i915_page_table *pt = ppgtt->pd.page_table[pde];
1936477eb7f9SFrançois Tigeot 
1937a05eeebfSFrançois Tigeot 		ppgtt->pd.page_table[pde] = vm->scratch_pt;
1938a05eeebfSFrançois Tigeot 		free_pt(vm->dev, pt);
1939477eb7f9SFrançois Tigeot 	}
1940477eb7f9SFrançois Tigeot 
1941477eb7f9SFrançois Tigeot 	mark_tlbs_dirty(ppgtt);
1942477eb7f9SFrançois Tigeot 	return ret;
1943ba55f2f5SFrançois Tigeot }
1944ba55f2f5SFrançois Tigeot 
1945a05eeebfSFrançois Tigeot static int gen6_init_scratch(struct i915_address_space *vm)
1946a05eeebfSFrançois Tigeot {
1947a05eeebfSFrançois Tigeot 	struct drm_device *dev = vm->dev;
1948a05eeebfSFrançois Tigeot 
1949a05eeebfSFrançois Tigeot 	vm->scratch_page = alloc_scratch_page(dev);
1950a05eeebfSFrançois Tigeot 	if (IS_ERR(vm->scratch_page))
1951a05eeebfSFrançois Tigeot 		return PTR_ERR(vm->scratch_page);
1952a05eeebfSFrançois Tigeot 
1953a05eeebfSFrançois Tigeot 	vm->scratch_pt = alloc_pt(dev);
1954a05eeebfSFrançois Tigeot 	if (IS_ERR(vm->scratch_pt)) {
1955a05eeebfSFrançois Tigeot 		free_scratch_page(dev, vm->scratch_page);
1956a05eeebfSFrançois Tigeot 		return PTR_ERR(vm->scratch_pt);
1957a05eeebfSFrançois Tigeot 	}
1958a05eeebfSFrançois Tigeot 
1959a05eeebfSFrançois Tigeot 	gen6_initialize_pt(vm, vm->scratch_pt);
1960a05eeebfSFrançois Tigeot 
1961a05eeebfSFrançois Tigeot 	return 0;
1962a05eeebfSFrançois Tigeot }
1963a05eeebfSFrançois Tigeot 
1964a05eeebfSFrançois Tigeot static void gen6_free_scratch(struct i915_address_space *vm)
1965a05eeebfSFrançois Tigeot {
1966a05eeebfSFrançois Tigeot 	struct drm_device *dev = vm->dev;
1967a05eeebfSFrançois Tigeot 
1968a05eeebfSFrançois Tigeot 	free_pt(dev, vm->scratch_pt);
1969a05eeebfSFrançois Tigeot 	free_scratch_page(dev, vm->scratch_page);
1970a05eeebfSFrançois Tigeot }
1971a05eeebfSFrançois Tigeot 
1972ba55f2f5SFrançois Tigeot static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
1973ba55f2f5SFrançois Tigeot {
19748621f407SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
19751487f786SFrançois Tigeot 	struct i915_page_directory *pd = &ppgtt->pd;
19761487f786SFrançois Tigeot 	struct drm_device *dev = vm->dev;
197719c468b4SFrançois Tigeot 	struct i915_page_table *pt;
197819c468b4SFrançois Tigeot 	uint32_t pde;
197919c468b4SFrançois Tigeot 
1980ba55f2f5SFrançois Tigeot 	drm_mm_remove_node(&ppgtt->node);
1981ba55f2f5SFrançois Tigeot 
19821487f786SFrançois Tigeot 	gen6_for_all_pdes(pt, pd, pde)
1983a05eeebfSFrançois Tigeot 		if (pt != vm->scratch_pt)
19841487f786SFrançois Tigeot 			free_pt(dev, pt);
198519c468b4SFrançois Tigeot 
1986a05eeebfSFrançois Tigeot 	gen6_free_scratch(vm);
1987ba55f2f5SFrançois Tigeot }
1988ba55f2f5SFrançois Tigeot 
1989ba55f2f5SFrançois Tigeot static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
1990a2fdbec6SFrançois Tigeot {
1991a05eeebfSFrançois Tigeot 	struct i915_address_space *vm = &ppgtt->base;
19929edbd4a0SFrançois Tigeot 	struct drm_device *dev = ppgtt->base.dev;
19938621f407SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
19948621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
1995ba55f2f5SFrançois Tigeot 	bool retried = false;
1996ba55f2f5SFrançois Tigeot 	int ret;
1997e3adcf8fSFrançois Tigeot 
1998ba55f2f5SFrançois Tigeot 	/* PPGTT PDEs reside in the GGTT and consists of 512 entries. The
1999ba55f2f5SFrançois Tigeot 	 * allocator works in address space sizes, so it's multiplied by page
2000ba55f2f5SFrançois Tigeot 	 * size. We allocate at the top of the GTT to avoid fragmentation.
2001ba55f2f5SFrançois Tigeot 	 */
20028621f407SFrançois Tigeot 	BUG_ON(!drm_mm_initialized(&ggtt->base.mm));
2003477eb7f9SFrançois Tigeot 
2004a05eeebfSFrançois Tigeot 	ret = gen6_init_scratch(vm);
2005a05eeebfSFrançois Tigeot 	if (ret)
2006a05eeebfSFrançois Tigeot 		return ret;
2007477eb7f9SFrançois Tigeot 
2008ba55f2f5SFrançois Tigeot alloc:
20098621f407SFrançois Tigeot 	ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm,
2010ba55f2f5SFrançois Tigeot 						  &ppgtt->node, GEN6_PD_SIZE,
2011ba55f2f5SFrançois Tigeot 						  GEN6_PD_ALIGN, 0,
20128621f407SFrançois Tigeot 						  0, ggtt->base.total,
2013ba55f2f5SFrançois Tigeot 						  DRM_MM_TOPDOWN);
2014ba55f2f5SFrançois Tigeot 	if (ret == -ENOSPC && !retried) {
2015*71f41f3eSFrançois Tigeot 		ret = i915_gem_evict_something(&ggtt->base,
2016ba55f2f5SFrançois Tigeot 					       GEN6_PD_SIZE, GEN6_PD_ALIGN,
2017ba55f2f5SFrançois Tigeot 					       I915_CACHE_NONE,
20188621f407SFrançois Tigeot 					       0, ggtt->base.total,
2019ba55f2f5SFrançois Tigeot 					       0);
2020ba55f2f5SFrançois Tigeot 		if (ret)
2021477eb7f9SFrançois Tigeot 			goto err_out;
2022e3adcf8fSFrançois Tigeot 
2023ba55f2f5SFrançois Tigeot 		retried = true;
2024ba55f2f5SFrançois Tigeot 		goto alloc;
2025ba55f2f5SFrançois Tigeot 	}
2026ba55f2f5SFrançois Tigeot 
2027477eb7f9SFrançois Tigeot 	if (ret)
2028477eb7f9SFrançois Tigeot 		goto err_out;
2029477eb7f9SFrançois Tigeot 
2030477eb7f9SFrançois Tigeot 
20318621f407SFrançois Tigeot 	if (ppgtt->node.start < ggtt->mappable_end)
2032ba55f2f5SFrançois Tigeot 		DRM_DEBUG("Forced to use aperture for PDEs\n");
2033ba55f2f5SFrançois Tigeot 
2034ba55f2f5SFrançois Tigeot 	return 0;
2035477eb7f9SFrançois Tigeot 
2036477eb7f9SFrançois Tigeot err_out:
2037a05eeebfSFrançois Tigeot 	gen6_free_scratch(vm);
2038477eb7f9SFrançois Tigeot 	return ret;
2039ba55f2f5SFrançois Tigeot }
2040ba55f2f5SFrançois Tigeot 
2041ba55f2f5SFrançois Tigeot static int gen6_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt)
2042ba55f2f5SFrançois Tigeot {
2043477eb7f9SFrançois Tigeot 	return gen6_ppgtt_allocate_page_directories(ppgtt);
2044e3adcf8fSFrançois Tigeot }
2045e3adcf8fSFrançois Tigeot 
2046477eb7f9SFrançois Tigeot static void gen6_scratch_va_range(struct i915_hw_ppgtt *ppgtt,
2047477eb7f9SFrançois Tigeot 				  uint64_t start, uint64_t length)
2048ba55f2f5SFrançois Tigeot {
204919c468b4SFrançois Tigeot 	struct i915_page_table *unused;
20501487f786SFrançois Tigeot 	uint32_t pde;
20519edbd4a0SFrançois Tigeot 
20521487f786SFrançois Tigeot 	gen6_for_each_pde(unused, &ppgtt->pd, start, length, pde)
2053a05eeebfSFrançois Tigeot 		ppgtt->pd.page_table[pde] = ppgtt->base.scratch_pt;
20549edbd4a0SFrançois Tigeot }
2055ba55f2f5SFrançois Tigeot 
2056056b1c44SFrançois Tigeot static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
2057ba55f2f5SFrançois Tigeot {
2058ba55f2f5SFrançois Tigeot 	struct drm_device *dev = ppgtt->base.dev;
20598621f407SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
20608621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
2061ba55f2f5SFrançois Tigeot 	int ret;
2062ba55f2f5SFrançois Tigeot 
20638621f407SFrançois Tigeot 	ppgtt->base.pte_encode = ggtt->base.pte_encode;
2064303bf270SFrançois Tigeot 	if (intel_vgpu_active(dev_priv) || IS_GEN6(dev))
2065ba55f2f5SFrançois Tigeot 		ppgtt->switch_mm = gen6_mm_switch;
2066303bf270SFrançois Tigeot 	else if (IS_HASWELL(dev))
2067ba55f2f5SFrançois Tigeot 		ppgtt->switch_mm = hsw_mm_switch;
2068303bf270SFrançois Tigeot 	else if (IS_GEN7(dev))
2069ba55f2f5SFrançois Tigeot 		ppgtt->switch_mm = gen7_mm_switch;
2070303bf270SFrançois Tigeot 	else
2071ba55f2f5SFrançois Tigeot 		BUG();
2072ba55f2f5SFrançois Tigeot 
2073ba55f2f5SFrançois Tigeot 	ret = gen6_ppgtt_alloc(ppgtt);
2074ba55f2f5SFrançois Tigeot 	if (ret)
2075ba55f2f5SFrançois Tigeot 		return ret;
2076ba55f2f5SFrançois Tigeot 
20777ec9f8e5SFrançois Tigeot 	ppgtt->base.allocate_va_range = gen6_alloc_va_range;
2078ba55f2f5SFrançois Tigeot 	ppgtt->base.clear_range = gen6_ppgtt_clear_range;
2079ba55f2f5SFrançois Tigeot 	ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
208019c468b4SFrançois Tigeot 	ppgtt->base.unbind_vma = ppgtt_unbind_vma;
208119c468b4SFrançois Tigeot 	ppgtt->base.bind_vma = ppgtt_bind_vma;
2082ba55f2f5SFrançois Tigeot 	ppgtt->base.cleanup = gen6_ppgtt_cleanup;
2083ba55f2f5SFrançois Tigeot 	ppgtt->base.start = 0;
208419c468b4SFrançois Tigeot 	ppgtt->base.total = I915_PDES * GEN6_PTES * PAGE_SIZE;
2085ba55f2f5SFrançois Tigeot 	ppgtt->debug_dump = gen6_dump_ppgtt;
2086ba55f2f5SFrançois Tigeot 
2087a05eeebfSFrançois Tigeot 	ppgtt->pd.base.ggtt_offset =
2088477eb7f9SFrançois Tigeot 		ppgtt->node.start / PAGE_SIZE * sizeof(gen6_pte_t);
2089ba55f2f5SFrançois Tigeot 
20908621f407SFrançois Tigeot 	ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm +
2091a05eeebfSFrançois Tigeot 		ppgtt->pd.base.ggtt_offset / sizeof(gen6_pte_t);
2092477eb7f9SFrançois Tigeot 
2093477eb7f9SFrançois Tigeot 	gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total);
2094477eb7f9SFrançois Tigeot 
2095477eb7f9SFrançois Tigeot 	gen6_write_page_range(dev_priv, &ppgtt->pd, 0, ppgtt->base.total);
2096ba55f2f5SFrançois Tigeot 
2097f77dbd6cSFrançois Tigeot 	DRM_DEBUG_DRIVER("Allocated pde space (%lldM) at GTT entry: %llx\n",
2098ba55f2f5SFrançois Tigeot 			 ppgtt->node.size >> 20,
2099ba55f2f5SFrançois Tigeot 			 ppgtt->node.start / PAGE_SIZE);
2100ba55f2f5SFrançois Tigeot 
21011b13d190SFrançois Tigeot 	DRM_DEBUG("Adding PPGTT at offset %x\n",
2102a05eeebfSFrançois Tigeot 		  ppgtt->pd.base.ggtt_offset << 10);
21031b13d190SFrançois Tigeot 
2104ba55f2f5SFrançois Tigeot 	return 0;
2105ba55f2f5SFrançois Tigeot }
2106ba55f2f5SFrançois Tigeot 
2107*71f41f3eSFrançois Tigeot static int __hw_ppgtt_init(struct i915_hw_ppgtt *ppgtt,
2108*71f41f3eSFrançois Tigeot 			   struct drm_i915_private *dev_priv)
2109a2fdbec6SFrançois Tigeot {
2110*71f41f3eSFrançois Tigeot 	ppgtt->base.dev = &dev_priv->drm;
2111a2fdbec6SFrançois Tigeot 
2112*71f41f3eSFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen < 8)
2113056b1c44SFrançois Tigeot 		return gen6_ppgtt_init(ppgtt);
21148e26cdf6SFrançois Tigeot 	else
211519c468b4SFrançois Tigeot 		return gen8_ppgtt_init(ppgtt);
21161b13d190SFrançois Tigeot }
2117a05eeebfSFrançois Tigeot 
2118352ff8bdSFrançois Tigeot static void i915_address_space_init(struct i915_address_space *vm,
2119352ff8bdSFrançois Tigeot 				    struct drm_i915_private *dev_priv)
2120352ff8bdSFrançois Tigeot {
2121352ff8bdSFrançois Tigeot 	drm_mm_init(&vm->mm, vm->start, vm->total);
2122352ff8bdSFrançois Tigeot 	INIT_LIST_HEAD(&vm->active_list);
2123352ff8bdSFrançois Tigeot 	INIT_LIST_HEAD(&vm->inactive_list);
2124*71f41f3eSFrançois Tigeot 	INIT_LIST_HEAD(&vm->unbound_list);
2125352ff8bdSFrançois Tigeot 	list_add_tail(&vm->global_link, &dev_priv->vm_list);
2126352ff8bdSFrançois Tigeot }
2127352ff8bdSFrançois Tigeot 
2128c0e85e96SFrançois Tigeot static void gtt_write_workarounds(struct drm_device *dev)
2129c0e85e96SFrançois Tigeot {
2130303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
2131c0e85e96SFrançois Tigeot 
2132c0e85e96SFrançois Tigeot 	/* This function is for gtt related workarounds. This function is
2133c0e85e96SFrançois Tigeot 	 * called on driver load and after a GPU reset, so you can place
2134c0e85e96SFrançois Tigeot 	 * workarounds here even if they get overwritten by GPU reset.
2135c0e85e96SFrançois Tigeot 	 */
2136c0e85e96SFrançois Tigeot 	/* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt */
2137c0e85e96SFrançois Tigeot 	if (IS_BROADWELL(dev))
2138c0e85e96SFrançois Tigeot 		I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW);
2139c0e85e96SFrançois Tigeot 	else if (IS_CHERRYVIEW(dev))
2140c0e85e96SFrançois Tigeot 		I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV);
2141c0e85e96SFrançois Tigeot 	else if (IS_SKYLAKE(dev))
2142c0e85e96SFrançois Tigeot 		I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL);
2143c0e85e96SFrançois Tigeot 	else if (IS_BROXTON(dev))
2144c0e85e96SFrançois Tigeot 		I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT);
2145c0e85e96SFrançois Tigeot }
2146c0e85e96SFrançois Tigeot 
2147*71f41f3eSFrançois Tigeot static int i915_ppgtt_init(struct i915_hw_ppgtt *ppgtt,
2148*71f41f3eSFrançois Tigeot 			   struct drm_i915_private *dev_priv,
2149*71f41f3eSFrançois Tigeot 			   struct drm_i915_file_private *file_priv)
21501b13d190SFrançois Tigeot {
2151*71f41f3eSFrançois Tigeot 	int ret;
21521b13d190SFrançois Tigeot 
2153*71f41f3eSFrançois Tigeot 	ret = __hw_ppgtt_init(ppgtt, dev_priv);
21541b13d190SFrançois Tigeot 	if (ret == 0) {
2155ba55f2f5SFrançois Tigeot 		kref_init(&ppgtt->ref);
2156352ff8bdSFrançois Tigeot 		i915_address_space_init(&ppgtt->base, dev_priv);
2157*71f41f3eSFrançois Tigeot 		ppgtt->base.file = file_priv;
21581b13d190SFrançois Tigeot 	}
21591b13d190SFrançois Tigeot 
21601b13d190SFrançois Tigeot 	return ret;
21611b13d190SFrançois Tigeot }
21621b13d190SFrançois Tigeot 
21631b13d190SFrançois Tigeot int i915_ppgtt_init_hw(struct drm_device *dev)
21641b13d190SFrançois Tigeot {
2165c0e85e96SFrançois Tigeot 	gtt_write_workarounds(dev);
2166c0e85e96SFrançois Tigeot 
21671b13d190SFrançois Tigeot 	/* In the case of execlists, PPGTT is enabled by the context descriptor
21681b13d190SFrançois Tigeot 	 * and the PDPs are contained within the context itself.  We don't
21691b13d190SFrançois Tigeot 	 * need to do anything here. */
21701b13d190SFrançois Tigeot 	if (i915.enable_execlists)
21711b13d190SFrançois Tigeot 		return 0;
21721b13d190SFrançois Tigeot 
21731b13d190SFrançois Tigeot 	if (!USES_PPGTT(dev))
21741b13d190SFrançois Tigeot 		return 0;
21751b13d190SFrançois Tigeot 
21761b13d190SFrançois Tigeot 	if (IS_GEN6(dev))
21771b13d190SFrançois Tigeot 		gen6_ppgtt_enable(dev);
21781b13d190SFrançois Tigeot 	else if (IS_GEN7(dev))
21791b13d190SFrançois Tigeot 		gen7_ppgtt_enable(dev);
21801b13d190SFrançois Tigeot 	else if (INTEL_INFO(dev)->gen >= 8)
21811b13d190SFrançois Tigeot 		gen8_ppgtt_enable(dev);
21821b13d190SFrançois Tigeot 	else
21832c9916cdSFrançois Tigeot 		MISSING_CASE(INTEL_INFO(dev)->gen);
21841b13d190SFrançois Tigeot 
2185a05eeebfSFrançois Tigeot 	return 0;
21869edbd4a0SFrançois Tigeot }
2187a2fdbec6SFrançois Tigeot 
21881b13d190SFrançois Tigeot struct i915_hw_ppgtt *
2189*71f41f3eSFrançois Tigeot i915_ppgtt_create(struct drm_i915_private *dev_priv,
2190*71f41f3eSFrançois Tigeot 		  struct drm_i915_file_private *fpriv)
21911b13d190SFrançois Tigeot {
21921b13d190SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt;
21931b13d190SFrançois Tigeot 	int ret;
21941b13d190SFrançois Tigeot 
21951b13d190SFrançois Tigeot 	ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
21961b13d190SFrançois Tigeot 	if (!ppgtt)
21971b13d190SFrançois Tigeot 		return ERR_PTR(-ENOMEM);
21981b13d190SFrançois Tigeot 
2199*71f41f3eSFrançois Tigeot 	ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv);
22001b13d190SFrançois Tigeot 	if (ret) {
22011b13d190SFrançois Tigeot 		kfree(ppgtt);
22021b13d190SFrançois Tigeot 		return ERR_PTR(ret);
22031b13d190SFrançois Tigeot 	}
22041b13d190SFrançois Tigeot 
22052c9916cdSFrançois Tigeot 	trace_i915_ppgtt_create(&ppgtt->base);
22062c9916cdSFrançois Tigeot 
22071b13d190SFrançois Tigeot 	return ppgtt;
22081b13d190SFrançois Tigeot }
22091b13d190SFrançois Tigeot 
22101b13d190SFrançois Tigeot void  i915_ppgtt_release(struct kref *kref)
22111b13d190SFrançois Tigeot {
22121b13d190SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt =
22131b13d190SFrançois Tigeot 		container_of(kref, struct i915_hw_ppgtt, ref);
22141b13d190SFrançois Tigeot 
22152c9916cdSFrançois Tigeot 	trace_i915_ppgtt_release(&ppgtt->base);
22162c9916cdSFrançois Tigeot 
2217*71f41f3eSFrançois Tigeot 	/* vmas should already be unbound and destroyed */
22181b13d190SFrançois Tigeot 	WARN_ON(!list_empty(&ppgtt->base.active_list));
22191b13d190SFrançois Tigeot 	WARN_ON(!list_empty(&ppgtt->base.inactive_list));
2220*71f41f3eSFrançois Tigeot 	WARN_ON(!list_empty(&ppgtt->base.unbound_list));
22211b13d190SFrançois Tigeot 
22221b13d190SFrançois Tigeot 	list_del(&ppgtt->base.global_link);
22231b13d190SFrançois Tigeot 	drm_mm_takedown(&ppgtt->base.mm);
22241b13d190SFrançois Tigeot 
22251b13d190SFrançois Tigeot 	ppgtt->base.cleanup(&ppgtt->base);
22261b13d190SFrançois Tigeot 	kfree(ppgtt);
22271b13d190SFrançois Tigeot }
2228a2fdbec6SFrançois Tigeot 
2229a2fdbec6SFrançois Tigeot /* Certain Gen5 chipsets require require idling the GPU before
2230a2fdbec6SFrançois Tigeot  * unmapping anything from the GTT when VT-d is enabled.
2231a2fdbec6SFrançois Tigeot  */
2232*71f41f3eSFrançois Tigeot static bool needs_idle_maps(struct drm_i915_private *dev_priv)
2233a2fdbec6SFrançois Tigeot {
2234a2fdbec6SFrançois Tigeot #ifdef CONFIG_INTEL_IOMMU
2235a2fdbec6SFrançois Tigeot 	/* Query intel_iommu to see if we need the workaround. Presumably that
2236a2fdbec6SFrançois Tigeot 	 * was loaded first.
2237a2fdbec6SFrançois Tigeot 	 */
2238*71f41f3eSFrançois Tigeot 	if (IS_GEN5(dev_priv) && IS_MOBILE(dev_priv) && intel_iommu_gfx_mapped)
2239a2fdbec6SFrançois Tigeot 		return true;
2240a2fdbec6SFrançois Tigeot #endif
2241a2fdbec6SFrançois Tigeot 	return false;
2242a2fdbec6SFrançois Tigeot }
2243a2fdbec6SFrançois Tigeot 
22441487f786SFrançois Tigeot void i915_check_and_clear_faults(struct drm_i915_private *dev_priv)
22459edbd4a0SFrançois Tigeot {
22468621f407SFrançois Tigeot 	struct intel_engine_cs *engine;
22479edbd4a0SFrançois Tigeot 
22481487f786SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen < 6)
22499edbd4a0SFrançois Tigeot 		return;
22509edbd4a0SFrançois Tigeot 
22518621f407SFrançois Tigeot 	for_each_engine(engine, dev_priv) {
22529edbd4a0SFrançois Tigeot 		u32 fault_reg;
22538621f407SFrançois Tigeot 		fault_reg = I915_READ(RING_FAULT_REG(engine));
22549edbd4a0SFrançois Tigeot 		if (fault_reg & RING_FAULT_VALID) {
22559edbd4a0SFrançois Tigeot 			DRM_DEBUG_DRIVER("Unexpected fault\n"
2256d653c727SFrançois Tigeot 					 "\tAddr: 0x%08ux\n"
22579edbd4a0SFrançois Tigeot 					 "\tAddress space: %s\n"
22589edbd4a0SFrançois Tigeot 					 "\tSource ID: %d\n"
22599edbd4a0SFrançois Tigeot 					 "\tType: %d\n",
2260d653c727SFrançois Tigeot 					 fault_reg & LINUX_PAGE_MASK,
22619edbd4a0SFrançois Tigeot 					 fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT",
22629edbd4a0SFrançois Tigeot 					 RING_FAULT_SRCID(fault_reg),
22639edbd4a0SFrançois Tigeot 					 RING_FAULT_FAULT_TYPE(fault_reg));
22648621f407SFrançois Tigeot 			I915_WRITE(RING_FAULT_REG(engine),
22659edbd4a0SFrançois Tigeot 				   fault_reg & ~RING_FAULT_VALID);
22669edbd4a0SFrançois Tigeot 		}
22679edbd4a0SFrançois Tigeot 	}
22688621f407SFrançois Tigeot 	POSTING_READ(RING_FAULT_REG(&dev_priv->engine[RCS]));
22699edbd4a0SFrançois Tigeot }
22709edbd4a0SFrançois Tigeot 
227124edb884SFrançois Tigeot static void i915_ggtt_flush(struct drm_i915_private *dev_priv)
227224edb884SFrançois Tigeot {
22738621f407SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen < 6) {
227424edb884SFrançois Tigeot 		intel_gtt_chipset_flush();
227524edb884SFrançois Tigeot 	} else {
227624edb884SFrançois Tigeot 		I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
227724edb884SFrançois Tigeot 		POSTING_READ(GFX_FLSH_CNTL_GEN6);
227824edb884SFrançois Tigeot 	}
227924edb884SFrançois Tigeot }
228024edb884SFrançois Tigeot 
22819edbd4a0SFrançois Tigeot void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
22829edbd4a0SFrançois Tigeot {
22838621f407SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
22848621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
22859edbd4a0SFrançois Tigeot 
22869edbd4a0SFrançois Tigeot 	/* Don't bother messing with faults pre GEN6 as we have little
22879edbd4a0SFrançois Tigeot 	 * documentation supporting that it's a good idea.
22889edbd4a0SFrançois Tigeot 	 */
22899edbd4a0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen < 6)
22909edbd4a0SFrançois Tigeot 		return;
22919edbd4a0SFrançois Tigeot 
22921487f786SFrançois Tigeot 	i915_check_and_clear_faults(dev_priv);
22939edbd4a0SFrançois Tigeot 
22948621f407SFrançois Tigeot 	ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total,
22959edbd4a0SFrançois Tigeot 			     true);
229624edb884SFrançois Tigeot 
229724edb884SFrançois Tigeot 	i915_ggtt_flush(dev_priv);
22989edbd4a0SFrançois Tigeot }
22999edbd4a0SFrançois Tigeot 
23000b869d8aSFrançois Tigeot int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
23010b869d8aSFrançois Tigeot {
2302fb572d17SFrançois Tigeot 	if (!dma_map_sg(&obj->base.dev->pdev->dev,
23030b869d8aSFrançois Tigeot 			obj->pages->sgl, obj->pages->nents,
23040b869d8aSFrançois Tigeot 			PCI_DMA_BIDIRECTIONAL))
23050b869d8aSFrançois Tigeot 		return -ENOSPC;
23060b869d8aSFrançois Tigeot 
23070b869d8aSFrançois Tigeot 	return 0;
23080b869d8aSFrançois Tigeot }
23090b869d8aSFrançois Tigeot 
231019c468b4SFrançois Tigeot static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
2311e3adcf8fSFrançois Tigeot {
2312056b1c44SFrançois Tigeot #ifdef writeq
23139edbd4a0SFrançois Tigeot 	writeq(pte, addr);
23149edbd4a0SFrançois Tigeot #else
23159edbd4a0SFrançois Tigeot 	iowrite32((u32)pte, addr);
23169edbd4a0SFrançois Tigeot 	iowrite32(pte >> 32, addr + 4);
23179edbd4a0SFrançois Tigeot #endif
23187cbd1a46SFrançois Tigeot }
2319e3adcf8fSFrançois Tigeot 
23201487f786SFrançois Tigeot static void gen8_ggtt_insert_page(struct i915_address_space *vm,
23211487f786SFrançois Tigeot 				  dma_addr_t addr,
23221487f786SFrançois Tigeot 				  uint64_t offset,
23231487f786SFrançois Tigeot 				  enum i915_cache_level level,
23241487f786SFrançois Tigeot 				  u32 unused)
23251487f786SFrançois Tigeot {
23261487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(vm->dev);
23271487f786SFrançois Tigeot 	gen8_pte_t __iomem *pte =
23281487f786SFrançois Tigeot 		(gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
23291487f786SFrançois Tigeot 		(offset >> PAGE_SHIFT);
23301487f786SFrançois Tigeot 	int rpm_atomic_seq;
23311487f786SFrançois Tigeot 
23321487f786SFrançois Tigeot 	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
23331487f786SFrançois Tigeot 
23341487f786SFrançois Tigeot 	gen8_set_pte(pte, gen8_pte_encode(addr, level, true));
23351487f786SFrançois Tigeot 
23361487f786SFrançois Tigeot 	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
23371487f786SFrançois Tigeot 	POSTING_READ(GFX_FLSH_CNTL_GEN6);
23381487f786SFrançois Tigeot 
23391487f786SFrançois Tigeot 	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
23401487f786SFrançois Tigeot }
23411487f786SFrançois Tigeot 
23429edbd4a0SFrançois Tigeot static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
23437ec9f8e5SFrançois Tigeot 				     struct sg_table *st,
2344ba55f2f5SFrançois Tigeot 				     uint64_t start,
234524edb884SFrançois Tigeot 				     enum i915_cache_level level, u32 unused)
23469edbd4a0SFrançois Tigeot {
23478621f407SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(vm->dev);
23481487f786SFrançois Tigeot 	struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
23491487f786SFrançois Tigeot 	struct sgt_iter sgt_iter;
23501487f786SFrançois Tigeot 	gen8_pte_t __iomem *gtt_entries;
23511487f786SFrançois Tigeot 	gen8_pte_t gtt_entry;
23521487f786SFrançois Tigeot 	dma_addr_t addr;
2353aee94f86SFrançois Tigeot 	int rpm_atomic_seq;
23541487f786SFrançois Tigeot 	int i = 0;
2355aee94f86SFrançois Tigeot 
2356aee94f86SFrançois Tigeot 	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
23579edbd4a0SFrançois Tigeot 
23581487f786SFrançois Tigeot 	gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT);
23591487f786SFrançois Tigeot 
23601487f786SFrançois Tigeot 	for_each_sgt_dma(addr, sgt_iter, st) {
23611487f786SFrançois Tigeot 		gtt_entry = gen8_pte_encode(addr, level, true);
23621487f786SFrançois Tigeot 		gen8_set_pte(&gtt_entries[i++], gtt_entry);
23639edbd4a0SFrançois Tigeot 	}
23649edbd4a0SFrançois Tigeot 
23659edbd4a0SFrançois Tigeot 	/*
23669edbd4a0SFrançois Tigeot 	 * XXX: This serves as a posting read to make sure that the PTE has
23677cbd1a46SFrançois Tigeot 	 * actually been updated. There is some concern that even though
23687cbd1a46SFrançois Tigeot 	 * registers and PTEs are within the same BAR that they are potentially
23697cbd1a46SFrançois Tigeot 	 * of NUMA access patterns. Therefore, even with the way we assume
23707cbd1a46SFrançois Tigeot 	 * hardware should work, we must keep this posting read for paranoia.
23717cbd1a46SFrançois Tigeot 	 */
23727cbd1a46SFrançois Tigeot 	if (i != 0)
23731487f786SFrançois Tigeot 		WARN_ON(readq(&gtt_entries[i-1]) != gtt_entry);
23747cbd1a46SFrançois Tigeot 
23757cbd1a46SFrançois Tigeot 	/* This next bit makes the above posting read even more important. We
23767cbd1a46SFrançois Tigeot 	 * want to flush the TLBs only after we're certain all the PTE updates
23777cbd1a46SFrançois Tigeot 	 * have finished.
23787cbd1a46SFrançois Tigeot 	 */
23797cbd1a46SFrançois Tigeot 	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
23807cbd1a46SFrançois Tigeot 	POSTING_READ(GFX_FLSH_CNTL_GEN6);
2381aee94f86SFrançois Tigeot 
2382aee94f86SFrançois Tigeot 	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
2383aee94f86SFrançois Tigeot }
2384aee94f86SFrançois Tigeot 
2385aee94f86SFrançois Tigeot struct insert_entries {
2386aee94f86SFrançois Tigeot 	struct i915_address_space *vm;
2387aee94f86SFrançois Tigeot 	struct sg_table *st;
2388aee94f86SFrançois Tigeot 	uint64_t start;
2389aee94f86SFrançois Tigeot 	enum i915_cache_level level;
2390aee94f86SFrançois Tigeot 	u32 flags;
2391aee94f86SFrançois Tigeot };
2392aee94f86SFrançois Tigeot 
2393aee94f86SFrançois Tigeot static int gen8_ggtt_insert_entries__cb(void *_arg)
2394aee94f86SFrançois Tigeot {
2395aee94f86SFrançois Tigeot 	struct insert_entries *arg = _arg;
2396aee94f86SFrançois Tigeot 	gen8_ggtt_insert_entries(arg->vm, arg->st,
2397aee94f86SFrançois Tigeot 				 arg->start, arg->level, arg->flags);
2398aee94f86SFrançois Tigeot 	return 0;
2399aee94f86SFrançois Tigeot }
2400aee94f86SFrançois Tigeot 
2401aee94f86SFrançois Tigeot static void gen8_ggtt_insert_entries__BKL(struct i915_address_space *vm,
2402aee94f86SFrançois Tigeot 					  struct sg_table *st,
2403aee94f86SFrançois Tigeot 					  uint64_t start,
2404aee94f86SFrançois Tigeot 					  enum i915_cache_level level,
2405aee94f86SFrançois Tigeot 					  u32 flags)
2406aee94f86SFrançois Tigeot {
2407aee94f86SFrançois Tigeot 	struct insert_entries arg = { vm, st, start, level, flags };
2408aee94f86SFrançois Tigeot 	stop_machine(gen8_ggtt_insert_entries__cb, &arg, NULL);
2409a2fdbec6SFrançois Tigeot }
2410a2fdbec6SFrançois Tigeot 
24111487f786SFrançois Tigeot static void gen6_ggtt_insert_page(struct i915_address_space *vm,
24121487f786SFrançois Tigeot 				  dma_addr_t addr,
24131487f786SFrançois Tigeot 				  uint64_t offset,
24141487f786SFrançois Tigeot 				  enum i915_cache_level level,
24151487f786SFrançois Tigeot 				  u32 flags)
24161487f786SFrançois Tigeot {
24171487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(vm->dev);
24181487f786SFrançois Tigeot 	gen6_pte_t __iomem *pte =
24191487f786SFrançois Tigeot 		(gen6_pte_t __iomem *)dev_priv->ggtt.gsm +
24201487f786SFrançois Tigeot 		(offset >> PAGE_SHIFT);
24211487f786SFrançois Tigeot 	int rpm_atomic_seq;
24221487f786SFrançois Tigeot 
24231487f786SFrançois Tigeot 	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
24241487f786SFrançois Tigeot 
24251487f786SFrançois Tigeot 	iowrite32(vm->pte_encode(addr, level, true, flags), pte);
24261487f786SFrançois Tigeot 
24271487f786SFrançois Tigeot 	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
24281487f786SFrançois Tigeot 	POSTING_READ(GFX_FLSH_CNTL_GEN6);
24291487f786SFrançois Tigeot 
24301487f786SFrançois Tigeot 	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
24311487f786SFrançois Tigeot }
24321487f786SFrançois Tigeot 
24339edbd4a0SFrançois Tigeot /*
24349edbd4a0SFrançois Tigeot  * Binds an object into the global gtt with the specified cache level. The object
24359edbd4a0SFrançois Tigeot  * will be accessible to the GPU via commands whose operands reference offsets
24369edbd4a0SFrançois Tigeot  * within the global GTT as well as accessible by the GPU through the GMADR
24379edbd4a0SFrançois Tigeot  * mapped BAR (dev_priv->mm.gtt->gtt).
24389edbd4a0SFrançois Tigeot  */
24399edbd4a0SFrançois Tigeot static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
24407ec9f8e5SFrançois Tigeot 				     struct sg_table *st,
2441ba55f2f5SFrançois Tigeot 				     uint64_t start,
244224edb884SFrançois Tigeot 				     enum i915_cache_level level, u32 flags)
2443a2fdbec6SFrançois Tigeot {
24448621f407SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(vm->dev);
24451487f786SFrançois Tigeot 	struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
24461487f786SFrançois Tigeot 	struct sgt_iter sgt_iter;
24471487f786SFrançois Tigeot 	gen6_pte_t __iomem *gtt_entries;
24481487f786SFrançois Tigeot 	gen6_pte_t gtt_entry;
24491487f786SFrançois Tigeot 	dma_addr_t addr;
2450aee94f86SFrançois Tigeot 	int rpm_atomic_seq;
24511487f786SFrançois Tigeot 	int i = 0;
2452aee94f86SFrançois Tigeot 
2453aee94f86SFrançois Tigeot 	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
24549edbd4a0SFrançois Tigeot 
24551487f786SFrançois Tigeot 	gtt_entries = (gen6_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT);
24561487f786SFrançois Tigeot 
24571487f786SFrançois Tigeot 	for_each_sgt_dma(addr, sgt_iter, st) {
24581487f786SFrançois Tigeot 		gtt_entry = vm->pte_encode(addr, level, true, flags);
24591487f786SFrançois Tigeot 		iowrite32(gtt_entry, &gtt_entries[i++]);
24609edbd4a0SFrançois Tigeot 	}
24619edbd4a0SFrançois Tigeot 
24629edbd4a0SFrançois Tigeot 	/* XXX: This serves as a posting read to make sure that the PTE has
24639edbd4a0SFrançois Tigeot 	 * actually been updated. There is some concern that even though
24649edbd4a0SFrançois Tigeot 	 * registers and PTEs are within the same BAR that they are potentially
24659edbd4a0SFrançois Tigeot 	 * of NUMA access patterns. Therefore, even with the way we assume
24669edbd4a0SFrançois Tigeot 	 * hardware should work, we must keep this posting read for paranoia.
24679edbd4a0SFrançois Tigeot 	 */
24681487f786SFrançois Tigeot 	if (i != 0)
24691487f786SFrançois Tigeot 		WARN_ON(readl(&gtt_entries[i-1]) != gtt_entry);
24709edbd4a0SFrançois Tigeot 
24719edbd4a0SFrançois Tigeot 	/* This next bit makes the above posting read even more important. We
24729edbd4a0SFrançois Tigeot 	 * want to flush the TLBs only after we're certain all the PTE updates
24739edbd4a0SFrançois Tigeot 	 * have finished.
24749edbd4a0SFrançois Tigeot 	 */
24759edbd4a0SFrançois Tigeot 	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
24769edbd4a0SFrançois Tigeot 	POSTING_READ(GFX_FLSH_CNTL_GEN6);
2477aee94f86SFrançois Tigeot 
2478aee94f86SFrançois Tigeot 	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
24799edbd4a0SFrançois Tigeot }
24809edbd4a0SFrançois Tigeot 
24811487f786SFrançois Tigeot static void nop_clear_range(struct i915_address_space *vm,
24821487f786SFrançois Tigeot 			    uint64_t start,
24831487f786SFrançois Tigeot 			    uint64_t length,
24841487f786SFrançois Tigeot 			    bool use_scratch)
24851487f786SFrançois Tigeot {
24861487f786SFrançois Tigeot }
24871487f786SFrançois Tigeot 
24889edbd4a0SFrançois Tigeot static void gen8_ggtt_clear_range(struct i915_address_space *vm,
2489ba55f2f5SFrançois Tigeot 				  uint64_t start,
2490ba55f2f5SFrançois Tigeot 				  uint64_t length,
24919edbd4a0SFrançois Tigeot 				  bool use_scratch)
24929edbd4a0SFrançois Tigeot {
24938621f407SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(vm->dev);
24941487f786SFrançois Tigeot 	struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
2495ba55f2f5SFrançois Tigeot 	unsigned first_entry = start >> PAGE_SHIFT;
2496ba55f2f5SFrançois Tigeot 	unsigned num_entries = length >> PAGE_SHIFT;
2497477eb7f9SFrançois Tigeot 	gen8_pte_t scratch_pte, __iomem *gtt_base =
24988621f407SFrançois Tigeot 		(gen8_pte_t __iomem *)ggtt->gsm + first_entry;
24998621f407SFrançois Tigeot 	const int max_entries = ggtt_total_entries(ggtt) - first_entry;
25009edbd4a0SFrançois Tigeot 	int i;
2501aee94f86SFrançois Tigeot 	int rpm_atomic_seq;
2502aee94f86SFrançois Tigeot 
2503aee94f86SFrançois Tigeot 	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
25049edbd4a0SFrançois Tigeot 
25059edbd4a0SFrançois Tigeot 	if (WARN(num_entries > max_entries,
25069edbd4a0SFrançois Tigeot 		 "First entry = %d; Num entries = %d (max=%d)\n",
25079edbd4a0SFrançois Tigeot 		 first_entry, num_entries, max_entries))
25089edbd4a0SFrançois Tigeot 		num_entries = max_entries;
25099edbd4a0SFrançois Tigeot 
2510a05eeebfSFrançois Tigeot 	scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
25119edbd4a0SFrançois Tigeot 				      I915_CACHE_LLC,
25129edbd4a0SFrançois Tigeot 				      use_scratch);
25139edbd4a0SFrançois Tigeot 	for (i = 0; i < num_entries; i++)
25149edbd4a0SFrançois Tigeot 		gen8_set_pte(&gtt_base[i], scratch_pte);
25159edbd4a0SFrançois Tigeot 	readl(gtt_base);
2516aee94f86SFrançois Tigeot 
2517aee94f86SFrançois Tigeot 	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
25189edbd4a0SFrançois Tigeot }
25199edbd4a0SFrançois Tigeot 
25209edbd4a0SFrançois Tigeot static void gen6_ggtt_clear_range(struct i915_address_space *vm,
2521ba55f2f5SFrançois Tigeot 				  uint64_t start,
2522ba55f2f5SFrançois Tigeot 				  uint64_t length,
25239edbd4a0SFrançois Tigeot 				  bool use_scratch)
25249edbd4a0SFrançois Tigeot {
25258621f407SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(vm->dev);
25261487f786SFrançois Tigeot 	struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
2527ba55f2f5SFrançois Tigeot 	unsigned first_entry = start >> PAGE_SHIFT;
2528ba55f2f5SFrançois Tigeot 	unsigned num_entries = length >> PAGE_SHIFT;
2529477eb7f9SFrançois Tigeot 	gen6_pte_t scratch_pte, __iomem *gtt_base =
25308621f407SFrançois Tigeot 		(gen6_pte_t __iomem *)ggtt->gsm + first_entry;
25318621f407SFrançois Tigeot 	const int max_entries = ggtt_total_entries(ggtt) - first_entry;
2532a2fdbec6SFrançois Tigeot 	int i;
2533aee94f86SFrançois Tigeot 	int rpm_atomic_seq;
2534aee94f86SFrançois Tigeot 
2535aee94f86SFrançois Tigeot 	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
2536a2fdbec6SFrançois Tigeot 
2537a2fdbec6SFrançois Tigeot 	if (WARN(num_entries > max_entries,
2538a2fdbec6SFrançois Tigeot 		 "First entry = %d; Num entries = %d (max=%d)\n",
2539a2fdbec6SFrançois Tigeot 		 first_entry, num_entries, max_entries))
2540a2fdbec6SFrançois Tigeot 		num_entries = max_entries;
2541a2fdbec6SFrançois Tigeot 
2542a05eeebfSFrançois Tigeot 	scratch_pte = vm->pte_encode(px_dma(vm->scratch_page),
2543a05eeebfSFrançois Tigeot 				     I915_CACHE_LLC, use_scratch, 0);
25449edbd4a0SFrançois Tigeot 
2545a2fdbec6SFrançois Tigeot 	for (i = 0; i < num_entries; i++)
2546a2fdbec6SFrançois Tigeot 		iowrite32(scratch_pte, &gtt_base[i]);
2547a2fdbec6SFrançois Tigeot 	readl(gtt_base);
2548aee94f86SFrançois Tigeot 
2549aee94f86SFrançois Tigeot 	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
2550a2fdbec6SFrançois Tigeot }
2551a2fdbec6SFrançois Tigeot 
25521487f786SFrançois Tigeot static void i915_ggtt_insert_page(struct i915_address_space *vm,
25531487f786SFrançois Tigeot 				  dma_addr_t addr,
25541487f786SFrançois Tigeot 				  uint64_t offset,
25551487f786SFrançois Tigeot 				  enum i915_cache_level cache_level,
25561487f786SFrançois Tigeot 				  u32 unused)
25571487f786SFrançois Tigeot {
25581487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(vm->dev);
25591487f786SFrançois Tigeot 	unsigned int flags = (cache_level == I915_CACHE_NONE) ?
25601487f786SFrançois Tigeot 		AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
25611487f786SFrançois Tigeot 	int rpm_atomic_seq;
25621487f786SFrançois Tigeot 
25631487f786SFrançois Tigeot 	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
25641487f786SFrançois Tigeot 
25651487f786SFrançois Tigeot 	intel_gtt_insert_page(addr, offset >> PAGE_SHIFT, flags);
25661487f786SFrançois Tigeot 
25671487f786SFrançois Tigeot 	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
25681487f786SFrançois Tigeot }
25691487f786SFrançois Tigeot 
25707ec9f8e5SFrançois Tigeot static void i915_ggtt_insert_entries(struct i915_address_space *vm,
25717ec9f8e5SFrançois Tigeot 				     struct sg_table *pages,
25727ec9f8e5SFrançois Tigeot 				     uint64_t start,
25737ec9f8e5SFrançois Tigeot 				     enum i915_cache_level cache_level, u32 unused)
2574a2fdbec6SFrançois Tigeot {
2575303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(vm->dev);
2576a2fdbec6SFrançois Tigeot 	unsigned int flags = (cache_level == I915_CACHE_NONE) ?
2577a2fdbec6SFrançois Tigeot 		AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
2578aee94f86SFrançois Tigeot 	int rpm_atomic_seq;
2579aee94f86SFrançois Tigeot 
2580aee94f86SFrançois Tigeot 	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
2581a2fdbec6SFrançois Tigeot 
25827ec9f8e5SFrançois Tigeot 	intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags);
2583056b1c44SFrançois Tigeot 
2584aee94f86SFrançois Tigeot 	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
2585aee94f86SFrançois Tigeot 
2586a2fdbec6SFrançois Tigeot }
2587a2fdbec6SFrançois Tigeot 
25889edbd4a0SFrançois Tigeot static void i915_ggtt_clear_range(struct i915_address_space *vm,
2589ba55f2f5SFrançois Tigeot 				  uint64_t start,
2590ba55f2f5SFrançois Tigeot 				  uint64_t length,
25919edbd4a0SFrançois Tigeot 				  bool unused)
2592a2fdbec6SFrançois Tigeot {
2593303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(vm->dev);
2594ba55f2f5SFrançois Tigeot 	unsigned first_entry = start >> PAGE_SHIFT;
2595ba55f2f5SFrançois Tigeot 	unsigned num_entries = length >> PAGE_SHIFT;
2596aee94f86SFrançois Tigeot 	int rpm_atomic_seq;
2597aee94f86SFrançois Tigeot 
2598aee94f86SFrançois Tigeot 	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
2599aee94f86SFrançois Tigeot 
2600a2fdbec6SFrançois Tigeot 	intel_gtt_clear_range(first_entry, num_entries);
2601aee94f86SFrançois Tigeot 
2602aee94f86SFrançois Tigeot 	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
2603a2fdbec6SFrançois Tigeot }
26047cbd1a46SFrançois Tigeot 
260519c468b4SFrançois Tigeot static int ggtt_bind_vma(struct i915_vma *vma,
2606ba55f2f5SFrançois Tigeot 			 enum i915_cache_level cache_level,
2607ba55f2f5SFrançois Tigeot 			 u32 flags)
2608e3adcf8fSFrançois Tigeot {
2609352ff8bdSFrançois Tigeot 	struct drm_i915_gem_object *obj = vma->obj;
2610352ff8bdSFrançois Tigeot 	u32 pte_flags = 0;
2611352ff8bdSFrançois Tigeot 	int ret;
2612352ff8bdSFrançois Tigeot 
2613352ff8bdSFrançois Tigeot 	ret = i915_get_ggtt_vma_pages(vma);
2614352ff8bdSFrançois Tigeot 	if (ret)
2615352ff8bdSFrançois Tigeot 		return ret;
2616352ff8bdSFrançois Tigeot 
2617352ff8bdSFrançois Tigeot 	/* Currently applicable only to VLV */
2618352ff8bdSFrançois Tigeot 	if (obj->gt_ro)
2619352ff8bdSFrançois Tigeot 		pte_flags |= PTE_READ_ONLY;
2620352ff8bdSFrançois Tigeot 
2621352ff8bdSFrançois Tigeot 	vma->vm->insert_entries(vma->vm, vma->ggtt_view.pages,
2622352ff8bdSFrançois Tigeot 				vma->node.start,
2623352ff8bdSFrançois Tigeot 				cache_level, pte_flags);
2624352ff8bdSFrançois Tigeot 
2625352ff8bdSFrançois Tigeot 	/*
2626352ff8bdSFrançois Tigeot 	 * Without aliasing PPGTT there's no difference between
2627352ff8bdSFrançois Tigeot 	 * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
2628352ff8bdSFrançois Tigeot 	 * upgrade to both bound if we bind either to avoid double-binding.
2629352ff8bdSFrançois Tigeot 	 */
2630*71f41f3eSFrançois Tigeot 	vma->flags |= I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
2631352ff8bdSFrançois Tigeot 
2632352ff8bdSFrançois Tigeot 	return 0;
2633352ff8bdSFrançois Tigeot }
2634352ff8bdSFrançois Tigeot 
2635352ff8bdSFrançois Tigeot static int aliasing_gtt_bind_vma(struct i915_vma *vma,
2636352ff8bdSFrançois Tigeot 				 enum i915_cache_level cache_level,
2637352ff8bdSFrançois Tigeot 				 u32 flags)
2638352ff8bdSFrançois Tigeot {
26398621f407SFrançois Tigeot 	u32 pte_flags;
26407ec9f8e5SFrançois Tigeot 	int ret;
26417ec9f8e5SFrançois Tigeot 
26427ec9f8e5SFrançois Tigeot 	ret = i915_get_ggtt_vma_pages(vma);
26437ec9f8e5SFrançois Tigeot 	if (ret)
26447ec9f8e5SFrançois Tigeot 		return ret;
2645e3adcf8fSFrançois Tigeot 
264624edb884SFrançois Tigeot 	/* Currently applicable only to VLV */
26478621f407SFrançois Tigeot 	pte_flags = 0;
26488621f407SFrançois Tigeot 	if (vma->obj->gt_ro)
264919c468b4SFrançois Tigeot 		pte_flags |= PTE_READ_ONLY;
265024edb884SFrançois Tigeot 
2651477eb7f9SFrançois Tigeot 
2652*71f41f3eSFrançois Tigeot 	if (flags & I915_VMA_GLOBAL_BIND) {
26538621f407SFrançois Tigeot 		vma->vm->insert_entries(vma->vm,
26548621f407SFrançois Tigeot 					vma->ggtt_view.pages,
2655ba55f2f5SFrançois Tigeot 					vma->node.start,
265619c468b4SFrançois Tigeot 					cache_level, pte_flags);
2657ba55f2f5SFrançois Tigeot 	}
2658e3adcf8fSFrançois Tigeot 
2659*71f41f3eSFrançois Tigeot 	if (flags & I915_VMA_LOCAL_BIND) {
26608621f407SFrançois Tigeot 		struct i915_hw_ppgtt *appgtt =
26618621f407SFrançois Tigeot 			to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
26628621f407SFrançois Tigeot 		appgtt->base.insert_entries(&appgtt->base,
26638621f407SFrançois Tigeot 					    vma->ggtt_view.pages,
2664ba55f2f5SFrançois Tigeot 					    vma->node.start,
266519c468b4SFrançois Tigeot 					    cache_level, pte_flags);
2666ba55f2f5SFrançois Tigeot 	}
266719c468b4SFrançois Tigeot 
266819c468b4SFrançois Tigeot 	return 0;
2669ba55f2f5SFrançois Tigeot }
2670ba55f2f5SFrançois Tigeot 
2671ba55f2f5SFrançois Tigeot static void ggtt_unbind_vma(struct i915_vma *vma)
2672ba55f2f5SFrançois Tigeot {
2673*71f41f3eSFrançois Tigeot 	struct i915_hw_ppgtt *appgtt = to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
2674*71f41f3eSFrançois Tigeot 	const u64 size = min(vma->size, vma->node.size);
2675ba55f2f5SFrançois Tigeot 
2676*71f41f3eSFrançois Tigeot 	if (vma->flags & I915_VMA_GLOBAL_BIND)
2677ba55f2f5SFrançois Tigeot 		vma->vm->clear_range(vma->vm,
2678*71f41f3eSFrançois Tigeot 				     vma->node.start, size,
2679ba55f2f5SFrançois Tigeot 				     true);
2680f192107fSFrançois Tigeot 
2681*71f41f3eSFrançois Tigeot 	if (vma->flags & I915_VMA_LOCAL_BIND && appgtt)
2682ba55f2f5SFrançois Tigeot 		appgtt->base.clear_range(&appgtt->base,
2683*71f41f3eSFrançois Tigeot 					 vma->node.start, size,
2684ba55f2f5SFrançois Tigeot 					 true);
2685ba55f2f5SFrançois Tigeot }
2686ba55f2f5SFrançois Tigeot 
2687f192107fSFrançois Tigeot void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
2688f192107fSFrançois Tigeot {
2689f192107fSFrançois Tigeot 	struct drm_device *dev = obj->base.dev;
2690303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
2691*71f41f3eSFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
2692f192107fSFrançois Tigeot 
2693*71f41f3eSFrançois Tigeot 	if (unlikely(ggtt->do_idle_maps)) {
2694*71f41f3eSFrançois Tigeot 		if (i915_gem_wait_for_idle(dev_priv, false)) {
2695*71f41f3eSFrançois Tigeot 			DRM_ERROR("Failed to wait for idle; VT'd may hang.\n");
2696*71f41f3eSFrançois Tigeot 			/* Wait a bit, in hopes it avoids the hang */
2697*71f41f3eSFrançois Tigeot 			udelay(10);
2698*71f41f3eSFrançois Tigeot 		}
2699*71f41f3eSFrançois Tigeot 	}
2700f192107fSFrançois Tigeot 
2701fb572d17SFrançois Tigeot 	dma_unmap_sg(&dev->pdev->dev, obj->pages->sgl, obj->pages->nents,
2702f192107fSFrançois Tigeot 		     PCI_DMA_BIDIRECTIONAL);
2703f192107fSFrançois Tigeot }
2704d1c259eeSFrançois Tigeot 
2705d1c259eeSFrançois Tigeot static void i915_gtt_color_adjust(struct drm_mm_node *node,
2706d1c259eeSFrançois Tigeot 				  unsigned long color,
27072c9916cdSFrançois Tigeot 				  u64 *start,
27082c9916cdSFrançois Tigeot 				  u64 *end)
2709d1c259eeSFrançois Tigeot {
2710d1c259eeSFrançois Tigeot 	if (node->color != color)
2711d1c259eeSFrançois Tigeot 		*start += 4096;
2712d1c259eeSFrançois Tigeot 
2713*71f41f3eSFrançois Tigeot 	node = list_first_entry_or_null(&node->node_list,
2714d1c259eeSFrançois Tigeot 					struct drm_mm_node,
2715d1c259eeSFrançois Tigeot 					node_list);
2716*71f41f3eSFrançois Tigeot 	if (node && node->allocated && node->color != color)
2717d1c259eeSFrançois Tigeot 		*end -= 4096;
2718d1c259eeSFrançois Tigeot }
27199edbd4a0SFrançois Tigeot 
2720*71f41f3eSFrançois Tigeot int i915_gem_init_ggtt(struct drm_i915_private *dev_priv)
2721d1c259eeSFrançois Tigeot {
2722a2fdbec6SFrançois Tigeot 	/* Let GEM Manage all of the aperture.
2723a2fdbec6SFrançois Tigeot 	 *
2724a2fdbec6SFrançois Tigeot 	 * However, leave one page at the end still bound to the scratch page.
2725a2fdbec6SFrançois Tigeot 	 * There are a number of places where the hardware apparently prefetches
2726a2fdbec6SFrançois Tigeot 	 * past the end of the object, and we've seen multiple hangs with the
2727a2fdbec6SFrançois Tigeot 	 * GPU head pointer stuck in a batchbuffer bound at the last page of the
2728a2fdbec6SFrançois Tigeot 	 * aperture.  One page should be enough to keep any prefetching inside
2729a2fdbec6SFrançois Tigeot 	 * of the aperture.
2730a2fdbec6SFrançois Tigeot 	 */
27318621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
27329edbd4a0SFrançois Tigeot 	unsigned long hole_start, hole_end;
2733*71f41f3eSFrançois Tigeot 	struct drm_mm_node *entry;
27341b13d190SFrançois Tigeot 	int ret;
2735*71f41f3eSFrançois Tigeot 	unsigned long mappable = min(ggtt->base.total, ggtt->mappable_end);
2736477eb7f9SFrançois Tigeot 
27371487f786SFrançois Tigeot 	ret = intel_vgt_balloon(dev_priv);
2738477eb7f9SFrançois Tigeot 	if (ret)
2739477eb7f9SFrançois Tigeot 		return ret;
2740477eb7f9SFrançois Tigeot 
27419edbd4a0SFrançois Tigeot 	/* Clear any non-preallocated blocks */
27428621f407SFrançois Tigeot 	drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) {
27439edbd4a0SFrançois Tigeot 		DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
27449edbd4a0SFrançois Tigeot 			      hole_start, hole_end);
27458621f407SFrançois Tigeot 		ggtt->base.clear_range(&ggtt->base, hole_start,
2746ba55f2f5SFrançois Tigeot 				     hole_end - hole_start, true);
27479edbd4a0SFrançois Tigeot 	}
2748cb170299SFrançois Tigeot 
2749310880c6SSascha Wildner #ifdef __DragonFly__
2750*71f41f3eSFrançois Tigeot 	DRM_INFO("taking over the fictitious range 0x%llx-0x%llx\n",
2751*71f41f3eSFrançois Tigeot 	    dev_priv->ggtt.mappable_base, dev_priv->ggtt.mappable_end);
2752*71f41f3eSFrançois Tigeot 	vm_phys_fictitious_reg_range(dev_priv->ggtt.mappable_base,
2753*71f41f3eSFrançois Tigeot 	     dev_priv->ggtt.mappable_base + mappable, VM_MEMATTR_WRITE_COMBINING);
2754310880c6SSascha Wildner #endif
27559edbd4a0SFrançois Tigeot 
27569edbd4a0SFrançois Tigeot 	/* And finally clear the reserved guard page */
2757*71f41f3eSFrançois Tigeot 	ggtt->base.clear_range(&ggtt->base,
2758*71f41f3eSFrançois Tigeot 			       ggtt->base.total - PAGE_SIZE, PAGE_SIZE,
2759*71f41f3eSFrançois Tigeot 			       true);
27601b13d190SFrançois Tigeot 
2761*71f41f3eSFrançois Tigeot 	if (USES_PPGTT(dev_priv) && !USES_FULL_PPGTT(dev_priv)) {
27621b13d190SFrançois Tigeot 		struct i915_hw_ppgtt *ppgtt;
27631b13d190SFrançois Tigeot 
27641b13d190SFrançois Tigeot 		ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
27651b13d190SFrançois Tigeot 		if (!ppgtt)
27661b13d190SFrançois Tigeot 			return -ENOMEM;
27671b13d190SFrançois Tigeot 
2768*71f41f3eSFrançois Tigeot 		ret = __hw_ppgtt_init(ppgtt, dev_priv);
2769477eb7f9SFrançois Tigeot 		if (ret) {
2770477eb7f9SFrançois Tigeot 			kfree(ppgtt);
27711b13d190SFrançois Tigeot 			return ret;
2772477eb7f9SFrançois Tigeot 		}
27731b13d190SFrançois Tigeot 
27747ec9f8e5SFrançois Tigeot 		if (ppgtt->base.allocate_va_range)
27757ec9f8e5SFrançois Tigeot 			ret = ppgtt->base.allocate_va_range(&ppgtt->base, 0,
27767ec9f8e5SFrançois Tigeot 							    ppgtt->base.total);
27777ec9f8e5SFrançois Tigeot 		if (ret) {
27787ec9f8e5SFrançois Tigeot 			ppgtt->base.cleanup(&ppgtt->base);
27797ec9f8e5SFrançois Tigeot 			kfree(ppgtt);
27807ec9f8e5SFrançois Tigeot 			return ret;
27817ec9f8e5SFrançois Tigeot 		}
27827ec9f8e5SFrançois Tigeot 
27837ec9f8e5SFrançois Tigeot 		ppgtt->base.clear_range(&ppgtt->base,
27847ec9f8e5SFrançois Tigeot 					ppgtt->base.start,
27857ec9f8e5SFrançois Tigeot 					ppgtt->base.total,
27867ec9f8e5SFrançois Tigeot 					true);
27877ec9f8e5SFrançois Tigeot 
27881b13d190SFrançois Tigeot 		dev_priv->mm.aliasing_ppgtt = ppgtt;
27898621f407SFrançois Tigeot 		WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma);
27908621f407SFrançois Tigeot 		ggtt->base.bind_vma = aliasing_gtt_bind_vma;
27911b13d190SFrançois Tigeot 	}
27921b13d190SFrançois Tigeot 
27931b13d190SFrançois Tigeot 	return 0;
2794a2fdbec6SFrançois Tigeot }
2795a2fdbec6SFrançois Tigeot 
27968621f407SFrançois Tigeot /**
27978621f407SFrançois Tigeot  * i915_ggtt_cleanup_hw - Clean up GGTT hardware initialization
2798*71f41f3eSFrançois Tigeot  * @dev_priv: i915 device
27998621f407SFrançois Tigeot  */
2800*71f41f3eSFrançois Tigeot void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv)
28011b13d190SFrançois Tigeot {
28028621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
28031b13d190SFrançois Tigeot 
28041b13d190SFrançois Tigeot 	if (dev_priv->mm.aliasing_ppgtt) {
28051b13d190SFrançois Tigeot 		struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
28061b13d190SFrançois Tigeot 
28071b13d190SFrançois Tigeot 		ppgtt->base.cleanup(&ppgtt->base);
28088621f407SFrançois Tigeot 		kfree(ppgtt);
28091b13d190SFrançois Tigeot 	}
28101b13d190SFrançois Tigeot 
2811*71f41f3eSFrançois Tigeot 	i915_gem_cleanup_stolen(&dev_priv->drm);
2812c0e85e96SFrançois Tigeot 
28138621f407SFrançois Tigeot 	if (drm_mm_initialized(&ggtt->base.mm)) {
28141487f786SFrançois Tigeot 		intel_vgt_deballoon(dev_priv);
2815477eb7f9SFrançois Tigeot 
28168621f407SFrançois Tigeot 		drm_mm_takedown(&ggtt->base.mm);
28178621f407SFrançois Tigeot 		list_del(&ggtt->base.global_link);
28181b13d190SFrançois Tigeot 	}
28191b13d190SFrançois Tigeot 
28208621f407SFrançois Tigeot 	ggtt->base.cleanup(&ggtt->base);
2821*71f41f3eSFrançois Tigeot 
2822*71f41f3eSFrançois Tigeot 	arch_phys_wc_del(ggtt->mtrr);
2823*71f41f3eSFrançois Tigeot 	io_mapping_free(ggtt->mappable);
28241b13d190SFrançois Tigeot }
28251b13d190SFrançois Tigeot 
282619c468b4SFrançois Tigeot static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl)
28279edbd4a0SFrançois Tigeot {
28289edbd4a0SFrançois Tigeot 	snb_gmch_ctl >>= SNB_GMCH_GGMS_SHIFT;
28299edbd4a0SFrançois Tigeot 	snb_gmch_ctl &= SNB_GMCH_GGMS_MASK;
28309edbd4a0SFrançois Tigeot 	return snb_gmch_ctl << 20;
28319edbd4a0SFrançois Tigeot }
28329edbd4a0SFrançois Tigeot 
283319c468b4SFrançois Tigeot static unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl)
28349edbd4a0SFrançois Tigeot {
28359edbd4a0SFrançois Tigeot 	bdw_gmch_ctl >>= BDW_GMCH_GGMS_SHIFT;
28369edbd4a0SFrançois Tigeot 	bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK;
28379edbd4a0SFrançois Tigeot 	if (bdw_gmch_ctl)
28389edbd4a0SFrançois Tigeot 		bdw_gmch_ctl = 1 << bdw_gmch_ctl;
2839ba55f2f5SFrançois Tigeot 
2840ba55f2f5SFrançois Tigeot #ifdef CONFIG_X86_32
2841ba55f2f5SFrançois Tigeot 	/* Limit 32b platforms to a 2GB GGTT: 4 << 20 / pte size * PAGE_SIZE */
2842ba55f2f5SFrançois Tigeot 	if (bdw_gmch_ctl > 4)
2843ba55f2f5SFrançois Tigeot 		bdw_gmch_ctl = 4;
2844ba55f2f5SFrançois Tigeot #endif
28459edbd4a0SFrançois Tigeot 
28469edbd4a0SFrançois Tigeot 	return bdw_gmch_ctl << 20;
28479edbd4a0SFrançois Tigeot }
28489edbd4a0SFrançois Tigeot 
284919c468b4SFrançois Tigeot static unsigned int chv_get_total_gtt_size(u16 gmch_ctrl)
2850ba55f2f5SFrançois Tigeot {
2851ba55f2f5SFrançois Tigeot 	gmch_ctrl >>= SNB_GMCH_GGMS_SHIFT;
2852ba55f2f5SFrançois Tigeot 	gmch_ctrl &= SNB_GMCH_GGMS_MASK;
2853ba55f2f5SFrançois Tigeot 
2854ba55f2f5SFrançois Tigeot 	if (gmch_ctrl)
2855ba55f2f5SFrançois Tigeot 		return 1 << (20 + gmch_ctrl);
2856ba55f2f5SFrançois Tigeot 
2857ba55f2f5SFrançois Tigeot 	return 0;
2858ba55f2f5SFrançois Tigeot }
2859ba55f2f5SFrançois Tigeot 
286019c468b4SFrançois Tigeot static size_t gen6_get_stolen_size(u16 snb_gmch_ctl)
28619edbd4a0SFrançois Tigeot {
28629edbd4a0SFrançois Tigeot 	snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT;
28639edbd4a0SFrançois Tigeot 	snb_gmch_ctl &= SNB_GMCH_GMS_MASK;
28649edbd4a0SFrançois Tigeot 	return snb_gmch_ctl << 25; /* 32 MB units */
28659edbd4a0SFrançois Tigeot }
28669edbd4a0SFrançois Tigeot 
286719c468b4SFrançois Tigeot static size_t gen8_get_stolen_size(u16 bdw_gmch_ctl)
28689edbd4a0SFrançois Tigeot {
28699edbd4a0SFrançois Tigeot 	bdw_gmch_ctl >>= BDW_GMCH_GMS_SHIFT;
28709edbd4a0SFrançois Tigeot 	bdw_gmch_ctl &= BDW_GMCH_GMS_MASK;
28719edbd4a0SFrançois Tigeot 	return bdw_gmch_ctl << 25; /* 32 MB units */
28729edbd4a0SFrançois Tigeot }
28739edbd4a0SFrançois Tigeot 
2874ba55f2f5SFrançois Tigeot static size_t chv_get_stolen_size(u16 gmch_ctrl)
2875ba55f2f5SFrançois Tigeot {
2876ba55f2f5SFrançois Tigeot 	gmch_ctrl >>= SNB_GMCH_GMS_SHIFT;
2877ba55f2f5SFrançois Tigeot 	gmch_ctrl &= SNB_GMCH_GMS_MASK;
2878ba55f2f5SFrançois Tigeot 
2879ba55f2f5SFrançois Tigeot 	/*
2880ba55f2f5SFrançois Tigeot 	 * 0x0  to 0x10: 32MB increments starting at 0MB
2881ba55f2f5SFrançois Tigeot 	 * 0x11 to 0x16: 4MB increments starting at 8MB
2882ba55f2f5SFrançois Tigeot 	 * 0x17 to 0x1d: 4MB increments start at 36MB
2883ba55f2f5SFrançois Tigeot 	 */
2884ba55f2f5SFrançois Tigeot 	if (gmch_ctrl < 0x11)
2885ba55f2f5SFrançois Tigeot 		return gmch_ctrl << 25;
2886ba55f2f5SFrançois Tigeot 	else if (gmch_ctrl < 0x17)
2887ba55f2f5SFrançois Tigeot 		return (gmch_ctrl - 0x11 + 2) << 22;
2888ba55f2f5SFrançois Tigeot 	else
2889ba55f2f5SFrançois Tigeot 		return (gmch_ctrl - 0x17 + 9) << 22;
2890ba55f2f5SFrançois Tigeot }
2891ba55f2f5SFrançois Tigeot 
28922c9916cdSFrançois Tigeot static size_t gen9_get_stolen_size(u16 gen9_gmch_ctl)
28932c9916cdSFrançois Tigeot {
28942c9916cdSFrançois Tigeot 	gen9_gmch_ctl >>= BDW_GMCH_GMS_SHIFT;
28952c9916cdSFrançois Tigeot 	gen9_gmch_ctl &= BDW_GMCH_GMS_MASK;
28962c9916cdSFrançois Tigeot 
28972c9916cdSFrançois Tigeot 	if (gen9_gmch_ctl < 0xf0)
28982c9916cdSFrançois Tigeot 		return gen9_gmch_ctl << 25; /* 32 MB units */
28992c9916cdSFrançois Tigeot 	else
29002c9916cdSFrançois Tigeot 		/* 4MB increments starting at 0xf0 for 4MB */
29012c9916cdSFrançois Tigeot 		return (gen9_gmch_ctl - 0xf0 + 1) << 22;
29022c9916cdSFrançois Tigeot }
29032c9916cdSFrançois Tigeot 
2904*71f41f3eSFrançois Tigeot static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
29059edbd4a0SFrançois Tigeot {
2906*71f41f3eSFrançois Tigeot 	struct pci_dev *pdev = ggtt->base.dev->pdev;
2907a05eeebfSFrançois Tigeot 	struct i915_page_scratch *scratch_page;
2908*71f41f3eSFrançois Tigeot 	phys_addr_t phys_addr;
29099edbd4a0SFrançois Tigeot 
29109edbd4a0SFrançois Tigeot 	/* For Modern GENs the PTEs and register space are split in the BAR */
2911*71f41f3eSFrançois Tigeot 	phys_addr = pci_resource_start(pdev, 0) + pci_resource_len(pdev, 0) / 2;
29129edbd4a0SFrançois Tigeot 
291319c468b4SFrançois Tigeot 	/*
291419c468b4SFrançois Tigeot 	 * On BXT writes larger than 64 bit to the GTT pagetable range will be
291519c468b4SFrançois Tigeot 	 * dropped. For WC mappings in general we have 64 byte burst writes
291619c468b4SFrançois Tigeot 	 * when the WC buffer is flushed, so we can't use it, but have to
291719c468b4SFrançois Tigeot 	 * resort to an uncached mapping. The WC issue is easily caught by the
291819c468b4SFrançois Tigeot 	 * readback check when writing GTT PTE entries.
291919c468b4SFrançois Tigeot 	 */
2920*71f41f3eSFrançois Tigeot 	if (IS_BROXTON(ggtt->base.dev))
2921*71f41f3eSFrançois Tigeot 		ggtt->gsm = ioremap_nocache(phys_addr, size);
292219c468b4SFrançois Tigeot 	else
2923*71f41f3eSFrançois Tigeot 		ggtt->gsm = ioremap_wc(phys_addr, size);
29248621f407SFrançois Tigeot 	if (!ggtt->gsm) {
2925*71f41f3eSFrançois Tigeot 		DRM_ERROR("Failed to map the ggtt page table\n");
29269edbd4a0SFrançois Tigeot 		return -ENOMEM;
29279edbd4a0SFrançois Tigeot 	}
29289edbd4a0SFrançois Tigeot 
2929*71f41f3eSFrançois Tigeot 	scratch_page = alloc_scratch_page(ggtt->base.dev);
2930a05eeebfSFrançois Tigeot 	if (IS_ERR(scratch_page)) {
29319edbd4a0SFrançois Tigeot 		DRM_ERROR("Scratch setup failed\n");
29329edbd4a0SFrançois Tigeot 		/* iounmap will also get called at remove, but meh */
29338621f407SFrançois Tigeot 		iounmap(ggtt->gsm);
2934a05eeebfSFrançois Tigeot 		return PTR_ERR(scratch_page);
29359edbd4a0SFrançois Tigeot 	}
29369edbd4a0SFrançois Tigeot 
29378621f407SFrançois Tigeot 	ggtt->base.scratch_page = scratch_page;
2938a05eeebfSFrançois Tigeot 
2939a05eeebfSFrançois Tigeot 	return 0;
29409edbd4a0SFrançois Tigeot }
29419edbd4a0SFrançois Tigeot 
29429edbd4a0SFrançois Tigeot /* The GGTT and PPGTT need a private PPAT setup in order to handle cacheability
29439edbd4a0SFrançois Tigeot  * bits. When using advanced contexts each context stores its own PAT, but
29449edbd4a0SFrançois Tigeot  * writing this data shouldn't be harmful even in those cases. */
2945ba55f2f5SFrançois Tigeot static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv)
29469edbd4a0SFrançois Tigeot {
29479edbd4a0SFrançois Tigeot 	uint64_t pat;
29489edbd4a0SFrançois Tigeot 
29499edbd4a0SFrançois Tigeot 	pat = GEN8_PPAT(0, GEN8_PPAT_WB | GEN8_PPAT_LLC)     | /* for normal objects, no eLLC */
29509edbd4a0SFrançois Tigeot 	      GEN8_PPAT(1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC) | /* for something pointing to ptes? */
29519edbd4a0SFrançois Tigeot 	      GEN8_PPAT(2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC) | /* for scanout with eLLC */
29529edbd4a0SFrançois Tigeot 	      GEN8_PPAT(3, GEN8_PPAT_UC)                     | /* Uncached objects, mostly for scanout */
29539edbd4a0SFrançois Tigeot 	      GEN8_PPAT(4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)) |
29549edbd4a0SFrançois Tigeot 	      GEN8_PPAT(5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)) |
29559edbd4a0SFrançois Tigeot 	      GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) |
29569edbd4a0SFrançois Tigeot 	      GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3));
29579edbd4a0SFrançois Tigeot 
29588621f407SFrançois Tigeot 	if (!USES_PPGTT(dev_priv))
2959a6e033d9SFrançois Tigeot 		/* Spec: "For GGTT, there is NO pat_sel[2:0] from the entry,
2960a6e033d9SFrançois Tigeot 		 * so RTL will always use the value corresponding to
2961a6e033d9SFrançois Tigeot 		 * pat_sel = 000".
2962a6e033d9SFrançois Tigeot 		 * So let's disable cache for GGTT to avoid screen corruptions.
2963a6e033d9SFrançois Tigeot 		 * MOCS still can be used though.
2964a6e033d9SFrançois Tigeot 		 * - System agent ggtt writes (i.e. cpu gtt mmaps) already work
2965a6e033d9SFrançois Tigeot 		 * before this patch, i.e. the same uncached + snooping access
2966a6e033d9SFrançois Tigeot 		 * like on gen6/7 seems to be in effect.
2967a6e033d9SFrançois Tigeot 		 * - So this just fixes blitter/render access. Again it looks
2968a6e033d9SFrançois Tigeot 		 * like it's not just uncached access, but uncached + snooping.
2969a6e033d9SFrançois Tigeot 		 * So we can still hold onto all our assumptions wrt cpu
2970a6e033d9SFrançois Tigeot 		 * clflushing on LLC machines.
2971a6e033d9SFrançois Tigeot 		 */
2972a6e033d9SFrançois Tigeot 		pat = GEN8_PPAT(0, GEN8_PPAT_UC);
2973a6e033d9SFrançois Tigeot 
29749edbd4a0SFrançois Tigeot 	/* XXX: spec defines this as 2 distinct registers. It's unclear if a 64b
29759edbd4a0SFrançois Tigeot 	 * write would work. */
2976352ff8bdSFrançois Tigeot 	I915_WRITE(GEN8_PRIVATE_PAT_LO, pat);
2977352ff8bdSFrançois Tigeot 	I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32);
29789edbd4a0SFrançois Tigeot }
29799edbd4a0SFrançois Tigeot 
2980ba55f2f5SFrançois Tigeot static void chv_setup_private_ppat(struct drm_i915_private *dev_priv)
2981ba55f2f5SFrançois Tigeot {
2982ba55f2f5SFrançois Tigeot 	uint64_t pat;
2983ba55f2f5SFrançois Tigeot 
2984ba55f2f5SFrançois Tigeot 	/*
2985ba55f2f5SFrançois Tigeot 	 * Map WB on BDW to snooped on CHV.
2986ba55f2f5SFrançois Tigeot 	 *
2987ba55f2f5SFrançois Tigeot 	 * Only the snoop bit has meaning for CHV, the rest is
2988ba55f2f5SFrançois Tigeot 	 * ignored.
2989ba55f2f5SFrançois Tigeot 	 *
29902c9916cdSFrançois Tigeot 	 * The hardware will never snoop for certain types of accesses:
29912c9916cdSFrançois Tigeot 	 * - CPU GTT (GMADR->GGTT->no snoop->memory)
29922c9916cdSFrançois Tigeot 	 * - PPGTT page tables
29932c9916cdSFrançois Tigeot 	 * - some other special cycles
29942c9916cdSFrançois Tigeot 	 *
29952c9916cdSFrançois Tigeot 	 * As with BDW, we also need to consider the following for GT accesses:
29962c9916cdSFrançois Tigeot 	 * "For GGTT, there is NO pat_sel[2:0] from the entry,
29972c9916cdSFrançois Tigeot 	 * so RTL will always use the value corresponding to
29982c9916cdSFrançois Tigeot 	 * pat_sel = 000".
29992c9916cdSFrançois Tigeot 	 * Which means we must set the snoop bit in PAT entry 0
30002c9916cdSFrançois Tigeot 	 * in order to keep the global status page working.
3001ba55f2f5SFrançois Tigeot 	 */
3002ba55f2f5SFrançois Tigeot 	pat = GEN8_PPAT(0, CHV_PPAT_SNOOP) |
3003ba55f2f5SFrançois Tigeot 	      GEN8_PPAT(1, 0) |
3004ba55f2f5SFrançois Tigeot 	      GEN8_PPAT(2, 0) |
3005ba55f2f5SFrançois Tigeot 	      GEN8_PPAT(3, 0) |
3006ba55f2f5SFrançois Tigeot 	      GEN8_PPAT(4, CHV_PPAT_SNOOP) |
3007ba55f2f5SFrançois Tigeot 	      GEN8_PPAT(5, CHV_PPAT_SNOOP) |
3008ba55f2f5SFrançois Tigeot 	      GEN8_PPAT(6, CHV_PPAT_SNOOP) |
3009ba55f2f5SFrançois Tigeot 	      GEN8_PPAT(7, CHV_PPAT_SNOOP);
3010ba55f2f5SFrançois Tigeot 
3011352ff8bdSFrançois Tigeot 	I915_WRITE(GEN8_PRIVATE_PAT_LO, pat);
3012352ff8bdSFrançois Tigeot 	I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32);
3013ba55f2f5SFrançois Tigeot }
3014ba55f2f5SFrançois Tigeot 
3015*71f41f3eSFrançois Tigeot static void gen6_gmch_remove(struct i915_address_space *vm)
30169edbd4a0SFrançois Tigeot {
3017*71f41f3eSFrançois Tigeot 	struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
30189edbd4a0SFrançois Tigeot 
3019*71f41f3eSFrançois Tigeot 	iounmap(ggtt->gsm);
3020*71f41f3eSFrançois Tigeot 	free_scratch_page(vm->dev, vm->scratch_page);
3021ba55f2f5SFrançois Tigeot }
3022ba55f2f5SFrançois Tigeot 
3023*71f41f3eSFrançois Tigeot static int gen8_gmch_probe(struct i915_ggtt *ggtt)
3024*71f41f3eSFrançois Tigeot {
3025*71f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(ggtt->base.dev);
3026*71f41f3eSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
3027*71f41f3eSFrançois Tigeot 	unsigned int size;
3028*71f41f3eSFrançois Tigeot 	u16 snb_gmch_ctl;
30299edbd4a0SFrançois Tigeot 
3030*71f41f3eSFrançois Tigeot 	/* TODO: We're not aware of mappable constraints on gen8 yet */
3031*71f41f3eSFrançois Tigeot 	ggtt->mappable_base = pci_resource_start(pdev, 2);
3032*71f41f3eSFrançois Tigeot 	ggtt->mappable_end = pci_resource_len(pdev, 2);
3033*71f41f3eSFrançois Tigeot 
3034*71f41f3eSFrançois Tigeot #if 0
3035*71f41f3eSFrançois Tigeot 	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(39)))
3036*71f41f3eSFrançois Tigeot 		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(39));
3037*71f41f3eSFrançois Tigeot #endif
3038*71f41f3eSFrançois Tigeot 
3039*71f41f3eSFrançois Tigeot 	pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
3040*71f41f3eSFrançois Tigeot 
3041*71f41f3eSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 9) {
3042*71f41f3eSFrançois Tigeot 		ggtt->stolen_size = gen9_get_stolen_size(snb_gmch_ctl);
3043*71f41f3eSFrançois Tigeot 		size = gen8_get_total_gtt_size(snb_gmch_ctl);
3044*71f41f3eSFrançois Tigeot 	} else if (IS_CHERRYVIEW(dev_priv)) {
3045*71f41f3eSFrançois Tigeot 		ggtt->stolen_size = chv_get_stolen_size(snb_gmch_ctl);
3046*71f41f3eSFrançois Tigeot 		size = chv_get_total_gtt_size(snb_gmch_ctl);
3047*71f41f3eSFrançois Tigeot 	} else {
3048*71f41f3eSFrançois Tigeot 		ggtt->stolen_size = gen8_get_stolen_size(snb_gmch_ctl);
3049*71f41f3eSFrançois Tigeot 		size = gen8_get_total_gtt_size(snb_gmch_ctl);
3050*71f41f3eSFrançois Tigeot 	}
3051*71f41f3eSFrançois Tigeot 
3052*71f41f3eSFrançois Tigeot 	ggtt->base.total = (size / sizeof(gen8_pte_t)) << PAGE_SHIFT;
3053*71f41f3eSFrançois Tigeot 
3054*71f41f3eSFrançois Tigeot 	if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv))
3055ba55f2f5SFrançois Tigeot 		chv_setup_private_ppat(dev_priv);
3056ba55f2f5SFrançois Tigeot 	else
3057ba55f2f5SFrançois Tigeot 		bdw_setup_private_ppat(dev_priv);
30589edbd4a0SFrançois Tigeot 
3059*71f41f3eSFrançois Tigeot 	ggtt->base.cleanup = gen6_gmch_remove;
30608621f407SFrançois Tigeot 	ggtt->base.bind_vma = ggtt_bind_vma;
30618621f407SFrançois Tigeot 	ggtt->base.unbind_vma = ggtt_unbind_vma;
30621487f786SFrançois Tigeot 	ggtt->base.insert_page = gen8_ggtt_insert_page;
30631487f786SFrançois Tigeot 	ggtt->base.clear_range = nop_clear_range;
3064303bf270SFrançois Tigeot 	if (!USES_FULL_PPGTT(dev_priv) || intel_scanout_needs_vtd_wa(dev_priv))
30651487f786SFrançois Tigeot 		ggtt->base.clear_range = gen8_ggtt_clear_range;
30661487f786SFrançois Tigeot 
30671487f786SFrançois Tigeot 	ggtt->base.insert_entries = gen8_ggtt_insert_entries;
30681487f786SFrançois Tigeot 	if (IS_CHERRYVIEW(dev_priv))
30691487f786SFrançois Tigeot 		ggtt->base.insert_entries = gen8_ggtt_insert_entries__BKL;
3070aee94f86SFrançois Tigeot 
3071*71f41f3eSFrançois Tigeot 	return ggtt_probe_common(ggtt, size);
30729edbd4a0SFrançois Tigeot }
30739edbd4a0SFrançois Tigeot 
30748621f407SFrançois Tigeot static int gen6_gmch_probe(struct i915_ggtt *ggtt)
30755d0b1887SFrançois Tigeot {
3076*71f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(ggtt->base.dev);
3077*71f41f3eSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
3078*71f41f3eSFrançois Tigeot 	unsigned int size;
30795d0b1887SFrançois Tigeot 	u16 snb_gmch_ctl;
30805d0b1887SFrançois Tigeot 
3081*71f41f3eSFrançois Tigeot 	ggtt->mappable_base = pci_resource_start(pdev, 2);
3082*71f41f3eSFrançois Tigeot 	ggtt->mappable_end = pci_resource_len(pdev, 2);
30835d0b1887SFrançois Tigeot 
30845d0b1887SFrançois Tigeot 	/* 64/512MB is the current min/max we actually know of, but this is just
30855d0b1887SFrançois Tigeot 	 * a coarse sanity check.
30865d0b1887SFrançois Tigeot 	 */
3087*71f41f3eSFrançois Tigeot 	if (ggtt->mappable_end < (64<<20) || ggtt->mappable_end > (512<<20)) {
30888621f407SFrançois Tigeot 		DRM_ERROR("Unknown GMADR size (%llx)\n", ggtt->mappable_end);
30895d0b1887SFrançois Tigeot 		return -ENXIO;
30905d0b1887SFrançois Tigeot 	}
30915d0b1887SFrançois Tigeot 
30929edbd4a0SFrançois Tigeot #if 0
3093*71f41f3eSFrançois Tigeot 	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(40)))
3094*71f41f3eSFrançois Tigeot 		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40));
30959edbd4a0SFrançois Tigeot #endif
3096*71f41f3eSFrançois Tigeot 	pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
30975d0b1887SFrançois Tigeot 
30988621f407SFrançois Tigeot 	ggtt->stolen_size = gen6_get_stolen_size(snb_gmch_ctl);
30995d0b1887SFrançois Tigeot 
3100*71f41f3eSFrançois Tigeot 	size = gen6_get_total_gtt_size(snb_gmch_ctl);
3101*71f41f3eSFrançois Tigeot 	ggtt->base.total = (size / sizeof(gen6_pte_t)) << PAGE_SHIFT;
31025d0b1887SFrançois Tigeot 
31038621f407SFrançois Tigeot 	ggtt->base.clear_range = gen6_ggtt_clear_range;
31041487f786SFrançois Tigeot 	ggtt->base.insert_page = gen6_ggtt_insert_page;
31058621f407SFrançois Tigeot 	ggtt->base.insert_entries = gen6_ggtt_insert_entries;
31068621f407SFrançois Tigeot 	ggtt->base.bind_vma = ggtt_bind_vma;
31078621f407SFrançois Tigeot 	ggtt->base.unbind_vma = ggtt_unbind_vma;
3108*71f41f3eSFrançois Tigeot 	ggtt->base.cleanup = gen6_gmch_remove;
31099edbd4a0SFrançois Tigeot 
3110*71f41f3eSFrançois Tigeot 	if (HAS_EDRAM(dev_priv))
3111*71f41f3eSFrançois Tigeot 		ggtt->base.pte_encode = iris_pte_encode;
3112*71f41f3eSFrançois Tigeot 	else if (IS_HASWELL(dev_priv))
3113*71f41f3eSFrançois Tigeot 		ggtt->base.pte_encode = hsw_pte_encode;
3114*71f41f3eSFrançois Tigeot 	else if (IS_VALLEYVIEW(dev_priv))
3115*71f41f3eSFrançois Tigeot 		ggtt->base.pte_encode = byt_pte_encode;
3116*71f41f3eSFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 7)
3117*71f41f3eSFrançois Tigeot 		ggtt->base.pte_encode = ivb_pte_encode;
3118*71f41f3eSFrançois Tigeot 	else
3119*71f41f3eSFrançois Tigeot 		ggtt->base.pte_encode = snb_pte_encode;
3120*71f41f3eSFrançois Tigeot 
3121*71f41f3eSFrançois Tigeot 	return ggtt_probe_common(ggtt, size);
31225d0b1887SFrançois Tigeot }
31235d0b1887SFrançois Tigeot 
3124*71f41f3eSFrançois Tigeot static void i915_gmch_remove(struct i915_address_space *vm)
31255d0b1887SFrançois Tigeot {
3126*71f41f3eSFrançois Tigeot 	intel_gmch_remove();
31279edbd4a0SFrançois Tigeot }
31285d0b1887SFrançois Tigeot 
31298621f407SFrançois Tigeot static int i915_gmch_probe(struct i915_ggtt *ggtt)
31305d0b1887SFrançois Tigeot {
3131*71f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(ggtt->base.dev);
31329edbd4a0SFrançois Tigeot #if 0
31339edbd4a0SFrançois Tigeot 	int ret;
31349edbd4a0SFrançois Tigeot 
3135303bf270SFrançois Tigeot 	ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->drm.pdev, NULL);
31369edbd4a0SFrançois Tigeot 	if (!ret) {
31379edbd4a0SFrançois Tigeot 		DRM_ERROR("failed to set up gmch\n");
31389edbd4a0SFrançois Tigeot 		return -EIO;
31399edbd4a0SFrançois Tigeot 	}
31409edbd4a0SFrançois Tigeot #endif
31419edbd4a0SFrançois Tigeot 
31428621f407SFrançois Tigeot 	intel_gtt_get(&ggtt->base.total, &ggtt->stolen_size,
31438621f407SFrançois Tigeot 		      &ggtt->mappable_base, &ggtt->mappable_end);
31449edbd4a0SFrançois Tigeot 
3145*71f41f3eSFrançois Tigeot 	ggtt->do_idle_maps = needs_idle_maps(dev_priv);
31461487f786SFrançois Tigeot 	ggtt->base.insert_page = i915_ggtt_insert_page;
31478621f407SFrançois Tigeot 	ggtt->base.insert_entries = i915_ggtt_insert_entries;
31488621f407SFrançois Tigeot 	ggtt->base.clear_range = i915_ggtt_clear_range;
31498621f407SFrançois Tigeot 	ggtt->base.bind_vma = ggtt_bind_vma;
31508621f407SFrançois Tigeot 	ggtt->base.unbind_vma = ggtt_unbind_vma;
3151*71f41f3eSFrançois Tigeot 	ggtt->base.cleanup = i915_gmch_remove;
31529edbd4a0SFrançois Tigeot 
31538621f407SFrançois Tigeot 	if (unlikely(ggtt->do_idle_maps))
31549edbd4a0SFrançois Tigeot 		DRM_INFO("applying Ironlake quirks for intel_iommu\n");
31559edbd4a0SFrançois Tigeot 
31565d0b1887SFrançois Tigeot 	return 0;
31575d0b1887SFrançois Tigeot }
31585d0b1887SFrançois Tigeot 
31598621f407SFrançois Tigeot /**
3160*71f41f3eSFrançois Tigeot  * i915_ggtt_probe_hw - Probe GGTT hardware location
3161*71f41f3eSFrançois Tigeot  * @dev_priv: i915 device
31628621f407SFrançois Tigeot  */
3163*71f41f3eSFrançois Tigeot int i915_ggtt_probe_hw(struct drm_i915_private *dev_priv)
31640b869d8aSFrançois Tigeot {
31658621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
31669edbd4a0SFrançois Tigeot 	int ret;
31670b869d8aSFrançois Tigeot 
3168*71f41f3eSFrançois Tigeot 	ggtt->base.dev = &dev_priv->drm;
31698621f407SFrançois Tigeot 
3170*71f41f3eSFrançois Tigeot 	if (INTEL_GEN(dev_priv) <= 5)
3171*71f41f3eSFrançois Tigeot 		ret = i915_gmch_probe(ggtt);
3172*71f41f3eSFrançois Tigeot 	else if (INTEL_GEN(dev_priv) < 8)
3173*71f41f3eSFrançois Tigeot 		ret = gen6_gmch_probe(ggtt);
31749edbd4a0SFrançois Tigeot 	else
3175*71f41f3eSFrançois Tigeot 		ret = gen8_gmch_probe(ggtt);
31769edbd4a0SFrançois Tigeot 	if (ret)
31779edbd4a0SFrançois Tigeot 		return ret;
31780b869d8aSFrançois Tigeot 
31798621f407SFrançois Tigeot 	if ((ggtt->base.total - 1) >> 32) {
31808621f407SFrançois Tigeot 		DRM_ERROR("We never expected a Global GTT with more than 32bits"
31818621f407SFrançois Tigeot 			  " of address space! Found %lldM!\n",
31828621f407SFrançois Tigeot 			  ggtt->base.total >> 20);
31838621f407SFrançois Tigeot 		ggtt->base.total = 1ULL << 32;
31848621f407SFrançois Tigeot 		ggtt->mappable_end = min(ggtt->mappable_end, ggtt->base.total);
31858621f407SFrançois Tigeot 	}
31868621f407SFrançois Tigeot 
3187*71f41f3eSFrançois Tigeot 	if (ggtt->mappable_end > ggtt->base.total) {
3188*71f41f3eSFrançois Tigeot 		DRM_ERROR("mappable aperture extends past end of GGTT,"
3189*71f41f3eSFrançois Tigeot 			  " aperture=%llx, total=%llx\n",
3190*71f41f3eSFrançois Tigeot 			  ggtt->mappable_end, ggtt->base.total);
3191*71f41f3eSFrançois Tigeot 		ggtt->mappable_end = ggtt->base.total;
3192*71f41f3eSFrançois Tigeot 	}
3193c0e85e96SFrançois Tigeot 
31945d0b1887SFrançois Tigeot 	/* GMADR is the PCI mmio aperture into the global GTT. */
3195f77dbd6cSFrançois Tigeot 	DRM_INFO("Memory usable by graphics device = %lluM\n",
31968621f407SFrançois Tigeot 		 ggtt->base.total >> 20);
31978621f407SFrançois Tigeot 	DRM_DEBUG_DRIVER("GMADR size = %lldM\n", ggtt->mappable_end >> 20);
31988621f407SFrançois Tigeot 	DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", ggtt->stolen_size >> 20);
3199ba55f2f5SFrançois Tigeot #ifdef CONFIG_INTEL_IOMMU
3200ba55f2f5SFrançois Tigeot 	if (intel_iommu_gfx_mapped)
3201ba55f2f5SFrançois Tigeot 		DRM_INFO("VT-d active for gfx access\n");
3202ba55f2f5SFrançois Tigeot #endif
3203a2fdbec6SFrançois Tigeot 
32040b869d8aSFrançois Tigeot 	return 0;
3205*71f41f3eSFrançois Tigeot }
3206*71f41f3eSFrançois Tigeot 
3207*71f41f3eSFrançois Tigeot /**
3208*71f41f3eSFrançois Tigeot  * i915_ggtt_init_hw - Initialize GGTT hardware
3209*71f41f3eSFrançois Tigeot  * @dev_priv: i915 device
3210*71f41f3eSFrançois Tigeot  */
3211*71f41f3eSFrançois Tigeot int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)
3212*71f41f3eSFrançois Tigeot {
3213*71f41f3eSFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
3214*71f41f3eSFrançois Tigeot 	int ret;
3215*71f41f3eSFrançois Tigeot 
3216*71f41f3eSFrançois Tigeot 	INIT_LIST_HEAD(&dev_priv->vm_list);
3217*71f41f3eSFrançois Tigeot 
3218*71f41f3eSFrançois Tigeot 	/* Subtract the guard page before address space initialization to
3219*71f41f3eSFrançois Tigeot 	 * shrink the range used by drm_mm.
3220*71f41f3eSFrançois Tigeot 	 */
3221*71f41f3eSFrançois Tigeot 	ggtt->base.total -= PAGE_SIZE;
3222*71f41f3eSFrançois Tigeot 	i915_address_space_init(&ggtt->base, dev_priv);
3223*71f41f3eSFrançois Tigeot 	ggtt->base.total += PAGE_SIZE;
3224*71f41f3eSFrançois Tigeot 	if (!HAS_LLC(dev_priv))
3225*71f41f3eSFrançois Tigeot 		ggtt->base.mm.color_adjust = i915_gtt_color_adjust;
3226*71f41f3eSFrançois Tigeot 
3227*71f41f3eSFrançois Tigeot 	ggtt->mappable =
3228*71f41f3eSFrançois Tigeot 		io_mapping_create_wc(ggtt->mappable_base, ggtt->mappable_end);
3229*71f41f3eSFrançois Tigeot 	if (!ggtt->mappable) {
3230*71f41f3eSFrançois Tigeot 		ret = -EIO;
3231*71f41f3eSFrançois Tigeot 		goto out_gtt_cleanup;
3232*71f41f3eSFrançois Tigeot 	}
3233*71f41f3eSFrançois Tigeot 
3234*71f41f3eSFrançois Tigeot 	ggtt->mtrr = arch_phys_wc_add(ggtt->mappable_base, ggtt->mappable_end);
3235*71f41f3eSFrançois Tigeot 
3236*71f41f3eSFrançois Tigeot 	/*
3237*71f41f3eSFrançois Tigeot 	 * Initialise stolen early so that we may reserve preallocated
3238*71f41f3eSFrançois Tigeot 	 * objects for the BIOS to KMS transition.
3239*71f41f3eSFrançois Tigeot 	 */
3240*71f41f3eSFrançois Tigeot 	ret = i915_gem_init_stolen(&dev_priv->drm);
3241*71f41f3eSFrançois Tigeot 	if (ret)
3242*71f41f3eSFrançois Tigeot 		goto out_gtt_cleanup;
3243*71f41f3eSFrançois Tigeot 
3244*71f41f3eSFrançois Tigeot 	return 0;
3245c0e85e96SFrançois Tigeot 
3246c0e85e96SFrançois Tigeot out_gtt_cleanup:
32478621f407SFrançois Tigeot 	ggtt->base.cleanup(&ggtt->base);
3248c0e85e96SFrançois Tigeot 	return ret;
32490b869d8aSFrançois Tigeot }
3250ba55f2f5SFrançois Tigeot 
3251*71f41f3eSFrançois Tigeot int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv)
32528621f407SFrançois Tigeot {
3253*71f41f3eSFrançois Tigeot 	if (INTEL_GEN(dev_priv) < 6 && !intel_enable_gtt())
32548621f407SFrançois Tigeot 		return -EIO;
32558621f407SFrançois Tigeot 
32568621f407SFrançois Tigeot 	return 0;
32578621f407SFrançois Tigeot }
32588621f407SFrançois Tigeot 
325919c468b4SFrançois Tigeot void i915_gem_restore_gtt_mappings(struct drm_device *dev)
326019c468b4SFrançois Tigeot {
32618621f407SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
32628621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
326319c468b4SFrançois Tigeot 	struct drm_i915_gem_object *obj;
3264056b1c44SFrançois Tigeot 	struct i915_vma *vma;
326519c468b4SFrançois Tigeot 
32661487f786SFrançois Tigeot 	i915_check_and_clear_faults(dev_priv);
326719c468b4SFrançois Tigeot 
326819c468b4SFrançois Tigeot 	/* First fill our portion of the GTT with scratch pages */
32698621f407SFrançois Tigeot 	ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total,
327019c468b4SFrançois Tigeot 			       true);
327119c468b4SFrançois Tigeot 
3272056b1c44SFrançois Tigeot 	/* Cache flush objects bound into GGTT and rebind them. */
327319c468b4SFrançois Tigeot 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
3274c0e85e96SFrançois Tigeot 		list_for_each_entry(vma, &obj->vma_list, obj_link) {
32758621f407SFrançois Tigeot 			if (vma->vm != &ggtt->base)
327619c468b4SFrançois Tigeot 				continue;
327719c468b4SFrançois Tigeot 
3278056b1c44SFrançois Tigeot 			WARN_ON(i915_vma_bind(vma, obj->cache_level,
3279056b1c44SFrançois Tigeot 					      PIN_UPDATE));
328019c468b4SFrançois Tigeot 		}
328119c468b4SFrançois Tigeot 
32821487f786SFrançois Tigeot 		if (obj->pin_display)
32831487f786SFrançois Tigeot 			WARN_ON(i915_gem_object_set_to_gtt_domain(obj, false));
3284056b1c44SFrançois Tigeot 	}
3285a05eeebfSFrançois Tigeot 
328619c468b4SFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 8) {
328719c468b4SFrançois Tigeot 		if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev))
328819c468b4SFrançois Tigeot 			chv_setup_private_ppat(dev_priv);
328919c468b4SFrançois Tigeot 		else
329019c468b4SFrançois Tigeot 			bdw_setup_private_ppat(dev_priv);
329119c468b4SFrançois Tigeot 
329219c468b4SFrançois Tigeot 		return;
329319c468b4SFrançois Tigeot 	}
329419c468b4SFrançois Tigeot 
329519c468b4SFrançois Tigeot 	if (USES_PPGTT(dev)) {
32968621f407SFrançois Tigeot 		struct i915_address_space *vm;
32978621f407SFrançois Tigeot 
329819c468b4SFrançois Tigeot 		list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
329919c468b4SFrançois Tigeot 			/* TODO: Perhaps it shouldn't be gen6 specific */
330019c468b4SFrançois Tigeot 
33018621f407SFrançois Tigeot 			struct i915_hw_ppgtt *ppgtt;
330219c468b4SFrançois Tigeot 
3303*71f41f3eSFrançois Tigeot 			if (i915_is_ggtt(vm))
330419c468b4SFrançois Tigeot 				ppgtt = dev_priv->mm.aliasing_ppgtt;
33058621f407SFrançois Tigeot 			else
33068621f407SFrançois Tigeot 				ppgtt = i915_vm_to_ppgtt(vm);
330719c468b4SFrançois Tigeot 
330819c468b4SFrançois Tigeot 			gen6_write_page_range(dev_priv, &ppgtt->pd,
330919c468b4SFrançois Tigeot 					      0, ppgtt->base.total);
331019c468b4SFrançois Tigeot 		}
331119c468b4SFrançois Tigeot 	}
331219c468b4SFrançois Tigeot 
331319c468b4SFrançois Tigeot 	i915_ggtt_flush(dev_priv);
331419c468b4SFrançois Tigeot }
331519c468b4SFrançois Tigeot 
3316*71f41f3eSFrançois Tigeot static void
3317*71f41f3eSFrançois Tigeot i915_vma_retire(struct i915_gem_active *active,
3318*71f41f3eSFrançois Tigeot 		struct drm_i915_gem_request *rq)
3319*71f41f3eSFrançois Tigeot {
3320*71f41f3eSFrançois Tigeot 	const unsigned int idx = rq->engine->id;
3321*71f41f3eSFrançois Tigeot 	struct i915_vma *vma =
3322*71f41f3eSFrançois Tigeot 		container_of(active, struct i915_vma, last_read[idx]);
3323*71f41f3eSFrançois Tigeot 
3324*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(!i915_vma_has_active_engine(vma, idx));
3325*71f41f3eSFrançois Tigeot 
3326*71f41f3eSFrançois Tigeot 	i915_vma_clear_active(vma, idx);
3327*71f41f3eSFrançois Tigeot 	if (i915_vma_is_active(vma))
3328*71f41f3eSFrançois Tigeot 		return;
3329*71f41f3eSFrançois Tigeot 
3330*71f41f3eSFrançois Tigeot 	list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
3331*71f41f3eSFrançois Tigeot 	if (unlikely(i915_vma_is_closed(vma) && !i915_vma_is_pinned(vma)))
3332*71f41f3eSFrançois Tigeot 		WARN_ON(i915_vma_unbind(vma));
3333*71f41f3eSFrançois Tigeot }
3334*71f41f3eSFrançois Tigeot 
3335*71f41f3eSFrançois Tigeot void i915_vma_destroy(struct i915_vma *vma)
3336*71f41f3eSFrançois Tigeot {
3337*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(vma->node.allocated);
3338*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(i915_vma_is_active(vma));
3339*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(!i915_vma_is_closed(vma));
3340*71f41f3eSFrançois Tigeot 
3341*71f41f3eSFrançois Tigeot 	list_del(&vma->vm_link);
3342*71f41f3eSFrançois Tigeot 	if (!i915_vma_is_ggtt(vma))
3343*71f41f3eSFrançois Tigeot 		i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm));
3344*71f41f3eSFrançois Tigeot 
3345*71f41f3eSFrançois Tigeot 	kmem_cache_free(to_i915(vma->obj->base.dev)->vmas, vma);
3346*71f41f3eSFrançois Tigeot }
3347*71f41f3eSFrançois Tigeot 
3348*71f41f3eSFrançois Tigeot void i915_vma_close(struct i915_vma *vma)
3349*71f41f3eSFrançois Tigeot {
3350*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(i915_vma_is_closed(vma));
3351*71f41f3eSFrançois Tigeot 	vma->flags |= I915_VMA_CLOSED;
3352*71f41f3eSFrançois Tigeot 
3353*71f41f3eSFrançois Tigeot 	list_del_init(&vma->obj_link);
3354*71f41f3eSFrançois Tigeot 	if (!i915_vma_is_active(vma) && !i915_vma_is_pinned(vma))
3355*71f41f3eSFrançois Tigeot 		WARN_ON(i915_vma_unbind(vma));
3356*71f41f3eSFrançois Tigeot }
3357*71f41f3eSFrançois Tigeot 
3358477eb7f9SFrançois Tigeot static struct i915_vma *
3359477eb7f9SFrançois Tigeot __i915_gem_vma_create(struct drm_i915_gem_object *obj,
33602c9916cdSFrançois Tigeot 		      struct i915_address_space *vm,
3361*71f41f3eSFrançois Tigeot 		      const struct i915_ggtt_view *view)
3362ba55f2f5SFrançois Tigeot {
3363477eb7f9SFrançois Tigeot 	struct i915_vma *vma;
3364*71f41f3eSFrançois Tigeot 	int i;
3365477eb7f9SFrançois Tigeot 
3366*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(vm->closed);
3367*71f41f3eSFrançois Tigeot 
3368*71f41f3eSFrançois Tigeot 	if (WARN_ON(i915_is_ggtt(vm) != !!view))
3369477eb7f9SFrançois Tigeot 		return ERR_PTR(-EINVAL);
33707ec9f8e5SFrançois Tigeot 
3371477eb7f9SFrançois Tigeot 	vma = kzalloc(sizeof(*vma), GFP_KERNEL);
3372ba55f2f5SFrançois Tigeot 	if (vma == NULL)
3373ba55f2f5SFrançois Tigeot 		return ERR_PTR(-ENOMEM);
3374ba55f2f5SFrançois Tigeot 
3375c0e85e96SFrançois Tigeot 	INIT_LIST_HEAD(&vma->obj_link);
3376ba55f2f5SFrançois Tigeot 	INIT_LIST_HEAD(&vma->exec_list);
3377*71f41f3eSFrançois Tigeot 	for (i = 0; i < ARRAY_SIZE(vma->last_read); i++)
3378*71f41f3eSFrançois Tigeot 		init_request_active(&vma->last_read[i], i915_vma_retire);
3379*71f41f3eSFrançois Tigeot 	list_add(&vma->vm_link, &vm->unbound_list);
3380ba55f2f5SFrançois Tigeot 	vma->vm = vm;
3381ba55f2f5SFrançois Tigeot 	vma->obj = obj;
3382*71f41f3eSFrançois Tigeot 	vma->size = obj->base.size;
3383ba55f2f5SFrançois Tigeot 
3384*71f41f3eSFrançois Tigeot 	if (i915_is_ggtt(vm)) {
3385*71f41f3eSFrançois Tigeot 		vma->flags |= I915_VMA_GGTT;
3386*71f41f3eSFrançois Tigeot 		vma->ggtt_view = *view;
3387*71f41f3eSFrançois Tigeot 		if (view->type == I915_GGTT_VIEW_PARTIAL) {
3388*71f41f3eSFrançois Tigeot 			vma->size = view->params.partial.size;
3389*71f41f3eSFrançois Tigeot 			vma->size <<= PAGE_SHIFT;
3390*71f41f3eSFrançois Tigeot 		} else if (view->type == I915_GGTT_VIEW_ROTATED) {
3391*71f41f3eSFrançois Tigeot 			vma->size =
3392*71f41f3eSFrançois Tigeot 				intel_rotation_info_size(&view->params.rotated);
3393*71f41f3eSFrançois Tigeot 			vma->size <<= PAGE_SHIFT;
3394*71f41f3eSFrançois Tigeot 		}
3395*71f41f3eSFrançois Tigeot 	} else {
33961b13d190SFrançois Tigeot 		i915_ppgtt_get(i915_vm_to_ppgtt(vm));
3397*71f41f3eSFrançois Tigeot 	}
3398ba55f2f5SFrançois Tigeot 
3399c0e85e96SFrançois Tigeot 	list_add_tail(&vma->obj_link, &obj->vma_list);
3400c0e85e96SFrançois Tigeot 
3401ba55f2f5SFrançois Tigeot 	return vma;
3402ba55f2f5SFrançois Tigeot }
3403ba55f2f5SFrançois Tigeot 
3404ba55f2f5SFrançois Tigeot struct i915_vma *
3405477eb7f9SFrançois Tigeot i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
3406477eb7f9SFrançois Tigeot 				  struct i915_address_space *vm)
3407ba55f2f5SFrançois Tigeot {
3408ba55f2f5SFrançois Tigeot 	struct i915_vma *vma;
3409ba55f2f5SFrançois Tigeot 
3410477eb7f9SFrançois Tigeot 	vma = i915_gem_obj_to_vma(obj, vm);
3411ba55f2f5SFrançois Tigeot 	if (!vma)
3412477eb7f9SFrançois Tigeot 		vma = __i915_gem_vma_create(obj, vm,
3413477eb7f9SFrançois Tigeot 					    i915_is_ggtt(vm) ? &i915_ggtt_view_normal : NULL);
3414ba55f2f5SFrançois Tigeot 
3415ba55f2f5SFrançois Tigeot 	return vma;
3416ba55f2f5SFrançois Tigeot }
34172c9916cdSFrançois Tigeot 
3418477eb7f9SFrançois Tigeot struct i915_vma *
3419477eb7f9SFrançois Tigeot i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj,
3420477eb7f9SFrançois Tigeot 				       const struct i915_ggtt_view *view)
34212c9916cdSFrançois Tigeot {
34228621f407SFrançois Tigeot 	struct drm_device *dev = obj->base.dev;
34238621f407SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
34248621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
34258621f407SFrançois Tigeot 	struct i915_vma *vma = i915_gem_obj_to_ggtt_view(obj, view);
3426477eb7f9SFrançois Tigeot 
3427*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(!view);
3428*71f41f3eSFrançois Tigeot 
3429477eb7f9SFrançois Tigeot 	if (!vma)
34308621f407SFrançois Tigeot 		vma = __i915_gem_vma_create(obj, &ggtt->base, view);
3431477eb7f9SFrançois Tigeot 
3432*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(i915_vma_is_closed(vma));
3433477eb7f9SFrançois Tigeot 	return vma;
3434477eb7f9SFrançois Tigeot 
3435477eb7f9SFrançois Tigeot }
3436477eb7f9SFrançois Tigeot 
3437352ff8bdSFrançois Tigeot static struct scatterlist *
3438c0e85e96SFrançois Tigeot rotate_pages(const dma_addr_t *in, unsigned int offset,
3439352ff8bdSFrançois Tigeot 	     unsigned int width, unsigned int height,
3440c0e85e96SFrançois Tigeot 	     unsigned int stride,
3441352ff8bdSFrançois Tigeot 	     struct sg_table *st, struct scatterlist *sg)
3442477eb7f9SFrançois Tigeot {
3443477eb7f9SFrançois Tigeot 	unsigned int column, row;
3444477eb7f9SFrançois Tigeot 	unsigned int src_idx;
3445477eb7f9SFrançois Tigeot 
3446477eb7f9SFrançois Tigeot 	for (column = 0; column < width; column++) {
3447c0e85e96SFrançois Tigeot 		src_idx = stride * (height - 1) + column;
3448477eb7f9SFrançois Tigeot 		for (row = 0; row < height; row++) {
3449477eb7f9SFrançois Tigeot 			st->nents++;
3450477eb7f9SFrançois Tigeot 			/* We don't need the pages, but need to initialize
3451477eb7f9SFrançois Tigeot 			 * the entries so the sg list can be happily traversed.
3452477eb7f9SFrançois Tigeot 			 * The only thing we need are DMA addresses.
3453477eb7f9SFrançois Tigeot 			 */
3454477eb7f9SFrançois Tigeot 			sg_set_page(sg, NULL, PAGE_SIZE, 0);
3455352ff8bdSFrançois Tigeot 			sg_dma_address(sg) = in[offset + src_idx];
3456477eb7f9SFrançois Tigeot 			sg_dma_len(sg) = PAGE_SIZE;
3457477eb7f9SFrançois Tigeot 			sg = sg_next(sg);
3458c0e85e96SFrançois Tigeot 			src_idx -= stride;
3459477eb7f9SFrançois Tigeot 		}
3460477eb7f9SFrançois Tigeot 	}
3461352ff8bdSFrançois Tigeot 
3462352ff8bdSFrançois Tigeot 	return sg;
3463477eb7f9SFrançois Tigeot }
3464477eb7f9SFrançois Tigeot 
3465477eb7f9SFrançois Tigeot static struct sg_table *
3466c0e85e96SFrançois Tigeot intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
3467477eb7f9SFrançois Tigeot 			  struct drm_i915_gem_object *obj)
3468477eb7f9SFrançois Tigeot {
3469bf017597SFrançois Tigeot 	const size_t n_pages = obj->base.size / PAGE_SIZE;
34708621f407SFrançois Tigeot 	unsigned int size_pages = rot_info->plane[0].width * rot_info->plane[0].height;
3471352ff8bdSFrançois Tigeot 	unsigned int size_pages_uv;
34721487f786SFrançois Tigeot 	struct sgt_iter sgt_iter;
34731487f786SFrançois Tigeot 	dma_addr_t dma_addr;
3474477eb7f9SFrançois Tigeot 	unsigned long i;
3475477eb7f9SFrançois Tigeot 	dma_addr_t *page_addr_list;
3476477eb7f9SFrançois Tigeot 	struct sg_table *st;
3477352ff8bdSFrançois Tigeot 	unsigned int uv_start_page;
3478352ff8bdSFrançois Tigeot 	struct scatterlist *sg;
3479477eb7f9SFrançois Tigeot 	int ret = -ENOMEM;
3480477eb7f9SFrançois Tigeot 
3481477eb7f9SFrançois Tigeot 	/* Allocate a temporary list of source pages for random access. */
3482bf017597SFrançois Tigeot 	page_addr_list = drm_malloc_gfp(n_pages,
3483bf017597SFrançois Tigeot 					sizeof(dma_addr_t),
3484bf017597SFrançois Tigeot 					GFP_TEMPORARY);
3485477eb7f9SFrançois Tigeot 	if (!page_addr_list)
3486477eb7f9SFrançois Tigeot 		return ERR_PTR(ret);
3487477eb7f9SFrançois Tigeot 
3488352ff8bdSFrançois Tigeot 	/* Account for UV plane with NV12. */
3489352ff8bdSFrançois Tigeot 	if (rot_info->pixel_format == DRM_FORMAT_NV12)
34908621f407SFrançois Tigeot 		size_pages_uv = rot_info->plane[1].width * rot_info->plane[1].height;
3491352ff8bdSFrançois Tigeot 	else
3492352ff8bdSFrançois Tigeot 		size_pages_uv = 0;
3493352ff8bdSFrançois Tigeot 
3494477eb7f9SFrançois Tigeot 	/* Allocate target SG list. */
3495bf017597SFrançois Tigeot 	st = kmalloc(sizeof(*st), M_DRM, GFP_KERNEL);
3496477eb7f9SFrançois Tigeot 	if (!st)
3497477eb7f9SFrançois Tigeot 		goto err_st_alloc;
3498477eb7f9SFrançois Tigeot 
3499352ff8bdSFrançois Tigeot 	ret = sg_alloc_table(st, size_pages + size_pages_uv, GFP_KERNEL);
3500477eb7f9SFrançois Tigeot 	if (ret)
3501477eb7f9SFrançois Tigeot 		goto err_sg_alloc;
3502477eb7f9SFrançois Tigeot 
3503477eb7f9SFrançois Tigeot 	/* Populate source page list from the object. */
3504477eb7f9SFrançois Tigeot 	i = 0;
35051487f786SFrançois Tigeot 	for_each_sgt_dma(dma_addr, sgt_iter, obj->pages)
35061487f786SFrançois Tigeot 		page_addr_list[i++] = dma_addr;
3507477eb7f9SFrançois Tigeot 
35081487f786SFrançois Tigeot 	GEM_BUG_ON(i != n_pages);
35098621f407SFrançois Tigeot 	st->nents = 0;
35108621f407SFrançois Tigeot 	sg = st->sgl;
35118621f407SFrançois Tigeot 
3512477eb7f9SFrançois Tigeot 	/* Rotate the pages. */
3513352ff8bdSFrançois Tigeot 	sg = rotate_pages(page_addr_list, 0,
35148621f407SFrançois Tigeot 			  rot_info->plane[0].width, rot_info->plane[0].height,
35158621f407SFrançois Tigeot 			  rot_info->plane[0].width,
35168621f407SFrançois Tigeot 			  st, sg);
3517352ff8bdSFrançois Tigeot 
3518352ff8bdSFrançois Tigeot 	/* Append the UV plane if NV12. */
3519352ff8bdSFrançois Tigeot 	if (rot_info->pixel_format == DRM_FORMAT_NV12) {
3520352ff8bdSFrançois Tigeot 		uv_start_page = size_pages;
3521352ff8bdSFrançois Tigeot 
3522352ff8bdSFrançois Tigeot 		/* Check for tile-row un-alignment. */
3523352ff8bdSFrançois Tigeot 		if (offset_in_page(rot_info->uv_offset))
3524352ff8bdSFrançois Tigeot 			uv_start_page--;
3525352ff8bdSFrançois Tigeot 
3526352ff8bdSFrançois Tigeot 		rot_info->uv_start_page = uv_start_page;
3527352ff8bdSFrançois Tigeot 
35288621f407SFrançois Tigeot 		sg = rotate_pages(page_addr_list, rot_info->uv_start_page,
35298621f407SFrançois Tigeot 				  rot_info->plane[1].width, rot_info->plane[1].height,
35308621f407SFrançois Tigeot 				  rot_info->plane[1].width,
3531352ff8bdSFrançois Tigeot 				  st, sg);
3532352ff8bdSFrançois Tigeot 	}
3533477eb7f9SFrançois Tigeot 
35348621f407SFrançois Tigeot 	DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages (%u plane 0)).\n",
35358621f407SFrançois Tigeot 		      obj->base.size, rot_info->plane[0].width,
35368621f407SFrançois Tigeot 		      rot_info->plane[0].height, size_pages + size_pages_uv,
3537352ff8bdSFrançois Tigeot 		      size_pages);
3538477eb7f9SFrançois Tigeot 
3539477eb7f9SFrançois Tigeot 	drm_free_large(page_addr_list);
3540477eb7f9SFrançois Tigeot 
3541477eb7f9SFrançois Tigeot 	return st;
3542477eb7f9SFrançois Tigeot 
3543477eb7f9SFrançois Tigeot err_sg_alloc:
3544477eb7f9SFrançois Tigeot 	kfree(st);
3545477eb7f9SFrançois Tigeot err_st_alloc:
3546477eb7f9SFrançois Tigeot 	drm_free_large(page_addr_list);
3547477eb7f9SFrançois Tigeot 
35488621f407SFrançois Tigeot 	DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! (%d) (%ux%u tiles, %u pages (%u plane 0))\n",
35498621f407SFrançois Tigeot 		      obj->base.size, ret, rot_info->plane[0].width,
35508621f407SFrançois Tigeot 		      rot_info->plane[0].height, size_pages + size_pages_uv,
3551352ff8bdSFrançois Tigeot 		      size_pages);
3552477eb7f9SFrançois Tigeot 	return ERR_PTR(ret);
3553477eb7f9SFrançois Tigeot }
355419c468b4SFrançois Tigeot 
355519c468b4SFrançois Tigeot static struct sg_table *
355619c468b4SFrançois Tigeot intel_partial_pages(const struct i915_ggtt_view *view,
355719c468b4SFrançois Tigeot 		    struct drm_i915_gem_object *obj)
355819c468b4SFrançois Tigeot {
355919c468b4SFrançois Tigeot 	struct sg_table *st;
356019c468b4SFrançois Tigeot 	struct scatterlist *sg;
356119c468b4SFrançois Tigeot 	struct sg_page_iter obj_sg_iter;
356219c468b4SFrançois Tigeot 	int ret = -ENOMEM;
356319c468b4SFrançois Tigeot 
3564bf017597SFrançois Tigeot 	st = kmalloc(sizeof(*st), M_DRM, GFP_KERNEL);
356519c468b4SFrançois Tigeot 	if (!st)
356619c468b4SFrançois Tigeot 		goto err_st_alloc;
356719c468b4SFrançois Tigeot 
356819c468b4SFrançois Tigeot 	ret = sg_alloc_table(st, view->params.partial.size, GFP_KERNEL);
356919c468b4SFrançois Tigeot 	if (ret)
357019c468b4SFrançois Tigeot 		goto err_sg_alloc;
357119c468b4SFrançois Tigeot 
357219c468b4SFrançois Tigeot 	sg = st->sgl;
357319c468b4SFrançois Tigeot 	st->nents = 0;
357419c468b4SFrançois Tigeot 	for_each_sg_page(obj->pages->sgl, &obj_sg_iter, obj->pages->nents,
357519c468b4SFrançois Tigeot 		view->params.partial.offset)
357619c468b4SFrançois Tigeot 	{
357719c468b4SFrançois Tigeot 		if (st->nents >= view->params.partial.size)
357819c468b4SFrançois Tigeot 			break;
357919c468b4SFrançois Tigeot 
358019c468b4SFrançois Tigeot 		sg_set_page(sg, NULL, PAGE_SIZE, 0);
358119c468b4SFrançois Tigeot 		sg_dma_address(sg) = sg_page_iter_dma_address(&obj_sg_iter);
358219c468b4SFrançois Tigeot 		sg_dma_len(sg) = PAGE_SIZE;
358319c468b4SFrançois Tigeot 
358419c468b4SFrançois Tigeot 		sg = sg_next(sg);
358519c468b4SFrançois Tigeot 		st->nents++;
358619c468b4SFrançois Tigeot 	}
358719c468b4SFrançois Tigeot 
358819c468b4SFrançois Tigeot 	return st;
358919c468b4SFrançois Tigeot 
359019c468b4SFrançois Tigeot err_sg_alloc:
359119c468b4SFrançois Tigeot 	kfree(st);
359219c468b4SFrançois Tigeot err_st_alloc:
359319c468b4SFrançois Tigeot 	return ERR_PTR(ret);
359419c468b4SFrançois Tigeot }
3595477eb7f9SFrançois Tigeot 
359619c468b4SFrançois Tigeot static int
3597477eb7f9SFrançois Tigeot i915_get_ggtt_vma_pages(struct i915_vma *vma)
3598477eb7f9SFrançois Tigeot {
3599477eb7f9SFrançois Tigeot 	int ret = 0;
3600477eb7f9SFrançois Tigeot 
36012c9916cdSFrançois Tigeot 	if (vma->ggtt_view.pages)
36022c9916cdSFrançois Tigeot 		return 0;
36032c9916cdSFrançois Tigeot 
36042c9916cdSFrançois Tigeot 	if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL)
36052c9916cdSFrançois Tigeot 		vma->ggtt_view.pages = vma->obj->pages;
3606477eb7f9SFrançois Tigeot 	else if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED)
3607477eb7f9SFrançois Tigeot 		vma->ggtt_view.pages =
3608c0e85e96SFrançois Tigeot 			intel_rotate_fb_obj_pages(&vma->ggtt_view.params.rotated, vma->obj);
360919c468b4SFrançois Tigeot 	else if (vma->ggtt_view.type == I915_GGTT_VIEW_PARTIAL)
361019c468b4SFrançois Tigeot 		vma->ggtt_view.pages =
361119c468b4SFrançois Tigeot 			intel_partial_pages(&vma->ggtt_view, vma->obj);
36122c9916cdSFrançois Tigeot 	else
36132c9916cdSFrançois Tigeot 		WARN_ONCE(1, "GGTT view %u not implemented!\n",
36142c9916cdSFrançois Tigeot 			  vma->ggtt_view.type);
36152c9916cdSFrançois Tigeot 
36162c9916cdSFrançois Tigeot 	if (!vma->ggtt_view.pages) {
3617477eb7f9SFrançois Tigeot 		DRM_ERROR("Failed to get pages for GGTT view type %u!\n",
36182c9916cdSFrançois Tigeot 			  vma->ggtt_view.type);
3619477eb7f9SFrançois Tigeot 		ret = -EINVAL;
3620477eb7f9SFrançois Tigeot 	} else if (IS_ERR(vma->ggtt_view.pages)) {
3621477eb7f9SFrançois Tigeot 		ret = PTR_ERR(vma->ggtt_view.pages);
3622477eb7f9SFrançois Tigeot 		vma->ggtt_view.pages = NULL;
3623477eb7f9SFrançois Tigeot 		DRM_ERROR("Failed to get pages for VMA view type %u (%d)!\n",
3624477eb7f9SFrançois Tigeot 			  vma->ggtt_view.type, ret);
36252c9916cdSFrançois Tigeot 	}
36262c9916cdSFrançois Tigeot 
3627477eb7f9SFrançois Tigeot 	return ret;
36282c9916cdSFrançois Tigeot }
36292c9916cdSFrançois Tigeot 
36302c9916cdSFrançois Tigeot /**
36312c9916cdSFrançois Tigeot  * i915_vma_bind - Sets up PTEs for an VMA in it's corresponding address space.
36322c9916cdSFrançois Tigeot  * @vma: VMA to map
36332c9916cdSFrançois Tigeot  * @cache_level: mapping cache level
36342c9916cdSFrançois Tigeot  * @flags: flags like global or local mapping
36352c9916cdSFrançois Tigeot  *
36362c9916cdSFrançois Tigeot  * DMA addresses are taken from the scatter-gather table of this object (or of
36372c9916cdSFrançois Tigeot  * this VMA in case of non-default GGTT views) and PTE entries set up.
36382c9916cdSFrançois Tigeot  * Note that DMA addresses are also the only part of the SG table we care about.
36392c9916cdSFrançois Tigeot  */
36402c9916cdSFrançois Tigeot int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
36412c9916cdSFrançois Tigeot 		  u32 flags)
36422c9916cdSFrançois Tigeot {
364319c468b4SFrançois Tigeot 	u32 bind_flags;
3644*71f41f3eSFrançois Tigeot 	u32 vma_flags;
3645*71f41f3eSFrançois Tigeot 	int ret;
36462c9916cdSFrançois Tigeot 
364719c468b4SFrançois Tigeot 	if (WARN_ON(flags == 0))
364819c468b4SFrançois Tigeot 		return -EINVAL;
364919c468b4SFrançois Tigeot 
365019c468b4SFrançois Tigeot 	bind_flags = 0;
365119c468b4SFrançois Tigeot 	if (flags & PIN_GLOBAL)
3652*71f41f3eSFrançois Tigeot 		bind_flags |= I915_VMA_GLOBAL_BIND;
365319c468b4SFrançois Tigeot 	if (flags & PIN_USER)
3654*71f41f3eSFrançois Tigeot 		bind_flags |= I915_VMA_LOCAL_BIND;
365519c468b4SFrançois Tigeot 
3656*71f41f3eSFrançois Tigeot 	vma_flags = vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
365719c468b4SFrançois Tigeot 	if (flags & PIN_UPDATE)
3658*71f41f3eSFrançois Tigeot 		bind_flags |= vma_flags;
365919c468b4SFrançois Tigeot 	else
3660*71f41f3eSFrançois Tigeot 		bind_flags &= ~vma_flags;
366119c468b4SFrançois Tigeot 	if (bind_flags == 0)
366219c468b4SFrançois Tigeot 		return 0;
366319c468b4SFrançois Tigeot 
3664*71f41f3eSFrançois Tigeot 	if (vma_flags == 0 && vma->vm->allocate_va_range) {
3665c0e85e96SFrançois Tigeot 		trace_i915_va_alloc(vma);
366619c468b4SFrançois Tigeot 		ret = vma->vm->allocate_va_range(vma->vm,
366719c468b4SFrançois Tigeot 						 vma->node.start,
366819c468b4SFrançois Tigeot 						 vma->node.size);
366919c468b4SFrançois Tigeot 		if (ret)
367019c468b4SFrançois Tigeot 			return ret;
367119c468b4SFrançois Tigeot 	}
367219c468b4SFrançois Tigeot 
367319c468b4SFrançois Tigeot 	ret = vma->vm->bind_vma(vma, cache_level, bind_flags);
367419c468b4SFrançois Tigeot 	if (ret)
367519c468b4SFrançois Tigeot 		return ret;
367619c468b4SFrançois Tigeot 
3677*71f41f3eSFrançois Tigeot 	vma->flags |= bind_flags;
36782c9916cdSFrançois Tigeot 	return 0;
36792c9916cdSFrançois Tigeot }
368019c468b4SFrançois Tigeot 
36811487f786SFrançois Tigeot void __iomem *i915_vma_pin_iomap(struct i915_vma *vma)
36821487f786SFrançois Tigeot {
36831487f786SFrançois Tigeot 	void __iomem *ptr;
36841487f786SFrançois Tigeot 
36851487f786SFrançois Tigeot 	lockdep_assert_held(&vma->vm->dev->struct_mutex);
36861487f786SFrançois Tigeot 	if (WARN_ON(!vma->obj->map_and_fenceable))
368787df8fc6SFrançois Tigeot 		return IO_ERR_PTR(-ENODEV);
36881487f786SFrançois Tigeot 
3689*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(!i915_vma_is_ggtt(vma));
3690*71f41f3eSFrançois Tigeot 	GEM_BUG_ON((vma->flags & I915_VMA_GLOBAL_BIND) == 0);
36911487f786SFrançois Tigeot 
36921487f786SFrançois Tigeot 	ptr = vma->iomap;
36931487f786SFrançois Tigeot 	if (ptr == NULL) {
36941487f786SFrançois Tigeot 		ptr = io_mapping_map_wc(i915_vm_to_ggtt(vma->vm)->mappable,
36951487f786SFrançois Tigeot 					vma->node.start,
36961487f786SFrançois Tigeot 					vma->node.size);
36971487f786SFrançois Tigeot 		if (ptr == NULL)
369887df8fc6SFrançois Tigeot 			return IO_ERR_PTR(-ENOMEM);
36991487f786SFrançois Tigeot 
37001487f786SFrançois Tigeot 		vma->iomap = ptr;
37011487f786SFrançois Tigeot 	}
37021487f786SFrançois Tigeot 
3703*71f41f3eSFrançois Tigeot 	__i915_vma_pin(vma);
37041487f786SFrançois Tigeot 	return ptr;
37051487f786SFrançois Tigeot }
3706