diff options
author | Sami Kiminki <skiminki@nvidia.com> | 2014-11-05 13:34:25 -0500 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:12:08 -0400 |
commit | f97e7036b1448aae6b39da93692514722b690fec (patch) | |
tree | 100c73e3a64225db9302fc02b9b25bd7af2f83d9 | |
parent | ca474ca33f13c432bb43f7705f762907682e1219 (diff) |
gpu: nvgpu: sanitize gk20a_vm_alloc_share()
Add sanity check for big_page_size parameter to avoid invoking
gk20a_init_vm() with a bogus big page size, potentially hitting a
BUG_ON there. Also, reorganize the code a bit to avoid memory leak in
case of bogus big page size, and properly forward the return value
from gk20a_init_vm().
Change-Id: I4eeada75415d2e9539b5e8859099cce35cd86db3
Signed-off-by: Sami Kiminki <skiminki@nvidia.com>
Reviewed-on: http://git-master/r/594469
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 1cdb2f8a..e4186c95 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -2341,10 +2341,19 @@ int gk20a_vm_alloc_share(struct gk20a_as_share *as_share, u32 big_page_size) | |||
2341 | struct vm_gk20a *vm; | 2341 | struct vm_gk20a *vm; |
2342 | char name[32]; | 2342 | char name[32]; |
2343 | int err; | 2343 | int err; |
2344 | u32 default_big_page_size; | ||
2345 | 2344 | ||
2346 | gk20a_dbg_fn(""); | 2345 | gk20a_dbg_fn(""); |
2347 | 2346 | ||
2347 | if (big_page_size == 0) | ||
2348 | big_page_size = | ||
2349 | gk20a_get_platform(g->dev)->default_big_page_size; | ||
2350 | |||
2351 | if (!is_power_of_2(big_page_size)) | ||
2352 | return -EINVAL; | ||
2353 | |||
2354 | if (!(big_page_size & g->gpu_characteristics.available_big_page_sizes)) | ||
2355 | return -EINVAL; | ||
2356 | |||
2348 | vm = kzalloc(sizeof(*vm), GFP_KERNEL); | 2357 | vm = kzalloc(sizeof(*vm), GFP_KERNEL); |
2349 | if (!vm) | 2358 | if (!vm) |
2350 | return -ENOMEM; | 2359 | return -ENOMEM; |
@@ -2355,20 +2364,10 @@ int gk20a_vm_alloc_share(struct gk20a_as_share *as_share, u32 big_page_size) | |||
2355 | 2364 | ||
2356 | snprintf(name, sizeof(name), "gk20a_as_%d", as_share->id); | 2365 | snprintf(name, sizeof(name), "gk20a_as_%d", as_share->id); |
2357 | 2366 | ||
2358 | default_big_page_size = | ||
2359 | gk20a_get_platform(g->dev)->default_big_page_size; | ||
2360 | |||
2361 | if (big_page_size == 0) | ||
2362 | big_page_size = default_big_page_size; | ||
2363 | |||
2364 | if (big_page_size != default_big_page_size && | ||
2365 | !g->ops.mm.set_big_page_size) | ||
2366 | return -EINVAL; | ||
2367 | |||
2368 | err = gk20a_init_vm(mm, vm, big_page_size, big_page_size << 10, | 2367 | err = gk20a_init_vm(mm, vm, big_page_size, big_page_size << 10, |
2369 | mm->channel.size, true, name); | 2368 | mm->channel.size, true, name); |
2370 | 2369 | ||
2371 | return 0; | 2370 | return err; |
2372 | } | 2371 | } |
2373 | 2372 | ||
2374 | int gk20a_vm_release_share(struct gk20a_as_share *as_share) | 2373 | int gk20a_vm_release_share(struct gk20a_as_share *as_share) |