|
21 | 21 | */ |
22 | 22 | #include "vmm.h" |
23 | 23 |
|
| 24 | +#include <core/client.h> |
24 | 25 | #include <subdev/fb.h> |
25 | 26 | #include <subdev/ltc.h> |
| 27 | +#include <subdev/timer.h> |
| 28 | +#include <engine/gr.h> |
26 | 29 |
|
27 | 30 | #include <nvif/ifc00d.h> |
28 | 31 | #include <nvif/unpack.h> |
@@ -384,6 +387,73 @@ gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, |
384 | 387 | return 0; |
385 | 388 | } |
386 | 389 |
|
| 390 | +static int |
| 391 | +gp100_vmm_fault_cancel(struct nvkm_vmm *vmm, void *argv, u32 argc) |
| 392 | +{ |
| 393 | + struct nvkm_device *device = vmm->mmu->subdev.device; |
| 394 | + union { |
| 395 | + struct gp100_vmm_fault_cancel_v0 v0; |
| 396 | + } *args = argv; |
| 397 | + int ret = -ENOSYS; |
| 398 | + u32 inst, aper; |
| 399 | + |
| 400 | + if ((ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) |
| 401 | + return ret; |
| 402 | + |
| 403 | + /* Translate MaxwellFaultBufferA instance pointer to the same |
| 404 | + * format as the NV_GR_FECS_CURRENT_CTX register. |
| 405 | + */ |
| 406 | + aper = (args->v0.inst >> 8) & 3; |
| 407 | + args->v0.inst >>= 12; |
| 408 | + args->v0.inst |= aper << 28; |
| 409 | + args->v0.inst |= 0x80000000; |
| 410 | + |
| 411 | + if (!WARN_ON(nvkm_gr_ctxsw_pause(device))) { |
| 412 | + if ((inst = nvkm_gr_ctxsw_inst(device)) == args->v0.inst) { |
| 413 | + gf100_vmm_invalidate(vmm, 0x0000001b |
| 414 | + /* CANCEL_TARGETED. */ | |
| 415 | + (args->v0.hub << 20) | |
| 416 | + (args->v0.gpc << 15) | |
| 417 | + (args->v0.client << 9)); |
| 418 | + } |
| 419 | + WARN_ON(nvkm_gr_ctxsw_resume(device)); |
| 420 | + } |
| 421 | + |
| 422 | + return 0; |
| 423 | +} |
| 424 | + |
| 425 | +static int |
| 426 | +gp100_vmm_fault_replay(struct nvkm_vmm *vmm, void *argv, u32 argc) |
| 427 | +{ |
| 428 | + union { |
| 429 | + struct gp100_vmm_fault_replay_vn vn; |
| 430 | + } *args = argv; |
| 431 | + int ret = -ENOSYS; |
| 432 | + |
| 433 | + if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { |
| 434 | + gf100_vmm_invalidate(vmm, 0x0000000b); /* REPLAY_GLOBAL. */ |
| 435 | + } |
| 436 | + |
| 437 | + return ret; |
| 438 | +} |
| 439 | + |
| 440 | +int |
| 441 | +gp100_vmm_mthd(struct nvkm_vmm *vmm, |
| 442 | + struct nvkm_client *client, u32 mthd, void *argv, u32 argc) |
| 443 | +{ |
| 444 | + if (client->super) { |
| 445 | + switch (mthd) { |
| 446 | + case GP100_VMM_VN_FAULT_REPLAY: |
| 447 | + return gp100_vmm_fault_replay(vmm, argv, argc); |
| 448 | + case GP100_VMM_VN_FAULT_CANCEL: |
| 449 | + return gp100_vmm_fault_cancel(vmm, argv, argc); |
| 450 | + default: |
| 451 | + break; |
| 452 | + } |
| 453 | + } |
| 454 | + return -EINVAL; |
| 455 | +} |
| 456 | + |
387 | 457 | void |
388 | 458 | gp100_vmm_invalidate_pdb(struct nvkm_vmm *vmm, u64 addr) |
389 | 459 | { |
@@ -417,6 +487,7 @@ gp100_vmm = { |
417 | 487 | .aper = gf100_vmm_aper, |
418 | 488 | .valid = gp100_vmm_valid, |
419 | 489 | .flush = gp100_vmm_flush, |
| 490 | + .mthd = gp100_vmm_mthd, |
420 | 491 | .invalidate_pdb = gp100_vmm_invalidate_pdb, |
421 | 492 | .page = { |
422 | 493 | { 47, &gp100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx }, |
|
0 commit comments