diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/mmu')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gh100.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/r535.c | 123 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgh100.c | 306 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c | 2 |
13 files changed, 353 insertions, 137 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild index 7ba35ea59c06..ea4848931540 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild @@ -15,8 +15,7 @@ nvkm-y += nvkm/subdev/mmu/gp100.o nvkm-y += nvkm/subdev/mmu/gp10b.o nvkm-y += nvkm/subdev/mmu/gv100.o nvkm-y += nvkm/subdev/mmu/tu102.o - -nvkm-y += nvkm/subdev/mmu/r535.o +nvkm-y += nvkm/subdev/mmu/gh100.o nvkm-y += nvkm/subdev/mmu/mem.o nvkm-y += nvkm/subdev/mmu/memnv04.o @@ -38,6 +37,7 @@ nvkm-y += nvkm/subdev/mmu/vmmgp100.o nvkm-y += nvkm/subdev/mmu/vmmgp10b.o nvkm-y += nvkm/subdev/mmu/vmmgv100.o nvkm-y += nvkm/subdev/mmu/vmmtu102.o +nvkm-y += nvkm/subdev/mmu/vmmgh100.o nvkm-y += nvkm/subdev/mmu/umem.o nvkm-y += nvkm/subdev/mmu/ummu.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gh100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gh100.c new file mode 100644 index 000000000000..2918fb32cc91 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gh100.c @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. + */ +#include "mem.h" +#include "vmm.h" + +#include <nvif/class.h> + +static const struct nvkm_mmu_func +gh100_mmu = { + .dma_bits = 52, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, + .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map }, + .vmm = {{ -1, 0, NVIF_CLASS_VMM_GP100}, gh100_vmm_new }, + .kind = tu102_mmu_kind, + .kind_sys = true, +}; + +int +gh100_mmu_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_mmu **pmmu) +{ + return r535_mmu_new(&gh100_mmu, device, type, inst, pmmu); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c index d9c9bee45222..160a5749a29f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c @@ -60,7 +60,7 @@ gf100_mem_map(struct nvkm_mmu *mmu, struct nvkm_memory *memory, void *argv, if (ret) return ret; - *paddr = device->func->resource_addr(device, 1) + (*pvma)->addr; + *paddr = device->func->resource_addr(device, NVKM_BAR1_FB) + (*pvma)->addr; *psize = (*pvma)->size; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c index 79a3b0cc9f5b..1e3db52de6cb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c @@ -41,7 +41,7 @@ nv04_mem_map(struct nvkm_mmu *mmu, struct nvkm_memory *memory, void *argv, if ((ret = nvif_unvers(ret, &argv, &argc, args->vn))) return ret; - *paddr = device->func->resource_addr(device, 1) + addr; + *paddr = device->func->resource_addr(device, NVKM_BAR1_FB) + addr; *psize = nvkm_memory_size(memory); *pvma = ERR_PTR(-ENODEV); return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c index 46759b89fc1f..33b2321e9d87 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c @@ -57,7 +57,7 @@ nv50_mem_map(struct nvkm_mmu *mmu, struct nvkm_memory *memory, void *argv, if (ret) return ret; - *paddr = device->func->resource_addr(device, 1) + (*pvma)->addr; + *paddr = device->func->resource_addr(device, NVKM_BAR1_FB) + (*pvma)->addr; *psize = (*pvma)->size; return nvkm_memory_map(memory, 0, bar, *pvma, &uvmm, sizeof(uvmm)); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h index e9ca6537778c..90efef8f0b54 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h @@ -53,6 +53,8 @@ const u8 *gf100_mmu_kind(struct nvkm_mmu *, int *count, u8 *invalid); const u8 *gm200_mmu_kind(struct nvkm_mmu *, int *, u8 *); +const u8 *tu102_mmu_kind(struct nvkm_mmu *, int *, u8 *); + struct nvkm_mmu_pt { union { struct nvkm_mmu_ptc *ptc; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/r535.c deleted file mode 100644 index d3e95453f25d..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/r535.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2023 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "vmm.h" - -#include <nvrm/nvtypes.h> -#include <nvrm/535.113.01/common/sdk/nvidia/inc/class/cl90f1.h> -#include <nvrm/535.113.01/common/sdk/nvidia/inc/ctrl/ctrl90f1.h> -#include <nvrm/535.113.01/common/sdk/nvidia/inc/nvos.h> - -static int -r535_mmu_promote_vmm(struct nvkm_vmm *vmm) -{ - NV_VASPACE_ALLOCATION_PARAMETERS *args; - int ret; - - ret = nvkm_gsp_client_device_ctor(vmm->mmu->subdev.device->gsp, - &vmm->rm.client, &vmm->rm.device); - if (ret) - return ret; - - args = nvkm_gsp_rm_alloc_get(&vmm->rm.device.object, 0x90f10000, FERMI_VASPACE_A, - sizeof(*args), &vmm->rm.object); - if (IS_ERR(args)) - return PTR_ERR(args); - - args->index = NV_VASPACE_ALLOCATION_INDEX_GPU_NEW; - - ret = nvkm_gsp_rm_alloc_wr(&vmm->rm.object, args); - if (ret) - return ret; - - { - NV90F1_CTRL_VASPACE_COPY_SERVER_RESERVED_PDES_PARAMS *ctrl; - - mutex_lock(&vmm->mutex.vmm); - ret = nvkm_vmm_get_locked(vmm, true, false, false, 0x1d, 32, 0x20000000, - &vmm->rm.rsvd); - mutex_unlock(&vmm->mutex.vmm); - if (ret) - return ret; - - ctrl = nvkm_gsp_rm_ctrl_get(&vmm->rm.object, - NV90F1_CTRL_CMD_VASPACE_COPY_SERVER_RESERVED_PDES, - sizeof(*ctrl)); - if (IS_ERR(ctrl)) - return PTR_ERR(ctrl); - - ctrl->pageSize = 0x20000000; - ctrl->virtAddrLo = vmm->rm.rsvd->addr; - ctrl->virtAddrHi = vmm->rm.rsvd->addr + vmm->rm.rsvd->size - 1; - ctrl->numLevelsToCopy = vmm->pd->pde[0]->pde[0] ? 3 : 2; - ctrl->levels[0].physAddress = vmm->pd->pt[0]->addr; - ctrl->levels[0].size = 0x20; - ctrl->levels[0].aperture = 1; - ctrl->levels[0].pageShift = 0x2f; - ctrl->levels[1].physAddress = vmm->pd->pde[0]->pt[0]->addr; - ctrl->levels[1].size = 0x1000; - ctrl->levels[1].aperture = 1; - ctrl->levels[1].pageShift = 0x26; - if (vmm->pd->pde[0]->pde[0]) { - ctrl->levels[2].physAddress = vmm->pd->pde[0]->pde[0]->pt[0]->addr; - ctrl->levels[2].size = 0x1000; - ctrl->levels[2].aperture = 1; - ctrl->levels[2].pageShift = 0x1d; - } - - ret = nvkm_gsp_rm_ctrl_wr(&vmm->rm.object, ctrl); - } - - return ret; -} - -static void -r535_mmu_dtor(struct nvkm_mmu *mmu) -{ - kfree(mmu->func); -} - -int -r535_mmu_new(const struct nvkm_mmu_func *hw, - struct nvkm_device *device, enum nvkm_subdev_type type, int inst, - struct nvkm_mmu **pmmu) -{ - struct nvkm_mmu_func *rm; - int ret; - - if (!(rm = kzalloc(sizeof(*rm), GFP_KERNEL))) - return -ENOMEM; - - rm->dtor = r535_mmu_dtor; - rm->dma_bits = hw->dma_bits; - rm->mmu = hw->mmu; - rm->mem = hw->mem; - rm->vmm = hw->vmm; - rm->kind = hw->kind; - rm->kind_sys = hw->kind_sys; - rm->promote_vmm = r535_mmu_promote_vmm; - - ret = nvkm_mmu_new_(rm, device, type, inst, pmmu); - if (ret) - kfree(rm); - - return ret; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c index df662ce4a4b0..7acff3642e20 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c @@ -28,7 +28,7 @@ #include <nvif/class.h> -static const u8 * +const u8 * tu102_mmu_kind(struct nvkm_mmu *mmu, int *count, u8 *invalid) { static const u8 diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c index 9c97800fe037..f95c58b67633 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c @@ -19,7 +19,7 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#define NVKM_VMM_LEVELS_MAX 5 +#define NVKM_VMM_LEVELS_MAX 6 #include "vmm.h" #include <subdev/fb.h> @@ -1030,12 +1030,8 @@ nvkm_vmm_dtor(struct nvkm_vmm *vmm) struct nvkm_vma *vma; struct rb_node *node; - if (vmm->rm.client.gsp) { - nvkm_gsp_rm_free(&vmm->rm.object); - nvkm_gsp_device_dtor(&vmm->rm.device); - nvkm_gsp_client_dtor(&vmm->rm.client); - nvkm_vmm_put(vmm, &vmm->rm.rsvd); - } + if (vmm->rm.client.gsp) + r535_mmu_vaspace_del(vmm); if (0) nvkm_vmm_dump(vmm); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h index f9bc30cdb2b3..4586a425dbe4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h @@ -143,6 +143,8 @@ struct nvkm_vmm_func { int (*aper)(enum nvkm_memory_target); int (*valid)(struct nvkm_vmm *, void *argv, u32 argc, struct nvkm_vmm_map *); + int (*valid2)(struct nvkm_vmm *, bool ro, bool priv, u8 kind, u8 comp, + struct nvkm_vmm_map *); void (*flush)(struct nvkm_vmm *, int depth); int (*mthd)(struct nvkm_vmm *, struct nvkm_client *, @@ -254,6 +256,8 @@ void gp100_vmm_invalidate_pdb(struct nvkm_vmm *, u64 addr); int gv100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *); +void tu102_vmm_flush(struct nvkm_vmm *, int depth); + int nv04_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, struct lock_class_key *, const char *, struct nvkm_vmm **); int nv41_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, @@ -296,6 +300,9 @@ int gv100_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, int tu102_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, struct lock_class_key *, const char *, struct nvkm_vmm **); +int gh100_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, + struct lock_class_key *, const char *, + struct nvkm_vmm **); #define VMM_PRINT(l,v,p,f,a...) do { \ struct nvkm_vmm *_vmm = (v); \ diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgh100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgh100.c new file mode 100644 index 000000000000..5614df3432da --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgh100.c @@ -0,0 +1,306 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. + */ +#include "vmm.h" + +#include <subdev/fb.h> + +#include <nvhw/drf.h> +#include <nvhw/ref/gh100/dev_mmu.h> + +static inline void +gh100_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes, + struct nvkm_vmm_map *map, u64 addr) +{ + u64 data = addr | map->type; + + while (ptes--) { + VMM_WO064(pt, vmm, ptei++ * NV_MMU_VER3_PTE__SIZE, data); + data += map->next; + } +} + +static void +gh100_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes, + struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, gh100_vmm_pgt_pte); +} + +static void +gh100_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes, + struct nvkm_vmm_map *map) +{ + if (map->page->shift == PAGE_SHIFT) { + VMM_SPAM(vmm, "DMAA %08x %08x PTE(s)", ptei, ptes); + + nvkm_kmap(pt->memory); + while (ptes--) { + const u64 data = *map->dma++ | map->type; + + VMM_WO064(pt, vmm, ptei++ * NV_MMU_VER3_PTE__SIZE, data); + } + nvkm_done(pt->memory); + return; + } + + VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, gh100_vmm_pgt_pte); +} + +static void +gh100_vmm_pgt_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes, + struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gh100_vmm_pgt_pte); +} + +static void +gh100_vmm_pgt_sparse(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) +{ + const u64 data = NVDEF(NV_MMU, VER3_PTE, PCF, SPARSE); + + VMM_FO064(pt, vmm, ptei * NV_MMU_VER3_PTE__SIZE, data, ptes); +} + +static const struct nvkm_vmm_desc_func +gh100_vmm_desc_spt = { + .unmap = gf100_vmm_pgt_unmap, + .sparse = gh100_vmm_pgt_sparse, + .mem = gh100_vmm_pgt_mem, + .dma = gh100_vmm_pgt_dma, + .sgl = gh100_vmm_pgt_sgl, +}; + +static void +gh100_vmm_lpt_invalid(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) +{ + const u64 data = NVDEF(NV_MMU, VER3_PTE, PCF, NO_VALID_4KB_PAGE); + + VMM_FO064(pt, vmm, ptei * NV_MMU_VER3_PTE__SIZE, data, ptes); +} + +static const struct nvkm_vmm_desc_func +gh100_vmm_desc_lpt = { + .invalid = gh100_vmm_lpt_invalid, + .unmap = gf100_vmm_pgt_unmap, + .sparse = gh100_vmm_pgt_sparse, + .mem = gh100_vmm_pgt_mem, +}; + +static inline void +gh100_vmm_pd0_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr) +{ + u64 data = addr | map->type; + + while (ptes--) { + VMM_WO128(pt, vmm, ptei++ * NV_MMU_VER3_DUAL_PDE__SIZE, data, 0ULL); + data += map->next; + } +} + +static void +gh100_vmm_pd0_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gh100_vmm_pd0_pte); +} + +static inline bool +gh100_vmm_pde(struct nvkm_mmu_pt *pt, u64 *data) +{ + switch (nvkm_memory_target(pt->memory)) { + case NVKM_MEM_TARGET_VRAM: + *data |= NVDEF(NV_MMU, VER3_PDE, APERTURE, VIDEO_MEMORY); + *data |= NVDEF(NV_MMU, VER3_PDE, PCF, VALID_CACHED_ATS_NOT_ALLOWED); + break; + case NVKM_MEM_TARGET_HOST: + *data |= NVDEF(NV_MMU, VER3_PDE, APERTURE, SYSTEM_COHERENT_MEMORY); + *data |= NVDEF(NV_MMU, VER3_PDE, PCF, VALID_UNCACHED_ATS_ALLOWED); + break; + case NVKM_MEM_TARGET_NCOH: + *data |= NVDEF(NV_MMU, VER3_PDE, APERTURE, SYSTEM_NON_COHERENT_MEMORY); + *data |= NVDEF(NV_MMU, VER3_PDE, PCF, VALID_CACHED_ATS_ALLOWED); + break; + default: + WARN_ON(1); + return false; + } + + *data |= pt->addr; + return true; +} + +static void +gh100_vmm_pd0_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei) +{ + struct nvkm_vmm_pt *pgt = pgd->pde[pdei]; + struct nvkm_mmu_pt *pd = pgd->pt[0]; + u64 data[2] = {}; + + if (pgt->pt[0] && !gh100_vmm_pde(pgt->pt[0], &data[0])) + return; + if (pgt->pt[1] && !gh100_vmm_pde(pgt->pt[1], &data[1])) + return; + + nvkm_kmap(pd->memory); + VMM_WO128(pd, vmm, pdei * NV_MMU_VER3_DUAL_PDE__SIZE, data[0], data[1]); + nvkm_done(pd->memory); +} + +static void +gh100_vmm_pd0_sparse(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes) +{ + const u64 data = NVDEF(NV_MMU, VER3_DUAL_PDE, PCF_BIG, SPARSE_ATS_ALLOWED); + + VMM_FO128(pt, vmm, pdei * NV_MMU_VER3_DUAL_PDE__SIZE, data, 0ULL, pdes); +} + +static void +gh100_vmm_pd0_unmap(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes) +{ + VMM_FO128(pt, vmm, pdei * NV_MMU_VER3_DUAL_PDE__SIZE, 0ULL, 0ULL, pdes); +} + +static const struct nvkm_vmm_desc_func +gh100_vmm_desc_pd0 = { + .unmap = gh100_vmm_pd0_unmap, + .sparse = gh100_vmm_pd0_sparse, + .pde = gh100_vmm_pd0_pde, + .mem = gh100_vmm_pd0_mem, +}; + +static void +gh100_vmm_pd1_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei) +{ + struct nvkm_vmm_pt *pgt = pgd->pde[pdei]; + struct nvkm_mmu_pt *pd = pgd->pt[0]; + u64 data = 0; + + if (!gh100_vmm_pde(pgt->pt[0], &data)) + return; + + nvkm_kmap(pd->memory); + VMM_WO064(pd, vmm, pdei * NV_MMU_VER3_PDE__SIZE, data); + nvkm_done(pd->memory); +} + +static const struct nvkm_vmm_desc_func +gh100_vmm_desc_pd1 = { + .unmap = gf100_vmm_pgt_unmap, + .sparse = gh100_vmm_pgt_sparse, + .pde = gh100_vmm_pd1_pde, +}; + +static const struct nvkm_vmm_desc +gh100_vmm_desc_16[] = { + { LPT, 5, 8, 0x0100, &gh100_vmm_desc_lpt }, + { PGD, 8, 16, 0x1000, &gh100_vmm_desc_pd0 }, + { PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 }, + { PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 }, + { PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 }, + { PGD, 1, 8, 0x1000, &gh100_vmm_desc_pd1 }, + {} +}; + +static const struct nvkm_vmm_desc +gh100_vmm_desc_12[] = { + { SPT, 9, 8, 0x1000, &gh100_vmm_desc_spt }, + { PGD, 8, 16, 0x1000, &gh100_vmm_desc_pd0 }, + { PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 }, + { PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 }, + { PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 }, + { PGD, 1, 8, 0x1000, &gh100_vmm_desc_pd1 }, + {} +}; + +static int +gh100_vmm_valid(struct nvkm_vmm *vmm, bool ro, bool priv, u8 kind, u8 comp, + struct nvkm_vmm_map *map) +{ + const enum nvkm_memory_target target = nvkm_memory_target(map->memory); + const bool vol = target == NVKM_MEM_TARGET_HOST; + const struct nvkm_vmm_page *page = map->page; + u8 kind_inv, pcf; + int kindn, aper; + const u8 *kindm; + + map->next = 1ULL << page->shift; + map->type = 0; + + aper = vmm->func->aper(target); + if (WARN_ON(aper < 0)) + return aper; + + kindm = vmm->mmu->func->kind(vmm->mmu, &kindn, &kind_inv); + if (kind >= kindn || kindm[kind] == kind_inv) { + VMM_DEBUG(vmm, "kind %02x", kind); + return -EINVAL; + } + + if (priv) { + if (ro) { + if (vol) + pcf = NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_ATOMIC_UNCACHED_ACD; + else + pcf = NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_ATOMIC_CACHED_ACD; + } else { + if (vol) + pcf = NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_ATOMIC_UNCACHED_ACD; + else + pcf = NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_ATOMIC_CACHED_ACD; + } + } else { + if (ro) { + if (vol) + pcf = NV_MMU_VER3_PTE_PCF_REGULAR_RO_ATOMIC_UNCACHED_ACD; + else + pcf = NV_MMU_VER3_PTE_PCF_REGULAR_RO_ATOMIC_CACHED_ACD; + } else { + if (vol) + pcf = NV_MMU_VER3_PTE_PCF_REGULAR_RW_ATOMIC_UNCACHED_ACD; + else + pcf = NV_MMU_VER3_PTE_PCF_REGULAR_RW_ATOMIC_CACHED_ACD; + } + } + + map->type |= NVDEF(NV_MMU, VER3_PTE, VALID, TRUE); + map->type |= NVVAL(NV_MMU, VER3_PTE, APERTURE, aper); + map->type |= NVVAL(NV_MMU, VER3_PTE, PCF, pcf); + map->type |= NVVAL(NV_MMU, VER3_PTE, KIND, kind); + return 0; +} + +static const struct nvkm_vmm_func +gh100_vmm = { + .join = gv100_vmm_join, + .part = gf100_vmm_part, + .aper = gf100_vmm_aper, + .valid = gp100_vmm_valid, + .valid2 = gh100_vmm_valid, + .flush = tu102_vmm_flush, + .page = { + { 56, &gh100_vmm_desc_16[5], NVKM_VMM_PAGE_Sxxx }, + { 47, &gh100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx }, + { 38, &gh100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx }, + { 29, &gh100_vmm_desc_16[2], NVKM_VMM_PAGE_SVxC }, + { 21, &gh100_vmm_desc_16[1], NVKM_VMM_PAGE_SVxC }, + { 16, &gh100_vmm_desc_16[0], NVKM_VMM_PAGE_SVxC }, + { 12, &gh100_vmm_desc_12[0], NVKM_VMM_PAGE_SVHx }, + {} + } +}; + +int +gh100_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 gp100_vmm_new_(&gh100_vmm, mmu, managed, addr, size, + argv, argc, key, name, pvmm); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c index bddac77f48f0..851fd847a2a9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c @@ -436,6 +436,9 @@ gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, return ret; } + if (vmm->func->valid2) + return vmm->func->valid2(vmm, ro, priv, kind, 0, map); + aper = vmm->func->aper(target); if (WARN_ON(aper < 0)) return aper; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c index 8379e72d77ab..4b30eab40bba 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c @@ -23,7 +23,7 @@ #include <subdev/timer.h> -static void +void tu102_vmm_flush(struct nvkm_vmm *vmm, int depth) { struct nvkm_device *device = vmm->mmu->subdev.device; |