FILE
vmmgp100.c
File preview with syntax highlighting.
linux-6.19.14/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
1/* 2 * Copyright 2017 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22#include "vmm.h" 23 24#include <subdev/fb.h> 25#include <subdev/timer.h> 26#include <engine/gr.h> 27 28#include <nvif/ifc00d.h> 29#include <nvif/unpack.h> 30 31static void 32gp100_vmm_pfn_unmap(struct nvkm_vmm *vmm, 33 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) 34{ 35 struct device *dev = vmm->mmu->subdev.device->dev; 36 dma_addr_t addr; 37 38 nvkm_kmap(pt->memory); 39 while (ptes--) { 40 u32 datalo = nvkm_ro32(pt->memory, pt->base + ptei * 8 + 0); 41 u32 datahi = nvkm_ro32(pt->memory, pt->base + ptei * 8 + 4); 42 u64 data = (u64)datahi << 32 | datalo; 43 if ((data & (3ULL << 1)) != 0) { 44 addr = (data >> 8) << 12; 45 dma_unmap_page(dev, addr, PAGE_SIZE, DMA_BIDIRECTIONAL); 46 } 47 ptei++; 48 } 49 nvkm_done(pt->memory); 50} 51 52static bool 53gp100_vmm_pfn_clear(struct nvkm_vmm *vmm, 54 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) 55{ 56 bool dma = false; 57 nvkm_kmap(pt->memory); 58 while (ptes--) { 59 u32 datalo = nvkm_ro32(pt->memory, pt->base + ptei * 8 + 0); 60 u32 datahi = nvkm_ro32(pt->memory, pt->base + ptei * 8 + 4); 61 u64 data = (u64)datahi << 32 | datalo; 62 if ((data & BIT_ULL(0)) && (data & (3ULL << 1)) != 0) { 63 VMM_WO064(pt, vmm, ptei * 8, data & ~BIT_ULL(0)); 64 dma = true; 65 } 66 ptei++; 67 } 68 nvkm_done(pt->memory); 69 return dma; 70} 71 72static void 73gp100_vmm_pgt_pfn(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, 74 u32 ptei, u32 ptes, struct nvkm_vmm_map *map) 75{ 76 struct device *dev = vmm->mmu->subdev.device->dev; 77 dma_addr_t addr; 78 79 nvkm_kmap(pt->memory); 80 for (; ptes; ptes--, map->pfn++) { 81 u64 data = 0; 82 83 if (!(*map->pfn & NVKM_VMM_PFN_V)) 84 continue; 85 86 if (!(*map->pfn & NVKM_VMM_PFN_W)) 87 data |= BIT_ULL(6); /* RO. */ 88 89 if (!(*map->pfn & NVKM_VMM_PFN_A)) 90 data |= BIT_ULL(7); /* Atomic disable. */ 91 92 if (!(*map->pfn & NVKM_VMM_PFN_VRAM)) { 93 addr = *map->pfn >> NVKM_VMM_PFN_ADDR_SHIFT; 94 addr = dma_map_page(dev, pfn_to_page(addr), 0, 95 PAGE_SIZE, DMA_BIDIRECTIONAL); 96 if (!WARN_ON(dma_mapping_error(dev, addr))) { 97 data |= addr >> 4; 98 data |= 2ULL << 1; /* SYSTEM_COHERENT_MEMORY. */ 99 data |= BIT_ULL(3); /* VOL. */ 100 data |= BIT_ULL(0); /* VALID. */ 101 } 102 } else { 103 data |= (*map->pfn & NVKM_VMM_PFN_ADDR) >> 4; 104 data |= BIT_ULL(0); /* VALID. */ 105 } 106 107 VMM_WO064(pt, vmm, ptei++ * 8, data); 108 } 109 nvkm_done(pt->memory); 110} 111 112static inline u64 113gp100_vmm_comptag_nr(u64 size) 114{ 115 return size >> 16; /* One comptag per 64KiB VRAM. */ 116} 117 118static inline u64 119gp100_vmm_pte_comptagline_base(u64 addr) 120{ 121 /* RM allocates enough comptags for all of VRAM, so use a 1:1 mapping. */ 122 return (1 + gp100_vmm_comptag_nr(addr)) << 36; /* NV_MMU_VER2_PTE_COMPTAGLINE */ 123} 124 125static inline u64 126gp100_vmm_pte_comptagline_incr(u32 page_size) 127{ 128 return gp100_vmm_comptag_nr(page_size) << 36; /* NV_MMU_VER2_PTE_COMPTAGLINE */ 129} 130 131static inline void 132gp100_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, 133 u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr) 134{ 135 u64 data = (addr >> 4) | map->type; 136 137 if (map->ctag) 138 data |= gp100_vmm_pte_comptagline_base(addr); 139 140 while (ptes--) { 141 VMM_WO064(pt, vmm, ptei++ * 8, data); 142 data += map->next; 143 } 144} 145 146static void 147gp100_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, 148 u32 ptei, u32 ptes, struct nvkm_vmm_map *map) 149{ 150 VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, gp100_vmm_pgt_pte); 151} 152 153static void 154gp100_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, 155 u32 ptei, u32 ptes, struct nvkm_vmm_map *map) 156{ 157 if (map->page->shift == PAGE_SHIFT) { 158 VMM_SPAM(vmm, "DMAA %08x %08x PTE(s)", ptei, ptes); 159 nvkm_kmap(pt->memory); 160 while (ptes--) { 161 const u64 data = (*map->dma++ >> 4) | map->type; 162 VMM_WO064(pt, vmm, ptei++ * 8, data); 163 } 164 nvkm_done(pt->memory); 165 return; 166 } 167 168 VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, gp100_vmm_pgt_pte); 169} 170 171static void 172gp100_vmm_pgt_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, 173 u32 ptei, u32 ptes, struct nvkm_vmm_map *map) 174{ 175 VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gp100_vmm_pgt_pte); 176} 177 178static void 179gp100_vmm_pgt_sparse(struct nvkm_vmm *vmm, 180 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) 181{ 182 /* VALID_FALSE + VOL tells the MMU to treat the PTE as sparse. */ 183 VMM_FO064(pt, vmm, ptei * 8, BIT_ULL(3) /* VOL. */, ptes); 184} 185 186static const struct nvkm_vmm_desc_func 187gp100_vmm_desc_spt = { 188 .unmap = gf100_vmm_pgt_unmap, 189 .sparse = gp100_vmm_pgt_sparse, 190 .mem = gp100_vmm_pgt_mem, 191 .dma = gp100_vmm_pgt_dma, 192 .sgl = gp100_vmm_pgt_sgl, 193 .pfn = gp100_vmm_pgt_pfn, 194 .pfn_clear = gp100_vmm_pfn_clear, 195 .pfn_unmap = gp100_vmm_pfn_unmap, 196}; 197 198static void 199gp100_vmm_lpt_invalid(struct nvkm_vmm *vmm, 200 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) 201{ 202 /* VALID_FALSE + PRIV tells the MMU to ignore corresponding SPTEs. */ 203 VMM_FO064(pt, vmm, ptei * 8, BIT_ULL(5) /* PRIV. */, ptes); 204} 205 206static const struct nvkm_vmm_desc_func 207gp100_vmm_desc_lpt = { 208 .invalid = gp100_vmm_lpt_invalid, 209 .unmap = gf100_vmm_pgt_unmap, 210 .sparse = gp100_vmm_pgt_sparse, 211 .mem = gp100_vmm_pgt_mem, 212}; 213 214static inline void 215gp100_vmm_pd0_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, 216 u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr) 217{ 218 u64 data = (addr >> 4) | map->type; 219 220 if (map->ctag) 221 data |= gp100_vmm_pte_comptagline_base(addr); 222 223 while (ptes--) { 224 VMM_WO128(pt, vmm, ptei++ * 0x10, data, 0ULL); 225 data += map->next; 226 } 227} 228 229static void 230gp100_vmm_pd0_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, 231 u32 ptei, u32 ptes, struct nvkm_vmm_map *map) 232{ 233 VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gp100_vmm_pd0_pte); 234} 235 236static inline bool 237gp100_vmm_pde(struct nvkm_mmu_pt *pt, u64 *data) 238{ 239 switch (nvkm_memory_target(pt->memory)) { 240 case NVKM_MEM_TARGET_VRAM: *data |= 1ULL << 1; break; 241 case NVKM_MEM_TARGET_HOST: *data |= 2ULL << 1; 242 *data |= BIT_ULL(3); /* VOL. */ 243 break; 244 case NVKM_MEM_TARGET_NCOH: *data |= 3ULL << 1; break; 245 default: 246 WARN_ON(1); 247 return false; 248 } 249 *data |= pt->addr >> 4; 250 return true; 251} 252 253static void 254gp100_vmm_pd0_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei) 255{ 256 struct nvkm_vmm_pt *pgt = pgd->pde[pdei]; 257 struct nvkm_mmu_pt *pd = pgd->pt[0]; 258 u64 data[2] = {}; 259 260 if (pgt->pt[0] && !gp100_vmm_pde(pgt->pt[0], &data[0])) 261 return; 262 if (pgt->pt[1] && !gp100_vmm_pde(pgt->pt[1], &data[1])) 263 return; 264 265 nvkm_kmap(pd->memory); 266 VMM_WO128(pd, vmm, pdei * 0x10, data[0], data[1]); 267 nvkm_done(pd->memory); 268} 269 270static void 271gp100_vmm_pd0_sparse(struct nvkm_vmm *vmm, 272 struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes) 273{ 274 /* VALID_FALSE + VOL_BIG tells the MMU to treat the PDE as sparse. */ 275 VMM_FO128(pt, vmm, pdei * 0x10, BIT_ULL(3) /* VOL_BIG. */, 0ULL, pdes); 276} 277 278static void 279gp100_vmm_pd0_unmap(struct nvkm_vmm *vmm, 280 struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes) 281{ 282 VMM_FO128(pt, vmm, pdei * 0x10, 0ULL, 0ULL, pdes); 283} 284 285static void 286gp100_vmm_pd0_pfn_unmap(struct nvkm_vmm *vmm, 287 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) 288{ 289 struct device *dev = vmm->mmu->subdev.device->dev; 290 dma_addr_t addr; 291 292 nvkm_kmap(pt->memory); 293 while (ptes--) { 294 u32 datalo = nvkm_ro32(pt->memory, pt->base + ptei * 16 + 0); 295 u32 datahi = nvkm_ro32(pt->memory, pt->base + ptei * 16 + 4); 296 u64 data = (u64)datahi << 32 | datalo; 297 298 if ((data & (3ULL << 1)) != 0) { 299 addr = (data >> 8) << 12; 300 dma_unmap_page(dev, addr, 1UL << 21, DMA_BIDIRECTIONAL); 301 } 302 ptei++; 303 } 304 nvkm_done(pt->memory); 305} 306 307static bool 308gp100_vmm_pd0_pfn_clear(struct nvkm_vmm *vmm, 309 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) 310{ 311 bool dma = false; 312 313 nvkm_kmap(pt->memory); 314 while (ptes--) { 315 u32 datalo = nvkm_ro32(pt->memory, pt->base + ptei * 16 + 0); 316 u32 datahi = nvkm_ro32(pt->memory, pt->base + ptei * 16 + 4); 317 u64 data = (u64)datahi << 32 | datalo; 318 319 if ((data & BIT_ULL(0)) && (data & (3ULL << 1)) != 0) { 320 VMM_WO064(pt, vmm, ptei * 16, data & ~BIT_ULL(0)); 321 dma = true; 322 } 323 ptei++; 324 } 325 nvkm_done(pt->memory); 326 return dma; 327} 328 329static void 330gp100_vmm_pd0_pfn(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, 331 u32 ptei, u32 ptes, struct nvkm_vmm_map *map) 332{ 333 struct device *dev = vmm->mmu->subdev.device->dev; 334 dma_addr_t addr; 335 336 nvkm_kmap(pt->memory); 337 for (; ptes; ptes--, map->pfn++) { 338 u64 data = 0; 339 340 if (!(*map->pfn & NVKM_VMM_PFN_V)) 341 continue; 342 343 if (!(*map->pfn & NVKM_VMM_PFN_W)) 344 data |= BIT_ULL(6); /* RO. */ 345 346 if (!(*map->pfn & NVKM_VMM_PFN_A)) 347 data |= BIT_ULL(7); /* Atomic disable. */ 348 349 if (!(*map->pfn & NVKM_VMM_PFN_VRAM)) { 350 addr = *map->pfn >> NVKM_VMM_PFN_ADDR_SHIFT; 351 addr = dma_map_page(dev, pfn_to_page(addr), 0, 352 1UL << 21, DMA_BIDIRECTIONAL); 353 if (!WARN_ON(dma_mapping_error(dev, addr))) { 354 data |= addr >> 4; 355 data |= 2ULL << 1; /* SYSTEM_COHERENT_MEMORY. */ 356 data |= BIT_ULL(3); /* VOL. */ 357 data |= BIT_ULL(0); /* VALID. */ 358 } 359 } else { 360 data |= (*map->pfn & NVKM_VMM_PFN_ADDR) >> 4; 361 data |= BIT_ULL(0); /* VALID. */ 362 } 363 364 VMM_WO064(pt, vmm, ptei++ * 16, data); 365 } 366 nvkm_done(pt->memory); 367} 368 369static const struct nvkm_vmm_desc_func 370gp100_vmm_desc_pd0 = { 371 .unmap = gp100_vmm_pd0_unmap, 372 .sparse = gp100_vmm_pd0_sparse, 373 .pde = gp100_vmm_pd0_pde, 374 .mem = gp100_vmm_pd0_mem, 375 .pfn = gp100_vmm_pd0_pfn, 376 .pfn_clear = gp100_vmm_pd0_pfn_clear, 377 .pfn_unmap = gp100_vmm_pd0_pfn_unmap, 378}; 379 380static void 381gp100_vmm_pd1_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei) 382{ 383 struct nvkm_vmm_pt *pgt = pgd->pde[pdei]; 384 struct nvkm_mmu_pt *pd = pgd->pt[0]; 385 u64 data = 0; 386 387 if (!gp100_vmm_pde(pgt->pt[0], &data)) 388 return; 389 390 nvkm_kmap(pd->memory); 391 VMM_WO064(pd, vmm, pdei * 8, data); 392 nvkm_done(pd->memory); 393} 394 395static const struct nvkm_vmm_desc_func 396gp100_vmm_desc_pd1 = { 397 .unmap = gf100_vmm_pgt_unmap, 398 .sparse = gp100_vmm_pgt_sparse, 399 .pde = gp100_vmm_pd1_pde, 400}; 401 402const struct nvkm_vmm_desc 403gp100_vmm_desc_16[] = { 404 { LPT, 5, 8, 0x0100, &gp100_vmm_desc_lpt }, 405 { PGD, 8, 16, 0x1000, &gp100_vmm_desc_pd0 }, 406 { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 }, 407 { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 }, 408 { PGD, 2, 8, 0x1000, &gp100_vmm_desc_pd1 }, 409 {} 410}; 411 412const struct nvkm_vmm_desc 413gp100_vmm_desc_12[] = { 414 { SPT, 9, 8, 0x1000, &gp100_vmm_desc_spt }, 415 { PGD, 8, 16, 0x1000, &gp100_vmm_desc_pd0 }, 416 { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 }, 417 { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 }, 418 { PGD, 2, 8, 0x1000, &gp100_vmm_desc_pd1 }, 419 {} 420}; 421 422int 423gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, 424 struct nvkm_vmm_map *map) 425{ 426 const enum nvkm_memory_target target = nvkm_memory_target(map->memory); 427 const struct nvkm_vmm_page *page = map->page; 428 union { 429 struct gp100_vmm_map_vn vn; 430 struct gp100_vmm_map_v0 v0; 431 } *args = argv; 432 u8 kind, kind_inv, priv, ro, vol; 433 int kindn, aper, ret = -ENOSYS; 434 const u8 *kindm; 435 436 map->next = (1ULL << page->shift) >> 4; 437 map->type = 0; 438 439 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { 440 vol = !!args->v0.vol; 441 ro = !!args->v0.ro; 442 priv = !!args->v0.priv; 443 kind = args->v0.kind; 444 } else 445 if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { 446 vol = target == NVKM_MEM_TARGET_HOST; 447 ro = 0; 448 priv = 0; 449 kind = 0x00; 450 } else { 451 VMM_DEBUG(vmm, "args"); 452 return ret; 453 } 454 455 if (vmm->func->valid2) 456 return vmm->func->valid2(vmm, ro, priv, kind, 0, map); 457 458 aper = vmm->func->aper(target); 459 if (WARN_ON(aper < 0)) 460 return aper; 461 462 kindm = vmm->mmu->func->kind(vmm->mmu, &kindn, &kind_inv); 463 if (kind >= kindn || kindm[kind] == kind_inv) { 464 VMM_DEBUG(vmm, "kind %02x", kind); 465 return -EINVAL; 466 } 467 468 /* Handle compression. */ 469 if (kindm[kind] != kind) { 470 struct nvkm_device *device = vmm->mmu->subdev.device; 471 472 /* Compression is only supported when using GSP-RM, as 473 * PMU firmware is required in order to initialise the 474 * compbit backing store. 475 */ 476 if (nvkm_gsp_rm(device->gsp)) { 477 /* Turing GPUs require PTE_COMPTAGLINE to be filled, 478 * in addition to specifying a compressed kind. 479 */ 480 if (device->card_type < GA100) { 481 map->ctag = gp100_vmm_pte_comptagline_incr(1 << map->page->shift); 482 map->next |= map->ctag; 483 } 484 } else { 485 /* Revert to non-compressed kind. */ 486 kind = kindm[kind]; 487 } 488 } 489 490 map->type |= BIT(0); 491 map->type |= (u64)aper << 1; 492 map->type |= (u64) vol << 3; 493 map->type |= (u64)priv << 5; 494 map->type |= (u64) ro << 6; 495 map->type |= (u64)kind << 56; 496 return 0; 497} 498 499static int 500gp100_vmm_fault_cancel(struct nvkm_vmm *vmm, void *argv, u32 argc) 501{ 502 struct nvkm_device *device = vmm->mmu->subdev.device; 503 union { 504 struct gp100_vmm_fault_cancel_v0 v0; 505 } *args = argv; 506 int ret = -ENOSYS; 507 u32 aper; 508 509 if ((ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) 510 return ret; 511 512 /* Translate MaxwellFaultBufferA instance pointer to the same 513 * format as the NV_GR_FECS_CURRENT_CTX register. 514 */ 515 aper = (args->v0.inst >> 8) & 3; 516 args->v0.inst >>= 12; 517 args->v0.inst |= aper << 28; 518 args->v0.inst |= 0x80000000; 519 520 if (!WARN_ON(nvkm_gr_ctxsw_pause(device))) { 521 if (nvkm_gr_ctxsw_inst(device) == args->v0.inst) { 522 gf100_vmm_invalidate(vmm, 0x0000001b 523 /* CANCEL_TARGETED. */ | 524 (args->v0.hub << 20) | 525 (args->v0.gpc << 15) | 526 (args->v0.client << 9)); 527 } 528 WARN_ON(nvkm_gr_ctxsw_resume(device)); 529 } 530 531 return 0; 532} 533 534static int 535gp100_vmm_fault_replay(struct nvkm_vmm *vmm, void *argv, u32 argc) 536{ 537 union { 538 struct gp100_vmm_fault_replay_vn vn; 539 } *args = argv; 540 int ret = -ENOSYS; 541 542 if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { 543 gf100_vmm_invalidate(vmm, 0x0000000b); /* REPLAY_GLOBAL. */ 544 } 545 546 return ret; 547} 548 549int 550gp100_vmm_mthd(struct nvkm_vmm *vmm, 551 struct nvkm_client *client, u32 mthd, void *argv, u32 argc) 552{ 553 switch (mthd) { 554 case GP100_VMM_VN_FAULT_REPLAY: 555 return gp100_vmm_fault_replay(vmm, argv, argc); 556 case GP100_VMM_VN_FAULT_CANCEL: 557 return gp100_vmm_fault_cancel(vmm, argv, argc); 558 default: 559 break; 560 } 561 return -EINVAL; 562} 563 564void 565gp100_vmm_invalidate_pdb(struct nvkm_vmm *vmm, u64 addr) 566{ 567 struct nvkm_device *device = vmm->mmu->subdev.device; 568 nvkm_wr32(device, 0x100cb8, lower_32_bits(addr)); 569 nvkm_wr32(device, 0x100cec, upper_32_bits(addr)); 570} 571 572void 573gp100_vmm_flush(struct nvkm_vmm *vmm, int depth) 574{ 575 u32 type = 0; 576 if (atomic_read(&vmm->engref[NVKM_SUBDEV_BAR])) 577 type |= 0x00000004; /* HUB_ONLY */ 578 type |= 0x00000001; /* PAGE_ALL */ 579 gf100_vmm_invalidate(vmm, type); 580} 581 582int 583gp100_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst) 584{ 585 u64 base = BIT_ULL(10) /* VER2 */ | BIT_ULL(11) /* 64KiB */; 586 if (vmm->replay) { 587 base |= BIT_ULL(4); /* FAULT_REPLAY_TEX */ 588 base |= BIT_ULL(5); /* FAULT_REPLAY_GCC */ 589 } 590 return gf100_vmm_join_(vmm, inst, base); 591} 592 593static const struct nvkm_vmm_func 594gp100_vmm = { 595 .join = gp100_vmm_join, 596 .part = gf100_vmm_part, 597 .aper = gf100_vmm_aper, 598 .valid = gp100_vmm_valid, 599 .flush = gp100_vmm_flush, 600 .mthd = gp100_vmm_mthd, 601 .invalidate_pdb = gp100_vmm_invalidate_pdb, 602 .page = { 603 { 47, &gp100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx }, 604 { 38, &gp100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx }, 605 { 29, &gp100_vmm_desc_16[2], NVKM_VMM_PAGE_Sxxx }, 606 { 21, &gp100_vmm_desc_16[1], NVKM_VMM_PAGE_SVxx }, 607 { 16, &gp100_vmm_desc_16[0], NVKM_VMM_PAGE_SVxx }, 608 { 12, &gp100_vmm_desc_12[0], NVKM_VMM_PAGE_SVHx }, 609 {} 610 } 611}; 612 613int 614gp100_vmm_new_(const struct nvkm_vmm_func *func, 615 struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 616 void *argv, u32 argc, struct lock_class_key *key, 617 const char *name, struct nvkm_vmm **pvmm) 618{ 619 union { 620 struct gp100_vmm_vn vn; 621 struct gp100_vmm_v0 v0; 622 } *args = argv; 623 int ret = -ENOSYS; 624 bool replay; 625 626 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { 627 replay = args->v0.fault_replay != 0; 628 } else 629 if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { 630 replay = false; 631 } else 632 return ret; 633 634 ret = nvkm_vmm_new_(func, mmu, 0, managed, addr, size, key, name, pvmm); 635 if (ret) 636 return ret; 637 638 (*pvmm)->replay = replay; 639 return 0; 640} 641 642int 643gp100_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 644 void *argv, u32 argc, struct lock_class_key *key, 645 const char *name, struct nvkm_vmm **pvmm) 646{ 647 return gp100_vmm_new_(&gp100_vmm, mmu, managed, addr, size, 648 argv, argc, key, name, pvmm); 649}
~/
Read-only file preview.