Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2017 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  */
0022 #include "vmm.h"
0023 
0024 #include <nvif/ifb00d.h>
0025 #include <nvif/unpack.h>
0026 
0027 static void
0028 gm200_vmm_pgt_sparse(struct nvkm_vmm *vmm,
0029              struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
0030 {
0031     /* VALID_FALSE + VOL tells the MMU to treat the PTE as sparse. */
0032     VMM_FO064(pt, vmm, ptei * 8, BIT_ULL(32) /* VOL. */, ptes);
0033 }
0034 
0035 static const struct nvkm_vmm_desc_func
0036 gm200_vmm_spt = {
0037     .unmap = gf100_vmm_pgt_unmap,
0038     .sparse = gm200_vmm_pgt_sparse,
0039     .mem = gf100_vmm_pgt_mem,
0040     .dma = gf100_vmm_pgt_dma,
0041     .sgl = gf100_vmm_pgt_sgl,
0042 };
0043 
0044 static const struct nvkm_vmm_desc_func
0045 gm200_vmm_lpt = {
0046     .invalid = gk104_vmm_lpt_invalid,
0047     .unmap = gf100_vmm_pgt_unmap,
0048     .sparse = gm200_vmm_pgt_sparse,
0049     .mem = gf100_vmm_pgt_mem,
0050 };
0051 
0052 static void
0053 gm200_vmm_pgd_sparse(struct nvkm_vmm *vmm,
0054              struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes)
0055 {
0056     /* VALID_FALSE + VOL_BIG tells the MMU to treat the PDE as sparse. */
0057     VMM_FO064(pt, vmm, pdei * 8, BIT_ULL(35) /* VOL_BIG. */, pdes);
0058 }
0059 
0060 static const struct nvkm_vmm_desc_func
0061 gm200_vmm_pgd = {
0062     .unmap = gf100_vmm_pgt_unmap,
0063     .sparse = gm200_vmm_pgd_sparse,
0064     .pde = gf100_vmm_pgd_pde,
0065 };
0066 
0067 const struct nvkm_vmm_desc
0068 gm200_vmm_desc_17_12[] = {
0069     { SPT, 15, 8, 0x1000, &gm200_vmm_spt },
0070     { PGD, 13, 8, 0x1000, &gm200_vmm_pgd },
0071     {}
0072 };
0073 
0074 const struct nvkm_vmm_desc
0075 gm200_vmm_desc_17_17[] = {
0076     { LPT, 10, 8, 0x1000, &gm200_vmm_lpt },
0077     { PGD, 13, 8, 0x1000, &gm200_vmm_pgd },
0078     {}
0079 };
0080 
0081 const struct nvkm_vmm_desc
0082 gm200_vmm_desc_16_12[] = {
0083     { SPT, 14, 8, 0x1000, &gm200_vmm_spt },
0084     { PGD, 14, 8, 0x1000, &gm200_vmm_pgd },
0085     {}
0086 };
0087 
0088 const struct nvkm_vmm_desc
0089 gm200_vmm_desc_16_16[] = {
0090     { LPT, 10, 8, 0x1000, &gm200_vmm_lpt },
0091     { PGD, 14, 8, 0x1000, &gm200_vmm_pgd },
0092     {}
0093 };
0094 
0095 int
0096 gm200_vmm_join_(struct nvkm_vmm *vmm, struct nvkm_memory *inst, u64 base)
0097 {
0098     if (vmm->func->page[1].shift == 16)
0099         base |= BIT_ULL(11);
0100     return gf100_vmm_join_(vmm, inst, base);
0101 }
0102 
0103 int
0104 gm200_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
0105 {
0106     return gm200_vmm_join_(vmm, inst, 0);
0107 }
0108 
0109 static const struct nvkm_vmm_func
0110 gm200_vmm_17 = {
0111     .join = gm200_vmm_join,
0112     .part = gf100_vmm_part,
0113     .aper = gf100_vmm_aper,
0114     .valid = gf100_vmm_valid,
0115     .flush = gf100_vmm_flush,
0116     .invalidate_pdb = gf100_vmm_invalidate_pdb,
0117     .page = {
0118         { 27, &gm200_vmm_desc_17_17[1], NVKM_VMM_PAGE_Sxxx },
0119         { 17, &gm200_vmm_desc_17_17[0], NVKM_VMM_PAGE_SVxC },
0120         { 12, &gm200_vmm_desc_17_12[0], NVKM_VMM_PAGE_SVHx },
0121         {}
0122     }
0123 };
0124 
0125 static const struct nvkm_vmm_func
0126 gm200_vmm_16 = {
0127     .join = gm200_vmm_join,
0128     .part = gf100_vmm_part,
0129     .aper = gf100_vmm_aper,
0130     .valid = gf100_vmm_valid,
0131     .flush = gf100_vmm_flush,
0132     .invalidate_pdb = gf100_vmm_invalidate_pdb,
0133     .page = {
0134         { 27, &gm200_vmm_desc_16_16[1], NVKM_VMM_PAGE_Sxxx },
0135         { 16, &gm200_vmm_desc_16_16[0], NVKM_VMM_PAGE_SVxC },
0136         { 12, &gm200_vmm_desc_16_12[0], NVKM_VMM_PAGE_SVHx },
0137         {}
0138     }
0139 };
0140 
0141 int
0142 gm200_vmm_new_(const struct nvkm_vmm_func *func_16,
0143            const struct nvkm_vmm_func *func_17,
0144            struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size,
0145            void *argv, u32 argc, struct lock_class_key *key,
0146            const char *name, struct nvkm_vmm **pvmm)
0147 {
0148     const struct nvkm_vmm_func *func;
0149     union {
0150         struct gm200_vmm_vn vn;
0151         struct gm200_vmm_v0 v0;
0152     } *args = argv;
0153     int ret = -ENOSYS;
0154 
0155     if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
0156         switch (args->v0.bigpage) {
0157         case 16: func = func_16; break;
0158         case 17: func = func_17; break;
0159         default:
0160             return -EINVAL;
0161         }
0162     } else
0163     if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) {
0164         func = func_17;
0165     } else
0166         return ret;
0167 
0168     return nvkm_vmm_new_(func, mmu, 0, managed, addr, size, key, name, pvmm);
0169 }
0170 
0171 int
0172 gm200_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size,
0173           void *argv, u32 argc, struct lock_class_key *key,
0174           const char *name, struct nvkm_vmm **pvmm)
0175 {
0176     return gm200_vmm_new_(&gm200_vmm_16, &gm200_vmm_17, mmu, managed, addr,
0177                   size, argv, argc, key, name, pvmm);
0178 }
0179 
0180 int
0181 gm200_vmm_new_fixed(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size,
0182             void *argv, u32 argc, struct lock_class_key *key,
0183             const char *name, struct nvkm_vmm **pvmm)
0184 {
0185     return gf100_vmm_new_(&gm200_vmm_16, &gm200_vmm_17, mmu, managed, addr,
0186                   size, argv, argc, key, name, pvmm);
0187 }