drm/nouveau/mmu/gp100-: support vmms with gcc/tex replayable faults enabled
authorBen Skeggs <bskeggs@redhat.com>
Tue, 8 May 2018 10:39:48 +0000 (20:39 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 19 Feb 2019 23:00:00 +0000 (09:00 +1000)
Some GPU units are capable of supporting "replayable" page faults, where
the execution unit will wait for SW to fixup GPU page tables rather than
triggering a channel-fatal fault.

This feature isn't useful (it's harmful, even) unless something like HMM
is being used to manage events appearing in the replayable fault buffer,
so, it's disabled by default.

This commit allows a client to request it be enabled.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvif/ifc00d.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp100.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gv100.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp10b.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgv100.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c

index 33ff6c7916431355f2b95fd3144022e77cf8fe3b..4cabd613a2805b56a57893955cf08b62149f5225 100644 (file)
@@ -6,6 +6,12 @@ struct gp100_vmm_vn {
        /* nvif_vmm_vX ... */
 };
 
+struct gp100_vmm_v0 {
+       /* nvif_vmm_vX ... */
+       __u8  version;
+       __u8  fault_replay;
+};
+
 struct gp100_vmm_map_vn {
        /* nvif_vmm_map_vX ... */
 };
index 8b117cbc853832400f982c9c8a4a6e35b18a2e5b..28ade86f74c5ff37c0c3a01fcb50a794d78fc63d 100644 (file)
@@ -45,6 +45,8 @@ struct nvkm_vmm {
 
        dma_addr_t null;
        void *nullp;
+
+       bool replay;
 };
 
 int nvkm_vmm_new(struct nvkm_device *, u64 addr, u64 size, void *argv, u32 argc,
index 651b8805c67c07d1bd842b0d0157c8f4d0e1fb3a..65cb9d28e60e2bac860cc6e8d155343a267a6c98 100644 (file)
@@ -31,7 +31,7 @@ gp100_mmu = {
        .dma_bits = 47,
        .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
        .mem = {{ -1,  0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map },
-       .vmm = {{ -1, -1, NVIF_CLASS_VMM_GP100}, gp100_vmm_new },
+       .vmm = {{ -1,  0, NVIF_CLASS_VMM_GP100}, gp100_vmm_new },
        .kind = gm200_mmu_kind,
        .kind_sys = true,
 };
index 3bd3db31e0bbbc8f9b50b54217d040258ad7beeb..0a50be9a785ae1042d405614ee4b121922120acd 100644 (file)
@@ -31,7 +31,7 @@ gp10b_mmu = {
        .dma_bits = 47,
        .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
        .mem = {{ -1, -1, NVIF_CLASS_MEM_GF100}, .umap = gf100_mem_map },
-       .vmm = {{ -1, -1, NVIF_CLASS_VMM_GP100}, gp10b_vmm_new },
+       .vmm = {{ -1,  0, NVIF_CLASS_VMM_GP100}, gp10b_vmm_new },
        .kind = gm200_mmu_kind,
        .kind_sys = true,
 };
index f666cb57f69e2d282f6558fa47da88aef2c985f2..e0997eedd6d9c97aec00c72a79d1bdd8246f952f 100644 (file)
@@ -31,7 +31,7 @@ gv100_mmu = {
        .dma_bits = 47,
        .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
        .mem = {{ -1,  0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map },
-       .vmm = {{ -1, -1, NVIF_CLASS_VMM_GP100}, gv100_vmm_new },
+       .vmm = {{ -1,  0, NVIF_CLASS_VMM_GP100}, gv100_vmm_new },
        .kind = gm200_mmu_kind,
        .kind_sys = true,
 };
index e85f19fdc59774179fa9db7d0014a5149398585e..5e55ecbd8005558d0319d3b84457e55be78d0bc4 100644 (file)
@@ -220,6 +220,9 @@ int gm200_vmm_new_(const struct nvkm_vmm_func *, const struct nvkm_vmm_func *,
 int gm200_vmm_join_(struct nvkm_vmm *, struct nvkm_memory *, u64 base);
 int gm200_vmm_join(struct nvkm_vmm *, struct nvkm_memory *);
 
+int gp100_vmm_new_(const struct nvkm_vmm_func *,
+                  struct nvkm_mmu *, bool, u64, u64, void *, u32,
+                  struct lock_class_key *, const char *, struct nvkm_vmm **);
 int gp100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *);
 int gp100_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *);
 void gp100_vmm_flush(struct nvkm_vmm *, int);
index af427daf9077aba6b4d57583f294fa0b30d180cd..b4f519768d5e082b1b8c0754b12666656e5b730e 100644 (file)
@@ -476,7 +476,11 @@ gp100_vmm_flush(struct nvkm_vmm *vmm, int depth)
 int
 gp100_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
 {
-       const u64 base = BIT_ULL(10) /* VER2 */ | BIT_ULL(11); /* 64KiB */
+       u64 base = BIT_ULL(10) /* VER2 */ | BIT_ULL(11) /* 64KiB */;
+       if (vmm->replay) {
+               base |= BIT_ULL(4); /* FAULT_REPLAY_TEX */
+               base |= BIT_ULL(5); /* FAULT_REPLAY_GCC */
+       }
        return gf100_vmm_join_(vmm, inst, base);
 }
 
@@ -500,11 +504,40 @@ gp100_vmm = {
        }
 };
 
+int
+gp100_vmm_new_(const struct nvkm_vmm_func *func,
+              struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size,
+              void *argv, u32 argc, struct lock_class_key *key,
+              const char *name, struct nvkm_vmm **pvmm)
+{
+       union {
+               struct gp100_vmm_vn vn;
+               struct gp100_vmm_v0 v0;
+       } *args = argv;
+       int ret = -ENOSYS;
+       bool replay;
+
+       if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
+               replay = args->v0.fault_replay != 0;
+       } else
+       if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) {
+               replay = false;
+       } else
+               return ret;
+
+       ret = nvkm_vmm_new_(func, mmu, 0, managed, addr, size, key, name, pvmm);
+       if (ret)
+               return ret;
+
+       (*pvmm)->replay = replay;
+       return 0;
+}
+
 int
 gp100_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size,
              void *argv, u32 argc, struct lock_class_key *key,
              const char *name, struct nvkm_vmm **pvmm)
 {
-       return nv04_vmm_new_(&gp100_vmm, mmu, 0, managed, addr, size,
-                            argv, argc, key, name, pvmm);
+       return gp100_vmm_new_(&gp100_vmm, mmu, managed, addr, size,
+                             argv, argc, key, name, pvmm);
 }
