Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright © 2020 Intel Corporation
   4 */
   5
   6#include <linux/log2.h>
   7
   8#include "gem/i915_gem_internal.h"
   9#include "gem/i915_gem_lmem.h"
  10
  11#include "gen8_ppgtt.h"
  12#include "i915_scatterlist.h"
  13#include "i915_trace.h"
  14#include "i915_pvinfo.h"
  15#include "i915_vgpu.h"
  16#include "intel_gt.h"
  17#include "intel_gtt.h"
  18
  19static u64 gen8_pde_encode(const dma_addr_t addr,
  20			   const enum i915_cache_level level)
  21{
  22	u64 pde = addr | GEN8_PAGE_PRESENT | GEN8_PAGE_RW;
  23
  24	if (level != I915_CACHE_NONE)
  25		pde |= PPAT_CACHED_PDE;
  26	else
  27		pde |= PPAT_UNCACHED;
  28
  29	return pde;
  30}
  31
  32static u64 gen8_pte_encode(dma_addr_t addr,
  33			   unsigned int pat_index,
  34			   u32 flags)
  35{
  36	gen8_pte_t pte = addr | GEN8_PAGE_PRESENT | GEN8_PAGE_RW;
  37
  38	if (unlikely(flags & PTE_READ_ONLY))
  39		pte &= ~GEN8_PAGE_RW;
  40
  41	/*
  42	 * For pre-gen12 platforms pat_index is the same as enum
  43	 * i915_cache_level, so the switch-case here is still valid.
  44	 * See translation table defined by LEGACY_CACHELEVEL.
  45	 */
  46	switch (pat_index) {
  47	case I915_CACHE_NONE:
  48		pte |= PPAT_UNCACHED;
  49		break;
  50	case I915_CACHE_WT:
  51		pte |= PPAT_DISPLAY_ELLC;
  52		break;
  53	default:
  54		pte |= PPAT_CACHED;
  55		break;
  56	}
  57
  58	return pte;
  59}
  60
  61static u64 gen12_pte_encode(dma_addr_t addr,
  62			    unsigned int pat_index,
  63			    u32 flags)
  64{
  65	gen8_pte_t pte = addr | GEN8_PAGE_PRESENT | GEN8_PAGE_RW;
  66
  67	if (unlikely(flags & PTE_READ_ONLY))
  68		pte &= ~GEN8_PAGE_RW;
  69
  70	if (flags & PTE_LM)
  71		pte |= GEN12_PPGTT_PTE_LM;
  72
  73	if (pat_index & BIT(0))
  74		pte |= GEN12_PPGTT_PTE_PAT0;
  75
  76	if (pat_index & BIT(1))
  77		pte |= GEN12_PPGTT_PTE_PAT1;
  78
  79	if (pat_index & BIT(2))
  80		pte |= GEN12_PPGTT_PTE_PAT2;
  81
  82	if (pat_index & BIT(3))
  83		pte |= MTL_PPGTT_PTE_PAT3;
  84
  85	return pte;
  86}
  87
  88static void gen8_ppgtt_notify_vgt(struct i915_ppgtt *ppgtt, bool create)
  89{
  90	struct drm_i915_private *i915 = ppgtt->vm.i915;
  91	struct intel_uncore *uncore = ppgtt->vm.gt->uncore;
  92	enum vgt_g2v_type msg;
  93	int i;
  94
  95	if (create)
  96		atomic_inc(px_used(ppgtt->pd)); /* never remove */
  97	else
  98		atomic_dec(px_used(ppgtt->pd));
  99
 100	mutex_lock(&i915->vgpu.lock);
 101
 102	if (i915_vm_is_4lvl(&ppgtt->vm)) {
 103		const u64 daddr = px_dma(ppgtt->pd);
 104
 105		intel_uncore_write(uncore,
 106				   vgtif_reg(pdp[0].lo), lower_32_bits(daddr));
 107		intel_uncore_write(uncore,
 108				   vgtif_reg(pdp[0].hi), upper_32_bits(daddr));
 109
 110		msg = create ?
 111			VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE :
 112			VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY;
 113	} else {
 114		for (i = 0; i < GEN8_3LVL_PDPES; i++) {
 115			const u64 daddr = i915_page_dir_dma_addr(ppgtt, i);
 116
 117			intel_uncore_write(uncore,
 118					   vgtif_reg(pdp[i].lo),
 119					   lower_32_bits(daddr));
 120			intel_uncore_write(uncore,
 121					   vgtif_reg(pdp[i].hi),
 122					   upper_32_bits(daddr));
 123		}
 124
 125		msg = create ?
 126			VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE :
 127			VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY;
 128	}
 129
 130	/* g2v_notify atomically (via hv trap) consumes the message packet. */
 131	intel_uncore_write(uncore, vgtif_reg(g2v_notify), msg);
 132
 133	mutex_unlock(&i915->vgpu.lock);
 134}
 135
 136/* Index shifts into the pagetable are offset by GEN8_PTE_SHIFT [12] */
 137#define GEN8_PAGE_SIZE (SZ_4K) /* page and page-directory sizes are the same */
 138#define GEN8_PTE_SHIFT (ilog2(GEN8_PAGE_SIZE))
 139#define GEN8_PDES (GEN8_PAGE_SIZE / sizeof(u64))
 140#define gen8_pd_shift(lvl) ((lvl) * ilog2(GEN8_PDES))
 141#define gen8_pd_index(i, lvl) i915_pde_index((i), gen8_pd_shift(lvl))
 142#define __gen8_pte_shift(lvl) (GEN8_PTE_SHIFT + gen8_pd_shift(lvl))
 143#define __gen8_pte_index(a, lvl) i915_pde_index((a), __gen8_pte_shift(lvl))
 144
 145#define as_pd(x) container_of((x), typeof(struct i915_page_directory), pt)
 146
 147static unsigned int
 148gen8_pd_range(u64 start, u64 end, int lvl, unsigned int *idx)
 149{
 150	const int shift = gen8_pd_shift(lvl);
 151	const u64 mask = ~0ull << gen8_pd_shift(lvl + 1);
 152
 153	GEM_BUG_ON(start >= end);
 154	end += ~mask >> gen8_pd_shift(1);
 155
 156	*idx = i915_pde_index(start, shift);
 157	if ((start ^ end) & mask)
 158		return GEN8_PDES - *idx;
 159	else
 160		return i915_pde_index(end, shift) - *idx;
 161}
 162
 163static bool gen8_pd_contains(u64 start, u64 end, int lvl)
 164{
 165	const u64 mask = ~0ull << gen8_pd_shift(lvl + 1);
 166
 167	GEM_BUG_ON(start >= end);
 168	return (start ^ end) & mask && (start & ~mask) == 0;
 169}
 170
 171static unsigned int gen8_pt_count(u64 start, u64 end)
 172{
 173	GEM_BUG_ON(start >= end);
 174	if ((start ^ end) >> gen8_pd_shift(1))
 175		return GEN8_PDES - (start & (GEN8_PDES - 1));
 176	else
 177		return end - start;
 178}
 179
 180static unsigned int gen8_pd_top_count(const struct i915_address_space *vm)
 181{
 182	unsigned int shift = __gen8_pte_shift(vm->top);
 183
 184	return (vm->total + (1ull << shift) - 1) >> shift;
 185}
 186
 187static struct i915_page_directory *
 188gen8_pdp_for_page_index(struct i915_address_space * const vm, const u64 idx)
 189{
 190	struct i915_ppgtt * const ppgtt = i915_vm_to_ppgtt(vm);
 191
 192	if (vm->top == 2)
 193		return ppgtt->pd;
 194	else
 195		return i915_pd_entry(ppgtt->pd, gen8_pd_index(idx, vm->top));
 196}
 197
 198static struct i915_page_directory *
 199gen8_pdp_for_page_address(struct i915_address_space * const vm, const u64 addr)
 200{
 201	return gen8_pdp_for_page_index(vm, addr >> GEN8_PTE_SHIFT);
 202}
 203
 204static void __gen8_ppgtt_cleanup(struct i915_address_space *vm,
 205				 struct i915_page_directory *pd,
 206				 int count, int lvl)
 207{
 208	if (lvl) {
 209		void **pde = pd->entry;
 210
 211		do {
 212			if (!*pde)
 213				continue;
 214
 215			__gen8_ppgtt_cleanup(vm, *pde, GEN8_PDES, lvl - 1);
 216		} while (pde++, --count);
 217	}
 218
 219	free_px(vm, &pd->pt, lvl);
 220}
 221
 222static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
 223{
 224	struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 225
 226	if (vm->rsvd.obj)
 227		i915_gem_object_put(vm->rsvd.obj);
 228
 229	if (intel_vgpu_active(vm->i915))
 230		gen8_ppgtt_notify_vgt(ppgtt, false);
 231
 232	if (ppgtt->pd)
 233		__gen8_ppgtt_cleanup(vm, ppgtt->pd,
 234				     gen8_pd_top_count(vm), vm->top);
 235
 236	free_scratch(vm);
 237}
 238
 239static u64 __gen8_ppgtt_clear(struct i915_address_space * const vm,
 240			      struct i915_page_directory * const pd,
 241			      u64 start, const u64 end, int lvl)
 242{
 243	const struct drm_i915_gem_object * const scratch = vm->scratch[lvl];
 244	unsigned int idx, len;
 245
 246	GEM_BUG_ON(end > vm->total >> GEN8_PTE_SHIFT);
 247
 248	len = gen8_pd_range(start, end, lvl--, &idx);
 249	GTT_TRACE("%s(%p):{ lvl:%d, start:%llx, end:%llx, idx:%d, len:%d, used:%d }\n",
 250		  __func__, vm, lvl + 1, start, end,
 251		  idx, len, atomic_read(px_used(pd)));
 252	GEM_BUG_ON(!len || len >= atomic_read(px_used(pd)));
 253
 254	do {
 255		struct i915_page_table *pt = pd->entry[idx];
 256
 257		if (atomic_fetch_inc(&pt->used) >> gen8_pd_shift(1) &&
 258		    gen8_pd_contains(start, end, lvl)) {
 259			GTT_TRACE("%s(%p):{ lvl:%d, idx:%d, start:%llx, end:%llx } removing pd\n",
 260				  __func__, vm, lvl + 1, idx, start, end);
 261			clear_pd_entry(pd, idx, scratch);
 262			__gen8_ppgtt_cleanup(vm, as_pd(pt), I915_PDES, lvl);
 263			start += (u64)I915_PDES << gen8_pd_shift(lvl);
 264			continue;
 265		}
 266
 267		if (lvl) {
 268			start = __gen8_ppgtt_clear(vm, as_pd(pt),
 269						   start, end, lvl);
 270		} else {
 271			unsigned int count;
 272			unsigned int pte = gen8_pd_index(start, 0);
 273			unsigned int num_ptes;
 274			u64 *vaddr;
 275
 276			count = gen8_pt_count(start, end);
 277			GTT_TRACE("%s(%p):{ lvl:%d, start:%llx, end:%llx, idx:%d, len:%d, used:%d } removing pte\n",
 278				  __func__, vm, lvl, start, end,
 279				  gen8_pd_index(start, 0), count,
 280				  atomic_read(&pt->used));
 281			GEM_BUG_ON(!count || count >= atomic_read(&pt->used));
 282
 283			num_ptes = count;
 284			if (pt->is_compact) {
 285				GEM_BUG_ON(num_ptes % 16);
 286				GEM_BUG_ON(pte % 16);
 287				num_ptes /= 16;
 288				pte /= 16;
 289			}
 290
 291			vaddr = px_vaddr(pt);
 292			memset64(vaddr + pte,
 293				 vm->scratch[0]->encode,
 294				 num_ptes);
 295
 296			atomic_sub(count, &pt->used);
 297			start += count;
 298		}
 299
 300		if (release_pd_entry(pd, idx, pt, scratch))
 301			free_px(vm, pt, lvl);
 302	} while (idx++, --len);
 303
 304	return start;
 305}
 306
 307static void gen8_ppgtt_clear(struct i915_address_space *vm,
 308			     u64 start, u64 length)
 309{
 310	GEM_BUG_ON(!IS_ALIGNED(start, BIT_ULL(GEN8_PTE_SHIFT)));
 311	GEM_BUG_ON(!IS_ALIGNED(length, BIT_ULL(GEN8_PTE_SHIFT)));
 312	GEM_BUG_ON(range_overflows(start, length, vm->total));
 313
 314	start >>= GEN8_PTE_SHIFT;
 315	length >>= GEN8_PTE_SHIFT;
 316	GEM_BUG_ON(length == 0);
 317
 318	__gen8_ppgtt_clear(vm, i915_vm_to_ppgtt(vm)->pd,
 319			   start, start + length, vm->top);
 320}
 321
 322static void __gen8_ppgtt_alloc(struct i915_address_space * const vm,
 323			       struct i915_vm_pt_stash *stash,
 324			       struct i915_page_directory * const pd,
 325			       u64 * const start, const u64 end, int lvl)
 326{
 327	unsigned int idx, len;
 328
 329	GEM_BUG_ON(end > vm->total >> GEN8_PTE_SHIFT);
 330
 331	len = gen8_pd_range(*start, end, lvl--, &idx);
 332	GTT_TRACE("%s(%p):{ lvl:%d, start:%llx, end:%llx, idx:%d, len:%d, used:%d }\n",
 333		  __func__, vm, lvl + 1, *start, end,
 334		  idx, len, atomic_read(px_used(pd)));
 335	GEM_BUG_ON(!len || (idx + len - 1) >> gen8_pd_shift(1));
 336
 337	spin_lock(&pd->lock);
 338	GEM_BUG_ON(!atomic_read(px_used(pd))); /* Must be pinned! */
 339	do {
 340		struct i915_page_table *pt = pd->entry[idx];
 341
 342		if (!pt) {
 343			spin_unlock(&pd->lock);
 344
 345			GTT_TRACE("%s(%p):{ lvl:%d, idx:%d } allocating new tree\n",
 346				  __func__, vm, lvl + 1, idx);
 347
 348			pt = stash->pt[!!lvl];
 349			__i915_gem_object_pin_pages(pt->base);
 350
 351			fill_px(pt, vm->scratch[lvl]->encode);
 352
 353			spin_lock(&pd->lock);
 354			if (likely(!pd->entry[idx])) {
 355				stash->pt[!!lvl] = pt->stash;
 356				atomic_set(&pt->used, 0);
 357				set_pd_entry(pd, idx, pt);
 358			} else {
 359				pt = pd->entry[idx];
 360			}
 361		}
 362
 363		if (lvl) {
 364			atomic_inc(&pt->used);
 365			spin_unlock(&pd->lock);
 366
 367			__gen8_ppgtt_alloc(vm, stash,
 368					   as_pd(pt), start, end, lvl);
 369
 370			spin_lock(&pd->lock);
 371			atomic_dec(&pt->used);
 372			GEM_BUG_ON(!atomic_read(&pt->used));
 373		} else {
 374			unsigned int count = gen8_pt_count(*start, end);
 375
 376			GTT_TRACE("%s(%p):{ lvl:%d, start:%llx, end:%llx, idx:%d, len:%d, used:%d } inserting pte\n",
 377				  __func__, vm, lvl, *start, end,
 378				  gen8_pd_index(*start, 0), count,
 379				  atomic_read(&pt->used));
 380
 381			atomic_add(count, &pt->used);
 382			/* All other pdes may be simultaneously removed */
 383			GEM_BUG_ON(atomic_read(&pt->used) > NALLOC * I915_PDES);
 384			*start += count;
 385		}
 386	} while (idx++, --len);
 387	spin_unlock(&pd->lock);
 388}
 389
 390static void gen8_ppgtt_alloc(struct i915_address_space *vm,
 391			     struct i915_vm_pt_stash *stash,
 392			     u64 start, u64 length)
 393{
 394	GEM_BUG_ON(!IS_ALIGNED(start, BIT_ULL(GEN8_PTE_SHIFT)));
 395	GEM_BUG_ON(!IS_ALIGNED(length, BIT_ULL(GEN8_PTE_SHIFT)));
 396	GEM_BUG_ON(range_overflows(start, length, vm->total));
 397
 398	start >>= GEN8_PTE_SHIFT;
 399	length >>= GEN8_PTE_SHIFT;
 400	GEM_BUG_ON(length == 0);
 401
 402	__gen8_ppgtt_alloc(vm, stash, i915_vm_to_ppgtt(vm)->pd,
 403			   &start, start + length, vm->top);
 404}
 405
 406static void __gen8_ppgtt_foreach(struct i915_address_space *vm,
 407				 struct i915_page_directory *pd,
 408				 u64 *start, u64 end, int lvl,
 409				 void (*fn)(struct i915_address_space *vm,
 410					    struct i915_page_table *pt,
 411					    void *data),
 412				 void *data)
 413{
 414	unsigned int idx, len;
 415
 416	len = gen8_pd_range(*start, end, lvl--, &idx);
 417
 418	spin_lock(&pd->lock);
 419	do {
 420		struct i915_page_table *pt = pd->entry[idx];
 421
 422		atomic_inc(&pt->used);
 423		spin_unlock(&pd->lock);
 424
 425		if (lvl) {
 426			__gen8_ppgtt_foreach(vm, as_pd(pt), start, end, lvl,
 427					     fn, data);
 428		} else {
 429			fn(vm, pt, data);
 430			*start += gen8_pt_count(*start, end);
 431		}
 432
 433		spin_lock(&pd->lock);
 434		atomic_dec(&pt->used);
 435	} while (idx++, --len);
 436	spin_unlock(&pd->lock);
 437}
 438
 439static void gen8_ppgtt_foreach(struct i915_address_space *vm,
 440			       u64 start, u64 length,
 441			       void (*fn)(struct i915_address_space *vm,
 442					  struct i915_page_table *pt,
 443					  void *data),
 444			       void *data)
 445{
 446	start >>= GEN8_PTE_SHIFT;
 447	length >>= GEN8_PTE_SHIFT;
 448
 449	__gen8_ppgtt_foreach(vm, i915_vm_to_ppgtt(vm)->pd,
 450			     &start, start + length, vm->top,
 451			     fn, data);
 452}
 453
 454static __always_inline u64
 455gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt,
 456		      struct i915_page_directory *pdp,
 457		      struct sgt_dma *iter,
 458		      u64 idx,
 459		      unsigned int pat_index,
 460		      u32 flags)
 461{
 462	struct i915_page_directory *pd;
 463	const gen8_pte_t pte_encode = ppgtt->vm.pte_encode(0, pat_index, flags);
 464	gen8_pte_t *vaddr;
 465
 466	pd = i915_pd_entry(pdp, gen8_pd_index(idx, 2));
 467	vaddr = px_vaddr(i915_pt_entry(pd, gen8_pd_index(idx, 1)));
 468	do {
 469		GEM_BUG_ON(sg_dma_len(iter->sg) < I915_GTT_PAGE_SIZE);
 470		vaddr[gen8_pd_index(idx, 0)] = pte_encode | iter->dma;
 471
 472		iter->dma += I915_GTT_PAGE_SIZE;
 473		if (iter->dma >= iter->max) {
 474			iter->sg = __sg_next(iter->sg);
 475			if (!iter->sg || sg_dma_len(iter->sg) == 0) {
 476				idx = 0;
 477				break;
 478			}
 479
 480			iter->dma = sg_dma_address(iter->sg);
 481			iter->max = iter->dma + sg_dma_len(iter->sg);
 482		}
 483
 484		if (gen8_pd_index(++idx, 0) == 0) {
 485			if (gen8_pd_index(idx, 1) == 0) {
 486				/* Limited by sg length for 3lvl */
 487				if (gen8_pd_index(idx, 2) == 0)
 488					break;
 489
 490				pd = pdp->entry[gen8_pd_index(idx, 2)];
 491			}
 492
 493			drm_clflush_virt_range(vaddr, PAGE_SIZE);
 494			vaddr = px_vaddr(i915_pt_entry(pd, gen8_pd_index(idx, 1)));
 495		}
 496	} while (1);
 497	drm_clflush_virt_range(vaddr, PAGE_SIZE);
 498
 499	return idx;
 500}
 501
 502static void
 503xehpsdv_ppgtt_insert_huge(struct i915_address_space *vm,
 504			  struct i915_vma_resource *vma_res,
 505			  struct sgt_dma *iter,
 506			  unsigned int pat_index,
 507			  u32 flags)
 508{
 509	const gen8_pte_t pte_encode = vm->pte_encode(0, pat_index, flags);
 510	unsigned int rem = sg_dma_len(iter->sg);
 511	u64 start = vma_res->start;
 512	u64 end = start + vma_res->vma_size;
 513
 514	GEM_BUG_ON(!i915_vm_is_4lvl(vm));
 515
 516	do {
 517		struct i915_page_directory * const pdp =
 518			gen8_pdp_for_page_address(vm, start);
 519		struct i915_page_directory * const pd =
 520			i915_pd_entry(pdp, __gen8_pte_index(start, 2));
 521		struct i915_page_table *pt =
 522			i915_pt_entry(pd, __gen8_pte_index(start, 1));
 523		gen8_pte_t encode = pte_encode;
 524		unsigned int page_size;
 525		gen8_pte_t *vaddr;
 526		u16 index, max, nent, i;
 527
 528		max = I915_PDES;
 529		nent = 1;
 530
 531		if (vma_res->bi.page_sizes.sg & I915_GTT_PAGE_SIZE_2M &&
 532		    IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_2M) &&
 533		    rem >= I915_GTT_PAGE_SIZE_2M &&
 534		    !__gen8_pte_index(start, 0)) {
 535			index = __gen8_pte_index(start, 1);
 536			encode |= GEN8_PDE_PS_2M;
 537			page_size = I915_GTT_PAGE_SIZE_2M;
 538
 539			vaddr = px_vaddr(pd);
 540		} else {
 541			index =  __gen8_pte_index(start, 0);
 542			page_size = I915_GTT_PAGE_SIZE;
 543
 544			if (vma_res->bi.page_sizes.sg & I915_GTT_PAGE_SIZE_64K) {
 545				/*
 546				 * Device local-memory on these platforms should
 547				 * always use 64K pages or larger (including GTT
 548				 * alignment), therefore if we know the whole
 549				 * page-table needs to be filled we can always
 550				 * safely use the compact-layout. Otherwise fall
 551				 * back to the TLB hint with PS64. If this is
 552				 * system memory we only bother with PS64.
 553				 */
 554				if ((encode & GEN12_PPGTT_PTE_LM) &&
 555				    end - start >= SZ_2M && !index) {
 556					index = __gen8_pte_index(start, 0) / 16;
 557					page_size = I915_GTT_PAGE_SIZE_64K;
 558
 559					max /= 16;
 560
 561					vaddr = px_vaddr(pd);
 562					vaddr[__gen8_pte_index(start, 1)] |= GEN12_PDE_64K;
 563
 564					pt->is_compact = true;
 565				} else if (IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) &&
 566					   rem >= I915_GTT_PAGE_SIZE_64K &&
 567					   !(index % 16)) {
 568					encode |= GEN12_PTE_PS64;
 569					page_size = I915_GTT_PAGE_SIZE_64K;
 570					nent = 16;
 571				}
 572			}
 573
 574			vaddr = px_vaddr(pt);
 575		}
 576
 577		do {
 578			GEM_BUG_ON(rem < page_size);
 579
 580			for (i = 0; i < nent; i++) {
 581				vaddr[index++] =
 582					encode | (iter->dma + i *
 583						  I915_GTT_PAGE_SIZE);
 584			}
 585
 586			start += page_size;
 587			iter->dma += page_size;
 588			rem -= page_size;
 589			if (iter->dma >= iter->max) {
 590				iter->sg = __sg_next(iter->sg);
 591				if (!iter->sg)
 592					break;
 593
 594				rem = sg_dma_len(iter->sg);
 595				if (!rem)
 596					break;
 597
 598				iter->dma = sg_dma_address(iter->sg);
 599				iter->max = iter->dma + rem;
 600
 601				if (unlikely(!IS_ALIGNED(iter->dma, page_size)))
 602					break;
 603			}
 604		} while (rem >= page_size && index < max);
 605
 606		drm_clflush_virt_range(vaddr, PAGE_SIZE);
 607		vma_res->page_sizes_gtt |= page_size;
 608	} while (iter->sg && sg_dma_len(iter->sg));
 609}
 610
 611static void gen8_ppgtt_insert_huge(struct i915_address_space *vm,
 612				   struct i915_vma_resource *vma_res,
 613				   struct sgt_dma *iter,
 614				   unsigned int pat_index,
 615				   u32 flags)
 616{
 617	const gen8_pte_t pte_encode = vm->pte_encode(0, pat_index, flags);
 618	unsigned int rem = sg_dma_len(iter->sg);
 619	u64 start = vma_res->start;
 620
 621	GEM_BUG_ON(!i915_vm_is_4lvl(vm));
 622
 623	do {
 624		struct i915_page_directory * const pdp =
 625			gen8_pdp_for_page_address(vm, start);
 626		struct i915_page_directory * const pd =
 627			i915_pd_entry(pdp, __gen8_pte_index(start, 2));
 628		gen8_pte_t encode = pte_encode;
 629		unsigned int maybe_64K = -1;
 630		unsigned int page_size;
 631		gen8_pte_t *vaddr;
 632		u16 index;
 633
 634		if (vma_res->bi.page_sizes.sg & I915_GTT_PAGE_SIZE_2M &&
 635		    IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_2M) &&
 636		    rem >= I915_GTT_PAGE_SIZE_2M &&
 637		    !__gen8_pte_index(start, 0)) {
 638			index = __gen8_pte_index(start, 1);
 639			encode |= GEN8_PDE_PS_2M;
 640			page_size = I915_GTT_PAGE_SIZE_2M;
 641
 642			vaddr = px_vaddr(pd);
 643		} else {
 644			struct i915_page_table *pt =
 645				i915_pt_entry(pd, __gen8_pte_index(start, 1));
 646
 647			index = __gen8_pte_index(start, 0);
 648			page_size = I915_GTT_PAGE_SIZE;
 649
 650			if (!index &&
 651			    vma_res->bi.page_sizes.sg & I915_GTT_PAGE_SIZE_64K &&
 652			    IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) &&
 653			    (IS_ALIGNED(rem, I915_GTT_PAGE_SIZE_64K) ||
 654			     rem >= (I915_PDES - index) * I915_GTT_PAGE_SIZE))
 655				maybe_64K = __gen8_pte_index(start, 1);
 656
 657			vaddr = px_vaddr(pt);
 658		}
 659
 660		do {
 661			GEM_BUG_ON(sg_dma_len(iter->sg) < page_size);
 662			vaddr[index++] = encode | iter->dma;
 663
 664			start += page_size;
 665			iter->dma += page_size;
 666			rem -= page_size;
 667			if (iter->dma >= iter->max) {
 668				iter->sg = __sg_next(iter->sg);
 669				if (!iter->sg)
 670					break;
 671
 672				rem = sg_dma_len(iter->sg);
 673				if (!rem)
 674					break;
 675
 676				iter->dma = sg_dma_address(iter->sg);
 677				iter->max = iter->dma + rem;
 678
 679				if (maybe_64K != -1 && index < I915_PDES &&
 680				    !(IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) &&
 681				      (IS_ALIGNED(rem, I915_GTT_PAGE_SIZE_64K) ||
 682				       rem >= (I915_PDES - index) * I915_GTT_PAGE_SIZE)))
 683					maybe_64K = -1;
 684
 685				if (unlikely(!IS_ALIGNED(iter->dma, page_size)))
 686					break;
 687			}
 688		} while (rem >= page_size && index < I915_PDES);
 689
 690		drm_clflush_virt_range(vaddr, PAGE_SIZE);
 691
 692		/*
 693		 * Is it safe to mark the 2M block as 64K? -- Either we have
 694		 * filled whole page-table with 64K entries, or filled part of
 695		 * it and have reached the end of the sg table and we have
 696		 * enough padding.
 697		 */
 698		if (maybe_64K != -1 &&
 699		    (index == I915_PDES ||
 700		     (i915_vm_has_scratch_64K(vm) &&
 701		      !iter->sg && IS_ALIGNED(vma_res->start +
 702					      vma_res->node_size,
 703					      I915_GTT_PAGE_SIZE_2M)))) {
 704			vaddr = px_vaddr(pd);
 705			vaddr[maybe_64K] |= GEN8_PDE_IPS_64K;
 706			drm_clflush_virt_range(vaddr, PAGE_SIZE);
 707			page_size = I915_GTT_PAGE_SIZE_64K;
 708
 709			/*
 710			 * We write all 4K page entries, even when using 64K
 711			 * pages. In order to verify that the HW isn't cheating
 712			 * by using the 4K PTE instead of the 64K PTE, we want
 713			 * to remove all the surplus entries. If the HW skipped
 714			 * the 64K PTE, it will read/write into the scratch page
 715			 * instead - which we detect as missing results during
 716			 * selftests.
 717			 */
 718			if (I915_SELFTEST_ONLY(vm->scrub_64K)) {
 719				u16 i;
 720
 721				encode = vm->scratch[0]->encode;
 722				vaddr = px_vaddr(i915_pt_entry(pd, maybe_64K));
 723
 724				for (i = 1; i < index; i += 16)
 725					memset64(vaddr + i, encode, 15);
 726
 727				drm_clflush_virt_range(vaddr, PAGE_SIZE);
 728			}
 729		}
 730
 731		vma_res->page_sizes_gtt |= page_size;
 732	} while (iter->sg && sg_dma_len(iter->sg));
 733}
 734
 735static void gen8_ppgtt_insert(struct i915_address_space *vm,
 736			      struct i915_vma_resource *vma_res,
 737			      unsigned int pat_index,
 738			      u32 flags)
 739{
 740	struct i915_ppgtt * const ppgtt = i915_vm_to_ppgtt(vm);
 741	struct sgt_dma iter = sgt_dma(vma_res);
 742
 743	if (vma_res->bi.page_sizes.sg > I915_GTT_PAGE_SIZE) {
 744		if (GRAPHICS_VER_FULL(vm->i915) >= IP_VER(12, 50))
 745			xehpsdv_ppgtt_insert_huge(vm, vma_res, &iter, pat_index, flags);
 746		else
 747			gen8_ppgtt_insert_huge(vm, vma_res, &iter, pat_index, flags);
 748	} else  {
 749		u64 idx = vma_res->start >> GEN8_PTE_SHIFT;
 750
 751		do {
 752			struct i915_page_directory * const pdp =
 753				gen8_pdp_for_page_index(vm, idx);
 754
 755			idx = gen8_ppgtt_insert_pte(ppgtt, pdp, &iter, idx,
 756						    pat_index, flags);
 757		} while (idx);
 758
 759		vma_res->page_sizes_gtt = I915_GTT_PAGE_SIZE;
 760	}
 761}
 762
 763static void gen8_ppgtt_insert_entry(struct i915_address_space *vm,
 764				    dma_addr_t addr,
 765				    u64 offset,
 766				    unsigned int pat_index,
 767				    u32 flags)
 768{
 769	u64 idx = offset >> GEN8_PTE_SHIFT;
 770	struct i915_page_directory * const pdp =
 771		gen8_pdp_for_page_index(vm, idx);
 772	struct i915_page_directory *pd =
 773		i915_pd_entry(pdp, gen8_pd_index(idx, 2));
 774	struct i915_page_table *pt = i915_pt_entry(pd, gen8_pd_index(idx, 1));
 775	gen8_pte_t *vaddr;
 776
 777	GEM_BUG_ON(pt->is_compact);
 778
 779	vaddr = px_vaddr(pt);
 780	vaddr[gen8_pd_index(idx, 0)] = vm->pte_encode(addr, pat_index, flags);
 781	drm_clflush_virt_range(&vaddr[gen8_pd_index(idx, 0)], sizeof(*vaddr));
 782}
 783
 784static void __xehpsdv_ppgtt_insert_entry_lm(struct i915_address_space *vm,
 785					    dma_addr_t addr,
 786					    u64 offset,
 787					    unsigned int pat_index,
 788					    u32 flags)
 789{
 790	u64 idx = offset >> GEN8_PTE_SHIFT;
 791	struct i915_page_directory * const pdp =
 792		gen8_pdp_for_page_index(vm, idx);
 793	struct i915_page_directory *pd =
 794		i915_pd_entry(pdp, gen8_pd_index(idx, 2));
 795	struct i915_page_table *pt = i915_pt_entry(pd, gen8_pd_index(idx, 1));
 796	gen8_pte_t *vaddr;
 797
 798	GEM_BUG_ON(!IS_ALIGNED(addr, SZ_64K));
 799	GEM_BUG_ON(!IS_ALIGNED(offset, SZ_64K));
 800
 801	/* XXX: we don't strictly need to use this layout */
 802
 803	if (!pt->is_compact) {
 804		vaddr = px_vaddr(pd);
 805		vaddr[gen8_pd_index(idx, 1)] |= GEN12_PDE_64K;
 806		pt->is_compact = true;
 807	}
 808
 809	vaddr = px_vaddr(pt);
 810	vaddr[gen8_pd_index(idx, 0) / 16] = vm->pte_encode(addr, pat_index, flags);
 811}
 812
 813static void xehpsdv_ppgtt_insert_entry(struct i915_address_space *vm,
 814				       dma_addr_t addr,
 815				       u64 offset,
 816				       unsigned int pat_index,
 817				       u32 flags)
 818{
 819	if (flags & PTE_LM)
 820		return __xehpsdv_ppgtt_insert_entry_lm(vm, addr, offset,
 821						       pat_index, flags);
 822
 823	return gen8_ppgtt_insert_entry(vm, addr, offset, pat_index, flags);
 824}
 825
 826static int gen8_init_scratch(struct i915_address_space *vm)
 827{
 828	u32 pte_flags;
 829	int ret;
 830	int i;
 831
 832	/*
 833	 * If everybody agrees to not to write into the scratch page,
 834	 * we can reuse it for all vm, keeping contexts and processes separate.
 835	 */
 836	if (vm->has_read_only && vm->gt->vm && !i915_is_ggtt(vm->gt->vm)) {
 837		struct i915_address_space *clone = vm->gt->vm;
 838
 839		GEM_BUG_ON(!clone->has_read_only);
 840
 841		vm->scratch_order = clone->scratch_order;
 842		for (i = 0; i <= vm->top; i++)
 843			vm->scratch[i] = i915_gem_object_get(clone->scratch[i]);
 844
 845		return 0;
 846	}
 847
 848	ret = setup_scratch_page(vm);
 849	if (ret)
 850		return ret;
 851
 852	pte_flags = vm->has_read_only;
 853	if (i915_gem_object_is_lmem(vm->scratch[0]))
 854		pte_flags |= PTE_LM;
 855
 856	vm->scratch[0]->encode =
 857		vm->pte_encode(px_dma(vm->scratch[0]),
 858			       i915_gem_get_pat_index(vm->i915,
 859						      I915_CACHE_NONE),
 860			       pte_flags);
 861
 862	for (i = 1; i <= vm->top; i++) {
 863		struct drm_i915_gem_object *obj;
 864
 865		obj = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K);
 866		if (IS_ERR(obj)) {
 867			ret = PTR_ERR(obj);
 868			goto free_scratch;
 869		}
 870
 871		ret = map_pt_dma(vm, obj);
 872		if (ret) {
 873			i915_gem_object_put(obj);
 874			goto free_scratch;
 875		}
 876
 877		fill_px(obj, vm->scratch[i - 1]->encode);
 878		obj->encode = gen8_pde_encode(px_dma(obj), I915_CACHE_NONE);
 879
 880		vm->scratch[i] = obj;
 881	}
 882
 883	return 0;
 884
 885free_scratch:
 886	while (i--)
 887		i915_gem_object_put(vm->scratch[i]);
 888	vm->scratch[0] = NULL;
 889	return ret;
 890}
 891
 892static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt)
 893{
 894	struct i915_address_space *vm = &ppgtt->vm;
 895	struct i915_page_directory *pd = ppgtt->pd;
 896	unsigned int idx;
 897
 898	GEM_BUG_ON(vm->top != 2);
 899	GEM_BUG_ON(gen8_pd_top_count(vm) != GEN8_3LVL_PDPES);
 900
 901	for (idx = 0; idx < GEN8_3LVL_PDPES; idx++) {
 902		struct i915_page_directory *pde;
 903		int err;
 904
 905		pde = alloc_pd(vm);
 906		if (IS_ERR(pde))
 907			return PTR_ERR(pde);
 908
 909		err = map_pt_dma(vm, pde->pt.base);
 910		if (err) {
 911			free_pd(vm, pde);
 912			return err;
 913		}
 914
 915		fill_px(pde, vm->scratch[1]->encode);
 916		set_pd_entry(pd, idx, pde);
 917		atomic_inc(px_used(pde)); /* keep pinned */
 918	}
 919	wmb();
 920
 921	return 0;
 922}
 923
 924static struct i915_page_directory *
 925gen8_alloc_top_pd(struct i915_address_space *vm)
 926{
 927	const unsigned int count = gen8_pd_top_count(vm);
 928	struct i915_page_directory *pd;
 929	int err;
 930
 931	GEM_BUG_ON(count > I915_PDES);
 932
 933	pd = __alloc_pd(count);
 934	if (unlikely(!pd))
 935		return ERR_PTR(-ENOMEM);
 936
 937	pd->pt.base = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K);
 938	if (IS_ERR(pd->pt.base)) {
 939		err = PTR_ERR(pd->pt.base);
 940		pd->pt.base = NULL;
 941		goto err_pd;
 942	}
 943
 944	err = map_pt_dma(vm, pd->pt.base);
 945	if (err)
 946		goto err_pd;
 947
 948	fill_page_dma(px_base(pd), vm->scratch[vm->top]->encode, count);
 949	atomic_inc(px_used(pd)); /* mark as pinned */
 950	return pd;
 951
 952err_pd:
 953	free_pd(vm, pd);
 954	return ERR_PTR(err);
 955}
 956
 957static int gen8_init_rsvd(struct i915_address_space *vm)
 958{
 959	struct drm_i915_private *i915 = vm->i915;
 960	struct drm_i915_gem_object *obj;
 961	struct i915_vma *vma;
 962	int ret;
 963
 964	if (!intel_gt_needs_wa_16018031267(vm->gt))
 965		return 0;
 966
 967	/* The memory will be used only by GPU. */
 968	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE,
 969					  I915_BO_ALLOC_VOLATILE |
 970					  I915_BO_ALLOC_GPU_ONLY);
 971	if (IS_ERR(obj))
 972		obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
 973	if (IS_ERR(obj))
 974		return PTR_ERR(obj);
 975
 976	vma = i915_vma_instance(obj, vm, NULL);
 977	if (IS_ERR(vma)) {
 978		ret = PTR_ERR(vma);
 979		goto unref;
 980	}
 981
 982	ret = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_HIGH);
 983	if (ret)
 984		goto unref;
 985
 986	vm->rsvd.vma = i915_vma_make_unshrinkable(vma);
 987	vm->rsvd.obj = obj;
 988	vm->total -= vma->node.size;
 989	return 0;
 990unref:
 991	i915_gem_object_put(obj);
 992	return ret;
 993}
 994
 995/*
 996 * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
 997 * with a net effect resembling a 2-level page table in normal x86 terms. Each
 998 * PDP represents 1GB of memory 4 * 512 * 512 * 4096 = 4GB legacy 32b address
 999 * space.
1000 *
1001 */
1002struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt,
1003				     unsigned long lmem_pt_obj_flags)
1004{
1005	struct i915_page_directory *pd;
1006	struct i915_ppgtt *ppgtt;
1007	int err;
1008
1009	ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
1010	if (!ppgtt)
1011		return ERR_PTR(-ENOMEM);
1012
1013	ppgtt_init(ppgtt, gt, lmem_pt_obj_flags);
1014	ppgtt->vm.top = i915_vm_is_4lvl(&ppgtt->vm) ? 3 : 2;
1015	ppgtt->vm.pd_shift = ilog2(SZ_4K * SZ_4K / sizeof(gen8_pte_t));
1016
1017	/*
1018	 * From bdw, there is hw support for read-only pages in the PPGTT.
1019	 *
1020	 * Gen11 has HSDES#:1807136187 unresolved. Disable ro support
1021	 * for now.
1022	 *
1023	 * Gen12 has inherited the same read-only fault issue from gen11.
1024	 */
1025	ppgtt->vm.has_read_only = !IS_GRAPHICS_VER(gt->i915, 11, 12);
1026
1027	if (HAS_LMEM(gt->i915))
1028		ppgtt->vm.alloc_pt_dma = alloc_pt_lmem;
1029	else
1030		ppgtt->vm.alloc_pt_dma = alloc_pt_dma;
1031
1032	/*
1033	 * Using SMEM here instead of LMEM has the advantage of not reserving
1034	 * high performance memory for a "never" used filler page. It also
1035	 * removes the device access that would be required to initialise the
1036	 * scratch page, reducing pressure on an even scarcer resource.
1037	 */
1038	ppgtt->vm.alloc_scratch_dma = alloc_pt_dma;
1039
1040	if (GRAPHICS_VER(gt->i915) >= 12)
1041		ppgtt->vm.pte_encode = gen12_pte_encode;
1042	else
1043		ppgtt->vm.pte_encode = gen8_pte_encode;
1044
1045	ppgtt->vm.bind_async_flags = I915_VMA_LOCAL_BIND;
1046	ppgtt->vm.insert_entries = gen8_ppgtt_insert;
1047	if (HAS_64K_PAGES(gt->i915))
1048		ppgtt->vm.insert_page = xehpsdv_ppgtt_insert_entry;
1049	else
1050		ppgtt->vm.insert_page = gen8_ppgtt_insert_entry;
1051	ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc;
1052	ppgtt->vm.clear_range = gen8_ppgtt_clear;
1053	ppgtt->vm.foreach = gen8_ppgtt_foreach;
1054	ppgtt->vm.cleanup = gen8_ppgtt_cleanup;
1055
1056	err = gen8_init_scratch(&ppgtt->vm);
1057	if (err)
1058		goto err_put;
1059
1060	pd = gen8_alloc_top_pd(&ppgtt->vm);
1061	if (IS_ERR(pd)) {
1062		err = PTR_ERR(pd);
1063		goto err_put;
1064	}
1065	ppgtt->pd = pd;
1066
1067	if (!i915_vm_is_4lvl(&ppgtt->vm)) {
1068		err = gen8_preallocate_top_level_pdp(ppgtt);
1069		if (err)
1070			goto err_put;
1071	}
1072
1073	if (intel_vgpu_active(gt->i915))
1074		gen8_ppgtt_notify_vgt(ppgtt, true);
1075
1076	err = gen8_init_rsvd(&ppgtt->vm);
1077	if (err)
1078		goto err_put;
1079
1080	return ppgtt;
1081
1082err_put:
1083	i915_vm_put(&ppgtt->vm);
1084	return ERR_PTR(err);
1085}