18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: MIT */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright © 2020 Intel Corporation 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Please try to maintain the following order within this file unless it makes 68c2ecf20Sopenharmony_ci * sense to do otherwise. From top to bottom: 78c2ecf20Sopenharmony_ci * 1. typedefs 88c2ecf20Sopenharmony_ci * 2. #defines, and macros 98c2ecf20Sopenharmony_ci * 3. structure definitions 108c2ecf20Sopenharmony_ci * 4. function prototypes 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Within each section, please try to order by generation in ascending order, 138c2ecf20Sopenharmony_ci * from top to bottom (ie. gen6 on the top, gen8 on the bottom). 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#ifndef __INTEL_GTT_H__ 178c2ecf20Sopenharmony_ci#define __INTEL_GTT_H__ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <linux/io-mapping.h> 208c2ecf20Sopenharmony_ci#include <linux/kref.h> 218c2ecf20Sopenharmony_ci#include <linux/mm.h> 228c2ecf20Sopenharmony_ci#include <linux/pagevec.h> 238c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 248c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <drm/drm_mm.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include "gt/intel_reset.h" 298c2ecf20Sopenharmony_ci#include "i915_selftest.h" 308c2ecf20Sopenharmony_ci#include "i915_vma_types.h" 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define I915_GFP_ALLOW_FAIL (GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_I915_TRACE_GTT) 358c2ecf20Sopenharmony_ci#define DBG(...) trace_printk(__VA_ARGS__) 368c2ecf20Sopenharmony_ci#else 378c2ecf20Sopenharmony_ci#define DBG(...) 388c2ecf20Sopenharmony_ci#endif 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define NALLOC 3 /* 1 normal, 1 for concurrent threads, 1 for preallocation */ 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define I915_GTT_PAGE_SIZE_4K BIT_ULL(12) 438c2ecf20Sopenharmony_ci#define I915_GTT_PAGE_SIZE_64K BIT_ULL(16) 448c2ecf20Sopenharmony_ci#define I915_GTT_PAGE_SIZE_2M BIT_ULL(21) 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define I915_GTT_PAGE_SIZE I915_GTT_PAGE_SIZE_4K 478c2ecf20Sopenharmony_ci#define I915_GTT_MAX_PAGE_SIZE I915_GTT_PAGE_SIZE_2M 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#define I915_GTT_PAGE_MASK -I915_GTT_PAGE_SIZE 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define I915_GTT_MIN_ALIGNMENT I915_GTT_PAGE_SIZE 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define I915_FENCE_REG_NONE -1 548c2ecf20Sopenharmony_ci#define I915_MAX_NUM_FENCES 32 558c2ecf20Sopenharmony_ci/* 32 fences + sign bit for FENCE_REG_NONE */ 568c2ecf20Sopenharmony_ci#define I915_MAX_NUM_FENCE_BITS 6 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_citypedef u32 gen6_pte_t; 598c2ecf20Sopenharmony_citypedef u64 gen8_pte_t; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define ggtt_total_entries(ggtt) ((ggtt)->vm.total >> PAGE_SHIFT) 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#define I915_PTES(pte_len) ((unsigned int)(PAGE_SIZE / (pte_len))) 648c2ecf20Sopenharmony_ci#define I915_PTE_MASK(pte_len) (I915_PTES(pte_len) - 1) 658c2ecf20Sopenharmony_ci#define I915_PDES 512 668c2ecf20Sopenharmony_ci#define I915_PDE_MASK (I915_PDES - 1) 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* gen6-hsw has bit 11-4 for physical addr bit 39-32 */ 698c2ecf20Sopenharmony_ci#define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0)) 708c2ecf20Sopenharmony_ci#define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) 718c2ecf20Sopenharmony_ci#define GEN6_PDE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) 728c2ecf20Sopenharmony_ci#define GEN6_PTE_CACHE_LLC (2 << 1) 738c2ecf20Sopenharmony_ci#define GEN6_PTE_UNCACHED (1 << 1) 748c2ecf20Sopenharmony_ci#define GEN6_PTE_VALID REG_BIT(0) 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#define GEN6_PTES I915_PTES(sizeof(gen6_pte_t)) 778c2ecf20Sopenharmony_ci#define GEN6_PD_SIZE (I915_PDES * PAGE_SIZE) 788c2ecf20Sopenharmony_ci#define GEN6_PD_ALIGN (PAGE_SIZE * 16) 798c2ecf20Sopenharmony_ci#define GEN6_PDE_SHIFT 22 808c2ecf20Sopenharmony_ci#define GEN6_PDE_VALID REG_BIT(0) 818c2ecf20Sopenharmony_ci#define NUM_PTE(pde_shift) (1 << (pde_shift - PAGE_SHIFT)) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define GEN7_PTE_CACHE_L3_LLC (3 << 1) 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#define BYT_PTE_SNOOPED_BY_CPU_CACHES REG_BIT(2) 868c2ecf20Sopenharmony_ci#define BYT_PTE_WRITEABLE REG_BIT(1) 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/* 898c2ecf20Sopenharmony_ci * Cacheability Control is a 4-bit value. The low three bits are stored in bits 908c2ecf20Sopenharmony_ci * 3:1 of the PTE, while the fourth bit is stored in bit 11 of the PTE. 918c2ecf20Sopenharmony_ci */ 928c2ecf20Sopenharmony_ci#define HSW_CACHEABILITY_CONTROL(bits) ((((bits) & 0x7) << 1) | \ 938c2ecf20Sopenharmony_ci (((bits) & 0x8) << (11 - 3))) 948c2ecf20Sopenharmony_ci#define HSW_WB_LLC_AGE3 HSW_CACHEABILITY_CONTROL(0x2) 958c2ecf20Sopenharmony_ci#define HSW_WB_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x3) 968c2ecf20Sopenharmony_ci#define HSW_WB_ELLC_LLC_AGE3 HSW_CACHEABILITY_CONTROL(0x8) 978c2ecf20Sopenharmony_ci#define HSW_WB_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0xb) 988c2ecf20Sopenharmony_ci#define HSW_WT_ELLC_LLC_AGE3 HSW_CACHEABILITY_CONTROL(0x7) 998c2ecf20Sopenharmony_ci#define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6) 1008c2ecf20Sopenharmony_ci#define HSW_PTE_UNCACHED (0) 1018c2ecf20Sopenharmony_ci#define HSW_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0x7f0)) 1028c2ecf20Sopenharmony_ci#define HSW_PTE_ADDR_ENCODE(addr) HSW_GTT_ADDR_ENCODE(addr) 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/* 1058c2ecf20Sopenharmony_ci * GEN8 32b style address is defined as a 3 level page table: 1068c2ecf20Sopenharmony_ci * 31:30 | 29:21 | 20:12 | 11:0 1078c2ecf20Sopenharmony_ci * PDPE | PDE | PTE | offset 1088c2ecf20Sopenharmony_ci * The difference as compared to normal x86 3 level page table is the PDPEs are 1098c2ecf20Sopenharmony_ci * programmed via register. 1108c2ecf20Sopenharmony_ci * 1118c2ecf20Sopenharmony_ci * GEN8 48b style address is defined as a 4 level page table: 1128c2ecf20Sopenharmony_ci * 47:39 | 38:30 | 29:21 | 20:12 | 11:0 1138c2ecf20Sopenharmony_ci * PML4E | PDPE | PDE | PTE | offset 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci#define GEN8_3LVL_PDPES 4 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci#define PPAT_UNCACHED (_PAGE_PWT | _PAGE_PCD) 1188c2ecf20Sopenharmony_ci#define PPAT_CACHED_PDE 0 /* WB LLC */ 1198c2ecf20Sopenharmony_ci#define PPAT_CACHED _PAGE_PAT /* WB LLCeLLC */ 1208c2ecf20Sopenharmony_ci#define PPAT_DISPLAY_ELLC _PAGE_PCD /* WT eLLC */ 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci#define CHV_PPAT_SNOOP REG_BIT(6) 1238c2ecf20Sopenharmony_ci#define GEN8_PPAT_AGE(x) ((x)<<4) 1248c2ecf20Sopenharmony_ci#define GEN8_PPAT_LLCeLLC (3<<2) 1258c2ecf20Sopenharmony_ci#define GEN8_PPAT_LLCELLC (2<<2) 1268c2ecf20Sopenharmony_ci#define GEN8_PPAT_LLC (1<<2) 1278c2ecf20Sopenharmony_ci#define GEN8_PPAT_WB (3<<0) 1288c2ecf20Sopenharmony_ci#define GEN8_PPAT_WT (2<<0) 1298c2ecf20Sopenharmony_ci#define GEN8_PPAT_WC (1<<0) 1308c2ecf20Sopenharmony_ci#define GEN8_PPAT_UC (0<<0) 1318c2ecf20Sopenharmony_ci#define GEN8_PPAT_ELLC_OVERRIDE (0<<2) 1328c2ecf20Sopenharmony_ci#define GEN8_PPAT(i, x) ((u64)(x) << ((i) * 8)) 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci#define GEN8_PDE_IPS_64K BIT(11) 1358c2ecf20Sopenharmony_ci#define GEN8_PDE_PS_2M BIT(7) 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cienum i915_cache_level; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistruct drm_i915_file_private; 1408c2ecf20Sopenharmony_cistruct drm_i915_gem_object; 1418c2ecf20Sopenharmony_cistruct i915_fence_reg; 1428c2ecf20Sopenharmony_cistruct i915_vma; 1438c2ecf20Sopenharmony_cistruct intel_gt; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci#define for_each_sgt_daddr(__dp, __iter, __sgt) \ 1468c2ecf20Sopenharmony_ci __for_each_sgt_daddr(__dp, __iter, __sgt, I915_GTT_PAGE_SIZE) 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistruct i915_page_table { 1498c2ecf20Sopenharmony_ci struct drm_i915_gem_object *base; 1508c2ecf20Sopenharmony_ci union { 1518c2ecf20Sopenharmony_ci atomic_t used; 1528c2ecf20Sopenharmony_ci struct i915_page_table *stash; 1538c2ecf20Sopenharmony_ci }; 1548c2ecf20Sopenharmony_ci}; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistruct i915_page_directory { 1578c2ecf20Sopenharmony_ci struct i915_page_table pt; 1588c2ecf20Sopenharmony_ci spinlock_t lock; 1598c2ecf20Sopenharmony_ci void **entry; 1608c2ecf20Sopenharmony_ci}; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci#define __px_choose_expr(x, type, expr, other) \ 1638c2ecf20Sopenharmony_ci __builtin_choose_expr( \ 1648c2ecf20Sopenharmony_ci __builtin_types_compatible_p(typeof(x), type) || \ 1658c2ecf20Sopenharmony_ci __builtin_types_compatible_p(typeof(x), const type), \ 1668c2ecf20Sopenharmony_ci ({ type __x = (type)(x); expr; }), \ 1678c2ecf20Sopenharmony_ci other) 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci#define px_base(px) \ 1708c2ecf20Sopenharmony_ci __px_choose_expr(px, struct drm_i915_gem_object *, __x, \ 1718c2ecf20Sopenharmony_ci __px_choose_expr(px, struct i915_page_table *, __x->base, \ 1728c2ecf20Sopenharmony_ci __px_choose_expr(px, struct i915_page_directory *, __x->pt.base, \ 1738c2ecf20Sopenharmony_ci (void)0))) 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistruct page *__px_page(struct drm_i915_gem_object *p); 1768c2ecf20Sopenharmony_cidma_addr_t __px_dma(struct drm_i915_gem_object *p); 1778c2ecf20Sopenharmony_ci#define px_dma(px) (__px_dma(px_base(px))) 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci#define px_pt(px) \ 1808c2ecf20Sopenharmony_ci __px_choose_expr(px, struct i915_page_table *, __x, \ 1818c2ecf20Sopenharmony_ci __px_choose_expr(px, struct i915_page_directory *, &__x->pt, \ 1828c2ecf20Sopenharmony_ci (void)0)) 1838c2ecf20Sopenharmony_ci#define px_used(px) (&px_pt(px)->used) 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistruct i915_vm_pt_stash { 1868c2ecf20Sopenharmony_ci /* preallocated chains of page tables/directories */ 1878c2ecf20Sopenharmony_ci struct i915_page_table *pt[2]; 1888c2ecf20Sopenharmony_ci}; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistruct i915_vma_ops { 1918c2ecf20Sopenharmony_ci /* Map an object into an address space with the given cache flags. */ 1928c2ecf20Sopenharmony_ci void (*bind_vma)(struct i915_address_space *vm, 1938c2ecf20Sopenharmony_ci struct i915_vm_pt_stash *stash, 1948c2ecf20Sopenharmony_ci struct i915_vma *vma, 1958c2ecf20Sopenharmony_ci enum i915_cache_level cache_level, 1968c2ecf20Sopenharmony_ci u32 flags); 1978c2ecf20Sopenharmony_ci /* 1988c2ecf20Sopenharmony_ci * Unmap an object from an address space. This usually consists of 1998c2ecf20Sopenharmony_ci * setting the valid PTE entries to a reserved scratch page. 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_ci void (*unbind_vma)(struct i915_address_space *vm, 2028c2ecf20Sopenharmony_ci struct i915_vma *vma); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci int (*set_pages)(struct i915_vma *vma); 2058c2ecf20Sopenharmony_ci void (*clear_pages)(struct i915_vma *vma); 2068c2ecf20Sopenharmony_ci}; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistruct i915_address_space { 2098c2ecf20Sopenharmony_ci struct kref ref; 2108c2ecf20Sopenharmony_ci struct rcu_work rcu; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci struct drm_mm mm; 2138c2ecf20Sopenharmony_ci struct intel_gt *gt; 2148c2ecf20Sopenharmony_ci struct drm_i915_private *i915; 2158c2ecf20Sopenharmony_ci struct device *dma; 2168c2ecf20Sopenharmony_ci /* 2178c2ecf20Sopenharmony_ci * Every address space belongs to a struct file - except for the global 2188c2ecf20Sopenharmony_ci * GTT that is owned by the driver (and so @file is set to NULL). In 2198c2ecf20Sopenharmony_ci * principle, no information should leak from one context to another 2208c2ecf20Sopenharmony_ci * (or between files/processes etc) unless explicitly shared by the 2218c2ecf20Sopenharmony_ci * owner. Tracking the owner is important in order to free up per-file 2228c2ecf20Sopenharmony_ci * objects along with the file, to aide resource tracking, and to 2238c2ecf20Sopenharmony_ci * assign blame. 2248c2ecf20Sopenharmony_ci */ 2258c2ecf20Sopenharmony_ci struct drm_i915_file_private *file; 2268c2ecf20Sopenharmony_ci u64 total; /* size addr space maps (ex. 2GB for ggtt) */ 2278c2ecf20Sopenharmony_ci u64 reserved; /* size addr space reserved */ 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci unsigned int bind_async_flags; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci /* 2328c2ecf20Sopenharmony_ci * Each active user context has its own address space (in full-ppgtt). 2338c2ecf20Sopenharmony_ci * Since the vm may be shared between multiple contexts, we count how 2348c2ecf20Sopenharmony_ci * many contexts keep us "open". Once open hits zero, we are closed 2358c2ecf20Sopenharmony_ci * and do not allow any new attachments, and proceed to shutdown our 2368c2ecf20Sopenharmony_ci * vma and page directories. 2378c2ecf20Sopenharmony_ci */ 2388c2ecf20Sopenharmony_ci atomic_t open; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci struct mutex mutex; /* protects vma and our lists */ 2418c2ecf20Sopenharmony_ci#define VM_CLASS_GGTT 0 2428c2ecf20Sopenharmony_ci#define VM_CLASS_PPGTT 1 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci struct drm_i915_gem_object *scratch[4]; 2458c2ecf20Sopenharmony_ci /** 2468c2ecf20Sopenharmony_ci * List of vma currently bound. 2478c2ecf20Sopenharmony_ci */ 2488c2ecf20Sopenharmony_ci struct list_head bound_list; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* Global GTT */ 2518c2ecf20Sopenharmony_ci bool is_ggtt:1; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* Some systems support read-only mappings for GGTT and/or PPGTT */ 2548c2ecf20Sopenharmony_ci bool has_read_only:1; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci u8 top; 2578c2ecf20Sopenharmony_ci u8 pd_shift; 2588c2ecf20Sopenharmony_ci u8 scratch_order; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci struct drm_i915_gem_object * 2618c2ecf20Sopenharmony_ci (*alloc_pt_dma)(struct i915_address_space *vm, int sz); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci u64 (*pte_encode)(dma_addr_t addr, 2648c2ecf20Sopenharmony_ci enum i915_cache_level level, 2658c2ecf20Sopenharmony_ci u32 flags); /* Create a valid PTE */ 2668c2ecf20Sopenharmony_ci#define PTE_READ_ONLY BIT(0) 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci void (*allocate_va_range)(struct i915_address_space *vm, 2698c2ecf20Sopenharmony_ci struct i915_vm_pt_stash *stash, 2708c2ecf20Sopenharmony_ci u64 start, u64 length); 2718c2ecf20Sopenharmony_ci void (*clear_range)(struct i915_address_space *vm, 2728c2ecf20Sopenharmony_ci u64 start, u64 length); 2738c2ecf20Sopenharmony_ci void (*insert_page)(struct i915_address_space *vm, 2748c2ecf20Sopenharmony_ci dma_addr_t addr, 2758c2ecf20Sopenharmony_ci u64 offset, 2768c2ecf20Sopenharmony_ci enum i915_cache_level cache_level, 2778c2ecf20Sopenharmony_ci u32 flags); 2788c2ecf20Sopenharmony_ci void (*insert_entries)(struct i915_address_space *vm, 2798c2ecf20Sopenharmony_ci struct i915_vma *vma, 2808c2ecf20Sopenharmony_ci enum i915_cache_level cache_level, 2818c2ecf20Sopenharmony_ci u32 flags); 2828c2ecf20Sopenharmony_ci void (*cleanup)(struct i915_address_space *vm); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci struct i915_vma_ops vma_ops; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci I915_SELFTEST_DECLARE(struct fault_attr fault_attr); 2878c2ecf20Sopenharmony_ci I915_SELFTEST_DECLARE(bool scrub_64K); 2888c2ecf20Sopenharmony_ci}; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/* 2918c2ecf20Sopenharmony_ci * The Graphics Translation Table is the way in which GEN hardware translates a 2928c2ecf20Sopenharmony_ci * Graphics Virtual Address into a Physical Address. In addition to the normal 2938c2ecf20Sopenharmony_ci * collateral associated with any va->pa translations GEN hardware also has a 2948c2ecf20Sopenharmony_ci * portion of the GTT which can be mapped by the CPU and remain both coherent 2958c2ecf20Sopenharmony_ci * and correct (in cases like swizzling). That region is referred to as GMADR in 2968c2ecf20Sopenharmony_ci * the spec. 2978c2ecf20Sopenharmony_ci */ 2988c2ecf20Sopenharmony_cistruct i915_ggtt { 2998c2ecf20Sopenharmony_ci struct i915_address_space vm; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci struct io_mapping iomap; /* Mapping to our CPU mappable region */ 3028c2ecf20Sopenharmony_ci struct resource gmadr; /* GMADR resource */ 3038c2ecf20Sopenharmony_ci resource_size_t mappable_end; /* End offset that we can CPU map */ 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /** "Graphics Stolen Memory" holds the global PTEs */ 3068c2ecf20Sopenharmony_ci void __iomem *gsm; 3078c2ecf20Sopenharmony_ci void (*invalidate)(struct i915_ggtt *ggtt); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci /** PPGTT used for aliasing the PPGTT with the GTT */ 3108c2ecf20Sopenharmony_ci struct i915_ppgtt *alias; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci bool do_idle_maps; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci int mtrr; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /** Bit 6 swizzling required for X tiling */ 3178c2ecf20Sopenharmony_ci u32 bit_6_swizzle_x; 3188c2ecf20Sopenharmony_ci /** Bit 6 swizzling required for Y tiling */ 3198c2ecf20Sopenharmony_ci u32 bit_6_swizzle_y; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci u32 pin_bias; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci unsigned int num_fences; 3248c2ecf20Sopenharmony_ci struct i915_fence_reg *fence_regs; 3258c2ecf20Sopenharmony_ci struct list_head fence_list; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /** 3288c2ecf20Sopenharmony_ci * List of all objects in gtt_space, currently mmaped by userspace. 3298c2ecf20Sopenharmony_ci * All objects within this list must also be on bound_list. 3308c2ecf20Sopenharmony_ci */ 3318c2ecf20Sopenharmony_ci struct list_head userfault_list; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci /* Manual runtime pm autosuspend delay for user GGTT mmaps */ 3348c2ecf20Sopenharmony_ci struct intel_wakeref_auto userfault_wakeref; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci struct mutex error_mutex; 3378c2ecf20Sopenharmony_ci struct drm_mm_node error_capture; 3388c2ecf20Sopenharmony_ci struct drm_mm_node uc_fw; 3398c2ecf20Sopenharmony_ci}; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistruct i915_ppgtt { 3428c2ecf20Sopenharmony_ci struct i915_address_space vm; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci struct i915_page_directory *pd; 3458c2ecf20Sopenharmony_ci}; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci#define i915_is_ggtt(vm) ((vm)->is_ggtt) 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_cistatic inline bool 3508c2ecf20Sopenharmony_cii915_vm_is_4lvl(const struct i915_address_space *vm) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci return (vm->total - 1) >> 32; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic inline bool 3568c2ecf20Sopenharmony_cii915_vm_has_scratch_64K(struct i915_address_space *vm) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci return vm->scratch_order == get_order(I915_GTT_PAGE_SIZE_64K); 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic inline bool 3628c2ecf20Sopenharmony_cii915_vm_has_cache_coloring(struct i915_address_space *vm) 3638c2ecf20Sopenharmony_ci{ 3648c2ecf20Sopenharmony_ci return i915_is_ggtt(vm) && vm->mm.color_adjust; 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic inline struct i915_ggtt * 3688c2ecf20Sopenharmony_cii915_vm_to_ggtt(struct i915_address_space *vm) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci BUILD_BUG_ON(offsetof(struct i915_ggtt, vm)); 3718c2ecf20Sopenharmony_ci GEM_BUG_ON(!i915_is_ggtt(vm)); 3728c2ecf20Sopenharmony_ci return container_of(vm, struct i915_ggtt, vm); 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic inline struct i915_ppgtt * 3768c2ecf20Sopenharmony_cii915_vm_to_ppgtt(struct i915_address_space *vm) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci BUILD_BUG_ON(offsetof(struct i915_ppgtt, vm)); 3798c2ecf20Sopenharmony_ci GEM_BUG_ON(i915_is_ggtt(vm)); 3808c2ecf20Sopenharmony_ci return container_of(vm, struct i915_ppgtt, vm); 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cistatic inline struct i915_address_space * 3848c2ecf20Sopenharmony_cii915_vm_get(struct i915_address_space *vm) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci kref_get(&vm->ref); 3878c2ecf20Sopenharmony_ci return vm; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_civoid i915_vm_release(struct kref *kref); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic inline void i915_vm_put(struct i915_address_space *vm) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci kref_put(&vm->ref, i915_vm_release); 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cistatic inline struct i915_address_space * 3988c2ecf20Sopenharmony_cii915_vm_open(struct i915_address_space *vm) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci GEM_BUG_ON(!atomic_read(&vm->open)); 4018c2ecf20Sopenharmony_ci atomic_inc(&vm->open); 4028c2ecf20Sopenharmony_ci return i915_vm_get(vm); 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistatic inline bool 4068c2ecf20Sopenharmony_cii915_vm_tryopen(struct i915_address_space *vm) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci if (atomic_add_unless(&vm->open, 1, 0)) 4098c2ecf20Sopenharmony_ci return i915_vm_get(vm); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci return false; 4128c2ecf20Sopenharmony_ci} 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_civoid __i915_vm_close(struct i915_address_space *vm); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_cistatic inline void 4178c2ecf20Sopenharmony_cii915_vm_close(struct i915_address_space *vm) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci GEM_BUG_ON(!atomic_read(&vm->open)); 4208c2ecf20Sopenharmony_ci __i915_vm_close(vm); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci i915_vm_put(vm); 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_civoid i915_address_space_init(struct i915_address_space *vm, int subclass); 4268c2ecf20Sopenharmony_civoid i915_address_space_fini(struct i915_address_space *vm); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_cistatic inline u32 i915_pte_index(u64 address, unsigned int pde_shift) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci const u32 mask = NUM_PTE(pde_shift) - 1; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci return (address >> PAGE_SHIFT) & mask; 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci/* 4368c2ecf20Sopenharmony_ci * Helper to counts the number of PTEs within the given length. This count 4378c2ecf20Sopenharmony_ci * does not cross a page table boundary, so the max value would be 4388c2ecf20Sopenharmony_ci * GEN6_PTES for GEN6, and GEN8_PTES for GEN8. 4398c2ecf20Sopenharmony_ci */ 4408c2ecf20Sopenharmony_cistatic inline u32 i915_pte_count(u64 addr, u64 length, unsigned int pde_shift) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci const u64 mask = ~((1ULL << pde_shift) - 1); 4438c2ecf20Sopenharmony_ci u64 end; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci GEM_BUG_ON(length == 0); 4468c2ecf20Sopenharmony_ci GEM_BUG_ON(offset_in_page(addr | length)); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci end = addr + length; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci if ((addr & mask) != (end & mask)) 4518c2ecf20Sopenharmony_ci return NUM_PTE(pde_shift) - i915_pte_index(addr, pde_shift); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci return i915_pte_index(end, pde_shift) - i915_pte_index(addr, pde_shift); 4548c2ecf20Sopenharmony_ci} 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_cistatic inline u32 i915_pde_index(u64 addr, u32 shift) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci return (addr >> shift) & I915_PDE_MASK; 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_cistatic inline struct i915_page_table * 4628c2ecf20Sopenharmony_cii915_pt_entry(const struct i915_page_directory * const pd, 4638c2ecf20Sopenharmony_ci const unsigned short n) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci return pd->entry[n]; 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_cistatic inline struct i915_page_directory * 4698c2ecf20Sopenharmony_cii915_pd_entry(const struct i915_page_directory * const pdp, 4708c2ecf20Sopenharmony_ci const unsigned short n) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci return pdp->entry[n]; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic inline dma_addr_t 4768c2ecf20Sopenharmony_cii915_page_dir_dma_addr(const struct i915_ppgtt *ppgtt, const unsigned int n) 4778c2ecf20Sopenharmony_ci{ 4788c2ecf20Sopenharmony_ci struct i915_page_table *pt = ppgtt->pd->entry[n]; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci return __px_dma(pt ? px_base(pt) : ppgtt->vm.scratch[ppgtt->vm.top]); 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_civoid ppgtt_init(struct i915_ppgtt *ppgtt, struct intel_gt *gt); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ciint i915_ggtt_probe_hw(struct drm_i915_private *i915); 4868c2ecf20Sopenharmony_ciint i915_ggtt_init_hw(struct drm_i915_private *i915); 4878c2ecf20Sopenharmony_ciint i915_ggtt_enable_hw(struct drm_i915_private *i915); 4888c2ecf20Sopenharmony_civoid i915_ggtt_enable_guc(struct i915_ggtt *ggtt); 4898c2ecf20Sopenharmony_civoid i915_ggtt_disable_guc(struct i915_ggtt *ggtt); 4908c2ecf20Sopenharmony_ciint i915_init_ggtt(struct drm_i915_private *i915); 4918c2ecf20Sopenharmony_civoid i915_ggtt_driver_release(struct drm_i915_private *i915); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic inline bool i915_ggtt_has_aperture(const struct i915_ggtt *ggtt) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci return ggtt->mappable_end > 0; 4968c2ecf20Sopenharmony_ci} 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ciint i915_ppgtt_init_hw(struct intel_gt *gt); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_cistruct i915_ppgtt *i915_ppgtt_create(struct intel_gt *gt); 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_civoid i915_ggtt_suspend(struct i915_ggtt *gtt); 5038c2ecf20Sopenharmony_civoid i915_ggtt_resume(struct i915_ggtt *ggtt); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci#define kmap_atomic_px(px) kmap_atomic(__px_page(px_base(px))) 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_civoid 5088c2ecf20Sopenharmony_cifill_page_dma(struct drm_i915_gem_object *p, const u64 val, unsigned int count); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci#define fill_px(px, v) fill_page_dma(px_base(px), (v), PAGE_SIZE / sizeof(u64)) 5118c2ecf20Sopenharmony_ci#define fill32_px(px, v) do { \ 5128c2ecf20Sopenharmony_ci u64 v__ = lower_32_bits(v); \ 5138c2ecf20Sopenharmony_ci fill_px((px), v__ << 32 | v__); \ 5148c2ecf20Sopenharmony_ci} while (0) 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ciint setup_scratch_page(struct i915_address_space *vm); 5178c2ecf20Sopenharmony_civoid free_scratch(struct i915_address_space *vm); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_cistruct drm_i915_gem_object *alloc_pt_dma(struct i915_address_space *vm, int sz); 5208c2ecf20Sopenharmony_cistruct i915_page_table *alloc_pt(struct i915_address_space *vm); 5218c2ecf20Sopenharmony_cistruct i915_page_directory *alloc_pd(struct i915_address_space *vm); 5228c2ecf20Sopenharmony_cistruct i915_page_directory *__alloc_pd(int npde); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ciint pin_pt_dma(struct i915_address_space *vm, struct drm_i915_gem_object *obj); 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_civoid free_px(struct i915_address_space *vm, 5278c2ecf20Sopenharmony_ci struct i915_page_table *pt, int lvl); 5288c2ecf20Sopenharmony_ci#define free_pt(vm, px) free_px(vm, px, 0) 5298c2ecf20Sopenharmony_ci#define free_pd(vm, px) free_px(vm, px_pt(px), 1) 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_civoid 5328c2ecf20Sopenharmony_ci__set_pd_entry(struct i915_page_directory * const pd, 5338c2ecf20Sopenharmony_ci const unsigned short idx, 5348c2ecf20Sopenharmony_ci struct i915_page_table *pt, 5358c2ecf20Sopenharmony_ci u64 (*encode)(const dma_addr_t, const enum i915_cache_level)); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci#define set_pd_entry(pd, idx, to) \ 5388c2ecf20Sopenharmony_ci __set_pd_entry((pd), (idx), px_pt(to), gen8_pde_encode) 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_civoid 5418c2ecf20Sopenharmony_ciclear_pd_entry(struct i915_page_directory * const pd, 5428c2ecf20Sopenharmony_ci const unsigned short idx, 5438c2ecf20Sopenharmony_ci const struct drm_i915_gem_object * const scratch); 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_cibool 5468c2ecf20Sopenharmony_cirelease_pd_entry(struct i915_page_directory * const pd, 5478c2ecf20Sopenharmony_ci const unsigned short idx, 5488c2ecf20Sopenharmony_ci struct i915_page_table * const pt, 5498c2ecf20Sopenharmony_ci const struct drm_i915_gem_object * const scratch); 5508c2ecf20Sopenharmony_civoid gen6_ggtt_invalidate(struct i915_ggtt *ggtt); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ciint ggtt_set_pages(struct i915_vma *vma); 5538c2ecf20Sopenharmony_ciint ppgtt_set_pages(struct i915_vma *vma); 5548c2ecf20Sopenharmony_civoid clear_pages(struct i915_vma *vma); 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_civoid ppgtt_bind_vma(struct i915_address_space *vm, 5578c2ecf20Sopenharmony_ci struct i915_vm_pt_stash *stash, 5588c2ecf20Sopenharmony_ci struct i915_vma *vma, 5598c2ecf20Sopenharmony_ci enum i915_cache_level cache_level, 5608c2ecf20Sopenharmony_ci u32 flags); 5618c2ecf20Sopenharmony_civoid ppgtt_unbind_vma(struct i915_address_space *vm, 5628c2ecf20Sopenharmony_ci struct i915_vma *vma); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_civoid gtt_write_workarounds(struct intel_gt *gt); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_civoid setup_private_pat(struct intel_uncore *uncore); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ciint i915_vm_alloc_pt_stash(struct i915_address_space *vm, 5698c2ecf20Sopenharmony_ci struct i915_vm_pt_stash *stash, 5708c2ecf20Sopenharmony_ci u64 size); 5718c2ecf20Sopenharmony_ciint i915_vm_pin_pt_stash(struct i915_address_space *vm, 5728c2ecf20Sopenharmony_ci struct i915_vm_pt_stash *stash); 5738c2ecf20Sopenharmony_civoid i915_vm_free_pt_stash(struct i915_address_space *vm, 5748c2ecf20Sopenharmony_ci struct i915_vm_pt_stash *stash); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_cistatic inline struct sgt_dma { 5778c2ecf20Sopenharmony_ci struct scatterlist *sg; 5788c2ecf20Sopenharmony_ci dma_addr_t dma, max; 5798c2ecf20Sopenharmony_ci} sgt_dma(struct i915_vma *vma) { 5808c2ecf20Sopenharmony_ci struct scatterlist *sg = vma->pages->sgl; 5818c2ecf20Sopenharmony_ci dma_addr_t addr = sg_dma_address(sg); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci return (struct sgt_dma){ sg, addr, addr + sg->length }; 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci#endif 587