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> 2718e26a6dSFrançois Tigeot #include <drm/drmP.h> 285c6c6f23SFrançois Tigeot #include <drm/i915_drm.h> 29e3adcf8fSFrançois Tigeot #include "i915_drv.h" 30477eb7f9SFrançois Tigeot #include "i915_vgpu.h" 31477eb7f9SFrançois Tigeot #include "i915_trace.h" 32e3adcf8fSFrançois Tigeot #include "intel_drv.h" 33e3adcf8fSFrançois Tigeot 34477eb7f9SFrançois Tigeot #include <linux/bitmap.h> 3582046b5cSFrançois Tigeot #include <linux/highmem.h> 3682046b5cSFrançois Tigeot 372c9916cdSFrançois Tigeot /** 382c9916cdSFrançois Tigeot * DOC: Global GTT views 392c9916cdSFrançois Tigeot * 402c9916cdSFrançois Tigeot * Background and previous state 412c9916cdSFrançois Tigeot * 422c9916cdSFrançois Tigeot * Historically objects could exists (be bound) in global GTT space only as 432c9916cdSFrançois Tigeot * singular instances with a view representing all of the object's backing pages 442c9916cdSFrançois Tigeot * in a linear fashion. This view will be called a normal view. 452c9916cdSFrançois Tigeot * 462c9916cdSFrançois Tigeot * To support multiple views of the same object, where the number of mapped 472c9916cdSFrançois Tigeot * pages is not equal to the backing store, or where the layout of the pages 482c9916cdSFrançois Tigeot * is not linear, concept of a GGTT view was added. 492c9916cdSFrançois Tigeot * 502c9916cdSFrançois Tigeot * One example of an alternative view is a stereo display driven by a single 512c9916cdSFrançois Tigeot * image. In this case we would have a framebuffer looking like this 522c9916cdSFrançois Tigeot * (2x2 pages): 532c9916cdSFrançois Tigeot * 542c9916cdSFrançois Tigeot * 12 552c9916cdSFrançois Tigeot * 34 562c9916cdSFrançois Tigeot * 572c9916cdSFrançois Tigeot * Above would represent a normal GGTT view as normally mapped for GPU or CPU 582c9916cdSFrançois Tigeot * rendering. In contrast, fed to the display engine would be an alternative 592c9916cdSFrançois Tigeot * view which could look something like this: 602c9916cdSFrançois Tigeot * 612c9916cdSFrançois Tigeot * 1212 622c9916cdSFrançois Tigeot * 3434 632c9916cdSFrançois Tigeot * 642c9916cdSFrançois Tigeot * In this example both the size and layout of pages in the alternative view is 652c9916cdSFrançois Tigeot * different from the normal view. 662c9916cdSFrançois Tigeot * 672c9916cdSFrançois Tigeot * Implementation and usage 682c9916cdSFrançois Tigeot * 692c9916cdSFrançois Tigeot * GGTT views are implemented using VMAs and are distinguished via enum 702c9916cdSFrançois Tigeot * i915_ggtt_view_type and struct i915_ggtt_view. 712c9916cdSFrançois Tigeot * 722c9916cdSFrançois Tigeot * A new flavour of core GEM functions which work with GGTT bound objects were 73477eb7f9SFrançois Tigeot * added with the _ggtt_ infix, and sometimes with _view postfix to avoid 74477eb7f9SFrançois Tigeot * renaming in large amounts of code. They take the struct i915_ggtt_view 75477eb7f9SFrançois Tigeot * parameter encapsulating all metadata required to implement a view. 762c9916cdSFrançois Tigeot * 772c9916cdSFrançois Tigeot * As a helper for callers which are only interested in the normal view, 782c9916cdSFrançois Tigeot * globally const i915_ggtt_view_normal singleton instance exists. All old core 792c9916cdSFrançois Tigeot * GEM API functions, the ones not taking the view parameter, are operating on, 802c9916cdSFrançois Tigeot * or with the normal GGTT view. 812c9916cdSFrançois Tigeot * 822c9916cdSFrançois Tigeot * Code wanting to add or use a new GGTT view needs to: 832c9916cdSFrançois Tigeot * 842c9916cdSFrançois Tigeot * 1. Add a new enum with a suitable name. 852c9916cdSFrançois Tigeot * 2. Extend the metadata in the i915_ggtt_view structure if required. 862c9916cdSFrançois Tigeot * 3. Add support to i915_get_vma_pages(). 872c9916cdSFrançois Tigeot * 882c9916cdSFrançois Tigeot * New views are required to build a scatter-gather table from within the 892c9916cdSFrançois Tigeot * i915_get_vma_pages function. This table is stored in the vma.ggtt_view and 902c9916cdSFrançois Tigeot * exists for the lifetime of an VMA. 912c9916cdSFrançois Tigeot * 922c9916cdSFrançois Tigeot * Core API is designed to have copy semantics which means that passed in 932c9916cdSFrançois Tigeot * struct i915_ggtt_view does not need to be persistent (left around after 942c9916cdSFrançois Tigeot * calling the core API functions). 952c9916cdSFrançois Tigeot * 962c9916cdSFrançois Tigeot */ 972c9916cdSFrançois Tigeot 9819c468b4SFrançois Tigeot static int 9919c468b4SFrançois Tigeot i915_get_ggtt_vma_pages(struct i915_vma *vma); 10019c468b4SFrançois Tigeot 1012c9916cdSFrançois Tigeot const struct i915_ggtt_view i915_ggtt_view_normal; 102477eb7f9SFrançois Tigeot const struct i915_ggtt_view i915_ggtt_view_rotated = { 103477eb7f9SFrançois Tigeot .type = I915_GGTT_VIEW_ROTATED 104477eb7f9SFrançois Tigeot }; 1052c9916cdSFrançois Tigeot 10624edb884SFrançois Tigeot static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) 10724edb884SFrançois Tigeot { 1082c9916cdSFrançois Tigeot bool has_aliasing_ppgtt; 1092c9916cdSFrançois Tigeot bool has_full_ppgtt; 1102c9916cdSFrançois Tigeot 1112c9916cdSFrançois Tigeot has_aliasing_ppgtt = INTEL_INFO(dev)->gen >= 6; 1122c9916cdSFrançois Tigeot has_full_ppgtt = INTEL_INFO(dev)->gen >= 7; 1132c9916cdSFrançois Tigeot 114477eb7f9SFrançois Tigeot if (intel_vgpu_active(dev)) 115477eb7f9SFrançois Tigeot has_full_ppgtt = false; /* emulation is too hard */ 116477eb7f9SFrançois Tigeot 1172c9916cdSFrançois Tigeot /* 1182c9916cdSFrançois Tigeot * We don't allow disabling PPGTT for gen9+ as it's a requirement for 1192c9916cdSFrançois Tigeot * execlists, the sole mechanism available to submit work. 1202c9916cdSFrançois Tigeot */ 1212c9916cdSFrançois Tigeot if (INTEL_INFO(dev)->gen < 9 && 1222c9916cdSFrançois Tigeot (enable_ppgtt == 0 || !has_aliasing_ppgtt)) 12324edb884SFrançois Tigeot return 0; 12424edb884SFrançois Tigeot 12524edb884SFrançois Tigeot if (enable_ppgtt == 1) 12624edb884SFrançois Tigeot return 1; 12724edb884SFrançois Tigeot 1282c9916cdSFrançois Tigeot if (enable_ppgtt == 2 && has_full_ppgtt) 12924edb884SFrançois Tigeot return 2; 13024edb884SFrançois Tigeot 131ba55f2f5SFrançois Tigeot #ifdef CONFIG_INTEL_IOMMU 132ba55f2f5SFrançois Tigeot /* Disable ppgtt on SNB if VT-d is on. */ 133ba55f2f5SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) { 134ba55f2f5SFrançois Tigeot DRM_INFO("Disabling PPGTT because VT-d is on\n"); 13524edb884SFrançois Tigeot return 0; 136ba55f2f5SFrançois Tigeot } 137ba55f2f5SFrançois Tigeot #endif 138f4e1c372SFrançois Tigeot 13924edb884SFrançois Tigeot /* Early VLV doesn't have this */ 14024edb884SFrançois Tigeot if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && 14130d4b906SFrançois Tigeot dev->pdev->revision < 0xb) { 14224edb884SFrançois Tigeot DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n"); 14324edb884SFrançois Tigeot return 0; 14424edb884SFrançois Tigeot } 14524edb884SFrançois Tigeot 1462c9916cdSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8 && i915.enable_execlists) 1472c9916cdSFrançois Tigeot return 2; 1482c9916cdSFrançois Tigeot else 1492c9916cdSFrançois Tigeot return has_aliasing_ppgtt ? 1 : 0; 150ba55f2f5SFrançois Tigeot } 1519edbd4a0SFrançois Tigeot 15219c468b4SFrançois Tigeot static int ppgtt_bind_vma(struct i915_vma *vma, 153ba55f2f5SFrançois Tigeot enum i915_cache_level cache_level, 15419c468b4SFrançois Tigeot u32 unused) 15519c468b4SFrançois Tigeot { 15619c468b4SFrançois Tigeot u32 pte_flags = 0; 1579edbd4a0SFrançois Tigeot 15819c468b4SFrançois Tigeot /* Currently applicable only to VLV */ 15919c468b4SFrançois Tigeot if (vma->obj->gt_ro) 16019c468b4SFrançois Tigeot pte_flags |= PTE_READ_ONLY; 16119c468b4SFrançois Tigeot 16219c468b4SFrançois Tigeot vma->vm->insert_entries(vma->vm, vma->obj->pages, vma->node.start, 16319c468b4SFrançois Tigeot cache_level, pte_flags); 16419c468b4SFrançois Tigeot 16519c468b4SFrançois Tigeot return 0; 16619c468b4SFrançois Tigeot } 16719c468b4SFrançois Tigeot 16819c468b4SFrançois Tigeot static void ppgtt_unbind_vma(struct i915_vma *vma) 16919c468b4SFrançois Tigeot { 17019c468b4SFrançois Tigeot vma->vm->clear_range(vma->vm, 17119c468b4SFrançois Tigeot vma->node.start, 17219c468b4SFrançois Tigeot vma->obj->base.size, 17319c468b4SFrançois Tigeot true); 17419c468b4SFrançois Tigeot } 17519c468b4SFrançois Tigeot 17619c468b4SFrançois Tigeot static gen8_pte_t gen8_pte_encode(dma_addr_t addr, 1779edbd4a0SFrançois Tigeot enum i915_cache_level level, 1789edbd4a0SFrançois Tigeot bool valid) 1799edbd4a0SFrançois Tigeot { 180477eb7f9SFrançois Tigeot gen8_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0; 1819edbd4a0SFrançois Tigeot pte |= addr; 182ba55f2f5SFrançois Tigeot 183ba55f2f5SFrançois Tigeot switch (level) { 184ba55f2f5SFrançois Tigeot case I915_CACHE_NONE: 1859edbd4a0SFrançois Tigeot pte |= PPAT_UNCACHED_INDEX; 186ba55f2f5SFrançois Tigeot break; 187ba55f2f5SFrançois Tigeot case I915_CACHE_WT: 188ba55f2f5SFrançois Tigeot pte |= PPAT_DISPLAY_ELLC_INDEX; 189ba55f2f5SFrançois Tigeot break; 190ba55f2f5SFrançois Tigeot default: 191ba55f2f5SFrançois Tigeot pte |= PPAT_CACHED_INDEX; 192ba55f2f5SFrançois Tigeot break; 193ba55f2f5SFrançois Tigeot } 194ba55f2f5SFrançois Tigeot 1959edbd4a0SFrançois Tigeot return pte; 1969edbd4a0SFrançois Tigeot } 1979edbd4a0SFrançois Tigeot 198*a05eeebfSFrançois Tigeot static gen8_pde_t gen8_pde_encode(const dma_addr_t addr, 199*a05eeebfSFrançois Tigeot const enum i915_cache_level level) 200e3adcf8fSFrançois Tigeot { 201477eb7f9SFrançois Tigeot gen8_pde_t pde = _PAGE_PRESENT | _PAGE_RW; 2029edbd4a0SFrançois Tigeot pde |= addr; 2039edbd4a0SFrançois Tigeot if (level != I915_CACHE_NONE) 2049edbd4a0SFrançois Tigeot pde |= PPAT_CACHED_PDE_INDEX; 2059edbd4a0SFrançois Tigeot else 2069edbd4a0SFrançois Tigeot pde |= PPAT_UNCACHED_INDEX; 2079edbd4a0SFrançois Tigeot return pde; 2089edbd4a0SFrançois Tigeot } 2099edbd4a0SFrançois Tigeot 210477eb7f9SFrançois Tigeot static gen6_pte_t snb_pte_encode(dma_addr_t addr, 2119edbd4a0SFrançois Tigeot enum i915_cache_level level, 21224edb884SFrançois Tigeot bool valid, u32 unused) 2139edbd4a0SFrançois Tigeot { 214477eb7f9SFrançois Tigeot gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; 215f4e1c372SFrançois Tigeot pte |= GEN6_PTE_ADDR_ENCODE(addr); 216f4e1c372SFrançois Tigeot 217f4e1c372SFrançois Tigeot switch (level) { 2189edbd4a0SFrançois Tigeot case I915_CACHE_L3_LLC: 2199edbd4a0SFrançois Tigeot case I915_CACHE_LLC: 2209edbd4a0SFrançois Tigeot pte |= GEN6_PTE_CACHE_LLC; 2219edbd4a0SFrançois Tigeot break; 2229edbd4a0SFrançois Tigeot case I915_CACHE_NONE: 2239edbd4a0SFrançois Tigeot pte |= GEN6_PTE_UNCACHED; 2249edbd4a0SFrançois Tigeot break; 2259edbd4a0SFrançois Tigeot default: 2262c9916cdSFrançois Tigeot MISSING_CASE(level); 2279edbd4a0SFrançois Tigeot } 2289edbd4a0SFrançois Tigeot 2299edbd4a0SFrançois Tigeot return pte; 2309edbd4a0SFrançois Tigeot } 2319edbd4a0SFrançois Tigeot 232477eb7f9SFrançois Tigeot static gen6_pte_t ivb_pte_encode(dma_addr_t addr, 2339edbd4a0SFrançois Tigeot enum i915_cache_level level, 23424edb884SFrançois Tigeot bool valid, u32 unused) 2359edbd4a0SFrançois Tigeot { 236477eb7f9SFrançois Tigeot gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; 2379edbd4a0SFrançois Tigeot pte |= GEN6_PTE_ADDR_ENCODE(addr); 2389edbd4a0SFrançois Tigeot 2399edbd4a0SFrançois Tigeot switch (level) { 2409edbd4a0SFrançois Tigeot case I915_CACHE_L3_LLC: 2419edbd4a0SFrançois Tigeot pte |= GEN7_PTE_CACHE_L3_LLC; 242f4e1c372SFrançois Tigeot break; 243f4e1c372SFrançois Tigeot case I915_CACHE_LLC: 244f4e1c372SFrançois Tigeot pte |= GEN6_PTE_CACHE_LLC; 245f4e1c372SFrançois Tigeot break; 246f4e1c372SFrançois Tigeot case I915_CACHE_NONE: 247f4e1c372SFrançois Tigeot pte |= GEN6_PTE_UNCACHED; 248f4e1c372SFrançois Tigeot break; 249f4e1c372SFrançois Tigeot default: 2502c9916cdSFrançois Tigeot MISSING_CASE(level); 251f4e1c372SFrançois Tigeot } 252f4e1c372SFrançois Tigeot 253f4e1c372SFrançois Tigeot return pte; 254f4e1c372SFrançois Tigeot } 255f4e1c372SFrançois Tigeot 256477eb7f9SFrançois Tigeot static gen6_pte_t byt_pte_encode(dma_addr_t addr, 2579edbd4a0SFrançois Tigeot enum i915_cache_level level, 25824edb884SFrançois Tigeot bool valid, u32 flags) 2595d0b1887SFrançois Tigeot { 260477eb7f9SFrançois Tigeot gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; 2615d0b1887SFrançois Tigeot pte |= GEN6_PTE_ADDR_ENCODE(addr); 2625d0b1887SFrançois Tigeot 26324edb884SFrançois Tigeot if (!(flags & PTE_READ_ONLY)) 2645d0b1887SFrançois Tigeot pte |= BYT_PTE_WRITEABLE; 2655d0b1887SFrançois Tigeot 2665d0b1887SFrançois Tigeot if (level != I915_CACHE_NONE) 2675d0b1887SFrançois Tigeot pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES; 2685d0b1887SFrançois Tigeot 2695d0b1887SFrançois Tigeot return pte; 2705d0b1887SFrançois Tigeot } 2715d0b1887SFrançois Tigeot 272477eb7f9SFrançois Tigeot static gen6_pte_t hsw_pte_encode(dma_addr_t addr, 2739edbd4a0SFrançois Tigeot enum i915_cache_level level, 27424edb884SFrançois Tigeot bool valid, u32 unused) 2755d0b1887SFrançois Tigeot { 276477eb7f9SFrançois Tigeot gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; 2779edbd4a0SFrançois Tigeot pte |= HSW_PTE_ADDR_ENCODE(addr); 2785d0b1887SFrançois Tigeot 2795d0b1887SFrançois Tigeot if (level != I915_CACHE_NONE) 2809edbd4a0SFrançois Tigeot pte |= HSW_WB_LLC_AGE3; 2815d0b1887SFrançois Tigeot 2825d0b1887SFrançois Tigeot return pte; 2835d0b1887SFrançois Tigeot } 2845d0b1887SFrançois Tigeot 285477eb7f9SFrançois Tigeot static gen6_pte_t iris_pte_encode(dma_addr_t addr, 2869edbd4a0SFrançois Tigeot enum i915_cache_level level, 28724edb884SFrançois Tigeot bool valid, u32 unused) 2889edbd4a0SFrançois Tigeot { 289477eb7f9SFrançois Tigeot gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; 2909edbd4a0SFrançois Tigeot pte |= HSW_PTE_ADDR_ENCODE(addr); 2919edbd4a0SFrançois Tigeot 2929edbd4a0SFrançois Tigeot switch (level) { 2939edbd4a0SFrançois Tigeot case I915_CACHE_NONE: 2949edbd4a0SFrançois Tigeot break; 2959edbd4a0SFrançois Tigeot case I915_CACHE_WT: 2969edbd4a0SFrançois Tigeot pte |= HSW_WT_ELLC_LLC_AGE3; 2979edbd4a0SFrançois Tigeot break; 2989edbd4a0SFrançois Tigeot default: 2999edbd4a0SFrançois Tigeot pte |= HSW_WB_ELLC_LLC_AGE3; 3009edbd4a0SFrançois Tigeot break; 3019edbd4a0SFrançois Tigeot } 3029edbd4a0SFrançois Tigeot 3039edbd4a0SFrançois Tigeot return pte; 3049edbd4a0SFrançois Tigeot } 3059edbd4a0SFrançois Tigeot 306*a05eeebfSFrançois Tigeot static int __setup_page_dma(struct drm_device *dev, 307*a05eeebfSFrançois Tigeot struct i915_page_dma *p, gfp_t flags) 308477eb7f9SFrançois Tigeot { 309477eb7f9SFrançois Tigeot struct device *device = dev->pdev->dev; 310477eb7f9SFrançois Tigeot 311*a05eeebfSFrançois Tigeot p->page = alloc_page(flags); 312*a05eeebfSFrançois Tigeot if (!p->page) 313477eb7f9SFrançois Tigeot return -ENOMEM; 314477eb7f9SFrançois Tigeot 315*a05eeebfSFrançois Tigeot p->daddr = dma_map_page(device, 316*a05eeebfSFrançois Tigeot p->page, 0, 4096, PCI_DMA_BIDIRECTIONAL); 317*a05eeebfSFrançois Tigeot 318*a05eeebfSFrançois Tigeot if (dma_mapping_error(device, p->daddr)) { 319*a05eeebfSFrançois Tigeot __free_page(p->page); 320*a05eeebfSFrançois Tigeot return -EINVAL; 321*a05eeebfSFrançois Tigeot } 322*a05eeebfSFrançois Tigeot 323477eb7f9SFrançois Tigeot return 0; 324477eb7f9SFrançois Tigeot } 325477eb7f9SFrançois Tigeot 326*a05eeebfSFrançois Tigeot static int setup_page_dma(struct drm_device *dev, struct i915_page_dma *p) 327477eb7f9SFrançois Tigeot { 328*a05eeebfSFrançois Tigeot return __setup_page_dma(dev, p, GFP_KERNEL); 329*a05eeebfSFrançois Tigeot } 330*a05eeebfSFrançois Tigeot 331*a05eeebfSFrançois Tigeot static void cleanup_page_dma(struct drm_device *dev, struct i915_page_dma *p) 332*a05eeebfSFrançois Tigeot { 333*a05eeebfSFrançois Tigeot if (WARN_ON(!p->page)) 334477eb7f9SFrançois Tigeot return; 335477eb7f9SFrançois Tigeot 336*a05eeebfSFrançois Tigeot dma_unmap_page(dev->pdev->dev, p->daddr, 4096, PCI_DMA_BIDIRECTIONAL); 337*a05eeebfSFrançois Tigeot __free_page(p->page); 338*a05eeebfSFrançois Tigeot memset(p, 0, sizeof(*p)); 339477eb7f9SFrançois Tigeot } 340477eb7f9SFrançois Tigeot 341*a05eeebfSFrançois Tigeot static void *kmap_page_dma(struct i915_page_dma *p) 342477eb7f9SFrançois Tigeot { 343*a05eeebfSFrançois Tigeot return kmap_atomic(p->page); 34419c468b4SFrançois Tigeot } 34519c468b4SFrançois Tigeot 346*a05eeebfSFrançois Tigeot /* We use the flushing unmap only with ppgtt structures: 347*a05eeebfSFrançois Tigeot * page directories, page tables and scratch pages. 348*a05eeebfSFrançois Tigeot */ 349*a05eeebfSFrançois Tigeot static void kunmap_page_dma(struct drm_device *dev, void *vaddr) 350*a05eeebfSFrançois Tigeot { 351*a05eeebfSFrançois Tigeot /* There are only few exceptions for gen >=6. chv and bxt. 352*a05eeebfSFrançois Tigeot * And we are not sure about the latter so play safe for now. 353*a05eeebfSFrançois Tigeot */ 354*a05eeebfSFrançois Tigeot if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) 355*a05eeebfSFrançois Tigeot drm_clflush_virt_range(vaddr, PAGE_SIZE); 356*a05eeebfSFrançois Tigeot 357*a05eeebfSFrançois Tigeot kunmap_atomic(vaddr); 358*a05eeebfSFrançois Tigeot } 359*a05eeebfSFrançois Tigeot 360*a05eeebfSFrançois Tigeot #define kmap_px(px) kmap_page_dma(px_base(px)) 361*a05eeebfSFrançois Tigeot #define kunmap_px(ppgtt, vaddr) kunmap_page_dma((ppgtt)->base.dev, (vaddr)) 362*a05eeebfSFrançois Tigeot 363*a05eeebfSFrançois Tigeot #define setup_px(dev, px) setup_page_dma((dev), px_base(px)) 364*a05eeebfSFrançois Tigeot #define cleanup_px(dev, px) cleanup_page_dma((dev), px_base(px)) 365*a05eeebfSFrançois Tigeot #define fill_px(dev, px, v) fill_page_dma((dev), px_base(px), (v)) 366*a05eeebfSFrançois Tigeot #define fill32_px(dev, px, v) fill_page_dma_32((dev), px_base(px), (v)) 367*a05eeebfSFrançois Tigeot 368*a05eeebfSFrançois Tigeot static void fill_page_dma(struct drm_device *dev, struct i915_page_dma *p, 369*a05eeebfSFrançois Tigeot const uint64_t val) 370*a05eeebfSFrançois Tigeot { 371*a05eeebfSFrançois Tigeot int i; 372*a05eeebfSFrançois Tigeot uint64_t * const vaddr = kmap_page_dma(p); 373*a05eeebfSFrançois Tigeot 374*a05eeebfSFrançois Tigeot for (i = 0; i < 512; i++) 375*a05eeebfSFrançois Tigeot vaddr[i] = val; 376*a05eeebfSFrançois Tigeot 377*a05eeebfSFrançois Tigeot kunmap_page_dma(dev, vaddr); 378*a05eeebfSFrançois Tigeot } 379*a05eeebfSFrançois Tigeot 380*a05eeebfSFrançois Tigeot static void fill_page_dma_32(struct drm_device *dev, struct i915_page_dma *p, 381*a05eeebfSFrançois Tigeot const uint32_t val32) 382*a05eeebfSFrançois Tigeot { 383*a05eeebfSFrançois Tigeot uint64_t v = val32; 384*a05eeebfSFrançois Tigeot 385*a05eeebfSFrançois Tigeot v = v << 32 | val32; 386*a05eeebfSFrançois Tigeot 387*a05eeebfSFrançois Tigeot fill_page_dma(dev, p, v); 388*a05eeebfSFrançois Tigeot } 389*a05eeebfSFrançois Tigeot 390*a05eeebfSFrançois Tigeot static struct i915_page_scratch *alloc_scratch_page(struct drm_device *dev) 391*a05eeebfSFrançois Tigeot { 392*a05eeebfSFrançois Tigeot struct i915_page_scratch *sp; 393*a05eeebfSFrançois Tigeot int ret; 394*a05eeebfSFrançois Tigeot 395*a05eeebfSFrançois Tigeot sp = kzalloc(sizeof(*sp), GFP_KERNEL); 396*a05eeebfSFrançois Tigeot if (sp == NULL) 397*a05eeebfSFrançois Tigeot return ERR_PTR(-ENOMEM); 398*a05eeebfSFrançois Tigeot 399*a05eeebfSFrançois Tigeot ret = __setup_page_dma(dev, px_base(sp), GFP_DMA32 | __GFP_ZERO); 400*a05eeebfSFrançois Tigeot if (ret) { 401*a05eeebfSFrançois Tigeot kfree(sp); 402*a05eeebfSFrançois Tigeot return ERR_PTR(ret); 403*a05eeebfSFrançois Tigeot } 404*a05eeebfSFrançois Tigeot 405*a05eeebfSFrançois Tigeot set_pages_uc(px_page(sp), 1); 406*a05eeebfSFrançois Tigeot 407*a05eeebfSFrançois Tigeot return sp; 408*a05eeebfSFrançois Tigeot } 409*a05eeebfSFrançois Tigeot 410*a05eeebfSFrançois Tigeot static void free_scratch_page(struct drm_device *dev, 411*a05eeebfSFrançois Tigeot struct i915_page_scratch *sp) 412*a05eeebfSFrançois Tigeot { 413*a05eeebfSFrançois Tigeot set_pages_wb(px_page(sp), 1); 414*a05eeebfSFrançois Tigeot 415*a05eeebfSFrançois Tigeot cleanup_px(dev, sp); 416*a05eeebfSFrançois Tigeot kfree(sp); 417*a05eeebfSFrançois Tigeot } 418*a05eeebfSFrançois Tigeot 419*a05eeebfSFrançois Tigeot static struct i915_page_table *alloc_pt(struct drm_device *dev) 42019c468b4SFrançois Tigeot { 42119c468b4SFrançois Tigeot struct i915_page_table *pt; 422477eb7f9SFrançois Tigeot const size_t count = INTEL_INFO(dev)->gen >= 8 ? 423477eb7f9SFrançois Tigeot GEN8_PTES : GEN6_PTES; 424477eb7f9SFrançois Tigeot int ret = -ENOMEM; 425477eb7f9SFrançois Tigeot 426477eb7f9SFrançois Tigeot pt = kzalloc(sizeof(*pt), GFP_KERNEL); 427477eb7f9SFrançois Tigeot if (!pt) 428477eb7f9SFrançois Tigeot return ERR_PTR(-ENOMEM); 429477eb7f9SFrançois Tigeot 430477eb7f9SFrançois Tigeot pt->used_ptes = kcalloc(BITS_TO_LONGS(count), sizeof(*pt->used_ptes), 431477eb7f9SFrançois Tigeot GFP_KERNEL); 432477eb7f9SFrançois Tigeot 433477eb7f9SFrançois Tigeot if (!pt->used_ptes) 434477eb7f9SFrançois Tigeot goto fail_bitmap; 435477eb7f9SFrançois Tigeot 436*a05eeebfSFrançois Tigeot ret = setup_px(dev, pt); 437477eb7f9SFrançois Tigeot if (ret) 438*a05eeebfSFrançois Tigeot goto fail_page_m; 439477eb7f9SFrançois Tigeot 440477eb7f9SFrançois Tigeot return pt; 441477eb7f9SFrançois Tigeot 442*a05eeebfSFrançois Tigeot fail_page_m: 443477eb7f9SFrançois Tigeot kfree(pt->used_ptes); 444477eb7f9SFrançois Tigeot fail_bitmap: 445477eb7f9SFrançois Tigeot kfree(pt); 446477eb7f9SFrançois Tigeot 447477eb7f9SFrançois Tigeot return ERR_PTR(ret); 448477eb7f9SFrançois Tigeot } 449477eb7f9SFrançois Tigeot 450*a05eeebfSFrançois Tigeot static void free_pt(struct drm_device *dev, struct i915_page_table *pt) 451*a05eeebfSFrançois Tigeot { 452*a05eeebfSFrançois Tigeot cleanup_px(dev, pt); 453*a05eeebfSFrançois Tigeot kfree(pt->used_ptes); 454*a05eeebfSFrançois Tigeot kfree(pt); 455*a05eeebfSFrançois Tigeot } 456*a05eeebfSFrançois Tigeot 457477eb7f9SFrançois Tigeot /** 458477eb7f9SFrançois Tigeot * alloc_pt_range() - Allocate a multiple page tables 459477eb7f9SFrançois Tigeot * @pd: The page directory which will have at least @count entries 460477eb7f9SFrançois Tigeot * available to point to the allocated page tables. 461477eb7f9SFrançois Tigeot * @pde: First page directory entry for which we are allocating. 462477eb7f9SFrançois Tigeot * @count: Number of pages to allocate. 463477eb7f9SFrançois Tigeot * @dev: DRM device. 464477eb7f9SFrançois Tigeot * 465477eb7f9SFrançois Tigeot * Allocates multiple page table pages and sets the appropriate entries in the 466477eb7f9SFrançois Tigeot * page table structure within the page directory. Function cleans up after 467477eb7f9SFrançois Tigeot * itself on any failures. 468477eb7f9SFrançois Tigeot * 469477eb7f9SFrançois Tigeot * Return: 0 if allocation succeeded. 470477eb7f9SFrançois Tigeot */ 47119c468b4SFrançois Tigeot static int alloc_pt_range(struct i915_page_directory *pd, uint16_t pde, size_t count, 472477eb7f9SFrançois Tigeot struct drm_device *dev) 473477eb7f9SFrançois Tigeot { 474477eb7f9SFrançois Tigeot int i, ret; 475477eb7f9SFrançois Tigeot 476477eb7f9SFrançois Tigeot /* 512 is the max page tables per page_directory on any platform. */ 477477eb7f9SFrançois Tigeot if (WARN_ON(pde + count > I915_PDES)) 478477eb7f9SFrançois Tigeot return -EINVAL; 479477eb7f9SFrançois Tigeot 480477eb7f9SFrançois Tigeot for (i = pde; i < pde + count; i++) { 481*a05eeebfSFrançois Tigeot struct i915_page_table *pt = alloc_pt(dev); 482477eb7f9SFrançois Tigeot 483477eb7f9SFrançois Tigeot if (IS_ERR(pt)) { 484477eb7f9SFrançois Tigeot ret = PTR_ERR(pt); 485477eb7f9SFrançois Tigeot goto err_out; 486477eb7f9SFrançois Tigeot } 487477eb7f9SFrançois Tigeot WARN(pd->page_table[i], 488477eb7f9SFrançois Tigeot "Leaking page directory entry %d (%p)\n", 489477eb7f9SFrançois Tigeot i, pd->page_table[i]); 490477eb7f9SFrançois Tigeot pd->page_table[i] = pt; 491477eb7f9SFrançois Tigeot } 492477eb7f9SFrançois Tigeot 493477eb7f9SFrançois Tigeot return 0; 494477eb7f9SFrançois Tigeot 495477eb7f9SFrançois Tigeot err_out: 496477eb7f9SFrançois Tigeot while (i-- > pde) 497*a05eeebfSFrançois Tigeot free_pt(dev, pd->page_table[i]); 498477eb7f9SFrançois Tigeot return ret; 499477eb7f9SFrançois Tigeot } 500477eb7f9SFrançois Tigeot 501*a05eeebfSFrançois Tigeot static void gen8_initialize_pt(struct i915_address_space *vm, 502*a05eeebfSFrançois Tigeot struct i915_page_table *pt) 503477eb7f9SFrançois Tigeot { 504*a05eeebfSFrançois Tigeot gen8_pte_t scratch_pte; 505*a05eeebfSFrançois Tigeot 506*a05eeebfSFrançois Tigeot scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), 507*a05eeebfSFrançois Tigeot I915_CACHE_LLC, true); 508*a05eeebfSFrançois Tigeot 509*a05eeebfSFrançois Tigeot fill_px(vm->dev, pt, scratch_pte); 510477eb7f9SFrançois Tigeot } 511477eb7f9SFrançois Tigeot 512*a05eeebfSFrançois Tigeot static void gen6_initialize_pt(struct i915_address_space *vm, 513*a05eeebfSFrançois Tigeot struct i915_page_table *pt) 514*a05eeebfSFrançois Tigeot { 515*a05eeebfSFrançois Tigeot gen6_pte_t scratch_pte; 516*a05eeebfSFrançois Tigeot 517*a05eeebfSFrançois Tigeot WARN_ON(px_dma(vm->scratch_page) == 0); 518*a05eeebfSFrançois Tigeot 519*a05eeebfSFrançois Tigeot scratch_pte = vm->pte_encode(px_dma(vm->scratch_page), 520*a05eeebfSFrançois Tigeot I915_CACHE_LLC, true, 0); 521*a05eeebfSFrançois Tigeot 522*a05eeebfSFrançois Tigeot fill32_px(vm->dev, pt, scratch_pte); 523*a05eeebfSFrançois Tigeot } 524*a05eeebfSFrançois Tigeot 525*a05eeebfSFrançois Tigeot static struct i915_page_directory *alloc_pd(struct drm_device *dev) 526477eb7f9SFrançois Tigeot { 52719c468b4SFrançois Tigeot struct i915_page_directory *pd; 52819c468b4SFrançois Tigeot int ret = -ENOMEM; 529477eb7f9SFrançois Tigeot 530477eb7f9SFrançois Tigeot pd = kzalloc(sizeof(*pd), GFP_KERNEL); 531477eb7f9SFrançois Tigeot if (!pd) 532477eb7f9SFrançois Tigeot return ERR_PTR(-ENOMEM); 533477eb7f9SFrançois Tigeot 53419c468b4SFrançois Tigeot pd->used_pdes = kcalloc(BITS_TO_LONGS(I915_PDES), 53519c468b4SFrançois Tigeot sizeof(*pd->used_pdes), GFP_KERNEL); 53619c468b4SFrançois Tigeot if (!pd->used_pdes) 537*a05eeebfSFrançois Tigeot goto fail_bitmap; 53819c468b4SFrançois Tigeot 539*a05eeebfSFrançois Tigeot ret = setup_px(dev, pd); 54019c468b4SFrançois Tigeot if (ret) 541*a05eeebfSFrançois Tigeot goto fail_page_m; 542477eb7f9SFrançois Tigeot 543477eb7f9SFrançois Tigeot return pd; 54419c468b4SFrançois Tigeot 545*a05eeebfSFrançois Tigeot fail_page_m: 54619c468b4SFrançois Tigeot kfree(pd->used_pdes); 547*a05eeebfSFrançois Tigeot fail_bitmap: 54819c468b4SFrançois Tigeot kfree(pd); 54919c468b4SFrançois Tigeot 55019c468b4SFrançois Tigeot return ERR_PTR(ret); 551477eb7f9SFrançois Tigeot } 552477eb7f9SFrançois Tigeot 553*a05eeebfSFrançois Tigeot static void free_pd(struct drm_device *dev, struct i915_page_directory *pd) 554*a05eeebfSFrançois Tigeot { 555*a05eeebfSFrançois Tigeot if (px_page(pd)) { 556*a05eeebfSFrançois Tigeot cleanup_px(dev, pd); 557*a05eeebfSFrançois Tigeot kfree(pd->used_pdes); 558*a05eeebfSFrançois Tigeot kfree(pd); 559*a05eeebfSFrançois Tigeot } 560*a05eeebfSFrançois Tigeot } 561*a05eeebfSFrançois Tigeot 562*a05eeebfSFrançois Tigeot static void gen8_initialize_pd(struct i915_address_space *vm, 563*a05eeebfSFrançois Tigeot struct i915_page_directory *pd) 564*a05eeebfSFrançois Tigeot { 565*a05eeebfSFrançois Tigeot gen8_pde_t scratch_pde; 566*a05eeebfSFrançois Tigeot 567*a05eeebfSFrançois Tigeot scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC); 568*a05eeebfSFrançois Tigeot 569*a05eeebfSFrançois Tigeot fill_px(vm->dev, pd, scratch_pde); 570*a05eeebfSFrançois Tigeot } 571*a05eeebfSFrançois Tigeot 5729edbd4a0SFrançois Tigeot /* Broadwell Page Directory Pointer Descriptors */ 573*a05eeebfSFrançois Tigeot static int gen8_write_pdp(struct drm_i915_gem_request *req, 57419c468b4SFrançois Tigeot unsigned entry, 57519c468b4SFrançois Tigeot dma_addr_t addr) 5769edbd4a0SFrançois Tigeot { 577*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 5789edbd4a0SFrançois Tigeot int ret; 5799edbd4a0SFrançois Tigeot 5809edbd4a0SFrançois Tigeot BUG_ON(entry >= 4); 5819edbd4a0SFrançois Tigeot 582*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 5839edbd4a0SFrançois Tigeot if (ret) 5849edbd4a0SFrançois Tigeot return ret; 5859edbd4a0SFrançois Tigeot 5869edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 5879edbd4a0SFrançois Tigeot intel_ring_emit(ring, GEN8_RING_PDP_UDW(ring, entry)); 58819c468b4SFrançois Tigeot intel_ring_emit(ring, upper_32_bits(addr)); 5899edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 5909edbd4a0SFrançois Tigeot intel_ring_emit(ring, GEN8_RING_PDP_LDW(ring, entry)); 59119c468b4SFrançois Tigeot intel_ring_emit(ring, lower_32_bits(addr)); 5929edbd4a0SFrançois Tigeot intel_ring_advance(ring); 5939edbd4a0SFrançois Tigeot 5949edbd4a0SFrançois Tigeot return 0; 5959edbd4a0SFrançois Tigeot } 5969edbd4a0SFrançois Tigeot 597ba55f2f5SFrançois Tigeot static int gen8_mm_switch(struct i915_hw_ppgtt *ppgtt, 598*a05eeebfSFrançois Tigeot struct drm_i915_gem_request *req) 5999edbd4a0SFrançois Tigeot { 600ba55f2f5SFrançois Tigeot int i, ret; 6019edbd4a0SFrançois Tigeot 60219c468b4SFrançois Tigeot for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) { 603*a05eeebfSFrançois Tigeot const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i); 604*a05eeebfSFrançois Tigeot 605*a05eeebfSFrançois Tigeot ret = gen8_write_pdp(req, i, pd_daddr); 6069edbd4a0SFrançois Tigeot if (ret) 6079edbd4a0SFrançois Tigeot return ret; 6089edbd4a0SFrançois Tigeot } 6099edbd4a0SFrançois Tigeot 610ba55f2f5SFrançois Tigeot return 0; 611ba55f2f5SFrançois Tigeot } 612ba55f2f5SFrançois Tigeot 6139edbd4a0SFrançois Tigeot static void gen8_ppgtt_clear_range(struct i915_address_space *vm, 614ba55f2f5SFrançois Tigeot uint64_t start, 615ba55f2f5SFrançois Tigeot uint64_t length, 6169edbd4a0SFrançois Tigeot bool use_scratch) 6179edbd4a0SFrançois Tigeot { 6189edbd4a0SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = 6199edbd4a0SFrançois Tigeot container_of(vm, struct i915_hw_ppgtt, base); 620477eb7f9SFrançois Tigeot gen8_pte_t *pt_vaddr, scratch_pte; 621ba55f2f5SFrançois Tigeot unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK; 622ba55f2f5SFrançois Tigeot unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK; 623ba55f2f5SFrançois Tigeot unsigned pte = start >> GEN8_PTE_SHIFT & GEN8_PTE_MASK; 624ba55f2f5SFrançois Tigeot unsigned num_entries = length >> PAGE_SHIFT; 6259edbd4a0SFrançois Tigeot unsigned last_pte, i; 6269edbd4a0SFrançois Tigeot 627*a05eeebfSFrançois Tigeot scratch_pte = gen8_pte_encode(px_dma(ppgtt->base.scratch_page), 6289edbd4a0SFrançois Tigeot I915_CACHE_LLC, use_scratch); 6299edbd4a0SFrançois Tigeot 6309edbd4a0SFrançois Tigeot while (num_entries) { 63119c468b4SFrançois Tigeot struct i915_page_directory *pd; 63219c468b4SFrançois Tigeot struct i915_page_table *pt; 633477eb7f9SFrançois Tigeot 634477eb7f9SFrançois Tigeot if (WARN_ON(!ppgtt->pdp.page_directory[pdpe])) 635*a05eeebfSFrançois Tigeot continue; 636477eb7f9SFrançois Tigeot 637477eb7f9SFrançois Tigeot pd = ppgtt->pdp.page_directory[pdpe]; 638477eb7f9SFrançois Tigeot 639477eb7f9SFrançois Tigeot if (WARN_ON(!pd->page_table[pde])) 640*a05eeebfSFrançois Tigeot continue; 641477eb7f9SFrançois Tigeot 642477eb7f9SFrançois Tigeot pt = pd->page_table[pde]; 643477eb7f9SFrançois Tigeot 644*a05eeebfSFrançois Tigeot if (WARN_ON(!px_page(pt))) 645*a05eeebfSFrançois Tigeot continue; 6469edbd4a0SFrançois Tigeot 647ba55f2f5SFrançois Tigeot last_pte = pte + num_entries; 648477eb7f9SFrançois Tigeot if (last_pte > GEN8_PTES) 649477eb7f9SFrançois Tigeot last_pte = GEN8_PTES; 6509edbd4a0SFrançois Tigeot 651*a05eeebfSFrançois Tigeot pt_vaddr = kmap_px(pt); 6529edbd4a0SFrançois Tigeot 653ba55f2f5SFrançois Tigeot for (i = pte; i < last_pte; i++) { 6549edbd4a0SFrançois Tigeot pt_vaddr[i] = scratch_pte; 655ba55f2f5SFrançois Tigeot num_entries--; 656ba55f2f5SFrançois Tigeot } 6579edbd4a0SFrançois Tigeot 658*a05eeebfSFrançois Tigeot kunmap_px(ppgtt, pt); 6599edbd4a0SFrançois Tigeot 660ba55f2f5SFrançois Tigeot pte = 0; 661477eb7f9SFrançois Tigeot if (++pde == I915_PDES) { 662ba55f2f5SFrançois Tigeot pdpe++; 663ba55f2f5SFrançois Tigeot pde = 0; 664ba55f2f5SFrançois Tigeot } 6659edbd4a0SFrançois Tigeot } 6669edbd4a0SFrançois Tigeot } 6679edbd4a0SFrançois Tigeot 6689edbd4a0SFrançois Tigeot static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, 6697ec9f8e5SFrançois Tigeot struct sg_table *pages, 670ba55f2f5SFrançois Tigeot uint64_t start, 67124edb884SFrançois Tigeot enum i915_cache_level cache_level, u32 unused) 6729edbd4a0SFrançois Tigeot { 6739edbd4a0SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = 6749edbd4a0SFrançois Tigeot container_of(vm, struct i915_hw_ppgtt, base); 675477eb7f9SFrançois Tigeot gen8_pte_t *pt_vaddr; 676ba55f2f5SFrançois Tigeot unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK; 677ba55f2f5SFrançois Tigeot unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK; 678ba55f2f5SFrançois Tigeot unsigned pte = start >> GEN8_PTE_SHIFT & GEN8_PTE_MASK; 6797ec9f8e5SFrançois Tigeot struct sg_page_iter sg_iter; 6809edbd4a0SFrançois Tigeot 6819edbd4a0SFrançois Tigeot pt_vaddr = NULL; 6829edbd4a0SFrançois Tigeot 6837ec9f8e5SFrançois Tigeot for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) { 684477eb7f9SFrançois Tigeot if (WARN_ON(pdpe >= GEN8_LEGACY_PDPES)) 685ba55f2f5SFrançois Tigeot break; 686ba55f2f5SFrançois Tigeot 687477eb7f9SFrançois Tigeot if (pt_vaddr == NULL) { 68819c468b4SFrançois Tigeot struct i915_page_directory *pd = ppgtt->pdp.page_directory[pdpe]; 68919c468b4SFrançois Tigeot struct i915_page_table *pt = pd->page_table[pde]; 690477eb7f9SFrançois Tigeot 691*a05eeebfSFrançois Tigeot pt_vaddr = kmap_px(pt); 692477eb7f9SFrançois Tigeot } 693ba55f2f5SFrançois Tigeot 694ba55f2f5SFrançois Tigeot pt_vaddr[pte] = 6957ec9f8e5SFrançois Tigeot gen8_pte_encode(sg_page_iter_dma_address(&sg_iter), 6969edbd4a0SFrançois Tigeot cache_level, true); 697477eb7f9SFrançois Tigeot if (++pte == GEN8_PTES) { 698*a05eeebfSFrançois Tigeot kunmap_px(ppgtt, pt_vaddr); 6999edbd4a0SFrançois Tigeot pt_vaddr = NULL; 700477eb7f9SFrançois Tigeot if (++pde == I915_PDES) { 701ba55f2f5SFrançois Tigeot pdpe++; 702ba55f2f5SFrançois Tigeot pde = 0; 703ba55f2f5SFrançois Tigeot } 704ba55f2f5SFrançois Tigeot pte = 0; 7059edbd4a0SFrançois Tigeot } 7069edbd4a0SFrançois Tigeot } 707*a05eeebfSFrançois Tigeot 708*a05eeebfSFrançois Tigeot if (pt_vaddr) 709*a05eeebfSFrançois Tigeot kunmap_px(ppgtt, pt_vaddr); 710ba55f2f5SFrançois Tigeot } 711ba55f2f5SFrançois Tigeot 712*a05eeebfSFrançois Tigeot static void gen8_free_page_tables(struct drm_device *dev, 71319c468b4SFrançois Tigeot struct i915_page_directory *pd) 71419c468b4SFrançois Tigeot { 71519c468b4SFrançois Tigeot int i; 71619c468b4SFrançois Tigeot 717*a05eeebfSFrançois Tigeot if (!px_page(pd)) 718ba55f2f5SFrançois Tigeot return; 719ba55f2f5SFrançois Tigeot 72019c468b4SFrançois Tigeot for_each_set_bit(i, pd->used_pdes, I915_PDES) { 721477eb7f9SFrançois Tigeot if (WARN_ON(!pd->page_table[i])) 722477eb7f9SFrançois Tigeot continue; 723477eb7f9SFrançois Tigeot 724*a05eeebfSFrançois Tigeot free_pt(dev, pd->page_table[i]); 725477eb7f9SFrançois Tigeot pd->page_table[i] = NULL; 726477eb7f9SFrançois Tigeot } 727ba55f2f5SFrançois Tigeot } 728ba55f2f5SFrançois Tigeot 729*a05eeebfSFrançois Tigeot static int gen8_init_scratch(struct i915_address_space *vm) 730*a05eeebfSFrançois Tigeot { 731*a05eeebfSFrançois Tigeot struct drm_device *dev = vm->dev; 732*a05eeebfSFrançois Tigeot 733*a05eeebfSFrançois Tigeot vm->scratch_page = alloc_scratch_page(dev); 734*a05eeebfSFrançois Tigeot if (IS_ERR(vm->scratch_page)) 735*a05eeebfSFrançois Tigeot return PTR_ERR(vm->scratch_page); 736*a05eeebfSFrançois Tigeot 737*a05eeebfSFrançois Tigeot vm->scratch_pt = alloc_pt(dev); 738*a05eeebfSFrançois Tigeot if (IS_ERR(vm->scratch_pt)) { 739*a05eeebfSFrançois Tigeot free_scratch_page(dev, vm->scratch_page); 740*a05eeebfSFrançois Tigeot return PTR_ERR(vm->scratch_pt); 741*a05eeebfSFrançois Tigeot } 742*a05eeebfSFrançois Tigeot 743*a05eeebfSFrançois Tigeot vm->scratch_pd = alloc_pd(dev); 744*a05eeebfSFrançois Tigeot if (IS_ERR(vm->scratch_pd)) { 745*a05eeebfSFrançois Tigeot free_pt(dev, vm->scratch_pt); 746*a05eeebfSFrançois Tigeot free_scratch_page(dev, vm->scratch_page); 747*a05eeebfSFrançois Tigeot return PTR_ERR(vm->scratch_pd); 748*a05eeebfSFrançois Tigeot } 749*a05eeebfSFrançois Tigeot 750*a05eeebfSFrançois Tigeot gen8_initialize_pt(vm, vm->scratch_pt); 751*a05eeebfSFrançois Tigeot gen8_initialize_pd(vm, vm->scratch_pd); 752*a05eeebfSFrançois Tigeot 753*a05eeebfSFrançois Tigeot return 0; 754*a05eeebfSFrançois Tigeot } 755*a05eeebfSFrançois Tigeot 756*a05eeebfSFrançois Tigeot static void gen8_free_scratch(struct i915_address_space *vm) 757*a05eeebfSFrançois Tigeot { 758*a05eeebfSFrançois Tigeot struct drm_device *dev = vm->dev; 759*a05eeebfSFrançois Tigeot 760*a05eeebfSFrançois Tigeot free_pd(dev, vm->scratch_pd); 761*a05eeebfSFrançois Tigeot free_pt(dev, vm->scratch_pt); 762*a05eeebfSFrançois Tigeot free_scratch_page(dev, vm->scratch_page); 763*a05eeebfSFrançois Tigeot } 764*a05eeebfSFrançois Tigeot 7659edbd4a0SFrançois Tigeot static void gen8_ppgtt_cleanup(struct i915_address_space *vm) 7669edbd4a0SFrançois Tigeot { 7679edbd4a0SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = 7689edbd4a0SFrançois Tigeot container_of(vm, struct i915_hw_ppgtt, base); 76919c468b4SFrançois Tigeot int i; 7709edbd4a0SFrançois Tigeot 77119c468b4SFrançois Tigeot for_each_set_bit(i, ppgtt->pdp.used_pdpes, GEN8_LEGACY_PDPES) { 77219c468b4SFrançois Tigeot if (WARN_ON(!ppgtt->pdp.page_directory[i])) 77319c468b4SFrançois Tigeot continue; 77419c468b4SFrançois Tigeot 775*a05eeebfSFrançois Tigeot gen8_free_page_tables(ppgtt->base.dev, 776*a05eeebfSFrançois Tigeot ppgtt->pdp.page_directory[i]); 777*a05eeebfSFrançois Tigeot free_pd(ppgtt->base.dev, ppgtt->pdp.page_directory[i]); 7789edbd4a0SFrançois Tigeot } 7799edbd4a0SFrançois Tigeot 780*a05eeebfSFrançois Tigeot gen8_free_scratch(vm); 78119c468b4SFrançois Tigeot } 782ba55f2f5SFrançois Tigeot 78319c468b4SFrançois Tigeot /** 78419c468b4SFrançois Tigeot * gen8_ppgtt_alloc_pagetabs() - Allocate page tables for VA range. 78519c468b4SFrançois Tigeot * @ppgtt: Master ppgtt structure. 78619c468b4SFrançois Tigeot * @pd: Page directory for this address range. 78719c468b4SFrançois Tigeot * @start: Starting virtual address to begin allocations. 78819c468b4SFrançois Tigeot * @length Size of the allocations. 78919c468b4SFrançois Tigeot * @new_pts: Bitmap set by function with new allocations. Likely used by the 79019c468b4SFrançois Tigeot * caller to free on error. 79119c468b4SFrançois Tigeot * 79219c468b4SFrançois Tigeot * Allocate the required number of page tables. Extremely similar to 79319c468b4SFrançois Tigeot * gen8_ppgtt_alloc_page_directories(). The main difference is here we are limited by 79419c468b4SFrançois Tigeot * the page directory boundary (instead of the page directory pointer). That 79519c468b4SFrançois Tigeot * boundary is 1GB virtual. Therefore, unlike gen8_ppgtt_alloc_page_directories(), it is 79619c468b4SFrançois Tigeot * possible, and likely that the caller will need to use multiple calls of this 79719c468b4SFrançois Tigeot * function to achieve the appropriate allocation. 79819c468b4SFrançois Tigeot * 79919c468b4SFrançois Tigeot * Return: 0 if success; negative error code otherwise. 80019c468b4SFrançois Tigeot */ 80119c468b4SFrançois Tigeot static int gen8_ppgtt_alloc_pagetabs(struct i915_hw_ppgtt *ppgtt, 80219c468b4SFrançois Tigeot struct i915_page_directory *pd, 80319c468b4SFrançois Tigeot uint64_t start, 80419c468b4SFrançois Tigeot uint64_t length, 80519c468b4SFrançois Tigeot unsigned long *new_pts) 80619c468b4SFrançois Tigeot { 80719c468b4SFrançois Tigeot struct drm_device *dev = ppgtt->base.dev; 80819c468b4SFrançois Tigeot struct i915_page_table *pt; 80919c468b4SFrançois Tigeot uint64_t temp; 81019c468b4SFrançois Tigeot uint32_t pde; 81119c468b4SFrançois Tigeot 81219c468b4SFrançois Tigeot gen8_for_each_pde(pt, pd, start, length, temp, pde) { 81319c468b4SFrançois Tigeot /* Don't reallocate page tables */ 81419c468b4SFrançois Tigeot if (pt) { 81519c468b4SFrançois Tigeot /* Scratch is never allocated this way */ 816*a05eeebfSFrançois Tigeot WARN_ON(pt == ppgtt->base.scratch_pt); 81719c468b4SFrançois Tigeot continue; 81819c468b4SFrançois Tigeot } 81919c468b4SFrançois Tigeot 820*a05eeebfSFrançois Tigeot pt = alloc_pt(dev); 82119c468b4SFrançois Tigeot if (IS_ERR(pt)) 822ba55f2f5SFrançois Tigeot goto unwind_out; 82319c468b4SFrançois Tigeot 82419c468b4SFrançois Tigeot gen8_initialize_pt(&ppgtt->base, pt); 82519c468b4SFrançois Tigeot pd->page_table[pde] = pt; 826*a05eeebfSFrançois Tigeot __set_bit(pde, new_pts); 827ba55f2f5SFrançois Tigeot } 828ba55f2f5SFrançois Tigeot 829ba55f2f5SFrançois Tigeot return 0; 830ba55f2f5SFrançois Tigeot 831ba55f2f5SFrançois Tigeot unwind_out: 83219c468b4SFrançois Tigeot for_each_set_bit(pde, new_pts, I915_PDES) 833*a05eeebfSFrançois Tigeot free_pt(dev, pd->page_table[pde]); 834ba55f2f5SFrançois Tigeot 835ba55f2f5SFrançois Tigeot return -ENOMEM; 836ba55f2f5SFrançois Tigeot } 837ba55f2f5SFrançois Tigeot 83819c468b4SFrançois Tigeot /** 83919c468b4SFrançois Tigeot * gen8_ppgtt_alloc_page_directories() - Allocate page directories for VA range. 84019c468b4SFrançois Tigeot * @ppgtt: Master ppgtt structure. 84119c468b4SFrançois Tigeot * @pdp: Page directory pointer for this address range. 84219c468b4SFrançois Tigeot * @start: Starting virtual address to begin allocations. 84319c468b4SFrançois Tigeot * @length Size of the allocations. 84419c468b4SFrançois Tigeot * @new_pds Bitmap set by function with new allocations. Likely used by the 84519c468b4SFrançois Tigeot * caller to free on error. 84619c468b4SFrançois Tigeot * 84719c468b4SFrançois Tigeot * Allocate the required number of page directories starting at the pde index of 84819c468b4SFrançois Tigeot * @start, and ending at the pde index @start + @length. This function will skip 84919c468b4SFrançois Tigeot * over already allocated page directories within the range, and only allocate 85019c468b4SFrançois Tigeot * new ones, setting the appropriate pointer within the pdp as well as the 85119c468b4SFrançois Tigeot * correct position in the bitmap @new_pds. 85219c468b4SFrançois Tigeot * 85319c468b4SFrançois Tigeot * The function will only allocate the pages within the range for a give page 85419c468b4SFrançois Tigeot * directory pointer. In other words, if @start + @length straddles a virtually 85519c468b4SFrançois Tigeot * addressed PDP boundary (512GB for 4k pages), there will be more allocations 85619c468b4SFrançois Tigeot * required by the caller, This is not currently possible, and the BUG in the 85719c468b4SFrançois Tigeot * code will prevent it. 85819c468b4SFrançois Tigeot * 85919c468b4SFrançois Tigeot * Return: 0 if success; negative error code otherwise. 86019c468b4SFrançois Tigeot */ 86119c468b4SFrançois Tigeot static int gen8_ppgtt_alloc_page_directories(struct i915_hw_ppgtt *ppgtt, 86219c468b4SFrançois Tigeot struct i915_page_directory_pointer *pdp, 86319c468b4SFrançois Tigeot uint64_t start, 86419c468b4SFrançois Tigeot uint64_t length, 86519c468b4SFrançois Tigeot unsigned long *new_pds) 86619c468b4SFrançois Tigeot { 86719c468b4SFrançois Tigeot struct drm_device *dev = ppgtt->base.dev; 86819c468b4SFrançois Tigeot struct i915_page_directory *pd; 86919c468b4SFrançois Tigeot uint64_t temp; 87019c468b4SFrançois Tigeot uint32_t pdpe; 87119c468b4SFrançois Tigeot 87219c468b4SFrançois Tigeot WARN_ON(!bitmap_empty(new_pds, GEN8_LEGACY_PDPES)); 87319c468b4SFrançois Tigeot 87419c468b4SFrançois Tigeot gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) { 87519c468b4SFrançois Tigeot if (pd) 87619c468b4SFrançois Tigeot continue; 87719c468b4SFrançois Tigeot 878*a05eeebfSFrançois Tigeot pd = alloc_pd(dev); 87919c468b4SFrançois Tigeot if (IS_ERR(pd)) 88019c468b4SFrançois Tigeot goto unwind_out; 88119c468b4SFrançois Tigeot 88219c468b4SFrançois Tigeot gen8_initialize_pd(&ppgtt->base, pd); 88319c468b4SFrançois Tigeot pdp->page_directory[pdpe] = pd; 884*a05eeebfSFrançois Tigeot __set_bit(pdpe, new_pds); 88519c468b4SFrançois Tigeot } 88619c468b4SFrançois Tigeot 88719c468b4SFrançois Tigeot return 0; 88819c468b4SFrançois Tigeot 88919c468b4SFrançois Tigeot unwind_out: 89019c468b4SFrançois Tigeot for_each_set_bit(pdpe, new_pds, GEN8_LEGACY_PDPES) 891*a05eeebfSFrançois Tigeot free_pd(dev, pdp->page_directory[pdpe]); 89219c468b4SFrançois Tigeot 89319c468b4SFrançois Tigeot return -ENOMEM; 89419c468b4SFrançois Tigeot } 89519c468b4SFrançois Tigeot 89619c468b4SFrançois Tigeot static void 89719c468b4SFrançois Tigeot free_gen8_temp_bitmaps(unsigned long *new_pds, unsigned long **new_pts) 898ba55f2f5SFrançois Tigeot { 899477eb7f9SFrançois Tigeot int i; 9009edbd4a0SFrançois Tigeot 90119c468b4SFrançois Tigeot for (i = 0; i < GEN8_LEGACY_PDPES; i++) 90219c468b4SFrançois Tigeot kfree(new_pts[i]); 90319c468b4SFrançois Tigeot kfree(new_pts); 90419c468b4SFrançois Tigeot kfree(new_pds); 905477eb7f9SFrançois Tigeot } 906477eb7f9SFrançois Tigeot 90719c468b4SFrançois Tigeot /* Fills in the page directory bitmap, and the array of page tables bitmap. Both 90819c468b4SFrançois Tigeot * of these are based on the number of PDPEs in the system. 90919c468b4SFrançois Tigeot */ 91019c468b4SFrançois Tigeot static 91119c468b4SFrançois Tigeot int __must_check alloc_gen8_temp_bitmaps(unsigned long **new_pds, 91219c468b4SFrançois Tigeot unsigned long ***new_pts) 91319c468b4SFrançois Tigeot { 91419c468b4SFrançois Tigeot int i; 91519c468b4SFrançois Tigeot unsigned long *pds; 91619c468b4SFrançois Tigeot unsigned long **pts; 9179edbd4a0SFrançois Tigeot 91819c468b4SFrançois Tigeot pds = kcalloc(BITS_TO_LONGS(GEN8_LEGACY_PDPES), sizeof(unsigned long), GFP_KERNEL); 91919c468b4SFrançois Tigeot if (!pds) 92019c468b4SFrançois Tigeot return -ENOMEM; 921477eb7f9SFrançois Tigeot 92219c468b4SFrançois Tigeot pts = kcalloc(GEN8_LEGACY_PDPES, sizeof(unsigned long *), GFP_KERNEL); 92319c468b4SFrançois Tigeot if (!pts) { 92419c468b4SFrançois Tigeot kfree(pds); 925477eb7f9SFrançois Tigeot return -ENOMEM; 926ba55f2f5SFrançois Tigeot } 927ba55f2f5SFrançois Tigeot 92819c468b4SFrançois Tigeot for (i = 0; i < GEN8_LEGACY_PDPES; i++) { 92919c468b4SFrançois Tigeot pts[i] = kcalloc(BITS_TO_LONGS(I915_PDES), 93019c468b4SFrançois Tigeot sizeof(unsigned long), GFP_KERNEL); 93119c468b4SFrançois Tigeot if (!pts[i]) 932477eb7f9SFrançois Tigeot goto err_out; 93319c468b4SFrançois Tigeot } 934ba55f2f5SFrançois Tigeot 93519c468b4SFrançois Tigeot *new_pds = pds; 93619c468b4SFrançois Tigeot *new_pts = pts; 937477eb7f9SFrançois Tigeot 938477eb7f9SFrançois Tigeot return 0; 939477eb7f9SFrançois Tigeot 940477eb7f9SFrançois Tigeot err_out: 94119c468b4SFrançois Tigeot free_gen8_temp_bitmaps(pds, pts); 94219c468b4SFrançois Tigeot return -ENOMEM; 943ba55f2f5SFrançois Tigeot } 944ba55f2f5SFrançois Tigeot 945*a05eeebfSFrançois Tigeot /* PDE TLBs are a pain to invalidate on GEN8+. When we modify 946*a05eeebfSFrançois Tigeot * the page table structures, we mark them dirty so that 947*a05eeebfSFrançois Tigeot * context switching/execlist queuing code takes extra steps 948*a05eeebfSFrançois Tigeot * to ensure that tlbs are flushed. 949*a05eeebfSFrançois Tigeot */ 950*a05eeebfSFrançois Tigeot static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt) 951*a05eeebfSFrançois Tigeot { 952*a05eeebfSFrançois Tigeot ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask; 953*a05eeebfSFrançois Tigeot } 954*a05eeebfSFrançois Tigeot 95519c468b4SFrançois Tigeot static int gen8_alloc_va_range(struct i915_address_space *vm, 95619c468b4SFrançois Tigeot uint64_t start, 95719c468b4SFrançois Tigeot uint64_t length) 958ba55f2f5SFrançois Tigeot { 95919c468b4SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = 96019c468b4SFrançois Tigeot container_of(vm, struct i915_hw_ppgtt, base); 96119c468b4SFrançois Tigeot unsigned long *new_page_dirs, **new_page_tables; 96219c468b4SFrançois Tigeot struct i915_page_directory *pd; 96319c468b4SFrançois Tigeot const uint64_t orig_start = start; 96419c468b4SFrançois Tigeot const uint64_t orig_length = length; 96519c468b4SFrançois Tigeot uint64_t temp; 96619c468b4SFrançois Tigeot uint32_t pdpe; 967ba55f2f5SFrançois Tigeot int ret; 968ba55f2f5SFrançois Tigeot 96919c468b4SFrançois Tigeot /* Wrap is never okay since we can only represent 48b, and we don't 97019c468b4SFrançois Tigeot * actually use the other side of the canonical address space. 97119c468b4SFrançois Tigeot */ 97219c468b4SFrançois Tigeot if (WARN_ON(start + length < start)) 973*a05eeebfSFrançois Tigeot return -ENODEV; 974*a05eeebfSFrançois Tigeot 975*a05eeebfSFrançois Tigeot if (WARN_ON(start + length > ppgtt->base.total)) 976*a05eeebfSFrançois Tigeot return -ENODEV; 977ba55f2f5SFrançois Tigeot 97819c468b4SFrançois Tigeot ret = alloc_gen8_temp_bitmaps(&new_page_dirs, &new_page_tables); 979ba55f2f5SFrançois Tigeot if (ret) 980ba55f2f5SFrançois Tigeot return ret; 981ba55f2f5SFrançois Tigeot 98219c468b4SFrançois Tigeot /* Do the allocations first so we can easily bail out */ 98319c468b4SFrançois Tigeot ret = gen8_ppgtt_alloc_page_directories(ppgtt, &ppgtt->pdp, start, length, 98419c468b4SFrançois Tigeot new_page_dirs); 98519c468b4SFrançois Tigeot if (ret) { 98619c468b4SFrançois Tigeot free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); 98719c468b4SFrançois Tigeot return ret; 98819c468b4SFrançois Tigeot } 98919c468b4SFrançois Tigeot 99019c468b4SFrançois Tigeot /* For every page directory referenced, allocate page tables */ 99119c468b4SFrançois Tigeot gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) { 99219c468b4SFrançois Tigeot ret = gen8_ppgtt_alloc_pagetabs(ppgtt, pd, start, length, 99319c468b4SFrançois Tigeot new_page_tables[pdpe]); 99419c468b4SFrançois Tigeot if (ret) 99519c468b4SFrançois Tigeot goto err_out; 99619c468b4SFrançois Tigeot } 99719c468b4SFrançois Tigeot 99819c468b4SFrançois Tigeot start = orig_start; 99919c468b4SFrançois Tigeot length = orig_length; 100019c468b4SFrançois Tigeot 100119c468b4SFrançois Tigeot /* Allocations have completed successfully, so set the bitmaps, and do 100219c468b4SFrançois Tigeot * the mappings. */ 100319c468b4SFrançois Tigeot gen8_for_each_pdpe(pd, &ppgtt->pdp, start, length, temp, pdpe) { 1004*a05eeebfSFrançois Tigeot gen8_pde_t *const page_directory = kmap_px(pd); 100519c468b4SFrançois Tigeot struct i915_page_table *pt; 100619c468b4SFrançois Tigeot uint64_t pd_len = gen8_clamp_pd(start, length); 100719c468b4SFrançois Tigeot uint64_t pd_start = start; 100819c468b4SFrançois Tigeot uint32_t pde; 100919c468b4SFrançois Tigeot 101019c468b4SFrançois Tigeot /* Every pd should be allocated, we just did that above. */ 101119c468b4SFrançois Tigeot WARN_ON(!pd); 101219c468b4SFrançois Tigeot 101319c468b4SFrançois Tigeot gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) { 101419c468b4SFrançois Tigeot /* Same reasoning as pd */ 101519c468b4SFrançois Tigeot WARN_ON(!pt); 101619c468b4SFrançois Tigeot WARN_ON(!pd_len); 101719c468b4SFrançois Tigeot WARN_ON(!gen8_pte_count(pd_start, pd_len)); 101819c468b4SFrançois Tigeot 101919c468b4SFrançois Tigeot /* Set our used ptes within the page table */ 102019c468b4SFrançois Tigeot bitmap_set(pt->used_ptes, 102119c468b4SFrançois Tigeot gen8_pte_index(pd_start), 102219c468b4SFrançois Tigeot gen8_pte_count(pd_start, pd_len)); 102319c468b4SFrançois Tigeot 102419c468b4SFrançois Tigeot /* Our pde is now pointing to the pagetable, pt */ 1025*a05eeebfSFrançois Tigeot __set_bit(pde, pd->used_pdes); 102619c468b4SFrançois Tigeot 102719c468b4SFrançois Tigeot /* Map the PDE to the page table */ 1028*a05eeebfSFrançois Tigeot page_directory[pde] = gen8_pde_encode(px_dma(pt), 1029*a05eeebfSFrançois Tigeot I915_CACHE_LLC); 103019c468b4SFrançois Tigeot 103119c468b4SFrançois Tigeot /* NB: We haven't yet mapped ptes to pages. At this 103219c468b4SFrançois Tigeot * point we're still relying on insert_entries() */ 103319c468b4SFrançois Tigeot } 103419c468b4SFrançois Tigeot 1035*a05eeebfSFrançois Tigeot kunmap_px(ppgtt, page_directory); 103619c468b4SFrançois Tigeot 1037*a05eeebfSFrançois Tigeot __set_bit(pdpe, ppgtt->pdp.used_pdpes); 103819c468b4SFrançois Tigeot } 103919c468b4SFrançois Tigeot 104019c468b4SFrançois Tigeot free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); 1041*a05eeebfSFrançois Tigeot mark_tlbs_dirty(ppgtt); 104219c468b4SFrançois Tigeot return 0; 104319c468b4SFrançois Tigeot 104419c468b4SFrançois Tigeot err_out: 104519c468b4SFrançois Tigeot while (pdpe--) { 104619c468b4SFrançois Tigeot for_each_set_bit(temp, new_page_tables[pdpe], I915_PDES) 1047*a05eeebfSFrançois Tigeot free_pt(vm->dev, ppgtt->pdp.page_directory[pdpe]->page_table[temp]); 104819c468b4SFrançois Tigeot } 104919c468b4SFrançois Tigeot 105019c468b4SFrançois Tigeot for_each_set_bit(pdpe, new_page_dirs, GEN8_LEGACY_PDPES) 1051*a05eeebfSFrançois Tigeot free_pd(vm->dev, ppgtt->pdp.page_directory[pdpe]); 105219c468b4SFrançois Tigeot 105319c468b4SFrançois Tigeot free_gen8_temp_bitmaps(new_page_dirs, new_page_tables); 1054*a05eeebfSFrançois Tigeot mark_tlbs_dirty(ppgtt); 105519c468b4SFrançois Tigeot return ret; 105619c468b4SFrançois Tigeot } 105719c468b4SFrançois Tigeot 105819c468b4SFrançois Tigeot /* 105919c468b4SFrançois Tigeot * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers 106019c468b4SFrançois Tigeot * with a net effect resembling a 2-level page table in normal x86 terms. Each 106119c468b4SFrançois Tigeot * PDP represents 1GB of memory 4 * 512 * 512 * 4096 = 4GB legacy 32b address 106219c468b4SFrançois Tigeot * space. 106319c468b4SFrançois Tigeot * 106419c468b4SFrançois Tigeot */ 106519c468b4SFrançois Tigeot static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) 1066ba55f2f5SFrançois Tigeot { 1067*a05eeebfSFrançois Tigeot int ret; 1068ba55f2f5SFrançois Tigeot 1069*a05eeebfSFrançois Tigeot ret = gen8_init_scratch(&ppgtt->base); 1070*a05eeebfSFrançois Tigeot if (ret) 1071*a05eeebfSFrançois Tigeot return ret; 107219c468b4SFrançois Tigeot 107319c468b4SFrançois Tigeot ppgtt->base.start = 0; 107419c468b4SFrançois Tigeot ppgtt->base.total = 1ULL << 32; 107519c468b4SFrançois Tigeot #define CONFIG_X86_32 0 107619c468b4SFrançois Tigeot if (IS_ENABLED(CONFIG_X86_32)) 107719c468b4SFrançois Tigeot /* While we have a proliferation of size_t variables 107819c468b4SFrançois Tigeot * we cannot represent the full ppgtt size on 32bit, 107919c468b4SFrançois Tigeot * so limit it to the same size as the GGTT (currently 108019c468b4SFrançois Tigeot * 2GiB). 1081477eb7f9SFrançois Tigeot */ 108219c468b4SFrançois Tigeot ppgtt->base.total = to_i915(ppgtt->base.dev)->gtt.base.total; 108319c468b4SFrançois Tigeot ppgtt->base.cleanup = gen8_ppgtt_cleanup; 108419c468b4SFrançois Tigeot ppgtt->base.allocate_va_range = gen8_alloc_va_range; 108519c468b4SFrançois Tigeot ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; 108619c468b4SFrançois Tigeot ppgtt->base.clear_range = gen8_ppgtt_clear_range; 108719c468b4SFrançois Tigeot ppgtt->base.unbind_vma = ppgtt_unbind_vma; 108819c468b4SFrançois Tigeot ppgtt->base.bind_vma = ppgtt_bind_vma; 10899edbd4a0SFrançois Tigeot 1090ba55f2f5SFrançois Tigeot ppgtt->switch_mm = gen8_mm_switch; 1091ba55f2f5SFrançois Tigeot 10929edbd4a0SFrançois Tigeot return 0; 10939edbd4a0SFrançois Tigeot } 10949edbd4a0SFrançois Tigeot 1095*a05eeebfSFrançois Tigeot static int gen8_aliasing_ppgtt_init(struct i915_hw_ppgtt *ppgtt) 1096*a05eeebfSFrançois Tigeot { 1097*a05eeebfSFrançois Tigeot struct drm_device *dev = ppgtt->base.dev; 1098*a05eeebfSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1099*a05eeebfSFrançois Tigeot uint64_t start = 0, size = dev_priv->gtt.base.total; 1100*a05eeebfSFrançois Tigeot int ret; 1101*a05eeebfSFrançois Tigeot 1102*a05eeebfSFrançois Tigeot ret = gen8_ppgtt_init(ppgtt); 1103*a05eeebfSFrançois Tigeot if (ret) 1104*a05eeebfSFrançois Tigeot return ret; 1105*a05eeebfSFrançois Tigeot 1106*a05eeebfSFrançois Tigeot /* Aliasing PPGTT has to always work and be mapped because of the way we 1107*a05eeebfSFrançois Tigeot * use RESTORE_INHIBIT in the context switch. This will be fixed 1108*a05eeebfSFrançois Tigeot * eventually. */ 1109*a05eeebfSFrançois Tigeot ret = gen8_alloc_va_range(&ppgtt->base, start, size); 1110*a05eeebfSFrançois Tigeot if (ret) { 1111*a05eeebfSFrançois Tigeot free_pd(ppgtt->base.dev, ppgtt->base.scratch_pd); 1112*a05eeebfSFrançois Tigeot free_pt(ppgtt->base.dev, ppgtt->base.scratch_pt); 1113*a05eeebfSFrançois Tigeot return ret; 1114*a05eeebfSFrançois Tigeot } 1115*a05eeebfSFrançois Tigeot 1116*a05eeebfSFrançois Tigeot ppgtt->base.allocate_va_range = NULL; 1117*a05eeebfSFrançois Tigeot ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true); 1118*a05eeebfSFrançois Tigeot 1119*a05eeebfSFrançois Tigeot return 0; 1120*a05eeebfSFrançois Tigeot } 1121*a05eeebfSFrançois Tigeot 1122ba55f2f5SFrançois Tigeot static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) 1123ba55f2f5SFrançois Tigeot { 1124ba55f2f5SFrançois Tigeot struct i915_address_space *vm = &ppgtt->base; 112519c468b4SFrançois Tigeot struct i915_page_table *unused; 1126477eb7f9SFrançois Tigeot gen6_pte_t scratch_pte; 1127ba55f2f5SFrançois Tigeot uint32_t pd_entry; 112819c468b4SFrançois Tigeot uint32_t pte, pde, temp; 112919c468b4SFrançois Tigeot uint32_t start = ppgtt->base.start, length = ppgtt->base.total; 1130ba55f2f5SFrançois Tigeot 1131*a05eeebfSFrançois Tigeot scratch_pte = vm->pte_encode(px_dma(vm->scratch_page), 1132*a05eeebfSFrançois Tigeot I915_CACHE_LLC, true, 0); 1133ba55f2f5SFrançois Tigeot 113419c468b4SFrançois Tigeot gen6_for_each_pde(unused, &ppgtt->pd, start, length, temp, pde) { 1135ba55f2f5SFrançois Tigeot u32 expected; 1136477eb7f9SFrançois Tigeot gen6_pte_t *pt_vaddr; 1137*a05eeebfSFrançois Tigeot const dma_addr_t pt_addr = px_dma(ppgtt->pd.page_table[pde]); 113819c468b4SFrançois Tigeot pd_entry = readl(ppgtt->pd_addr + pde); 1139ba55f2f5SFrançois Tigeot expected = (GEN6_PDE_ADDR_ENCODE(pt_addr) | GEN6_PDE_VALID); 1140ba55f2f5SFrançois Tigeot 1141ba55f2f5SFrançois Tigeot if (pd_entry != expected) 1142ba55f2f5SFrançois Tigeot seq_printf(m, "\tPDE #%d mismatch: Actual PDE: %x Expected PDE: %x\n", 1143ba55f2f5SFrançois Tigeot pde, 1144ba55f2f5SFrançois Tigeot pd_entry, 1145ba55f2f5SFrançois Tigeot expected); 1146ba55f2f5SFrançois Tigeot seq_printf(m, "\tPDE: %x\n", pd_entry); 1147ba55f2f5SFrançois Tigeot 1148*a05eeebfSFrançois Tigeot pt_vaddr = kmap_px(ppgtt->pd.page_table[pde]); 1149*a05eeebfSFrançois Tigeot 1150477eb7f9SFrançois Tigeot for (pte = 0; pte < GEN6_PTES; pte+=4) { 1151ba55f2f5SFrançois Tigeot unsigned long va = 1152477eb7f9SFrançois Tigeot (pde * PAGE_SIZE * GEN6_PTES) + 1153ba55f2f5SFrançois Tigeot (pte * PAGE_SIZE); 1154ba55f2f5SFrançois Tigeot int i; 1155ba55f2f5SFrançois Tigeot bool found = false; 1156ba55f2f5SFrançois Tigeot for (i = 0; i < 4; i++) 1157ba55f2f5SFrançois Tigeot if (pt_vaddr[pte + i] != scratch_pte) 1158ba55f2f5SFrançois Tigeot found = true; 1159ba55f2f5SFrançois Tigeot if (!found) 1160ba55f2f5SFrançois Tigeot continue; 1161ba55f2f5SFrançois Tigeot 1162ba55f2f5SFrançois Tigeot seq_printf(m, "\t\t0x%lx [%03d,%04d]: =", va, pde, pte); 1163ba55f2f5SFrançois Tigeot for (i = 0; i < 4; i++) { 1164ba55f2f5SFrançois Tigeot if (pt_vaddr[pte + i] != scratch_pte) 1165ba55f2f5SFrançois Tigeot seq_printf(m, " %08x", pt_vaddr[pte + i]); 1166ba55f2f5SFrançois Tigeot else 1167477eb7f9SFrançois Tigeot seq_puts(m, " SCRATCH "); 1168ba55f2f5SFrançois Tigeot } 1169477eb7f9SFrançois Tigeot seq_puts(m, "\n"); 1170ba55f2f5SFrançois Tigeot } 1171*a05eeebfSFrançois Tigeot kunmap_px(ppgtt, pt_vaddr); 1172ba55f2f5SFrançois Tigeot } 1173ba55f2f5SFrançois Tigeot } 1174ba55f2f5SFrançois Tigeot 1175477eb7f9SFrançois Tigeot /* Write pde (index) from the page directory @pd to the page table @pt */ 117619c468b4SFrançois Tigeot static void gen6_write_pde(struct i915_page_directory *pd, 117719c468b4SFrançois Tigeot const int pde, struct i915_page_table *pt) 11789edbd4a0SFrançois Tigeot { 1179477eb7f9SFrançois Tigeot /* Caller needs to make sure the write completes if necessary */ 1180477eb7f9SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = 1181477eb7f9SFrançois Tigeot container_of(pd, struct i915_hw_ppgtt, pd); 1182477eb7f9SFrançois Tigeot u32 pd_entry; 11839edbd4a0SFrançois Tigeot 1184*a05eeebfSFrançois Tigeot pd_entry = GEN6_PDE_ADDR_ENCODE(px_dma(pt)); 11859edbd4a0SFrançois Tigeot pd_entry |= GEN6_PDE_VALID; 11869edbd4a0SFrançois Tigeot 1187477eb7f9SFrançois Tigeot writel(pd_entry, ppgtt->pd_addr + pde); 11889edbd4a0SFrançois Tigeot } 1189477eb7f9SFrançois Tigeot 1190477eb7f9SFrançois Tigeot /* Write all the page tables found in the ppgtt structure to incrementing page 1191477eb7f9SFrançois Tigeot * directories. */ 1192477eb7f9SFrançois Tigeot static void gen6_write_page_range(struct drm_i915_private *dev_priv, 119319c468b4SFrançois Tigeot struct i915_page_directory *pd, 1194477eb7f9SFrançois Tigeot uint32_t start, uint32_t length) 1195477eb7f9SFrançois Tigeot { 119619c468b4SFrançois Tigeot struct i915_page_table *pt; 1197477eb7f9SFrançois Tigeot uint32_t pde, temp; 1198477eb7f9SFrançois Tigeot 1199477eb7f9SFrançois Tigeot gen6_for_each_pde(pt, pd, start, length, temp, pde) 1200477eb7f9SFrançois Tigeot gen6_write_pde(pd, pde, pt); 1201477eb7f9SFrançois Tigeot 1202477eb7f9SFrançois Tigeot /* Make sure write is complete before other code can use this page 1203477eb7f9SFrançois Tigeot * table. Also require for WC mapped PTEs */ 1204477eb7f9SFrançois Tigeot readl(dev_priv->gtt.gsm); 12059edbd4a0SFrançois Tigeot } 12069edbd4a0SFrançois Tigeot 1207ba55f2f5SFrançois Tigeot static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt) 12088e26cdf6SFrançois Tigeot { 1209*a05eeebfSFrançois Tigeot BUG_ON(ppgtt->pd.base.ggtt_offset & 0x3f); 12105d0b1887SFrançois Tigeot 1211*a05eeebfSFrançois Tigeot return (ppgtt->pd.base.ggtt_offset / 64) << 16; 1212ba55f2f5SFrançois Tigeot } 12138e26cdf6SFrançois Tigeot 1214ba55f2f5SFrançois Tigeot static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt, 1215*a05eeebfSFrançois Tigeot struct drm_i915_gem_request *req) 1216ba55f2f5SFrançois Tigeot { 1217*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1218ba55f2f5SFrançois Tigeot int ret; 12198e26cdf6SFrançois Tigeot 1220ba55f2f5SFrançois Tigeot /* NB: TLBs must be flushed and invalidated before a switch */ 1221*a05eeebfSFrançois Tigeot ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); 1222ba55f2f5SFrançois Tigeot if (ret) 1223ba55f2f5SFrançois Tigeot return ret; 12248e26cdf6SFrançois Tigeot 1225*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 1226ba55f2f5SFrançois Tigeot if (ret) 1227ba55f2f5SFrançois Tigeot return ret; 12288e26cdf6SFrançois Tigeot 1229ba55f2f5SFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2)); 1230ba55f2f5SFrançois Tigeot intel_ring_emit(ring, RING_PP_DIR_DCLV(ring)); 1231ba55f2f5SFrançois Tigeot intel_ring_emit(ring, PP_DIR_DCLV_2G); 1232ba55f2f5SFrançois Tigeot intel_ring_emit(ring, RING_PP_DIR_BASE(ring)); 1233ba55f2f5SFrançois Tigeot intel_ring_emit(ring, get_pd_offset(ppgtt)); 1234ba55f2f5SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1235ba55f2f5SFrançois Tigeot intel_ring_advance(ring); 1236ba55f2f5SFrançois Tigeot 1237ba55f2f5SFrançois Tigeot return 0; 1238ba55f2f5SFrançois Tigeot } 1239ba55f2f5SFrançois Tigeot 1240477eb7f9SFrançois Tigeot static int vgpu_mm_switch(struct i915_hw_ppgtt *ppgtt, 1241*a05eeebfSFrançois Tigeot struct drm_i915_gem_request *req) 1242477eb7f9SFrançois Tigeot { 1243*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1244477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev); 1245477eb7f9SFrançois Tigeot 1246477eb7f9SFrançois Tigeot I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); 1247477eb7f9SFrançois Tigeot I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt)); 1248477eb7f9SFrançois Tigeot return 0; 1249477eb7f9SFrançois Tigeot } 1250477eb7f9SFrançois Tigeot 1251ba55f2f5SFrançois Tigeot static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt, 1252*a05eeebfSFrançois Tigeot struct drm_i915_gem_request *req) 1253ba55f2f5SFrançois Tigeot { 1254*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1255ba55f2f5SFrançois Tigeot int ret; 1256ba55f2f5SFrançois Tigeot 1257ba55f2f5SFrançois Tigeot /* NB: TLBs must be flushed and invalidated before a switch */ 1258*a05eeebfSFrançois Tigeot ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); 1259ba55f2f5SFrançois Tigeot if (ret) 1260ba55f2f5SFrançois Tigeot return ret; 1261ba55f2f5SFrançois Tigeot 1262*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 1263ba55f2f5SFrançois Tigeot if (ret) 1264ba55f2f5SFrançois Tigeot return ret; 1265ba55f2f5SFrançois Tigeot 1266ba55f2f5SFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2)); 1267ba55f2f5SFrançois Tigeot intel_ring_emit(ring, RING_PP_DIR_DCLV(ring)); 1268ba55f2f5SFrançois Tigeot intel_ring_emit(ring, PP_DIR_DCLV_2G); 1269ba55f2f5SFrançois Tigeot intel_ring_emit(ring, RING_PP_DIR_BASE(ring)); 1270ba55f2f5SFrançois Tigeot intel_ring_emit(ring, get_pd_offset(ppgtt)); 1271ba55f2f5SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1272ba55f2f5SFrançois Tigeot intel_ring_advance(ring); 1273ba55f2f5SFrançois Tigeot 1274ba55f2f5SFrançois Tigeot /* XXX: RCS is the only one to auto invalidate the TLBs? */ 1275ba55f2f5SFrançois Tigeot if (ring->id != RCS) { 1276*a05eeebfSFrançois Tigeot ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); 1277ba55f2f5SFrançois Tigeot if (ret) 1278ba55f2f5SFrançois Tigeot return ret; 1279ba55f2f5SFrançois Tigeot } 1280ba55f2f5SFrançois Tigeot 1281ba55f2f5SFrançois Tigeot return 0; 1282ba55f2f5SFrançois Tigeot } 1283ba55f2f5SFrançois Tigeot 1284ba55f2f5SFrançois Tigeot static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt, 1285*a05eeebfSFrançois Tigeot struct drm_i915_gem_request *req) 1286ba55f2f5SFrançois Tigeot { 1287*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1288ba55f2f5SFrançois Tigeot struct drm_device *dev = ppgtt->base.dev; 1289ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1290ba55f2f5SFrançois Tigeot 1291ba55f2f5SFrançois Tigeot 1292ba55f2f5SFrançois Tigeot I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); 1293ba55f2f5SFrançois Tigeot I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt)); 1294ba55f2f5SFrançois Tigeot 1295ba55f2f5SFrançois Tigeot POSTING_READ(RING_PP_DIR_DCLV(ring)); 1296ba55f2f5SFrançois Tigeot 1297ba55f2f5SFrançois Tigeot return 0; 1298ba55f2f5SFrançois Tigeot } 1299ba55f2f5SFrançois Tigeot 13001b13d190SFrançois Tigeot static void gen8_ppgtt_enable(struct drm_device *dev) 1301ba55f2f5SFrançois Tigeot { 1302ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1303ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring; 13041b13d190SFrançois Tigeot int j; 1305ba55f2f5SFrançois Tigeot 1306ba55f2f5SFrançois Tigeot for_each_ring(ring, dev_priv, j) { 1307ba55f2f5SFrançois Tigeot I915_WRITE(RING_MODE_GEN7(ring), 1308ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); 13091b13d190SFrançois Tigeot } 1310ba55f2f5SFrançois Tigeot } 1311ba55f2f5SFrançois Tigeot 13121b13d190SFrançois Tigeot static void gen7_ppgtt_enable(struct drm_device *dev) 1313ba55f2f5SFrançois Tigeot { 1314ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1315ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring; 13168e26cdf6SFrançois Tigeot uint32_t ecochk, ecobits; 1317ba55f2f5SFrançois Tigeot int i; 13188e26cdf6SFrançois Tigeot 13198e26cdf6SFrançois Tigeot ecobits = I915_READ(GAC_ECO_BITS); 13208e26cdf6SFrançois Tigeot I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B); 13218e26cdf6SFrançois Tigeot 13228e26cdf6SFrançois Tigeot ecochk = I915_READ(GAM_ECOCHK); 13238e26cdf6SFrançois Tigeot if (IS_HASWELL(dev)) { 13248e26cdf6SFrançois Tigeot ecochk |= ECOCHK_PPGTT_WB_HSW; 13258e26cdf6SFrançois Tigeot } else { 13268e26cdf6SFrançois Tigeot ecochk |= ECOCHK_PPGTT_LLC_IVB; 13278e26cdf6SFrançois Tigeot ecochk &= ~ECOCHK_PPGTT_GFDT_IVB; 13288e26cdf6SFrançois Tigeot } 13298e26cdf6SFrançois Tigeot I915_WRITE(GAM_ECOCHK, ecochk); 13308e26cdf6SFrançois Tigeot 13318e26cdf6SFrançois Tigeot for_each_ring(ring, dev_priv, i) { 1332ba55f2f5SFrançois Tigeot /* GFX_MODE is per-ring on gen7+ */ 13338e26cdf6SFrançois Tigeot I915_WRITE(RING_MODE_GEN7(ring), 13348e26cdf6SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); 13351b13d190SFrançois Tigeot } 13368e26cdf6SFrançois Tigeot } 1337ba55f2f5SFrançois Tigeot 13381b13d190SFrançois Tigeot static void gen6_ppgtt_enable(struct drm_device *dev) 1339ba55f2f5SFrançois Tigeot { 1340ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1341ba55f2f5SFrançois Tigeot uint32_t ecochk, gab_ctl, ecobits; 1342ba55f2f5SFrançois Tigeot 1343ba55f2f5SFrançois Tigeot ecobits = I915_READ(GAC_ECO_BITS); 1344ba55f2f5SFrançois Tigeot I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_SNB_BIT | 1345ba55f2f5SFrançois Tigeot ECOBITS_PPGTT_CACHE64B); 1346ba55f2f5SFrançois Tigeot 1347ba55f2f5SFrançois Tigeot gab_ctl = I915_READ(GAB_CTL); 1348ba55f2f5SFrançois Tigeot I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT); 1349ba55f2f5SFrançois Tigeot 1350ba55f2f5SFrançois Tigeot ecochk = I915_READ(GAM_ECOCHK); 1351ba55f2f5SFrançois Tigeot I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | ECOCHK_PPGTT_CACHE64B); 1352ba55f2f5SFrançois Tigeot 1353ba55f2f5SFrançois Tigeot I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); 13548e26cdf6SFrançois Tigeot } 13558e26cdf6SFrançois Tigeot 1356f4e1c372SFrançois Tigeot /* PPGTT support for Sandybdrige/Gen6 and later */ 13579edbd4a0SFrançois Tigeot static void gen6_ppgtt_clear_range(struct i915_address_space *vm, 1358ba55f2f5SFrançois Tigeot uint64_t start, 1359ba55f2f5SFrançois Tigeot uint64_t length, 13609edbd4a0SFrançois Tigeot bool use_scratch) 1361f4e1c372SFrançois Tigeot { 13629edbd4a0SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = 13639edbd4a0SFrançois Tigeot container_of(vm, struct i915_hw_ppgtt, base); 1364477eb7f9SFrançois Tigeot gen6_pte_t *pt_vaddr, scratch_pte; 1365ba55f2f5SFrançois Tigeot unsigned first_entry = start >> PAGE_SHIFT; 1366ba55f2f5SFrançois Tigeot unsigned num_entries = length >> PAGE_SHIFT; 1367477eb7f9SFrançois Tigeot unsigned act_pt = first_entry / GEN6_PTES; 1368477eb7f9SFrançois Tigeot unsigned first_pte = first_entry % GEN6_PTES; 1369f4e1c372SFrançois Tigeot unsigned last_pte, i; 1370e3adcf8fSFrançois Tigeot 1371*a05eeebfSFrançois Tigeot scratch_pte = vm->pte_encode(px_dma(vm->scratch_page), 1372*a05eeebfSFrançois Tigeot I915_CACHE_LLC, true, 0); 1373e3adcf8fSFrançois Tigeot 1374e3adcf8fSFrançois Tigeot while (num_entries) { 1375e3adcf8fSFrançois Tigeot last_pte = first_pte + num_entries; 1376477eb7f9SFrançois Tigeot if (last_pte > GEN6_PTES) 1377477eb7f9SFrançois Tigeot last_pte = GEN6_PTES; 1378e3adcf8fSFrançois Tigeot 1379*a05eeebfSFrançois Tigeot pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]); 1380e3adcf8fSFrançois Tigeot 1381e3adcf8fSFrançois Tigeot for (i = first_pte; i < last_pte; i++) 1382e3adcf8fSFrançois Tigeot pt_vaddr[i] = scratch_pte; 1383e3adcf8fSFrançois Tigeot 1384*a05eeebfSFrançois Tigeot kunmap_px(ppgtt, pt_vaddr); 1385e3adcf8fSFrançois Tigeot 1386e3adcf8fSFrançois Tigeot num_entries -= last_pte - first_pte; 1387e3adcf8fSFrançois Tigeot first_pte = 0; 13888e26cdf6SFrançois Tigeot act_pt++; 1389e3adcf8fSFrançois Tigeot } 1390e3adcf8fSFrançois Tigeot } 1391e3adcf8fSFrançois Tigeot 13929edbd4a0SFrançois Tigeot static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, 13937ec9f8e5SFrançois Tigeot struct sg_table *pages, 1394ba55f2f5SFrançois Tigeot uint64_t start, 139524edb884SFrançois Tigeot enum i915_cache_level cache_level, u32 flags) 1396e3adcf8fSFrançois Tigeot { 13979edbd4a0SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = 13989edbd4a0SFrançois Tigeot container_of(vm, struct i915_hw_ppgtt, base); 1399477eb7f9SFrançois Tigeot gen6_pte_t *pt_vaddr; 1400ba55f2f5SFrançois Tigeot unsigned first_entry = start >> PAGE_SHIFT; 1401477eb7f9SFrançois Tigeot unsigned act_pt = first_entry / GEN6_PTES; 1402477eb7f9SFrançois Tigeot unsigned act_pte = first_entry % GEN6_PTES; 14037ec9f8e5SFrançois Tigeot struct sg_page_iter sg_iter; 1404a2fdbec6SFrançois Tigeot 14059edbd4a0SFrançois Tigeot pt_vaddr = NULL; 14067ec9f8e5SFrançois Tigeot for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) { 14079edbd4a0SFrançois Tigeot if (pt_vaddr == NULL) 1408*a05eeebfSFrançois Tigeot pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]); 1409a2fdbec6SFrançois Tigeot 14109edbd4a0SFrançois Tigeot pt_vaddr[act_pte] = 14117ec9f8e5SFrançois Tigeot vm->pte_encode(sg_page_iter_dma_address(&sg_iter), 141224edb884SFrançois Tigeot cache_level, true, flags); 1413477eb7f9SFrançois Tigeot 1414477eb7f9SFrançois Tigeot if (++act_pte == GEN6_PTES) { 1415*a05eeebfSFrançois Tigeot kunmap_px(ppgtt, pt_vaddr); 14169edbd4a0SFrançois Tigeot pt_vaddr = NULL; 14178e26cdf6SFrançois Tigeot act_pt++; 14189edbd4a0SFrançois Tigeot act_pte = 0; 1419a2fdbec6SFrançois Tigeot } 1420a2fdbec6SFrançois Tigeot } 14219edbd4a0SFrançois Tigeot if (pt_vaddr) 1422*a05eeebfSFrançois Tigeot kunmap_px(ppgtt, pt_vaddr); 1423a2fdbec6SFrançois Tigeot } 1424477eb7f9SFrançois Tigeot 1425477eb7f9SFrançois Tigeot static int gen6_alloc_va_range(struct i915_address_space *vm, 1426*a05eeebfSFrançois Tigeot uint64_t start_in, uint64_t length_in) 1427477eb7f9SFrançois Tigeot { 1428477eb7f9SFrançois Tigeot DECLARE_BITMAP(new_page_tables, I915_PDES); 1429477eb7f9SFrançois Tigeot struct drm_device *dev = vm->dev; 1430477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1431477eb7f9SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = 1432477eb7f9SFrançois Tigeot container_of(vm, struct i915_hw_ppgtt, base); 143319c468b4SFrançois Tigeot struct i915_page_table *pt; 1434*a05eeebfSFrançois Tigeot uint32_t start, length, start_save, length_save; 1435477eb7f9SFrançois Tigeot uint32_t pde, temp; 1436477eb7f9SFrançois Tigeot int ret; 1437477eb7f9SFrançois Tigeot 1438*a05eeebfSFrançois Tigeot if (WARN_ON(start_in + length_in > ppgtt->base.total)) 1439*a05eeebfSFrançois Tigeot return -ENODEV; 1440*a05eeebfSFrançois Tigeot 1441*a05eeebfSFrançois Tigeot start = start_save = start_in; 1442*a05eeebfSFrançois Tigeot length = length_save = length_in; 1443477eb7f9SFrançois Tigeot 1444477eb7f9SFrançois Tigeot bitmap_zero(new_page_tables, I915_PDES); 1445477eb7f9SFrançois Tigeot 1446477eb7f9SFrançois Tigeot /* The allocation is done in two stages so that we can bail out with 1447477eb7f9SFrançois Tigeot * minimal amount of pain. The first stage finds new page tables that 1448477eb7f9SFrançois Tigeot * need allocation. The second stage marks use ptes within the page 1449477eb7f9SFrançois Tigeot * tables. 1450477eb7f9SFrançois Tigeot */ 1451477eb7f9SFrançois Tigeot gen6_for_each_pde(pt, &ppgtt->pd, start, length, temp, pde) { 1452*a05eeebfSFrançois Tigeot if (pt != vm->scratch_pt) { 1453*a05eeebfSFrançois Tigeot // WARN_ON(bitmap_empty(pt->used_ptes, GEN6_PTES)); 1454477eb7f9SFrançois Tigeot continue; 1455477eb7f9SFrançois Tigeot } 1456477eb7f9SFrançois Tigeot 1457477eb7f9SFrançois Tigeot /* We've already allocated a page table */ 1458477eb7f9SFrançois Tigeot WARN_ON(!bitmap_empty(pt->used_ptes, GEN6_PTES)); 1459477eb7f9SFrançois Tigeot 1460*a05eeebfSFrançois Tigeot pt = alloc_pt(dev); 1461477eb7f9SFrançois Tigeot if (IS_ERR(pt)) { 1462477eb7f9SFrançois Tigeot ret = PTR_ERR(pt); 1463477eb7f9SFrançois Tigeot goto unwind_out; 1464477eb7f9SFrançois Tigeot } 1465477eb7f9SFrançois Tigeot 1466477eb7f9SFrançois Tigeot gen6_initialize_pt(vm, pt); 1467477eb7f9SFrançois Tigeot 1468477eb7f9SFrançois Tigeot ppgtt->pd.page_table[pde] = pt; 1469*a05eeebfSFrançois Tigeot __set_bit(pde, new_page_tables); 1470477eb7f9SFrançois Tigeot trace_i915_page_table_entry_alloc(vm, pde, start, GEN6_PDE_SHIFT); 1471477eb7f9SFrançois Tigeot } 1472477eb7f9SFrançois Tigeot 1473477eb7f9SFrançois Tigeot start = start_save; 1474477eb7f9SFrançois Tigeot length = length_save; 1475477eb7f9SFrançois Tigeot 1476477eb7f9SFrançois Tigeot gen6_for_each_pde(pt, &ppgtt->pd, start, length, temp, pde) { 1477477eb7f9SFrançois Tigeot DECLARE_BITMAP(tmp_bitmap, GEN6_PTES); 1478477eb7f9SFrançois Tigeot 1479477eb7f9SFrançois Tigeot bitmap_zero(tmp_bitmap, GEN6_PTES); 1480477eb7f9SFrançois Tigeot bitmap_set(tmp_bitmap, gen6_pte_index(start), 1481477eb7f9SFrançois Tigeot gen6_pte_count(start, length)); 1482477eb7f9SFrançois Tigeot 1483*a05eeebfSFrançois Tigeot if (__test_and_clear_bit(pde, new_page_tables)) 1484477eb7f9SFrançois Tigeot gen6_write_pde(&ppgtt->pd, pde, pt); 1485477eb7f9SFrançois Tigeot 1486477eb7f9SFrançois Tigeot trace_i915_page_table_entry_map(vm, pde, pt, 1487477eb7f9SFrançois Tigeot gen6_pte_index(start), 1488477eb7f9SFrançois Tigeot gen6_pte_count(start, length), 1489477eb7f9SFrançois Tigeot GEN6_PTES); 1490477eb7f9SFrançois Tigeot bitmap_or(pt->used_ptes, tmp_bitmap, pt->used_ptes, 1491477eb7f9SFrançois Tigeot GEN6_PTES); 1492477eb7f9SFrançois Tigeot } 1493477eb7f9SFrançois Tigeot 1494477eb7f9SFrançois Tigeot WARN_ON(!bitmap_empty(new_page_tables, I915_PDES)); 1495477eb7f9SFrançois Tigeot 1496477eb7f9SFrançois Tigeot /* Make sure write is complete before other code can use this page 1497477eb7f9SFrançois Tigeot * table. Also require for WC mapped PTEs */ 1498477eb7f9SFrançois Tigeot readl(dev_priv->gtt.gsm); 1499477eb7f9SFrançois Tigeot 1500477eb7f9SFrançois Tigeot mark_tlbs_dirty(ppgtt); 1501477eb7f9SFrançois Tigeot return 0; 1502477eb7f9SFrançois Tigeot 1503477eb7f9SFrançois Tigeot unwind_out: 1504477eb7f9SFrançois Tigeot for_each_set_bit(pde, new_page_tables, I915_PDES) { 150519c468b4SFrançois Tigeot struct i915_page_table *pt = ppgtt->pd.page_table[pde]; 1506477eb7f9SFrançois Tigeot 1507*a05eeebfSFrançois Tigeot ppgtt->pd.page_table[pde] = vm->scratch_pt; 1508*a05eeebfSFrançois Tigeot free_pt(vm->dev, pt); 1509477eb7f9SFrançois Tigeot } 1510477eb7f9SFrançois Tigeot 1511477eb7f9SFrançois Tigeot mark_tlbs_dirty(ppgtt); 1512477eb7f9SFrançois Tigeot return ret; 1513ba55f2f5SFrançois Tigeot } 1514ba55f2f5SFrançois Tigeot 1515*a05eeebfSFrançois Tigeot static int gen6_init_scratch(struct i915_address_space *vm) 1516*a05eeebfSFrançois Tigeot { 1517*a05eeebfSFrançois Tigeot struct drm_device *dev = vm->dev; 1518*a05eeebfSFrançois Tigeot 1519*a05eeebfSFrançois Tigeot vm->scratch_page = alloc_scratch_page(dev); 1520*a05eeebfSFrançois Tigeot if (IS_ERR(vm->scratch_page)) 1521*a05eeebfSFrançois Tigeot return PTR_ERR(vm->scratch_page); 1522*a05eeebfSFrançois Tigeot 1523*a05eeebfSFrançois Tigeot vm->scratch_pt = alloc_pt(dev); 1524*a05eeebfSFrançois Tigeot if (IS_ERR(vm->scratch_pt)) { 1525*a05eeebfSFrançois Tigeot free_scratch_page(dev, vm->scratch_page); 1526*a05eeebfSFrançois Tigeot return PTR_ERR(vm->scratch_pt); 1527*a05eeebfSFrançois Tigeot } 1528*a05eeebfSFrançois Tigeot 1529*a05eeebfSFrançois Tigeot gen6_initialize_pt(vm, vm->scratch_pt); 1530*a05eeebfSFrançois Tigeot 1531*a05eeebfSFrançois Tigeot return 0; 1532*a05eeebfSFrançois Tigeot } 1533*a05eeebfSFrançois Tigeot 1534*a05eeebfSFrançois Tigeot static void gen6_free_scratch(struct i915_address_space *vm) 1535*a05eeebfSFrançois Tigeot { 1536*a05eeebfSFrançois Tigeot struct drm_device *dev = vm->dev; 1537*a05eeebfSFrançois Tigeot 1538*a05eeebfSFrançois Tigeot free_pt(dev, vm->scratch_pt); 1539*a05eeebfSFrançois Tigeot free_scratch_page(dev, vm->scratch_page); 1540*a05eeebfSFrançois Tigeot } 1541*a05eeebfSFrançois Tigeot 1542ba55f2f5SFrançois Tigeot static void gen6_ppgtt_cleanup(struct i915_address_space *vm) 1543ba55f2f5SFrançois Tigeot { 1544ba55f2f5SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = 1545ba55f2f5SFrançois Tigeot container_of(vm, struct i915_hw_ppgtt, base); 154619c468b4SFrançois Tigeot struct i915_page_table *pt; 154719c468b4SFrançois Tigeot uint32_t pde; 154819c468b4SFrançois Tigeot 1549ba55f2f5SFrançois Tigeot drm_mm_remove_node(&ppgtt->node); 1550ba55f2f5SFrançois Tigeot 155119c468b4SFrançois Tigeot gen6_for_all_pdes(pt, ppgtt, pde) { 1552*a05eeebfSFrançois Tigeot if (pt != vm->scratch_pt) 1553*a05eeebfSFrançois Tigeot free_pt(ppgtt->base.dev, pt); 155419c468b4SFrançois Tigeot } 155519c468b4SFrançois Tigeot 1556*a05eeebfSFrançois Tigeot gen6_free_scratch(vm); 1557ba55f2f5SFrançois Tigeot } 1558ba55f2f5SFrançois Tigeot 1559ba55f2f5SFrançois Tigeot static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt) 1560a2fdbec6SFrançois Tigeot { 1561*a05eeebfSFrançois Tigeot struct i915_address_space *vm = &ppgtt->base; 15629edbd4a0SFrançois Tigeot struct drm_device *dev = ppgtt->base.dev; 15637cbd1a46SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1564ba55f2f5SFrançois Tigeot bool retried = false; 1565ba55f2f5SFrançois Tigeot int ret; 1566e3adcf8fSFrançois Tigeot 1567ba55f2f5SFrançois Tigeot /* PPGTT PDEs reside in the GGTT and consists of 512 entries. The 1568ba55f2f5SFrançois Tigeot * allocator works in address space sizes, so it's multiplied by page 1569ba55f2f5SFrançois Tigeot * size. We allocate at the top of the GTT to avoid fragmentation. 1570ba55f2f5SFrançois Tigeot */ 1571ba55f2f5SFrançois Tigeot BUG_ON(!drm_mm_initialized(&dev_priv->gtt.base.mm)); 1572477eb7f9SFrançois Tigeot 1573*a05eeebfSFrançois Tigeot ret = gen6_init_scratch(vm); 1574*a05eeebfSFrançois Tigeot if (ret) 1575*a05eeebfSFrançois Tigeot return ret; 1576477eb7f9SFrançois Tigeot 1577ba55f2f5SFrançois Tigeot alloc: 1578ba55f2f5SFrançois Tigeot ret = drm_mm_insert_node_in_range_generic(&dev_priv->gtt.base.mm, 1579ba55f2f5SFrançois Tigeot &ppgtt->node, GEN6_PD_SIZE, 1580ba55f2f5SFrançois Tigeot GEN6_PD_ALIGN, 0, 1581ba55f2f5SFrançois Tigeot 0, dev_priv->gtt.base.total, 1582ba55f2f5SFrançois Tigeot DRM_MM_TOPDOWN); 1583ba55f2f5SFrançois Tigeot if (ret == -ENOSPC && !retried) { 1584ba55f2f5SFrançois Tigeot ret = i915_gem_evict_something(dev, &dev_priv->gtt.base, 1585ba55f2f5SFrançois Tigeot GEN6_PD_SIZE, GEN6_PD_ALIGN, 1586ba55f2f5SFrançois Tigeot I915_CACHE_NONE, 1587ba55f2f5SFrançois Tigeot 0, dev_priv->gtt.base.total, 1588ba55f2f5SFrançois Tigeot 0); 1589ba55f2f5SFrançois Tigeot if (ret) 1590477eb7f9SFrançois Tigeot goto err_out; 1591e3adcf8fSFrançois Tigeot 1592ba55f2f5SFrançois Tigeot retried = true; 1593ba55f2f5SFrançois Tigeot goto alloc; 1594ba55f2f5SFrançois Tigeot } 1595ba55f2f5SFrançois Tigeot 1596477eb7f9SFrançois Tigeot if (ret) 1597477eb7f9SFrançois Tigeot goto err_out; 1598477eb7f9SFrançois Tigeot 1599477eb7f9SFrançois Tigeot 1600ba55f2f5SFrançois Tigeot if (ppgtt->node.start < dev_priv->gtt.mappable_end) 1601ba55f2f5SFrançois Tigeot DRM_DEBUG("Forced to use aperture for PDEs\n"); 1602ba55f2f5SFrançois Tigeot 1603ba55f2f5SFrançois Tigeot return 0; 1604477eb7f9SFrançois Tigeot 1605477eb7f9SFrançois Tigeot err_out: 1606*a05eeebfSFrançois Tigeot gen6_free_scratch(vm); 1607477eb7f9SFrançois Tigeot return ret; 1608ba55f2f5SFrançois Tigeot } 1609ba55f2f5SFrançois Tigeot 1610ba55f2f5SFrançois Tigeot static int gen6_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt) 1611ba55f2f5SFrançois Tigeot { 1612477eb7f9SFrançois Tigeot return gen6_ppgtt_allocate_page_directories(ppgtt); 1613e3adcf8fSFrançois Tigeot } 1614e3adcf8fSFrançois Tigeot 1615477eb7f9SFrançois Tigeot static void gen6_scratch_va_range(struct i915_hw_ppgtt *ppgtt, 1616477eb7f9SFrançois Tigeot uint64_t start, uint64_t length) 1617ba55f2f5SFrançois Tigeot { 161819c468b4SFrançois Tigeot struct i915_page_table *unused; 1619477eb7f9SFrançois Tigeot uint32_t pde, temp; 16209edbd4a0SFrançois Tigeot 1621477eb7f9SFrançois Tigeot gen6_for_each_pde(unused, &ppgtt->pd, start, length, temp, pde) 1622*a05eeebfSFrançois Tigeot ppgtt->pd.page_table[pde] = ppgtt->base.scratch_pt; 16239edbd4a0SFrançois Tigeot } 1624ba55f2f5SFrançois Tigeot 1625477eb7f9SFrançois Tigeot static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing) 1626ba55f2f5SFrançois Tigeot { 1627ba55f2f5SFrançois Tigeot struct drm_device *dev = ppgtt->base.dev; 1628ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1629ba55f2f5SFrançois Tigeot int ret; 1630ba55f2f5SFrançois Tigeot 1631ba55f2f5SFrançois Tigeot ppgtt->base.pte_encode = dev_priv->gtt.base.pte_encode; 1632ba55f2f5SFrançois Tigeot if (IS_GEN6(dev)) { 1633ba55f2f5SFrançois Tigeot ppgtt->switch_mm = gen6_mm_switch; 1634ba55f2f5SFrançois Tigeot } else if (IS_HASWELL(dev)) { 1635ba55f2f5SFrançois Tigeot ppgtt->switch_mm = hsw_mm_switch; 1636ba55f2f5SFrançois Tigeot } else if (IS_GEN7(dev)) { 1637ba55f2f5SFrançois Tigeot ppgtt->switch_mm = gen7_mm_switch; 1638ba55f2f5SFrançois Tigeot } else 1639ba55f2f5SFrançois Tigeot BUG(); 1640ba55f2f5SFrançois Tigeot 1641477eb7f9SFrançois Tigeot if (intel_vgpu_active(dev)) 1642477eb7f9SFrançois Tigeot ppgtt->switch_mm = vgpu_mm_switch; 1643477eb7f9SFrançois Tigeot 1644ba55f2f5SFrançois Tigeot ret = gen6_ppgtt_alloc(ppgtt); 1645ba55f2f5SFrançois Tigeot if (ret) 1646ba55f2f5SFrançois Tigeot return ret; 1647ba55f2f5SFrançois Tigeot 1648477eb7f9SFrançois Tigeot if (aliasing) { 1649477eb7f9SFrançois Tigeot /* preallocate all pts */ 165019c468b4SFrançois Tigeot ret = alloc_pt_range(&ppgtt->pd, 0, I915_PDES, 1651477eb7f9SFrançois Tigeot ppgtt->base.dev); 1652477eb7f9SFrançois Tigeot 1653ba55f2f5SFrançois Tigeot if (ret) { 1654477eb7f9SFrançois Tigeot gen6_ppgtt_cleanup(&ppgtt->base); 16550b869d8aSFrançois Tigeot return ret; 1656e3adcf8fSFrançois Tigeot } 1657477eb7f9SFrançois Tigeot } 1658e3adcf8fSFrançois Tigeot 16597ec9f8e5SFrançois Tigeot ppgtt->base.allocate_va_range = gen6_alloc_va_range; 1660ba55f2f5SFrançois Tigeot ppgtt->base.clear_range = gen6_ppgtt_clear_range; 1661ba55f2f5SFrançois Tigeot ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; 166219c468b4SFrançois Tigeot ppgtt->base.unbind_vma = ppgtt_unbind_vma; 166319c468b4SFrançois Tigeot ppgtt->base.bind_vma = ppgtt_bind_vma; 1664ba55f2f5SFrançois Tigeot ppgtt->base.cleanup = gen6_ppgtt_cleanup; 1665ba55f2f5SFrançois Tigeot ppgtt->base.start = 0; 166619c468b4SFrançois Tigeot ppgtt->base.total = I915_PDES * GEN6_PTES * PAGE_SIZE; 1667ba55f2f5SFrançois Tigeot ppgtt->debug_dump = gen6_dump_ppgtt; 1668ba55f2f5SFrançois Tigeot 1669*a05eeebfSFrançois Tigeot ppgtt->pd.base.ggtt_offset = 1670477eb7f9SFrançois Tigeot ppgtt->node.start / PAGE_SIZE * sizeof(gen6_pte_t); 1671ba55f2f5SFrançois Tigeot 1672477eb7f9SFrançois Tigeot ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->gtt.gsm + 1673*a05eeebfSFrançois Tigeot ppgtt->pd.base.ggtt_offset / sizeof(gen6_pte_t); 1674477eb7f9SFrançois Tigeot 1675477eb7f9SFrançois Tigeot if (aliasing) 1676ba55f2f5SFrançois Tigeot ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true); 1677477eb7f9SFrançois Tigeot else 1678477eb7f9SFrançois Tigeot gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total); 1679477eb7f9SFrançois Tigeot 1680477eb7f9SFrançois Tigeot gen6_write_page_range(dev_priv, &ppgtt->pd, 0, ppgtt->base.total); 1681ba55f2f5SFrançois Tigeot 1682ba55f2f5SFrançois Tigeot DRM_DEBUG_DRIVER("Allocated pde space (%ldM) at GTT entry: %lx\n", 1683ba55f2f5SFrançois Tigeot ppgtt->node.size >> 20, 1684ba55f2f5SFrançois Tigeot ppgtt->node.start / PAGE_SIZE); 1685ba55f2f5SFrançois Tigeot 16861b13d190SFrançois Tigeot DRM_DEBUG("Adding PPGTT at offset %x\n", 1687*a05eeebfSFrançois Tigeot ppgtt->pd.base.ggtt_offset << 10); 16881b13d190SFrançois Tigeot 1689ba55f2f5SFrançois Tigeot return 0; 1690ba55f2f5SFrançois Tigeot } 1691ba55f2f5SFrançois Tigeot 1692477eb7f9SFrançois Tigeot static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt, 1693477eb7f9SFrançois Tigeot bool aliasing) 1694a2fdbec6SFrançois Tigeot { 16959edbd4a0SFrançois Tigeot ppgtt->base.dev = dev; 1696a2fdbec6SFrançois Tigeot 16978e26cdf6SFrançois Tigeot if (INTEL_INFO(dev)->gen < 8) 1698477eb7f9SFrançois Tigeot return gen6_ppgtt_init(ppgtt, aliasing); 169919c468b4SFrançois Tigeot else if (aliasing) 170019c468b4SFrançois Tigeot return gen8_aliasing_ppgtt_init(ppgtt); 17018e26cdf6SFrançois Tigeot else 170219c468b4SFrançois Tigeot return gen8_ppgtt_init(ppgtt); 17031b13d190SFrançois Tigeot } 1704*a05eeebfSFrançois Tigeot 17051b13d190SFrançois Tigeot int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) 17061b13d190SFrançois Tigeot { 1707ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17081b13d190SFrançois Tigeot int ret = 0; 17091b13d190SFrançois Tigeot 1710477eb7f9SFrançois Tigeot ret = __hw_ppgtt_init(dev, ppgtt, false); 17111b13d190SFrançois Tigeot if (ret == 0) { 1712ba55f2f5SFrançois Tigeot kref_init(&ppgtt->ref); 17139edbd4a0SFrançois Tigeot drm_mm_init(&ppgtt->base.mm, ppgtt->base.start, 17149edbd4a0SFrançois Tigeot ppgtt->base.total); 1715ba55f2f5SFrançois Tigeot i915_init_vm(dev_priv, &ppgtt->base); 17161b13d190SFrançois Tigeot } 17171b13d190SFrançois Tigeot 17181b13d190SFrançois Tigeot return ret; 17191b13d190SFrançois Tigeot } 17201b13d190SFrançois Tigeot 17211b13d190SFrançois Tigeot int i915_ppgtt_init_hw(struct drm_device *dev) 17221b13d190SFrançois Tigeot { 17231b13d190SFrançois Tigeot /* In the case of execlists, PPGTT is enabled by the context descriptor 17241b13d190SFrançois Tigeot * and the PDPs are contained within the context itself. We don't 17251b13d190SFrançois Tigeot * need to do anything here. */ 17261b13d190SFrançois Tigeot if (i915.enable_execlists) 17271b13d190SFrançois Tigeot return 0; 17281b13d190SFrançois Tigeot 17291b13d190SFrançois Tigeot if (!USES_PPGTT(dev)) 17301b13d190SFrançois Tigeot return 0; 17311b13d190SFrançois Tigeot 17321b13d190SFrançois Tigeot if (IS_GEN6(dev)) 17331b13d190SFrançois Tigeot gen6_ppgtt_enable(dev); 17341b13d190SFrançois Tigeot else if (IS_GEN7(dev)) 17351b13d190SFrançois Tigeot gen7_ppgtt_enable(dev); 17361b13d190SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 8) 17371b13d190SFrançois Tigeot gen8_ppgtt_enable(dev); 17381b13d190SFrançois Tigeot else 17392c9916cdSFrançois Tigeot MISSING_CASE(INTEL_INFO(dev)->gen); 17401b13d190SFrançois Tigeot 1741*a05eeebfSFrançois Tigeot return 0; 17429edbd4a0SFrançois Tigeot } 1743a2fdbec6SFrançois Tigeot 1744*a05eeebfSFrançois Tigeot int i915_ppgtt_init_ring(struct drm_i915_gem_request *req) 1745*a05eeebfSFrançois Tigeot { 1746*a05eeebfSFrançois Tigeot struct drm_i915_private *dev_priv = req->ring->dev->dev_private; 1747*a05eeebfSFrançois Tigeot struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; 1748*a05eeebfSFrançois Tigeot 1749*a05eeebfSFrançois Tigeot if (i915.enable_execlists) 1750*a05eeebfSFrançois Tigeot return 0; 1751*a05eeebfSFrançois Tigeot 1752*a05eeebfSFrançois Tigeot if (!ppgtt) 1753*a05eeebfSFrançois Tigeot return 0; 1754*a05eeebfSFrançois Tigeot 1755*a05eeebfSFrançois Tigeot return ppgtt->switch_mm(ppgtt, req); 1756a2fdbec6SFrançois Tigeot } 1757*a05eeebfSFrançois Tigeot 17581b13d190SFrançois Tigeot struct i915_hw_ppgtt * 17591b13d190SFrançois Tigeot i915_ppgtt_create(struct drm_device *dev, struct drm_i915_file_private *fpriv) 17601b13d190SFrançois Tigeot { 17611b13d190SFrançois Tigeot struct i915_hw_ppgtt *ppgtt; 17621b13d190SFrançois Tigeot int ret; 17631b13d190SFrançois Tigeot 17641b13d190SFrançois Tigeot ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); 17651b13d190SFrançois Tigeot if (!ppgtt) 17661b13d190SFrançois Tigeot return ERR_PTR(-ENOMEM); 17671b13d190SFrançois Tigeot 17681b13d190SFrançois Tigeot ret = i915_ppgtt_init(dev, ppgtt); 17691b13d190SFrançois Tigeot if (ret) { 17701b13d190SFrançois Tigeot kfree(ppgtt); 17711b13d190SFrançois Tigeot return ERR_PTR(ret); 17721b13d190SFrançois Tigeot } 17731b13d190SFrançois Tigeot 17741b13d190SFrançois Tigeot ppgtt->file_priv = fpriv; 17751b13d190SFrançois Tigeot 17762c9916cdSFrançois Tigeot trace_i915_ppgtt_create(&ppgtt->base); 17772c9916cdSFrançois Tigeot 17781b13d190SFrançois Tigeot return ppgtt; 17791b13d190SFrançois Tigeot } 17801b13d190SFrançois Tigeot 17811b13d190SFrançois Tigeot void i915_ppgtt_release(struct kref *kref) 17821b13d190SFrançois Tigeot { 17831b13d190SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = 17841b13d190SFrançois Tigeot container_of(kref, struct i915_hw_ppgtt, ref); 17851b13d190SFrançois Tigeot 17862c9916cdSFrançois Tigeot trace_i915_ppgtt_release(&ppgtt->base); 17872c9916cdSFrançois Tigeot 17881b13d190SFrançois Tigeot /* vmas should already be unbound */ 17891b13d190SFrançois Tigeot WARN_ON(!list_empty(&ppgtt->base.active_list)); 17901b13d190SFrançois Tigeot WARN_ON(!list_empty(&ppgtt->base.inactive_list)); 17911b13d190SFrançois Tigeot 17921b13d190SFrançois Tigeot list_del(&ppgtt->base.global_link); 17931b13d190SFrançois Tigeot drm_mm_takedown(&ppgtt->base.mm); 17941b13d190SFrançois Tigeot 17951b13d190SFrançois Tigeot ppgtt->base.cleanup(&ppgtt->base); 17961b13d190SFrançois Tigeot kfree(ppgtt); 17971b13d190SFrançois Tigeot } 1798a2fdbec6SFrançois Tigeot 1799a2fdbec6SFrançois Tigeot extern int intel_iommu_gfx_mapped; 1800a2fdbec6SFrançois Tigeot /* Certain Gen5 chipsets require require idling the GPU before 1801a2fdbec6SFrançois Tigeot * unmapping anything from the GTT when VT-d is enabled. 1802a2fdbec6SFrançois Tigeot */ 180319c468b4SFrançois Tigeot static bool needs_idle_maps(struct drm_device *dev) 1804a2fdbec6SFrançois Tigeot { 1805a2fdbec6SFrançois Tigeot #ifdef CONFIG_INTEL_IOMMU 1806a2fdbec6SFrançois Tigeot /* Query intel_iommu to see if we need the workaround. Presumably that 1807a2fdbec6SFrançois Tigeot * was loaded first. 1808a2fdbec6SFrançois Tigeot */ 1809a2fdbec6SFrançois Tigeot if (IS_GEN5(dev) && IS_MOBILE(dev) && intel_iommu_gfx_mapped) 1810a2fdbec6SFrançois Tigeot return true; 1811a2fdbec6SFrançois Tigeot #endif 1812a2fdbec6SFrançois Tigeot return false; 1813a2fdbec6SFrançois Tigeot } 1814a2fdbec6SFrançois Tigeot 18157cbd1a46SFrançois Tigeot static bool do_idling(struct drm_i915_private *dev_priv) 1816e3adcf8fSFrançois Tigeot { 1817e3adcf8fSFrançois Tigeot bool ret = dev_priv->mm.interruptible; 1818e3adcf8fSFrançois Tigeot 1819a2fdbec6SFrançois Tigeot if (unlikely(dev_priv->gtt.do_idle_maps)) { 1820e3adcf8fSFrançois Tigeot dev_priv->mm.interruptible = false; 1821b030f26bSFrançois Tigeot if (i915_gpu_idle(dev_priv->dev)) { 1822e3adcf8fSFrançois Tigeot DRM_ERROR("Couldn't idle GPU\n"); 1823e3adcf8fSFrançois Tigeot /* Wait a bit, in hopes it avoids the hang */ 18240b869d8aSFrançois Tigeot udelay(10); 1825e3adcf8fSFrançois Tigeot } 1826e3adcf8fSFrançois Tigeot } 1827e3adcf8fSFrançois Tigeot 1828e3adcf8fSFrançois Tigeot return ret; 1829e3adcf8fSFrançois Tigeot } 1830e3adcf8fSFrançois Tigeot 18317cbd1a46SFrançois Tigeot static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) 1832e3adcf8fSFrançois Tigeot { 1833a2fdbec6SFrançois Tigeot if (unlikely(dev_priv->gtt.do_idle_maps)) 1834e3adcf8fSFrançois Tigeot dev_priv->mm.interruptible = interruptible; 1835e3adcf8fSFrançois Tigeot } 1836e3adcf8fSFrançois Tigeot 18379edbd4a0SFrançois Tigeot void i915_check_and_clear_faults(struct drm_device *dev) 18389edbd4a0SFrançois Tigeot { 18399edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1840ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring; 18419edbd4a0SFrançois Tigeot int i; 18429edbd4a0SFrançois Tigeot 18439edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen < 6) 18449edbd4a0SFrançois Tigeot return; 18459edbd4a0SFrançois Tigeot 18469edbd4a0SFrançois Tigeot for_each_ring(ring, dev_priv, i) { 18479edbd4a0SFrançois Tigeot u32 fault_reg; 18489edbd4a0SFrançois Tigeot fault_reg = I915_READ(RING_FAULT_REG(ring)); 18499edbd4a0SFrançois Tigeot if (fault_reg & RING_FAULT_VALID) { 18509edbd4a0SFrançois Tigeot #if 0 18519edbd4a0SFrançois Tigeot DRM_DEBUG_DRIVER("Unexpected fault\n" 18522c9916cdSFrançois Tigeot "\tAddr: 0x%08lx\n" 18539edbd4a0SFrançois Tigeot "\tAddress space: %s\n" 18549edbd4a0SFrançois Tigeot "\tSource ID: %d\n" 18559edbd4a0SFrançois Tigeot "\tType: %d\n", 18569edbd4a0SFrançois Tigeot fault_reg & PAGE_MASK, 18579edbd4a0SFrançois Tigeot fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT", 18589edbd4a0SFrançois Tigeot RING_FAULT_SRCID(fault_reg), 18599edbd4a0SFrançois Tigeot RING_FAULT_FAULT_TYPE(fault_reg)); 18609edbd4a0SFrançois Tigeot #endif 18619edbd4a0SFrançois Tigeot I915_WRITE(RING_FAULT_REG(ring), 18629edbd4a0SFrançois Tigeot fault_reg & ~RING_FAULT_VALID); 18639edbd4a0SFrançois Tigeot } 18649edbd4a0SFrançois Tigeot } 18659edbd4a0SFrançois Tigeot POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS])); 18669edbd4a0SFrançois Tigeot } 18679edbd4a0SFrançois Tigeot 186824edb884SFrançois Tigeot static void i915_ggtt_flush(struct drm_i915_private *dev_priv) 186924edb884SFrançois Tigeot { 187024edb884SFrançois Tigeot if (INTEL_INFO(dev_priv->dev)->gen < 6) { 187124edb884SFrançois Tigeot intel_gtt_chipset_flush(); 187224edb884SFrançois Tigeot } else { 187324edb884SFrançois Tigeot I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); 187424edb884SFrançois Tigeot POSTING_READ(GFX_FLSH_CNTL_GEN6); 187524edb884SFrançois Tigeot } 187624edb884SFrançois Tigeot } 187724edb884SFrançois Tigeot 18789edbd4a0SFrançois Tigeot void i915_gem_suspend_gtt_mappings(struct drm_device *dev) 18799edbd4a0SFrançois Tigeot { 18809edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 18819edbd4a0SFrançois Tigeot 18829edbd4a0SFrançois Tigeot /* Don't bother messing with faults pre GEN6 as we have little 18839edbd4a0SFrançois Tigeot * documentation supporting that it's a good idea. 18849edbd4a0SFrançois Tigeot */ 18859edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen < 6) 18869edbd4a0SFrançois Tigeot return; 18879edbd4a0SFrançois Tigeot 18889edbd4a0SFrançois Tigeot i915_check_and_clear_faults(dev); 18899edbd4a0SFrançois Tigeot 18909edbd4a0SFrançois Tigeot dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, 1891ba55f2f5SFrançois Tigeot dev_priv->gtt.base.start, 1892ba55f2f5SFrançois Tigeot dev_priv->gtt.base.total, 18939edbd4a0SFrançois Tigeot true); 189424edb884SFrançois Tigeot 189524edb884SFrançois Tigeot i915_ggtt_flush(dev_priv); 18969edbd4a0SFrançois Tigeot } 18979edbd4a0SFrançois Tigeot 18980b869d8aSFrançois Tigeot int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) 18990b869d8aSFrançois Tigeot { 19007ec9f8e5SFrançois Tigeot if (!dma_map_sg(obj->base.dev->pdev->dev, 19010b869d8aSFrançois Tigeot obj->pages->sgl, obj->pages->nents, 19020b869d8aSFrançois Tigeot PCI_DMA_BIDIRECTIONAL)) 19030b869d8aSFrançois Tigeot return -ENOSPC; 19040b869d8aSFrançois Tigeot 19050b869d8aSFrançois Tigeot return 0; 19060b869d8aSFrançois Tigeot } 19070b869d8aSFrançois Tigeot 190819c468b4SFrançois Tigeot static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte) 1909e3adcf8fSFrançois Tigeot { 19109edbd4a0SFrançois Tigeot #if 0 19119edbd4a0SFrançois Tigeot writeq(pte, addr); 19129edbd4a0SFrançois Tigeot #else 19139edbd4a0SFrançois Tigeot iowrite32((u32)pte, addr); 19149edbd4a0SFrançois Tigeot iowrite32(pte >> 32, addr + 4); 19159edbd4a0SFrançois Tigeot #endif 19167cbd1a46SFrançois Tigeot } 1917e3adcf8fSFrançois Tigeot 19189edbd4a0SFrançois Tigeot static void gen8_ggtt_insert_entries(struct i915_address_space *vm, 19197ec9f8e5SFrançois Tigeot struct sg_table *st, 1920ba55f2f5SFrançois Tigeot uint64_t start, 192124edb884SFrançois Tigeot enum i915_cache_level level, u32 unused) 19229edbd4a0SFrançois Tigeot { 19239edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = vm->dev->dev_private; 1924ba55f2f5SFrançois Tigeot unsigned first_entry = start >> PAGE_SHIFT; 1925477eb7f9SFrançois Tigeot gen8_pte_t __iomem *gtt_entries = 1926477eb7f9SFrançois Tigeot (gen8_pte_t __iomem *)dev_priv->gtt.gsm + first_entry; 19279edbd4a0SFrançois Tigeot int i = 0; 19287ec9f8e5SFrançois Tigeot struct sg_page_iter sg_iter; 19297ec9f8e5SFrançois Tigeot dma_addr_t addr = 0; /* shut up gcc */ 19309edbd4a0SFrançois Tigeot 19317ec9f8e5SFrançois Tigeot for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { 19327ec9f8e5SFrançois Tigeot addr = sg_dma_address(sg_iter.sg) + 19337ec9f8e5SFrançois Tigeot (sg_iter.sg_pgoffset << PAGE_SHIFT); 19349edbd4a0SFrançois Tigeot gen8_set_pte(>t_entries[i], 19359edbd4a0SFrançois Tigeot gen8_pte_encode(addr, level, true)); 19367ec9f8e5SFrançois Tigeot i++; 19379edbd4a0SFrançois Tigeot } 19389edbd4a0SFrançois Tigeot 19399edbd4a0SFrançois Tigeot /* 19409edbd4a0SFrançois Tigeot * XXX: This serves as a posting read to make sure that the PTE has 19417cbd1a46SFrançois Tigeot * actually been updated. There is some concern that even though 19427cbd1a46SFrançois Tigeot * registers and PTEs are within the same BAR that they are potentially 19437cbd1a46SFrançois Tigeot * of NUMA access patterns. Therefore, even with the way we assume 19447cbd1a46SFrançois Tigeot * hardware should work, we must keep this posting read for paranoia. 19457cbd1a46SFrançois Tigeot */ 19467cbd1a46SFrançois Tigeot if (i != 0) 19479edbd4a0SFrançois Tigeot WARN_ON(readq(>t_entries[i-1]) 19489edbd4a0SFrançois Tigeot != gen8_pte_encode(addr, level, true)); 19497cbd1a46SFrançois Tigeot 19507cbd1a46SFrançois Tigeot /* This next bit makes the above posting read even more important. We 19517cbd1a46SFrançois Tigeot * want to flush the TLBs only after we're certain all the PTE updates 19527cbd1a46SFrançois Tigeot * have finished. 19537cbd1a46SFrançois Tigeot */ 19547cbd1a46SFrançois Tigeot I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); 19557cbd1a46SFrançois Tigeot POSTING_READ(GFX_FLSH_CNTL_GEN6); 1956a2fdbec6SFrançois Tigeot } 1957a2fdbec6SFrançois Tigeot 19589edbd4a0SFrançois Tigeot /* 19599edbd4a0SFrançois Tigeot * Binds an object into the global gtt with the specified cache level. The object 19609edbd4a0SFrançois Tigeot * will be accessible to the GPU via commands whose operands reference offsets 19619edbd4a0SFrançois Tigeot * within the global GTT as well as accessible by the GPU through the GMADR 19629edbd4a0SFrançois Tigeot * mapped BAR (dev_priv->mm.gtt->gtt). 19639edbd4a0SFrançois Tigeot */ 19649edbd4a0SFrançois Tigeot static void gen6_ggtt_insert_entries(struct i915_address_space *vm, 19657ec9f8e5SFrançois Tigeot struct sg_table *st, 1966ba55f2f5SFrançois Tigeot uint64_t start, 196724edb884SFrançois Tigeot enum i915_cache_level level, u32 flags) 1968a2fdbec6SFrançois Tigeot { 19699edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = vm->dev->dev_private; 1970ba55f2f5SFrançois Tigeot unsigned first_entry = start >> PAGE_SHIFT; 1971477eb7f9SFrançois Tigeot gen6_pte_t __iomem *gtt_entries = 1972477eb7f9SFrançois Tigeot (gen6_pte_t __iomem *)dev_priv->gtt.gsm + first_entry; 19739edbd4a0SFrançois Tigeot int i = 0; 19747ec9f8e5SFrançois Tigeot struct sg_page_iter sg_iter; 19757ec9f8e5SFrançois Tigeot dma_addr_t addr = 0; 19769edbd4a0SFrançois Tigeot 19777ec9f8e5SFrançois Tigeot for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { 19787ec9f8e5SFrançois Tigeot addr = sg_page_iter_dma_address(&sg_iter); 197924edb884SFrançois Tigeot iowrite32(vm->pte_encode(addr, level, true, flags), >t_entries[i]); 19807ec9f8e5SFrançois Tigeot i++; 19819edbd4a0SFrançois Tigeot } 19829edbd4a0SFrançois Tigeot 19839edbd4a0SFrançois Tigeot /* XXX: This serves as a posting read to make sure that the PTE has 19849edbd4a0SFrançois Tigeot * actually been updated. There is some concern that even though 19859edbd4a0SFrançois Tigeot * registers and PTEs are within the same BAR that they are potentially 19869edbd4a0SFrançois Tigeot * of NUMA access patterns. Therefore, even with the way we assume 19879edbd4a0SFrançois Tigeot * hardware should work, we must keep this posting read for paranoia. 19889edbd4a0SFrançois Tigeot */ 198924edb884SFrançois Tigeot if (i != 0) { 199024edb884SFrançois Tigeot unsigned long gtt = readl(>t_entries[i-1]); 199124edb884SFrançois Tigeot WARN_ON(gtt != vm->pte_encode(addr, level, true, flags)); 199224edb884SFrançois Tigeot } 19939edbd4a0SFrançois Tigeot 19949edbd4a0SFrançois Tigeot /* This next bit makes the above posting read even more important. We 19959edbd4a0SFrançois Tigeot * want to flush the TLBs only after we're certain all the PTE updates 19969edbd4a0SFrançois Tigeot * have finished. 19979edbd4a0SFrançois Tigeot */ 19989edbd4a0SFrançois Tigeot I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); 19999edbd4a0SFrançois Tigeot POSTING_READ(GFX_FLSH_CNTL_GEN6); 20009edbd4a0SFrançois Tigeot } 20019edbd4a0SFrançois Tigeot 20029edbd4a0SFrançois Tigeot static void gen8_ggtt_clear_range(struct i915_address_space *vm, 2003ba55f2f5SFrançois Tigeot uint64_t start, 2004ba55f2f5SFrançois Tigeot uint64_t length, 20059edbd4a0SFrançois Tigeot bool use_scratch) 20069edbd4a0SFrançois Tigeot { 20079edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = vm->dev->dev_private; 2008ba55f2f5SFrançois Tigeot unsigned first_entry = start >> PAGE_SHIFT; 2009ba55f2f5SFrançois Tigeot unsigned num_entries = length >> PAGE_SHIFT; 2010477eb7f9SFrançois Tigeot gen8_pte_t scratch_pte, __iomem *gtt_base = 2011477eb7f9SFrançois Tigeot (gen8_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; 20129edbd4a0SFrançois Tigeot const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; 20139edbd4a0SFrançois Tigeot int i; 20149edbd4a0SFrançois Tigeot 20159edbd4a0SFrançois Tigeot if (WARN(num_entries > max_entries, 20169edbd4a0SFrançois Tigeot "First entry = %d; Num entries = %d (max=%d)\n", 20179edbd4a0SFrançois Tigeot first_entry, num_entries, max_entries)) 20189edbd4a0SFrançois Tigeot num_entries = max_entries; 20199edbd4a0SFrançois Tigeot 2020*a05eeebfSFrançois Tigeot scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), 20219edbd4a0SFrançois Tigeot I915_CACHE_LLC, 20229edbd4a0SFrançois Tigeot use_scratch); 20239edbd4a0SFrançois Tigeot for (i = 0; i < num_entries; i++) 20249edbd4a0SFrançois Tigeot gen8_set_pte(>t_base[i], scratch_pte); 20259edbd4a0SFrançois Tigeot readl(gtt_base); 20269edbd4a0SFrançois Tigeot } 20279edbd4a0SFrançois Tigeot 20289edbd4a0SFrançois Tigeot static void gen6_ggtt_clear_range(struct i915_address_space *vm, 2029ba55f2f5SFrançois Tigeot uint64_t start, 2030ba55f2f5SFrançois Tigeot uint64_t length, 20319edbd4a0SFrançois Tigeot bool use_scratch) 20329edbd4a0SFrançois Tigeot { 20339edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = vm->dev->dev_private; 2034ba55f2f5SFrançois Tigeot unsigned first_entry = start >> PAGE_SHIFT; 2035ba55f2f5SFrançois Tigeot unsigned num_entries = length >> PAGE_SHIFT; 2036477eb7f9SFrançois Tigeot gen6_pte_t scratch_pte, __iomem *gtt_base = 2037477eb7f9SFrançois Tigeot (gen6_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; 20388e26cdf6SFrançois Tigeot const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; 2039a2fdbec6SFrançois Tigeot int i; 2040a2fdbec6SFrançois Tigeot 2041a2fdbec6SFrançois Tigeot if (WARN(num_entries > max_entries, 2042a2fdbec6SFrançois Tigeot "First entry = %d; Num entries = %d (max=%d)\n", 2043a2fdbec6SFrançois Tigeot first_entry, num_entries, max_entries)) 2044a2fdbec6SFrançois Tigeot num_entries = max_entries; 2045a2fdbec6SFrançois Tigeot 2046*a05eeebfSFrançois Tigeot scratch_pte = vm->pte_encode(px_dma(vm->scratch_page), 2047*a05eeebfSFrançois Tigeot I915_CACHE_LLC, use_scratch, 0); 20489edbd4a0SFrançois Tigeot 2049a2fdbec6SFrançois Tigeot for (i = 0; i < num_entries; i++) 2050a2fdbec6SFrançois Tigeot iowrite32(scratch_pte, >t_base[i]); 2051a2fdbec6SFrançois Tigeot readl(gtt_base); 2052a2fdbec6SFrançois Tigeot } 2053a2fdbec6SFrançois Tigeot 20547ec9f8e5SFrançois Tigeot static void i915_ggtt_insert_entries(struct i915_address_space *vm, 20557ec9f8e5SFrançois Tigeot struct sg_table *pages, 20567ec9f8e5SFrançois Tigeot uint64_t start, 20577ec9f8e5SFrançois Tigeot enum i915_cache_level cache_level, u32 unused) 2058a2fdbec6SFrançois Tigeot { 2059a2fdbec6SFrançois Tigeot unsigned int flags = (cache_level == I915_CACHE_NONE) ? 2060a2fdbec6SFrançois Tigeot AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY; 2061a2fdbec6SFrançois Tigeot 20627ec9f8e5SFrançois Tigeot intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags); 2063a2fdbec6SFrançois Tigeot } 2064a2fdbec6SFrançois Tigeot 20659edbd4a0SFrançois Tigeot static void i915_ggtt_clear_range(struct i915_address_space *vm, 2066ba55f2f5SFrançois Tigeot uint64_t start, 2067ba55f2f5SFrançois Tigeot uint64_t length, 20689edbd4a0SFrançois Tigeot bool unused) 2069a2fdbec6SFrançois Tigeot { 2070ba55f2f5SFrançois Tigeot unsigned first_entry = start >> PAGE_SHIFT; 2071ba55f2f5SFrançois Tigeot unsigned num_entries = length >> PAGE_SHIFT; 2072a2fdbec6SFrançois Tigeot intel_gtt_clear_range(first_entry, num_entries); 2073a2fdbec6SFrançois Tigeot } 20747cbd1a46SFrançois Tigeot 207519c468b4SFrançois Tigeot static int ggtt_bind_vma(struct i915_vma *vma, 2076ba55f2f5SFrançois Tigeot enum i915_cache_level cache_level, 2077ba55f2f5SFrançois Tigeot u32 flags) 2078e3adcf8fSFrançois Tigeot { 2079ba55f2f5SFrançois Tigeot struct drm_device *dev = vma->vm->dev; 2080e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2081ba55f2f5SFrançois Tigeot struct drm_i915_gem_object *obj = vma->obj; 20827ec9f8e5SFrançois Tigeot struct sg_table *pages = obj->pages; 208319c468b4SFrançois Tigeot u32 pte_flags = 0; 20847ec9f8e5SFrançois Tigeot int ret; 20857ec9f8e5SFrançois Tigeot 20867ec9f8e5SFrançois Tigeot ret = i915_get_ggtt_vma_pages(vma); 20877ec9f8e5SFrançois Tigeot if (ret) 20887ec9f8e5SFrançois Tigeot return ret; 20897ec9f8e5SFrançois Tigeot pages = vma->ggtt_view.pages; 2090e3adcf8fSFrançois Tigeot 209124edb884SFrançois Tigeot /* Currently applicable only to VLV */ 209224edb884SFrançois Tigeot if (obj->gt_ro) 209319c468b4SFrançois Tigeot pte_flags |= PTE_READ_ONLY; 209424edb884SFrançois Tigeot 2095477eb7f9SFrançois Tigeot 2096ba55f2f5SFrançois Tigeot if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) { 2097477eb7f9SFrançois Tigeot vma->vm->insert_entries(vma->vm, pages, 2098ba55f2f5SFrançois Tigeot vma->node.start, 209919c468b4SFrançois Tigeot cache_level, pte_flags); 2100ba55f2f5SFrançois Tigeot } 2101e3adcf8fSFrançois Tigeot 210219c468b4SFrançois Tigeot if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) { 2103ba55f2f5SFrançois Tigeot struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt; 2104477eb7f9SFrançois Tigeot appgtt->base.insert_entries(&appgtt->base, pages, 2105ba55f2f5SFrançois Tigeot vma->node.start, 210619c468b4SFrançois Tigeot cache_level, pte_flags); 2107ba55f2f5SFrançois Tigeot } 210819c468b4SFrançois Tigeot 210919c468b4SFrançois Tigeot return 0; 2110ba55f2f5SFrançois Tigeot } 2111ba55f2f5SFrançois Tigeot 2112ba55f2f5SFrançois Tigeot static void ggtt_unbind_vma(struct i915_vma *vma) 2113ba55f2f5SFrançois Tigeot { 2114ba55f2f5SFrançois Tigeot struct drm_device *dev = vma->vm->dev; 2115ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2116ba55f2f5SFrançois Tigeot struct drm_i915_gem_object *obj = vma->obj; 211719c468b4SFrançois Tigeot const uint64_t size = min_t(uint64_t, 211819c468b4SFrançois Tigeot obj->base.size, 211919c468b4SFrançois Tigeot vma->node.size); 2120ba55f2f5SFrançois Tigeot 21212c9916cdSFrançois Tigeot if (vma->bound & GLOBAL_BIND) { 2122ba55f2f5SFrançois Tigeot vma->vm->clear_range(vma->vm, 2123ba55f2f5SFrançois Tigeot vma->node.start, 212419c468b4SFrançois Tigeot size, 2125ba55f2f5SFrançois Tigeot true); 2126f4e1c372SFrançois Tigeot } 2127f192107fSFrançois Tigeot 212819c468b4SFrançois Tigeot if (dev_priv->mm.aliasing_ppgtt && vma->bound & LOCAL_BIND) { 2129ba55f2f5SFrançois Tigeot struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt; 213019c468b4SFrançois Tigeot 2131ba55f2f5SFrançois Tigeot appgtt->base.clear_range(&appgtt->base, 2132ba55f2f5SFrançois Tigeot vma->node.start, 213319c468b4SFrançois Tigeot size, 2134ba55f2f5SFrançois Tigeot true); 2135ba55f2f5SFrançois Tigeot } 2136ba55f2f5SFrançois Tigeot } 2137ba55f2f5SFrançois Tigeot 2138f192107fSFrançois Tigeot void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) 2139f192107fSFrançois Tigeot { 2140f192107fSFrançois Tigeot struct drm_device *dev = obj->base.dev; 2141f192107fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2142f192107fSFrançois Tigeot bool interruptible; 2143f192107fSFrançois Tigeot 2144f192107fSFrançois Tigeot interruptible = do_idling(dev_priv); 2145f192107fSFrançois Tigeot 21467ec9f8e5SFrançois Tigeot dma_unmap_sg(dev->pdev->dev, obj->pages->sgl, obj->pages->nents, 2147f192107fSFrançois Tigeot PCI_DMA_BIDIRECTIONAL); 2148f192107fSFrançois Tigeot 2149f192107fSFrançois Tigeot undo_idling(dev_priv, interruptible); 2150f192107fSFrançois Tigeot } 2151d1c259eeSFrançois Tigeot 2152d1c259eeSFrançois Tigeot static void i915_gtt_color_adjust(struct drm_mm_node *node, 2153d1c259eeSFrançois Tigeot unsigned long color, 21542c9916cdSFrançois Tigeot u64 *start, 21552c9916cdSFrançois Tigeot u64 *end) 2156d1c259eeSFrançois Tigeot { 2157d1c259eeSFrançois Tigeot if (node->color != color) 2158d1c259eeSFrançois Tigeot *start += 4096; 2159d1c259eeSFrançois Tigeot 2160d1c259eeSFrançois Tigeot if (!list_empty(&node->node_list)) { 2161d1c259eeSFrançois Tigeot node = list_entry(node->node_list.next, 2162d1c259eeSFrançois Tigeot struct drm_mm_node, 2163d1c259eeSFrançois Tigeot node_list); 2164d1c259eeSFrançois Tigeot if (node->allocated && node->color != color) 2165d1c259eeSFrançois Tigeot *end -= 4096; 2166d1c259eeSFrançois Tigeot } 2167d1c259eeSFrançois Tigeot } 21689edbd4a0SFrançois Tigeot 21692c9916cdSFrançois Tigeot static int i915_gem_setup_global_gtt(struct drm_device *dev, 2170d1c259eeSFrançois Tigeot unsigned long start, 2171d1c259eeSFrançois Tigeot unsigned long mappable_end, 2172d1c259eeSFrançois Tigeot unsigned long end) 2173d1c259eeSFrançois Tigeot { 2174a2fdbec6SFrançois Tigeot /* Let GEM Manage all of the aperture. 2175a2fdbec6SFrançois Tigeot * 2176a2fdbec6SFrançois Tigeot * However, leave one page at the end still bound to the scratch page. 2177a2fdbec6SFrançois Tigeot * There are a number of places where the hardware apparently prefetches 2178a2fdbec6SFrançois Tigeot * past the end of the object, and we've seen multiple hangs with the 2179a2fdbec6SFrançois Tigeot * GPU head pointer stuck in a batchbuffer bound at the last page of the 2180a2fdbec6SFrançois Tigeot * aperture. One page should be enough to keep any prefetching inside 2181a2fdbec6SFrançois Tigeot * of the aperture. 2182a2fdbec6SFrançois Tigeot */ 21839edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 21849edbd4a0SFrançois Tigeot struct i915_address_space *ggtt_vm = &dev_priv->gtt.base; 2185e084c92dSFrançois Tigeot unsigned long mappable; 2186e084c92dSFrançois Tigeot int error; 21879edbd4a0SFrançois Tigeot struct drm_mm_node *entry; 21889edbd4a0SFrançois Tigeot struct drm_i915_gem_object *obj; 21899edbd4a0SFrançois Tigeot unsigned long hole_start, hole_end; 21901b13d190SFrançois Tigeot int ret; 2191e084c92dSFrançois Tigeot 2192e084c92dSFrançois Tigeot mappable = min(end, mappable_end) - start; 21937ec9f8e5SFrançois Tigeot BUG_ON(mappable_end > end); 2194e084c92dSFrançois Tigeot 21959edbd4a0SFrançois Tigeot /* Subtract the guard page ... */ 21969edbd4a0SFrançois Tigeot drm_mm_init(&ggtt_vm->mm, start, end - start - PAGE_SIZE); 2197477eb7f9SFrançois Tigeot 2198477eb7f9SFrançois Tigeot dev_priv->gtt.base.start = start; 2199477eb7f9SFrançois Tigeot dev_priv->gtt.base.total = end - start; 2200477eb7f9SFrançois Tigeot 2201477eb7f9SFrançois Tigeot if (intel_vgpu_active(dev)) { 2202477eb7f9SFrançois Tigeot ret = intel_vgt_balloon(dev); 2203477eb7f9SFrançois Tigeot if (ret) 2204477eb7f9SFrançois Tigeot return ret; 2205477eb7f9SFrançois Tigeot } 2206477eb7f9SFrançois Tigeot 2207d1c259eeSFrançois Tigeot if (!HAS_LLC(dev)) 22089edbd4a0SFrançois Tigeot dev_priv->gtt.base.mm.color_adjust = i915_gtt_color_adjust; 2209d1c259eeSFrançois Tigeot 22109edbd4a0SFrançois Tigeot /* Mark any preallocated objects as occupied */ 22119edbd4a0SFrançois Tigeot list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { 22129edbd4a0SFrançois Tigeot struct i915_vma *vma = i915_gem_obj_to_vma(obj, ggtt_vm); 22131b13d190SFrançois Tigeot 22149edbd4a0SFrançois Tigeot DRM_DEBUG_KMS("reserving preallocated space: %lx + %zx\n", 22159edbd4a0SFrançois Tigeot i915_gem_obj_ggtt_offset(obj), obj->base.size); 2216d1c259eeSFrançois Tigeot 22179edbd4a0SFrançois Tigeot WARN_ON(i915_gem_obj_ggtt_bound(obj)); 22189edbd4a0SFrançois Tigeot ret = drm_mm_reserve_node(&ggtt_vm->mm, &vma->node); 22191b13d190SFrançois Tigeot if (ret) { 22201b13d190SFrançois Tigeot DRM_DEBUG_KMS("Reservation failed: %i\n", ret); 22211b13d190SFrançois Tigeot return ret; 22221b13d190SFrançois Tigeot } 22232c9916cdSFrançois Tigeot vma->bound |= GLOBAL_BIND; 22249edbd4a0SFrançois Tigeot } 22259edbd4a0SFrançois Tigeot 22269edbd4a0SFrançois Tigeot /* Clear any non-preallocated blocks */ 22279edbd4a0SFrançois Tigeot drm_mm_for_each_hole(entry, &ggtt_vm->mm, hole_start, hole_end) { 22289edbd4a0SFrançois Tigeot DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", 22299edbd4a0SFrançois Tigeot hole_start, hole_end); 2230ba55f2f5SFrançois Tigeot ggtt_vm->clear_range(ggtt_vm, hole_start, 2231ba55f2f5SFrançois Tigeot hole_end - hole_start, true); 22329edbd4a0SFrançois Tigeot } 2233cb170299SFrançois Tigeot 2234310880c6SSascha Wildner #ifdef __DragonFly__ 2235e084c92dSFrançois Tigeot device_printf(dev->dev, 2236e084c92dSFrançois Tigeot "taking over the fictitious range 0x%lx-0x%lx\n", 2237cb170299SFrançois Tigeot dev_priv->gtt.mappable_base + start, dev_priv->gtt.mappable_base + start + mappable); 2238cb170299SFrançois Tigeot error = -vm_phys_fictitious_reg_range(dev_priv->gtt.mappable_base + start, 2239cb170299SFrançois Tigeot dev_priv->gtt.mappable_base + start + mappable, VM_MEMATTR_WRITE_COMBINING); 2240310880c6SSascha Wildner #endif 22419edbd4a0SFrançois Tigeot 22429edbd4a0SFrançois Tigeot /* And finally clear the reserved guard page */ 2243ba55f2f5SFrançois Tigeot ggtt_vm->clear_range(ggtt_vm, end - PAGE_SIZE, PAGE_SIZE, true); 22441b13d190SFrançois Tigeot 22451b13d190SFrançois Tigeot if (USES_PPGTT(dev) && !USES_FULL_PPGTT(dev)) { 22461b13d190SFrançois Tigeot struct i915_hw_ppgtt *ppgtt; 22471b13d190SFrançois Tigeot 22481b13d190SFrançois Tigeot ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); 22491b13d190SFrançois Tigeot if (!ppgtt) 22501b13d190SFrançois Tigeot return -ENOMEM; 22511b13d190SFrançois Tigeot 2252477eb7f9SFrançois Tigeot ret = __hw_ppgtt_init(dev, ppgtt, true); 2253477eb7f9SFrançois Tigeot if (ret) { 225419c468b4SFrançois Tigeot ppgtt->base.cleanup(&ppgtt->base); 2255477eb7f9SFrançois Tigeot kfree(ppgtt); 22561b13d190SFrançois Tigeot return ret; 2257477eb7f9SFrançois Tigeot } 22581b13d190SFrançois Tigeot 22597ec9f8e5SFrançois Tigeot if (ppgtt->base.allocate_va_range) 22607ec9f8e5SFrançois Tigeot ret = ppgtt->base.allocate_va_range(&ppgtt->base, 0, 22617ec9f8e5SFrançois Tigeot ppgtt->base.total); 22627ec9f8e5SFrançois Tigeot if (ret) { 22637ec9f8e5SFrançois Tigeot ppgtt->base.cleanup(&ppgtt->base); 22647ec9f8e5SFrançois Tigeot kfree(ppgtt); 22657ec9f8e5SFrançois Tigeot return ret; 22667ec9f8e5SFrançois Tigeot } 22677ec9f8e5SFrançois Tigeot 22687ec9f8e5SFrançois Tigeot ppgtt->base.clear_range(&ppgtt->base, 22697ec9f8e5SFrançois Tigeot ppgtt->base.start, 22707ec9f8e5SFrançois Tigeot ppgtt->base.total, 22717ec9f8e5SFrançois Tigeot true); 22727ec9f8e5SFrançois Tigeot 22731b13d190SFrançois Tigeot dev_priv->mm.aliasing_ppgtt = ppgtt; 22741b13d190SFrançois Tigeot } 22751b13d190SFrançois Tigeot 22761b13d190SFrançois Tigeot return 0; 2277a2fdbec6SFrançois Tigeot } 2278a2fdbec6SFrançois Tigeot 2279a2fdbec6SFrançois Tigeot void i915_gem_init_global_gtt(struct drm_device *dev) 2280a2fdbec6SFrançois Tigeot { 2281a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2282*a05eeebfSFrançois Tigeot u64 gtt_size, mappable_size; 2283a2fdbec6SFrançois Tigeot 22849edbd4a0SFrançois Tigeot gtt_size = dev_priv->gtt.base.total; 22859edbd4a0SFrançois Tigeot mappable_size = dev_priv->gtt.mappable_end; 2286a2fdbec6SFrançois Tigeot 2287a2fdbec6SFrançois Tigeot i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size); 2288a2fdbec6SFrançois Tigeot } 2289a2fdbec6SFrançois Tigeot 22901b13d190SFrançois Tigeot void i915_global_gtt_cleanup(struct drm_device *dev) 22911b13d190SFrançois Tigeot { 22921b13d190SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 22931b13d190SFrançois Tigeot struct i915_address_space *vm = &dev_priv->gtt.base; 22941b13d190SFrançois Tigeot 22951b13d190SFrançois Tigeot if (dev_priv->mm.aliasing_ppgtt) { 22961b13d190SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; 22971b13d190SFrançois Tigeot 22981b13d190SFrançois Tigeot ppgtt->base.cleanup(&ppgtt->base); 22991b13d190SFrançois Tigeot } 23001b13d190SFrançois Tigeot 23011b13d190SFrançois Tigeot if (drm_mm_initialized(&vm->mm)) { 2302477eb7f9SFrançois Tigeot if (intel_vgpu_active(dev)) 2303477eb7f9SFrançois Tigeot intel_vgt_deballoon(); 2304477eb7f9SFrançois Tigeot 23051b13d190SFrançois Tigeot drm_mm_takedown(&vm->mm); 23061b13d190SFrançois Tigeot list_del(&vm->global_link); 23071b13d190SFrançois Tigeot } 23081b13d190SFrançois Tigeot 23091b13d190SFrançois Tigeot vm->cleanup(vm); 23101b13d190SFrançois Tigeot } 23111b13d190SFrançois Tigeot 231219c468b4SFrançois Tigeot static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) 23139edbd4a0SFrançois Tigeot { 23149edbd4a0SFrançois Tigeot snb_gmch_ctl >>= SNB_GMCH_GGMS_SHIFT; 23159edbd4a0SFrançois Tigeot snb_gmch_ctl &= SNB_GMCH_GGMS_MASK; 23169edbd4a0SFrançois Tigeot return snb_gmch_ctl << 20; 23179edbd4a0SFrançois Tigeot } 23189edbd4a0SFrançois Tigeot 231919c468b4SFrançois Tigeot static unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl) 23209edbd4a0SFrançois Tigeot { 23219edbd4a0SFrançois Tigeot bdw_gmch_ctl >>= BDW_GMCH_GGMS_SHIFT; 23229edbd4a0SFrançois Tigeot bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK; 23239edbd4a0SFrançois Tigeot if (bdw_gmch_ctl) 23249edbd4a0SFrançois Tigeot bdw_gmch_ctl = 1 << bdw_gmch_ctl; 2325ba55f2f5SFrançois Tigeot 2326ba55f2f5SFrançois Tigeot #ifdef CONFIG_X86_32 2327ba55f2f5SFrançois Tigeot /* Limit 32b platforms to a 2GB GGTT: 4 << 20 / pte size * PAGE_SIZE */ 2328ba55f2f5SFrançois Tigeot if (bdw_gmch_ctl > 4) 2329ba55f2f5SFrançois Tigeot bdw_gmch_ctl = 4; 2330ba55f2f5SFrançois Tigeot #endif 23319edbd4a0SFrançois Tigeot 23329edbd4a0SFrançois Tigeot return bdw_gmch_ctl << 20; 23339edbd4a0SFrançois Tigeot } 23349edbd4a0SFrançois Tigeot 233519c468b4SFrançois Tigeot static unsigned int chv_get_total_gtt_size(u16 gmch_ctrl) 2336ba55f2f5SFrançois Tigeot { 2337ba55f2f5SFrançois Tigeot gmch_ctrl >>= SNB_GMCH_GGMS_SHIFT; 2338ba55f2f5SFrançois Tigeot gmch_ctrl &= SNB_GMCH_GGMS_MASK; 2339ba55f2f5SFrançois Tigeot 2340ba55f2f5SFrançois Tigeot if (gmch_ctrl) 2341ba55f2f5SFrançois Tigeot return 1 << (20 + gmch_ctrl); 2342ba55f2f5SFrançois Tigeot 2343ba55f2f5SFrançois Tigeot return 0; 2344ba55f2f5SFrançois Tigeot } 2345ba55f2f5SFrançois Tigeot 234619c468b4SFrançois Tigeot static size_t gen6_get_stolen_size(u16 snb_gmch_ctl) 23479edbd4a0SFrançois Tigeot { 23489edbd4a0SFrançois Tigeot snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT; 23499edbd4a0SFrançois Tigeot snb_gmch_ctl &= SNB_GMCH_GMS_MASK; 23509edbd4a0SFrançois Tigeot return snb_gmch_ctl << 25; /* 32 MB units */ 23519edbd4a0SFrançois Tigeot } 23529edbd4a0SFrançois Tigeot 235319c468b4SFrançois Tigeot static size_t gen8_get_stolen_size(u16 bdw_gmch_ctl) 23549edbd4a0SFrançois Tigeot { 23559edbd4a0SFrançois Tigeot bdw_gmch_ctl >>= BDW_GMCH_GMS_SHIFT; 23569edbd4a0SFrançois Tigeot bdw_gmch_ctl &= BDW_GMCH_GMS_MASK; 23579edbd4a0SFrançois Tigeot return bdw_gmch_ctl << 25; /* 32 MB units */ 23589edbd4a0SFrançois Tigeot } 23599edbd4a0SFrançois Tigeot 2360ba55f2f5SFrançois Tigeot static size_t chv_get_stolen_size(u16 gmch_ctrl) 2361ba55f2f5SFrançois Tigeot { 2362ba55f2f5SFrançois Tigeot gmch_ctrl >>= SNB_GMCH_GMS_SHIFT; 2363ba55f2f5SFrançois Tigeot gmch_ctrl &= SNB_GMCH_GMS_MASK; 2364ba55f2f5SFrançois Tigeot 2365ba55f2f5SFrançois Tigeot /* 2366ba55f2f5SFrançois Tigeot * 0x0 to 0x10: 32MB increments starting at 0MB 2367ba55f2f5SFrançois Tigeot * 0x11 to 0x16: 4MB increments starting at 8MB 2368ba55f2f5SFrançois Tigeot * 0x17 to 0x1d: 4MB increments start at 36MB 2369ba55f2f5SFrançois Tigeot */ 2370ba55f2f5SFrançois Tigeot if (gmch_ctrl < 0x11) 2371ba55f2f5SFrançois Tigeot return gmch_ctrl << 25; 2372ba55f2f5SFrançois Tigeot else if (gmch_ctrl < 0x17) 2373ba55f2f5SFrançois Tigeot return (gmch_ctrl - 0x11 + 2) << 22; 2374ba55f2f5SFrançois Tigeot else 2375ba55f2f5SFrançois Tigeot return (gmch_ctrl - 0x17 + 9) << 22; 2376ba55f2f5SFrançois Tigeot } 2377ba55f2f5SFrançois Tigeot 23782c9916cdSFrançois Tigeot static size_t gen9_get_stolen_size(u16 gen9_gmch_ctl) 23792c9916cdSFrançois Tigeot { 23802c9916cdSFrançois Tigeot gen9_gmch_ctl >>= BDW_GMCH_GMS_SHIFT; 23812c9916cdSFrançois Tigeot gen9_gmch_ctl &= BDW_GMCH_GMS_MASK; 23822c9916cdSFrançois Tigeot 23832c9916cdSFrançois Tigeot if (gen9_gmch_ctl < 0xf0) 23842c9916cdSFrançois Tigeot return gen9_gmch_ctl << 25; /* 32 MB units */ 23852c9916cdSFrançois Tigeot else 23862c9916cdSFrançois Tigeot /* 4MB increments starting at 0xf0 for 4MB */ 23872c9916cdSFrançois Tigeot return (gen9_gmch_ctl - 0xf0 + 1) << 22; 23882c9916cdSFrançois Tigeot } 23892c9916cdSFrançois Tigeot 23909edbd4a0SFrançois Tigeot static int ggtt_probe_common(struct drm_device *dev, 23919edbd4a0SFrançois Tigeot size_t gtt_size) 23929edbd4a0SFrançois Tigeot { 23939edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2394*a05eeebfSFrançois Tigeot struct i915_page_scratch *scratch_page; 23959edbd4a0SFrançois Tigeot phys_addr_t gtt_phys_addr; 23969edbd4a0SFrançois Tigeot 23979edbd4a0SFrançois Tigeot /* For Modern GENs the PTEs and register space are split in the BAR */ 23989edbd4a0SFrançois Tigeot gtt_phys_addr = pci_resource_start(dev->pdev, 0) + 23999edbd4a0SFrançois Tigeot (pci_resource_len(dev->pdev, 0) / 2); 24009edbd4a0SFrançois Tigeot 240119c468b4SFrançois Tigeot /* 240219c468b4SFrançois Tigeot * On BXT writes larger than 64 bit to the GTT pagetable range will be 240319c468b4SFrançois Tigeot * dropped. For WC mappings in general we have 64 byte burst writes 240419c468b4SFrançois Tigeot * when the WC buffer is flushed, so we can't use it, but have to 240519c468b4SFrançois Tigeot * resort to an uncached mapping. The WC issue is easily caught by the 240619c468b4SFrançois Tigeot * readback check when writing GTT PTE entries. 240719c468b4SFrançois Tigeot */ 240819c468b4SFrançois Tigeot if (IS_BROXTON(dev)) 240919c468b4SFrançois Tigeot dev_priv->gtt.gsm = ioremap_nocache(gtt_phys_addr, gtt_size); 241019c468b4SFrançois Tigeot else 24119edbd4a0SFrançois Tigeot dev_priv->gtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size); 24129edbd4a0SFrançois Tigeot if (!dev_priv->gtt.gsm) { 24139edbd4a0SFrançois Tigeot DRM_ERROR("Failed to map the gtt page table\n"); 24149edbd4a0SFrançois Tigeot return -ENOMEM; 24159edbd4a0SFrançois Tigeot } 24169edbd4a0SFrançois Tigeot 2417*a05eeebfSFrançois Tigeot scratch_page = alloc_scratch_page(dev); 2418*a05eeebfSFrançois Tigeot if (IS_ERR(scratch_page)) { 24199edbd4a0SFrançois Tigeot DRM_ERROR("Scratch setup failed\n"); 24209edbd4a0SFrançois Tigeot /* iounmap will also get called at remove, but meh */ 24219edbd4a0SFrançois Tigeot iounmap(dev_priv->gtt.gsm); 2422*a05eeebfSFrançois Tigeot return PTR_ERR(scratch_page); 24239edbd4a0SFrançois Tigeot } 24249edbd4a0SFrançois Tigeot 2425*a05eeebfSFrançois Tigeot dev_priv->gtt.base.scratch_page = scratch_page; 2426*a05eeebfSFrançois Tigeot 2427*a05eeebfSFrançois Tigeot return 0; 24289edbd4a0SFrançois Tigeot } 24299edbd4a0SFrançois Tigeot 24309edbd4a0SFrançois Tigeot /* The GGTT and PPGTT need a private PPAT setup in order to handle cacheability 24319edbd4a0SFrançois Tigeot * bits. When using advanced contexts each context stores its own PAT, but 24329edbd4a0SFrançois Tigeot * writing this data shouldn't be harmful even in those cases. */ 2433ba55f2f5SFrançois Tigeot static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv) 24349edbd4a0SFrançois Tigeot { 24359edbd4a0SFrançois Tigeot uint64_t pat; 24369edbd4a0SFrançois Tigeot 24379edbd4a0SFrançois Tigeot pat = GEN8_PPAT(0, GEN8_PPAT_WB | GEN8_PPAT_LLC) | /* for normal objects, no eLLC */ 24389edbd4a0SFrançois Tigeot GEN8_PPAT(1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC) | /* for something pointing to ptes? */ 24399edbd4a0SFrançois Tigeot GEN8_PPAT(2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC) | /* for scanout with eLLC */ 24409edbd4a0SFrançois Tigeot GEN8_PPAT(3, GEN8_PPAT_UC) | /* Uncached objects, mostly for scanout */ 24419edbd4a0SFrançois Tigeot GEN8_PPAT(4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)) | 24429edbd4a0SFrançois Tigeot GEN8_PPAT(5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)) | 24439edbd4a0SFrançois Tigeot GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) | 24449edbd4a0SFrançois Tigeot GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); 24459edbd4a0SFrançois Tigeot 2446a6e033d9SFrançois Tigeot if (!USES_PPGTT(dev_priv->dev)) 2447a6e033d9SFrançois Tigeot /* Spec: "For GGTT, there is NO pat_sel[2:0] from the entry, 2448a6e033d9SFrançois Tigeot * so RTL will always use the value corresponding to 2449a6e033d9SFrançois Tigeot * pat_sel = 000". 2450a6e033d9SFrançois Tigeot * So let's disable cache for GGTT to avoid screen corruptions. 2451a6e033d9SFrançois Tigeot * MOCS still can be used though. 2452a6e033d9SFrançois Tigeot * - System agent ggtt writes (i.e. cpu gtt mmaps) already work 2453a6e033d9SFrançois Tigeot * before this patch, i.e. the same uncached + snooping access 2454a6e033d9SFrançois Tigeot * like on gen6/7 seems to be in effect. 2455a6e033d9SFrançois Tigeot * - So this just fixes blitter/render access. Again it looks 2456a6e033d9SFrançois Tigeot * like it's not just uncached access, but uncached + snooping. 2457a6e033d9SFrançois Tigeot * So we can still hold onto all our assumptions wrt cpu 2458a6e033d9SFrançois Tigeot * clflushing on LLC machines. 2459a6e033d9SFrançois Tigeot */ 2460a6e033d9SFrançois Tigeot pat = GEN8_PPAT(0, GEN8_PPAT_UC); 2461a6e033d9SFrançois Tigeot 24629edbd4a0SFrançois Tigeot /* XXX: spec defines this as 2 distinct registers. It's unclear if a 64b 24639edbd4a0SFrançois Tigeot * write would work. */ 24649edbd4a0SFrançois Tigeot I915_WRITE(GEN8_PRIVATE_PAT, pat); 24659edbd4a0SFrançois Tigeot I915_WRITE(GEN8_PRIVATE_PAT + 4, pat >> 32); 24669edbd4a0SFrançois Tigeot } 24679edbd4a0SFrançois Tigeot 2468ba55f2f5SFrançois Tigeot static void chv_setup_private_ppat(struct drm_i915_private *dev_priv) 2469ba55f2f5SFrançois Tigeot { 2470ba55f2f5SFrançois Tigeot uint64_t pat; 2471ba55f2f5SFrançois Tigeot 2472ba55f2f5SFrançois Tigeot /* 2473ba55f2f5SFrançois Tigeot * Map WB on BDW to snooped on CHV. 2474ba55f2f5SFrançois Tigeot * 2475ba55f2f5SFrançois Tigeot * Only the snoop bit has meaning for CHV, the rest is 2476ba55f2f5SFrançois Tigeot * ignored. 2477ba55f2f5SFrançois Tigeot * 24782c9916cdSFrançois Tigeot * The hardware will never snoop for certain types of accesses: 24792c9916cdSFrançois Tigeot * - CPU GTT (GMADR->GGTT->no snoop->memory) 24802c9916cdSFrançois Tigeot * - PPGTT page tables 24812c9916cdSFrançois Tigeot * - some other special cycles 24822c9916cdSFrançois Tigeot * 24832c9916cdSFrançois Tigeot * As with BDW, we also need to consider the following for GT accesses: 24842c9916cdSFrançois Tigeot * "For GGTT, there is NO pat_sel[2:0] from the entry, 24852c9916cdSFrançois Tigeot * so RTL will always use the value corresponding to 24862c9916cdSFrançois Tigeot * pat_sel = 000". 24872c9916cdSFrançois Tigeot * Which means we must set the snoop bit in PAT entry 0 24882c9916cdSFrançois Tigeot * in order to keep the global status page working. 2489ba55f2f5SFrançois Tigeot */ 2490ba55f2f5SFrançois Tigeot pat = GEN8_PPAT(0, CHV_PPAT_SNOOP) | 2491ba55f2f5SFrançois Tigeot GEN8_PPAT(1, 0) | 2492ba55f2f5SFrançois Tigeot GEN8_PPAT(2, 0) | 2493ba55f2f5SFrançois Tigeot GEN8_PPAT(3, 0) | 2494ba55f2f5SFrançois Tigeot GEN8_PPAT(4, CHV_PPAT_SNOOP) | 2495ba55f2f5SFrançois Tigeot GEN8_PPAT(5, CHV_PPAT_SNOOP) | 2496ba55f2f5SFrançois Tigeot GEN8_PPAT(6, CHV_PPAT_SNOOP) | 2497ba55f2f5SFrançois Tigeot GEN8_PPAT(7, CHV_PPAT_SNOOP); 2498ba55f2f5SFrançois Tigeot 2499ba55f2f5SFrançois Tigeot I915_WRITE(GEN8_PRIVATE_PAT, pat); 2500ba55f2f5SFrançois Tigeot I915_WRITE(GEN8_PRIVATE_PAT + 4, pat >> 32); 2501ba55f2f5SFrançois Tigeot } 2502ba55f2f5SFrançois Tigeot 25039edbd4a0SFrançois Tigeot static int gen8_gmch_probe(struct drm_device *dev, 2504*a05eeebfSFrançois Tigeot u64 *gtt_total, 25059edbd4a0SFrançois Tigeot size_t *stolen, 25069edbd4a0SFrançois Tigeot phys_addr_t *mappable_base, 2507*a05eeebfSFrançois Tigeot u64 *mappable_end) 25089edbd4a0SFrançois Tigeot { 25099edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2510*a05eeebfSFrançois Tigeot u64 gtt_size; 25119edbd4a0SFrançois Tigeot u16 snb_gmch_ctl; 25129edbd4a0SFrançois Tigeot int ret; 25139edbd4a0SFrançois Tigeot 25149edbd4a0SFrançois Tigeot /* TODO: We're not aware of mappable constraints on gen8 yet */ 25159edbd4a0SFrançois Tigeot *mappable_base = pci_resource_start(dev->pdev, 2); 25169edbd4a0SFrançois Tigeot *mappable_end = pci_resource_len(dev->pdev, 2); 25179edbd4a0SFrançois Tigeot 25189edbd4a0SFrançois Tigeot #if 0 25199edbd4a0SFrançois Tigeot if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(39))) 25209edbd4a0SFrançois Tigeot pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(39)); 25219edbd4a0SFrançois Tigeot #endif 25229edbd4a0SFrançois Tigeot 25239edbd4a0SFrançois Tigeot pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); 25249edbd4a0SFrançois Tigeot 25252c9916cdSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 9) { 25262c9916cdSFrançois Tigeot *stolen = gen9_get_stolen_size(snb_gmch_ctl); 25272c9916cdSFrançois Tigeot gtt_size = gen8_get_total_gtt_size(snb_gmch_ctl); 25282c9916cdSFrançois Tigeot } else if (IS_CHERRYVIEW(dev)) { 2529ba55f2f5SFrançois Tigeot *stolen = chv_get_stolen_size(snb_gmch_ctl); 2530ba55f2f5SFrançois Tigeot gtt_size = chv_get_total_gtt_size(snb_gmch_ctl); 2531ba55f2f5SFrançois Tigeot } else { 25329edbd4a0SFrançois Tigeot *stolen = gen8_get_stolen_size(snb_gmch_ctl); 25339edbd4a0SFrançois Tigeot gtt_size = gen8_get_total_gtt_size(snb_gmch_ctl); 2534ba55f2f5SFrançois Tigeot } 2535ba55f2f5SFrançois Tigeot 2536477eb7f9SFrançois Tigeot *gtt_total = (gtt_size / sizeof(gen8_pte_t)) << PAGE_SHIFT; 25379edbd4a0SFrançois Tigeot 253819c468b4SFrançois Tigeot if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) 2539ba55f2f5SFrançois Tigeot chv_setup_private_ppat(dev_priv); 2540ba55f2f5SFrançois Tigeot else 2541ba55f2f5SFrançois Tigeot bdw_setup_private_ppat(dev_priv); 25429edbd4a0SFrançois Tigeot 25439edbd4a0SFrançois Tigeot ret = ggtt_probe_common(dev, gtt_size); 25449edbd4a0SFrançois Tigeot 25459edbd4a0SFrançois Tigeot dev_priv->gtt.base.clear_range = gen8_ggtt_clear_range; 25469edbd4a0SFrançois Tigeot dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries; 254719c468b4SFrançois Tigeot dev_priv->gtt.base.bind_vma = ggtt_bind_vma; 254819c468b4SFrançois Tigeot dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; 25499edbd4a0SFrançois Tigeot 25509edbd4a0SFrançois Tigeot return ret; 25519edbd4a0SFrançois Tigeot } 25529edbd4a0SFrançois Tigeot 25535d0b1887SFrançois Tigeot static int gen6_gmch_probe(struct drm_device *dev, 2554*a05eeebfSFrançois Tigeot u64 *gtt_total, 25555d0b1887SFrançois Tigeot size_t *stolen, 25565d0b1887SFrançois Tigeot phys_addr_t *mappable_base, 2557*a05eeebfSFrançois Tigeot u64 *mappable_end) 25585d0b1887SFrançois Tigeot { 25595d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 25605d0b1887SFrançois Tigeot unsigned int gtt_size; 25615d0b1887SFrançois Tigeot u16 snb_gmch_ctl; 25625d0b1887SFrançois Tigeot int ret; 25635d0b1887SFrançois Tigeot 25645d0b1887SFrançois Tigeot *mappable_base = pci_resource_start(dev->pdev, 2); 25655d0b1887SFrançois Tigeot *mappable_end = pci_resource_len(dev->pdev, 2); 25665d0b1887SFrançois Tigeot 25675d0b1887SFrançois Tigeot /* 64/512MB is the current min/max we actually know of, but this is just 25685d0b1887SFrançois Tigeot * a coarse sanity check. 25695d0b1887SFrançois Tigeot */ 25705d0b1887SFrançois Tigeot if ((*mappable_end < (64<<20) || (*mappable_end > (512<<20)))) { 25715d0b1887SFrançois Tigeot DRM_ERROR("Unknown GMADR size (%lx)\n", 25725d0b1887SFrançois Tigeot dev_priv->gtt.mappable_end); 25735d0b1887SFrançois Tigeot return -ENXIO; 25745d0b1887SFrançois Tigeot } 25755d0b1887SFrançois Tigeot 25769edbd4a0SFrançois Tigeot #if 0 25775d0b1887SFrançois Tigeot if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(40))) 25785d0b1887SFrançois Tigeot pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40)); 25799edbd4a0SFrançois Tigeot #endif 25805d0b1887SFrançois Tigeot pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); 25815d0b1887SFrançois Tigeot 25825d0b1887SFrançois Tigeot *stolen = gen6_get_stolen_size(snb_gmch_ctl); 25835d0b1887SFrançois Tigeot 25849edbd4a0SFrançois Tigeot gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); 2585477eb7f9SFrançois Tigeot *gtt_total = (gtt_size / sizeof(gen6_pte_t)) << PAGE_SHIFT; 25865d0b1887SFrançois Tigeot 25879edbd4a0SFrançois Tigeot ret = ggtt_probe_common(dev, gtt_size); 25885d0b1887SFrançois Tigeot 25899edbd4a0SFrançois Tigeot dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range; 25909edbd4a0SFrançois Tigeot dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries; 259119c468b4SFrançois Tigeot dev_priv->gtt.base.bind_vma = ggtt_bind_vma; 259219c468b4SFrançois Tigeot dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; 25939edbd4a0SFrançois Tigeot 25949edbd4a0SFrançois Tigeot return ret; 25955d0b1887SFrançois Tigeot } 25965d0b1887SFrançois Tigeot 25979edbd4a0SFrançois Tigeot static void gen6_gmch_remove(struct i915_address_space *vm) 25985d0b1887SFrançois Tigeot { 25999edbd4a0SFrançois Tigeot struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base); 26009edbd4a0SFrançois Tigeot 26019edbd4a0SFrançois Tigeot iounmap(gtt->gsm); 2602*a05eeebfSFrançois Tigeot free_scratch_page(vm->dev, vm->scratch_page); 26039edbd4a0SFrançois Tigeot } 26045d0b1887SFrançois Tigeot 26055d0b1887SFrançois Tigeot static int i915_gmch_probe(struct drm_device *dev, 2606*a05eeebfSFrançois Tigeot u64 *gtt_total, 26075d0b1887SFrançois Tigeot size_t *stolen, 26085d0b1887SFrançois Tigeot phys_addr_t *mappable_base, 2609*a05eeebfSFrançois Tigeot u64 *mappable_end) 26105d0b1887SFrançois Tigeot { 26119edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 26129edbd4a0SFrançois Tigeot #if 0 26139edbd4a0SFrançois Tigeot int ret; 26149edbd4a0SFrançois Tigeot 26159edbd4a0SFrançois Tigeot ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->dev->pdev, NULL); 26169edbd4a0SFrançois Tigeot if (!ret) { 26179edbd4a0SFrançois Tigeot DRM_ERROR("failed to set up gmch\n"); 26189edbd4a0SFrançois Tigeot return -EIO; 26199edbd4a0SFrançois Tigeot } 26209edbd4a0SFrançois Tigeot #endif 26219edbd4a0SFrançois Tigeot 26229edbd4a0SFrançois Tigeot intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end); 26239edbd4a0SFrançois Tigeot 26249edbd4a0SFrançois Tigeot dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev); 26257ec9f8e5SFrançois Tigeot dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries; 26269edbd4a0SFrançois Tigeot dev_priv->gtt.base.clear_range = i915_ggtt_clear_range; 26277ec9f8e5SFrançois Tigeot dev_priv->gtt.base.bind_vma = ggtt_bind_vma; 26287ec9f8e5SFrançois Tigeot dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; 26299edbd4a0SFrançois Tigeot 26309edbd4a0SFrançois Tigeot if (unlikely(dev_priv->gtt.do_idle_maps)) 26319edbd4a0SFrançois Tigeot DRM_INFO("applying Ironlake quirks for intel_iommu\n"); 26329edbd4a0SFrançois Tigeot 26335d0b1887SFrançois Tigeot return 0; 26345d0b1887SFrançois Tigeot } 26355d0b1887SFrançois Tigeot 26369edbd4a0SFrançois Tigeot static void i915_gmch_remove(struct i915_address_space *vm) 26375d0b1887SFrançois Tigeot { 263824edb884SFrançois Tigeot intel_gmch_remove(); 26395d0b1887SFrançois Tigeot } 26405d0b1887SFrançois Tigeot 26410b869d8aSFrançois Tigeot int i915_gem_gtt_init(struct drm_device *dev) 26420b869d8aSFrançois Tigeot { 26430b869d8aSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 26449edbd4a0SFrançois Tigeot struct i915_gtt *gtt = &dev_priv->gtt; 26459edbd4a0SFrançois Tigeot int ret; 26460b869d8aSFrançois Tigeot 26479edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen <= 5) { 26489edbd4a0SFrançois Tigeot gtt->gtt_probe = i915_gmch_probe; 26499edbd4a0SFrançois Tigeot gtt->base.cleanup = i915_gmch_remove; 26509edbd4a0SFrançois Tigeot } else if (INTEL_INFO(dev)->gen < 8) { 26519edbd4a0SFrançois Tigeot gtt->gtt_probe = gen6_gmch_probe; 26529edbd4a0SFrançois Tigeot gtt->base.cleanup = gen6_gmch_remove; 26539edbd4a0SFrançois Tigeot if (IS_HASWELL(dev) && dev_priv->ellc_size) 26549edbd4a0SFrançois Tigeot gtt->base.pte_encode = iris_pte_encode; 26559edbd4a0SFrançois Tigeot else if (IS_HASWELL(dev)) 26569edbd4a0SFrançois Tigeot gtt->base.pte_encode = hsw_pte_encode; 26579edbd4a0SFrançois Tigeot else if (IS_VALLEYVIEW(dev)) 26589edbd4a0SFrançois Tigeot gtt->base.pte_encode = byt_pte_encode; 26599edbd4a0SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 7) 26609edbd4a0SFrançois Tigeot gtt->base.pte_encode = ivb_pte_encode; 26619edbd4a0SFrançois Tigeot else 26629edbd4a0SFrançois Tigeot gtt->base.pte_encode = snb_pte_encode; 26635d0b1887SFrançois Tigeot } else { 26649edbd4a0SFrançois Tigeot dev_priv->gtt.gtt_probe = gen8_gmch_probe; 26659edbd4a0SFrançois Tigeot dev_priv->gtt.base.cleanup = gen6_gmch_remove; 26665d0b1887SFrançois Tigeot } 2667a2fdbec6SFrançois Tigeot 2668*a05eeebfSFrançois Tigeot gtt->base.dev = dev; 2669*a05eeebfSFrançois Tigeot 26709edbd4a0SFrançois Tigeot ret = gtt->gtt_probe(dev, >t->base.total, >t->stolen_size, 26719edbd4a0SFrançois Tigeot >t->mappable_base, >t->mappable_end); 26729edbd4a0SFrançois Tigeot if (ret) 26739edbd4a0SFrançois Tigeot return ret; 26740b869d8aSFrançois Tigeot 26755d0b1887SFrançois Tigeot /* GMADR is the PCI mmio aperture into the global GTT. */ 2676*a05eeebfSFrançois Tigeot DRM_INFO("Memory usable by graphics device = %luM\n", 26779edbd4a0SFrançois Tigeot gtt->base.total >> 20); 26789edbd4a0SFrançois Tigeot DRM_DEBUG_DRIVER("GMADR size = %ldM\n", gtt->mappable_end >> 20); 26799edbd4a0SFrançois Tigeot DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20); 2680ba55f2f5SFrançois Tigeot #ifdef CONFIG_INTEL_IOMMU 2681ba55f2f5SFrançois Tigeot if (intel_iommu_gfx_mapped) 2682ba55f2f5SFrançois Tigeot DRM_INFO("VT-d active for gfx access\n"); 2683ba55f2f5SFrançois Tigeot #endif 268424edb884SFrançois Tigeot /* 268524edb884SFrançois Tigeot * i915.enable_ppgtt is read-only, so do an early pass to validate the 268624edb884SFrançois Tigeot * user's requested state against the hardware/driver capabilities. We 268724edb884SFrançois Tigeot * do this now so that we can print out any log messages once rather 268824edb884SFrançois Tigeot * than every time we check intel_enable_ppgtt(). 268924edb884SFrançois Tigeot */ 269024edb884SFrançois Tigeot i915.enable_ppgtt = sanitize_enable_ppgtt(dev, i915.enable_ppgtt); 269124edb884SFrançois Tigeot DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915.enable_ppgtt); 2692a2fdbec6SFrançois Tigeot 26930b869d8aSFrançois Tigeot return 0; 26940b869d8aSFrançois Tigeot } 2695ba55f2f5SFrançois Tigeot 269619c468b4SFrançois Tigeot void i915_gem_restore_gtt_mappings(struct drm_device *dev) 269719c468b4SFrançois Tigeot { 269819c468b4SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 269919c468b4SFrançois Tigeot struct drm_i915_gem_object *obj; 270019c468b4SFrançois Tigeot struct i915_address_space *vm; 270119c468b4SFrançois Tigeot 270219c468b4SFrançois Tigeot i915_check_and_clear_faults(dev); 270319c468b4SFrançois Tigeot 270419c468b4SFrançois Tigeot /* First fill our portion of the GTT with scratch pages */ 270519c468b4SFrançois Tigeot dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, 270619c468b4SFrançois Tigeot dev_priv->gtt.base.start, 270719c468b4SFrançois Tigeot dev_priv->gtt.base.total, 270819c468b4SFrançois Tigeot true); 270919c468b4SFrançois Tigeot 271019c468b4SFrançois Tigeot list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { 2711*a05eeebfSFrançois Tigeot struct i915_vma *vma = i915_gem_obj_to_vma(obj, 2712*a05eeebfSFrançois Tigeot &dev_priv->gtt.base); 2713*a05eeebfSFrançois Tigeot if (!vma) 271419c468b4SFrançois Tigeot continue; 271519c468b4SFrançois Tigeot 271619c468b4SFrançois Tigeot i915_gem_clflush_object(obj, obj->pin_display); 2717*a05eeebfSFrançois Tigeot WARN_ON(i915_vma_bind(vma, obj->cache_level, PIN_UPDATE)); 271819c468b4SFrançois Tigeot } 271919c468b4SFrançois Tigeot 2720*a05eeebfSFrançois Tigeot 272119c468b4SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 272219c468b4SFrançois Tigeot if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) 272319c468b4SFrançois Tigeot chv_setup_private_ppat(dev_priv); 272419c468b4SFrançois Tigeot else 272519c468b4SFrançois Tigeot bdw_setup_private_ppat(dev_priv); 272619c468b4SFrançois Tigeot 272719c468b4SFrançois Tigeot return; 272819c468b4SFrançois Tigeot } 272919c468b4SFrançois Tigeot 273019c468b4SFrançois Tigeot if (USES_PPGTT(dev)) { 273119c468b4SFrançois Tigeot list_for_each_entry(vm, &dev_priv->vm_list, global_link) { 273219c468b4SFrançois Tigeot /* TODO: Perhaps it shouldn't be gen6 specific */ 273319c468b4SFrançois Tigeot 273419c468b4SFrançois Tigeot struct i915_hw_ppgtt *ppgtt = 273519c468b4SFrançois Tigeot container_of(vm, struct i915_hw_ppgtt, 273619c468b4SFrançois Tigeot base); 273719c468b4SFrançois Tigeot 273819c468b4SFrançois Tigeot if (i915_is_ggtt(vm)) 273919c468b4SFrançois Tigeot ppgtt = dev_priv->mm.aliasing_ppgtt; 274019c468b4SFrançois Tigeot 274119c468b4SFrançois Tigeot gen6_write_page_range(dev_priv, &ppgtt->pd, 274219c468b4SFrançois Tigeot 0, ppgtt->base.total); 274319c468b4SFrançois Tigeot } 274419c468b4SFrançois Tigeot } 274519c468b4SFrançois Tigeot 274619c468b4SFrançois Tigeot i915_ggtt_flush(dev_priv); 274719c468b4SFrançois Tigeot } 274819c468b4SFrançois Tigeot 2749477eb7f9SFrançois Tigeot static struct i915_vma * 2750477eb7f9SFrançois Tigeot __i915_gem_vma_create(struct drm_i915_gem_object *obj, 27512c9916cdSFrançois Tigeot struct i915_address_space *vm, 2752477eb7f9SFrançois Tigeot const struct i915_ggtt_view *ggtt_view) 2753ba55f2f5SFrançois Tigeot { 2754477eb7f9SFrançois Tigeot struct i915_vma *vma; 2755477eb7f9SFrançois Tigeot 2756477eb7f9SFrançois Tigeot if (WARN_ON(i915_is_ggtt(vm) != !!ggtt_view)) 2757477eb7f9SFrançois Tigeot return ERR_PTR(-EINVAL); 27587ec9f8e5SFrançois Tigeot 2759477eb7f9SFrançois Tigeot vma = kzalloc(sizeof(*vma), GFP_KERNEL); 2760ba55f2f5SFrançois Tigeot if (vma == NULL) 2761ba55f2f5SFrançois Tigeot return ERR_PTR(-ENOMEM); 2762ba55f2f5SFrançois Tigeot 2763ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&vma->vma_link); 2764ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&vma->mm_list); 2765ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&vma->exec_list); 2766ba55f2f5SFrançois Tigeot vma->vm = vm; 2767ba55f2f5SFrançois Tigeot vma->obj = obj; 2768ba55f2f5SFrançois Tigeot 276919c468b4SFrançois Tigeot if (i915_is_ggtt(vm)) 2770477eb7f9SFrançois Tigeot vma->ggtt_view = *ggtt_view; 2771477eb7f9SFrançois Tigeot 2772ba55f2f5SFrançois Tigeot list_add_tail(&vma->vma_link, &obj->vma_list); 27732c9916cdSFrançois Tigeot if (!i915_is_ggtt(vm)) 27741b13d190SFrançois Tigeot i915_ppgtt_get(i915_vm_to_ppgtt(vm)); 2775ba55f2f5SFrançois Tigeot 2776ba55f2f5SFrançois Tigeot return vma; 2777ba55f2f5SFrançois Tigeot } 2778ba55f2f5SFrançois Tigeot 2779ba55f2f5SFrançois Tigeot struct i915_vma * 2780477eb7f9SFrançois Tigeot i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj, 2781477eb7f9SFrançois Tigeot struct i915_address_space *vm) 2782ba55f2f5SFrançois Tigeot { 2783ba55f2f5SFrançois Tigeot struct i915_vma *vma; 2784ba55f2f5SFrançois Tigeot 2785477eb7f9SFrançois Tigeot vma = i915_gem_obj_to_vma(obj, vm); 2786ba55f2f5SFrançois Tigeot if (!vma) 2787477eb7f9SFrançois Tigeot vma = __i915_gem_vma_create(obj, vm, 2788477eb7f9SFrançois Tigeot i915_is_ggtt(vm) ? &i915_ggtt_view_normal : NULL); 2789ba55f2f5SFrançois Tigeot 2790ba55f2f5SFrançois Tigeot return vma; 2791ba55f2f5SFrançois Tigeot } 27922c9916cdSFrançois Tigeot 2793477eb7f9SFrançois Tigeot struct i915_vma * 2794477eb7f9SFrançois Tigeot i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj, 2795477eb7f9SFrançois Tigeot const struct i915_ggtt_view *view) 27962c9916cdSFrançois Tigeot { 2797477eb7f9SFrançois Tigeot struct i915_address_space *ggtt = i915_obj_to_ggtt(obj); 2798477eb7f9SFrançois Tigeot struct i915_vma *vma; 2799477eb7f9SFrançois Tigeot 2800477eb7f9SFrançois Tigeot if (WARN_ON(!view)) 2801477eb7f9SFrançois Tigeot return ERR_PTR(-EINVAL); 2802477eb7f9SFrançois Tigeot 2803477eb7f9SFrançois Tigeot vma = i915_gem_obj_to_ggtt_view(obj, view); 2804477eb7f9SFrançois Tigeot 2805477eb7f9SFrançois Tigeot if (IS_ERR(vma)) 2806477eb7f9SFrançois Tigeot return vma; 2807477eb7f9SFrançois Tigeot 2808477eb7f9SFrançois Tigeot if (!vma) 2809477eb7f9SFrançois Tigeot vma = __i915_gem_vma_create(obj, ggtt, view); 2810477eb7f9SFrançois Tigeot 2811477eb7f9SFrançois Tigeot return vma; 2812477eb7f9SFrançois Tigeot 2813477eb7f9SFrançois Tigeot } 2814477eb7f9SFrançois Tigeot 2815477eb7f9SFrançois Tigeot static void 2816477eb7f9SFrançois Tigeot rotate_pages(dma_addr_t *in, unsigned int width, unsigned int height, 2817477eb7f9SFrançois Tigeot struct sg_table *st) 2818477eb7f9SFrançois Tigeot { 2819477eb7f9SFrançois Tigeot unsigned int column, row; 2820477eb7f9SFrançois Tigeot unsigned int src_idx; 2821477eb7f9SFrançois Tigeot struct scatterlist *sg = st->sgl; 2822477eb7f9SFrançois Tigeot 2823477eb7f9SFrançois Tigeot st->nents = 0; 2824477eb7f9SFrançois Tigeot 2825477eb7f9SFrançois Tigeot for (column = 0; column < width; column++) { 2826477eb7f9SFrançois Tigeot src_idx = width * (height - 1) + column; 2827477eb7f9SFrançois Tigeot for (row = 0; row < height; row++) { 2828477eb7f9SFrançois Tigeot st->nents++; 2829477eb7f9SFrançois Tigeot /* We don't need the pages, but need to initialize 2830477eb7f9SFrançois Tigeot * the entries so the sg list can be happily traversed. 2831477eb7f9SFrançois Tigeot * The only thing we need are DMA addresses. 2832477eb7f9SFrançois Tigeot */ 2833477eb7f9SFrançois Tigeot sg_set_page(sg, NULL, PAGE_SIZE, 0); 2834477eb7f9SFrançois Tigeot sg_dma_address(sg) = in[src_idx]; 2835477eb7f9SFrançois Tigeot sg_dma_len(sg) = PAGE_SIZE; 2836477eb7f9SFrançois Tigeot sg = sg_next(sg); 2837477eb7f9SFrançois Tigeot src_idx -= width; 2838477eb7f9SFrançois Tigeot } 2839477eb7f9SFrançois Tigeot } 2840477eb7f9SFrançois Tigeot } 2841477eb7f9SFrançois Tigeot 2842477eb7f9SFrançois Tigeot static struct sg_table * 2843477eb7f9SFrançois Tigeot intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, 2844477eb7f9SFrançois Tigeot struct drm_i915_gem_object *obj) 2845477eb7f9SFrançois Tigeot { 2846477eb7f9SFrançois Tigeot struct intel_rotation_info *rot_info = &ggtt_view->rotation_info; 2847*a05eeebfSFrançois Tigeot unsigned int size_pages = rot_info->size >> PAGE_SHIFT; 2848477eb7f9SFrançois Tigeot struct sg_page_iter sg_iter; 2849477eb7f9SFrançois Tigeot unsigned long i; 2850477eb7f9SFrançois Tigeot dma_addr_t *page_addr_list; 2851477eb7f9SFrançois Tigeot struct sg_table *st; 2852477eb7f9SFrançois Tigeot int ret = -ENOMEM; 2853477eb7f9SFrançois Tigeot 2854477eb7f9SFrançois Tigeot /* Allocate a temporary list of source pages for random access. */ 2855*a05eeebfSFrançois Tigeot page_addr_list = drm_malloc_ab(obj->base.size / PAGE_SIZE, 2856*a05eeebfSFrançois Tigeot sizeof(dma_addr_t)); 2857477eb7f9SFrançois Tigeot if (!page_addr_list) 2858477eb7f9SFrançois Tigeot return ERR_PTR(ret); 2859477eb7f9SFrançois Tigeot 2860477eb7f9SFrançois Tigeot /* Allocate target SG list. */ 28617ec9f8e5SFrançois Tigeot st = kmalloc(sizeof(*st), M_DRM, M_WAITOK); 2862477eb7f9SFrançois Tigeot if (!st) 2863477eb7f9SFrançois Tigeot goto err_st_alloc; 2864477eb7f9SFrançois Tigeot 2865*a05eeebfSFrançois Tigeot ret = sg_alloc_table(st, size_pages, GFP_KERNEL); 2866477eb7f9SFrançois Tigeot if (ret) 2867477eb7f9SFrançois Tigeot goto err_sg_alloc; 2868477eb7f9SFrançois Tigeot 2869477eb7f9SFrançois Tigeot /* Populate source page list from the object. */ 2870477eb7f9SFrançois Tigeot i = 0; 2871477eb7f9SFrançois Tigeot for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) { 2872477eb7f9SFrançois Tigeot page_addr_list[i] = sg_page_iter_dma_address(&sg_iter); 2873477eb7f9SFrançois Tigeot i++; 2874477eb7f9SFrançois Tigeot } 2875477eb7f9SFrançois Tigeot 2876477eb7f9SFrançois Tigeot /* Rotate the pages. */ 2877*a05eeebfSFrançois Tigeot rotate_pages(page_addr_list, 2878*a05eeebfSFrançois Tigeot rot_info->width_pages, rot_info->height_pages, 2879*a05eeebfSFrançois Tigeot st); 2880477eb7f9SFrançois Tigeot 2881477eb7f9SFrançois Tigeot DRM_DEBUG_KMS( 2882*a05eeebfSFrançois Tigeot "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages).\n", 2883*a05eeebfSFrançois Tigeot obj->base.size, rot_info->pitch, rot_info->height, 2884*a05eeebfSFrançois Tigeot rot_info->pixel_format, rot_info->width_pages, 2885*a05eeebfSFrançois Tigeot rot_info->height_pages, size_pages); 2886477eb7f9SFrançois Tigeot 2887477eb7f9SFrançois Tigeot drm_free_large(page_addr_list); 2888477eb7f9SFrançois Tigeot 2889477eb7f9SFrançois Tigeot return st; 2890477eb7f9SFrançois Tigeot 2891477eb7f9SFrançois Tigeot err_sg_alloc: 2892477eb7f9SFrançois Tigeot kfree(st); 2893477eb7f9SFrançois Tigeot err_st_alloc: 2894477eb7f9SFrançois Tigeot drm_free_large(page_addr_list); 2895477eb7f9SFrançois Tigeot 2896477eb7f9SFrançois Tigeot DRM_DEBUG_KMS( 2897*a05eeebfSFrançois Tigeot "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages)\n", 2898*a05eeebfSFrançois Tigeot obj->base.size, ret, rot_info->pitch, rot_info->height, 2899*a05eeebfSFrançois Tigeot rot_info->pixel_format, rot_info->width_pages, 2900*a05eeebfSFrançois Tigeot rot_info->height_pages, size_pages); 2901477eb7f9SFrançois Tigeot return ERR_PTR(ret); 2902477eb7f9SFrançois Tigeot } 290319c468b4SFrançois Tigeot 290419c468b4SFrançois Tigeot static struct sg_table * 290519c468b4SFrançois Tigeot intel_partial_pages(const struct i915_ggtt_view *view, 290619c468b4SFrançois Tigeot struct drm_i915_gem_object *obj) 290719c468b4SFrançois Tigeot { 290819c468b4SFrançois Tigeot struct sg_table *st; 290919c468b4SFrançois Tigeot struct scatterlist *sg; 291019c468b4SFrançois Tigeot struct sg_page_iter obj_sg_iter; 291119c468b4SFrançois Tigeot int ret = -ENOMEM; 291219c468b4SFrançois Tigeot 29137ec9f8e5SFrançois Tigeot st = kmalloc(sizeof(*st), M_DRM, M_WAITOK); 291419c468b4SFrançois Tigeot if (!st) 291519c468b4SFrançois Tigeot goto err_st_alloc; 291619c468b4SFrançois Tigeot 291719c468b4SFrançois Tigeot ret = sg_alloc_table(st, view->params.partial.size, GFP_KERNEL); 291819c468b4SFrançois Tigeot if (ret) 291919c468b4SFrançois Tigeot goto err_sg_alloc; 292019c468b4SFrançois Tigeot 292119c468b4SFrançois Tigeot sg = st->sgl; 292219c468b4SFrançois Tigeot st->nents = 0; 292319c468b4SFrançois Tigeot for_each_sg_page(obj->pages->sgl, &obj_sg_iter, obj->pages->nents, 292419c468b4SFrançois Tigeot view->params.partial.offset) 292519c468b4SFrançois Tigeot { 292619c468b4SFrançois Tigeot if (st->nents >= view->params.partial.size) 292719c468b4SFrançois Tigeot break; 292819c468b4SFrançois Tigeot 292919c468b4SFrançois Tigeot sg_set_page(sg, NULL, PAGE_SIZE, 0); 293019c468b4SFrançois Tigeot sg_dma_address(sg) = sg_page_iter_dma_address(&obj_sg_iter); 293119c468b4SFrançois Tigeot sg_dma_len(sg) = PAGE_SIZE; 293219c468b4SFrançois Tigeot 293319c468b4SFrançois Tigeot sg = sg_next(sg); 293419c468b4SFrançois Tigeot st->nents++; 293519c468b4SFrançois Tigeot } 293619c468b4SFrançois Tigeot 293719c468b4SFrançois Tigeot return st; 293819c468b4SFrançois Tigeot 293919c468b4SFrançois Tigeot err_sg_alloc: 294019c468b4SFrançois Tigeot kfree(st); 294119c468b4SFrançois Tigeot err_st_alloc: 294219c468b4SFrançois Tigeot return ERR_PTR(ret); 294319c468b4SFrançois Tigeot } 2944477eb7f9SFrançois Tigeot 294519c468b4SFrançois Tigeot static int 2946477eb7f9SFrançois Tigeot i915_get_ggtt_vma_pages(struct i915_vma *vma) 2947477eb7f9SFrançois Tigeot { 2948477eb7f9SFrançois Tigeot int ret = 0; 2949477eb7f9SFrançois Tigeot 29502c9916cdSFrançois Tigeot if (vma->ggtt_view.pages) 29512c9916cdSFrançois Tigeot return 0; 29522c9916cdSFrançois Tigeot 29532c9916cdSFrançois Tigeot if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) 29542c9916cdSFrançois Tigeot vma->ggtt_view.pages = vma->obj->pages; 2955477eb7f9SFrançois Tigeot else if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED) 2956477eb7f9SFrançois Tigeot vma->ggtt_view.pages = 2957477eb7f9SFrançois Tigeot intel_rotate_fb_obj_pages(&vma->ggtt_view, vma->obj); 295819c468b4SFrançois Tigeot else if (vma->ggtt_view.type == I915_GGTT_VIEW_PARTIAL) 295919c468b4SFrançois Tigeot vma->ggtt_view.pages = 296019c468b4SFrançois Tigeot intel_partial_pages(&vma->ggtt_view, vma->obj); 29612c9916cdSFrançois Tigeot else 29622c9916cdSFrançois Tigeot WARN_ONCE(1, "GGTT view %u not implemented!\n", 29632c9916cdSFrançois Tigeot vma->ggtt_view.type); 29642c9916cdSFrançois Tigeot 29652c9916cdSFrançois Tigeot if (!vma->ggtt_view.pages) { 2966477eb7f9SFrançois Tigeot DRM_ERROR("Failed to get pages for GGTT view type %u!\n", 29672c9916cdSFrançois Tigeot vma->ggtt_view.type); 2968477eb7f9SFrançois Tigeot ret = -EINVAL; 2969477eb7f9SFrançois Tigeot } else if (IS_ERR(vma->ggtt_view.pages)) { 2970477eb7f9SFrançois Tigeot ret = PTR_ERR(vma->ggtt_view.pages); 2971477eb7f9SFrançois Tigeot vma->ggtt_view.pages = NULL; 2972477eb7f9SFrançois Tigeot DRM_ERROR("Failed to get pages for VMA view type %u (%d)!\n", 2973477eb7f9SFrançois Tigeot vma->ggtt_view.type, ret); 29742c9916cdSFrançois Tigeot } 29752c9916cdSFrançois Tigeot 2976477eb7f9SFrançois Tigeot return ret; 29772c9916cdSFrançois Tigeot } 29782c9916cdSFrançois Tigeot 29792c9916cdSFrançois Tigeot /** 29802c9916cdSFrançois Tigeot * i915_vma_bind - Sets up PTEs for an VMA in it's corresponding address space. 29812c9916cdSFrançois Tigeot * @vma: VMA to map 29822c9916cdSFrançois Tigeot * @cache_level: mapping cache level 29832c9916cdSFrançois Tigeot * @flags: flags like global or local mapping 29842c9916cdSFrançois Tigeot * 29852c9916cdSFrançois Tigeot * DMA addresses are taken from the scatter-gather table of this object (or of 29862c9916cdSFrançois Tigeot * this VMA in case of non-default GGTT views) and PTE entries set up. 29872c9916cdSFrançois Tigeot * Note that DMA addresses are also the only part of the SG table we care about. 29882c9916cdSFrançois Tigeot */ 29892c9916cdSFrançois Tigeot int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, 29902c9916cdSFrançois Tigeot u32 flags) 29912c9916cdSFrançois Tigeot { 299219c468b4SFrançois Tigeot int ret; 299319c468b4SFrançois Tigeot u32 bind_flags; 29942c9916cdSFrançois Tigeot 299519c468b4SFrançois Tigeot if (WARN_ON(flags == 0)) 299619c468b4SFrançois Tigeot return -EINVAL; 299719c468b4SFrançois Tigeot 299819c468b4SFrançois Tigeot bind_flags = 0; 299919c468b4SFrançois Tigeot if (flags & PIN_GLOBAL) 300019c468b4SFrançois Tigeot bind_flags |= GLOBAL_BIND; 300119c468b4SFrançois Tigeot if (flags & PIN_USER) 300219c468b4SFrançois Tigeot bind_flags |= LOCAL_BIND; 300319c468b4SFrançois Tigeot 300419c468b4SFrançois Tigeot if (flags & PIN_UPDATE) 300519c468b4SFrançois Tigeot bind_flags |= vma->bound; 300619c468b4SFrançois Tigeot else 300719c468b4SFrançois Tigeot bind_flags &= ~vma->bound; 300819c468b4SFrançois Tigeot 300919c468b4SFrançois Tigeot if (bind_flags == 0) 301019c468b4SFrançois Tigeot return 0; 301119c468b4SFrançois Tigeot 301219c468b4SFrançois Tigeot if (vma->bound == 0 && vma->vm->allocate_va_range) { 301319c468b4SFrançois Tigeot trace_i915_va_alloc(vma->vm, 301419c468b4SFrançois Tigeot vma->node.start, 301519c468b4SFrançois Tigeot vma->node.size, 301619c468b4SFrançois Tigeot VM_TO_TRACE_NAME(vma->vm)); 301719c468b4SFrançois Tigeot 3018*a05eeebfSFrançois Tigeot /* XXX: i915_vma_pin() will fix this +- hack */ 3019*a05eeebfSFrançois Tigeot vma->pin_count++; 302019c468b4SFrançois Tigeot ret = vma->vm->allocate_va_range(vma->vm, 302119c468b4SFrançois Tigeot vma->node.start, 302219c468b4SFrançois Tigeot vma->node.size); 3023*a05eeebfSFrançois Tigeot vma->pin_count--; 302419c468b4SFrançois Tigeot if (ret) 302519c468b4SFrançois Tigeot return ret; 302619c468b4SFrançois Tigeot } 302719c468b4SFrançois Tigeot 302819c468b4SFrançois Tigeot ret = vma->vm->bind_vma(vma, cache_level, bind_flags); 302919c468b4SFrançois Tigeot if (ret) 303019c468b4SFrançois Tigeot return ret; 303119c468b4SFrançois Tigeot 303219c468b4SFrançois Tigeot vma->bound |= bind_flags; 30332c9916cdSFrançois Tigeot 30342c9916cdSFrançois Tigeot return 0; 30352c9916cdSFrançois Tigeot } 303619c468b4SFrançois Tigeot 303719c468b4SFrançois Tigeot /** 303819c468b4SFrançois Tigeot * i915_ggtt_view_size - Get the size of a GGTT view. 303919c468b4SFrançois Tigeot * @obj: Object the view is of. 304019c468b4SFrançois Tigeot * @view: The view in question. 304119c468b4SFrançois Tigeot * 304219c468b4SFrançois Tigeot * @return The size of the GGTT view in bytes. 304319c468b4SFrançois Tigeot */ 304419c468b4SFrançois Tigeot size_t 304519c468b4SFrançois Tigeot i915_ggtt_view_size(struct drm_i915_gem_object *obj, 304619c468b4SFrançois Tigeot const struct i915_ggtt_view *view) 304719c468b4SFrançois Tigeot { 3048*a05eeebfSFrançois Tigeot if (view->type == I915_GGTT_VIEW_NORMAL) { 304919c468b4SFrançois Tigeot return obj->base.size; 3050*a05eeebfSFrançois Tigeot } else if (view->type == I915_GGTT_VIEW_ROTATED) { 3051*a05eeebfSFrançois Tigeot return view->rotation_info.size; 305219c468b4SFrançois Tigeot } else if (view->type == I915_GGTT_VIEW_PARTIAL) { 305319c468b4SFrançois Tigeot return view->params.partial.size << PAGE_SHIFT; 305419c468b4SFrançois Tigeot } else { 305519c468b4SFrançois Tigeot WARN_ONCE(1, "GGTT view %u not implemented!\n", view->type); 305619c468b4SFrançois Tigeot return obj->base.size; 305719c468b4SFrançois Tigeot } 305819c468b4SFrançois Tigeot } 3059