From fdb804681278fd4df8318583f91445ae880d989c Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Wed, 4 Dec 2019 19:32:51 +0530 Subject: [PATCH] gpu: nvgpu: unit: add negative tests for common.gr.obj_ctx Add negative tests that inject memory allocation failures and HAL function call errors to verify error handling path in common.gr.obj_ctx unit. Update common.gr.setup test to cover invalid class input while setting preemption mode. Jira NVGPU-4457 Change-Id: I74d1ba63ba8aace6087b51fd50e2c136822d3a00 Signed-off-by: Deepak Nibade Reviewed-on: https://git-master.nvidia.com/r/2260939 Reviewed-by: mobile promotions Tested-by: mobile promotions --- Makefile.umbrella.tmk | 1 + drivers/gpu/nvgpu/common/gr/global_ctx.c | 34 ++ .../gpu/nvgpu/include/nvgpu/gr/global_ctx.h | 5 + .../nvgpu/posix/posix-fault-injection.h | 2 + drivers/gpu/nvgpu/libnvgpu-drv_safe.export | 8 + userspace/Makefile.sources | 1 + userspace/SWUTS.h | 1 + userspace/SWUTS.sources | 1 + userspace/required_tests.json | 18 + userspace/units/gr/obj_ctx/Makefile | 33 ++ .../units/gr/obj_ctx/Makefile.interface.tmk | 35 ++ userspace/units/gr/obj_ctx/Makefile.tmk | 40 ++ userspace/units/gr/obj_ctx/nvgpu-gr-obj-ctx.c | 438 ++++++++++++++++++ userspace/units/gr/obj_ctx/nvgpu-gr-obj-ctx.h | 83 ++++ userspace/units/gr/setup/nvgpu-gr-setup.c | 7 + 15 files changed, 707 insertions(+) create mode 100644 userspace/units/gr/obj_ctx/Makefile create mode 100644 userspace/units/gr/obj_ctx/Makefile.interface.tmk create mode 100644 userspace/units/gr/obj_ctx/Makefile.tmk create mode 100644 userspace/units/gr/obj_ctx/nvgpu-gr-obj-ctx.c create mode 100644 userspace/units/gr/obj_ctx/nvgpu-gr-obj-ctx.h diff --git a/Makefile.umbrella.tmk b/Makefile.umbrella.tmk index 5ebacef82..b748d301d 100644 --- a/Makefile.umbrella.tmk +++ b/Makefile.umbrella.tmk @@ -122,6 +122,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/gr/setup NV_REPOSITORY_COMPONENTS += userspace/units/gr/fs_state NV_REPOSITORY_COMPONENTS += userspace/units/gr/global_ctx NV_REPOSITORY_COMPONENTS += userspace/units/gr/ctx +NV_REPOSITORY_COMPONENTS += userspace/units/gr/obj_ctx NV_REPOSITORY_COMPONENTS += userspace/units/gr/intr NV_REPOSITORY_COMPONENTS += userspace/units/acr NV_REPOSITORY_COMPONENTS += userspace/units/ce diff --git a/drivers/gpu/nvgpu/common/gr/global_ctx.c b/drivers/gpu/nvgpu/common/gr/global_ctx.c index 9416c496d..6537347b1 100644 --- a/drivers/gpu/nvgpu/common/gr/global_ctx.c +++ b/drivers/gpu/nvgpu/common/gr/global_ctx.c @@ -35,6 +35,26 @@ #include "global_ctx_priv.h" +#ifdef NVGPU_UNITTEST_FAULT_INJECTION_ENABLEMENT +#include + +struct nvgpu_posix_fault_inj *nvgpu_golden_ctx_verif_get_fault_injection(void) +{ + struct nvgpu_posix_fault_inj_container *c = + nvgpu_posix_fault_injection_get_container(); + + return &c->golden_ctx_verif_fi; +} + +struct nvgpu_posix_fault_inj *nvgpu_local_golden_image_get_fault_injection(void) +{ + struct nvgpu_posix_fault_inj_container *c = + nvgpu_posix_fault_injection_get_container(); + + return &c->local_golden_image_fi; +} +#endif + struct nvgpu_gr_global_ctx_buffer_desc * nvgpu_gr_global_ctx_desc_alloc(struct gk20a *g) { @@ -311,6 +331,13 @@ nvgpu_gr_global_ctx_init_local_golden_image(struct gk20a *g, { struct nvgpu_gr_global_ctx_local_golden_image *local_golden_image; +#ifdef NVGPU_UNITTEST_FAULT_INJECTION_ENABLEMENT + if (nvgpu_posix_fault_injection_handle_call( + nvgpu_local_golden_image_get_fault_injection())) { + return NULL; + } +#endif + local_golden_image = nvgpu_kzalloc(g, sizeof(*local_golden_image)); if (local_golden_image == NULL) { return NULL; @@ -345,6 +372,13 @@ bool nvgpu_gr_global_ctx_compare_golden_images(struct gk20a *g, u32 i; #endif +#ifdef NVGPU_UNITTEST_FAULT_INJECTION_ENABLEMENT + if (nvgpu_posix_fault_injection_handle_call( + nvgpu_golden_ctx_verif_get_fault_injection())) { + return false; + } +#endif + /* * In case of sysmem, direct mem compare can be used. * For vidmem, word by word comparison only works and diff --git a/drivers/gpu/nvgpu/include/nvgpu/gr/global_ctx.h b/drivers/gpu/nvgpu/include/nvgpu/gr/global_ctx.h index 61ee33254..4bb75ec34 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gr/global_ctx.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gr/global_ctx.h @@ -314,6 +314,11 @@ bool nvgpu_gr_global_ctx_compare_golden_images(struct gk20a *g, size_t size); #endif +#ifdef NVGPU_UNITTEST_FAULT_INJECTION_ENABLEMENT +struct nvgpu_posix_fault_inj *nvgpu_golden_ctx_verif_get_fault_injection(void); +struct nvgpu_posix_fault_inj *nvgpu_local_golden_image_get_fault_injection(void); +#endif + #ifdef CONFIG_NVGPU_DEBUGGER u32 *nvgpu_gr_global_ctx_get_local_golden_image_ptr( struct nvgpu_gr_global_ctx_local_golden_image *local_golden_image); diff --git a/drivers/gpu/nvgpu/include/nvgpu/posix/posix-fault-injection.h b/drivers/gpu/nvgpu/include/nvgpu/posix/posix-fault-injection.h index 740ca08c1..da97cc968 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/posix/posix-fault-injection.h +++ b/drivers/gpu/nvgpu/include/nvgpu/posix/posix-fault-injection.h @@ -42,6 +42,8 @@ struct nvgpu_posix_fault_inj_container { struct nvgpu_posix_fault_inj fread_op; struct nvgpu_posix_fault_inj kmem_fi; struct nvgpu_posix_fault_inj nvgpu_fi; + struct nvgpu_posix_fault_inj golden_ctx_verif_fi; + struct nvgpu_posix_fault_inj local_golden_image_fi; struct nvgpu_posix_fault_inj dma_fi; struct nvgpu_posix_fault_inj queue_out_fi; struct nvgpu_posix_fault_inj timers_fi; diff --git a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export index efd5624bc..ad7c1aa31 100644 --- a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export +++ b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export @@ -366,6 +366,14 @@ nvgpu_gr_ctx_map_global_ctx_buffers nvgpu_gr_ctx_patch_write_begin nvgpu_gr_ctx_patch_write nvgpu_gr_ctx_patch_write_end +nvgpu_golden_ctx_verif_get_fault_injection +nvgpu_local_golden_image_get_fault_injection +nvgpu_gr_obj_ctx_init +nvgpu_gr_obj_ctx_alloc +nvgpu_gr_obj_ctx_deinit +nvgpu_gr_subctx_alloc +nvgpu_gr_subctx_free +nvgpu_gr_obj_ctx_set_ctxsw_preemption_mode nvgpu_hr_timestamp nvgpu_init_ltc_support nvgpu_ltc_ecc_free diff --git a/userspace/Makefile.sources b/userspace/Makefile.sources index e33bf4ddc..11573600c 100644 --- a/userspace/Makefile.sources +++ b/userspace/Makefile.sources @@ -129,6 +129,7 @@ UNITS := \ $(UNIT_SRC)/gr/fs_state \ $(UNIT_SRC)/gr/global_ctx \ $(UNIT_SRC)/gr/ctx \ + $(UNIT_SRC)/gr/obj_ctx \ $(UNIT_SRC)/gr/intr \ $(UNIT_SRC)/gr/setup \ $(UNIT_SRC)/acr \ diff --git a/userspace/SWUTS.h b/userspace/SWUTS.h index 7554e6f09..279b5e159 100644 --- a/userspace/SWUTS.h +++ b/userspace/SWUTS.h @@ -108,6 +108,7 @@ * - @ref SWUTS-gr-fs-state * - @ref SWUTS-gr-global-ctx * - @ref SWUTS-gr-ctx + * - @ref SWUTS-gr-obj-ctx * - @ref SWUTS-gr-config * */ diff --git a/userspace/SWUTS.sources b/userspace/SWUTS.sources index c296b7562..d9d9b2398 100644 --- a/userspace/SWUTS.sources +++ b/userspace/SWUTS.sources @@ -79,4 +79,5 @@ INPUT += ../../../userspace/units/gr/intr/nvgpu-gr-falcon.h INPUT += ../../../userspace/units/gr/intr/nvgpu-gr-fs-state.h INPUT += ../../../userspace/units/gr/intr/nvgpu-gr-global-ctx.h INPUT += ../../../userspace/units/gr/intr/nvgpu-gr-ctx.h +INPUT += ../../../userspace/units/gr/intr/nvgpu-gr-obj-ctx.h INPUT += ../../../userspace/units/gr/config/nvgpu-gr-config.h diff --git a/userspace/required_tests.json b/userspace/required_tests.json index e06f7551c..bd37d08a5 100644 --- a/userspace/required_tests.json +++ b/userspace/required_tests.json @@ -2633,6 +2633,24 @@ "unit": "nvgpu_gr_ctx", "test_level": 0 }, + { + "test": "test_gr_init_setup_ready", + "case": "gr_obj_ctx_setup", + "unit": "nvgpu_gr_obj_ctx", + "test_level": 0 + }, + { + "test": "test_gr_obj_ctx_error_injection", + "case": "gr_obj_ctx_alloc_errors", + "unit": "nvgpu_gr_obj_ctx", + "test_level": 0 + }, + { + "test": "test_gr_init_setup_cleanup", + "case": "gr_obj_ctx_cleanup", + "unit": "nvgpu_gr_obj_ctx", + "test_level": 0 + }, { "test": "test_nvgpu_mem_create_from_phys", "case": "mem_create_from_phys", diff --git a/userspace/units/gr/obj_ctx/Makefile b/userspace/units/gr/obj_ctx/Makefile new file mode 100644 index 000000000..1edb0050d --- /dev/null +++ b/userspace/units/gr/obj_ctx/Makefile @@ -0,0 +1,33 @@ +# 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-gr-obj-ctx.o +MODULE = nvgpu-gr-obj-ctx + +LIB_PATHS += -lnvgpu-gr +include ../../Makefile.units + +lib$(MODULE).so: nvgpu-gr + +nvgpu-gr: + $(MAKE) -C .. + diff --git a/userspace/units/gr/obj_ctx/Makefile.interface.tmk b/userspace/units/gr/obj_ctx/Makefile.interface.tmk new file mode 100644 index 000000000..17c31472f --- /dev/null +++ b/userspace/units/gr/obj_ctx/Makefile.interface.tmk @@ -0,0 +1,35 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# 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. +# +# tmake for SW Mobile component makefile +# +############################################################################### + +NVGPU_UNIT_NAME=nvgpu-gr-obj-ctx + +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/gr/obj_ctx/Makefile.tmk b/userspace/units/gr/obj_ctx/Makefile.tmk new file mode 100644 index 000000000..eb5c322aa --- /dev/null +++ b/userspace/units/gr/obj_ctx/Makefile.tmk @@ -0,0 +1,40 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# 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. +# +# tmake for SW Mobile component makefile +# +############################################################################### + +NVGPU_UNIT_NAME = nvgpu-gr-obj-ctx +NVGPU_UNIT_SRCS = nvgpu-gr-obj-ctx.c + +NVGPU_UNIT_INTERFACE_DIRS := \ + $(NV_COMPONENT_DIR)/.. \ + $(NV_SOURCE)/kernel/nvgpu/drivers/gpu/nvgpu + +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/gr/obj_ctx/nvgpu-gr-obj-ctx.c b/userspace/units/gr/obj_ctx/nvgpu-gr-obj-ctx.c new file mode 100644 index 000000000..c4f6df0af --- /dev/null +++ b/userspace/units/gr/obj_ctx/nvgpu-gr-obj-ctx.c @@ -0,0 +1,438 @@ +/* + * 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 +#include +#include +#include +#include + +#include +#include + +#include "common/gr/gr_priv.h" +#include "common/gr/ctx_priv.h" +#include "common/gr/obj_ctx_priv.h" +#include "common/gr/gr_config_priv.h" + +#include "../nvgpu-gr.h" +#include "nvgpu-gr-obj-ctx.h" + +#define DUMMY_SIZE 0xF0U + +static int fe_pwr_mode_count; +static int test_fe_pwr_mode_force_on(struct gk20a *g, bool force_on) +{ + if (fe_pwr_mode_count == 0) { + return -1; + } else { + fe_pwr_mode_count--; + return 0; + } +} + +static int test_l2_flush(struct gk20a *g, bool flag) +{ + return 0; +} + +static int test_init_sm_id_table(struct gk20a *g, + struct nvgpu_gr_config *gr_config) +{ + return -1; +} + +static int ctrl_ctxsw_count; +static int test_falcon_ctrl_ctxsw(struct gk20a *g, u32 fecs_method, + u32 data, u32 *ret_val) +{ + if (ctrl_ctxsw_count == 0) { + return -1; + } else { + ctrl_ctxsw_count--; + return 0; + } +} + +static int gr_wait_idle_count; +static int test_gr_wait_idle(struct gk20a *g) +{ + if (gr_wait_idle_count == 0) { + gr_wait_idle_count--; + return -1; + } else { + gr_wait_idle_count--; + return 0; + } +} + +static int load_sw_bundle_count; +static int test_load_sw_bundle(struct gk20a *g, + struct netlist_av_list *sw_bundle_init) +{ + if (load_sw_bundle_count == 0) { + return -1; + } else { + load_sw_bundle_count--; + return 0; + } +} + +int test_gr_obj_ctx_error_injection(struct unit_module *m, + struct gk20a *g, void *args) +{ + int err; + struct nvgpu_gr_obj_ctx_golden_image *golden_image; + struct vm_gk20a *vm; + struct nvgpu_gr_ctx_desc *desc; + struct nvgpu_gr_global_ctx_buffer_desc *global_desc; + struct nvgpu_gr_ctx *gr_ctx = NULL; + struct nvgpu_gr_subctx *subctx = NULL; + struct nvgpu_mem inst_block; + struct nvgpu_gr_config *config = nvgpu_gr_get_config_ptr(g); + struct nvgpu_posix_fault_inj *kmem_fi = + nvgpu_kmem_get_fault_injection(); + struct nvgpu_posix_fault_inj *golden_ctx_verif_fi = + nvgpu_golden_ctx_verif_get_fault_injection(); + struct nvgpu_posix_fault_inj *local_golden_image_fi = + nvgpu_local_golden_image_get_fault_injection(); + int (*init_sm_id_table_tmp)(struct gk20a *g, + struct nvgpu_gr_config *config); + + /* Inject allocation failures and initialize obj_ctx, should fail */ + nvgpu_posix_enable_fault_injection(kmem_fi, true, 0); + err = nvgpu_gr_obj_ctx_init(g, &golden_image, DUMMY_SIZE); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + g->ops.mm.cache.l2_flush = test_l2_flush; + + /* Disable error injection and initialize obj_ctx, should pass */ + nvgpu_posix_enable_fault_injection(kmem_fi, false, 0); + err = nvgpu_gr_obj_ctx_init(g, &golden_image, DUMMY_SIZE); + if (err != 0) { + unit_return_fail(m, "failed to init obj_ctx"); + } + + /* Setup VM */ + vm = nvgpu_vm_init(g, SZ_4K, SZ_4K << 10, (1ULL << 32), + (1ULL << 32) + (1ULL << 37), false, false, false, + "dummy"); + if (!vm) { + unit_return_fail(m, "failed to allocate VM"); + } + + /* Allocate inst_block */ + err = nvgpu_dma_alloc(g, DUMMY_SIZE, &inst_block); + if (err) { + unit_return_fail(m, "failed to allocate instance block"); + } + + /* Setup graphics context prerequisites, global buffers and subcontext */ + desc = nvgpu_gr_ctx_desc_alloc(g); + if (!desc) { + unit_return_fail(m, "failed to allocate memory"); + } + + gr_ctx = nvgpu_alloc_gr_ctx_struct(g); + if (!gr_ctx) { + unit_return_fail(m, "failed to allocate memory"); + } + + global_desc = nvgpu_gr_global_ctx_desc_alloc(g); + if (!global_desc) { + unit_return_fail(m, "failed to allocate desc"); + } + + nvgpu_gr_global_ctx_set_size(global_desc, NVGPU_GR_GLOBAL_CTX_CIRCULAR, + DUMMY_SIZE); + nvgpu_gr_global_ctx_set_size(global_desc, NVGPU_GR_GLOBAL_CTX_PAGEPOOL, + DUMMY_SIZE); + nvgpu_gr_global_ctx_set_size(global_desc, NVGPU_GR_GLOBAL_CTX_ATTRIBUTE, + DUMMY_SIZE); + nvgpu_gr_global_ctx_set_size(global_desc, NVGPU_GR_GLOBAL_CTX_PRIV_ACCESS_MAP, + DUMMY_SIZE); + + err = nvgpu_gr_global_ctx_buffer_alloc(g, global_desc); + if (err != 0) { + unit_return_fail(m, "failed to allocate global buffers"); + } + + subctx = nvgpu_gr_subctx_alloc(g, vm); + if (!subctx) { + unit_return_fail(m, "failed to allocate subcontext"); + } + + /* Fail gr_ctx allocation */ + nvgpu_posix_enable_fault_injection(kmem_fi, true, 0); + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* Fail patch_ctx allocation */ + nvgpu_posix_enable_fault_injection(kmem_fi, true, 3); + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* Fail circular buffer mapping */ + nvgpu_posix_enable_fault_injection(kmem_fi, true, 8); + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + nvgpu_posix_enable_fault_injection(kmem_fi, false, 0); + + /* Fail first call to gops.gr.init.fe_pwr_mode_force_on */ + g->ops.gr.init.fe_pwr_mode_force_on = test_fe_pwr_mode_force_on; + fe_pwr_mode_count = 0; + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* Fail second call to gops.gr.init.fe_pwr_mode_force_on */ + fe_pwr_mode_count = 1; + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* Re-enable gops.gr.init.fe_pwr_mode_force_on */ + fe_pwr_mode_count = -1; + + /* Fail nvgpu_gr_fs_state_init() */ + init_sm_id_table_tmp = g->ops.gr.config.init_sm_id_table; + g->ops.gr.config.init_sm_id_table = test_init_sm_id_table; + g->ops.gr.falcon.ctrl_ctxsw = test_falcon_ctrl_ctxsw; + ctrl_ctxsw_count = -1; + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* restore gops.gr.config.init_sm_id_table */ + g->ops.gr.config.init_sm_id_table = init_sm_id_table_tmp; + + /* Fail 3rd gops.gr.init.wait_idle */ + g->ops.gr.init.wait_idle = test_gr_wait_idle; + gr_wait_idle_count = 2; + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* Pass gops.gr.init.wait_idle */ + gr_wait_idle_count = -1; + + /* Fail gops.gr.init.load_sw_bundle_init */ + g->ops.gr.init.load_sw_bundle_init = test_load_sw_bundle; + load_sw_bundle_count = 0; + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* Fail gops.gr.init.load_sw_veid_bundle */ + g->ops.gr.init.load_sw_veid_bundle = test_load_sw_bundle; + load_sw_bundle_count = 1; + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* Pass load sw bundle */ + load_sw_bundle_count = -1; + + /* gops.gr.init.load_sw_veid_bundle could be NULL */ + g->ops.gr.init.load_sw_veid_bundle = NULL; + /* gops.gr.init.restore_stats_counter_bundle_data could be NULL */ + g->ops.gr.init.restore_stats_counter_bundle_data = NULL; + + /* Fail 4th gops.gr.init.wait_idle */ + g->ops.gr.init.wait_idle = test_gr_wait_idle; + gr_wait_idle_count = 4; + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* + * Fail first local golden image allocation in + * nvgpu_gr_global_ctx_init_local_golden_image() + */ + nvgpu_posix_enable_fault_injection(local_golden_image_fi, true, 0); + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* + * Fail second local golden image allocation in + * nvgpu_gr_global_ctx_init_local_golden_image() + */ + nvgpu_posix_enable_fault_injection(local_golden_image_fi, true, 1); + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* + * Fail third local golden image allocation in + * nvgpu_gr_global_ctx_init_local_golden_image() + */ + nvgpu_posix_enable_fault_injection(local_golden_image_fi, true, 2); + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* Disable error injection */ + nvgpu_posix_enable_fault_injection(local_golden_image_fi, false, 0); + + /* + * Fail first gops.gr.falcon.ctrl_ctxsw in + * nvgpu_gr_obj_ctx_save_golden_ctx() + */ + ctrl_ctxsw_count = 1; + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* + * Fail second gops.gr.falcon.ctrl_ctxsw in + * nvgpu_gr_obj_ctx_save_golden_ctx() + */ + ctrl_ctxsw_count = 2; + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* Pass gops.gr.falcon.ctrl_ctxsw */ + ctrl_ctxsw_count = -1; + + /* Fail golden context verification */ + nvgpu_posix_enable_fault_injection(golden_ctx_verif_fi, true, 0); + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* Pass golden context verification */ + nvgpu_posix_enable_fault_injection(golden_ctx_verif_fi, false, 0); + + /* Finally, successful obj_ctx allocation */ + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err != 0) { + unit_return_fail(m, "failed to allocate obj_ctx"); + } + + /* Check if golden image is ready */ + if (!nvgpu_gr_obj_ctx_is_golden_image_ready(golden_image)) { + unit_return_fail(m, "golden image is not initialzed"); + } + + /* Reallocation with golden image already created */ + err = nvgpu_gr_obj_ctx_alloc(g, golden_image, global_desc, desc, + config, gr_ctx, subctx, vm, &inst_block, + VOLTA_COMPUTE_A, 0, false, false); + if (err != 0) { + unit_return_fail(m, "failed to re-allocate obj_ctx"); + } + + /* Set preemption mode with invalid compute class */ + err = nvgpu_gr_obj_ctx_set_ctxsw_preemption_mode(g, config, desc, gr_ctx, vm, + VOLTA_DMA_COPY_A, 0, NVGPU_PREEMPTION_MODE_COMPUTE_CTA); + if (err == 0) { + unit_return_fail(m, "unexpected success"); + } + + /* Cleanup */ + nvgpu_gr_subctx_free(g, subctx, vm); + nvgpu_gr_ctx_free_patch_ctx(g, vm, gr_ctx); + nvgpu_gr_ctx_free(g, gr_ctx, global_desc, vm); + nvgpu_free_gr_ctx_struct(g, gr_ctx); + nvgpu_gr_ctx_desc_free(g, desc); + nvgpu_gr_obj_ctx_deinit(g, golden_image); + nvgpu_vm_put(vm); + + return UNIT_SUCCESS; +} + +struct unit_module_test nvgpu_gr_obj_ctx_tests[] = { + UNIT_TEST(gr_obj_ctx_setup, test_gr_init_setup_ready, NULL, 0), + UNIT_TEST(gr_obj_ctx_alloc_errors, test_gr_obj_ctx_error_injection, NULL, 0), + UNIT_TEST(gr_obj_ctx_cleanup, test_gr_init_setup_cleanup, NULL, 0), +}; + +UNIT_MODULE(nvgpu_gr_obj_ctx, nvgpu_gr_obj_ctx_tests, UNIT_PRIO_NVGPU_TEST); diff --git a/userspace/units/gr/obj_ctx/nvgpu-gr-obj-ctx.h b/userspace/units/gr/obj_ctx/nvgpu-gr-obj-ctx.h new file mode 100644 index 000000000..a54d6a4ac --- /dev/null +++ b/userspace/units/gr/obj_ctx/nvgpu-gr-obj-ctx.h @@ -0,0 +1,83 @@ +/* + * 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_GR_OBJ_CTX_H +#define UNIT_NVGPU_GR_OBJ_CTX_H + +#include + +struct gk20a; +struct unit_module; + +/** @addtogroup SWUTS-gr-obj-ctx + * @{ + * + * Software Unit Test Specification for common.gr.obj_ctx + */ + +/** + * Test specification for: test_gr_obj_ctx_error_injection. + * + * Description: Verify error handling in object context creation path. + * + * Test Type: Feature based, Error guessing. + * + * Targets: #nvgpu_gr_obj_ctx_init, + * #nvgpu_gr_obj_ctx_alloc, + * #nvgpu_gr_obj_ctx_is_golden_image_ready + * #nvgpu_gr_obj_ctx_deinit, + * #nvgpu_gr_obj_ctx_set_ctxsw_preemption_mode. + * + * Input: gr_obj_ctx_setup must have been executed successfully. + * + * Steps: + * - Inject memory allocation failures and call #nvgpu_gr_obj_ctx_init, + * should fail. + * - Disable error injection and call #nvgpu_gr_obj_ctx_init, should pass. + * - Initialize VM, instance block, global context buffers, subcontext + * which are needed to allocate object context. + * - Inject errors for gr_ctx and patch_ctx allocation, + * #nvgpu_gr_obj_ctx_alloc should fail. + * - Inject errors to fail global context buffer mapping, + * #nvgpu_gr_obj_ctx_alloc should fail. + * - Replace existing HALs with dummy ones to return errors, + * #nvgpu_gr_obj_ctx_alloc should fail in each case. + * - Inject error to fail golden context verification, + * #nvgpu_gr_obj_ctx_alloc should fail. + * - Disable all error injection and #nvgpu_gr_obj_ctx_alloc should pass. + * - Check if golden image is ready with + * #nvgpu_gr_obj_ctx_is_golden_image_ready. + * - Call #nvgpu_gr_obj_ctx_alloc again and ensure no error is return. + * - Call #nvgpu_gr_obj_ctx_set_ctxsw_preemption_mode with incorrect + * compute class and ensure it returns error. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_gr_obj_ctx_error_injection(struct unit_module *m, + struct gk20a *g, void *args); + +#endif /* UNIT_NVGPU_GR_OBJ_CTX_H */ + +/** + * @} + */ + diff --git a/userspace/units/gr/setup/nvgpu-gr-setup.c b/userspace/units/gr/setup/nvgpu-gr-setup.c index 23dd4ca9b..ee9f2ccf2 100644 --- a/userspace/units/gr/setup/nvgpu-gr-setup.c +++ b/userspace/units/gr/setup/nvgpu-gr-setup.c @@ -318,6 +318,13 @@ int test_gr_setup_preemption_mode_errors(struct unit_module *m, unit_return_fail(m, "Fail Preemp_mode Error Test-2\n"); } + /* Set invalid Class*/ + gr_setup_ch->obj_class = 0x1234; + err = g->ops.gr.setup.set_preemption_mode(gr_setup_ch, 0, 0); + if (err == 0) { + unit_return_fail(m, "Fail Preemp_mode Error Test-2\n"); + } + gr_setup_ch->obj_class = class_num; return UNIT_SUCCESS;