.. | .. |
---|
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; |
---|