diff --git a/Makefile.umbrella.tmk b/Makefile.umbrella.tmk index 485266b5f..a63cc4e40 100644 --- a/Makefile.umbrella.tmk +++ b/Makefile.umbrella.tmk @@ -39,6 +39,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/posix/env NV_REPOSITORY_COMPONENTS += userspace/units/posix/mockio NV_REPOSITORY_COMPONENTS += userspace/units/posix/fault-injection NV_REPOSITORY_COMPONENTS += userspace/units/posix/bug +NV_REPOSITORY_COMPONENTS += userspace/units/init NV_REPOSITORY_COMPONENTS += userspace/units/interface/bsearch NV_REPOSITORY_COMPONENTS += userspace/units/interface/lock NV_REPOSITORY_COMPONENTS += userspace/units/interface/atomic diff --git a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export index 02cb79d58..25603204e 100644 --- a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export +++ b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export @@ -90,6 +90,7 @@ nvgpu_gr_config_set_sm_info_sm_index nvgpu_gr_config_get_sm_info_sm_index nvgpu_gr_config_set_gpc_tpc_mask nvgpu_gr_config_get_gpc_tpc_mask +nvgpu_can_busy nvgpu_channel_alloc_inst nvgpu_channel_cleanup_sw nvgpu_channel_close @@ -103,6 +104,8 @@ nvgpu_channel_setup_bind nvgpu_channel_refch_from_inst_ptr nvgpu_channel_setup_sw nvgpu_channel_sync_create +nvgpu_check_gpu_state +nvgpu_detect_chip nvgpu_dma_alloc nvgpu_dma_alloc_get_fault_injection nvgpu_dma_alloc_flags_sys @@ -111,6 +114,7 @@ nvgpu_dma_alloc_map_sys nvgpu_dma_alloc_sys nvgpu_dma_free nvgpu_dma_unmap_free +nvgpu_get nvgpu_falcon_bl_bootstrap nvgpu_falcon_bootstrap nvgpu_falcon_copy_to_dmem @@ -208,6 +212,7 @@ nvgpu_posix_io_writel_reg_space nvgpu_posix_is_fault_injection_triggered nvgpu_posix_probe nvgpu_posix_register_io +nvgpu_put nvgpu_raw_spinlock_acquire nvgpu_raw_spinlock_init nvgpu_raw_spinlock_release diff --git a/userspace/Makefile.sources b/userspace/Makefile.sources index 83885da56..975f2ecec 100644 --- a/userspace/Makefile.sources +++ b/userspace/Makefile.sources @@ -48,6 +48,7 @@ UNITS := \ $(UNIT_SRC)/posix/fault-injection \ $(UNIT_SRC)/posix/bug \ $(UNIT_SRC)/pramin \ + $(UNIT_SRC)/init \ $(UNIT_SRC)/interface/bsearch \ $(UNIT_SRC)/interface/lock \ $(UNIT_SRC)/interface/atomic \ diff --git a/userspace/units/init/Makefile b/userspace/units/init/Makefile new file mode 100644 index 000000000..aa14e1923 --- /dev/null +++ b/userspace/units/init/Makefile @@ -0,0 +1,26 @@ +# Copyright (c) 2019, 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"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +.SUFFIXES: + +OBJS = nvgpu-init.o +MODULE = init + +include ../Makefile.units diff --git a/userspace/units/init/Makefile.interface.tmk b/userspace/units/init/Makefile.interface.tmk new file mode 100644 index 000000000..504793621 --- /dev/null +++ b/userspace/units/init/Makefile.interface.tmk @@ -0,0 +1,23 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# Copyright (c) 2019, NVIDIA CORPORATION. All Rights Reserved. +# +# NVIDIA CORPORATION and its licensors retain all intellectual property +# and proprietary rights in and to this software, related documentation +# and any modifications thereto. Any use, reproduction, disclosure or +# distribution of this software and related documentation without an express +# license agreement from NVIDIA CORPORATION is strictly prohibited. +# +# tmake for SW Mobile component makefile +# +############################################################################### + +NVGPU_UNIT_NAME=init + +include $(NV_COMPONENT_DIR)/../Makefile.units.common.interface.tmk + +# Local Variables: +# indent-tabs-mode: t +# tab-width: 8 +# End: +# vi: set tabstop=8 noexpandtab: diff --git a/userspace/units/init/Makefile.tmk b/userspace/units/init/Makefile.tmk new file mode 100644 index 000000000..0c345f58d --- /dev/null +++ b/userspace/units/init/Makefile.tmk @@ -0,0 +1,24 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# Copyright (c) 2019, NVIDIA CORPORATION. All Rights Reserved. +# +# NVIDIA CORPORATION and its licensors retain all intellectual property +# and proprietary rights in and to this software, related documentation +# and any modifications thereto. Any use, reproduction, disclosure or +# distribution of this software and related documentation without an express +# license agreement from NVIDIA CORPORATION is strictly prohibited. +# +# tmake for SW Mobile component makefile +# +############################################################################### + +NVGPU_UNIT_NAME=init +NVGPU_UNIT_SRCS=nvgpu-init.c + +include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk + +# Local Variables: +# indent-tabs-mode: t +# tab-width: 8 +# End: +# vi: set tabstop=8 noexpandtab: diff --git a/userspace/units/init/nvgpu-init.c b/userspace/units/init/nvgpu-init.c new file mode 100644 index 000000000..4fd71f275 --- /dev/null +++ b/userspace/units/init/nvgpu-init.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2019, 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "nvgpu-init.h" + +/* value for GV11B */ +#define MC_BOOT_0_GV11B ((0x15 << 24) | (0xB << 20)) +/* to set the security fuses */ +#define GP10B_FUSE_REG_BASE 0x00021000U +#define GP10B_FUSE_OPT_PRIV_SEC_EN (GP10B_FUSE_REG_BASE+0x434U) + +/* + * Mock I/O + */ + +/* + * Write callback. Forward the write access to the mock IO framework. + */ +static void writel_access_reg_fn(struct gk20a *g, + struct nvgpu_reg_access *access) +{ + nvgpu_posix_io_writel_reg_space(g, access->addr, access->value); +} + +/* + * Read callback. Get the register value from the mock IO framework. + */ +static void readl_access_reg_fn(struct gk20a *g, + struct nvgpu_reg_access *access) +{ + access->value = nvgpu_posix_io_readl_reg_space(g, access->addr); +} + +static struct nvgpu_posix_io_callbacks test_reg_callbacks = { + /* Write APIs all can use the same accessor. */ + .writel = writel_access_reg_fn, + .writel_check = writel_access_reg_fn, + .bar1_writel = writel_access_reg_fn, + .usermode_writel = writel_access_reg_fn, + + /* Likewise for the read APIs. */ + .__readl = readl_access_reg_fn, + .readl = readl_access_reg_fn, + .bar1_readl = readl_access_reg_fn, +}; + +/* generic replacement functions that can be assigned to function pointers */ +static void no_return(struct gk20a *g) +{ + /* noop */ +} + +static int test_setup_env(struct unit_module *m, + struct gk20a *g, void *args) +{ + /* Create mc register space */ + nvgpu_posix_io_init_reg_space(g); + if (nvgpu_posix_io_add_reg_space(g, mc_boot_0_r(), 0xfff) != 0) { + unit_err(m, "%s: failed to create register space\n", + __func__); + return UNIT_FAIL; + } + /* Create fuse register space */ + if (nvgpu_posix_io_add_reg_space(g, GP10B_FUSE_REG_BASE, 0xfff) != 0) { + unit_err(m, "%s: failed to create register space\n", + __func__); + return UNIT_FAIL; + } + (void)nvgpu_posix_register_io(g, &test_reg_callbacks); + + return UNIT_SUCCESS; +} + +static int test_free_env(struct unit_module *m, + struct gk20a *g, void *args) +{ + /* Free mc register space */ + nvgpu_posix_io_delete_reg_space(g, mc_boot_0_r()); + nvgpu_posix_io_delete_reg_space(g, GP10B_FUSE_REG_BASE); + + return UNIT_SUCCESS; +} + +static int test_can_busy(struct unit_module *m, + struct gk20a *g, void *args) +{ + int ret = UNIT_SUCCESS; + + nvgpu_set_enabled(g, NVGPU_KERNEL_IS_DYING, false); + nvgpu_set_enabled(g, NVGPU_DRIVER_IS_DYING, false); + if (nvgpu_can_busy(g) != 1) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_can_busy() returned 0\n"); + } + + nvgpu_set_enabled(g, NVGPU_KERNEL_IS_DYING, true); + nvgpu_set_enabled(g, NVGPU_DRIVER_IS_DYING, false); + if (nvgpu_can_busy(g) != 0) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_can_busy() returned 1\n"); + } + + nvgpu_set_enabled(g, NVGPU_KERNEL_IS_DYING, false); + nvgpu_set_enabled(g, NVGPU_DRIVER_IS_DYING, true); + if (nvgpu_can_busy(g) != 0) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_can_busy() returned 1\n"); + } + + nvgpu_set_enabled(g, NVGPU_KERNEL_IS_DYING, true); + nvgpu_set_enabled(g, NVGPU_DRIVER_IS_DYING, true); + if (nvgpu_can_busy(g) != 0) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_can_busy() returned 1\n"); + } + + return ret; +} + +static int test_get_put(struct unit_module *m, + struct gk20a *g, void *args) +{ + int ret = UNIT_SUCCESS; + + nvgpu_ref_init(&g->refcount); + + if (g != nvgpu_get(g)) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_get() returned NULL\n"); + } + if (nvgpu_atomic_read(&g->refcount.refcount) != 2) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_get() did not increment refcount\n"); + } + + nvgpu_put(g); + if (nvgpu_atomic_read(&g->refcount.refcount) != 1) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_put() did not decrement refcount\n"); + } + + /* one more to get to 0 to teardown */ + nvgpu_put(g); + if (nvgpu_atomic_read(&g->refcount.refcount) != 0) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_put() did not decrement refcount\n"); + } + + /* This is expected to fail */ + if (nvgpu_get(g) != NULL) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_get() did not return NULL\n"); + } + if (nvgpu_atomic_read(&g->refcount.refcount) != 0) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_get() did not increment refcount\n"); + } + + /* start over */ + nvgpu_ref_init(&g->refcount); + + /* to cover the cases where these are set */ + g->remove_support = no_return; + g->gfree = no_return; + + if (g != nvgpu_get(g)) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_get() returned NULL\n"); + } + if (nvgpu_atomic_read(&g->refcount.refcount) != 2) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_get() did not increment refcount\n"); + } + + nvgpu_put(g); + if (nvgpu_atomic_read(&g->refcount.refcount) != 1) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_put() did not decrement refcount\n"); + } + + /* one more to get to 0 to teardown */ + nvgpu_put(g); + if (nvgpu_atomic_read(&g->refcount.refcount) != 0) { + ret = UNIT_FAIL; + unit_err(m, "nvgpu_put() did not decrement refcount\n"); + } + + return ret; +} + +static int test_check_gpu_state(struct unit_module *m, + struct gk20a *g, void *args) +{ + /* Valid state */ + nvgpu_posix_io_writel_reg_space(g, mc_boot_0_r(), MC_BOOT_0_GV11B); + nvgpu_check_gpu_state(g); + + /* + * Test INVALID state. This should cause a kernel_restart() which + * is a BUG() in posix, so verify we hit the BUG(). + */ + nvgpu_posix_io_writel_reg_space(g, mc_boot_0_r(), U32_MAX); + if (!EXPECT_BUG(nvgpu_check_gpu_state(g))) { + unit_err(m, "%s: failed to detect INVALID state\n", + __func__); + return UNIT_FAIL; + } + + return UNIT_SUCCESS; +} + +static int test_hal_init(struct unit_module *m, + struct gk20a *g, void *args) +{ + nvgpu_posix_io_writel_reg_space(g, mc_boot_0_r(), MC_BOOT_0_GV11B); + nvgpu_posix_io_writel_reg_space(g, GP10B_FUSE_OPT_PRIV_SEC_EN, 0x0); + if (nvgpu_detect_chip(g) != 0) { + unit_err(m, "%s: failed to init HAL\n", __func__); + return UNIT_FAIL; + } + + return UNIT_SUCCESS; +} + +struct unit_module_test init_tests[] = { + UNIT_TEST(init_setup_env, test_setup_env, NULL, 0), + UNIT_TEST(init_can_busy, test_can_busy, NULL, 0), + UNIT_TEST(init_get_put, test_get_put, NULL, 0), + UNIT_TEST(init_check_gpu_state, test_check_gpu_state, NULL, 0), + UNIT_TEST(init_hal_init, test_hal_init, NULL, 0), + UNIT_TEST(init_free_env, test_free_env, NULL, 0), +}; + +UNIT_MODULE(init, init_tests, UNIT_PRIO_NVGPU_TEST); diff --git a/userspace/units/init/nvgpu-init.h b/userspace/units/init/nvgpu-init.h new file mode 100644 index 000000000..36baabc1c --- /dev/null +++ b/userspace/units/init/nvgpu-init.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2019, 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef UNIT_NVGPU_INIT_H +#define UNIT_NVGPU_INIT_H + +#include +#include + +/** @addtogroup SWUTS-init + * @{ + * + * Software Unit Test Specification for nvgpu.common.init + */ + +/** + * Test specification for: test_setup_env + * + * Description: Do basic setup before starting other tests. + * + * Test Type: Other (setup) + * + * Input: None + * + * Steps: + * - Initialize reg spaces used by init unit tests. + * + * Output: + * - UNIT_FAIL if encounters an error creating reg space + * - UNIT_SUCCESS otherwise + */ +static int test_setup_env(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_free_env + * + * Description: Cleanup resources allocated in test_setup_env() + * + * Test Type: Other (setup) + * + * Input: None + * + * Steps: + * - Delete reg spaces + * + * Output: + * - UNIT_SUCCESS always + */ +static int test_free_env(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_can_busy + * + * Description: Validate nvgpu_can_busy() + * + * Test Type: Feature based + * + * Input: None + * + * Steps: + * - Vary NVGPU_KERNEL_IS_DYING & NVGPU_DRIVER_IS_DYING enable values and + * verify the result from nvgpu_can_busy() + * + * + * Output: + * - UNIT_FAIL if nvgpu_can_busy() returns the incorrect value. + * - UNIT_SUCCESS otherwise + */ +static int test_can_busy(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_get_put + * + * Description: Validate nvgpu_get() and nvgpu_put() and the refcount. + * + * Test Type: Feature based + * + * Input: + * - test_setup_env() must be called before. + * + * Steps: + * - Initialize refcount. + * - Get gpu and validate return and refcount. + * - Put gpu and validate refcount. + * - Put gpu again to initiate teardown and validate refcount. + * - Get gpu again to verify failure return and validate refcount. + * - Re-Initialize refcount. + * - Set function pointers to NULL to test different paths/branches. + * - Get gpu and validate return and refcount. + * - Put gpu and validate refcount. + * - Put gpu again to initiate teardown and validate refcount. + * + * Output: + * - UNIT_FAIL if nvgpu_get() returns the incorrect value or refcount is + * incorrect + * - UNIT_SUCCESS otherwise + */ +static int test_get_put(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_check_gpu_state + * + * Description: Validate the nvgpu_check_gpu_state() API which will restart + * + * Test Type: Feature based + * + * Input: + * - test_setup_env() must be called before. + * + * Steps: + * - Test valid case. + * - Set the mc_boot_0 reg to a valid state. + * - Call nvgpu_check_gpu_state() and the call should return normally. + * - Test invalid case. + * - Set the mc_boot_0 reg to the invalid state. + * - Call nvgpu_check_gpu_state() and trap the BUG() call. + * + * Output: + * - UNIT_FAIL if nvgpu_check_gpu_state() does not cause a BUG() for the invalid + * case + * - If the valid case fails, BUG() may occur and cause the framework to stop + * the test. + * - UNIT_SUCCESS otherwise + */ +static int test_check_gpu_state(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_hal_init + * + * Description: Test HAL initialization for GV11B + * + * Test Type: Feature based + * + * Input: + * - test_setup_env() must be called before. + * + * Steps: + * - Setup the mc_boot_0 reg for GV11B. + * - Initialize the fuse regs. + * - Init the HAL and verify return. + * + * Output: + * - UNIT_FAIL if HAL initialization fails + * - UNIT_SUCCESS otherwise + */ +static int test_hal_init(struct unit_module *m, + struct gk20a *g, void *args); + + +#endif /* UNIT_NVGPU_INIT_H */