diff --git a/userspace/SWUTS.h b/userspace/SWUTS.h index 04435bf6a..5c5ca12ce 100644 --- a/userspace/SWUTS.h +++ b/userspace/SWUTS.h @@ -81,6 +81,7 @@ * - @ref SWUTS-gr * - @ref SWUTS-gr-setup * - @ref SWUTS-gr-intr + * - @ref SWUTS-gr-falcon * - @ref SWUTS-gr-config * */ diff --git a/userspace/SWUTS.sources b/userspace/SWUTS.sources index d1a476ba4..2adbde9c9 100644 --- a/userspace/SWUTS.sources +++ b/userspace/SWUTS.sources @@ -50,4 +50,5 @@ INPUT += ../../../userspace/units/class/nvgpu-class.h INPUT += ../../../userspace/units/gr/nvgpu-gr.h INPUT += ../../../userspace/units/gr/setup/nvgpu-gr-setup.h INPUT += ../../../userspace/units/gr/intr/nvgpu-gr-intr.h +INPUT += ../../../userspace/units/gr/intr/nvgpu-gr-falcon.h INPUT += ../../../userspace/units/gr/config/nvgpu-gr-config.h diff --git a/userspace/required_tests.json b/userspace/required_tests.json index 3e415b3d9..5286a2182 100644 --- a/userspace/required_tests.json +++ b/userspace/required_tests.json @@ -1379,42 +1379,18 @@ "unit": "nvgpu_gr_config", "test_level": 0 }, - { - "test": "test_gr_falcon_deinit", - "case": "gr_falcon_deinit", - "unit": "nvgpu_gr_falcon", - "test_level": 0 - }, { "test": "test_gr_falcon_init", "case": "gr_falcon_init", "unit": "nvgpu_gr_falcon", "test_level": 0 }, - { - "test": "test_gr_falcon_init_ctx_state", - "case": "gr_falcon_init_ctx_state", - "unit": "nvgpu_gr_falcon", - "test_level": 0 - }, { "test": "test_gr_falcon_init_ctxsw", "case": "gr_falcon_init_ctxsw", "unit": "nvgpu_gr_falcon", "test_level": 0 }, - { - "test": "test_gr_falcon_nonsecure_gpccs_init_ctxsw", - "case": "gr_falcon_nonsecure_gpccs_init_ctxsw", - "unit": "nvgpu_gr_falcon", - "test_level": 0 - }, - { - "test": "test_gr_falcon_nonsecure_gpccs_recovery_ctxsw", - "case": "gr_falcon_nonsecure_gpccs_recovery_ctxsw", - "unit": "nvgpu_gr_falcon", - "test_level": 0 - }, { "test": "test_gr_falcon_query_test", "case": "gr_falcon_query_test", @@ -1422,8 +1398,14 @@ "test_level": 0 }, { - "test": "test_gr_falcon_recovery_ctxsw", - "case": "gr_falcon_recovery_ctxsw", + "test": "test_gr_falcon_init_ctx_state", + "case": "gr_falcon_init_ctx_state", + "unit": "nvgpu_gr_falcon", + "test_level": 0 + }, + { + "test": "test_gr_falcon_deinit", + "case": "gr_falcon_deinit", "unit": "nvgpu_gr_falcon", "test_level": 0 }, diff --git a/userspace/units/gr/falcon/nvgpu-gr-falcon.c b/userspace/units/gr/falcon/nvgpu-gr-falcon.c index 09b4b0513..83b94b365 100644 --- a/userspace/units/gr/falcon/nvgpu-gr-falcon.c +++ b/userspace/units/gr/falcon/nvgpu-gr-falcon.c @@ -27,6 +27,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -36,8 +40,20 @@ #include "hal/gr/falcon/gr_falcon_gm20b.h" #include "../nvgpu-gr.h" +#include "nvgpu-gr-falcon.h" -struct nvgpu_gr_falcon *unit_gr_falcon; +struct gr_gops_falcon_orgs { + void (*bind_instblk)(struct gk20a *g, + struct nvgpu_mem *mem, u64 inst_ptr); + void (*load_ctxsw_ucode_header)(struct gk20a *g, + u32 reg_offset, u32 boot_signature, u32 addr_code32, + u32 addr_data32, u32 code_size, u32 data_size); + int (*load_ctxsw_ucode)(struct gk20a *g, + struct nvgpu_gr_falcon *falcon); +}; + +static struct nvgpu_gr_falcon *unit_gr_falcon; +static struct gr_gops_falcon_orgs gr_falcon_gops; static void test_gr_falcon_bind_instblk(struct gk20a *g, struct nvgpu_mem *mem, u64 inst_ptr) @@ -53,10 +69,30 @@ static void test_gr_falcon_load_ctxsw_ucode_header(struct gk20a *g, } -static int test_gr_falcon_init(struct unit_module *m, - struct gk20a *g, void *args) +static void gr_falcon_save_gops(struct gk20a *g) +{ + gr_falcon_gops.load_ctxsw_ucode = + g->ops.gr.falcon.load_ctxsw_ucode; + gr_falcon_gops.load_ctxsw_ucode_header = + g->ops.gr.falcon.load_ctxsw_ucode_header; + gr_falcon_gops.bind_instblk = g->ops.gr.falcon.bind_instblk; +} + +static void gr_falcon_stub_gops(struct gk20a *g) +{ + g->ops.gr.falcon.load_ctxsw_ucode = + nvgpu_gr_falcon_load_secure_ctxsw_ucode; + g->ops.gr.falcon.load_ctxsw_ucode_header = + test_gr_falcon_load_ctxsw_ucode_header; + g->ops.gr.falcon.bind_instblk = test_gr_falcon_bind_instblk; +} + +int test_gr_falcon_init(struct unit_module *m, + struct gk20a *g, void *args) { int err = 0; + struct nvgpu_posix_fault_inj *kmem_fi = + nvgpu_kmem_get_fault_injection(); /* Allocate and Initialize GR */ err = test_gr_init_setup_ready(m, g, args); @@ -65,11 +101,16 @@ static int test_gr_falcon_init(struct unit_module *m, } /* set up test specific HALs */ - g->ops.gr.falcon.load_ctxsw_ucode = - nvgpu_gr_falcon_load_secure_ctxsw_ucode; - g->ops.gr.falcon.load_ctxsw_ucode_header = - test_gr_falcon_load_ctxsw_ucode_header; - g->ops.gr.falcon.bind_instblk = test_gr_falcon_bind_instblk; + gr_falcon_save_gops(g); + gr_falcon_stub_gops(g); + + /* Fail - kmem alloc */ + nvgpu_posix_enable_fault_injection(kmem_fi, true, 0); + unit_gr_falcon = nvgpu_gr_falcon_init_support(g); + if (unit_gr_falcon != 0) { + unit_return_fail(m, "nvgpu_gr_falcon_init_support failed\n"); + } + nvgpu_posix_enable_fault_injection(kmem_fi, false, 0); unit_gr_falcon = nvgpu_gr_falcon_init_support(g); if (unit_gr_falcon == NULL) { @@ -79,39 +120,27 @@ static int test_gr_falcon_init(struct unit_module *m, return UNIT_SUCCESS; } -static int test_gr_falcon_init_ctxsw(struct unit_module *m, +int test_gr_falcon_init_ctxsw(struct unit_module *m, struct gk20a *g, void *args) { int err = 0; + /* Test secure gpccs */ err = nvgpu_gr_falcon_init_ctxsw(g, unit_gr_falcon); if (err) { unit_return_fail(m, "nvgpu_gr_falcon_init_ctxsw failed\n"); } - return UNIT_SUCCESS; -} - -static int test_gr_falcon_nonsecure_gpccs_init_ctxsw(struct unit_module *m, - struct gk20a *g, void *args) -{ - int err = 0; - + /* Test nonsecure gpccs */ nvgpu_set_enabled(g, NVGPU_SEC_SECUREGPCCS, false); + nvgpu_set_enabled(g, NVGPU_PMU_FECS_BOOTSTRAP_DONE, false); err = nvgpu_gr_falcon_init_ctxsw(g, unit_gr_falcon); if (err) { unit_return_fail(m, "nvgpu_gr_falcon_init_ctxsw failed\n"); } nvgpu_set_enabled(g, NVGPU_SEC_SECUREGPCCS, true); - return UNIT_SUCCESS; -} - -static int test_gr_falcon_recovery_ctxsw(struct unit_module *m, - struct gk20a *g, void *args) -{ - int err = 0; - + /* Test for recovery to fail */ err = nvgpu_gr_falcon_init_ctxsw(g, unit_gr_falcon); /* Recovey expected to fail */ if (err == 0) { @@ -119,16 +148,8 @@ static int test_gr_falcon_recovery_ctxsw(struct unit_module *m, "test_gr_falcon_init_recovery_ctxsw failed\n"); } - return UNIT_SUCCESS; -} - -static int test_gr_falcon_nonsecure_gpccs_recovery_ctxsw(struct unit_module *m, - struct gk20a *g, void *args) -{ - int err = 0; - + /* Test for nonsecure gpccs recovery */ nvgpu_set_enabled(g, NVGPU_SEC_SECUREGPCCS, false); - err = nvgpu_gr_falcon_init_ctxsw(g, unit_gr_falcon); if (err) { unit_return_fail(m, "nvgpu_gr_falcon_init_ctxsw failed\n"); @@ -138,7 +159,7 @@ static int test_gr_falcon_nonsecure_gpccs_recovery_ctxsw(struct unit_module *m, return UNIT_SUCCESS; } -static int test_gr_falcon_query_test(struct unit_module *m, +int test_gr_falcon_query_test(struct unit_module *m, struct gk20a *g, void *args) { #ifdef CONFIG_NVGPU_ENGINE_RESET @@ -173,7 +194,7 @@ static int test_gr_falcon_query_test(struct unit_module *m, } -static int test_gr_falcon_init_ctx_state(struct unit_module *m, +int test_gr_falcon_init_ctx_state(struct unit_module *m, struct gk20a *g, void *args) { int err = 0; @@ -186,15 +207,19 @@ static int test_gr_falcon_init_ctx_state(struct unit_module *m, return UNIT_SUCCESS; } -static int test_gr_falcon_deinit(struct unit_module *m, +int test_gr_falcon_deinit(struct unit_module *m, struct gk20a *g, void *args) { int err = 0; if (unit_gr_falcon != NULL) { nvgpu_gr_falcon_remove_support(g, unit_gr_falcon); + unit_gr_falcon = NULL; } + /* Call with NULL pointer */ + nvgpu_gr_falcon_remove_support(g, unit_gr_falcon); + /* Cleanup GR */ err = test_gr_init_setup_cleanup(m, g, args); if (err != 0) { @@ -207,12 +232,6 @@ static int test_gr_falcon_deinit(struct unit_module *m, struct unit_module_test nvgpu_gr_falcon_tests[] = { UNIT_TEST(gr_falcon_init, test_gr_falcon_init, NULL, 0), UNIT_TEST(gr_falcon_init_ctxsw, test_gr_falcon_init_ctxsw, NULL, 0), - UNIT_TEST(gr_falcon_nonsecure_gpccs_init_ctxsw, - test_gr_falcon_nonsecure_gpccs_init_ctxsw, NULL, 0), - UNIT_TEST(gr_falcon_recovery_ctxsw, - test_gr_falcon_recovery_ctxsw, NULL, 0), - UNIT_TEST(gr_falcon_nonsecure_gpccs_recovery_ctxsw, - test_gr_falcon_nonsecure_gpccs_recovery_ctxsw, NULL, 0), UNIT_TEST(gr_falcon_query_test, test_gr_falcon_query_test, NULL, 0), UNIT_TEST(gr_falcon_init_ctx_state, diff --git a/userspace/units/gr/falcon/nvgpu-gr-falcon.h b/userspace/units/gr/falcon/nvgpu-gr-falcon.h new file mode 100644 index 000000000..b3bd5583f --- /dev/null +++ b/userspace/units/gr/falcon/nvgpu-gr-falcon.h @@ -0,0 +1,161 @@ +/* + * 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_FALCON_H +#define UNIT_NVGPU_GR_FALCON_H + +#include + +struct gk20a; +struct unit_module; + +/** @addtogroup SWUTS-gr-falcon + * @{ + * + * Software Unit Test Specification for common.gr.falcon + */ + +/** + * Test specification for: test_gr_falcon_init. + * + * Description: Helps to verify common.gr.falcon subunit initialization. + * + * Test Type: Feature based, Error injection. + * + * Targets: #nvgpu_gr_falcon_init_support. + * + * Input: #test_gr_init_setup_ready must have been executed successfully. + * + * Steps: + * - Call #test_gr_init_setup_ready to setup the common.gr init. + * - Stub some falcon hals + * - g->ops.gr.falcon.load_ctxsw_ucode. + * - g->ops.gr.falcon.load_ctxsw_ucode_header. + * - g->ops.gr.falcon.bind_instblk. + * - Call #nvgpu_gr_falcon_init_support and fail memory allocation. + * - Call #nvgpu_gr_falcon_init_support and pass memory allocation. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_gr_falcon_init(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_gr_falcon_deinit. + * + * Description: Helps to verify common.gr.falcon subunit deinitialization. + * + * Test Type: Feature based, Error injection.. + * + * Targets: #nvgpu_gr_falcon_remove_support. + * + * Input: #test_gr_falcon_init must have been executed successfully. + * + * Steps: + * - Call #nvgpu_gr_falcon_remove_support. + * - Call #nvgpu_gr_falcon_remove_support will NULL pointer. + * - Call #test_gr_init_setup_cleanup to cleanup common.gr. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_gr_falcon_deinit(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_gr_falcon_init_ctxsw. + * + * Description: This test helps to verify load and boot FECS and GPCCS ucodes. + * + * Test Type: Feature based. + * + * Targets: #nvgpu_gr_falcon_init_ctxsw. + * + * Input: #test_gr_falcon_init must have been executed successfully. + * + * Steps: + * - By default code use secure gpccs path. + * - Call #nvgpu_gr_falcon_init_ctxsw. + * - Enable nonsecure gpccs path. + * - Call #nvgpu_gr_falcon_init_ctxsw. + * - Enable secure gpccs path. + * - Call #nvgpu_gr_falcon_init_ctxsw to test recovery path failure. + * - Enable nonsecure gpccs path. + * - Call #nvgpu_gr_falcon_init_ctxsw to test recovery path success. + * - Enable secure gpccs path. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_gr_falcon_init_ctxsw(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_gr_falcon_init_ctx_state. + * + * Description: Helps to verify context state initialization + * + * Test Type: Feature based. + * + * Targets: #nvgpu_gr_falcon_init_ctx_state. + * + * Input: #test_gr_falcon_init must have been executed successfully. + * + * Steps: + * - Call #nvgpu_gr_falcon_init_ctx_state. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_gr_falcon_init_ctx_state(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_gr_falcon_query_test. + * + * Description: Helps to verify the common.gr.falcon query + * functions return valid values. + * + * Test Type: Feature based. + * + * Targets: #nvgpu_gr_falcon_get_fecs_ucode_segments, + * #nvgpu_gr_falcon_get_gpccs_ucode_segments, + * #nvgpu_gr_falcon_get_surface_desc_cpu_va. + * + * Input: #test_gr_falcon_init must have been executed successfully. + * + * Steps: + * - Call #nvgpu_gr_falcon_get_fecs_ucode_segments. + * - Call #nvgpu_gr_falcon_get_gpccs_ucode_segments. + * - Call #nvgpu_gr_falcon_get_surface_desc_cpu_va. + * + * Output: Returns PASS if the steps above were executed successfully. FAIL + * otherwise. + */ +int test_gr_falcon_query_test(struct unit_module *m, + struct gk20a *g, void *args); +#endif /* UNIT_NVGPU_GR_FALCON_H */ + +/** + * @} + */ + diff --git a/userspace/units/gr/setup/nvgpu-gr-setup.c b/userspace/units/gr/setup/nvgpu-gr-setup.c index 628fe104d..7eb2195b8 100644 --- a/userspace/units/gr/setup/nvgpu-gr-setup.c +++ b/userspace/units/gr/setup/nvgpu-gr-setup.c @@ -428,6 +428,33 @@ static int gr_setup_alloc_fail_fe_pwr_mode(struct unit_module *m, struct gk20a * return (err != 0) ? UNIT_SUCCESS: UNIT_FAIL; } +static int gr_setup_alloc_fail_ctrl_ctxsw(struct unit_module *m, + struct gk20a *g, void *args) +{ + int err; + + err = gr_test_setup_allocate_ch_tsg(m, g); + if (err != 0) { + unit_return_fail(m, "alloc setup channel failed\n"); + } + + g->ops.mm.cache.l2_flush = stub_mm_l2_flush; + g->ops.gr.init.fe_pwr_mode_force_on = stub_gr_init_fe_pwr_mode; + + /* Reset golden image ready bit */ + g->gr->golden_image->ready = false; + g->gr->golden_image->size = 0x800; + + err = g->ops.gr.setup.alloc_obj_ctx(gr_setup_ch, VOLTA_COMPUTE_A, 0); + if (err == 0) { + unit_err(m, "setup alloc ctrl_ctxsw failed\n"); + } + + test_gr_setup_free_obj_ctx(m, g, args); + + return (err != 0) ? UNIT_SUCCESS: UNIT_FAIL; +} + static int gr_setup_alloc_fail_l2_flush(struct unit_module *m, struct gk20a *g) { int err; @@ -440,6 +467,12 @@ static int gr_setup_alloc_fail_l2_flush(struct unit_module *m, struct gk20a *g) unit_return_fail(m, "setup alloc l2 flush failed\n"); } + /* Subctx already created - redo for branch coverage */ + err = g->ops.gr.setup.alloc_obj_ctx(gr_setup_ch, VOLTA_COMPUTE_A, 0); + if (err != 0) { + unit_return_fail(m, "setup alloc l2 flush failed\n"); + } + g->ops.mm.cache.l2_flush = stub_mm_l2_flush; return (err == 0) ? UNIT_SUCCESS: UNIT_FAIL; @@ -529,6 +562,12 @@ int test_gr_setup_alloc_obj_ctx_error_injections(struct unit_module *m, test_gr_setup_free_obj_ctx(m, g, args); g->allow_all = false; + /* TEST-8 fail ctrl_ctxsw */ + err = gr_setup_alloc_fail_ctrl_ctxsw(m, g, args); + if (err != 0) { + unit_return_fail(m, "setup alloc TEST-8 failed\n"); + } + return UNIT_SUCCESS; } diff --git a/userspace/units/gr/setup/nvgpu-gr-setup.h b/userspace/units/gr/setup/nvgpu-gr-setup.h index d38ffa5d1..52e841602 100644 --- a/userspace/units/gr/setup/nvgpu-gr-setup.h +++ b/userspace/units/gr/setup/nvgpu-gr-setup.h @@ -27,7 +27,7 @@ struct gk20a; struct unit_module; -/** @addtogroup SWUTS-common-gr-setup +/** @addtogroup SWUTS-gr-setup * @{ * * Software Unit Test Specification for common.gr.setup @@ -162,12 +162,13 @@ int test_gr_setup_preemption_mode_errors(struct unit_module *m, * - Test-1 using invalid tsg, classobj and classnum. * - Test-2 error injection in subctx allocation call. * - Test-3 fail nvgpu_gr_obj_ctx_alloc by setting zero image size. - * - Test-4 fail nvgpu_gr_obj_ctx_alloc_golden_ctx_image by failing ctrl_ctsw. - * - Test-5 Fail L2 flush for branch coverage - * - Test-6 Fake setup_free call for NULL checking + * - Test-4 and Test-8 fail nvgpu_gr_obj_ctx_alloc_golden_ctx_image + * by failing ctrl_ctsw. + * - Test-5 Fail L2 flush for branch coverage. + * - Test-6 Fake setup_free call for NULL checking. * * - Positive Tests - * - Test-7 nvgpu_gr_setup_alloc_obj_ctx pass without TST subcontexts + * - Test-7 nvgpu_gr_setup_alloc_obj_ctx pass without TSG subcontexts. * * Output: Returns PASS if the steps above were executed successfully. FAIL * otherwise.