summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/vgpu/mm_vgpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/vgpu/mm_vgpu.c')
-rw-r--r--drivers/gpu/nvgpu/vgpu/mm_vgpu.c197
1 files changed, 32 insertions, 165 deletions
diff --git a/drivers/gpu/nvgpu/vgpu/mm_vgpu.c b/drivers/gpu/nvgpu/vgpu/mm_vgpu.c
index 287567d6..b2bc6f0a 100644
--- a/drivers/gpu/nvgpu/vgpu/mm_vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/mm_vgpu.c
@@ -21,6 +21,8 @@
21#include <nvgpu/vm.h> 21#include <nvgpu/vm.h>
22#include <nvgpu/vm_area.h> 22#include <nvgpu/vm_area.h>
23 23
24#include <nvgpu/vgpu/vm.h>
25
24#include "vgpu/vgpu.h" 26#include "vgpu/vgpu.h"
25#include "gk20a/mm_gk20a.h" 27#include "gk20a/mm_gk20a.h"
26 28
@@ -201,7 +203,36 @@ static void vgpu_locked_gmmu_unmap(struct vm_gk20a *vm,
201 /* TLB invalidate handled on server side */ 203 /* TLB invalidate handled on server side */
202} 204}
203 205
204void nvgpu_vm_remove_vgpu(struct vm_gk20a *vm) 206/*
207 * This is called by the common VM init routine to handle vGPU specifics of
208 * intializing a VM on a vGPU. This alone is not enough to init a VM. See
209 * nvgpu_vm_init().
210 */
211int vgpu_vm_init(struct gk20a *g, struct vm_gk20a *vm)
212{
213 struct tegra_vgpu_cmd_msg msg;
214 struct tegra_vgpu_as_share_params *p = &msg.params.as_share;
215 int err;
216
217 msg.cmd = TEGRA_VGPU_CMD_AS_ALLOC_SHARE;
218 msg.handle = vgpu_get_handle(g);
219 p->size = vm->va_limit;
220 p->big_page_size = vm->big_page_size;
221
222 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
223 if (err || msg.ret)
224 return -ENOMEM;
225
226 vm->handle = p->handle;
227
228 return 0;
229}
230
231/*
232 * Similar to vgpu_vm_init() this is called as part of the cleanup path for
233 * VMs. This alone is not enough to remove a VM - see nvgpu_vm_remove().
234 */
235void vgpu_vm_remove(struct vm_gk20a *vm)
205{ 236{
206 struct gk20a *g = gk20a_from_vm(vm); 237 struct gk20a *g = gk20a_from_vm(vm);
207 struct tegra_vgpu_cmd_msg msg; 238 struct tegra_vgpu_cmd_msg msg;
@@ -238,169 +269,6 @@ u64 vgpu_bar1_map(struct gk20a *g, struct sg_table **sgt, u64 size)
238 return addr; 269 return addr;
239} 270}
240 271
241/* address space interfaces for the gk20a module */
242static int vgpu_vm_alloc_share(struct gk20a_as_share *as_share,
243 u32 big_page_size, u32 flags)
244{
245 struct gk20a_as *as = as_share->as;
246 struct gk20a *g = gk20a_from_as(as);
247 struct gk20a_platform *platform = gk20a_get_platform(g->dev);
248 struct tegra_vgpu_cmd_msg msg;
249 struct tegra_vgpu_as_share_params *p = &msg.params.as_share;
250 struct mm_gk20a *mm = &g->mm;
251 struct vm_gk20a *vm;
252 u64 user_vma_start, user_vma_limit, kernel_vma_start, kernel_vma_limit;
253 char name[32];
254 int err, i;
255 const bool userspace_managed =
256 (flags & NVGPU_GPU_IOCTL_ALLOC_AS_FLAGS_USERSPACE_MANAGED) != 0;
257
258 /* note: keep the page sizes sorted lowest to highest here */
259 u32 gmmu_page_sizes[gmmu_nr_page_sizes] = {
260 SZ_4K,
261 big_page_size ? big_page_size : platform->default_big_page_size,
262 SZ_4K
263 };
264
265 gk20a_dbg_fn("");
266
267 if (userspace_managed) {
268 nvgpu_err(g,
269 "userspace-managed address spaces not yet supported");
270 return -ENOSYS;
271 }
272
273 big_page_size = gmmu_page_sizes[gmmu_page_size_big];
274
275 vm = nvgpu_kzalloc(g, sizeof(*vm));
276 if (!vm)
277 return -ENOMEM;
278
279 as_share->vm = vm;
280
281 vm->mm = mm;
282 vm->as_share = as_share;
283
284 /* Set up vma pointers. */
285 vm->vma[0] = &vm->user;
286 vm->vma[1] = &vm->user;
287 vm->vma[2] = &vm->kernel;
288
289 for (i = 0; i < gmmu_nr_page_sizes; i++)
290 vm->gmmu_page_sizes[i] = gmmu_page_sizes[i];
291
292 vm->big_pages = !mm->disable_bigpage;
293 vm->big_page_size = big_page_size;
294
295 vm->va_start = big_page_size << 10; /* create a one pde hole */
296 vm->va_limit = mm->channel.user_size + mm->channel.kernel_size;
297
298 msg.cmd = TEGRA_VGPU_CMD_AS_ALLOC_SHARE;
299 msg.handle = vgpu_get_handle(g);
300 p->size = vm->va_limit;
301 p->big_page_size = vm->big_page_size;
302 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
303 if (err || msg.ret) {
304 err = -ENOMEM;
305 goto clean_up;
306 }
307
308 vm->handle = p->handle;
309
310 /* setup vma limits */
311 user_vma_start = vm->va_start;
312 user_vma_limit = vm->va_limit - mm->channel.kernel_size;
313
314 kernel_vma_start = vm->va_limit - mm->channel.kernel_size;
315 kernel_vma_limit = vm->va_limit;
316
317 gk20a_dbg_info(
318 "user_vma=[0x%llx,0x%llx) kernel_vma=[0x%llx,0x%llx)\n",
319 user_vma_start, user_vma_limit,
320 kernel_vma_start, kernel_vma_limit);
321
322 WARN_ON(user_vma_start > user_vma_limit);
323 WARN_ON(kernel_vma_start >= kernel_vma_limit);
324
325 if (user_vma_start > user_vma_limit ||
326 kernel_vma_start >= kernel_vma_limit) {
327 err = -EINVAL;
328 goto clean_up_share;
329 }
330
331 if (user_vma_start < user_vma_limit) {
332 snprintf(name, sizeof(name), "gk20a_as_%d-%dKB", as_share->id,
333 gmmu_page_sizes[gmmu_page_size_small] >> 10);
334 if (!nvgpu_big_pages_possible(vm, user_vma_start,
335 user_vma_limit - user_vma_start))
336 vm->big_pages = false;
337
338 err = __nvgpu_buddy_allocator_init(
339 g,
340 vm->vma[gmmu_page_size_small],
341 vm, name,
342 user_vma_start,
343 user_vma_limit - user_vma_start,
344 SZ_4K,
345 GPU_BALLOC_MAX_ORDER,
346 GPU_ALLOC_GVA_SPACE);
347 if (err)
348 goto clean_up_share;
349 } else {
350 /*
351 * Make these allocator pointers point to the kernel allocator
352 * since we still use the legacy notion of page size to choose
353 * the allocator.
354 */
355 vm->vma[0] = &vm->kernel;
356 vm->vma[1] = &vm->kernel;
357 }
358
359 snprintf(name, sizeof(name), "gk20a_as_%dKB-sys",
360 gmmu_page_sizes[gmmu_page_size_kernel] >> 10);
361 if (!nvgpu_big_pages_possible(vm, kernel_vma_start,
362 kernel_vma_limit - kernel_vma_start))
363 vm->big_pages = false;
364
365 /*
366 * kernel reserved VMA is at the end of the aperture
367 */
368 err = __nvgpu_buddy_allocator_init(
369 g,
370 vm->vma[gmmu_page_size_kernel],
371 vm, name,
372 kernel_vma_start,
373 kernel_vma_limit - kernel_vma_start,
374 SZ_4K,
375 GPU_BALLOC_MAX_ORDER,
376 GPU_ALLOC_GVA_SPACE);
377 if (err)
378 goto clean_up_user_allocator;
379
380 vm->mapped_buffers = NULL;
381
382 nvgpu_mutex_init(&vm->update_gmmu_lock);
383 kref_init(&vm->ref);
384 nvgpu_init_list_node(&vm->vm_area_list);
385
386 vm->enable_ctag = true;
387
388 return 0;
389
390clean_up_user_allocator:
391 if (user_vma_start < user_vma_limit)
392 nvgpu_alloc_destroy(&vm->user);
393clean_up_share:
394 msg.cmd = TEGRA_VGPU_CMD_AS_FREE_SHARE;
395 msg.handle = vgpu_get_handle(g);
396 p->handle = vm->handle;
397 WARN_ON(vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)) || msg.ret);
398clean_up:
399 nvgpu_kfree(g, vm);
400 as_share->vm = NULL;
401 return err;
402}
403
404static int vgpu_vm_bind_channel(struct gk20a_as_share *as_share, 272static int vgpu_vm_bind_channel(struct gk20a_as_share *as_share,
405 struct channel_gk20a *ch) 273 struct channel_gk20a *ch)
406{ 274{
@@ -501,7 +369,6 @@ void vgpu_init_mm_ops(struct gpu_ops *gops)
501 gops->fb.set_debug_mode = vgpu_mm_mmu_set_debug_mode; 369 gops->fb.set_debug_mode = vgpu_mm_mmu_set_debug_mode;
502 gops->mm.gmmu_map = vgpu_locked_gmmu_map; 370 gops->mm.gmmu_map = vgpu_locked_gmmu_map;
503 gops->mm.gmmu_unmap = vgpu_locked_gmmu_unmap; 371 gops->mm.gmmu_unmap = vgpu_locked_gmmu_unmap;
504 gops->mm.vm_alloc_share = vgpu_vm_alloc_share;
505 gops->mm.vm_bind_channel = vgpu_vm_bind_channel; 372 gops->mm.vm_bind_channel = vgpu_vm_bind_channel;
506 gops->mm.fb_flush = vgpu_mm_fb_flush; 373 gops->mm.fb_flush = vgpu_mm_fb_flush;
507 gops->mm.l2_invalidate = vgpu_mm_l2_invalidate; 374 gops->mm.l2_invalidate = vgpu_mm_l2_invalidate;