From c8c8e59a46bc98ae1161c293b24531aef1fc0446 Mon Sep 17 00:00:00 2001 From: Tejal Kudav Date: Tue, 26 Nov 2019 16:26:40 +0530 Subject: [PATCH] gpu: nvgpu: unit: add priv_ring unit tests Add unit tests for common.priv_ring unit. JIRA NVGPU-934 Change-Id: Ic825f571a3032cf9a194773df09a255bcba1bf79 Signed-off-by: Tejal Kudav Reviewed-on: https://git-master.nvidia.com/r/2248567 Reviewed-by: mobile promotions Tested-by: mobile promotions --- Makefile.umbrella.tmk | 1 + drivers/gpu/nvgpu/libnvgpu-drv_safe.export | 7 + userspace/Makefile.sources | 1 + userspace/SWUTS.h | 1 + userspace/SWUTS.sources | 1 + userspace/required_tests.json | 54 +++ userspace/units/priv_ring/Makefile | 26 ++ .../units/priv_ring/Makefile.interface.tmk | 23 ++ userspace/units/priv_ring/Makefile.tmk | 24 ++ userspace/units/priv_ring/nvgpu-priv_ring.c | 364 ++++++++++++++++++ userspace/units/priv_ring/nvgpu-priv_ring.h | 243 ++++++++++++ 11 files changed, 745 insertions(+) create mode 100644 userspace/units/priv_ring/Makefile create mode 100644 userspace/units/priv_ring/Makefile.interface.tmk create mode 100644 userspace/units/priv_ring/Makefile.tmk create mode 100644 userspace/units/priv_ring/nvgpu-priv_ring.c create mode 100644 userspace/units/priv_ring/nvgpu-priv_ring.h diff --git a/Makefile.umbrella.tmk b/Makefile.umbrella.tmk index c1a25d188..20443dd01 100644 --- a/Makefile.umbrella.tmk +++ b/Makefile.umbrella.tmk @@ -52,6 +52,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/interface/lock NV_REPOSITORY_COMPONENTS += userspace/units/interface/atomic NV_REPOSITORY_COMPONENTS += userspace/units/interface/rbtree NV_REPOSITORY_COMPONENTS += userspace/units/pramin +NV_REPOSITORY_COMPONENTS += userspace/units/priv_ring NV_REPOSITORY_COMPONENTS += userspace/units/ptimer NV_REPOSITORY_COMPONENTS += userspace/units/mm/nvgpu_sgt NV_REPOSITORY_COMPONENTS += userspace/units/mm/nvgpu_mem diff --git a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export index 657dee72a..0e9d09874 100644 --- a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export +++ b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export @@ -40,6 +40,11 @@ gm20b_top_get_max_ltc_per_fbp gm20b_top_get_max_lts_per_ltc gm20b_top_get_num_ltcs gm20b_fuse_status_opt_fbp +gm20b_priv_ring_enable +gm20b_priv_set_timeout_settings +gm20b_priv_ring_enum_ltc +gm20b_priv_ring_get_gpc_count +gm20b_priv_ring_get_fbp_count gp10b_get_max_page_table_levels gp10b_mm_get_default_big_page_size gp10b_mm_get_iommu_bit @@ -51,6 +56,8 @@ gp10b_device_info_parse_data gp10b_get_num_engine_type_entries gp10b_get_device_info gp10b_is_engine_ce +gp10b_priv_ring_isr +gp10b_priv_ring_decode_error_code gv11b_channel_count gv11b_channel_debug_dump gv11b_channel_read_state diff --git a/userspace/Makefile.sources b/userspace/Makefile.sources index 3fbe92dd8..9fa878c9a 100644 --- a/userspace/Makefile.sources +++ b/userspace/Makefile.sources @@ -56,6 +56,7 @@ UNITS := \ $(UNIT_SRC)/posix/rwsem \ $(UNIT_SRC)/pramin \ $(UNIT_SRC)/ptimer \ + $(UNIT_SRC)/priv_ring \ $(UNIT_SRC)/init \ $(UNIT_SRC)/interface/bsearch \ $(UNIT_SRC)/interface/lock \ diff --git a/userspace/SWUTS.h b/userspace/SWUTS.h index e53b9be0d..04435bf6a 100644 --- a/userspace/SWUTS.h +++ b/userspace/SWUTS.h @@ -69,6 +69,7 @@ * - @ref SWUTS-posix-sizes * - @ref SWUTS-posix-thread * - @ref SWUTS-posix-timers + * - @ref SWUTS-priv_ring * - @ref SWUTS-ptimer * - @ref SWUTS-sdl * - @ref SWUTS-acr diff --git a/userspace/SWUTS.sources b/userspace/SWUTS.sources index 6f2dd3025..d1a476ba4 100644 --- a/userspace/SWUTS.sources +++ b/userspace/SWUTS.sources @@ -42,6 +42,7 @@ INPUT += ../../../userspace/units/posix/fault-injection/posix-fault-injection-dm INPUT += ../../../userspace/units/posix/sizes/posix-sizes.h INPUT += ../../../userspace/units/posix/thread/posix-thread.h INPUT += ../../../userspace/units/posix/timers/posix-timers.h +INPUT += ../../../userspace/units/priv_ring/nvgpu-priv_ring.h INPUT += ../../../userspace/units/ptimer/nvgpu-ptimer.h INPUT += ../../../userspace/units/acr/nvgpu-acr.h INPUT += ../../../userspace/units/top/nvgpu-top.h diff --git a/userspace/required_tests.json b/userspace/required_tests.json index 0956148c1..3e415b3d9 100644 --- a/userspace/required_tests.json +++ b/userspace/required_tests.json @@ -1103,6 +1103,60 @@ "unit": "nvgpu-netlist", "test_level": 0 }, + { + "test": "test_setup", + "case": "priv_ring_setup", + "unit": "priv_ring", + "test_level": 0 + }, + { + "test": "test_enable_priv_ring", + "case": "priv_ring_enable_priv_ring", + "unit": "priv_ring", + "test_level": 0 + }, + { + "test": "test_set_ppriv_timeout_settings", + "case": "priv_ring_set_ppriv_timeout_settings", + "unit": "priv_ring", + "test_level": 0 + }, + { + "test": "test_enum_ltc", + "case": "priv_ring_enum_ltc", + "unit": "priv_ring", + "test_level": 0 + }, + { + "test": "test_get_gpc_count", + "case": "priv_ring_get_gpc_count", + "unit": "priv_ring", + "test_level": 0 + }, + { + "test": "test_get_fbp_count", + "case": "priv_ring_get_fbp_count", + "unit": "priv_ring", + "test_level": 0 + }, + { + "test": "test_decode_error_code", + "case": "priv_ring_decode_error_code", + "unit": "priv_ring", + "test_level": 0 + }, + { + "test": "test_isr", + "case": "priv_ring_isr", + "unit": "priv_ring", + "test_level": 0 + }, + { + "test": "test_free_reg_space", + "case": "priv_ring_free_reg_space", + "unit": "priv_ring", + "test_level": 0 + }, { "test": "free_falcon_test_env", "case": "falcon_free_test_env", diff --git a/userspace/units/priv_ring/Makefile b/userspace/units/priv_ring/Makefile new file mode 100644 index 000000000..0690f968e --- /dev/null +++ b/userspace/units/priv_ring/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-priv_ring.o +MODULE = priv_ring + +include ../Makefile.units diff --git a/userspace/units/priv_ring/Makefile.interface.tmk b/userspace/units/priv_ring/Makefile.interface.tmk new file mode 100644 index 000000000..e50468e6c --- /dev/null +++ b/userspace/units/priv_ring/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=priv_ring + +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/priv_ring/Makefile.tmk b/userspace/units/priv_ring/Makefile.tmk new file mode 100644 index 000000000..517bc4696 --- /dev/null +++ b/userspace/units/priv_ring/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=priv_ring +NVGPU_UNIT_SRCS=nvgpu-priv_ring.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/priv_ring/nvgpu-priv_ring.c b/userspace/units/priv_ring/nvgpu-priv_ring.c new file mode 100644 index 000000000..3fb239b3f --- /dev/null +++ b/userspace/units/priv_ring/nvgpu-priv_ring.c @@ -0,0 +1,364 @@ +/* + * 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 "nvgpu-priv_ring.h" + +u32 read_cmd_reg = 3U; + +/* + * Write callback. + */ +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. + */ +static void readl_access_reg_fn(struct gk20a *g, + struct nvgpu_reg_access *access) +{ + /* Completion of clear_interrupts is indicated by value of + * pri_ringmaster_command_r() changing from + * pri_ringmaster_command_cmd_ack_interrupt_f() to + * pri_ringmaster_command_cmd_no_cmd_v(). + * + * During ISR, the pri_ringmaster_command_r() register is polled to + * check if its value changed to no_cmd. + * To get complete branch coverage in priv_ring.isr(), after + * "read_cmd_reg" read attempts, the value of pri_ringmaster_command_r() + * is read as pri_ringmaster_command_cmd_no_cmd_v(). + * This maps to clearing interrupts after "read_cmd_reg" polling + * attempts. + */ + if (access->addr == pri_ringmaster_command_r()) { + if (read_cmd_reg == 0U) { + access->value = pri_ringmaster_command_cmd_no_cmd_v(); + return; + } + read_cmd_reg = nvgpu_safe_sub_u32(read_cmd_reg, 1U); + } + 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, +}; + +/* NV_PRIV_MASTER register space */ +#define NV_PRIV_MASTER_START 0x00120000U +#define NV_PRIV_MASTER_SIZE 0x000003FFU + +/* NV_PRIV_SYS register space */ +#define NV_PRIV_SYS_START 0x00122000U +#define NV_PRIV_SYS_SIZE 0x000007FFU + +/* NV_PRIV_GPC register space */ +#define NV_PRIV_GPC_START 0x00128000U +#define NV_PRIV_GPC_SIZE 0x000007FFU + +/* NV_PRIV_GPC register space */ +#define NV_PMC_START 0x00000000U +#define NV_PMC_SIZE 0x00000FFFU + +int test_setup(struct unit_module *m, struct gk20a *g, void *args) +{ + /* Init HAL */ + g->ops.priv_ring.enable_priv_ring = gm20b_priv_ring_enable; + g->ops.priv_ring.isr = gp10b_priv_ring_isr; + g->ops.priv_ring.decode_error_code = gp10b_priv_ring_decode_error_code; + g->ops.priv_ring.set_ppriv_timeout_settings = + gm20b_priv_set_timeout_settings; + g->ops.priv_ring.enum_ltc = gm20b_priv_ring_enum_ltc; + g->ops.priv_ring.get_gpc_count = gm20b_priv_ring_get_gpc_count; + g->ops.priv_ring.get_fbp_count = gm20b_priv_ring_get_fbp_count; + g->ops.get_litter_value = gv11b_get_litter_value; + g->ops.mc.intr_stall_unit_config = + mc_gp10b_intr_stall_unit_config; + /* Init register space */ + nvgpu_posix_io_init_reg_space(g); + + /* Map register space NV_PRIV_MASTER */ + if (nvgpu_posix_io_add_reg_space(g, NV_PRIV_MASTER_START, + NV_PRIV_MASTER_SIZE) != 0) { + unit_err(m, "%s: failed to register space: NV_PRIV_MASTER\n", + __func__); + return UNIT_FAIL; + } + + /* Map register space NV_PRIV_SYS */ + if (nvgpu_posix_io_add_reg_space(g, NV_PRIV_SYS_START, + NV_PRIV_SYS_SIZE) != 0) { + unit_err(m, "%s: failed to register space: NV_PRIV_SYS\n", + __func__); + return UNIT_FAIL; + } + + /* Map register space NV_PRIV_GPC */ + if (nvgpu_posix_io_add_reg_space(g, NV_PRIV_GPC_START, + NV_PRIV_GPC_SIZE) != 0) { + unit_err(m, "%s: failed to register space: NV_PRIV_GPC\n", + __func__); + return UNIT_FAIL; + } + + /* Map register space NV_PMC */ + if (nvgpu_posix_io_add_reg_space(g, NV_PMC_START, + NV_PMC_SIZE) != 0) { + unit_err(m, "%s: failed to register space: NV_PMC\n", + __func__); + return UNIT_FAIL; + } + + (void)nvgpu_posix_register_io(g, &test_reg_callbacks); + + return UNIT_SUCCESS; +} + +int test_free_reg_space(struct unit_module *m, struct gk20a *g, void *args) +{ + /* Free register space */ + nvgpu_posix_io_delete_reg_space(g, NV_PRIV_MASTER_START); + nvgpu_posix_io_delete_reg_space(g, NV_PRIV_SYS_START); + nvgpu_posix_io_delete_reg_space(g, NV_PRIV_GPC_START); + nvgpu_posix_io_delete_reg_space(g, NV_PMC_START); + + return UNIT_SUCCESS; +} + +int test_enable_priv_ring(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret = UNIT_SUCCESS; + u32 val_cmd; + u32 val_sys_decode_config; + + /* Call enable_priv_ring HAL. */ + ret = g->ops.priv_ring.enable_priv_ring(g); + + /* Read back the registers to make sure intended values are written. */ + if (ret == 0U) { + val_cmd = nvgpu_posix_io_readl_reg_space(g, + pri_ringmaster_command_r()); + val_sys_decode_config = nvgpu_posix_io_readl_reg_space(g, + pri_ringstation_sys_decode_config_r()); + if ((val_cmd != 0x4) || (val_sys_decode_config != 0x2)) { + unit_err(m, "Priv_ring enable failed.\n"); + ret = UNIT_FAIL; + } + } else { + unit_err(m, "priv_ring.enable_priv_ring HAL failed.\n"); + ret = UNIT_FAIL; + } + + return ret; +} + +int test_set_ppriv_timeout_settings(struct unit_module *m, struct gk20a *g, + void *args) +{ + int ret = UNIT_SUCCESS; + u32 val_sys; + u32 val_gpc; + + /* Call set_ppriv_timeout_settings HAL to set the timeout values + * to 0x800. + */ + g->ops.priv_ring.set_ppriv_timeout_settings(g); + + /* Read back the registers to make sure the timeouts are set to 0x800 */ + val_sys = nvgpu_posix_io_readl_reg_space(g, + pri_ringstation_sys_master_config_r(0x15)); + val_gpc = nvgpu_posix_io_readl_reg_space(g, + pri_ringstation_gpc_master_config_r(0xa)); + if ((val_sys != 0x800) || (val_gpc != 0x800)) { + unit_err(m, "Timeout setting failed.\n"); + ret = UNIT_FAIL; + } + + return ret; +} + +int test_enum_ltc(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret = UNIT_SUCCESS; + u32 val; + + /* Set pri_ringmaster_enum_ltc_r to 0x1D */ + nvgpu_posix_io_writel_reg_space(g, pri_ringmaster_enum_ltc_r(), 0x1DU); + val = g->ops.priv_ring.enum_ltc(g); + if (val != 0x1DU) { + unit_err(m, "enum LTC parsing incorrect.\n"); + ret = UNIT_FAIL; + } + + return ret; +} + +int test_get_gpc_count(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret = UNIT_SUCCESS; + u32 val; + + /* Set Count field in pri_ringmaster_enum_gpc_r to 0x1D */ + nvgpu_posix_io_writel_reg_space(g, pri_ringmaster_enum_gpc_r(), 0x1DU); + val = g->ops.priv_ring.get_gpc_count(g); + if (val != 0x1DU) { + unit_err(m, "enum GPC count parsing incorrect.\n"); + ret = UNIT_FAIL; + } + + return ret; +} + +int test_get_fbp_count(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret = UNIT_SUCCESS; + u32 val; + + /* Set Count field in pri_ringmaster_enum_fbp_r to 0x1D */ + nvgpu_posix_io_writel_reg_space(g, pri_ringmaster_enum_fbp_r(), 0x1DU); + val = g->ops.priv_ring.get_fbp_count(g); + if (val != 0x1DU) { + unit_err(m, "enum FBP count parsing incorrect.\n"); + ret = UNIT_FAIL; + } + + return ret; +} + +int test_isr(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret = UNIT_SUCCESS; + + /* Set status0 such that: + * 1. start_conn_fault (Bit 0:0) = 1. + * 2. disconnect_fault (Bit 1:1) = 1. + * 3. overflow_fault (Bit 2:2) = 1. + * 4. gbl_write_error (Bit 8:8) = 1. + * So status0 = 0x00000107*/ + nvgpu_posix_io_writel_reg_space(g, pri_ringmaster_intr_status0_r(), + 0x00000107U); + + /* Set status1 such that: + * 1. gbl_write_error (Bit 31:0) = 0x14. + */ + nvgpu_posix_io_writel_reg_space(g, pri_ringmaster_intr_status1_r(), + 0x00000014U); + + /* Set Count field in pri_ringmaster_enum_gpc_r to 0x1D. */ + nvgpu_posix_io_writel_reg_space(g, pri_ringmaster_enum_gpc_r(), 0x1DU); + + /* Call priv_ring ISR and clear the interrupts using readl callback. */ + g->ops.priv_ring.isr(g); + + /* For better branch coveage, call ISR with: + * g->ops.priv_ring.decode_error_code = NULL. + */ + g->ops.priv_ring.decode_error_code = NULL; + g->ops.priv_ring.isr(g); + + /* To cover negative case in for loop, call ISR with + * g->ops.priv_ring.get_gpc_count(g) = 0. + */ + nvgpu_posix_io_writel_reg_space(g, pri_ringmaster_enum_gpc_r(), 0x0U); + g->ops.priv_ring.isr(g); + + /* Call the ISR again without clearing the interrupts and setting + * status0 and status1 to 0 to cover additional branches. + */ + read_cmd_reg = U32_MAX; + nvgpu_posix_io_writel_reg_space(g, pri_ringmaster_intr_status0_r(), 0U); + nvgpu_posix_io_writel_reg_space(g, pri_ringmaster_intr_status1_r(), 0U); + g->ops.priv_ring.isr(g); + + return ret; +} + +u32 error_codes[] = { + 0xBADF1100U, + 0xBADF1800U, + 0xBADF1A00U, + 0xBADF2000U, + 0xBADF2100U, + 0xBADF3000U, + 0xBADF3100U, + 0xBADF4100U, + 0xBADF4200U, + 0xBADF5100U, + 0xBADF5500U, + 0xBADF5600U, +}; + +int test_decode_error_code(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret = UNIT_SUCCESS; + u32 i; + + /* Call priv_ring ISR and clear the interrupts using readl callback. */ + for (i = 0; i < sizeof(error_codes)/sizeof(u32); i++) { + g->ops.priv_ring.decode_error_code(g, error_codes[i]); + } + + return ret; +} + +struct unit_module_test priv_ring_tests[] = { + UNIT_TEST(priv_ring_setup, test_setup, NULL, 0), + UNIT_TEST(priv_ring_enable_priv_ring, test_enable_priv_ring, NULL, 0), + UNIT_TEST(priv_ring_set_ppriv_timeout_settings, + test_set_ppriv_timeout_settings, NULL, 0), + UNIT_TEST(priv_ring_enum_ltc, test_enum_ltc, NULL, 0), + UNIT_TEST(priv_ring_get_gpc_count, test_get_gpc_count, NULL, 0), + UNIT_TEST(priv_ring_get_fbp_count, test_get_fbp_count, NULL, 0), + UNIT_TEST(priv_ring_decode_error_code, test_decode_error_code, NULL, 0), + UNIT_TEST(priv_ring_isr, test_isr, NULL, 0), + UNIT_TEST(priv_ring_free_reg_space, test_free_reg_space, NULL, 0), +}; + +UNIT_MODULE(priv_ring, priv_ring_tests, UNIT_PRIO_NVGPU_TEST); diff --git a/userspace/units/priv_ring/nvgpu-priv_ring.h b/userspace/units/priv_ring/nvgpu-priv_ring.h new file mode 100644 index 000000000..b059294d4 --- /dev/null +++ b/userspace/units/priv_ring/nvgpu-priv_ring.h @@ -0,0 +1,243 @@ +/* + * 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_PRIV_RING_H +#define UNIT_NVGPU_PRIV_RING_H + +struct gk20a; +struct unit_module; + +/** @addtogroup SWUTS-priv_ring + * @{ + * + * Software Unit Test Specification for nvgpu.common.priv_ring + */ + +/** + * Test specification for: test_setup + * + * Description: Setup prerequisites for tests. + * + * Test Type: Other (setup) + * + * Input: None + * + * Steps: + * - Initialize common.priv_ring and few other necessary HAL function pointers. + * - Map the register space for NV_PRIV_MASTER, NV_PRIV_SYS, NV_PRIV_GPC + * and NV_PMC + * - Register read/write callback functions. + * + * Output: + * - UNIT_FAIL if encounters an error creating reg space + * - UNIT_SUCCESS otherwise + */ +int test_setup(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_free_reg_space + * + * Description: Free resources from test_setup() + * + * Test Type: Other (setup) + * + * Input: test_setup() has been executed. + * + * Steps: + * - Free up NV_PRIV_MASTER, NV_PRIV_SYS, NV_PRIV_GPC and NV_PMC register space. + * + * Output: + * - UNIT_SUCCESS + */ +int test_free_reg_space(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_enable_priv_ring + * + * Description: Verify the priv_ring.enable_priv_ring HAL. + * + * Test Type: Feature Based + * + * Targets: gm20b_enable_priv_ring + * + * Input: test_setup() has been executed. + * + * Steps: + * - Call enable_priv_ring() HAL. + * - Read back the registers to make sure intended values are written. + * pri_ringmaster_command_r = 0x4 + * pri_ringstation_sys_decode_config_r = 0x2 + * + * Output: + * - UNIT_FAIL if above HAL fails to enable interrupts. + * - UNIT_SUCCESS otherwise. + */ +int test_enable_priv_ring(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_set_ppriv_timeout_settings + * + * Description: Verify the priv_ring.set_ppriv_timeout_settings HAL. + * + * Test Type: Feature Based + * + * Targets: gm20b_priv_set_timeout_settings + * + * Input: test_setup() has been executed. + * + * Steps: + * - Call set_ppriv_timeout_settings HAL to set the timeout values to 0x800. + * - Read back the registers to make sure the timeouts are set to 0x800. + * + * Output: + * - UNIT_FAIL if above HAL fails to set timeouts. + * - UNIT_SUCCESS otherwise. + */ +int test_set_ppriv_timeout_settings(struct unit_module *m, struct gk20a *g, + void *args); + +/** + * Test specification for: test_enum_ltc + * + * Description: Verify the priv_ring.enum_ltc HAL. + * + * Test Type: Feature Based + * + * Targets: gm20b_priv_ring_enum_ltc. + * + * Input: test_setup() has been executed. + * + * Steps: + * - Initialize bits corresponding to count (Bits 4:0) in + * pri_ringmaster_enum_ltc_r() to 0x1D to make sure all 5 bits are parsed. + * - Call enum_ltc() HAL. + * - Verify that the HAL returns . + * + * Output: + * - UNIT_FAIL if above HAL fails to LTC count. + * - UNIT_SUCCESS otherwise + */ +int test_enum_ltc(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_get_gpc_count + * + * Description: Verify the priv_ring.get_gpc_count HAL. + * + * Test Type: Feature Based + * + * Targets: gm20b_priv_ring_get_gpc_count + * + * Input: test_setup() has been executed. + * + * Steps: + * - Initialize bits corresponding to count (Bits 4:0) in + * pri_ringmaster_enum_gpc_r() to 0x1D to make sure all 5 bits are parsed. + * - Call get_gpc_count() HAL. + * - Verify that the HAL returns 4. + * + * Output: + * - UNIT_FAIL if above HAL fails to GPC count. + * - UNIT_SUCCESS otherwise + */ +int test_get_gpc_count(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_get_fbp_count + * + * Description: Verify the priv_ring.get_fbp_count HAL. + * + * Test Type: Feature Based + * + * Targets: gm20b_priv_ring_get_fbp_count + * + * Input: test_setup() has been executed. + * + * Steps: + * - Initialize bits corresponding to count (Bits 4:0) in + * pri_ringmaster_enum_fbp_r() to 0x1D to make sure all 5 bits are parsed. + * - Call get_fbp_count() HAL. + * - Verify that the HAL returns 4. + * + * Output: + * - UNIT_FAIL if above HAL fails to FBP count. + * - UNIT_SUCCESS otherwise + */ +int test_get_fbp_count(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_isr + * + * Description: Verify the priv_ring.isr HAL. + * + * Test Type: Feature Based + * + * Targets: gp10b_priv_ring_isr + * + * Input: test_setup() has been executed. + * + * Steps: + * - Set status0 such that: + * 1. start_conn_fault (Bit 0:0) = 1. + * 2. disconnect_fault (Bit 1:1) = 1. + * 3. overflow_fault (Bit 2:2) = 1. + * 4. gbl_write_error (Bit 8:8) = 1. + * So status0 = 0x00000107. + * - Set status1 such that: + * 1. gbl_write_error (Bit 31:0) = 0x14. + * - Set Count field in pri_ringmaster_enum_gpc_r to 0x1D. + * - Call priv_ring ISR and clear the interrupts using readl callback. + * - For increasing branch coverage: + * 1. Call ISR with g->ops.priv_ring.decode_error_code = NULL. + * 2. To cover negative case in for loop, call ISR with + * g->ops.priv_ring.get_gpc_count(g) = 0. + * 3. Call the ISR again without clearing the interrupts and setting + * status0 and status1 to 0. + * + * Output: + * - UNIT_SUCCESS + */ +int test_isr(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_decode_error_code + * + * Description: Verify the priv_ring.decode_error_code HAL. + * + * Test Type: Feature Based + * + * Targets: gp10b_decode_error_code + * + * Input: test_setup() has been executed. + * + * Steps: + * - Call decode_error_code HAL with different error_codes covering all the + * branches (0xBADF1xxx, 0xBADF2xxx, 0xBADF3xxx, 0xBADF5xxx). + * - Include error codes with reference the largest index for each of the error + * types. + * + * Output: + * - UNIT_SUCCESS + */ +int test_decode_error_code(struct unit_module *m, struct gk20a *g, void *args); + +#endif /* UNIT_NVGPU_PRIV_RING_H */