index 317a83e40def930b06391cc474c570556e64e0ed..e081239afe58bdc68007eee5db7ef83abecc8ea5 100644 (file)
@@ -46,6 +46,6 @@ gp10b_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size,
              void *argv, u32 argc, struct lock_class_key *key,
              const char *name, struct nvkm_vmm **pvmm)
 {
-       return nv04_vmm_new_(&gp10b_vmm, mmu, 0, managed, addr, size,
-                            argv, argc, key, name, pvmm);
+       return gp100_vmm_new_(&gp10b_vmm, mmu, managed, addr, size,
+                             argv, argc, key, name, pvmm);
 }
index 172d685932d08ad2ab8d594534af918e8fa2b522..f0e21f63253afb3a7160dac94d72407b174926a2 100644 (file)
@@ -84,6 +84,6 @@ gv100_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size,
              void *argv, u32 argc, struct lock_class_key *key,
              const char *name, struct nvkm_vmm **pvmm)
 {
-       return nv04_vmm_new_(&gv100_vmm, mmu, 0, managed, addr, size,
-                            argv, argc, key, name, pvmm);
+       return gp100_vmm_new_(&gv100_vmm, mmu, managed, addr, size,
+                             argv, argc, key, name, pvmm);
 }
index 3bfef146dd1f73df3410936ca2ffd64177e45c6f..be91cffc3b52aa2733915bd29d037f5589addbb5 100644 (file)
@@ -73,6 +73,6 @@ tu102_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size,
              void *argv, u32 argc, struct lock_class_key *key,
              const char *name, struct nvkm_vmm **pvmm)
 {
-       return nv04_vmm_new_(&tu102_vmm, mmu, 0, managed, addr, size,
-                            argv, argc, key, name, pvmm);
+       return gp100_vmm_new_(&tu102_vmm, mmu, managed, addr, size,
+                             argv, argc, key, name, pvmm);
 }