summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/vgpu/mm_vgpu.c
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2017-05-09 19:41:18 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-06-06 20:09:11 -0400
commitc2b63150cd947557b8d17637258b988459b8e0ec (patch)
tree5b15911b0b4799538ca98c9b6c1a31c0cbfe4a99 /drivers/gpu/nvgpu/vgpu/mm_vgpu.c
parent6bd7d22c0f248d0d29ea44b06798b247d0d2753a (diff)
gpu: nvgpu: Unify vm_init for vGPU and regular GPU
Unify the initialization routines for the vGPU and regular GPU paths. This helps avoid any further code divergence. This also assumes that the code running on the regular GPU essentially works for the vGPU. The only addition is that the regular GPU path calls an API in the vGPU code that sends the necessary RM server message. JIRA NVGPU-12 JIRA NVGPU-30 Change-Id: I37af1993fd8b50f666ae27524d382cce49cf28f7 Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: http://git-master/r/1480226 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
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;