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