From b1d7c77d8eafc3fc71b6b021aad2768822250f82 Mon Sep 17 00:00:00 2001 From: Dinesh T Date: Fri, 8 Jul 2022 20:28:27 +0000 Subject: [PATCH] gpu: nvgpu: Create unique share id This is fixing a race in address space identifier creation by making atomic variable increment. Bug 3684734 Change-Id: I864e8f61257569e35f926822c2a5260532d41360 Signed-off-by: Dinesh T Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2742206 Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-cert Reviewed-by: Vaibhav Kachore Reviewed-by: Sagar Kamble Reviewed-by: Richard Zhao GVS: Gerrit_Virtual_Submit --- drivers/gpu/nvgpu/common/mm/as.c | 42 ++++++++++--------------- drivers/gpu/nvgpu/include/nvgpu/as.h | 25 ++------------- drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 3 -- drivers/gpu/nvgpu/os/linux/ioctl_as.c | 4 +-- libs/igpu/libnvgpu-drv-igpu_safe.export | 1 - userspace/required_tests.ini | 11 +++---- userspace/units/mm/as/as.c | 40 ++++------------------- userspace/units/mm/as/as.h | 24 ++------------ 8 files changed, 33 insertions(+), 117 deletions(-) diff --git a/drivers/gpu/nvgpu/common/mm/as.c b/drivers/gpu/nvgpu/common/mm/as.c index d57a8639f..0157b554f 100644 --- a/drivers/gpu/nvgpu/common/mm/as.c +++ b/drivers/gpu/nvgpu/common/mm/as.c @@ -1,7 +1,7 @@ /* * GK20A Address Spaces * - * Copyright (c) 2011-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2022, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,32 +32,28 @@ #define VM_NAME_PREFIX "as_" -/* dumb allocator... */ -static int generate_as_share_id(struct gk20a_as *as) +static nvgpu_atomic_t unique_share_id = NVGPU_ATOMIC_INIT(0); +/* + * Generate unique id by doing atomic increment on unique_share_id. + */ +static int generate_unique_share_id(void) { - struct gk20a *g = gk20a_from_as(as); + int ret = 0; - nvgpu_log_fn(g, " "); - as->last_share_id = nvgpu_safe_add_s32(as->last_share_id, 1); - return as->last_share_id; + ret = nvgpu_atomic_inc_return(&unique_share_id); + if (ret == 0) { + nvgpu_err(NULL, "incrementing share_id overflow"); + } + + return ret; } -/* still dumb */ -static void release_as_share_id(struct gk20a_as_share *as_share) -{ - struct gk20a *g = gk20a_from_as(as_share->as); - - nvgpu_log_fn(g, " "); - return; -} - /* address space interfaces for the gk20a module */ static int gk20a_vm_alloc_share(struct gk20a_as_share *as_share, u32 big_page_size, u32 flags, u64 va_range_start, u64 va_range_end, u64 va_range_split) { - struct gk20a_as *as = as_share->as; - struct gk20a *g = gk20a_from_as(as); + struct gk20a *g = as_share->g; struct mm_gk20a *mm = &g->mm; struct vm_gk20a *vm; char name[NVGPU_VM_NAME_LEN] = VM_NAME_PREFIX; @@ -171,8 +167,8 @@ int gk20a_as_alloc_share(struct gk20a *g, return -ENOMEM; } - as_share->as = &g->as; - as_share->id = generate_as_share_id(as_share->as); + as_share->g = g; + as_share->id = generate_unique_share_id(); /* this will set as_share->vm. */ err = gk20a_busy(g); @@ -232,14 +228,8 @@ int gk20a_as_release_share(struct gk20a_as_share *as_share) gk20a_idle(g); release_fail: - release_as_share_id(as_share); nvgpu_put(g); nvgpu_kfree(g, as_share); return err; } - -struct gk20a *gk20a_from_as(struct gk20a_as *as) -{ - return (struct gk20a *)((uintptr_t)as - offsetof(struct gk20a, as)); -} diff --git a/drivers/gpu/nvgpu/include/nvgpu/as.h b/drivers/gpu/nvgpu/include/nvgpu/as.h index 34ceba107..3bee14332 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/as.h +++ b/drivers/gpu/nvgpu/include/nvgpu/as.h @@ -1,7 +1,7 @@ /* * GK20A Address Spaces * - * Copyright (c) 2011-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2022, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -29,16 +29,6 @@ struct vm_gk20a; struct gk20a; -/** - * Basic structure to identify an address space (AS). - */ -struct gk20a_as { - /** - * Incrementing id to identify the AS, dummy allocator for now. - */ - int last_share_id; -}; - /** * Basic structure to share an AS. */ @@ -46,7 +36,7 @@ struct gk20a_as_share { /** * The AS to share. */ - struct gk20a_as *as; + struct gk20a *g; /** * The VM used by the AS. @@ -144,15 +134,4 @@ int gk20a_as_alloc_share(struct gk20a *g, u32 big_page_size, u64 va_range_end, u64 va_range_split, struct gk20a_as_share **out); -/** - * @brief Retrieve the instance of gk20a from a gk20a_as instance. - * - * @param as [in] The address space - * - * Given an instance of gk20a_as, retrieve a pointer to the underlying gk20a - * instance. - * - * @return pointer to the underlying GPU (gk20a). - */ -struct gk20a *gk20a_from_as(struct gk20a_as *as); #endif /* NVGPU_AS_H */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index 90f0ee71c..f24f430ce 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -693,9 +693,6 @@ struct gk20a { u32 pg_ms_gating_cnt; #endif - /** GPU address-space identifier. */ - struct gk20a_as as; - /** The HAL function pointers */ struct gpu_ops ops; diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_as.c b/drivers/gpu/nvgpu/os/linux/ioctl_as.c index 1e582a7b8..ab770d06c 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_as.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_as.c @@ -1,7 +1,7 @@ /* * GK20A Address Spaces * - * Copyright (c) 2011-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2022, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -457,7 +457,7 @@ long gk20a_as_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; struct gk20a_as_share *as_share = filp->private_data; - struct gk20a *g = gk20a_from_as(as_share->as); + struct gk20a *g = as_share->g; bool always_copy_to_user = false; u8 buf[NVGPU_AS_IOCTL_MAX_ARG_SIZE]; diff --git a/libs/igpu/libnvgpu-drv-igpu_safe.export b/libs/igpu/libnvgpu-drv-igpu_safe.export index 53699cc81..2b1ba8408 100644 --- a/libs/igpu/libnvgpu-drv-igpu_safe.export +++ b/libs/igpu/libnvgpu-drv-igpu_safe.export @@ -17,7 +17,6 @@ gk20a_fifo_intr_1_isr gk20a_fifo_intr_handle_chsw_error gk20a_fifo_intr_handle_runlist_event gk20a_fifo_pbdma_isr -gk20a_from_as gk20a_get_pde_pgsz gk20a_get_pte_pgsz gk20a_mm_fb_flush diff --git a/userspace/required_tests.ini b/userspace/required_tests.ini index c34a52cae..db07dd013 100644 --- a/userspace/required_tests.ini +++ b/userspace/required_tests.ini @@ -333,18 +333,17 @@ test_pause_resume_mask.pause_resume_mask=0 test_unit_config.unit_config=2 [mm.as] -test_as_alloc_share.as_alloc_share_0k_um=0 -test_as_alloc_share.as_alloc_share_64k_um=0 +test_as_alloc_share.as_alloc_share_0k_um=2 +test_as_alloc_share.as_alloc_share_64k_um=2 test_as_alloc_share.as_alloc_share_64k_um_as_fail=0 test_as_alloc_share.as_alloc_share_64k_um_busy_fail_1=0 -test_as_alloc_share.as_alloc_share_64k_um_busy_fail_2=0 +test_as_alloc_share.as_alloc_share_64k_um_busy_fail_2=2 test_as_alloc_share.as_alloc_share_64k_um_vm_fail=0 test_as_alloc_share.as_alloc_share_einval_um=0 test_as_alloc_share.as_alloc_share_notp2_um=0 -test_as_alloc_share.as_alloc_share_uva=0 -test_as_alloc_share.as_alloc_share_uva_enabled=0 +test_as_alloc_share.as_alloc_share_uva=2 +test_as_alloc_share.as_alloc_share_uva_enabled=2 test_init_mm.init=0 -test_gk20a_from_as.gk20a_from_as=0 [mm.dma] test_mm_dma_alloc.alloc=0 diff --git a/userspace/units/mm/as/as.c b/userspace/units/mm/as/as.c index ae017d20b..b31df30df 100644 --- a/userspace/units/mm/as/as.c +++ b/userspace/units/mm/as/as.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -268,33 +268,6 @@ int test_as_alloc_share(struct unit_module *m, struct gk20a *g, void *args) return UNIT_SUCCESS; } -int test_gk20a_from_as(struct unit_module *m, struct gk20a *g, void *args) -{ - int ret = UNIT_FAIL; - struct gk20a_as_share *out; - int err; - - err = gk20a_as_alloc_share(g, SZ_64K, NVGPU_AS_ALLOC_USERSPACE_MANAGED, - (SZ_64K << 10), (1ULL << 37), - nvgpu_gmmu_va_small_page_limit(), &out); - if (err != 0) { - unit_return_fail(m, "gk20a_as_alloc_share failed err=%d\n", - err); - } - - if (g != gk20a_from_as(out->as)) { - unit_err(m, "ptr mismatch in gk20a_from_as\n"); - goto exit; - } - - ret = UNIT_SUCCESS; - -exit: - gk20a_as_release_share(out); - - return ret; -} - struct unit_module_test nvgpu_mm_as_tests[] = { UNIT_TEST(init, test_init_mm, NULL, 0), UNIT_TEST(as_alloc_share_64k_um_as_fail, test_as_alloc_share, @@ -304,20 +277,19 @@ struct unit_module_test nvgpu_mm_as_tests[] = { UNIT_TEST(as_alloc_share_64k_um_busy_fail_1, test_as_alloc_share, (void *) &test_64k_user_managed_busy_fail_1, 0), UNIT_TEST(as_alloc_share_64k_um_busy_fail_2, test_as_alloc_share, - (void *) &test_64k_user_managed_busy_fail_2, 0), + (void *) &test_64k_user_managed_busy_fail_2, 2), UNIT_TEST(as_alloc_share_64k_um, test_as_alloc_share, - (void *) &test_64k_user_managed, 0), + (void *) &test_64k_user_managed, 2), UNIT_TEST(as_alloc_share_0k_um, test_as_alloc_share, - (void *) &test_0k_user_managed, 0), + (void *) &test_0k_user_managed, 2), UNIT_TEST(as_alloc_share_einval_um, test_as_alloc_share, (void *) &test_einval_user_managed, 0), UNIT_TEST(as_alloc_share_notp2_um, test_as_alloc_share, (void *) &test_notp2_user_managed, 0), UNIT_TEST(as_alloc_share_uva, test_as_alloc_share, - (void *) &test_64k_unified_va, 0), + (void *) &test_64k_unified_va, 2), UNIT_TEST(as_alloc_share_uva_enabled, test_as_alloc_share, - (void *) &test_64k_unified_va_enabled, 0), - UNIT_TEST(gk20a_from_as, test_gk20a_from_as, NULL, 0), + (void *) &test_64k_unified_va_enabled, 2), }; UNIT_MODULE(mm.as, nvgpu_mm_as_tests, UNIT_PRIO_NVGPU_TEST); diff --git a/userspace/units/mm/as/as.h b/userspace/units/mm/as/as.h index f7a82451e..a1c1b8d74 100644 --- a/userspace/units/mm/as/as.h +++ b/userspace/units/mm/as/as.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -119,7 +119,7 @@ int test_init_mm(struct unit_module *m, struct gk20a *g, void *args); * Test Type: Feature * * Targets: gk20a_as_alloc_share, gk20a_as_release_share, - * gk20a_vm_release_share, gk20a_from_as + * gk20a_vm_release_share * * Input: * - The test_init_mm must have been executed @@ -153,24 +153,4 @@ int test_init_mm(struct unit_module *m, struct gk20a *g, void *args); */ int test_as_alloc_share(struct unit_module *m, struct gk20a *g, void *args); -/** - * Test specification for: test_gk20a_from_as - * - * Description: Simple test to check gk20a_from_as. - * - * Test Type: Feature - * - * Targets: gk20a_from_as - * - * Input: None - * - * Steps: - * - Call gk20a_from_as with an 'as' pointer and ensure it returns a - * pointer on g. - * - * Output: Returns PASS if the steps above were executed successfully. FAIL - * otherwise. - */ -int test_gk20a_from_as(struct unit_module *m, struct gk20a *g, void *args); - #endif /* UNIT_MM_AS_H */