| .. | .. |
|---|
| 43 | 43 | } |
|---|
| 44 | 44 | |
|---|
| 45 | 45 | static int |
|---|
| 46 | +nvkm_uvmm_mthd_pfnclr(struct nvkm_uvmm *uvmm, void *argv, u32 argc) |
|---|
| 47 | +{ |
|---|
| 48 | + struct nvkm_client *client = uvmm->object.client; |
|---|
| 49 | + union { |
|---|
| 50 | + struct nvif_vmm_pfnclr_v0 v0; |
|---|
| 51 | + } *args = argv; |
|---|
| 52 | + struct nvkm_vmm *vmm = uvmm->vmm; |
|---|
| 53 | + int ret = -ENOSYS; |
|---|
| 54 | + u64 addr, size; |
|---|
| 55 | + |
|---|
| 56 | + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { |
|---|
| 57 | + addr = args->v0.addr; |
|---|
| 58 | + size = args->v0.size; |
|---|
| 59 | + } else |
|---|
| 60 | + return ret; |
|---|
| 61 | + |
|---|
| 62 | + if (!client->super) |
|---|
| 63 | + return -ENOENT; |
|---|
| 64 | + |
|---|
| 65 | + if (size) { |
|---|
| 66 | + mutex_lock(&vmm->mutex); |
|---|
| 67 | + ret = nvkm_vmm_pfn_unmap(vmm, addr, size); |
|---|
| 68 | + mutex_unlock(&vmm->mutex); |
|---|
| 69 | + } |
|---|
| 70 | + |
|---|
| 71 | + return ret; |
|---|
| 72 | +} |
|---|
| 73 | + |
|---|
| 74 | +static int |
|---|
| 75 | +nvkm_uvmm_mthd_pfnmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc) |
|---|
| 76 | +{ |
|---|
| 77 | + struct nvkm_client *client = uvmm->object.client; |
|---|
| 78 | + union { |
|---|
| 79 | + struct nvif_vmm_pfnmap_v0 v0; |
|---|
| 80 | + } *args = argv; |
|---|
| 81 | + struct nvkm_vmm *vmm = uvmm->vmm; |
|---|
| 82 | + int ret = -ENOSYS; |
|---|
| 83 | + u64 addr, size, *phys; |
|---|
| 84 | + u8 page; |
|---|
| 85 | + |
|---|
| 86 | + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) { |
|---|
| 87 | + page = args->v0.page; |
|---|
| 88 | + addr = args->v0.addr; |
|---|
| 89 | + size = args->v0.size; |
|---|
| 90 | + phys = args->v0.phys; |
|---|
| 91 | + if (argc != (size >> page) * sizeof(args->v0.phys[0])) |
|---|
| 92 | + return -EINVAL; |
|---|
| 93 | + } else |
|---|
| 94 | + return ret; |
|---|
| 95 | + |
|---|
| 96 | + if (!client->super) |
|---|
| 97 | + return -ENOENT; |
|---|
| 98 | + |
|---|
| 99 | + if (size) { |
|---|
| 100 | + mutex_lock(&vmm->mutex); |
|---|
| 101 | + ret = nvkm_vmm_pfn_map(vmm, page, addr, size, phys); |
|---|
| 102 | + mutex_unlock(&vmm->mutex); |
|---|
| 103 | + } |
|---|
| 104 | + |
|---|
| 105 | + return ret; |
|---|
| 106 | +} |
|---|
| 107 | + |
|---|
| 108 | +static int |
|---|
| 46 | 109 | nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc) |
|---|
| 47 | 110 | { |
|---|
| 48 | 111 | struct nvkm_client *client = uvmm->object.client; |
|---|
| .. | .. |
|---|
| 78 | 141 | goto done; |
|---|
| 79 | 142 | } |
|---|
| 80 | 143 | |
|---|
| 81 | | - nvkm_vmm_unmap_locked(vmm, vma); |
|---|
| 144 | + nvkm_vmm_unmap_locked(vmm, vma, false); |
|---|
| 82 | 145 | ret = 0; |
|---|
| 83 | 146 | done: |
|---|
| 84 | 147 | mutex_unlock(&vmm->mutex); |
|---|
| .. | .. |
|---|
| 124 | 187 | goto fail; |
|---|
| 125 | 188 | } |
|---|
| 126 | 189 | |
|---|
| 190 | + if (ret = -EINVAL, vma->mapped && !vma->memory) { |
|---|
| 191 | + VMM_DEBUG(vmm, "pfnmap %016llx", addr); |
|---|
| 192 | + goto fail; |
|---|
| 193 | + } |
|---|
| 194 | + |
|---|
| 127 | 195 | if (ret = -EINVAL, vma->addr != addr || vma->size != size) { |
|---|
| 128 | 196 | if (addr + size > vma->addr + vma->size || vma->memory || |
|---|
| 129 | 197 | (vma->refd == NVKM_VMA_PAGE_NONE && !vma->mapref)) { |
|---|
| .. | .. |
|---|
| 134 | 202 | goto fail; |
|---|
| 135 | 203 | } |
|---|
| 136 | 204 | |
|---|
| 137 | | - if (vma->addr != addr) { |
|---|
| 138 | | - const u64 tail = vma->size + vma->addr - addr; |
|---|
| 139 | | - if (ret = -ENOMEM, !(vma = nvkm_vma_tail(vma, tail))) |
|---|
| 140 | | - goto fail; |
|---|
| 141 | | - vma->part = true; |
|---|
| 142 | | - nvkm_vmm_node_insert(vmm, vma); |
|---|
| 143 | | - } |
|---|
| 144 | | - |
|---|
| 145 | | - if (vma->size != size) { |
|---|
| 146 | | - const u64 tail = vma->size - size; |
|---|
| 147 | | - struct nvkm_vma *tmp; |
|---|
| 148 | | - if (ret = -ENOMEM, !(tmp = nvkm_vma_tail(vma, tail))) { |
|---|
| 149 | | - nvkm_vmm_unmap_region(vmm, vma); |
|---|
| 150 | | - goto fail; |
|---|
| 151 | | - } |
|---|
| 152 | | - tmp->part = true; |
|---|
| 153 | | - nvkm_vmm_node_insert(vmm, tmp); |
|---|
| 205 | + vma = nvkm_vmm_node_split(vmm, vma, addr, size); |
|---|
| 206 | + if (!vma) { |
|---|
| 207 | + ret = -ENOMEM; |
|---|
| 208 | + goto fail; |
|---|
| 154 | 209 | } |
|---|
| 155 | 210 | } |
|---|
| 156 | 211 | vma->busy = true; |
|---|
| .. | .. |
|---|
| 284 | 339 | case NVIF_VMM_V0_PUT : return nvkm_uvmm_mthd_put (uvmm, argv, argc); |
|---|
| 285 | 340 | case NVIF_VMM_V0_MAP : return nvkm_uvmm_mthd_map (uvmm, argv, argc); |
|---|
| 286 | 341 | case NVIF_VMM_V0_UNMAP : return nvkm_uvmm_mthd_unmap (uvmm, argv, argc); |
|---|
| 342 | + case NVIF_VMM_V0_PFNMAP: return nvkm_uvmm_mthd_pfnmap(uvmm, argv, argc); |
|---|
| 343 | + case NVIF_VMM_V0_PFNCLR: return nvkm_uvmm_mthd_pfnclr(uvmm, argv, argc); |
|---|
| 344 | + case NVIF_VMM_V0_MTHD(0x00) ... NVIF_VMM_V0_MTHD(0x7f): |
|---|
| 345 | + if (uvmm->vmm->func->mthd) { |
|---|
| 346 | + return uvmm->vmm->func->mthd(uvmm->vmm, |
|---|
| 347 | + uvmm->object.client, |
|---|
| 348 | + mthd, argv, argc); |
|---|
| 349 | + } |
|---|
| 350 | + break; |
|---|
| 287 | 351 | default: |
|---|
| 288 | 352 | break; |
|---|
| 289 | 353 | } |
|---|
| .. | .. |
|---|
| 317 | 381 | struct nvkm_uvmm *uvmm; |
|---|
| 318 | 382 | int ret = -ENOSYS; |
|---|
| 319 | 383 | u64 addr, size; |
|---|
| 384 | + bool managed; |
|---|
| 320 | 385 | |
|---|
| 321 | 386 | if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, more))) { |
|---|
| 387 | + managed = args->v0.managed != 0; |
|---|
| 322 | 388 | addr = args->v0.addr; |
|---|
| 323 | 389 | size = args->v0.size; |
|---|
| 324 | 390 | } else |
|---|
| .. | .. |
|---|
| 330 | 396 | *pobject = &uvmm->object; |
|---|
| 331 | 397 | |
|---|
| 332 | 398 | if (!mmu->vmm) { |
|---|
| 333 | | - ret = mmu->func->vmm.ctor(mmu, addr, size, argv, argc, |
|---|
| 399 | + ret = mmu->func->vmm.ctor(mmu, managed, addr, size, argv, argc, |
|---|
| 334 | 400 | NULL, "user", &uvmm->vmm); |
|---|
| 335 | 401 | if (ret) |
|---|
| 336 | 402 | return ret; |
|---|