summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2017-04-25 18:56:12 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-05-19 18:34:12 -0400
commit29cc82844e03b6f9f0e6801169b6fa0e72d56628 (patch)
treef616b6c651ce80765ee344aa33ca204c555e67f2 /drivers/gpu/nvgpu
parent014ace5a85f274de7debb4c6168d69c803445e19 (diff)
gpu: nvgpu: Split vm_area management into vm code
The vm_reserve_va_node struct is essentially a special VM area that can be used for sparse mappings and fixed mappings. The name of this struct is somewhat confusing (as node is typically used for list items). Though this struct is a part of a list it doesn't really make sense to call this a list item since it's much more. Based on that the struct has been renamed to nvgpu_vm_area to capture the actual use of the struct more accurately. This also moves all of the management code of vm areas to a new file devoted solely to vm_area management. Also add a brief overview of the VM architecture. This should help other people follow along the hierachy of ownership and lifetimes in the rather complex MM code. JIRA NVGPU-12 JIRA NVGPU-30 Change-Id: If85e1cf868031d0dc265e7bed50b58a2aed2602e Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: http://git-master/r/1477744 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r--drivers/gpu/nvgpu/Makefile.nvgpu1
-rw-r--r--drivers/gpu/nvgpu/common/linux/ioctl_as.c6
-rw-r--r--drivers/gpu/nvgpu/common/linux/vm.c14
-rw-r--r--drivers/gpu/nvgpu/common/linux/vm_priv.h3
-rw-r--r--drivers/gpu/nvgpu/common/mm/vm.c13
-rw-r--r--drivers/gpu/nvgpu/gk20a/mm_gk20a.c241
-rw-r--r--drivers/gpu/nvgpu/gk20a/mm_gk20a.h21
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/as.h10
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/vm.h41
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/vm_area.h63
-rw-r--r--drivers/gpu/nvgpu/vgpu/mm_vgpu.c15
11 files changed, 146 insertions, 282 deletions
diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu
index 2f9d1b36..6bbf49a5 100644
--- a/drivers/gpu/nvgpu/Makefile.nvgpu
+++ b/drivers/gpu/nvgpu/Makefile.nvgpu
@@ -47,6 +47,7 @@ nvgpu-y := \
47 common/mm/lockless_allocator.o \ 47 common/mm/lockless_allocator.o \
48 common/mm/gmmu.o \ 48 common/mm/gmmu.o \
49 common/mm/vm.o \ 49 common/mm/vm.o \
50 common/mm/vm_area.o \
50 common/pramin.o \ 51 common/pramin.o \
51 common/semaphore.o \ 52 common/semaphore.o \
52 common/as.o \ 53 common/as.o \
diff --git a/drivers/gpu/nvgpu/common/linux/ioctl_as.c b/drivers/gpu/nvgpu/common/linux/ioctl_as.c
index 7a24a14f..023f8236 100644
--- a/drivers/gpu/nvgpu/common/linux/ioctl_as.c
+++ b/drivers/gpu/nvgpu/common/linux/ioctl_as.c
@@ -24,6 +24,7 @@
24#include <uapi/linux/nvgpu.h> 24#include <uapi/linux/nvgpu.h>
25 25
26#include <nvgpu/gmmu.h> 26#include <nvgpu/gmmu.h>
27#include <nvgpu/vm_area.h>
27 28
28#include "gk20a/gk20a.h" 29#include "gk20a/gk20a.h"
29#include "gk20a/platform_gk20a.h" 30#include "gk20a/platform_gk20a.h"
@@ -56,7 +57,8 @@ static int gk20a_as_ioctl_alloc_space(
56 struct nvgpu_as_alloc_space_args *args) 57 struct nvgpu_as_alloc_space_args *args)
57{ 58{
58 gk20a_dbg_fn(""); 59 gk20a_dbg_fn("");
59 return gk20a_vm_alloc_space(as_share, args); 60 return nvgpu_vm_area_alloc(as_share->vm, args->pages, args->page_size,
61 &args->o_a.offset, args->flags);
60} 62}
61 63
62static int gk20a_as_ioctl_free_space( 64static int gk20a_as_ioctl_free_space(
@@ -64,7 +66,7 @@ static int gk20a_as_ioctl_free_space(
64 struct nvgpu_as_free_space_args *args) 66 struct nvgpu_as_free_space_args *args)
65{ 67{
66 gk20a_dbg_fn(""); 68 gk20a_dbg_fn("");
67 return gk20a_vm_free_space(as_share, args); 69 return nvgpu_vm_area_free(as_share->vm, args->offset);
68} 70}
69 71
70static int gk20a_as_ioctl_map_buffer_ex( 72static int gk20a_as_ioctl_map_buffer_ex(
diff --git a/drivers/gpu/nvgpu/common/linux/vm.c b/drivers/gpu/nvgpu/common/linux/vm.c
index 8b9d6f96..5470d9ee 100644
--- a/drivers/gpu/nvgpu/common/linux/vm.c
+++ b/drivers/gpu/nvgpu/common/linux/vm.c
@@ -20,6 +20,7 @@
20#include <nvgpu/log.h> 20#include <nvgpu/log.h>
21#include <nvgpu/lock.h> 21#include <nvgpu/lock.h>
22#include <nvgpu/rbtree.h> 22#include <nvgpu/rbtree.h>
23#include <nvgpu/vm_area.h>
23#include <nvgpu/page_allocator.h> 24#include <nvgpu/page_allocator.h>
24 25
25#include "gk20a/gk20a.h" 26#include "gk20a/gk20a.h"
@@ -196,7 +197,7 @@ u64 nvgpu_vm_map(struct vm_gk20a *vm,
196 struct scatterlist *sgl; 197 struct scatterlist *sgl;
197 u64 ctag_map_win_size = 0; 198 u64 ctag_map_win_size = 0;
198 u32 ctag_map_win_ctagline = 0; 199 u32 ctag_map_win_ctagline = 0;
199 struct vm_reserved_va_node *va_node = NULL; 200 struct nvgpu_vm_area *vm_area = NULL;
200 u32 ctag_offset; 201 u32 ctag_offset;
201 enum nvgpu_aperture aperture; 202 enum nvgpu_aperture aperture;
202 203
@@ -256,9 +257,8 @@ u64 nvgpu_vm_map(struct vm_gk20a *vm,
256 257
257 /* Check if we should use a fixed offset for mapping this buffer */ 258 /* Check if we should use a fixed offset for mapping this buffer */
258 if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) { 259 if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) {
259 err = validate_fixed_buffer(vm, &bfr, 260 err = nvgpu_vm_area_validate_buffer(vm, offset_align, mapping_size,
260 offset_align, mapping_size, 261 bfr.pgsz_idx, &vm_area);
261 &va_node);
262 if (err) 262 if (err)
263 goto clean_up; 263 goto clean_up;
264 264
@@ -376,10 +376,10 @@ u64 nvgpu_vm_map(struct vm_gk20a *vm,
376 if (user_mapped) 376 if (user_mapped)
377 vm->num_user_mapped_buffers++; 377 vm->num_user_mapped_buffers++;
378 378
379 if (va_node) { 379 if (vm_area) {
380 nvgpu_list_add_tail(&mapped_buffer->buffer_list, 380 nvgpu_list_add_tail(&mapped_buffer->buffer_list,
381 &va_node->buffer_list_head); 381 &vm_area->buffer_list_head);
382 mapped_buffer->va_node = va_node; 382 mapped_buffer->vm_area = vm_area;
383 } 383 }
384 384
385 nvgpu_mutex_release(&vm->update_gmmu_lock); 385 nvgpu_mutex_release(&vm->update_gmmu_lock);
diff --git a/drivers/gpu/nvgpu/common/linux/vm_priv.h b/drivers/gpu/nvgpu/common/linux/vm_priv.h
index 9e064d76..14852264 100644
--- a/drivers/gpu/nvgpu/common/linux/vm_priv.h
+++ b/drivers/gpu/nvgpu/common/linux/vm_priv.h
@@ -77,7 +77,7 @@ enum nvgpu_aperture gk20a_dmabuf_aperture(struct gk20a *g,
77int validate_fixed_buffer(struct vm_gk20a *vm, 77int validate_fixed_buffer(struct vm_gk20a *vm,
78 struct buffer_attrs *bfr, 78 struct buffer_attrs *bfr,
79 u64 map_offset, u64 map_size, 79 u64 map_offset, u64 map_size,
80 struct vm_reserved_va_node **pva_node); 80 struct nvgpu_vm_area **pva_node);
81int setup_buffer_kind_and_compression(struct vm_gk20a *vm, 81int setup_buffer_kind_and_compression(struct vm_gk20a *vm,
82 u32 flags, 82 u32 flags,
83 struct buffer_attrs *bfr, 83 struct buffer_attrs *bfr,
@@ -89,6 +89,5 @@ int gk20a_alloc_comptags(struct gk20a *g,
89 u32 lines, bool user_mappable, 89 u32 lines, bool user_mappable,
90 u64 *ctag_map_win_size, 90 u64 *ctag_map_win_size,
91 u32 *ctag_map_win_ctagline); 91 u32 *ctag_map_win_ctagline);
92void gk20a_vm_unmap_locked_kref(struct kref *ref);
93 92
94#endif 93#endif
diff --git a/drivers/gpu/nvgpu/common/mm/vm.c b/drivers/gpu/nvgpu/common/mm/vm.c
index 635ac0fb..3bdc905e 100644
--- a/drivers/gpu/nvgpu/common/mm/vm.c
+++ b/drivers/gpu/nvgpu/common/mm/vm.c
@@ -15,6 +15,7 @@
15 */ 15 */
16 16
17#include <nvgpu/vm.h> 17#include <nvgpu/vm.h>
18#include <nvgpu/vm_area.h>
18#include <nvgpu/lock.h> 19#include <nvgpu/lock.h>
19#include <nvgpu/list.h> 20#include <nvgpu/list.h>
20#include <nvgpu/rbtree.h> 21#include <nvgpu/rbtree.h>
@@ -58,7 +59,7 @@ void nvgpu_vm_mapping_batch_finish(struct vm_gk20a *vm,
58void nvgpu_vm_remove_support_nofree(struct vm_gk20a *vm) 59void nvgpu_vm_remove_support_nofree(struct vm_gk20a *vm)
59{ 60{
60 struct nvgpu_mapped_buf *mapped_buffer; 61 struct nvgpu_mapped_buf *mapped_buffer;
61 struct vm_reserved_va_node *va_node, *va_node_tmp; 62 struct nvgpu_vm_area *vm_area, *vm_area_tmp;
62 struct nvgpu_rbtree_node *node = NULL; 63 struct nvgpu_rbtree_node *node = NULL;
63 struct gk20a *g = vm->mm->g; 64 struct gk20a *g = vm->mm->g;
64 65
@@ -86,11 +87,11 @@ void nvgpu_vm_remove_support_nofree(struct vm_gk20a *vm)
86 } 87 }
87 88
88 /* destroy remaining reserved memory areas */ 89 /* destroy remaining reserved memory areas */
89 nvgpu_list_for_each_entry_safe(va_node, va_node_tmp, 90 nvgpu_list_for_each_entry_safe(vm_area, vm_area_tmp,
90 &vm->reserved_va_list, 91 &vm->vm_area_list,
91 vm_reserved_va_node, reserved_va_list) { 92 nvgpu_vm_area, vm_area_list) {
92 nvgpu_list_del(&va_node->reserved_va_list); 93 nvgpu_list_del(&vm_area->vm_area_list);
93 nvgpu_kfree(vm->mm->g, va_node); 94 nvgpu_kfree(vm->mm->g, vm_area);
94 } 95 }
95 96
96 nvgpu_deinit_vm(vm); 97 nvgpu_deinit_vm(vm);
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
index 84919d50..5051f028 100644
--- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
@@ -26,6 +26,7 @@
26#include <trace/events/gk20a.h> 26#include <trace/events/gk20a.h>
27 27
28#include <nvgpu/vm.h> 28#include <nvgpu/vm.h>
29#include <nvgpu/vm_area.h>
29#include <nvgpu/dma.h> 30#include <nvgpu/dma.h>
30#include <nvgpu/kmem.h> 31#include <nvgpu/kmem.h>
31#include <nvgpu/timers.h> 32#include <nvgpu/timers.h>
@@ -1065,19 +1066,6 @@ u32 pte_index_from_vaddr(struct vm_gk20a *vm,
1065 return ret; 1066 return ret;
1066} 1067}
1067 1068
1068static struct vm_reserved_va_node *addr_to_reservation(struct vm_gk20a *vm,
1069 u64 addr)
1070{
1071 struct vm_reserved_va_node *va_node;
1072 nvgpu_list_for_each_entry(va_node, &vm->reserved_va_list,
1073 vm_reserved_va_node, reserved_va_list)
1074 if (addr >= va_node->vaddr_start &&
1075 addr < (u64)va_node->vaddr_start + (u64)va_node->size)
1076 return va_node;
1077
1078 return NULL;
1079}
1080
1081int nvgpu_vm_get_buffers(struct vm_gk20a *vm, 1069int nvgpu_vm_get_buffers(struct vm_gk20a *vm,
1082 struct nvgpu_mapped_buf ***mapped_buffers, 1070 struct nvgpu_mapped_buf ***mapped_buffers,
1083 int *num_buffers) 1071 int *num_buffers)
@@ -1301,57 +1289,6 @@ int setup_buffer_kind_and_compression(struct vm_gk20a *vm,
1301 return 0; 1289 return 0;
1302} 1290}
1303 1291
1304int validate_fixed_buffer(struct vm_gk20a *vm,
1305 struct buffer_attrs *bfr,
1306 u64 map_offset, u64 map_size,
1307 struct vm_reserved_va_node **pva_node)
1308{
1309 struct gk20a *g = vm->mm->g;
1310 struct vm_reserved_va_node *va_node;
1311 struct nvgpu_mapped_buf *buffer;
1312 u64 map_end = map_offset + map_size;
1313
1314 /* can wrap around with insane map_size; zero is disallowed too */
1315 if (map_end <= map_offset) {
1316 nvgpu_warn(g, "fixed offset mapping with invalid map_size");
1317 return -EINVAL;
1318 }
1319
1320 if (map_offset & (vm->gmmu_page_sizes[bfr->pgsz_idx] - 1)) {
1321 nvgpu_err(g, "map offset must be buffer page size aligned 0x%llx",
1322 map_offset);
1323 return -EINVAL;
1324 }
1325
1326 /* Find the space reservation, but it's ok to have none for
1327 * userspace-managed address spaces */
1328 va_node = addr_to_reservation(vm, map_offset);
1329 if (!va_node && !vm->userspace_managed) {
1330 nvgpu_warn(g, "fixed offset mapping without space allocation");
1331 return -EINVAL;
1332 }
1333
1334 /* Mapped area should fit inside va, if there's one */
1335 if (va_node && map_end > va_node->vaddr_start + va_node->size) {
1336 nvgpu_warn(g, "fixed offset mapping size overflows va node");
1337 return -EINVAL;
1338 }
1339
1340 /* check that this mapping does not collide with existing
1341 * mappings by checking the buffer with the highest GPU VA
1342 * that is less than our buffer end */
1343 buffer = __nvgpu_vm_find_mapped_buf_less_than(
1344 vm, map_offset + map_size);
1345 if (buffer && buffer->addr + buffer->size > map_offset) {
1346 nvgpu_warn(g, "overlapping buffer map requested");
1347 return -EINVAL;
1348 }
1349
1350 *pva_node = va_node;
1351
1352 return 0;
1353}
1354
1355u64 gk20a_locked_gmmu_map(struct vm_gk20a *vm, 1292u64 gk20a_locked_gmmu_map(struct vm_gk20a *vm,
1356 u64 map_offset, 1293 u64 map_offset,
1357 struct sg_table *sgt, 1294 struct sg_table *sgt,
@@ -1850,22 +1787,22 @@ int nvgpu_vm_map_compbits(struct vm_gk20a *vm,
1850 if (fixed_mapping) { 1787 if (fixed_mapping) {
1851 struct buffer_attrs bfr; 1788 struct buffer_attrs bfr;
1852 int err; 1789 int err;
1853 struct vm_reserved_va_node *va_node = NULL; 1790 struct nvgpu_vm_area *vm_area = NULL;
1854 1791
1855 memset(&bfr, 0, sizeof(bfr)); 1792 memset(&bfr, 0, sizeof(bfr));
1856 1793
1857 bfr.pgsz_idx = small_pgsz_index; 1794 bfr.pgsz_idx = small_pgsz_index;
1858 1795
1859 err = validate_fixed_buffer( 1796 err = nvgpu_vm_area_validate_buffer(
1860 vm, &bfr, *compbits_win_gva, 1797 vm, *compbits_win_gva, mapped_buffer->ctag_map_win_size,
1861 mapped_buffer->ctag_map_win_size, &va_node); 1798 bfr.pgsz_idx, &vm_area);
1862 1799
1863 if (err) { 1800 if (err) {
1864 nvgpu_mutex_release(&vm->update_gmmu_lock); 1801 nvgpu_mutex_release(&vm->update_gmmu_lock);
1865 return err; 1802 return err;
1866 } 1803 }
1867 1804
1868 if (va_node) { 1805 if (vm_area) {
1869 /* this would create a dangling GPU VA 1806 /* this would create a dangling GPU VA
1870 * pointer if the space is freed 1807 * pointer if the space is freed
1871 * before before the buffer is 1808 * before before the buffer is
@@ -2564,8 +2501,8 @@ void nvgpu_vm_unmap_locked(struct nvgpu_mapped_buf *mapped_buffer,
2564 mapped_buffer->pgsz_idx, 2501 mapped_buffer->pgsz_idx,
2565 mapped_buffer->va_allocated, 2502 mapped_buffer->va_allocated,
2566 gk20a_mem_flag_none, 2503 gk20a_mem_flag_none,
2567 mapped_buffer->va_node ? 2504 mapped_buffer->vm_area ?
2568 mapped_buffer->va_node->sparse : false, 2505 mapped_buffer->vm_area->sparse : false,
2569 batch); 2506 batch);
2570 2507
2571 gk20a_dbg(gpu_dbg_map, 2508 gk20a_dbg(gpu_dbg_map,
@@ -2712,13 +2649,13 @@ int gk20a_big_pages_possible(struct vm_gk20a *vm, u64 base, u64 size)
2712enum gmmu_pgsz_gk20a __get_pte_size_fixed_map(struct vm_gk20a *vm, 2649enum gmmu_pgsz_gk20a __get_pte_size_fixed_map(struct vm_gk20a *vm,
2713 u64 base, u64 size) 2650 u64 base, u64 size)
2714{ 2651{
2715 struct vm_reserved_va_node *node; 2652 struct nvgpu_vm_area *vm_area;
2716 2653
2717 node = addr_to_reservation(vm, base); 2654 vm_area = nvgpu_vm_area_find(vm, base);
2718 if (!node) 2655 if (!vm_area)
2719 return gmmu_page_size_small; 2656 return gmmu_page_size_small;
2720 2657
2721 return node->pgsz_idx; 2658 return vm_area->pgsz_idx;
2722} 2659}
2723 2660
2724/* 2661/*
@@ -3012,7 +2949,7 @@ int nvgpu_init_vm(struct mm_gk20a *mm,
3012 2949
3013 nvgpu_mutex_init(&vm->update_gmmu_lock); 2950 nvgpu_mutex_init(&vm->update_gmmu_lock);
3014 kref_init(&vm->ref); 2951 kref_init(&vm->ref);
3015 nvgpu_init_list_node(&vm->reserved_va_list); 2952 nvgpu_init_list_node(&vm->vm_area_list);
3016 2953
3017 /* 2954 /*
3018 * This is only necessary for channel address spaces. The best way to 2955 * This is only necessary for channel address spaces. The best way to
@@ -3100,158 +3037,6 @@ int gk20a_vm_release_share(struct gk20a_as_share *as_share)
3100 return 0; 3037 return 0;
3101} 3038}
3102 3039
3103
3104int gk20a_vm_alloc_space(struct gk20a_as_share *as_share,
3105 struct nvgpu_as_alloc_space_args *args)
3106
3107{
3108 int err = -ENOMEM;
3109 int pgsz_idx = gmmu_page_size_small;
3110 struct nvgpu_allocator *vma;
3111 struct vm_gk20a *vm = as_share->vm;
3112 struct gk20a *g = vm->mm->g;
3113 struct vm_reserved_va_node *va_node;
3114 u64 vaddr_start = 0;
3115 int page_sizes = gmmu_nr_page_sizes;
3116
3117 gk20a_dbg_fn("flags=0x%x pgsz=0x%x nr_pages=0x%x o/a=0x%llx",
3118 args->flags, args->page_size, args->pages,
3119 args->o_a.offset);
3120
3121 if (!vm->big_pages)
3122 page_sizes--;
3123
3124 for (; pgsz_idx < page_sizes; pgsz_idx++) {
3125 if (vm->gmmu_page_sizes[pgsz_idx] == args->page_size)
3126 break;
3127 }
3128
3129 if (pgsz_idx >= page_sizes) {
3130 err = -EINVAL;
3131 goto clean_up;
3132 }
3133
3134 va_node = nvgpu_kzalloc(g, sizeof(*va_node));
3135 if (!va_node) {
3136 err = -ENOMEM;
3137 goto clean_up;
3138 }
3139
3140 vma = vm->vma[pgsz_idx];
3141 if (args->flags & NVGPU_AS_ALLOC_SPACE_FLAGS_FIXED_OFFSET)
3142 vaddr_start = nvgpu_alloc_fixed(vma, args->o_a.offset,
3143 (u64)args->pages *
3144 (u64)args->page_size,
3145 args->page_size);
3146 else
3147 vaddr_start = nvgpu_alloc(vma,
3148 (u64)args->pages *
3149 (u64)args->page_size);
3150
3151 if (!vaddr_start) {
3152 nvgpu_kfree(g, va_node);
3153 goto clean_up;
3154 }
3155
3156 va_node->vaddr_start = vaddr_start;
3157 va_node->size = (u64)args->page_size * (u64)args->pages;
3158 va_node->pgsz_idx = pgsz_idx;
3159 nvgpu_init_list_node(&va_node->buffer_list_head);
3160 nvgpu_init_list_node(&va_node->reserved_va_list);
3161
3162 nvgpu_mutex_acquire(&vm->update_gmmu_lock);
3163
3164 /* mark that we need to use sparse mappings here */
3165 if (args->flags & NVGPU_AS_ALLOC_SPACE_FLAGS_SPARSE) {
3166 u64 map_offset = g->ops.mm.gmmu_map(vm, vaddr_start,
3167 NULL,
3168 0,
3169 va_node->size,
3170 pgsz_idx,
3171 0,
3172 0,
3173 args->flags,
3174 gk20a_mem_flag_none,
3175 false,
3176 true,
3177 false,
3178 NULL,
3179 APERTURE_INVALID);
3180 if (!map_offset) {
3181 nvgpu_mutex_release(&vm->update_gmmu_lock);
3182 nvgpu_free(vma, vaddr_start);
3183 nvgpu_kfree(g, va_node);
3184 goto clean_up;
3185 }
3186
3187 va_node->sparse = true;
3188 }
3189 nvgpu_list_add_tail(&va_node->reserved_va_list, &vm->reserved_va_list);
3190
3191 nvgpu_mutex_release(&vm->update_gmmu_lock);
3192
3193 args->o_a.offset = vaddr_start;
3194 err = 0;
3195
3196clean_up:
3197 return err;
3198}
3199
3200int gk20a_vm_free_space(struct gk20a_as_share *as_share,
3201 struct nvgpu_as_free_space_args *args)
3202{
3203 int err = -ENOMEM;
3204 int pgsz_idx;
3205 struct nvgpu_allocator *vma;
3206 struct vm_gk20a *vm = as_share->vm;
3207 struct vm_reserved_va_node *va_node;
3208 struct gk20a *g = gk20a_from_vm(vm);
3209
3210 gk20a_dbg_fn("pgsz=0x%x nr_pages=0x%x o/a=0x%llx", args->page_size,
3211 args->pages, args->offset);
3212
3213 /* determine pagesz idx */
3214 pgsz_idx = __get_pte_size(vm, args->offset,
3215 args->page_size * args->pages);
3216
3217 vma = vm->vma[pgsz_idx];
3218 nvgpu_free(vma, args->offset);
3219
3220 nvgpu_mutex_acquire(&vm->update_gmmu_lock);
3221 va_node = addr_to_reservation(vm, args->offset);
3222 if (va_node) {
3223 struct nvgpu_mapped_buf *buffer, *n;
3224
3225 /* Decrement the ref count on all buffers in this va_node. This
3226 * allows userspace to let the kernel free mappings that are
3227 * only used by this va_node. */
3228 nvgpu_list_for_each_entry_safe(buffer, n,
3229 &va_node->buffer_list_head,
3230 nvgpu_mapped_buf, buffer_list) {
3231 nvgpu_list_del(&buffer->buffer_list);
3232 kref_put(&buffer->ref, gk20a_vm_unmap_locked_kref);
3233 }
3234
3235 nvgpu_list_del(&va_node->reserved_va_list);
3236
3237 /* if this was a sparse mapping, free the va */
3238 if (va_node->sparse)
3239 g->ops.mm.gmmu_unmap(vm,
3240 va_node->vaddr_start,
3241 va_node->size,
3242 va_node->pgsz_idx,
3243 true,
3244 gk20a_mem_flag_none,
3245 true,
3246 NULL);
3247 nvgpu_kfree(g, va_node);
3248 }
3249 nvgpu_mutex_release(&vm->update_gmmu_lock);
3250 err = 0;
3251
3252 return err;
3253}
3254
3255int __gk20a_vm_bind_channel(struct vm_gk20a *vm, struct channel_gk20a *ch) 3040int __gk20a_vm_bind_channel(struct vm_gk20a *vm, struct channel_gk20a *ch)
3256{ 3041{
3257 int err = 0; 3042 int err = 0;
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h
index 357962c7..6ddf842a 100644
--- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h
@@ -140,22 +140,6 @@ struct priv_cmd_entry {
140 u32 size; /* in words */ 140 u32 size; /* in words */
141}; 141};
142 142
143struct vm_reserved_va_node {
144 struct nvgpu_list_node reserved_va_list;
145 struct nvgpu_list_node buffer_list_head;
146 u32 pgsz_idx;
147 u64 vaddr_start;
148 u64 size;
149 bool sparse;
150};
151
152static inline struct vm_reserved_va_node *
153vm_reserved_va_node_from_reserved_va_list(struct nvgpu_list_node *node)
154{
155 return (struct vm_reserved_va_node *)
156 ((uintptr_t)node - offsetof(struct vm_reserved_va_node, reserved_va_list));
157};
158
159struct gk20a; 143struct gk20a;
160struct channel_gk20a; 144struct channel_gk20a;
161 145
@@ -442,10 +426,6 @@ struct nvgpu_as_free_space_args;
442int gk20a_vm_alloc_share(struct gk20a_as_share *as_share, u32 big_page_size, 426int gk20a_vm_alloc_share(struct gk20a_as_share *as_share, u32 big_page_size,
443 u32 flags); 427 u32 flags);
444int gk20a_vm_release_share(struct gk20a_as_share *as_share); 428int gk20a_vm_release_share(struct gk20a_as_share *as_share);
445int gk20a_vm_alloc_space(struct gk20a_as_share *as_share,
446 struct nvgpu_as_alloc_space_args *args);
447int gk20a_vm_free_space(struct gk20a_as_share *as_share,
448 struct nvgpu_as_free_space_args *args);
449int gk20a_vm_bind_channel(struct gk20a_as_share *as_share, 429int gk20a_vm_bind_channel(struct gk20a_as_share *as_share,
450 struct channel_gk20a *ch); 430 struct channel_gk20a *ch);
451int __gk20a_vm_bind_channel(struct vm_gk20a *vm, struct channel_gk20a *ch); 431int __gk20a_vm_bind_channel(struct vm_gk20a *vm, struct channel_gk20a *ch);
@@ -491,5 +471,6 @@ extern const struct gk20a_mmu_level gk20a_mm_levels_128k[];
491 471
492int gk20a_mm_get_buffer_info(struct device *dev, int dmabuf_fd, 472int gk20a_mm_get_buffer_info(struct device *dev, int dmabuf_fd,
493 u64 *buffer_id, u64 *buffer_len); 473 u64 *buffer_id, u64 *buffer_len);
474void gk20a_vm_unmap_locked_kref(struct kref *ref);
494 475
495#endif /* MM_GK20A_H */ 476#endif /* MM_GK20A_H */
diff --git a/drivers/gpu/nvgpu/include/nvgpu/as.h b/drivers/gpu/nvgpu/include/nvgpu/as.h
index 0e784396..e3233f87 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/as.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/as.h
@@ -17,14 +17,14 @@
17 17
18struct vm_gk20a; 18struct vm_gk20a;
19 19
20struct gk20a_as {
21 int last_share_id; /* dummy allocator for now */
22};
23
20struct gk20a_as_share { 24struct gk20a_as_share {
21 struct gk20a_as *as; 25 struct gk20a_as *as;
22 int id;
23 struct vm_gk20a *vm; 26 struct vm_gk20a *vm;
24}; 27 int id;
25
26struct gk20a_as {
27 int last_share_id; /* dummy allocator for now */
28}; 28};
29 29
30int gk20a_as_release_share(struct gk20a_as_share *as_share); 30int gk20a_as_release_share(struct gk20a_as_share *as_share);
diff --git a/drivers/gpu/nvgpu/include/nvgpu/vm.h b/drivers/gpu/nvgpu/include/nvgpu/vm.h
index e1ceffd4..69c08c77 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/vm.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/vm.h
@@ -26,11 +26,10 @@
26#include <nvgpu/allocator.h> 26#include <nvgpu/allocator.h>
27 27
28struct vm_gk20a; 28struct vm_gk20a;
29struct vm_reserved_va_node; 29struct nvgpu_vm_area;
30struct buffer_attrs; 30struct buffer_attrs;
31struct gk20a_comptag_allocator; 31struct gk20a_comptag_allocator;
32 32
33
34/** 33/**
35 * This header contains the OS agnostic APIs for dealing with VMs. Most of the 34 * This header contains the OS agnostic APIs for dealing with VMs. Most of the
36 * VM implementation is system specific - it must translate from a platform's 35 * VM implementation is system specific - it must translate from a platform's
@@ -39,6 +38,38 @@ struct gk20a_comptag_allocator;
39 * However, some stuff is platform agnostic. VM ref-counting and the VM struct 38 * However, some stuff is platform agnostic. VM ref-counting and the VM struct
40 * itself are platform agnostic. Also, the initialization and destruction of 39 * itself are platform agnostic. Also, the initialization and destruction of
41 * VMs is the same across all platforms (for now). 40 * VMs is the same across all platforms (for now).
41 *
42 * VM Architecture:
43 * ----------------
44 *
45 * The VM managment in nvgpu is split up as follows: a vm_gk20a struct which
46 * defines an address space. Each address space is a set of page tables and a
47 * GPU Virtual Address (GVA) allocator. Any number of channels may bind to a VM.
48 *
49 * +----+ +----+ +----+ +-----+ +-----+
50 * | C1 | | C2 | ... | Cn | | VM1 | ... | VMn |
51 * +-+--+ +-+--+ +-+--+ +--+--+ +--+--+
52 * | | | | |
53 * | | +----->-----+ |
54 * | +---------------->-----+ |
55 * +------------------------>-----------------+
56 *
57 * Each VM also manages a set of mapped buffers (struct nvgpu_mapped_buf)
58 * which corresponds to _user space_ buffers which have been mapped into this VM.
59 * Kernel space mappings (created by nvgpu_gmmu_map()) are not tracked by VMs.
60 * This may be an architectural bug, but for now it seems to be OK. VMs can be
61 * closed in various ways - refs counts hitting zero, direct calls to the remove
62 * routine, etc. Note: this is going to change. VM cleanup is going to be
63 * homogonized around ref-counts. When a VM is closed all mapped buffers in the
64 * VM are unmapped from the GMMU. This means that those mappings will no longer
65 * be valid and any subsequent access by the GPU will fault. That means one must
66 * ensure the VM is not in use before closing it.
67 *
68 * VMs may also contain VM areas (struct nvgpu_vm_area) which are created for
69 * the purpose of sparse and/or fixed mappings. If userspace wishes to create a
70 * fixed mapping it must first create a VM area - either with a fixed address or
71 * not. VM areas are reserved - other mapping operations will not use the space.
72 * Userspace may then create fixed mappings within that VM area.
42 */ 73 */
43 74
44/* map/unmap batch state */ 75/* map/unmap batch state */
@@ -49,9 +80,10 @@ struct vm_gk20a_mapping_batch {
49 80
50struct nvgpu_mapped_buf { 81struct nvgpu_mapped_buf {
51 struct vm_gk20a *vm; 82 struct vm_gk20a *vm;
83 struct nvgpu_vm_area *vm_area;
84
52 struct nvgpu_rbtree_node node; 85 struct nvgpu_rbtree_node node;
53 struct nvgpu_list_node buffer_list; 86 struct nvgpu_list_node buffer_list;
54 struct vm_reserved_va_node *va_node;
55 u64 addr; 87 u64 addr;
56 u64 size; 88 u64 size;
57 struct dma_buf *dmabuf; 89 struct dma_buf *dmabuf;
@@ -102,7 +134,6 @@ struct vm_gk20a {
102 134
103 bool big_pages; /* enable large page support */ 135 bool big_pages; /* enable large page support */
104 bool enable_ctag; 136 bool enable_ctag;
105 bool mapped;
106 137
107 u32 big_page_size; 138 u32 big_page_size;
108 139
@@ -129,7 +160,7 @@ struct vm_gk20a {
129 160
130 struct nvgpu_rbtree_node *mapped_buffers; 161 struct nvgpu_rbtree_node *mapped_buffers;
131 162
132 struct nvgpu_list_node reserved_va_list; 163 struct nvgpu_list_node vm_area_list;
133 164
134#ifdef CONFIG_TEGRA_GR_VIRTUALIZATION 165#ifdef CONFIG_TEGRA_GR_VIRTUALIZATION
135 u64 handle; 166 u64 handle;
diff --git a/drivers/gpu/nvgpu/include/nvgpu/vm_area.h b/drivers/gpu/nvgpu/include/nvgpu/vm_area.h
new file mode 100644
index 00000000..ffe4b99b
--- /dev/null
+++ b/drivers/gpu/nvgpu/include/nvgpu/vm_area.h
@@ -0,0 +1,63 @@
1/*
2 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef __NVGPU_VM_AREA_H__
18#define __NVGPU_VM_AREA_H__
19
20#include <nvgpu/list.h>
21#include <nvgpu/types.h>
22
23struct vm_gk20a;
24struct gk20a_as_share;
25struct nvgpu_as_alloc_space_args;
26struct nvgpu_as_free_space_args;
27
28struct nvgpu_vm_area {
29 /*
30 * Entry into the list of VM areas owned by a VM.
31 */
32 struct nvgpu_list_node vm_area_list;
33
34 /*
35 * List of buffers mapped into this vm_area.
36 */
37 struct nvgpu_list_node buffer_list_head;
38
39 u32 flags;
40 u32 pgsz_idx;
41 u64 addr;
42 u64 size;
43 bool sparse;
44};
45
46static inline struct nvgpu_vm_area *
47nvgpu_vm_area_from_vm_area_list(struct nvgpu_list_node *node)
48{
49 return (struct nvgpu_vm_area *)
50 ((uintptr_t)node - offsetof(struct nvgpu_vm_area,
51 vm_area_list));
52};
53
54int nvgpu_vm_area_alloc(struct vm_gk20a *vm, u32 pages, u32 page_size,
55 u64 *addr, u32 flags);
56int nvgpu_vm_area_free(struct vm_gk20a *vm, u64 addr);
57
58struct nvgpu_vm_area *nvgpu_vm_area_find(struct vm_gk20a *vm, u64 addr);
59int nvgpu_vm_area_validate_buffer(struct vm_gk20a *vm,
60 u64 map_offset, u64 map_size, int pgsz_idx,
61 struct nvgpu_vm_area **pvm_area);
62
63#endif
diff --git a/drivers/gpu/nvgpu/vgpu/mm_vgpu.c b/drivers/gpu/nvgpu/vgpu/mm_vgpu.c
index f4004f42..b42fbcb3 100644
--- a/drivers/gpu/nvgpu/vgpu/mm_vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/mm_vgpu.c
@@ -18,6 +18,7 @@
18#include <nvgpu/kmem.h> 18#include <nvgpu/kmem.h>
19#include <nvgpu/dma.h> 19#include <nvgpu/dma.h>
20#include <nvgpu/bug.h> 20#include <nvgpu/bug.h>
21#include <nvgpu/vm_area.h>
21 22
22#include "vgpu/vgpu.h" 23#include "vgpu/vgpu.h"
23#include "gk20a/mm_gk20a.h" 24#include "gk20a/mm_gk20a.h"
@@ -203,7 +204,7 @@ static void vgpu_vm_remove_support(struct vm_gk20a *vm)
203{ 204{
204 struct gk20a *g = vm->mm->g; 205 struct gk20a *g = vm->mm->g;
205 struct nvgpu_mapped_buf *mapped_buffer; 206 struct nvgpu_mapped_buf *mapped_buffer;
206 struct vm_reserved_va_node *va_node, *va_node_tmp; 207 struct nvgpu_vm_area *vm_area, *vm_area_tmp;
207 struct tegra_vgpu_cmd_msg msg; 208 struct tegra_vgpu_cmd_msg msg;
208 struct tegra_vgpu_as_share_params *p = &msg.params.as_share; 209 struct tegra_vgpu_as_share_params *p = &msg.params.as_share;
209 struct nvgpu_rbtree_node *node = NULL; 210 struct nvgpu_rbtree_node *node = NULL;
@@ -223,11 +224,11 @@ static void vgpu_vm_remove_support(struct vm_gk20a *vm)
223 } 224 }
224 225
225 /* destroy remaining reserved memory areas */ 226 /* destroy remaining reserved memory areas */
226 nvgpu_list_for_each_entry_safe(va_node, va_node_tmp, 227 nvgpu_list_for_each_entry_safe(vm_area, vm_area_tmp,
227 &vm->reserved_va_list, 228 &vm->vm_area_list,
228 vm_reserved_va_node, reserved_va_list) { 229 nvgpu_vm_area, vm_area_list) {
229 nvgpu_list_del(&va_node->reserved_va_list); 230 nvgpu_list_del(&vm_area->vm_area_list);
230 nvgpu_kfree(g, va_node); 231 nvgpu_kfree(g, vm_area);
231 } 232 }
232 233
233 msg.cmd = TEGRA_VGPU_CMD_AS_FREE_SHARE; 234 msg.cmd = TEGRA_VGPU_CMD_AS_FREE_SHARE;
@@ -413,7 +414,7 @@ static int vgpu_vm_alloc_share(struct gk20a_as_share *as_share,
413 414
414 nvgpu_mutex_init(&vm->update_gmmu_lock); 415 nvgpu_mutex_init(&vm->update_gmmu_lock);
415 kref_init(&vm->ref); 416 kref_init(&vm->ref);
416 nvgpu_init_list_node(&vm->reserved_va_list); 417 nvgpu_init_list_node(&vm->vm_area_list);
417 418
418 vm->enable_ctag = true; 419 vm->enable_ctag = true;
419 420