Open source GPL/LGPL release

This commit is contained in:
svcmobrel-release
2025-12-19 15:25:44 -08:00
commit 9fc87a7ec7
2261 changed files with 576825 additions and 0 deletions

9
userspace/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
build/
# The annoying GCC debug files
*.gcno
*.gcda
# The HTML, etc, generated by the unit test script.
results.html
results.json

174
userspace/Makefile Normal file
View File

@@ -0,0 +1,174 @@
# Copyright (c) 2018-2020, 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.
# TODO:
# - Separate rule for nvgpu_unit shared library
# - Proper header dependency checking.
# Turn off suffix rules. They are deprecated.
.SUFFIXES:
# Full paths. Makes submakefiles easier. That said this make file _must_ be run
# from <NVGPU>/userspace/.
TWD=$(CURDIR)
# Top level out dir.
OUT=$(TWD)/build
# Core unit test framework.
CORE_SRC=$(TWD)/src
CORE_OUT=$(OUT)/nvgpu_unit_core
# Nvgpu driver code.
NVGPU_SRC=$(TWD)/../drivers/gpu/nvgpu
# Nvgpu-next driver code.
NVGPU_NEXT_SRC=$(TWD)/../../nvgpu-next/drivers/gpu/nvgpu
NVGPU_OUT=$(OUT)/libnvgpu
# Unit tests themselves.
UNIT_SRC=$(TWD)/units
UNIT_OUT=$(OUT)/units
INCLUDES= \
-I$(NVGPU_SRC) \
-I$(NVGPU_SRC)/include \
-I$(NVGPU_NEXT_SRC) \
-I$(NVGPU_NEXT_SRC)/include \
-I$(TWD)/../include \
-I$(TWD)/../include/uapi \
-I$(TWD)/include \
# This is safety build by default.
NV_BUILD_CONFIGURATION_IS_SAFETY=1
# This Makefile is only for host POSIX builds
NVGPU_POSIX=1
# Enable fault injection for unit tests
NVGPU_FAULT_INJECTION_ENABLEMENT=1
# Linux configs. We want these so that we can mirror builds from the actual
# Linux kernel.
# include Makefile.configs
CONFIGS := -D__NVGPU_POSIX__ \
-DNVGPU_UNITTEST_FAULT_INJECTION_ENABLEMENT \
-D__NVGPU_UNIT_TEST__
# safety-debug profile is used by default
NVGPU_FORCE_SAFETY_PROFILE := 1
NVGPU_FORCE_DEBUG_PROFILE := 1
include $(NVGPU_SRC)/Makefile.shared.configs
CONFIGS+=$(NVGPU_COMMON_CFLAGS)
# Compiler, c-flags, etc.
# CC = clang
CC = gcc
CFLAGS = -Wall -Wextra -ggdb -Werror -Wno-unused-parameter \
-Wno-missing-field-initializers -Wformat -Wchar-subscripts \
-Wparentheses -Wtrigraphs -Wpointer-arith -Wmissing-declarations \
-Wmissing-prototypes -Wredundant-decls -Wmain -Wreturn-type \
-Wmultichar -Wunused -Wmissing-braces -Wstrict-aliasing \
-Wsign-compare -Waddress -Wno-unused-local-typedefs -fPIC \
-Wno-maybe-uninitialized $(INCLUDES) $(CONFIGS)
LIB_PATHS = -L$(OUT) -L$(UNIT_OUT)
LIBS = -lpthread -pthread -lgcov -ldl
# NV_IS_COVERITY is used by violation whitelisting macros which use pragma
# directives. Whitelisting is only enabled when a coverity scan is being run.
ifeq ($(NV_BUILD_CONFIGURATION_IS_COVERITY),1)
CFLAGS += -Wno-unknown-pragmas
CONFIGS += -DNV_IS_COVERITY
endif
# Source files. We expect $(OBJS) and $(HEADERS) to get filled in here.
include Makefile.sources
all: $(OUT)/nvgpu_unit $(UNITS)
# Convenience targets.
.PHONY: libnvgpu core units
libnvgpu: $(OUT)/libnvgpu-drv-igpu.so
core: $(OUT)/nvgpu_unit
units: $(UNITS)
# Note the weird libnvgpu_unit.so file: this is a bit of a hack. It lets the
# unit tests link back against the nvgpu_unit executable so that they can call
# functions (like unit_info()) directly. This shared library isn't actually
# used for anything beyond that.
#
# Also it really should have its own rule...
$(OUT)/nvgpu_unit: $(OUT)/libnvgpu-drv-igpu.so $(CORE_OBJS)
$(CC) -shared -o $(OUT)/libnvgpu_unit.so \
$(CORE_OBJS) $(LIB_PATHS) $(LIBS)
$(CC) --coverage \
-o $(OUT)/nvgpu_unit $(CORE_OBJS) $(LIB_PATHS) $(LIBS)
$(OUT)/libnvgpu-drv-igpu.so: $(OBJS)
$(CC) -shared -Wl,--no-undefined -o $(OUT)/libnvgpu-drv-igpu.so $(OBJS) -lgcov -rdynamic -lpthread
# Default build target for all the nvgpu driver object files we want to build in
# userspace. These get bundled into libnvgpu-drv-igpu.so.
$(NVGPU_OUT)/%.o : $(NVGPU_SRC)/%.c $(HEADERS)
@if [ ! -d $(dir $@) ] ; then \
mkdir -p $(dir $@) ; \
fi
$(CC) --coverage $(CFLAGS) -c -o $@ $<
# Default build target for all the nvgpu-next driver object files we want to
# build in userspace. These too get bundled into libnvgpu-drv-igpu.so.
$(NVGPU_OUT)/%.o : $(NVGPU_NEXT_SRC)/%.c $(HEADERS) $(HEADERS_NEXT)
@if [ ! -d $(dir $@) ] ; then \
mkdir -p $(dir $@) ; \
fi
$(CC) --coverage $(CFLAGS) $(configs) -c -o $@ $<
# Build target for unit test files. These are not part of the libnvgpu-drv-igpu.so.
# These comprise the unit test framework.
$(CORE_OUT)/%.o : $(CORE_SRC)/%.c $(CORE_HEADERS)
@if [ ! -d $(dir $@) ] ; then \
mkdir -p $(dir $@) ; \
fi
$(CC) --coverage $(CFLAGS) -c -o $@ $<
# Certain variables should be exported to the unit test module builds.
export TWD INCLUDES CONFIGS UNIT_SRC UNIT_OUT
export CC CFLAGS LIB_PATHS LIBS
.PHONY: $(UNITS)
$(UNITS): $(OUT)/libnvgpu-drv-igpu.so
@echo "Building unit module: $@"
@+$(MAKE) --no-print-directory -C $@
.PHONY: clean nvgpu_clean core_clean unit_clean
clean: nvgpu_clean core_clean unit_clean
rm -rf $(OUT)
nvgpu_clean:
rm -rf $(OUT)/libnvgpu*
core_clean:
rm -rf $(OUT)/nvgpu_unit*
unit_clean:
@for d in $(UNITS); do \
echo Cleaning $$d; \
$(MAKE) --no-print-directory -C $$d clean; \
done
rm -rf $(OUT)/units

View File

@@ -0,0 +1,38 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
#
# Copyright (c) 2018-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
#
###############################################################################
ifdef NV_INTERFACE_FLAG_SHARED_LIBRARY_SECTION
NV_INTERFACE_NAME := nvgpu-unit
NV_INTERFACE_EXPORTS := libnvgpu-unit
NV_INTERFACE_PUBLIC_INCLUDES := include
endif
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

160
userspace/Makefile.sources Normal file
View File

@@ -0,0 +1,160 @@
# -*- mode: makefile -*-
#
# Copyright (c) 2019-2021, 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 $(NVGPU_SRC)/Makefile.sources
include $(NVGPU_NEXT_SRC)/Makefile.sources
OBJS := $(srcs:%.c=$(NVGPU_OUT)/%.o) $(srcs_next:%.c=$(NVGPU_OUT)/%.o)
HEADERS := \
$(NVGPU_SRC)/include/nvgpu/*.h \
$(NVGPU_SRC)/include/nvgpu/hw/*/*.h
CORE_OBJS := \
$(CORE_OUT)/unit_main.o \
$(CORE_OUT)/nvgpu.o \
$(CORE_OUT)/args.o \
$(CORE_OUT)/io.o \
$(CORE_OUT)/module.o \
$(CORE_OUT)/required_tests.o \
$(CORE_OUT)/results.o \
$(CORE_OUT)/exec.o
CORE_HEADERS := \
$(CORE_SRC)/../include/unit/*.h
# Each directory under the UNIT_SRC directory should correspond to one module.
UNITS := \
$(UNIT_SRC)/posix/env \
$(UNIT_SRC)/posix/bitops \
$(UNIT_SRC)/posix/fault-injection \
$(UNIT_SRC)/posix/bug \
$(UNIT_SRC)/posix/os_sched \
$(UNIT_SRC)/posix/log2 \
$(UNIT_SRC)/posix/sizes \
$(UNIT_SRC)/posix/thread \
$(UNIT_SRC)/posix/cond \
$(UNIT_SRC)/posix/timers \
$(UNIT_SRC)/posix/kmem \
$(UNIT_SRC)/posix/rwsem \
$(UNIT_SRC)/posix/queue \
$(UNIT_SRC)/posix/utils \
$(UNIT_SRC)/posix/circ_buf \
$(UNIT_SRC)/bus \
$(UNIT_SRC)/pramin \
$(UNIT_SRC)/ptimer \
$(UNIT_SRC)/priv_ring \
$(UNIT_SRC)/init \
$(UNIT_SRC)/interface/bit-utils \
$(UNIT_SRC)/interface/lock \
$(UNIT_SRC)/interface/nvgpu_gk20a \
$(UNIT_SRC)/interface/atomic \
$(UNIT_SRC)/interface/rbtree \
$(UNIT_SRC)/interface/static_analysis \
$(UNIT_SRC)/interface/string \
$(UNIT_SRC)/interface/worker \
$(UNIT_SRC)/interface/kref \
$(UNIT_SRC)/interface/list \
$(UNIT_SRC)/mc \
$(UNIT_SRC)/mm/nvgpu_sgt \
$(UNIT_SRC)/mm/allocators/buddy_allocator \
$(UNIT_SRC)/mm/allocators/nvgpu_allocator \
$(UNIT_SRC)/mm/allocators/bitmap_allocator \
$(UNIT_SRC)/mm/allocators/page_allocator \
$(UNIT_SRC)/mm/as \
$(UNIT_SRC)/mm/dma \
$(UNIT_SRC)/mm/gmmu/pd_cache \
$(UNIT_SRC)/mm/gmmu/page_table \
$(UNIT_SRC)/mm/hal/cache/flush_gk20a_fusa \
$(UNIT_SRC)/mm/hal/cache/flush_gv11b_fusa \
$(UNIT_SRC)/mm/hal/gmmu/gmmu_gk20a_fusa \
$(UNIT_SRC)/mm/hal/gmmu/gmmu_gm20b_fusa \
$(UNIT_SRC)/mm/hal/gmmu/gmmu_gp10b_fusa \
$(UNIT_SRC)/mm/hal/gmmu/gmmu_gv11b_fusa \
$(UNIT_SRC)/mm/hal/gp10b_fusa \
$(UNIT_SRC)/mm/hal/gv11b_fusa \
$(UNIT_SRC)/mm/hal/mmu_fault/gv11b_fusa \
$(UNIT_SRC)/mm/mm \
$(UNIT_SRC)/mm/page_table_faults \
$(UNIT_SRC)/mm/nvgpu_mem \
$(UNIT_SRC)/mm/vm \
$(UNIT_SRC)/netlist \
$(UNIT_SRC)/fb \
$(UNIT_SRC)/fbp \
$(UNIT_SRC)/fifo \
$(UNIT_SRC)/fifo/fifo/gk20a \
$(UNIT_SRC)/fifo/fifo/gv11b \
$(UNIT_SRC)/fifo/channel \
$(UNIT_SRC)/fifo/channel/gk20a \
$(UNIT_SRC)/fifo/channel/gm20b \
$(UNIT_SRC)/fifo/channel/gv11b \
$(UNIT_SRC)/fifo/ctxsw_timeout/gv11b \
$(UNIT_SRC)/fifo/engine \
$(UNIT_SRC)/fifo/engine/gm20b \
$(UNIT_SRC)/fifo/engine/gp10b \
$(UNIT_SRC)/fifo/engine/gv100 \
$(UNIT_SRC)/fifo/engine/gv11b \
$(UNIT_SRC)/fifo/fifo \
$(UNIT_SRC)/fifo/pbdma \
$(UNIT_SRC)/fifo/pbdma/gm20b \
$(UNIT_SRC)/fifo/pbdma/gp10b \
$(UNIT_SRC)/fifo/pbdma/gv11b \
$(UNIT_SRC)/fifo/preempt \
$(UNIT_SRC)/fifo/preempt/gv11b \
$(UNIT_SRC)/fifo/ramfc/gp10b \
$(UNIT_SRC)/fifo/ramfc/gv11b \
$(UNIT_SRC)/fifo/ramin/gk20a \
$(UNIT_SRC)/fifo/ramin/gm20b \
$(UNIT_SRC)/fifo/ramin/gv11b \
$(UNIT_SRC)/fifo/runlist \
$(UNIT_SRC)/fifo/runlist/gk20a \
$(UNIT_SRC)/fifo/runlist/gv11b \
$(UNIT_SRC)/fifo/tsg \
$(UNIT_SRC)/fifo/tsg/gv11b \
$(UNIT_SRC)/fifo/userd/gk20a \
$(UNIT_SRC)/fifo/usermode/gv11b \
$(UNIT_SRC)/ltc \
$(UNIT_SRC)/enabled \
$(UNIT_SRC)/falcon \
$(UNIT_SRC)/falcon/falcon_tests \
$(UNIT_SRC)/fuse \
$(UNIT_SRC)/pmu \
$(UNIT_SRC)/therm \
$(UNIT_SRC)/top \
$(UNIT_SRC)/class \
$(UNIT_SRC)/gr \
$(UNIT_SRC)/gr/falcon \
$(UNIT_SRC)/gr/config \
$(UNIT_SRC)/gr/init \
$(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 \
$(UNIT_SRC)/ce \
$(UNIT_SRC)/cg \
$(UNIT_SRC)/rc \
$(UNIT_SRC)/sync \
$(UNIT_SRC)/ecc \
$(UNIT_SRC)/io

134
userspace/Makefile.tmk Normal file
View File

@@ -0,0 +1,134 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2018-2020, 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_COMMON_SRCS := \
src/nvgpu.c \
src/args.c \
src/io.c \
src/module.c \
src/required_tests.c \
src/results.c \
src/exec.c
NVGPU_UNIT_COMMON_INCLUDES := \
include \
../drivers/gpu/nvgpu \
../drivers/gpu/nvgpu/include
ifdef NV_COMPONENT_FLAG_NVTEST_EXECUTABLE_SECTION
include $(NV_BUILD_START_COMPONENT)
NV_COMPONENT_NAME := nvgpu_unit
NV_COMPONENT_SOURCES := \
src/unit_main.c \
$(NVGPU_UNIT_COMMON_SRCS)
NV_COMPONENT_INCLUDES := \
$(NVGPU_UNIT_COMMON_INCLUDES)
ifndef NVGPU_UNIT_GPU
NVGPU_UNIT_GPU := igpu
endif
NV_COMPONENT_NEEDED_INTERFACE_DIRS := ../libs/$(NVGPU_UNIT_GPU)
ifneq ($(NV_BUILD_CONFIGURATION_OS_IS_QNX),1)
NV_COMPONENT_SYSTEM_SHARED_LIBRARIES += pthread
NV_COMPONENT_SYSTEM_SHARED_LIBRARIES += dl
NV_COMPONENT_SYSTEM_SHARED_LIBRARIES += gcov
endif
_NV_TOOLCHAIN_CFLAGS += -rdynamic
NV_UNIT_SH=unit.sh
NV_SUBMIT_UNIT_SH=nvgpu_submit_unit.sh
NV_TESTLIST_PY=testlist.py
NV_REQ_TESTS_INI=required_tests.ini
NV_COMPONENT_SYSTEMIMAGE_DIR := $(NV_SYSTEMIMAGE_TEST_EXECUTABLE_DIR)/nvgpu_unit
systemimage:: $(NV_COMPONENT_SYSTEMIMAGE_DIR) $(NV_COMPONENT_SYSTEMIMAGE_DIR)/$(NV_UNIT_SH) \
$(NV_SYSTEMIMAGE_TEST_EXECUTABLE_DIR)/$(NV_SUBMIT_UNIT_SH) \
$(NV_COMPONENT_SYSTEMIMAGE_DIR)/$(NV_TESTLIST_PY) \
$(NV_COMPONENT_SYSTEMIMAGE_DIR)/$(NV_REQ_TESTS_INI)
#make the output directory
$(NV_COMPONENT_SYSTEMIMAGE_DIR) : $(NV_SYSTEMIMAGE_TEST_EXECUTABLE_DIR)
$(MKDIR_P) $@
#copy the test script
$(NV_COMPONENT_SYSTEMIMAGE_DIR)/$(NV_UNIT_SH) : $(NV_COMPONENT_DIR)/$(NV_UNIT_SH) $(NV_COMPONENT_SYSTEMIMAGE_DIR)
$(CP) $< $@
#the submit script goes in the parent directory
$(NV_SYSTEMIMAGE_TEST_EXECUTABLE_DIR)/$(NV_SUBMIT_UNIT_SH) : $(NV_COMPONENT_DIR)/$(NV_SUBMIT_UNIT_SH) $(NV_COMPONENT_SYSTEMIMAGE_DIR)
$(CP) $< $@
$(NV_COMPONENT_SYSTEMIMAGE_DIR)/$(NV_TESTLIST_PY) : $(NV_COMPONENT_DIR)/$(NV_TESTLIST_PY) $(NV_COMPONENT_SYSTEMIMAGE_DIR)
$(CP) $< $@
$(NV_COMPONENT_SYSTEMIMAGE_DIR)/$(NV_REQ_TESTS_INI) : $(NV_COMPONENT_DIR)/$(NV_REQ_TESTS_INI) $(NV_COMPONENT_SYSTEMIMAGE_DIR)
$(CP) $< $@
include $(NV_BUILD_NVTEST_EXECUTABLE)
endif
ifdef NV_COMPONENT_FLAG_SHARED_LIBRARY_SECTION
include $(NV_BUILD_START_COMPONENT)
NV_COMPONENT_NAME := nvgpu_unit-lib
NV_COMPONENT_OWN_INTERFACE_DIR := .
NV_COMPONENT_SOURCES := \
$(NVGPU_UNIT_COMMON_SRCS)
NV_COMPONENT_INCLUDES := \
$(NVGPU_UNIT_COMMON_INCLUDES)
ifneq ($(NV_BUILD_CONFIGURATION_OS_IS_QNX),1)
NV_COMPONENT_SYSTEM_SHARED_LIBRARIES += pthread
NV_COMPONENT_SYSTEM_SHARED_LIBRARIES += dl
NVGPU_FORCE_SAFETY_PROFILE := 1
NVGPU_FORCE_DEBUG_PROFILE := 1
endif
NV_COMPONENT_CFLAGS += \
-D__NVGPU_POSIX__ \
-DNVGPU_UNITTEST_FAULT_INJECTION_ENABLEMENT
-include ../drivers/gpu/nvgpu/Makefile.shared.configs
NV_COMPONENT_CFLAGS += $(NVGPU_COMMON_CFLAGS)
NV_COMPONENT_SYSTEMIMAGE_DIR := $(NV_SYSTEMIMAGE_TEST_EXECUTABLE_DIR)/nvgpu_unit/
systemimage:: $(NV_COMPONENT_SYSTEMIMAGE_DIR)
$(NV_COMPONENT_SYSTEMIMAGE_DIR) : $(NV_SYSTEMIMAGE_TEST_EXECUTABLE_DIR)
$(MKDIR_P) $@
NV_COMPONENT_SYSTEMIMAGE_NAME := libnvgpu-unit.so
include $(NV_BUILD_SHARED_LIBRARY)
endif
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

156
userspace/SWUTS.h Normal file
View File

@@ -0,0 +1,156 @@
/*
* Copyright (c) 2019-2021, 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.
*/
/**
* @file
* @page NVGPU-SWUTS
*
* NVGPU Software Unit Test Specifications
* =======================================
*
* The following pages cover the various unit test specifications needed
* to test the NVGPU driver.
*
* - @ref SWUTS-enabled
* - @ref SWUTS-interface-bit-utils
* - @ref SWUTS-interface-lock
* - @ref SWUTS-interface-nvgpu-gk20a
* - @ref SWUTS-interface-rbtree
* - @ref SWUTS-interface-static_analysis
* - @ref SWUTS-interface-string
* - @ref SWUTS-interface-worker
* - @ref SWUTS-interface-kref
* - @ref SWUTS-interface-list
* - @ref SWUTS-bus
* - @ref SWUTS-falcon
* - @ref SWUTS-netlist
* - @ref SWUTS-fifo
* - @ref SWUTS-fifo-channel
* - @ref SWUTS-fifo-channel-gk20a
* - @ref SWUTS-fifo-channel-gm20b
* - @ref SWUTS-fifo-channel-gv11b
* - @ref SWUTS-fifo-ctxsw_timeout-gv11b
* - @ref SWUTS-fifo-engine
* - @ref SWUTS-fifo-engine-gm20b
* - @ref SWUTS-fifo-engine-gp10b
* - @ref SWUTS-fifo-engine-gv100
* - @ref SWUTS-fifo-engine-gv11b
* - @ref SWUTS-fifo-fifo
* - @ref SWUTS-fifo-fifo-gk20a
* - @ref SWUTS-fifo-fifo-gv11b
* - @ref SWUTS-fifo-pbdma
* - @ref SWUTS-fifo-pbdma-gm20b
* - @ref SWUTS-fifo-pbdma-gp10b
* - @ref SWUTS-fifo-pbdma-gv11b
* - @ref SWUTS-fifo-preempt
* - @ref SWUTS-fifo-preempt-gv11b
* - @ref SWUTS-fifo-ramfc-gp10b
* - @ref SWUTS-fifo-ramfc-gv11b
* - @ref SWUTS-fifo-ramin-gk20a
* - @ref SWUTS-fifo-ramin-gm20b
* - @ref SWUTS-fifo-ramin-gp10b
* - @ref SWUTS-fifo-ramin-gv11b
* - @ref SWUTS-fifo-runlist
* - @ref SWUTS-fifo-runlist-gk20a
* - @ref SWUTS-fifo-runlist-gv11b
* - @ref SWUTS-fifo-tsg
* - @ref SWUTS-fifo-tsg-gv11b
* - @ref SWUTS-fifo-userd-gk20a
* - @ref SWUTS-fifo-usermode-gv11b
* - @ref SWUTS-nvgpu-sync
* - @ref SWUTS-init
* - @ref SWUTS-intr
* - @ref SWUTS-interface-atomic
* - @ref SWUTS-ltc
* - @ref SWUTS-nvgpu-rc
* - @ref SWUTS-mc
* - @ref SWUTS-mm-allocators-bitmap-allocator
* - @ref SWUTS-mm-allocators-buddy-allocator
* - @ref SWUTS-mm-allocators-nvgpu-allocator
* - @ref SWUTS-mm-as
* - @ref SWUTS-mm-dma
* - @ref SWUTS-mm-gmmu-page_table
* - @ref SWUTS-mm-gmmu-pd_cache
* - @ref SWUTS-mm-hal-cache-flush-gk20a-fusa
* - @ref SWUTS-mm-hal-cache-flush-gv11b-fusa
* - @ref SWUTS-mm-hal-gmmu-gmmu_gk20a_fusa
* - @ref SWUTS-mm-hal-gmmu-gmmu_gm20b_fusa
* - @ref SWUTS-mm-hal-gmmu-gmmu_gp10b_fusa
* - @ref SWUTS-mm-hal-gmmu-gmmu_gv11b_fusa
* - @ref SWUTS-mm-hal-gp10b_fusa
* - @ref SWUTS-mm-hal-gv11b-fusa
* - @ref SWUTS-mm-hal-mmu_fault-gv11b_fusa
* - @ref SWUTS-mm-nvgpu-mem
* - @ref SWUTS-mm-nvgpu-sgt
* - @ref SWUTS-mm-page_table_faults
* - @ref SWUTS-mm-mm
* - @ref SWUTS-mm-vm
* - @ref SWUTS-nvgpu-sync
* - @ref SWUTS-fb
* - @ref SWUTS-fbp
* - @ref SWUTS-fuse
* - @ref SWUTS-posix-bitops
* - @ref SWUTS-posix-cond
* - @ref SWUTS-posix-log2
* - @ref SWUTS-posix-fault-injection
* - @ref SWUTS-posix-sizes
* - @ref SWUTS-posix-thread
* - @ref SWUTS-posix-timers
* - @ref SWUTS-posix-queue
* - @ref SWUTS-posix-bug
* - @ref SWUTS-posix-ossched
* - @ref SWUTS-posix-rwsem
* - @ref SWUTS-posix-utils
* - @ref SWUTS-posix-circbuf
* - @ref SWUTS-posix-kmem
* - @ref SWUTS-priv_ring
* - @ref SWUTS-ptimer
* - @ref SWUTS-sdl
* - @ref SWUTS-therm
* - @ref SWUTS-acr
* - @ref SWUTS-ce
* - @ref SWUTS-cg
* - @ref SWUTS-init_test
* - @ref SWUTS-power_mgmt
* - @ref SWUTS-qnx-fuse
* - @ref SWUTS-nvrm_dev_os
* - @ref SWUTS-devctl_ctrl
* - @ref SWUTS-channel_os
* - @ref SWUTS-top
* - @ref SWUTS-class
* - @ref SWUTS-gr
* - @ref SWUTS-gr-setup
* - @ref SWUTS-gr-intr
* - @ref SWUTS-gr-init-hal-gv11b
* - @ref SWUTS-gr-falcon
* - @ref SWUTS-gr-falcon-gm20b
* - @ref SWUTS-gr-fs-state
* - @ref SWUTS-gr-global-ctx
* - @ref SWUTS-gr-ctx
* - @ref SWUTS-gr-obj-ctx
* - @ref SWUTS-gr-config
* - @ref SWUTS-ecc
* - @ref SWUTS-pmu
* - @ref SWUTS-io
*
*/

124
userspace/SWUTS.sources Normal file
View File

@@ -0,0 +1,124 @@
INPUT += ../../../userspace/SWUTS.h
INPUT += ../../../userspace/units/ce/nvgpu-ce.h
INPUT += ../../../userspace/units/cg/nvgpu-cg.h
INPUT += ../../../userspace/units/enabled/nvgpu-enabled.h
INPUT += ../../../userspace/units/interface/bit-utils/bit-utils.h
INPUT += ../../../userspace/units/interface/lock/lock.h
INPUT += ../../../userspace/units/interface/nvgpu_gk20a/nvgpu_gk20a.h
INPUT += ../../../userspace/units/interface/rbtree/rbtree.h
INPUT += ../../../userspace/units/interface/static_analysis/static_analysis.h
INPUT += ../../../userspace/units/interface/string/nvgpu-string.h
INPUT += ../../../userspace/units/interface/worker/worker.h
INPUT += ../../../userspace/units/interface/kref/kref.h
INPUT += ../../../userspace/units/interface/list/list.h
INPUT += ../../../userspace/units/bus/nvgpu-bus.h
INPUT += ../../../userspace/units/falcon/falcon_tests/nvgpu-falcon.h
INPUT += ../../../userspace/units/netlist/nvgpu-netlist.h
INPUT += ../../../userspace/units/fbp/nvgpu-fbp.h
INPUT += ../../../userspace/units/fb/fb_fusa.h
INPUT += ../../../userspace/units/fifo/nvgpu-fifo-common.h
INPUT += ../../../userspace/units/fifo/channel/nvgpu-channel.h
INPUT += ../../../userspace/units/fifo/channel/gk20a/nvgpu-channel-gk20a.h
INPUT += ../../../userspace/units/fifo/channel/gm20b/nvgpu-channel-gm20b.h
INPUT += ../../../userspace/units/fifo/channel/gv11b/nvgpu-channel-gv11b.h
INPUT += ../../../userspace/units/fifo/ctxsw_timeout/gv11b/nvgpu-ctxsw-timeout-gv11b.h
INPUT += ../../../userspace/units/fifo/engine/nvgpu-engine.h
INPUT += ../../../userspace/units/fifo/engine/nvgpu-engine-status.h
INPUT += ../../../userspace/units/fifo/engine/gm20b/nvgpu-engine-gm20b.h
INPUT += ../../../userspace/units/fifo/engine/gp10b/nvgpu-engine-gp10b.h
INPUT += ../../../userspace/units/fifo/engine/gv100/nvgpu-engine-gv100.h
INPUT += ../../../userspace/units/fifo/engine/gv11b/nvgpu-engine-gv11b.h
INPUT += ../../../userspace/units/fifo/fifo/nvgpu-fifo.h
INPUT += ../../../userspace/units/fifo/fifo/gk20a/nvgpu-fifo-gk20a.h
INPUT += ../../../userspace/units/fifo/fifo/gk20a/nvgpu-fifo-intr-gk20a.h
INPUT += ../../../userspace/units/fifo/fifo/gv11b/nvgpu-fifo-gv11b.h
INPUT += ../../../userspace/units/fifo/fifo/gv11b/nvgpu-fifo-intr-gv11b.h
INPUT += ../../../userspace/units/fifo/pbdma/nvgpu-pbdma.h
INPUT += ../../../userspace/units/fifo/pbdma/gm20b/nvgpu-pbdma-gm20b.h
INPUT += ../../../userspace/units/fifo/pbdma/gm20b/nvgpu-pbdma-status-gm20b.h
INPUT += ../../../userspace/units/fifo/pbdma/gp10b/nvgpu-pbdma-gp10b.h
INPUT += ../../../userspace/units/fifo/pbdma/gv11b/nvgpu-pbdma-gv11b.h
INPUT += ../../../userspace/units/fifo/preempt/nvgpu-preempt.h
INPUT += ../../../userspace/units/fifo/preempt/gv11b/nvgpu-preempt-gv11b.h
INPUT += ../../../userspace/units/fifo/ramfc/gp10b/nvgpu-ramfc-gp10b.h
INPUT += ../../../userspace/units/fifo/ramfc/gv11b/nvgpu-ramfc-gv11b.h
INPUT += ../../../userspace/units/fifo/ramin/gk20a/ramin-gk20a-fusa.h
INPUT += ../../../userspace/units/fifo/ramin/gm20b/ramin-gm20b-fusa.h
INPUT += ../../../userspace/units/fifo/ramin/gv11b/ramin-gv11b-fusa.h
INPUT += ../../../userspace/units/fifo/runlist/nvgpu-runlist.h
INPUT += ../../../userspace/units/fifo/runlist/gk20a/nvgpu-runlist-gk20a.h
INPUT += ../../../userspace/units/fifo/runlist/gv11b/nvgpu-runlist-gv11b.h
INPUT += ../../../userspace/units/fifo/tsg/nvgpu-tsg.h
INPUT += ../../../userspace/units/fifo/tsg/gv11b/nvgpu-tsg-gv11b.h
INPUT += ../../../userspace/units/rc/nvgpu-rc.h
INPUT += ../../../userspace/units/rc/nvgpu-rc.c
INPUT += ../../../userspace/units/fifo/userd/gk20a/nvgpu-userd-gk20a.h
INPUT += ../../../userspace/units/fifo/userd/gv11b/nvgpu-usermode-gv11b.h
INPUT += ../../../userspace/units/fifo/usermode/gv11b/nvgpu-usermode-gv11b.h
INPUT += ../../../userspace/units/sync/nvgpu-sync.c
INPUT += ../../../userspace/units/sync/nvgpu-sync.h
INPUT += ../../../userspace/units/fuse/nvgpu-fuse.h
INPUT += ../../../userspace/units/fuse/nvgpu-fuse-gm20b.h
INPUT += ../../../userspace/units/fuse/nvgpu-fuse-gp10b.h
INPUT += ../../../userspace/units/init/nvgpu-init.h
INPUT += ../../../userspace/units/interface/atomic/atomic.h
INPUT += ../../../userspace/units/ltc/nvgpu-ltc.h
INPUT += ../../../userspace/units/mc/nvgpu-mc.h
INPUT += ../../../userspace/units/mm/allocators/bitmap_allocator/bitmap_allocator.h
INPUT += ../../../userspace/units/mm/allocators/buddy_allocator/buddy_allocator.h
INPUT += ../../../userspace/units/mm/allocators/nvgpu_allocator/nvgpu_allocator.h
INPUT += ../../../userspace/units/mm/as/as.h
INPUT += ../../../userspace/units/mm/dma/dma.h
INPUT += ../../../userspace/units/mm/gmmu/page_table/page_table.h
INPUT += ../../../userspace/units/mm/gmmu/pd_cache/pd_cache.h
INPUT += ../../../userspace/units/mm/hal/cache/flush_gk20a_fusa/flush-gk20a-fusa.h
INPUT += ../../../userspace/units/mm/hal/cache/flush_gv11b_fusa/flush-gv11b-fusa.h
INPUT += ../../../userspace/units/mm/hal/gmmu/gmmu_gk20a_fusa/gmmu-gk20a-fusa.h
INPUT += ../../../userspace/units/mm/hal/gmmu/gmmu_gm20b_fusa/gmmu-gm20b-fusa.h
INPUT += ../../../userspace/units/mm/hal/gmmu/gmmu_gp10b_fusa/gmmu-gp10b-fusa.h
INPUT += ../../../userspace/units/mm/hal/gmmu/gmmu_gv11b_fusa/gmmu-gv11b-fusa.h
INPUT += ../../../userspace/units/mm/hal/gp10b_fusa/mm-gp10b-fusa.h
INPUT += ../../../userspace/units/mm/hal/gv11b_fusa/mm-gv11b-fusa.h
INPUT += ../../../userspace/units/mm/hal/mmu_fault/gv11b_fusa/mmu-fault-gv11b-fusa.h
INPUT += ../../../userspace/units/mm/nvgpu_mem/nvgpu_mem.h
INPUT += ../../../userspace/units/mm/nvgpu_sgt/nvgpu_sgt.h
INPUT += ../../../userspace/units/mm/page_table_faults/page_table_faults.h
INPUT += ../../../userspace/units/mm/mm/mm.h
INPUT += ../../../userspace/units/mm/vm/vm.h
INPUT += ../../../userspace/units/sync/nvgpu-sync.h
INPUT += ../../../userspace/units/posix/bitops/posix-bitops.h
INPUT += ../../../userspace/units/posix/bug/posix-bug.h
INPUT += ../../../userspace/units/posix/cond/posix-cond.h
INPUT += ../../../userspace/units/posix/log2/posix-log2.h
INPUT += ../../../userspace/units/posix/queue/posix-queue.h
INPUT += ../../../userspace/units/posix/fault-injection/posix-fault-injection.h
INPUT += ../../../userspace/units/posix/fault-injection/posix-fault-injection-kmem.h
INPUT += ../../../userspace/units/posix/fault-injection/posix-fault-injection-dma-alloc.h
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/posix/os_sched/posix-ossched.h
INPUT += ../../../userspace/units/posix/rwsem/posix-rwsem.h
INPUT += ../../../userspace/units/posix/utils/posix-utils.h
INPUT += ../../../userspace/units/posix/circ_buf/posix-circbuf.h
INPUT += ../../../userspace/units/posix/kmem/posix-kmem.h
INPUT += ../../../userspace/units/priv_ring/nvgpu-priv_ring.h
INPUT += ../../../userspace/units/ptimer/nvgpu-ptimer.h
INPUT += ../../../userspace/units/therm/nvgpu-therm.h
INPUT += ../../../userspace/units/acr/nvgpu-acr.h
INPUT += ../../../userspace/units/top/nvgpu-top.h
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/init/nvgpu-gr-init-hal-gv11b.h
INPUT += ../../../userspace/units/gr/falcon/nvgpu-gr-falcon.h
INPUT += ../../../userspace/units/gr/falcon/nvgpu-gr-falcon-gm20b.h
INPUT += ../../../userspace/units/gr/fs_state/nvgpu-gr-fs-state.h
INPUT += ../../../userspace/units/gr/global_ctx/nvgpu-gr-global-ctx.h
INPUT += ../../../userspace/units/gr/ctx/nvgpu-gr-ctx.h
INPUT += ../../../userspace/units/gr/obj_ctx/nvgpu-gr-obj-ctx.h
INPUT += ../../../userspace/units/gr/config/nvgpu-gr-config.h
INPUT += ../../../userspace/units/ecc/nvgpu-ecc.h
INPUT += ../../../userspace/units/pmu/nvgpu-pmu.h
INPUT += ../../../userspace/units/io/common_io.h

103
userspace/gcov.sh Executable file
View File

@@ -0,0 +1,103 @@
#!/bin/bash
#
# Copyright (c) 2018, 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.
# Script to run NVGPU unit tests and collect GCOV coverage.
# First check dependencies and install them if needed
if [ -z $(which gcc) ] || [ -z "$(pip show gcovr)" ]
then
echo "Some dependencies are missing, installing the now..."
sudo apt install gcc python-pip -y
#pip may have a more recent version of gcovr than apt.
pip install gcovr
fi
SCRIPT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )"
pushd $SCRIPT_ROOT
#Libraries are in a different folder on host and target
LIB_FOLDER="."
if [ -d "./build" ]; then
LIB_FOLDER="./build"
fi
#Extract the root path of the source code
NVGPU_SRC_ROOT=$(readelf -p .debug_line $LIB_FOLDER/libnvgpu-drv-igpu.so | \
grep drivers/gpu/nvgpu/os/posix | sed 's/\s*\[.*\]\s*//g' | \
sed 's/drivers\/gpu\/nvgpu\/os\/posix//g' | head -n 1)
NVGPU_SRC_ROOT=$(realpath $NVGPU_SRC_ROOT)
#Make sure the source code is accessible (for on target testing)
if [ -d "$NVGPU_SRC_ROOT/drivers/gpu/nvgpu" ]; then
echo "Root folder for sources: $NVGPU_SRC_ROOT"
else
echo "FATAL: Source code folder not found: $NVGPU_SRC_ROOT"
exit
fi
#Clean existing GCOV files to avoid getting a cumulative result
find . -name "*.gcda" -exec rm {} +
find $NVGPU_SRC_ROOT -name "*.gcda" -exec rm {} +
#Run unit tests
./unit.sh
OUT=$?
if [ ! $OUT -eq 0 ]; then
echo "ERROR: Unit test run failed."
read -p "Press ENTER to run GCOV anyway" -n 1 -r
fi
#Run GCOV
cd ..
if [ -d report ]; then
rm -rf report/
fi
mkdir report
echo "Generating GCOV report..."
python -m gcovr -v -s -e '.+posix/.+' -e '.*userspace/.+' \
-r $NVGPU_SRC_ROOT --html-details --output report/index.html &> gcov.log
#Patch the paths to match output from automative runs so that hashes are identical
sed -i 's/Value\">drivers\//Value\">kernel\/nvgpu\/drivers\//g' report/*.c.html
#Present the results
if [ "$(uname -m)" = "aarch64" ]; then
echo "Running on target, starting a webserver..."
HOST_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
if [[ "$HOST_IP" =~ ^[0-9\.]+$ ]]; then
echo -e "\n\nOpen http://$HOST_IP:8000/ to see the results"
else
echo "ERROR: Network is down: $HOST_IP"
exit 1
fi
cd report/
python -m SimpleHTTPServer &> /dev/null &
PYTHON_PID=$!
cd ..
read -p "Press ENTER to stop the webserver. " -n 1 -r
kill $PYTHON_PID
else
echo "Running on host, opening default browser..."
xdg-open $SCRIPT_ROOT/../report/index.html
fi
popd

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2018-2020, 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_ARGS_H__
#define __UNIT_ARGS_H__
#include <stdbool.h>
/*
* Allow defaults to be changed at compile time.
*/
#define __stringify(x) #x
#define stringify(x) __stringify(x)
#ifndef __DEFAULT_ARG_DRIVER_LOAD_PATH
#if defined(__NVGPU_POSIX__)
#define __DEFAULT_ARG_DRIVER_LOAD_PATH ./build/libnvgpu-drv-igpu.so
#else
#define __DEFAULT_ARG_DRIVER_LOAD_PATH ./libnvgpu-drv-igpu.so
#endif
#endif
#define DEFAULT_ARG_DRIVER_LOAD_PATH stringify(__DEFAULT_ARG_DRIVER_LOAD_PATH)
#ifndef __DEFAULT_ARG_UNIT_LOAD_PATH
#define __DEFAULT_ARG_UNIT_LOAD_PATH build/units
#endif
#define DEFAULT_ARG_UNIT_LOAD_PATH stringify(__DEFAULT_ARG_UNIT_LOAD_PATH)
#define TEST_PLAN_MAX 1
struct unit_fw;
struct unit_fw_args {
bool help;
int verbose_lvl;
bool no_color;
int thread_count;
bool nvtest;
bool is_qnx;
unsigned int test_lvl;
bool debug;
const char *binary_name;
const char *driver_load_path;
const char *unit_name;
const char *unit_load_path;
const char *unit_to_run;
const char *required_tests_file;
};
int core_parse_args(struct unit_fw *fw, int argc, char **argv);
void core_print_help(struct unit_fw *fw);
/*
* Convenience for getting the args struct pointer.
*/
#define args(fw) ((fw)->args)
#endif

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2018-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_CORE_H__
#define __UNIT_CORE_H__
struct unit_fw_args;
struct unit_modules;
struct unit_results;
struct gk20a;
struct nvgpu_posix_fault_inj_container;
/*
* The core unit testing framework data structure. Keeps track of global state
* for the unit test app.
*/
struct unit_fw {
struct unit_fw_args *args;
struct unit_module **modules;
struct unit_results *results;
/*
* driver library interface. Currently the only two directly referenced
* functions are:
*
* nvgpu_posix_probe()
* nvgpu_posix_cleanup()
*
* There will get populated so that we can call them before/after each
* module.
*/
void *nvgpu_so;
struct {
struct gk20a *(*nvgpu_posix_probe)(void);
void (*nvgpu_posix_cleanup)(struct gk20a *g);
void (*nvgpu_posix_init_fault_injection)
(struct nvgpu_posix_fault_inj_container *c);
void (*nvgpu_posix_init_fault_injection_qnx)
(struct nvgpu_posix_fault_inj_container *c);
} nvgpu;
void *nvgpu_qnx_ut;
};
int core_load_nvgpu(struct unit_fw *fw);
int core_exec(struct unit_fw *fw);
int verbose_lvl(struct unit_module *module);
#endif

103
userspace/include/unit/io.h Normal file
View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 2018, 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_IO_H__
#define __UNIT_IO_H__
struct unit_fw;
struct unit_module;
/*
* necessary for args(fw) macro. IO will always, in general, depend on args
* since the args will specify where IO should be directed to.
*/
#include <unit/args.h>
#define core_msg(fw, msg, ...) \
core_vbs(fw, 0, msg, ##__VA_ARGS__)
#define core_msg_color(fw, color, msg, ...) \
core_vbs_color(fw, color, 0, msg, ##__VA_ARGS__)
#define core_vbs_color(fw, color, lvl, msg, ...) \
do { \
if ((lvl) > args(fw)->verbose_lvl) \
continue; \
\
/* Print if verbosity level is high enough. */ \
__core_print_stdout(fw, color, msg, ##__VA_ARGS__); \
} while (0)
#define core_vbs(fw, lvl, msg, ...) \
core_vbs_color(fw, NULL, lvl, msg, ##__VA_ARGS__)
#define core_err(fw, msg, ...) \
__core_print_stderr(fw, "(%s:%d) " msg, \
__func__, __LINE__, ##__VA_ARGS__)
/*
* Output macro for unit tests to use.
*/
#define unit_info(unit, msg, ...) \
__unit_info_color(unit, NULL, msg, ##__VA_ARGS__)
#define unit_err(unit, msg, ...) \
__unit_info_color(unit, C_RED, msg, ##__VA_ARGS__)
/*
* helper to check a condition, output and error if condition is false
* and execute bail_out_code
*/
#define unit_assert(cond, bail_out_code) \
do { \
if (!(cond)) { \
unit_err(m, "%s:%d (" #cond ") is false\n", \
__func__, __LINE__); \
bail_out_code; \
} \
} while (0)
/*
* Don't go overboard with these!!!
*/
#define C_RED "\x1B[31m"
#define C_GREEN "\x1B[32m"
#define C_YELLOW "\x1B[33m"
#define C_BLUE "\x1B[34m"
#define C_MAGENTA "\x1B[35m"
#define C_CYAN "\x1B[36m"
#define C_WHITE "\x1B[37m"
#define C_RESET "\x1B[0m"
/*
* Printing functions. Do not use these directly. Instead use the provided
* macros.
*/
__attribute__((format (printf, 3, 4)))
void __core_print_stdout(struct unit_fw *fw, const char *color,
const char *fmt, ...);
__attribute__((format (printf, 2, 3)))
void __core_print_stderr(struct unit_fw *fw, const char *fmt, ...);
__attribute__((format (printf, 3, 4)))
void __unit_info_color(struct unit_module *unit, const char *color,
const char *fmt, ...);
#endif

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018, 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_MODULE_H__
#define __UNIT_MODULE_H__
struct unit_fw;
struct unit_module;
struct unit_module **core_load_modules(struct unit_fw *fw);
#endif

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2020, 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 __REQUIRED_TESTS_H__
#define __REQUIRED_TESTS_H__
#define MAX_LINE_SIZE 256
int parse_req_file(struct unit_fw *fw, const char *ini_file);
int check_executed_tests(struct unit_fw *fw);
#endif

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2018-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_RESULTS_H__
#define __UNIT_RESULTS_H__
/*
* Keep track of the the results of a set of unit tests. This is effectively
* just a single linked list of records for each test.
*/
struct unit_test_record {
/*
* Let's us determine the name of the test.
*/
struct unit_module *mod;
struct unit_module_test *test;
/*
* True for pass, false for fail.
*/
bool status;
struct unit_test_record *next;
};
struct unit_test_list {
struct unit_test_record *head;
struct unit_test_record *last;
};
enum result_enum {
PASSED,
FAILED,
SKIPPED,
};
struct unit_results {
struct unit_test_list passing;
struct unit_test_list failing;
struct unit_test_list skipped;
int nr_tests;
int nr_passing;
int nr_skipped;
};
#define for_record_in_test_list(__test_list, __test) \
for ((__test) = (__test_list)->head; \
(__test) != NULL; \
(__test) = (__test)->next)
int core_add_test_record(struct unit_fw *fw,
struct unit_module *mod,
struct unit_module_test *test,
enum result_enum result);
void core_print_test_status(struct unit_fw *fw);
#endif

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2018-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_UNIT_REQUIREMENT_IDS_H__
#define __UNIT_UNIT_REQUIREMENT_IDS_H__
/*
* Unit requirement test specification unique IDs.
*/
#define PD_CACHE_REQ1_UID "6439202"
#define PD_CACHE_REQ2_UID "6898078"
#define PD_CACHE_REQ3_UID "6957786"
#define PD_CACHE_REQ4_UID "6962424"
#define PD_CACHE_REQ5_UID "6963067"
#define PD_CACHE_REQ6_UID "6962548"
#define PD_CACHE_REQ7_UID "7138651"
#define PD_CACHE_REQ8_UID "6962610"
#define PAGE_TABLE_REQ1_UID "6439094"
#define VM_REQ1_UID "6434840"
#endif

View File

@@ -0,0 +1,192 @@
/*
* Copyright (c) 2018-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_UNIT_H__
#define __UNIT_UNIT_H__
#include <pthread.h>
struct gk20a;
struct unit_module;
typedef int (*module_test_fn)(struct unit_module *m,
struct gk20a *g, void *args);
#define UNIT_SUCCESS 0
#define UNIT_FAIL -1
struct unit_module_test {
/*
* Function to call to execute the test.
*/
module_test_fn fn;
/*
* Name of the test function. It will be used to match the test
* results with its SWUTS.
*/
const char *fn_name;
/*
* Name of the test. It can be used to describe a subcase when the
* same test function is used several times.
*/
const char *case_name;
/*
* Minimum test plan level (L0, L1) to execute the test.
*/
unsigned int test_lvl;
/*
* A void pointer to arbitrary arguments. Lets the same unit test
* function perform multiple tests. This gets passed into the
* module_test_fn as @args.
*/
void *args;
/*
* Linkage to JAMA test specification. An example would be:
*
* .requirement = "NVGPU-RQCD-68"
* .verification_criteria = "C1"
*
* This would link to C1 verification criteria of the pd_cache
* requirement NVGPU-RQCD-68.
*
* This is an optional field for any given unit test. But a unit
* test module must satisfy the necessary VC for all requirements
* within that unit.
*/
struct {
/*
* Requirement linkage: this should point to the unique ID
* of the test specification.
*/
const char *unique_id;
/*
* The particular verification criteria that this is
* satisfying.
*/
const char *verification_criteria;
/*
* Specific requirement this test provides coverage for.
*/
const char *requirement;
} jama;
};
/*
* Interface to the unit test framework module loader. Each unit test module
* will have exactly one of these.
*/
struct unit_module {
/*
* Name of the module.
*/
const char *name;
/*
* NULL terminated list of tests within the module.
*/
struct unit_module_test *tests;
unsigned long nr_tests;
/*
* Run priority. Currently 3 defined:
*
* UNIT_PRIO_SELF_TEST
* UNIT_PRIO_POSIX_TEST
* UNIT_PRIO_NVGPU_TEST
*
* These let us run environment and POSIX API wrapper tests before the
* rest of the unit tests run.
*/
unsigned int prio;
/*
* For the core FW to use. Not for modules!!!
*/
void *lib_handle;
struct unit_fw *fw;
pthread_t thread;
};
/*
* Zero is the higest priority. Increasing the prio value decreases priority to
* run.
*/
#define UNIT_PRIO_SELF_TEST 0U
#define UNIT_PRIO_POSIX_TEST 50U
#define UNIT_PRIO_NVGPU_TEST 100U
#define UNIT_MODULE(__name, __tests, __prio) \
struct unit_module __unit_module__ = { \
.name = #__name, \
.tests = __tests, \
.nr_tests = (sizeof(__tests) / \
sizeof(struct unit_module_test)), \
.prio = __prio, \
.lib_handle = NULL, \
.fw = NULL, \
}
#define UNIT_TEST(__name, __fn, __args, __test_lvl) \
{ \
.fn_name = #__fn, \
.case_name = #__name, \
.fn = __fn, \
.args = __args, \
.test_lvl = __test_lvl, \
.jama.requirement = "", \
.jama.unique_id = "", \
.jama.verification_criteria = "", \
}
/*
* Use this for a unit test that satisfies or contributes to satisfying a
* verification criteria for a given requirement.
*/
#define UNIT_TEST_REQ(__req, __uid, __vc, __name, __fn, __args, __test_lvl) \
{ \
.fn_name = #__fn, \
.case_name = #__name, \
.fn = __fn, \
.args = __args, \
.test_lvl = __test_lvl, \
.jama.requirement = __req, \
.jama.unique_id = __uid, \
.jama.verification_criteria = __vc, \
}
#define unit_return_fail(m, msg, ...) \
do { \
unit_err(m, "%s():%d " msg, \
__func__, __LINE__, ##__VA_ARGS__); \
return UNIT_FAIL; \
} while (0)
#endif

136
userspace/install-unit.sh Executable file
View File

@@ -0,0 +1,136 @@
#!/bin/bash
#
# Copyright (c) 2019-2020, 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.
#
# Install the unit test binaries, build by tmake, onto a jetson running
# L4T. The only argument is the IP address of the jetson.
#
usage() {
echo "Usage:"
echo ""
echo " $ $1 [-hs] [--help] [--install-sshkey] <jetson-ip>"
echo ""
}
# Copy to target jetson. Takes a local path and a remote path relative
# to ubuntu's $HOME.
#
# It helps a lot of you set up an authorized key on the target! Otherwise
# you may have a lot of typing to do...
jcp() {
cmd="rsync -qur $1 $target:$2"
echo "> $cmd"
$cmd
}
# Add our public key to the authorized key list on the target host.
install_ssh_key() {
ssh-copy-id -f $target
return $?
}
# Variables which may be set by CLI arguments.
install_sshkey=
# To start with filter out any non-target arguments. Right now that's only -h
# and -s.
positionals=()
while [[ $# -gt 0 ]]
do
arg="$1"
case $arg in
-h|--help)
usage $0
exit 1
;;
-s|--install-sshkey)
install_sshkey=yes
shift
;;
*)
positionals+=("$1")
shift
;;
esac
done
set -- "${positionals[@]}"
if [ "x$1" == "x" ]
then
echo "Missing IP address!"
usage $0
exit 1
fi
if [ "x$TOP" == "x" ]
then
echo "\$TOP must be set!"
exit 1
fi
target="ubuntu@$1"
nvgpu_bins=$TOP/out/*/nvidia/kernel/nvgpu
# Install the ssh key if needed.
if [ "$install_sshkey" == "yes" ]
then
echo "Installing our SSH key"
install_ssh_key $target || exit 1
fi
# Building the necessary directory structure. It may not be present
# first time this is run.
ssh $target mkdir -p nvgpu_unit/units/igpu
ssh $target mkdir -p nvgpu_unit/firmware/gv11b
ssh $target mkdir -p $TOP/kernel
if [ $? != 0 ]; then
echo
echo "!! Unable to make $TOP on the target jetson! This directory needs"
echo "!! to be present and writable by this script in order for coverage"
echo "!! tracking to work."
exit 1
fi
# And copy...
jcp $nvgpu_bins/userspace-l4t_64/nvgpu_unit nvgpu_unit/nvgpu_unit
jcp $nvgpu_bins/userspace-l4t_64/libnvgpu_unit-lib.so nvgpu_unit/libnvgpu-unit.so
jcp $nvgpu_bins/libs/igpu-l4t_64/libnvgpu-drv-igpu.so nvgpu_unit/libnvgpu-drv-igpu.so
jcp $TOP/kernel/nvgpu/userspace/unit.sh nvgpu_unit/unit.sh
jcp $TOP/kernel/nvgpu/userspace/gcov.sh nvgpu_unit/gcov.sh
jcp $TOP/kernel/nvgpu/userspace/testlist.py nvgpu_unit/testlist.py
find $nvgpu_bins/userspace/units -name "*.so" -not -path "*unit.so" \
-not -path "*drv.so" -exec du -b {} \; | sort -n | while read size unit_so ; do
jcp $unit_so nvgpu_unit/units/igpu
done
# Set up the necessary coverage files. Basically what we do is recreate just
# enough of the source/build output here on the local machine over on the
# target jetson. This means you may
jcp $nvgpu_bins nvgpu_unit
jcp $TOP/kernel/nvgpu $TOP/kernel
if [ -d TOP/kernel/nvgpu-next ]; then
jcp $TOP/kernel/nvgpu-next $TOP/kernel
fi

View File

@@ -0,0 +1,26 @@
#
# Copyright (c) 2018-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.
#
__core_print_stdout
__core_print_stderr
__unit_info_color
verbose_lvl

34
userspace/nvgpu_submit_unit.sh Executable file
View File

@@ -0,0 +1,34 @@
#!/bin/bash
#
# 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.
#
# Execute the unit test. Args to this script are passed on to the unit test
# core. This just serves to set the LD_LIBRARY_PATH environment variable such
# that unit tests are found and nvgpu-drv-igpu is found.
#
this_script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )"
pushd $this_script_dir/nvgpu_unit
./unit.sh $*
rc=$?
popd
exit $rc

1072
userspace/required_tests.ini Normal file
View File

File diff suppressed because it is too large Load Diff

201
userspace/src/args.c Normal file
View File

@@ -0,0 +1,201 @@
/*
* Copyright (c) 2018-2020, 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 <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <unit/core.h>
#include <unit/args.h>
#include <unit/io.h>
static struct option core_opts[] = {
{ "help", 0, NULL, 'h' },
{ "verbose", 0, NULL, 'v' },
{ "quiet", 0, NULL, 'q' },
{ "no-color", 0, NULL, 'C' },
{ "nvtest", 0, NULL, 'n' },
{ "is-qnx", 0, NULL, 'Q' },
{ "unit-load-path", 1, NULL, 'L' },
{ "driver-load-path", 1, NULL, 'K' },
{ "num-threads", 1, NULL, 'j' },
{ "test-level", 1, NULL, 't' },
{ "debug", 0, NULL, 'd' },
{ "required", 0, NULL, 'r' },
{ NULL, 0, NULL, 0 }
};
static const char *core_opts_str = "hvqCnQL:K:j:t:dr:";
void core_print_help(struct unit_fw *fw)
{
const char **line, *help_msg[] = {
"NvGpu Unit Testing FW. Basic usage\n",
"\n",
" $ nvgpu_unit [options] <unit>\n",
"\n",
"Basic usage consists of one or more options and a particular unit test to\n",
"execute.\n",
"\n",
"Available options are as follows:\n",
"\n",
" -h, --help Print this help message and exit.\n",
" -v, --verbose Increment the verbosity level. Can be specified\n",
" multiple times.\n",
" -q, --quiet Set the verbose level back to 0.\n",
" -C, --no-color Disable color printing; for example, if writing\n",
" output to a file the color escape sequences will\n",
" corrupt that file.\n",
" -n, --nvtest Enable nvtest-formatted output results\n",
" -Q, --is-qnx QNX specific tests\n",
" -L, --unit-load-path <PATH>\n",
" Path to where the unit test libraries reside.\n",
" -K, --driver-load-path <PATH>\n",
" Path to driver library.\n",
" -j, --num-threads <COUNT>\n",
" Number of threads to use while running all tests.\n",
" -t, --test-level <LEVEL>\n",
" Test plan level. 0=L0, 1=L1. default: 1\n",
" -d, --debug Disable signal handling to facilitate debug of",
" crashes.\n",
" -r, --required <FILE> Path to a file with a list of required tests to\n"
" check if all were executed.\n",
"\n",
"Note: mandatory arguments to long arguments are mandatory for short\n",
"arguments as well.\n",
NULL
};
line = help_msg;
while (*line != NULL) {
core_msg(fw, "%s", *line);
line++;
}
}
static void set_arg_defaults(struct unit_fw_args *args)
{
args->driver_load_path = DEFAULT_ARG_DRIVER_LOAD_PATH;
args->unit_load_path = DEFAULT_ARG_UNIT_LOAD_PATH;
args->thread_count = 1;
args->test_lvl = TEST_PLAN_MAX;
args->required_tests_file = NULL;
}
/*
* Parse command line arguments.
*/
int core_parse_args(struct unit_fw *fw, int argc, char **argv)
{
int c, opt_index;
struct unit_fw_args *args;
args = malloc(sizeof(*args));
if (!args)
return -1;
memset(args, 0, sizeof(*args));
set_arg_defaults(args);
args->binary_name = strrchr(argv[0], '/');
if (args->binary_name == NULL) {
/* no slash, so use the whole name */
args->binary_name = argv[0];
} else {
/* move past the slash */
args->binary_name++;
}
fw->args = args;
while (1) {
c = getopt_long(argc, argv,
core_opts_str, core_opts, &opt_index);
if (c == -1)
break;
switch (c) {
case 'h':
args->help = true;
break;
case 'v':
args->verbose_lvl += 1;
break;
case 'q':
args->verbose_lvl = 0;
break;
case 'C':
args->no_color = true;
break;
case 'n':
args->nvtest = true;
break;
case 'L':
args->unit_load_path = optarg;
break;
case 'K':
args->driver_load_path = optarg;
break;
case 'j':
args->thread_count = strtol(optarg, NULL, 10);
if (args->thread_count == 0) {
core_err(fw, "Invalid number of threads\n");
return -1;
}
break;
case 'Q':
args->is_qnx = true;
break;
case 't':
args->test_lvl = strtol(optarg, NULL, 10);
if (args->test_lvl > TEST_PLAN_MAX) {
core_err(fw, "Invalid test plan level\n");
return -1;
}
break;
case 'd':
args->debug = true;
break;
case 'r':
args->required_tests_file = optarg;
break;
case '?':
args->help = true;
return -1;
default:
core_err(fw, "bug?!\n");
return -1;
}
}
/*
* If there is an extra argument after the command-line options, then
* it is a unit test name that need to be specifically run.
*/
if (optind < argc) {
args->unit_to_run = argv[optind];
}
return 0;
}

275
userspace/src/exec.c Normal file
View File

@@ -0,0 +1,275 @@
/*
* Copyright (c) 2018-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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <time.h>
#include <unit/io.h>
#include <unit/core.h>
#include <unit/args.h>
#include <unit/unit.h>
#include <unit/module.h>
#include <unit/results.h>
#include <nvgpu/posix/probe.h>
#include <nvgpu/posix/posix-fault-injection.h>
/*
* Sempaphore to limit the number of threads
*/
sem_t unit_thread_semaphore;
/*
* C11 thread local storage, used to access test context when a signal is
* received (ex: SIGSEGV) in a thread.
*/
_Thread_local struct unit_module *thread_local_module;
_Thread_local struct unit_module_test *thread_local_test;
/*
* Execute a module and all its subtests. This function builds a gk20a for the
* test to use by executing nvgpu_posix_probe() and nvgpu_posix_cleanup();
*/
static void *core_exec_module(void *module_param)
{
unsigned int i;
struct unit_module *module = (struct unit_module *) module_param;
struct gk20a *g;
struct nvgpu_posix_fault_inj_container *fi_container = NULL;
clock_t begin;
double time_spent;
/*
* Setup fault injection first so that faults can be injected in
* nvgpu_posix_probe().
*/
fi_container = (struct nvgpu_posix_fault_inj_container *)
malloc(sizeof(struct nvgpu_posix_fault_inj_container));
if (fi_container == NULL) {
core_msg_color(module->fw, C_RED,
" failed to allocate fault inj: Module %s\n",
module->name);
goto thread_exit;
}
memset(fi_container, 0, sizeof(struct nvgpu_posix_fault_inj_container));
module->fw->nvgpu.nvgpu_posix_init_fault_injection(fi_container);
if (module->fw->nvgpu.nvgpu_posix_init_fault_injection_qnx != NULL) {
module->fw->nvgpu.nvgpu_posix_init_fault_injection_qnx(fi_container);
}
g = module->fw->nvgpu.nvgpu_posix_probe();
if (!g) {
core_msg_color(module->fw, C_RED,
" nvgpu_posix_probe failed: Module %s\n",
module->name);
goto thread_exit;
}
core_vbs(module->fw, 1, "Execing module: %s\n", module->name);
begin = clock();
thread_local_module = module;
/*
* Execute each test within the module. No reinit is done between tests.
* Thats up to the module itself to handle. Any setup/teardown between
* unit tests must be handled within the module.
*/
for (i = 0; i < module->nr_tests; i++) {
struct unit_module_test *t = module->tests + i;
int test_status;
thread_local_test = t;
if (t->test_lvl > module->fw->args->test_lvl) {
core_add_test_record(module->fw, module, t, SKIPPED);
core_vbs(module->fw, 1, "Skipping L%d test %s.%s\n",
t->test_lvl, module->name, t->fn_name);
continue;
}
core_msg(module->fw, "Running %s.%s(%s)\n", module->name,
t->fn_name, t->case_name);
test_status = t->fn(module, g, t->args);
if (test_status != UNIT_SUCCESS)
core_msg_color(module->fw, C_RED,
" Unit error! Test %s.%s(%s) FAILED!\n",
module->name, t->fn_name, t->case_name);
core_add_test_record(module->fw, module, t,
test_status == UNIT_SUCCESS ? PASSED : FAILED);
}
module->fw->nvgpu.nvgpu_posix_cleanup(g);
time_spent = (double)(clock() - begin) / CLOCKS_PER_SEC;
core_vbs(module->fw, 1, "Module completed: %s (execution time: %f)\n",
module->name, time_spent);
thread_exit:
if (fi_container != NULL) {
free(fi_container);
}
sem_post(&unit_thread_semaphore);
return NULL;
}
/*
* Go over all the modules and run them one by one.
*/
static void run_modules(struct unit_fw *fw)
{
struct unit_module **modules;
for (modules = fw->modules; *modules != NULL; modules++) {
if (fw->args->thread_count == 1) {
core_exec_module(*modules);
} else {
sem_wait(&unit_thread_semaphore);
pthread_create(&((*modules)->thread), NULL,
core_exec_module, (void *) *modules);
}
}
}
/*
* According to POSIX, "Signals which are generated by some action attributable
* to a particular thread, such as a hardware fault, shall be generated for the
* thread that caused the signal to be generated."
* This custom signal handler will be run from within the thread that caused the
* exception. Thanks to the context being saved in local thread storage, it is
* then trivial to report which test case failed, and then terminate the thread.
*/
static void thread_error_handler(int sig, siginfo_t *siginfo, void *context)
{
core_msg_color(thread_local_module->fw, C_RED,
" Signal %d in Test: %s.%s(%s)!\n", sig,
thread_local_module->name, thread_local_test->fn_name,
thread_local_test->case_name);
core_add_test_record(thread_local_module->fw, thread_local_module,
thread_local_test, FAILED);
sem_post(&unit_thread_semaphore);
/*
* If single threaded, the signal will cause the process to end, so
* exit gracefully while printing test results.
*/
if (thread_local_module->fw->args->thread_count == 1) {
core_print_test_status(thread_local_module->fw);
exit(-1);
}
pthread_exit(NULL);
}
/*
* Install a custom signal handler for several signals to be used when running
* in multithreaded environment.
*/
static int install_thread_error_handler(void)
{
struct sigaction action;
int err;
memset(&action, 0, sizeof(action));
action.sa_sigaction = &thread_error_handler;
action.sa_flags = SA_SIGINFO;
/* SIGSEGV: Invalid memory reference */
err = sigaction(SIGSEGV, &action, NULL);
if (err < 0) {
return err;
}
/* SIGILL: Illegal Instruction */
err = sigaction(SIGILL, &action, NULL);
if (err < 0) {
return err;
}
/* SIGFPE: Floating-point exception */
err = sigaction(SIGFPE, &action, NULL);
if (err < 0) {
return err;
}
/* SIGBUS: Bus error */
err = sigaction(SIGBUS, &action, NULL);
if (err < 0) {
return err;
}
/* SIGSYS: Bad system call */
err = sigaction(SIGSYS, &action, NULL);
if (err < 0) {
return err;
}
return 0;
}
/*
* Execute all modules loaded by the unit test framework.
*/
int core_exec(struct unit_fw *fw)
{
struct unit_module **modules;
int err = 0;
if (args(fw)->nvtest) {
/* special prints for NVTEST fw in GVS */
printf("[start: %s]\n", args(fw)->binary_name);
}
core_vbs(fw, 1, "Using %d threads\n", fw->args->thread_count);
sem_init(&unit_thread_semaphore, 0, fw->args->thread_count);
/*
* By default, use a custom signal hanlder to catch faults such as
* SIGSEGV. This can be disabled with the -d argument to make it
* easier to investigate with a debugger.
*/
if (!fw->args->debug) {
err = install_thread_error_handler();
if (err != 0) {
core_msg_color(fw, C_RED,
" Failed to install signal handler!\n");
return err;
}
}
run_modules(fw);
if (fw->args->thread_count > 1) {
for (modules = fw->modules; *modules != NULL; modules++) {
pthread_join((*modules)->thread, NULL);
}
}
if (args(fw)->nvtest) {
/* special prints for NVTEST fw in GVS */
printf("[%s: %s]\n",
((fw->results->nr_tests - fw->results->nr_passing -
fw->results->nr_skipped) == 0) ?
"pass" : "fail",
args(fw)->binary_name);
}
return 0;
}

110
userspace/src/io.c Normal file
View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2018, 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 <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unit/io.h>
#include <unit/args.h>
#include <unit/core.h>
#include <unit/unit.h>
#define MAX_LOG_LINE_LENGTH 4096
static void __core_print_file(struct unit_fw *fw, FILE *filp,
const char *prefix, const char *msg,
const char *color)
{
const char *reset = C_RESET;
if (color == NULL || args(fw)->no_color) {
color = "";
reset = "";
}
fprintf(filp, "[%s%s%s] %s%s%s",
color, prefix, reset,
color, msg, reset);
fflush(stdout);
}
__attribute__((format (printf, 3, 4)))
void __core_print_stdout(struct unit_fw *fw, const char *color,
const char *fmt, ...)
{
va_list args;
char buf[MAX_LOG_LINE_LENGTH];
va_start(args, fmt);
vsnprintf(buf, MAX_LOG_LINE_LENGTH, fmt, args);
va_end(args);
buf[MAX_LOG_LINE_LENGTH - 1] = 0;
__core_print_file(fw, stdout, "C", buf, color);
}
__attribute__((format (printf, 2, 3)))
void __core_print_stderr(struct unit_fw *fw, const char *fmt, ...)
{
va_list args;
char buf[MAX_LOG_LINE_LENGTH];
va_start(args, fmt);
vsnprintf(buf, MAX_LOG_LINE_LENGTH, fmt, args);
va_end(args);
buf[MAX_LOG_LINE_LENGTH - 1] = 0;
__core_print_file(fw, stdout, "E", buf, C_RED);
}
__attribute__((format (printf, 3, 4)))
void __unit_info_color(struct unit_module *unit, const char *color,
const char *fmt, ...)
{
va_list args;
char buf[MAX_LOG_LINE_LENGTH];
char *msg_start;
int written;
/*
* Default color for module prints is blue. Users can still turn this
* off with '-C'.
*/
if (color == NULL)
color = C_BLUE;
/*
* First prepend the unit name to the print.
*/
written = snprintf(buf, MAX_LOG_LINE_LENGTH, " [%s] ", unit->name);
msg_start = buf + written;
va_start(args, fmt);
vsnprintf(msg_start, MAX_LOG_LINE_LENGTH - written, fmt, args);
va_end(args);
__core_print_file(unit->fw, stdout, "T", buf, color);
}

221
userspace/src/module.c Normal file
View File

@@ -0,0 +1,221 @@
/*
* Copyright (c) 2018-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 <errno.h>
#include <dlfcn.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unit/core.h>
#include <unit/io.h>
#include <unit/args.h>
#include <unit/unit.h>
#include <unit/module.h>
static int check_module(struct unit_fw *fw, struct unit_module *mod)
{
unsigned int i;
/*
* Make sure this module has reasonable data.
*/
if (mod->name == NULL) {
core_err(fw, "Unnamed module!");
return -1;
}
if (mod->tests == NULL || mod->nr_tests == 0) {
core_err(fw, "%s: Empty module!\n", mod->name);
return -1;
}
for (i = 0; i < mod->nr_tests; i++) {
struct unit_module_test *test = &mod->tests[i];
if (test->fn_name == NULL) {
core_err(fw, "%s: Unnamed test\n", mod->name);
return -1;
}
if (test->fn == NULL) {
core_err(fw, "%s: Test %s missing function\n",
mod->name, test->fn_name);
return -1;
}
}
return 0;
}
static struct unit_module *load_one_module(struct unit_fw *fw,
struct dirent *dent)
{
void *lib_handle;
struct unit_module *mod;
core_vbs(fw, 1, "Loading: %s\n", dent->d_name);
if (fw->args->unit_to_run != NULL) {
if (strstr(dent->d_name, fw->args->unit_to_run) == NULL) {
core_vbs(fw, 1, " Skipping unit (not *%s*)\n",
fw->args->unit_to_run);
return NULL;
}
}
lib_handle = dlopen(dent->d_name, RTLD_NOW);
if (lib_handle == NULL) {
core_err(fw, "Failed to load %s: %s\n",
dent->d_name, dlerror());
return NULL;
}
mod = dlsym(lib_handle, "__unit_module__");
if (mod == NULL) {
core_vbs(fw, 1,
"Failed to resolve __unit_module__ in %s: %s\n",
dent->d_name, dlerror());
return NULL;
}
mod->lib_handle = lib_handle;
mod->fw = fw;
core_vbs(fw, 1, " '%s' contains %lu tests\n", mod->name, mod->nr_tests);
return mod;
}
static int cmp_module_prio(const void *__mod_a, const void *__mod_b)
{
const struct unit_module * const *mod_a = __mod_a;
const struct unit_module * const *mod_b = __mod_b;
return (*mod_a)->prio > (*mod_b)->prio;
}
/*
* Sort the module list according to prio.
*/
static void sort_modules_by_prio(struct unit_module **modules, int nr)
{
qsort(modules, (size_t)nr, sizeof(struct unit_module *),
cmp_module_prio);
}
static bool is_shared_obj_filename(char *name)
{
size_t len = strlen(name);
if ((len > 3) && (strcmp(&name[len-3], ".so") == 0)) {
return true;
} else {
return false;
}
}
/*
* Load all the modules we can from the module load path. Return the list of
* loaded module as an array of pointers to modules. The returned list of
* modules is NULL terminated.
*/
struct unit_module **core_load_modules(struct unit_fw *fw)
{
int nr_modules = 0, i;
DIR *load_dir;
struct dirent *ent;
const char *load_path = args(fw)->unit_load_path;
struct unit_module **modules, *mod;
core_vbs(fw, 1, "Loading modules from %s\n", load_path);
/*
* Open and count the number of files in the dir.
*/
load_dir = opendir(load_path);
if (!load_dir) {
core_err(fw, "%s: Unable to open dir (%s)\n",
load_path, strerror(errno));
return NULL;
}
ent = readdir(load_dir);
while (ent != NULL) {
if (is_shared_obj_filename(ent->d_name)) {
nr_modules += 1;
} else {
core_vbs(fw, 1,
"Skipping load of file %s (not a .so)\n",
ent->d_name);
}
ent = readdir(load_dir);
}
/*
* Now allocate necessary space for storing pointers to the modules and
* load the modules. +1 for the last NULL entry.
*/
modules = malloc(sizeof(*modules) * (nr_modules + 1));
if (!modules) {
core_err(fw, "Out of mem! (huh?)\n");
goto err;
}
rewinddir(load_dir);
i = 0;
while ((ent = readdir(load_dir)) != NULL) {
if (strcmp(".", ent->d_name) == 0 ||
strcmp("..", ent->d_name) == 0 ||
!is_shared_obj_filename(ent->d_name))
continue;
mod = load_one_module(fw, ent);
if (mod == NULL)
continue;
if (check_module(fw, mod) != 0)
continue;
modules[i] = mod;
i++;
}
modules[i] = NULL;
sort_modules_by_prio(modules, i);
closedir(load_dir);
return modules;
err:
closedir(load_dir);
return NULL;
}
/* Return the current verbosity level */
int verbose_lvl(struct unit_module *module)
{
return module->fw->args->verbose_lvl;
}

115
userspace/src/nvgpu.c Normal file
View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2018-2020, 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 <dlfcn.h>
#include <stdlib.h>
#include <unit/io.h>
#include <unit/core.h>
/*
* Load driver library. This is done with dlopen() since this will make
* resolving addresses into symbols easier in the future.
*
* Also, this makes people think carefully about what functions to call in
* nvgpu-drv-igpu from the unit test FW. The interaction should really be limited
* and doing explicit name lookups is a good way to prevent too much coupling.
*/
int core_load_nvgpu(struct unit_fw *fw)
{
const char *msg;
int flag = RTLD_NOW;
const char *load_path = args(fw)->driver_load_path;
if (fw->args->is_qnx == 0) {
/*
* Specify a GLOBAL binding so that subsequently loaded
* unit tests see the nvgpu-drv-igpu library. They will of course
* need it (and will access it directly). I.e they will link
* against nvgpu-drv-igpu and this should satisfy that linkage.
*/
flag |= RTLD_GLOBAL;
}
/* TODO: WAR: remove this dependency of libnvgpu-drv-igpu.so for qnx unit
* test, refer NVGPU-1935 for more detail */
fw->nvgpu_so = dlopen(load_path, flag);
if (fw->nvgpu_so == NULL) {
msg = dlerror();
core_err(fw, "Failed to load %s: %s\n", load_path, msg);
return -1;
}
/*
* We directly check the value of the returned symbol for these
* functions against NULL because if it is NULL then something is
* terribly wrong.
*/
fw->nvgpu.nvgpu_posix_probe = dlsym(fw->nvgpu_so,
"nvgpu_posix_probe");
if (fw->nvgpu.nvgpu_posix_probe == NULL) {
msg = dlerror();
core_err(fw, "Failed to resolve nvgpu_posix_probe: %s\n", msg);
return -1;
}
fw->nvgpu.nvgpu_posix_cleanup = dlsym(fw->nvgpu_so,
"nvgpu_posix_cleanup");
if (fw->nvgpu.nvgpu_posix_cleanup == NULL) {
msg = dlerror();
core_err(fw, "Failed to resolve nvgpu_posix_cleanup: %s\n", msg);
return -1;
}
fw->nvgpu.nvgpu_posix_init_fault_injection = dlsym(fw->nvgpu_so,
"nvgpu_posix_init_fault_injection");
if (fw->nvgpu.nvgpu_posix_init_fault_injection == NULL) {
msg = dlerror();
core_err(fw, "Failed to resolve nvgpu_posix_init_fault_injection: %s\n",
msg);
return -1;
}
if (fw->args->is_qnx != 0) {
fw->nvgpu_qnx_ut = dlopen("libnvgpu_ut_igpu.so", flag);
if (fw->nvgpu_qnx_ut == NULL) {
msg = dlerror();
core_err(fw, "Failed to load nvgpu_ut_igpu: %s\n", msg);
return -1;
}
fw->nvgpu.nvgpu_posix_init_fault_injection_qnx =
dlsym(fw->nvgpu_qnx_ut,
"nvgpu_posix_init_fault_injection");
if (fw->nvgpu.nvgpu_posix_init_fault_injection_qnx == NULL) {
msg = dlerror();
core_err(fw, "Failed to resolve nvgpu_posix_init_fault_injection: %s\n",
msg);
return -1;
}
} else {
fw->nvgpu.nvgpu_posix_init_fault_injection_qnx = NULL;
}
return 0;
}

View File

@@ -0,0 +1,333 @@
/*
* Copyright (c) 2020, 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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unit/io.h>
#include <unit/core.h>
#include <unit/unit.h>
#include <unit/required_tests.h>
#include <unit/results.h>
#include <nvgpu/list.h>
struct test_list_node {
char *test_subtest_name;
long test_level;
struct nvgpu_list_node list;
};
struct unit_list_node {
char *unit_name;
struct nvgpu_list_node test_list_head;
struct nvgpu_list_node list;
};
static struct nvgpu_list_node unit_list_head;
static inline struct test_list_node *
test_list_node_from_list(struct nvgpu_list_node *node)
{
return (struct test_list_node *)
((uintptr_t)node - offsetof(struct test_list_node, list));
};
static inline struct unit_list_node *
unit_list_node_from_list(struct nvgpu_list_node *node)
{
return (struct unit_list_node *)
((uintptr_t)node - offsetof(struct unit_list_node, list));
};
/*
* Add a unit in the list of units. The node will hold the name of the unit and
* another list of tests.
*/
static struct unit_list_node *add_unit(struct nvgpu_list_node *head,
const char *unit_name)
{
struct unit_list_node *node = malloc(sizeof(struct unit_list_node));
if (node == NULL) {
return NULL;
}
node->unit_name = malloc(strlen(unit_name)+1);
if (node->unit_name == NULL) {
free(node);
return NULL;
}
strcpy(node->unit_name, unit_name);
nvgpu_init_list_node(&node->test_list_head);
nvgpu_list_add(&node->list, head);
return node;
}
/*
* From a unit list node, add a test_subtest string along with its test level.
*/
static struct test_list_node *add_test_subtest_level(
struct unit_list_node *unit, const char *test_subtest_name, long level)
{
struct test_list_node *node = malloc(sizeof(struct test_list_node));
if (node == NULL) {
return NULL;
}
node->test_level = level;
node->test_subtest_name = malloc(strlen(test_subtest_name)+1);
if (node->test_subtest_name == NULL) {
free(node);
return NULL;
}
strcpy(node->test_subtest_name, test_subtest_name);
nvgpu_list_add(&node->list, &unit->test_list_head);
return node;
}
/*
* Simple helper to sanitize the input and remove un-needed characters.
*/
static void sanitize(char *dest, const char *src)
{
char *dest_start = dest;
if (dest == NULL || src == NULL)
return;
/* Trim leading spaces */
while (*src == ' ' || *src == '\t')
src++;
/* Copy the rest of the string */
while (*src != '\0') {
if (*src == '#') {
/* Rest of the line is a comment, discard it */
break;
}
*dest++ = *src++;
}
*dest = '\0';
/* Backtrack to remove line returns and trim spaces at the end */
while (dest_start <= dest) {
if ((*dest == '\0') || (*dest == '\r') || (*dest == '\n')
|| (*dest == ' ')) {
*dest = '\0';
} else {
return;
}
dest--;
}
}
/* Parse a sting looking for a long number, along with error handling. */
static bool parse_long(const char *str, long *val)
{
char *tmp;
bool result = true;
errno = 0;
*val = strtol(str, &tmp, 10);
if (tmp == str || *tmp != '\0' ||
((*val == LONG_MIN || *val == LONG_MAX) && errno == ERANGE)) {
result = false;
}
return result;
}
/*
* Load the INI file that contains the list of required tests. This manages a
* list of units, and each unit node has a list of test cases.
*/
int parse_req_file(struct unit_fw *fw, const char *ini_file)
{
char rawline[MAX_LINE_SIZE];
char line[MAX_LINE_SIZE];
char tmp[MAX_LINE_SIZE];
char *open_bracket, *close_bracket, *equal;
long value, len;
struct unit_list_node *current_unit = NULL;
FILE *file = fopen(ini_file, "r");
if (file == NULL) {
perror("Error reading INI file: ");
return -1;
}
nvgpu_init_list_node(&unit_list_head);
while (fgets(rawline, sizeof(rawline), file)) {
line[0] = '\0';
tmp[0] = '\0';
sanitize(line, rawline);
if (strlen(line) == 0) {
continue;
}
open_bracket = strchr(line, '[');
close_bracket = strchr(line, ']');
equal = strchr(line, '=');
if (equal != NULL) {
/* This is a key/value pair */
if (current_unit == NULL) {
continue;
}
strncpy(tmp, line, (equal-line));
tmp[equal-line] = '\0';
if (!parse_long(equal+1, &value)) {
core_err(fw, "Conversion error:\n%s\n",
rawline);
return -1;
}
if (add_test_subtest_level(current_unit, tmp, value)
== NULL) {
return -ENOMEM;
}
} else if ((open_bracket != NULL) && (close_bracket != NULL)) {
/* This is a section */
if (open_bracket++ > close_bracket) {
continue;
}
len = close_bracket-open_bracket;
strncpy(tmp, open_bracket, len);
tmp[len] = '\0';
current_unit = add_unit(&unit_list_head, tmp);
if (current_unit == NULL) {
return -ENOMEM;
}
} else {
/* Unknown line or syntax error */
core_err(fw, "Syntax error parsing:\n%s\n", rawline);
return -1;
}
}
fclose(file);
return 0;
}
/*
* Helper that takes a test function name and a subcase name, combines them to
* be in the same format as the INI file, and compare the result to a given
* string. Returns true if it matches.
*/
static bool cmp_test_name(const char *exec_fn_name, const char* exec_case_name,
const char *ini_test_subtest_name)
{
char exec_test_subtest_name[MAX_LINE_SIZE];
exec_test_subtest_name[0] = '\0';
strcat(exec_test_subtest_name, exec_fn_name);
strcat(exec_test_subtest_name, ".");
strcat(exec_test_subtest_name, exec_case_name);
if (strcmp(ini_test_subtest_name, exec_test_subtest_name) == 0) {
return true;
}
return false;
}
/*
* Check the tests that were executed and compare them to the list of tests
* from the INI file. This only check passing tests; if there are failed tests,
* the failure will be handled somewhere else, and skipped tests are handled by
* the test level in the INI file.
* Returns the number of required tests that were not executed.
*/
int check_executed_tests(struct unit_fw *fw)
{
struct unit_test_record *rec;
struct unit_list_node *unit_node, *found_unit_node = NULL;
struct test_list_node *test_node, *found_test_node = NULL;
struct unit_test_list *passing_tests = &fw->results->passing;
int missing_count = 0;
for_record_in_test_list(passing_tests, rec) {
found_unit_node = NULL;
found_test_node = NULL;
/* Search for the unit name */
nvgpu_list_for_each_entry(unit_node, &unit_list_head,
unit_list_node, list) {
if (strcmp(unit_node->unit_name, rec->mod->name) != 0) {
continue;
}
found_unit_node = unit_node;
/* Search for the fn_name.case_name */
nvgpu_list_for_each_entry(test_node,
&unit_node->test_list_head,
test_list_node, list) {
if (cmp_test_name(rec->test->fn_name,
rec->test->case_name,
test_node->test_subtest_name)) {
found_test_node = test_node;
break;
}
}
break;
}
if (found_test_node == NULL) {
/* Test should be added to the INI file */
core_err(fw,
"Test not in required tests: [%s] %s.%s\n",
rec->mod->name, rec->test->fn_name,
rec->test->case_name);
} else {
/* Found it, remove it from the list. */
nvgpu_list_del(&found_test_node->list);
if (nvgpu_list_empty(
&found_unit_node->test_list_head)) {
/* No more tests, remove the unit itself */
nvgpu_list_del(&found_unit_node->list);
}
}
}
/*
* Now that all the executed tests were removed from the list, any test
* that is leftover is a required test that was not executed.
*/
nvgpu_list_for_each_entry(unit_node, &unit_list_head, unit_list_node,
list) {
nvgpu_list_for_each_entry(test_node, &unit_node->test_list_head,
test_list_node, list) {
if (test_node->test_level <= fw->args->test_lvl) {
core_err(fw, "Required test not run: [%s] %s\n",
unit_node->unit_name,
test_node->test_subtest_name);
missing_count++;
}
}
}
return missing_count;
}

201
userspace/src/results.c Normal file
View File

@@ -0,0 +1,201 @@
/*
* 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 <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <stdio.h>
#include <unit/io.h>
#include <unit/core.h>
#include <unit/unit.h>
#include <unit/results.h>
/*
* Mutex to ensure core_add_test_record() is thread safe.
*/
pthread_mutex_t mutex_results = PTHREAD_MUTEX_INITIALIZER;
static int __init_results(struct unit_fw *fw)
{
struct unit_results *results;
if (fw->results != NULL)
return 0;
results = malloc(sizeof(*results));
if (results == NULL)
return -1;
memset(results, 0, sizeof(*results));
fw->results = results;
return 0;
}
static void add_record(struct unit_test_list *list,
struct unit_test_record *tr)
{
/*
* First entry.
*/
if (list->head == NULL) {
list->head = tr;
list->last = tr;
return;
}
/*
* Add to the end of the list and update the pointer to the last entry
* in the list. This gives us O(1) add time.
*/
list->last->next = tr;
list->last = tr;
}
int core_add_test_record(struct unit_fw *fw,
struct unit_module *mod,
struct unit_module_test *test,
enum result_enum result)
{
struct unit_test_record *tr;
int err = 0;
pthread_mutex_lock(&mutex_results);
/*
* Does nothing if results are already inited.
*/
if (__init_results(fw) != 0) {
err = -1;
goto done;
}
tr = malloc(sizeof(*tr));
if (tr == NULL) {
err = -1;
goto done;
}
tr->mod = mod;
tr->test = test;
tr->status = (result == PASSED);
tr->next = NULL;
fw->results->nr_tests += 1;
switch (result) {
case PASSED:
add_record(&fw->results->passing, tr);
fw->results->nr_passing += 1;
break;
case FAILED:
add_record(&fw->results->failing, tr);
break;
case SKIPPED:
add_record(&fw->results->skipped, tr);
fw->results->nr_skipped += 1;
break;
}
done:
pthread_mutex_unlock(&mutex_results);
return err;
}
static void dump_test_record(FILE *logfile, struct unit_test_record *rec,
bool status, bool first)
{
first ? fprintf(logfile, "\t{") : fprintf(logfile, ",\n\t{");
fprintf(logfile, "\"unit\": \"%s\", ", rec->mod->name);
fprintf(logfile, "\"test\": \"%s\", ", rec->test->fn_name);
fprintf(logfile, "\"case\": \"%s\", ", rec->test->case_name);
fprintf(logfile, "\"status\": %s, ", status ? "true":"false");
fprintf(logfile, "\"uid\": \"%s\", ", rec->test->jama.unique_id);
fprintf(logfile, "\"vc\": \"%s\", ",
rec->test->jama.verification_criteria);
fprintf(logfile, "\"req\": \"%s\", ", rec->test->jama.requirement);
fprintf(logfile, "\"test_level\": %d", rec->test->test_lvl);
fprintf(logfile, "}");
}
static void dump_test_log(struct unit_fw *fw, struct unit_test_list
*passing_tests, struct unit_test_list *failing_tests)
{
struct unit_test_record *rec;
int count = 0;
FILE *logfile = fopen("results.json", "w+");
fprintf(logfile, "[\n");
for_record_in_test_list(passing_tests, rec) {
dump_test_record(logfile, rec, true, count == 0);
count++;
}
for_record_in_test_list(failing_tests, rec) {
dump_test_record(logfile, rec, false, count == 0);
count++;
}
fprintf(logfile, "\n]\n");
fclose(logfile);
}
void core_print_test_status(struct unit_fw *fw)
{
struct unit_test_list *failing_tests = &fw->results->failing;
struct unit_test_list *skipped_tests = &fw->results->skipped;
struct unit_test_record *rec;
/*
* Print stats for the tests.
*/
core_msg(fw, "\n");
core_msg(fw, "Test results:\n");
core_msg(fw, "-------------\n");
core_msg(fw, "\n");
core_msg(fw, " Skipped: %d\n", fw->results->nr_skipped);
core_msg(fw, " Passing: %d\n", fw->results->nr_passing);
core_msg(fw, " Failing: %d\n",
fw->results->nr_tests - fw->results->nr_passing -
fw->results->nr_skipped);
core_msg(fw, " Total: %d\n", fw->results->nr_tests);
core_msg(fw, "\n");
core_msg(fw, "Skipped tests:\n");
core_msg(fw, "\n");
for_record_in_test_list(skipped_tests, rec) {
core_msg(fw, " %s.%s(%s)\n",
rec->mod->name,
rec->test->fn_name,
rec->test->case_name);
}
core_msg(fw, "\n");
core_msg(fw, "Failing tests:\n");
core_msg(fw, "\n");
for_record_in_test_list(failing_tests, rec) {
core_msg(fw, " %s.%s(%s)\n",
rec->mod->name,
rec->test->fn_name,
rec->test->case_name);
}
dump_test_log(fw, &fw->results->passing, &fw->results->failing);
}

113
userspace/src/unit_main.c Normal file
View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2018-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.
*/
/**
* NvGpu unit testing framework!
*/
#include <stdlib.h>
#include <string.h>
#include <unit/io.h>
#include <unit/core.h>
#include <unit/args.h>
#include <unit/module.h>
#include <unit/results.h>
#include <unit/required_tests.h>
int main(int argc, char **argv)
{
struct unit_fw *fw;
int ret;
fw = malloc(sizeof(*fw));
if (!fw)
return 1;
memset(fw, 0, sizeof(*fw));
ret = core_parse_args(fw, argc, argv);
if (ret) {
core_err(fw, "Unable to parse args.\n");
core_err(fw, "Exiting!\n");
return 1;
}
core_vbs(fw, 1, "Welcome to the nvgpu unit testing framework!\n");
if (args(fw)->help) {
core_print_help(fw);
return 1;
}
ret = core_load_nvgpu(fw);
if (ret != 0)
return ret;
fw->modules = core_load_modules(fw);
if (fw->modules == NULL)
return -1;
ret = core_exec(fw);
if (ret != 0)
return ret;
if (fw->results == NULL) {
core_msg(fw, "No tests were run!\n");
return -1;
}
core_print_test_status(fw);
if ((fw->results->nr_tests - fw->results->nr_passing -
fw->results->nr_skipped) != 0) {
/* Some tests failed */
return -1;
}
if (fw->args->unit_to_run != NULL) {
/*
* Just in case (especially when running in automation), return
* a failure if only executed a subset of the units
*/
return -2;
}
if (fw->args->required_tests_file != NULL) {
ret = parse_req_file(fw, fw->args->required_tests_file);
if (ret != 0) {
core_err(fw,
"Failed to load the required tests file.\n");
return -1;
}
ret = check_executed_tests(fw);
if (ret != 0) {
core_err(fw,
"Found %d required tests that were not run!\n",
ret);
return -1;
}
}
return 0;
}

235
userspace/testlist.py Executable file
View File

@@ -0,0 +1,235 @@
#!/usr/bin/python2
#
# Copyright (c) 2019-2021, 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.
import argparse, os
import json, md5
RESULTS_FILE = 'results.json'
HTML_FILE = 'results.html'
REQ_FILE = 'required_tests.json'
HTML_HEAD='''
<html>
<head>
<style>
body {
font-family: Verdana;
}
.res-table {
border: solid 1px #DDD;
border-collapse: collapse;
border-spacing: 0; font-size: 12px;
}
.res-table thead th {
background-color: #76B900;
border: solid 1px #DDD;
padding: 10px;
text-align: left;
}
.res-table tbody td {
border: solid 1px #DDD;
padding: 10px;
}
h2 {
color: #76B900;
text-transfer: uppercase;
}
a[href*="jamacloud.com/"] {
background:url(https://nvidia.jamacloud.com/img/favicon-16x16.png) no-repeat left center;
padding-left:19px;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$("#uid-toggle").click(function() {
$(".invalid-uid").parent().toggle();
return false;
});
});
</script>
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<h2>Results</h2>
'''
#Build a dictionary-based structure to easily access tests by unit and name.
def build_results_dict(results):
test_dict = {}
#Iterate through the results and group them by unit name
for result in results:
unit = result['unit']
test = result['case']
if unit not in test_dict:
test_dict[unit] = {}
if test in test_dict[unit]:
print("WARNING: %s - %s already exists." % (unit, test))
test_dict[unit][test] = result
return test_dict
def regen():
output_list = []
if not os.path.exists(RESULTS_FILE):
print("File 'results.json' not found. Run unit.sh first.")
exit(1)
with open(RESULTS_FILE) as infile:
results = json.loads(infile.read())
test_dict = build_results_dict(results)
#Generate the output by alphabetical order
test_count = 0
for unit, tests in sorted(test_dict.items(), key=lambda kv: kv[0], reverse=False):
for test in sorted(tests.items()):
entry = {"unit": unit, "test": test[1]['test'], 'case': test[1]['case'], 'test_level': test[1]['test_level']}
if test[1]['uid'] != "":
entry['uid'] = test[1]['uid']
entry['vc'] = test[1]['vc']
entry['req'] = test[1]['req']
output_list.append(entry)
test_count += 1
with open(REQ_FILE, "w+") as outfile:
json_text = json.dumps(output_list, indent=4).replace(" \n", "\n")
outfile.write(json_text+"\n")
print("Generated updated version of \"%s\" based on tests in \"%s\"." % (REQ_FILE, RESULTS_FILE))
print("Required tests: %d" % test_count)
def get_RGB(s):
hash = md5.md5(s).hexdigest()
rgb = '#' + hash[0:2] + hash[2:4] + hash[4:6]
return rgb
def format_html_test(unit, test, status, error, uid, req, vc):
if status:
status = "green"
else:
status = "red"
color = get_RGB(unit)
ret = "<tr><td bgcolor='%s'></td><td>%s</td><td>%s</td><td bgcolor=%s>%s</td>" % (color, unit, test, status, error)
jamalink = ""
class_name = "invalid-uid"
if uid != "":
jamalink = "https://nvidia.jamacloud.com/perspective.req#/items/%s?projectId=20460" % uid
jamalink = "<a class=\"jama\" href=\"%s\" target=\"_blank\">%s</a>" % (jamalink, uid)
class_name = "valid-uid"
ret += "<td class='uid %s'>%s</td>\n" % (class_name, jamalink)
ret += "<td>%s</td><td>%s</td>\n" % (req, vc)
ret += "</tr>\n"
return ret
def check(test_level, html = False):
#Check that tests in results.json cover required_tests.json
with open(RESULTS_FILE) as results_file:
results = json.loads(results_file.read())
with open(REQ_FILE) as req_file:
reqd_tests = json.loads(req_file.read())
test_dict = build_results_dict(results)
req_dict = build_results_dict(reqd_tests)
errors = 0
test_count = 0
log = ""
html = ""
#First make sure that all required tests were run and PASSED.
for reqd_test in reqd_tests:
unit = reqd_test['unit']
test = reqd_test['case']
error = ""
status = False
skipped = False
if unit not in test_dict:
error = ("ERROR: Required unit %s is not in test results.\n" % unit)
log += error
errors += 1
elif test not in test_dict[unit]:
if req_dict[unit][test]['test_level'] <= test_level:
error = ("ERROR: Required test %s - %s is not in test results.\n" % (unit, test))
log += error
errors += 1
else:
skipped = True
elif test_dict[unit][test]['status'] is False:
log += ("ERROR: Required test %s - %s FAILED.\n" % (unit, test))
error = "FAILED"
errors += 1
else:
status = True
error = "PASS"
if not skipped:
html += format_html_test(unit, test, status, error, reqd_test.get('uid', ''), reqd_test.get('req', ''), reqd_test.get('vc', ''))
test_count += 1
#As a helpful hint, check to see if any tests were run without being in the list of required
#tests. This should not cause a failure, but just a warning for the developer to add the
#test to the required list.
for result in results:
unit = result['unit']
test = result['case']
if unit not in req_dict:
log += ("WARNING: Tested unit %s is not in required tests. Use testlist.py --regen\n" % unit)
elif test not in req_dict[unit]:
log +=("WARNING: Test %s - %s is not in required tests. Use testlist.py --regen\n" % (unit, test))
if log != "":
print(log)
if html:
with open(HTML_FILE, "w+") as outfile:
outfile.write(HTML_HEAD)
outfile.write("<table class=\"res-table\" width=\"100%\">\n")
outfile.write("<thead><tr><th width=20 colspan=2>Unit</th><th>Test</th><th>Result</th>\n")
outfile.write("<th>JAMA UID <a href=\"#\" id=\"uid-toggle\">[Toggle]</a></th><th>Requirement</th><th>VC</th></tr></thead>\n")
outfile.write("<tbody>\n")
outfile.write(html)
outfile.write("</tbody></table>\n")
outfile.write("</body></html>")
print("Wrote %s" % HTML_FILE)
if errors > 0:
return 1
else:
print("PASS: All %d tests found in result log." % test_count)
return 0
def html(test_level):
return check(test_level, html = True)
parser = argparse.ArgumentParser()
parser.add_argument("--regen", help="Regenerate list of expected test cases.", action="store_true")
parser.add_argument("--check", help="Make sure all expected test cases were run.", action="store_true")
parser.add_argument("--test-level", "-t", help="Test level used for checking results. Default=0", type=int, default=0)
parser.add_argument("--html", help="Perform --check and export results in an HTML file.", action="store_true")
args = parser.parse_args()
if args.regen:
regen()
exit(0)
if args.check:
exit(check(args.test_level))
if args.html:
exit(html(args.test_level))
else:
parser.print_help()

118
userspace/unit.sh Executable file
View File

@@ -0,0 +1,118 @@
#!/bin/bash
#
# 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.
#
# Execute the unit test. Args to this script are passed on to the unit test
# core. This just serves to set the LD_LIBRARY_PATH environment variable such
# that unit tests are found and nvgpu-drv-igpu is found.
#
options=$(getopt -o t: --long test-level: -- "$@")
this_script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )"
pushd $this_script_dir
FIRMWARES=("/gpu-firmware-private/t19x/gr/net/safety/NETD_img.bin"
"/gpu-firmware-private/t19x/gr/net/safety/fecs_sig.bin"
"/gpu-firmware-private/t19x/gr/net/safety/gpccs_sig.bin"
"/gpu-firmware-private/t19x/gr/fecs/safety/fecs.bin"
"/gpu-firmware-private/t19x/gr/gpccs/safety/gpccs.bin"
"/gpu-firmware-private/t19x/gr/pmu/safety/acr_ucode_prod.bin"
"/gpu-firmware-private/t19x/gr/pmu/safety/acr_ucode_dbg.bin")
FIRMWARE_TARGET_PATH="/lib/firmware/gv11b/"
CUR_DIR=`pwd`
DEST_DIR=${CUR_DIR}/firmware/gv11b/
mkdir -p ${DEST_DIR}
if [ -f nvgpu_unit ]; then
if [ -d ${FIRMWARE_TARGET_PATH} ]
then
cp -rf ${FIRMWARE_TARGET_PATH}/* ${DEST_DIR}
else
echo "${FIRMWARE_TARGET_PATH} doesn't exist\n"
exit 1
fi
# if the executable is in the current directory, we are running on
# target, so use that dir structure
LD_LIBRARY_PATH=".:units/igpu"
cores=$(cat /proc/cpuinfo |grep processor |wc -l)
# Ignore number of cores for now; it seems that the parallel unit
# tests are just too buggy and that they really don't save much
# actual computing time.
NVGPU_UNIT="./nvgpu_unit --nvtest --unit-load-path units/igpu --no-color \
--num-threads 1"
else
# running on host
if [ "x$TEGRA_TOP" == "x" ]
then
echo "\$TEGRA_TOP must be set!"
exit 1
fi
for i in "${FIRMWARES[@]}"
do
if [ -f ${TEGRA_TOP}/${i} ]
then
cp -f ${TEGRA_TOP}/${i} ${DEST_DIR}
else
echo "firmware file \"${TEGRA_TOP}/${i}\" doesn't exist\n"
exit 1
fi
done
LD_LIBRARY_PATH="build:build/units"
# On host, must run single-threaded to avoid high VAs
NVGPU_UNIT="./build/nvgpu_unit --num-threads 1"
fi
export LD_LIBRARY_PATH
echo "$ $NVGPU_UNIT $*"
$NVGPU_UNIT $*
rc=$?
if [ $rc -eq "0" ]; then
#get the test level, if passed into this script
eval set -- $options
while true; do
case "$1" in
-t|--test-level)
shift;
testlevelparam="-t $1"
;;
--)
shift;
break;
;;
esac
shift
done
fi
rm -rf ${CUR_DIR}/firmware
popd
exit $rc

View File

@@ -0,0 +1,45 @@
# -*- mode: makefile -*-
#
# Copyright (c) 2018, 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.
#
# Inlcude this in unit test makefiles to get useful rules.
#
LOCAL_HEADERS = (shell ls *.h)
.PHONY: all clean
all: lib$(MODULE).so
@true
#
# Inherits from the top level makefile. As such the unit test make files cannot
# be invoked by themselves.
%.o : %.c # $(LOCAL_HEADERS)
$(CC) --coverage $(CFLAGS) -c -o $@ $<
lib$(MODULE).so: $(OBJS)
$(CC) -shared -o $@ $(OBJS) $(LIB_PATHS) -lnvgpu_unit -lgcov
@mkdir -p $(UNIT_OUT)/
@cp $@ $(UNIT_OUT)/
clean:
rm -rf *.o *.so

View File

@@ -0,0 +1,37 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2018-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
#
###############################################################################
ifdef NV_INTERFACE_FLAG_SHARED_LIBRARY_SECTION
NV_INTERFACE_NAME := $(NVGPU_UNIT_NAME)
NV_INTERFACE_EXPORTS := $(NV_SOURCE)/kernel/nvgpu/userspace/units/nvgpu_unit.common
NV_INTERFACE_PUBLIC_INCLUDES := . include
endif
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,110 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2018-2020, 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
#
###############################################################################
ifdef NV_COMPONENT_FLAG_SHARED_LIBRARY_SECTION
include $(NV_BUILD_START_COMPONENT)
NV_COMPONENT_NAME := $(NVGPU_UNIT_NAME)
NV_COMPONENT_OWN_INTERFACE_DIR := .
#For the simple case, if there's only one source file with the same name as the
#component, the unit test can let this makefile add it.
#But if the unit test has > 1 file, they can define NVGPU_UNIT_SRCS
ifdef NVGPU_UNIT_SRCS
NV_COMPONENT_SOURCES := \
$(NVGPU_UNIT_SRCS)
else
NV_COMPONENT_SOURCES := \
$(NVGPU_UNIT_NAME).c
endif
ifdef NVGPU_UNIT_INCLUDES
NV_COMPONENT_INCLUDES := \
$(NVGPU_UNIT_INCLUDES)
endif
NV_COMPONENT_INCLUDES += \
$(NV_SOURCE)/kernel/nvgpu/userspace/units/mock-iospace/include \
$(NV_SOURCE)/kernel/nvgpu/drivers/gpu/nvgpu/include \
$(NV_SOURCE)/kernel/nvgpu/drivers/gpu/nvgpu \
$(NV_SOURCE)/kernel/nvgpu-next/drivers/gpu/nvgpu/include \
$(NV_SOURCE)/kernel/nvgpu-next/drivers/gpu/nvgpu
ifdef NVGPU_CFLAGS
NV_COMPONENT_CFLAGS := \
$(NVGPU_CFLAGS)
else
NV_COMPONENT_CFLAGS += -D__NVGPU_POSIX__
endif
NV_COMPONENT_CFLAGS += -D__NVGPU_UNIT_TEST__
NV_COMPONENT_CFLAGS += -DNVGPU_UNITTEST_FAULT_INJECTION_ENABLEMENT
ifneq ($(NV_BUILD_CONFIGURATION_OS_IS_QNX),1)
NVGPU_FORCE_SAFETY_PROFILE := 1
NVGPU_FORCE_DEBUG_PROFILE := 1
endif
-include $(NV_SOURCE)/kernel/nvgpu/drivers/gpu/nvgpu/Makefile.shared.configs
NV_COMPONENT_CFLAGS += $(NVGPU_COMMON_CFLAGS)
NV_COMPONENT_NEEDED_INTERFACE_DIRS := \
$(NV_SOURCE)/kernel/nvgpu/userspace
ifdef NVGPU_UNIT_SHARED_LIBRARIES
NV_COMPONENT_SYSTEM_SHARED_LIBRARIES += $(NVGPU_UNIT_SHARED_LIBRARIES)
endif
ifdef NVGPU_UNIT_INTERFACE_DIRS
NV_COMPONENT_NEEDED_INTERFACE_DIRS += $(NVGPU_UNIT_INTERFACE_DIRS)
endif
ifdef CONFIG_NVGPU_DGPU
NV_COMPONENT_NEEDED_INTERFACE_DIRS += $(NV_SOURCE)/kernel/nvgpu/libs/dgpu
else
NV_COMPONENT_NEEDED_INTERFACE_DIRS += $(NV_SOURCE)/kernel/nvgpu/libs/igpu
endif
ifdef NVGPU_SYSTEMIMAGE_DIR
NV_COMPONENT_SYSTEMIMAGE_DIR := $(NVGPU_SYSTEMIMAGE_DIR)
else
ifdef CONFIG_NVGPU_DGPU
NV_COMPONENT_SYSTEMIMAGE_DIR := $(NV_SYSTEMIMAGE_TEST_EXECUTABLE_DIR)/nvgpu_unit/units/dgpu
else
NV_COMPONENT_SYSTEMIMAGE_DIR := $(NV_SYSTEMIMAGE_TEST_EXECUTABLE_DIR)/nvgpu_unit/units/igpu
endif
endif
systemimage:: $(NV_COMPONENT_SYSTEMIMAGE_DIR)
$(NV_COMPONENT_SYSTEMIMAGE_DIR) : $(NV_SYSTEMIMAGE_TEST_EXECUTABLE_DIR)
$(MKDIR_P) $@
include $(NV_BUILD_SHARED_LIBRARY)
endif
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,38 @@
# Copyright (c) 2019-2020, 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-acr.o
MODULE = nvgpu-acr
LIB_PATHS += -lfalcon_utf \
-lnvgpu-gr
include ../Makefile.units
lib$(MODULE).so: falcon_utf \
nvgpu-gr
falcon_utf:
$(MAKE) -C ../falcon
nvgpu-gr:
$(MAKE) -C ../gr

View File

@@ -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-acr
include $(NV_COMPONENT_DIR)/../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,40 @@
################################## tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019-2020, 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-acr
NVGPU_UNIT_SRCS=nvgpu-acr.c
NVGPU_UNIT_INTERFACE_DIRS := \
$(NV_COMPONENT_DIR)/../falcon \
$(NV_COMPONENT_DIR)/../gr
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,188 @@
/*
* Copyright (c) 2019-2020, 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.
*/
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-acr
* @{
*
* Software Unit Test Specification for acr
*/
/**
* Test specification for: test_acr_init
*
* Description: The test_acr_init shall test the initialization of
* the ACR unit
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_acr_init
*
* Input: None
*
* Steps:
* - Initialize the falcon test environment
* - Initialize the ECC support
* - Initialize the PMU
* - Inject memory allocation fault to test the fail scenario 1
* - Give incorrect chip version to test the fail scenario 2
* - Give correct chip id and set the register to enable debug mode
* to have branch coverage
* - Give correct chip id and test the pass scenario
* - Uninitialize the PMU support
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_acr_init(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_acr_prepare_ucode_blob
*
* Description: The test_acr_prepare_ucode_blob shall test the blob creation of
* the ACR unit
*
* Test Type: Feature, Error guessing
*
* Targets: g->acr->prepare_ucode_blob
*
* Input: None
* Steps:
* - Initialize the test env and register space needed for the test
* - Prepare HW and SW setup needed for the test
* - Inject memmory allocation failure to test fai scneario for
* g->acr->prepare_ucode_blob(g)
* - Give incorrect chip version number to test second fail scenario
* - NVGPU_SEC_SECUREGPCCS flag is set to false to get the branch coverage
* - NVGPU_SEC_SECUREGPCCS flag is set to true to test the pass scenario
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_acr_prepare_ucode_blob(struct unit_module *m, struct gk20a *g,
void *__args);
/**
* Test specification for: test_acr_is_lsf_lazy_bootstrap
*
* Description: The test_acr_is_lsf_lazy_bootstrap shall test the
* lazy bootstrap of the ACR unit
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_acr_is_lsf_lazy_bootstrap
*
* Input: None
*
* Steps:
* - Initialize the test env and register space needed for the test
* - Prepare HW and SW setup needed for the test
* - Pass scenario: lsf lazy bootstrap the ACR for following falcon ids:
* FALCON_ID_FECS, FALCON_ID_PMU and FALCON_ID_GPCCS
* - Pass invalid falcon id to fail the function
* - Pass acr as NULL to fail nvgpu_acr_is_lsf_lazy_bootstrap()
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_acr_is_lsf_lazy_bootstrap(struct unit_module *m, struct gk20a *g,
void *__args);
/**
* Test specification for: test_acr_construct_execute
*
* Description: The test_acr_construct_execute shall test the two main tasks of
* the ACR unit:
* 1. Blob construct of LS ucode in non-wpr memory
* 2. ACR HS ucode load & bootstrap
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_acr_construct_execute
*
* Input: None
*
* Steps:
* - Initialize the test env and register space needed for the test
* - Prepare HW and SW setup needed for the test
* - Set the falcon_falcon_cpuctl_halt_intr_m bit for the
* register falcon_falcon_cpuctl_r
* - Inject memory allocation failure in g->acr->prepare_ucode_blob so that
* acr_construct_execute() fails
* - Cover fail scenario when "is_falcon_supported"
* is set to false. This fails nvgpu_acr_bootstrap_hs_acr()
* - Set is_falcon_supported to true to test the pass scenario
* - Pass g->acr as NULL to create fail scenario.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_acr_construct_execute(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for: test_acr_bootstrap_hs_acr
*
* Description: The test_acr_bootstrap_hs_acr shall test the ACR HS ucode load
* & bootstrap functionality of the ACR unit
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_acr_bootstrap_hs_acr, nvgpu_pmu_report_bar0_pri_err_status,
* gops_pmu.validate_mem_integrity, gv11b_pmu_validate_mem_integrity,
* gops_pmu.is_debug_mode_enabled, gv11b_pmu_is_debug_mode_en,
* gops_acr.pmu_clear_bar0_host_err_status,
* gv11b_clear_pmu_bar0_host_err_status, gops_pmu.bar0_error_status,
* gv11b_pmu_bar0_error_status
*
* Input: None
*
* Steps:
* - Initialize the test env and register space needed for the test
* - Prepare HW and SW setup needed for the test
* - Call prepare_ucode_blob without setting halt bit so that
* timeout error occurs in acr bootstrap
* - Set the falcon_falcon_cpuctl_halt_intr_m bit for the
* register falcon_falcon_cpuctl_r
* - Prepare the ucode blob
* - Set mailbox_error = true to create read failure for mailbox 0 register
* - Inject memory allocation failure to fail nvgpu_acr_bootstrap_hs_acr()
* - Call nvgpu_acr_bootstrap_hs_acr() twice to cover recovery branch.
* - Cover branch for fail scenario when "is_falcon_supported" is set to false
* - Cover branch by setting g->acr->acr.acr_engine_bus_err_status = NULL
* - Cover branch when "acr_engine_bus_err_status" ops fails
* - Cover all scenarios to test gv11b_pmu_bar0_error_status() by wriring
* different values to pwr_pmu_bar0_error_status_r() register
* - Set g->acr->acr.acr_validate_mem_integrity = NULL to cover branch
* - Set g->acr->acr.report_acr_engine_bus_err_status = NULL to cover branch
* - Set ->ops.pmu.is_debug_mode_enabled = true to get branch coverage
* - Cover branch by setting p->is_silicon = true
* - Pass g->acr = NULL to fail nvgpu_acr_bootstrap_hs_acr()
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_acr_bootstrap_hs_acr(struct unit_module *m,
struct gk20a *g, void *args);

View File

@@ -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-bus.o
MODULE = bus
include ../Makefile.units

View File

@@ -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=bus
include $(NV_COMPONENT_DIR)/../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -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=bus
NVGPU_UNIT_SRCS=nvgpu-bus.c
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,357 @@
/*
* Copyright (c) 2019-2021, 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <unit/core.h>
#include <nvgpu/io.h>
#include <nvgpu/cic.h>
#include <os/posix/os_posix.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include <nvgpu/gk20a.h>
#include <hal/mc/mc_gp10b.h>
#include <hal/ptimer/ptimer_gk20a.h>
#include <hal/bus/bus_gk20a.h>
#include <hal/bus/bus_gm20b.h>
#include <hal/bus/bus_gp10b.h>
#include <hal/bus/bus_gv11b.h>
#include <hal/cic/cic_gv11b.h>
#include <nvgpu/hw/gv11b/hw_mc_gv11b.h>
#include <nvgpu/hw/gv11b/hw_bus_gv11b.h>
#include "nvgpu-bus.h"
#define assert(cond) unit_assert(cond, goto done)
u32 read_bind_status_reg = 0U;
/*
* 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)
{
/* BAR_1 bind status is indicated by value of
* bus_bind_status_bar1_pending = empty(0x0U) and
* bus_bind_status_bar1_outstanding = false(0x0U).
*
* Similarly, for BAR_2 bind status, we check
* bus_bind_status_bar2_pending = empty (0x0U)
* and bus_bind_status_bar2_outstanding = false(0x0U).
*
* During bar1/2_bind HAL, the bus_bind_status_r() register is polled to
* check if its value changed as described above.
* To get complete branch coverage in bus.bar1/2_bind(), after
* "read_bind_status_reg" read attempts, the value of
* bus_bind_status_r() is read as pending field = empty and
* outstanding field = false.
* This maps to bind_status = done after "read_cmd_reg" polling
* attempts.
*/
if (access->addr == bus_bind_status_r()) {
if (read_bind_status_reg == 3U) {
access->value =
(bus_bind_status_bar1_pending_empty_f() |
bus_bind_status_bar1_outstanding_false_f() |
bus_bind_status_bar2_pending_empty_f() |
bus_bind_status_bar2_outstanding_false_f());
read_bind_status_reg = nvgpu_safe_add_u32(
read_bind_status_reg, 1U);
return;
}
read_bind_status_reg = nvgpu_safe_add_u32(read_bind_status_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_PBUS register space */
#define NV_PBUS_START 0x00001000U
#define NV_PBUS_SIZE 0x00000FFFU
/* NV_PRIV_GPC register space */
#define NV_PMC_START 0x00000000U
#define NV_PMC_SIZE 0x00000FFFU
/* NV_PTIMER register space */
#define NV_PTIMER_START 0x00009000U
#define NV_PTIMER_SIZE 0x00000FFFU
int test_bus_setup(struct unit_module *m, struct gk20a *g, void *args)
{
/* Init HAL */
g->ops.bus.init_hw = gk20a_bus_init_hw;
g->ops.bus.isr = gk20a_bus_isr;
g->ops.bus.bar1_bind = gm20b_bus_bar1_bind;
g->ops.bus.bar2_bind = gp10b_bus_bar2_bind;
g->ops.bus.configure_debug_bus = gv11b_bus_configure_debug_bus;
g->ops.mc.intr_nonstall_unit_config =
mc_gp10b_intr_nonstall_unit_config;
g->ops.ptimer.isr = gk20a_ptimer_isr;
g->ops.cic.init = gv11b_cic_init;
g->ops.cic.report_err = nvgpu_cic_report_err_safety_services;
/* Map register space NV_PRIV_MASTER */
if (nvgpu_posix_io_add_reg_space(g, NV_PBUS_START, NV_PBUS_SIZE) != 0) {
unit_err(m, "%s: failed to register space: NV_PBUS\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;
}
/* Map register space NV_PTIMER */
if (nvgpu_posix_io_add_reg_space(g, NV_PTIMER_START,
NV_PTIMER_SIZE) != 0) {
unit_err(m, "%s: failed to register space: NV_PTIMER\n",
__func__);
return UNIT_FAIL;
}
(void)nvgpu_posix_register_io(g, &test_reg_callbacks);
if (nvgpu_cic_init_common(g) != 0) {
unit_err(m, "%s: Failed to initialize CIC\n",
__func__);
return UNIT_FAIL;
}
return UNIT_SUCCESS;
}
int test_bus_free_reg_space(struct unit_module *m, struct gk20a *g, void *args)
{
/* Free register space */
nvgpu_posix_io_delete_reg_space(g, NV_PBUS_START);
nvgpu_posix_io_delete_reg_space(g, NV_PMC_START);
nvgpu_posix_io_delete_reg_space(g, NV_PTIMER_START);
return UNIT_SUCCESS;
}
int test_init_hw(struct unit_module *m, struct gk20a *g, void *args)
{
int ret = UNIT_FAIL;
struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g);
nvgpu_writel(g, bus_debug_sel_0_r(), 0xFU);
nvgpu_writel(g, bus_debug_sel_1_r(), 0xFU);
nvgpu_writel(g, bus_debug_sel_2_r(), 0xFU);
nvgpu_writel(g, bus_debug_sel_3_r(), 0xFU);
p->is_fpga = false;
p->is_silicon = false;
g->ops.bus.configure_debug_bus = NULL;
ret = g->ops.bus.init_hw(g);
assert(nvgpu_readl(g, bus_intr_en_1_r()) == 0U);
assert(nvgpu_readl(g, bus_debug_sel_0_r()) == 0xFU);
assert(nvgpu_readl(g, bus_debug_sel_1_r()) == 0xFU);
assert(nvgpu_readl(g, bus_debug_sel_2_r()) == 0xFU);
assert(nvgpu_readl(g, bus_debug_sel_3_r()) == 0xFU);
p->is_silicon = true;
g->ops.bus.configure_debug_bus = gv11b_bus_configure_debug_bus;
ret = g->ops.bus.init_hw(g);
assert(nvgpu_readl(g, bus_intr_en_1_r()) == 0xEU);
assert(nvgpu_readl(g, bus_debug_sel_0_r()) == 0x0U);
assert(nvgpu_readl(g, bus_debug_sel_1_r()) == 0x0U);
assert(nvgpu_readl(g, bus_debug_sel_2_r()) == 0x0U);
assert(nvgpu_readl(g, bus_debug_sel_3_r()) == 0x0U);
p->is_fpga = true;
p->is_silicon = false;
ret = g->ops.bus.init_hw(g);
assert(nvgpu_readl(g, bus_intr_en_1_r()) == 0xEU);
ret = UNIT_SUCCESS;
done:
return ret;
}
int test_bar_bind(struct unit_module *m, struct gk20a *g, void *args)
{
int ret = UNIT_FAIL;
struct nvgpu_mem bar_inst = {0};
struct nvgpu_posix_fault_inj *timer_fi =
nvgpu_timers_get_fault_injection();
/* Initialize cpu_va to a known value */
bar_inst.cpu_va = (void *) 0xCE418000U;
bar_inst.aperture = APERTURE_VIDMEM;
/* Set bus_bind_status_r to 0xF that is both bar1 and bar2 status
* pending and outstanding.
*/
nvgpu_posix_io_writel_reg_space(g, bus_bind_status_r(), 0xFU);
/* Call bus.bar1_bind() HAL */
ret = g->ops.bus.bar1_bind(g, &bar_inst);
/* Make sure HAL returns success as bind_status is marked as done in
* third polling attempt.
*/
if (ret != 0U) {
unit_err(m, "bus.bar1_bind HAL failed.\n");
ret = UNIT_FAIL;
}
/* Send error if bar1_block register is not set as expected:
* Bit 27:0 - 4k aligned block pointer = bar_inst.cpu_va >> 12 = 0xCE418
* Bit 29:28- Target = Vidmem = (00)b
* Bit 30 - Debug CYA = (0)b
* Bit 31 - Mode = virtual = (1)b
*/
assert(nvgpu_readl(g, bus_bar1_block_r()) == 0x800CE418U);
/* Call bus.bar1_bind HAL again and except ret != 0 as the bind status
* will remain outstanding during this call.
*/
nvgpu_posix_io_writel_reg_space(g, bus_bind_status_r(), 0x5U);
ret = g->ops.bus.bar1_bind(g, &bar_inst);
/* The HAL should return error this time as timeout is expected to
* expire.
*/
if (ret != -EINVAL) {
unit_err(m, "bus.bar1_bind did not fail as expected.\n");
ret = UNIT_FAIL;
}
/* Call bus.bar1_bind HAL again and except ret != 0 as the bind status
* will remain pending during this call.
*/
nvgpu_posix_io_writel_reg_space(g, bus_bind_status_r(), 0xAU);
ret = g->ops.bus.bar1_bind(g, &bar_inst);
/* The HAL should return error this time as timeout is expected to
* expire.
*/
if (ret != -EINVAL) {
unit_err(m, "bus.bar1_bind did not fail as expected.\n");
ret = UNIT_FAIL;
}
/* Enable fault injection for the timer init call for branch coverage */
nvgpu_posix_enable_fault_injection(timer_fi, true, 0);
ret = g->ops.bus.bar1_bind(g, &bar_inst);
if (ret == 0U) {
unit_err(m, "Error injection for timeout init failed.\n");
ret = UNIT_FAIL;
}
nvgpu_posix_enable_fault_injection(timer_fi, false, 0);
bar_inst.cpu_va = (void *) 0x2670C000U;
read_bind_status_reg = 0U;
ret = g->ops.bus.bar2_bind(g, &bar_inst);
if (ret != 0U) {
unit_err(m, "bus.bar2_bind HAL failed.\n");
ret = UNIT_FAIL;
}
assert(nvgpu_readl(g, bus_bar2_block_r()) == 0x8002670CU);
/* Call bus.bar2_bind HAL again and except ret != 0 as the bind status
* will remain outstanding during this call.
*/
nvgpu_posix_io_writel_reg_space(g, bus_bind_status_r(), 0x5U);
ret = g->ops.bus.bar2_bind(g, &bar_inst);
if (ret != -EINVAL) {
unit_err(m, "bus.bar2_bind did not fail as expected.\n");
ret = UNIT_FAIL;
}
/* Call bus.bar2_bind HAL again and except ret != 0 as the bind status
* will remain pending during this call.
*/
nvgpu_posix_io_writel_reg_space(g, bus_bind_status_r(), 0xAU);
ret = g->ops.bus.bar2_bind(g, &bar_inst);
if (ret != -EINVAL) {
unit_err(m, "bus.bar2_bind did not fail as expected.\n");
ret = UNIT_FAIL;
}
/* Enable fault injection for the timer init call for branch coverage */
nvgpu_posix_enable_fault_injection(timer_fi, true, 0);
ret = g->ops.bus.bar2_bind(g, &bar_inst);
if (ret == 0U) {
unit_err(m, "Error injection for timeout init failed.\n");
ret = UNIT_FAIL;
}
nvgpu_posix_enable_fault_injection(timer_fi, false, 0);
ret = UNIT_SUCCESS;
done:
return ret;
}
int test_bus_isr(struct unit_module *m, struct gk20a *g, void *args)
{
int ret = UNIT_SUCCESS;
nvgpu_writel(g, bus_intr_0_r(), bus_intr_0_pri_squash_m());
g->ops.bus.isr(g);
nvgpu_writel(g, bus_intr_0_r(), bus_intr_0_pri_fecserr_m());
g->ops.bus.isr(g);
nvgpu_writel(g, bus_intr_0_r(), bus_intr_0_pri_timeout_m());
g->ops.bus.isr(g);
nvgpu_writel(g, bus_intr_0_r(), 0x10U);
g->ops.bus.isr(g);
return ret;
}
struct unit_module_test bus_tests[] = {
UNIT_TEST(bus_setup, test_bus_setup, NULL, 0),
UNIT_TEST(bus_init_hw, test_init_hw, NULL, 0),
UNIT_TEST(bus_bar_bind, test_bar_bind, NULL, 0),
UNIT_TEST(bus_isr, test_bus_isr, NULL, 0),
UNIT_TEST(bus_free_reg_space, test_bus_free_reg_space, NULL, 0),
};
UNIT_MODULE(bus, bus_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,178 @@
/*
* Copyright (c) 2019-2020, 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_BUS_H
#define UNIT_NVGPU_BUS_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-bus
* @{
*
* Software Unit Test Specification for nvgpu.common.bus
*/
/**
* Test specification for: test_bus_setup
*
* Description: Setup prerequisites for tests.
*
* Test Type: Other (setup)
*
* Input: None
*
* Steps:
* - Initialize common.bus and few other necessary HAL function pointers.
* - Map the register space for NV_PBUS, NV_PMC and NV_PTIMER.
* - Register read/write callback functions.
*
* Output:
* - UNIT_FAIL if encounters an error creating reg space
* - UNIT_SUCCESS otherwise
*/
int test_bus_setup(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_bus_free_reg_space
*
* Description: Free resources from test_bus_setup()
*
* Test Type: Other (cleanup)
*
* Input: test_bus_setup() has been executed.
*
* Steps:
* - Free up NV_PBUS, NV_PMC and NV_PTIMER register space.
*
* Output:
* - UNIT_SUCCESS
*/
int test_bus_free_reg_space(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_init_hw
*
* Description: Verify the bus.init_hw and bus.configure_debug_bus HAL.
*
* Test Type: Feature
*
* Targets: gops_bus.init_hw, gk20a_bus_init_hw,
* gops_bus.configure_debug_bus, gv11b_bus_configure_debug_bus
*
* Input: test_bus_setup() has been executed.
*
* Steps:
* - Initialize the Debug bus related registers to non-zero value.
* - Set is_silicon and is_fpga flag to false to get branch coverage.
* - Set configure_debug_bus HAL to NULL for branch coverage.
* - Call init_hw() HAL.
* - Read back the interrupt enable register and check if it is equal to 0.
* - Read back the debug bus registers to make sure they are NOT zeroed out.
*
* - For more branch coverage, set is_silicon flag to true.
* - Initialize the configure_debug_bus HAL to gv11b_bus_configure_debug_bus.
* - Call init_hw() HAL.
* - Read back the interrupt enable register and check if it is equal to 0xEU.
* - PRI_SQUASH = Bit 1:1
* - PRI_FECSERR = Bit 2:2
* - PRI_TIMEOUT = Bit 3:3
* - Read back the debug bus registers to make sure they are zeroed out.
*
* - For better branch coverage, set is_silicon to false and is_fpga to true
* - Call init_hw() HAL.
* - Read back the interrupt enable register and check if it is equal to 0xEU.
*
* Output:
* - UNIT_FAIL if above HAL fails to enable interrupts.
* - UNIT_SUCCESS otherwise.
*/
int test_init_hw(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_bar_bind
*
* Description: Verify the bus.bar1_bind and bus.bar2_bind HAL.
*
* Test Type: Feature, Error injection
*
* Targets: gops_bus.bar1_bind, gm20b_bus_bar1_bind,
* gops_bus.bar2_bind, gp10b_bus_bar2_bind
*
* Input: test_bus_setup() has been executed.
*
* Steps:
* - Initialize cpu_va to a known value (say 0xCE418000U).
* - Set bus_bind_status_r to 0xF that is both bar1 and bar2 status
* pending and outstanding.
* - Call bus.bar1_bind() HAL.
* - Make sure HAL returns success as bind_status is marked as done in
* third polling attempt.
* - Send error if bar1_block register is not set as expected:
* - Bit 27:0 - 4k aligned block pointer = bar_inst.cpu_va >> 12 = 0xCE418
* - Bit 29:28- Target = (11)b
* - Bit 30 - Debug CYA = (0)b
* - Bit 31 - Mode = virtual = (1)b
* - Set bus_bind_status_r to 0x5U that is both bar1 and bar2 status
* is set as outstanding.
* - Call bus.bar1_bind HAL again and except ret != 0 as the bind status
* will remain outstanding during this call.
* - Set bus_bind_status_r to 0xAU that is both bar1 and bar2 status
* is set as pending.
* - Call bus.bar1_bind HAL again and except ret != 0 as the bind status
* will remain pending during this call.
* - The HAL should return error this time as timeout is expected to expire.
* - Enable fault injection for the timer init call for branch coverage.
* - Repeat the above steps for BAR2 but with different cpu_va = 0x2670C000U.
*
* Output:
* - UNIT_FAIL if above HAL fails to bind BAR1/2
* - UNIT_SUCCESS otherwise.
*/
int test_bar_bind(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_bus_isr
*
* Description: Verify the bus.isr HAL.
*
* Test Type: Feature, Error injection
*
* Targets: gops_bus.isr, gk20a_bus_isr
*
* Input: test_bus_setup() has been executed.
*
* Steps:
* - Initialize interrupt register bus_intr_0_r() to 0x2(pri_squash)
* - Call isr HAL.
* - Initialize interrupt register bus_intr_0_r() to 0x4(pri_fecserr)
* - Call isr HAL.
* - Initialize interrupt register bus_intr_0_r() to 0x8(pri_timeout)
* - Call isr HAL.
* - Initialize interrupt register bus_intr_0_r() to 0x10(fb_req_timeout)
* - Call isr HAL.
*
* Output:
* - UNIT_SUCCESS.
*/
int test_bus_isr(struct unit_module *m, struct gk20a *g, void *args);
#endif /* UNIT_NVGPU_BUS_H */

View File

@@ -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-ce.o
MODULE = ce
include ../Makefile.units

View File

@@ -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=ce
include $(NV_COMPONENT_DIR)/../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -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=ce
NVGPU_UNIT_SRCS=nvgpu-ce.c
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,388 @@
/*
* Copyright (c) 2019-2021, 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/device.h>
#include <nvgpu/ce.h>
#include <nvgpu/cic.h>
#include <hal/ce/ce_gp10b.h>
#include <hal/ce/ce_gv11b.h>
#include <hal/cic/cic_gv11b.h>
#include <nvgpu/hw/gv11b/hw_ce_gv11b.h>
#include "nvgpu-ce.h"
#define assert(cond) unit_assert(cond, goto fail)
#define CE_ADDR_SPACE_START 0x00104000
#define CE_ADDR_SPACE_SIZE 0xfff
#define NUM_INST 2
/*
* Mock I/O
*/
/*
* Write callback. Forward the write access to the mock IO framework.
*/
static u32 intr_status_written[NUM_INST];
static void writel_access_reg_fn(struct gk20a *g,
struct nvgpu_reg_access *access)
{
if (access->addr == ce_intr_status_r(0)) {
intr_status_written[0] |= access->value;
nvgpu_posix_io_writel_reg_space(g, access->addr,
nvgpu_posix_io_readl_reg_space(g, access->addr) &
~access->value);
} else if (access->addr == ce_intr_status_r(1)) {
intr_status_written[1] |= access->value;
nvgpu_posix_io_writel_reg_space(g, access->addr,
nvgpu_posix_io_readl_reg_space(g, access->addr) &
~access->value);
} else {
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,
};
/*
* Replacement functions that can be assigned to function pointers
*/
static void mock_void_return(struct gk20a *g)
{
/* noop */
}
static int mock_mc_enable_units(struct gk20a *g, u32 units, bool enable)
{
return 0;
}
static int mock_mc_enable_dev(struct gk20a *g, const struct nvgpu_device *dev,
bool enable)
{
return 0;
}
static void mock_intr_unit_config(struct gk20a *g, u32 unit, bool enable)
{
/* noop */
}
int test_ce_setup_env(struct unit_module *m,
struct gk20a *g, void *args)
{
/* Create mc register space */
if (nvgpu_posix_io_add_reg_space(g, CE_ADDR_SPACE_START,
CE_ADDR_SPACE_SIZE) != 0) {
unit_err(m, "%s: failed to create register space\n",
__func__);
return UNIT_FAIL;
}
(void)nvgpu_posix_register_io(g, &test_reg_callbacks);
nvgpu_mutex_init(&g->cg_pg_lock);
g->blcg_enabled = false;
nvgpu_spinlock_init(&g->mc.intr_lock);
g->ops.cic.init = gv11b_cic_init;
g->ops.cic.report_err = nvgpu_cic_report_err_safety_services;
if (nvgpu_cic_init_common(g) != 0) {
unit_err(m, "%s: failed to initialize CIC\n",
__func__);
return UNIT_FAIL;
}
return UNIT_SUCCESS;
}
int test_ce_free_env(struct unit_module *m, struct gk20a *g, void *args)
{
/* Free mc register space */
nvgpu_posix_io_delete_reg_space(g, CE_ADDR_SPACE_START);
return UNIT_SUCCESS;
}
int test_ce_init_support(struct unit_module *m, struct gk20a *g, void *args)
{
int ret = UNIT_SUCCESS;
int err;
nvgpu_device_init(g);
g->fifo.num_engines = 0;
g->ops.ce.set_pce2lce_mapping = mock_void_return;
g->ops.ce.init_prod_values = mock_void_return;
g->ops.mc.enable_units = mock_mc_enable_units;
g->ops.mc.enable_dev = mock_mc_enable_dev;
g->ops.mc.intr_nonstall_unit_config = mock_intr_unit_config;
g->ops.mc.intr_stall_unit_config = mock_intr_unit_config;
/* test default case where all HALs are defined */
err = nvgpu_ce_init_support(g);
if (err != 0) {
ret = UNIT_FAIL;
unit_err(m, "failed to init ce\n");
goto done;
}
/* test with this HAL set to NULL for branch coverage */
g->ops.ce.set_pce2lce_mapping = NULL;
err = nvgpu_ce_init_support(g);
if (err != 0) {
ret = UNIT_FAIL;
unit_err(m, "failed to init ce\n");
goto done;
}
/* test with this HAL set to NULL for branch coverage */
g->ops.ce.init_prod_values = NULL;
err = nvgpu_ce_init_support(g);
if (err != 0) {
ret = UNIT_FAIL;
unit_err(m, "failed to init ce\n");
goto done;
}
done:
return ret;
}
int test_ce_stall_isr(struct unit_module *m, struct gk20a *g, void *args)
{
int ret = UNIT_SUCCESS;
int inst_id;
u32 intr_val;
g->ops.ce.isr_stall = gv11b_ce_stall_isr;
for (inst_id = 0; inst_id < NUM_INST; inst_id++) {
intr_status_written[inst_id] = 0;
intr_val = 0x1f; /* all intr sources */
nvgpu_posix_io_writel_reg_space(g, ce_intr_status_r(inst_id),
intr_val);
g->ops.ce.isr_stall(g, inst_id, 0);
if (intr_status_written[inst_id] != (intr_val &
~ce_intr_status_nonblockpipe_pending_f())) {
ret = UNIT_FAIL;
unit_err(m, "intr_status not cleared, only 0x%08x\n",
intr_status_written[inst_id]);
goto done;
}
intr_status_written[inst_id] = 0;
intr_val = 0x0;
nvgpu_posix_io_writel_reg_space(g, ce_intr_status_r(inst_id),
intr_val);
g->ops.ce.isr_stall(g, inst_id, 0);
if (intr_status_written[inst_id] != intr_val) {
ret = UNIT_FAIL;
unit_err(m, "intr_status not cleared, only 0x%08x\n",
intr_status_written[inst_id]);
goto done;
}
}
done:
return ret;
}
int test_ce_nonstall_isr(struct unit_module *m, struct gk20a *g, void *args)
{
int ret = UNIT_SUCCESS;
int inst_id;
u32 intr_val;
u32 val;
g->ops.ce.isr_nonstall = gp10b_ce_nonstall_isr;
for (inst_id = 0; inst_id < NUM_INST; inst_id++) {
intr_status_written[inst_id] = 0;
intr_val = 0x1f; /* all intr sources */
nvgpu_posix_io_writel_reg_space(g, ce_intr_status_r(inst_id),
intr_val);
val = g->ops.ce.isr_nonstall(g, inst_id, 0);
if (val != (NVGPU_CIC_NONSTALL_OPS_WAKEUP_SEMAPHORE |
NVGPU_CIC_NONSTALL_OPS_POST_EVENTS)) {
ret = UNIT_FAIL;
unit_err(m, "incorrect ops returned 0x%08x\n", val);
goto done;
}
if (intr_status_written[inst_id] !=
ce_intr_status_nonblockpipe_pending_f()) {
ret = UNIT_FAIL;
unit_err(m, "intr_status not cleared properly, only 0x%08x\n",
intr_status_written[inst_id]);
goto done;
}
intr_status_written[inst_id] = 0;
intr_val = 0x0;
nvgpu_posix_io_writel_reg_space(g, ce_intr_status_r(inst_id),
intr_val);
val = g->ops.ce.isr_nonstall(g, inst_id, 0);
if (val != 0U) {
ret = UNIT_FAIL;
unit_err(m, "incorrect ops returned 0x%08x\n", val);
goto done;
}
if (intr_status_written[inst_id] != intr_val) {
ret = UNIT_FAIL;
unit_err(m, "intr_status not cleared, only 0x%08x\n",
intr_status_written[inst_id]);
goto done;
}
}
done:
return ret;
}
static u32 mock_get_num_lce(struct gk20a *g)
{
return NUM_INST;
}
int test_mthd_buffer_fault_in_bar2_fault(struct unit_module *m, struct gk20a *g,
void *args)
{
int ret = UNIT_SUCCESS;
int inst_id;
u32 intr_val;
g->ops.ce.mthd_buffer_fault_in_bar2_fault =
gv11b_ce_mthd_buffer_fault_in_bar2_fault;
g->ops.top.get_num_lce = mock_get_num_lce;
intr_val = 0x1f; /* all intr sources */
for (inst_id = 0; inst_id < NUM_INST; inst_id++) {
intr_status_written[inst_id] = 0;
nvgpu_posix_io_writel_reg_space(g, ce_intr_status_r(inst_id),
intr_val);
}
g->ops.ce.mthd_buffer_fault_in_bar2_fault(g);
for (inst_id = 0; inst_id < NUM_INST; inst_id++) {
if (intr_status_written[inst_id] !=
ce_intr_status_mthd_buffer_fault_pending_f()) {
ret = UNIT_FAIL;
unit_err(m, "intr_status not cleared properly, only 0x%08x\n",
intr_status_written[inst_id]);
goto done;
}
}
intr_val = 0x0;
for (inst_id = 0; inst_id < NUM_INST; inst_id++) {
intr_status_written[inst_id] = 0;
nvgpu_posix_io_writel_reg_space(g, ce_intr_status_r(inst_id),
intr_val);
}
g->ops.ce.mthd_buffer_fault_in_bar2_fault(g);
for (inst_id = 0; inst_id < NUM_INST; inst_id++) {
if (intr_status_written[inst_id] != 0) {
ret = UNIT_FAIL;
unit_err(m, "intr_status not cleared properly, only 0x%08x\n",
intr_status_written[inst_id]);
goto done;
}
}
done:
return ret;
}
int test_get_num_pce(struct unit_module *m, struct gk20a *g, void *args)
{
u32 pce_map_val; /* 16 bit bitmap */
u32 val;
g->ops.ce.get_num_pce = gv11b_ce_get_num_pce;
for (pce_map_val = 0; pce_map_val <= U16_MAX; pce_map_val++) {
nvgpu_posix_io_writel_reg_space(g, ce_pce_map_r(),
pce_map_val);
val = g->ops.ce.get_num_pce(g);
if (val != hweight32(pce_map_val)) {
unit_return_fail(m, "incorrect value %u\n", val);
}
}
return UNIT_SUCCESS;
}
int test_init_prod_values(struct unit_module *m, struct gk20a *g, void *args)
{
int inst_id;
u32 val;
g->ops.ce.init_prod_values = gv11b_ce_init_prod_values;
for (inst_id = 0; inst_id < NUM_INST; inst_id++) {
/* init reg to known state */
nvgpu_posix_io_writel_reg_space(g, ce_lce_opt_r(inst_id), 0U);
}
g->ops.ce.init_prod_values(g);
for (inst_id = 0; inst_id < NUM_INST; inst_id++) {
/* verify written correctly */
val = nvgpu_posix_io_readl_reg_space(g, ce_lce_opt_r(inst_id));
if (val != ce_lce_opt_force_barriers_npl__prod_f()) {
unit_return_fail(m, "value incorrect 0x%08x\n", val);
}
}
return UNIT_SUCCESS;
}
struct unit_module_test ce_tests[] = {
UNIT_TEST(ce_setup_env, test_ce_setup_env, NULL, 0),
UNIT_TEST(ce_init_support, test_ce_init_support, NULL, 0),
UNIT_TEST(ce_stall_isr, test_ce_stall_isr, NULL, 0),
UNIT_TEST(ce_nonstall_isr, test_ce_nonstall_isr, NULL, 0),
UNIT_TEST(mthd_buffer_fault_in_bar2_fault, test_mthd_buffer_fault_in_bar2_fault, NULL, 0),
UNIT_TEST(ce_get_num_pce, test_get_num_pce, NULL, 0),
UNIT_TEST(ce_init_prod_values, test_init_prod_values, NULL, 0),
UNIT_TEST(ce_free_env, test_ce_free_env, NULL, 0),
};
UNIT_MODULE(ce, ce_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,212 @@
/*
* Copyright (c) 2019-2021, 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_CE_H
#define UNIT_NVGPU_CE_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-ce
* @{
*
* Software Unit Test Specification for CE
*/
/**
* Test specification for: test_ce_setup_env
*
* Description: Do basic setup before starting other tests.
*
* Test Type: Other (setup)
*
* Input: None
*
* Steps:
* - Initialize reg spaces used by tests.
* - Initialize required data for cg, mc modules.
*
* Output:
* - UNIT_FAIL if encounters an error creating reg space
* - UNIT_SUCCESS otherwise
*/
int test_ce_setup_env(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for: test_ce_free_env
*
* Description: Do basic setup before starting other tests.
*
* Test Type: Other (setup)
*
* Input: None
*
* Steps:
* - Free reg spaces
*
* Output: UNIT_SUCCESS always.
*/
int test_ce_free_env(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_ce_init_support
*
* Description: Validate CE init functionality.
*
* Test Type: Feature
*
* Targets: gops_ce.ce_init_support, nvgpu_ce_init_support
*
* Input: test_ce_setup_env must have been run.
*
* Steps:
* - Setup necessary mock HALs to do nothing and return success as appropriate.
* - Call nvgpu_ce_init_support and verify success is returned.
* - Set set_pce2lce_mapping and init_prod_values HAL function pointers to NULL
* for branch coverage.
* - Call nvgpu_ce_init_support and verify success is returned.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_ce_init_support(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_ce_stall_isr
*
* Description: Validate stall interrupt handler functionality.
*
* Test Type: Feature
*
* Targets: gops_ce.isr_stall, gv11b_ce_stall_isr, gp10b_ce_stall_isr
*
* Input: test_ce_setup_env must have been run.
*
* Steps:
* - Set all CE interrupt sources pending in the interrupt status reg for each
* instance.
* - Call gops_ce.isr_stall.
* - Verify all (and only) the stall interrupts are cleared.
* - Set no CE interrupt sources pending in the interrupt status reg for each
* instance.
* - Call gops_ce.isr_stall.
* - Verify no interrupts are cleared.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_ce_stall_isr(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_ce_nonstall_isr
*
* Description: Validate nonstall interrupt handler functionality.
*
* Test Type: Feature
*
* Targets: gops_ce.isr_nonstall, gp10b_ce_nonstall_isr
*
* Input: test_ce_setup_env must have been run.
*
* Steps:
* - Set all CE interrupt sources pending in the interrupt status reg for each
* instance.
* - Call gops_ce.isr_nonstall.
* - Verify only the nonstall interrupt is cleared and the expected ops are
* returned.
* - Set no CE interrupt sources pending in the interrupt status reg for each
* instance.
* - Call gops_ce.isr_nonstall.
* - Verify no interrupts are cleared and no ops are returned.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_ce_nonstall_isr(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_mthd_buffer_fault_in_bar2_fault
*
* Description: Validate method buffer interrupt functionality.
*
* Test Type: Feature
*
* Targets: gops_ce.mthd_buffer_fault_in_bar2_fault,
* gv11b_ce_mthd_buffer_fault_in_bar2_fault
*
* Input: test_ce_setup_env must have been run.
*
* Steps:
* - Set all CE interrupt sources pending in the interrupt status reg for each
* instance.
* - Call gops_ce.mthd_buffer_fault_in_bar2_fault.
* - Verify only the correct interrupt is cleared.
* - Set no CE interrupt sources pending in the interrupt status reg for each
* instance.
* - Call gops_ce.mthd_buffer_fault_in_bar2_fault.
* - Verify no interrupts are cleared.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_mthd_buffer_fault_in_bar2_fault(struct unit_module *m, struct gk20a *g,
void *args);
/**
* Test specification for: test_get_num_pce
*
* Description: Validate function to get number of PCEs.
*
* Test Type: Feature
*
* Targets: gops_ce.get_num_pce, gv11b_ce_get_num_pce
*
* Input: test_ce_setup_env must have been run.
*
* Steps:
* - Loop through all possible 16 bit values for the PCE Map register.
* - For each value, write to the PCE Map register.
* - Call gops_ce.get_num_pce and verify the correct number of PCEs is
* returned.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_get_num_pce(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_init_prod_values
*
* Description: Validate prod value init functionality.
*
* Test Type: Feature
*
* Targets: gops_ce.init_prod_values, gv11b_ce_init_prod_values
*
* Input: test_ce_setup_env must have been run.
*
* Steps:
* - Clear the LCE Options register for all instances.
* - Call gops_ce.init_prod_values.
* - Verify all instances of the LCE Options register are set properly.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_init_prod_values(struct unit_module *m, struct gk20a *g, void *args);
#endif /* UNIT_NVGPU_CE_H */

View File

@@ -0,0 +1,32 @@
# 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-cg.o
MODULE = nvgpu-cg
LIB_PATHS += -lnvgpu-fifo-common
include ../Makefile.units
lib$(MODULE).so: fifo
fifo:
$(MAKE) -C ../fifo

View File

@@ -0,0 +1,34 @@
################################### 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-cg
include $(NV_COMPONENT_DIR)/../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,39 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019-2020, 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-cg
NVGPU_UNIT_SRCS=nvgpu-cg.c
NVGPU_UNIT_INTERFACE_DIRS := \
$(NV_COMPONENT_DIR)/../fifo
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,710 @@
/*
* Copyright (c) 2019-2020, 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/io.h>
#include <nvgpu/enabled.h>
#include <nvgpu/power_features/cg.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/device.h>
#include <nvgpu/hw/gp10b/hw_fuse_gp10b.h>
#include <nvgpu/hw/gv11b/hw_gr_gv11b.h>
#include <nvgpu/hw/gv11b/hw_therm_gv11b.h>
#include "hal/init/hal_gv11b.h"
#include "hal/power_features/cg/gating_reglist.h"
#include "hal/power_features/cg/gv11b_gating_reglist.h"
#include "../fifo/nvgpu-fifo-common.h"
#include "nvgpu-cg.h"
struct cg_test_data {
u32 cg_type;
void (*load_enable)(struct gk20a *g);
u32 domain_count;
const struct gating_desc *domain_descs[16];
void (*gating_funcs[16])(struct gk20a *g, bool prod);
u32 domain_desc_sizes[16];
};
static struct cg_test_data blcg_fb_ltc = {
.cg_type = NVGPU_GPU_CAN_BLCG,
.load_enable = nvgpu_cg_blcg_fb_ltc_load_enable,
.domain_count = 2,
};
static struct cg_test_data blcg_fifo = {
.cg_type = NVGPU_GPU_CAN_BLCG,
.load_enable = nvgpu_cg_blcg_fifo_load_enable,
.domain_count = 1,
};
static struct cg_test_data blcg_pmu = {
.cg_type = NVGPU_GPU_CAN_BLCG,
.load_enable = nvgpu_cg_blcg_pmu_load_enable,
.domain_count = 1,
};
static struct cg_test_data blcg_ce = {
.cg_type = NVGPU_GPU_CAN_BLCG,
.load_enable = nvgpu_cg_blcg_ce_load_enable,
.domain_count = 1,
};
static struct cg_test_data blcg_gr = {
.cg_type = NVGPU_GPU_CAN_BLCG,
.load_enable = nvgpu_cg_blcg_gr_load_enable,
.domain_count = 1,
};
static struct cg_test_data slcg_fb_ltc = {
.cg_type = NVGPU_GPU_CAN_SLCG,
.load_enable = nvgpu_cg_slcg_fb_ltc_load_enable,
.domain_count = 2,
};
static struct cg_test_data slcg_priring = {
.cg_type = NVGPU_GPU_CAN_SLCG,
.load_enable = nvgpu_cg_slcg_priring_load_enable,
.domain_count = 1,
};
static struct cg_test_data slcg_fifo = {
.cg_type = NVGPU_GPU_CAN_SLCG,
.load_enable = nvgpu_cg_slcg_fifo_load_enable,
.domain_count = 1,
};
struct cg_test_data slcg_pmu = {
.cg_type = NVGPU_GPU_CAN_SLCG,
.load_enable = nvgpu_cg_slcg_pmu_load_enable,
.domain_count = 1,
};
struct cg_test_data slcg_therm = {
.cg_type = NVGPU_GPU_CAN_SLCG,
.load_enable = nvgpu_cg_slcg_therm_load_enable,
.domain_count = 1,
};
struct cg_test_data slcg_ce2 = {
.cg_type = NVGPU_GPU_CAN_SLCG,
.load_enable = nvgpu_cg_slcg_ce2_load_enable,
.domain_count = 1,
};
struct cg_test_data slcg_gr_load_gating_prod = {
.cg_type = NVGPU_GPU_CAN_SLCG,
.load_enable = nvgpu_cg_init_gr_load_gating_prod,
.domain_count = 6,
};
struct cg_test_data blcg_gr_load_gating_prod = {
.cg_type = NVGPU_GPU_CAN_BLCG,
.load_enable = nvgpu_cg_init_gr_load_gating_prod,
.domain_count = 4,
};
#define INIT_BLCG_DOMAIN_TEST_DATA(param) ({\
struct cg_test_data *tmp = &blcg_##param; \
tmp->domain_descs[0] = gv11b_blcg_##param##_get_gating_prod(); \
tmp->gating_funcs[0] = g->ops.cg.blcg_##param##_load_gating_prod; \
tmp->domain_desc_sizes[0] = gv11b_blcg_##param##_gating_prod_size(); \
})
static void init_blcg_fb_ltc_data(struct gk20a *g)
{
blcg_fb_ltc.domain_descs[0] = gv11b_blcg_fb_get_gating_prod();
blcg_fb_ltc.gating_funcs[0] = g->ops.cg.blcg_fb_load_gating_prod;
blcg_fb_ltc.domain_desc_sizes[0] = gv11b_blcg_fb_gating_prod_size();
blcg_fb_ltc.domain_descs[1] = gv11b_blcg_ltc_get_gating_prod();
blcg_fb_ltc.gating_funcs[1] = g->ops.cg.blcg_ltc_load_gating_prod;
blcg_fb_ltc.domain_desc_sizes[1] = gv11b_blcg_ltc_gating_prod_size();
}
static void init_blcg_fifo_data(struct gk20a *g)
{
INIT_BLCG_DOMAIN_TEST_DATA(fifo);
}
static void init_blcg_pmu_data(struct gk20a *g)
{
INIT_BLCG_DOMAIN_TEST_DATA(pmu);
}
static void init_blcg_ce_data(struct gk20a *g)
{
INIT_BLCG_DOMAIN_TEST_DATA(ce);
}
static void init_blcg_gr_data(struct gk20a *g)
{
INIT_BLCG_DOMAIN_TEST_DATA(gr);
}
static void init_blcg_gr_load_gating_data(struct gk20a *g)
{
blcg_gr_load_gating_prod.domain_descs[0] =
gv11b_blcg_bus_get_gating_prod();
blcg_gr_load_gating_prod.gating_funcs[0] =
g->ops.cg.blcg_bus_load_gating_prod;
blcg_gr_load_gating_prod.domain_desc_sizes[0] =
gv11b_blcg_bus_gating_prod_size();
blcg_gr_load_gating_prod.domain_descs[1] =
gv11b_blcg_gr_get_gating_prod();
blcg_gr_load_gating_prod.gating_funcs[1] =
g->ops.cg.blcg_gr_load_gating_prod;
blcg_gr_load_gating_prod.domain_desc_sizes[1] =
gv11b_blcg_gr_gating_prod_size();
blcg_gr_load_gating_prod.domain_descs[2] =
gv11b_blcg_xbar_get_gating_prod();
blcg_gr_load_gating_prod.gating_funcs[2] =
g->ops.cg.blcg_xbar_load_gating_prod;
blcg_gr_load_gating_prod.domain_desc_sizes[2] =
gv11b_blcg_xbar_gating_prod_size();
blcg_gr_load_gating_prod.domain_descs[3] =
gv11b_blcg_hshub_get_gating_prod();
blcg_gr_load_gating_prod.gating_funcs[3] =
g->ops.cg.blcg_hshub_load_gating_prod;
blcg_gr_load_gating_prod.domain_desc_sizes[3] =
gv11b_blcg_hshub_gating_prod_size();
}
#define INIT_SLCG_DOMAIN_TEST_DATA(param) ({\
struct cg_test_data *tmp = &slcg_##param; \
tmp->domain_descs[0] = gv11b_slcg_##param##_get_gating_prod(); \
tmp->gating_funcs[0] = g->ops.cg.slcg_##param##_load_gating_prod; \
tmp->domain_desc_sizes[0] = gv11b_slcg_##param##_gating_prod_size(); \
})
static void init_slcg_fb_ltc_data(struct gk20a *g)
{
slcg_fb_ltc.domain_descs[0] = gv11b_slcg_fb_get_gating_prod();
slcg_fb_ltc.gating_funcs[0] = g->ops.cg.slcg_fb_load_gating_prod;
slcg_fb_ltc.domain_desc_sizes[0] = gv11b_slcg_fb_gating_prod_size();
slcg_fb_ltc.domain_descs[1] = gv11b_slcg_ltc_get_gating_prod();
slcg_fb_ltc.gating_funcs[1] = g->ops.cg.slcg_ltc_load_gating_prod;
slcg_fb_ltc.domain_desc_sizes[1] = gv11b_slcg_ltc_gating_prod_size();
}
static void init_slcg_priring_data(struct gk20a *g)
{
INIT_SLCG_DOMAIN_TEST_DATA(priring);
}
static void init_slcg_fifo_data(struct gk20a *g)
{
INIT_SLCG_DOMAIN_TEST_DATA(fifo);
}
static void init_slcg_pmu_data(struct gk20a *g)
{
INIT_SLCG_DOMAIN_TEST_DATA(pmu);
}
static void init_slcg_therm_data(struct gk20a *g)
{
INIT_SLCG_DOMAIN_TEST_DATA(therm);
}
static void init_slcg_ce2_data(struct gk20a *g)
{
INIT_SLCG_DOMAIN_TEST_DATA(ce2);
}
static void init_slcg_gr_load_gating_data(struct gk20a *g)
{
slcg_gr_load_gating_prod.domain_descs[0] =
gv11b_slcg_bus_get_gating_prod();
slcg_gr_load_gating_prod.gating_funcs[0] =
g->ops.cg.slcg_bus_load_gating_prod;
slcg_gr_load_gating_prod.domain_desc_sizes[0] =
gv11b_slcg_bus_gating_prod_size();
slcg_gr_load_gating_prod.domain_descs[1] =
gv11b_slcg_chiplet_get_gating_prod();
slcg_gr_load_gating_prod.gating_funcs[1] =
g->ops.cg.slcg_chiplet_load_gating_prod;
slcg_gr_load_gating_prod.domain_desc_sizes[1] =
gv11b_slcg_chiplet_gating_prod_size();
slcg_gr_load_gating_prod.domain_descs[2] =
gv11b_slcg_gr_get_gating_prod();
slcg_gr_load_gating_prod.gating_funcs[2] =
g->ops.cg.slcg_gr_load_gating_prod;
slcg_gr_load_gating_prod.domain_desc_sizes[2] =
gv11b_slcg_gr_gating_prod_size();
slcg_gr_load_gating_prod.domain_descs[3] =
gv11b_slcg_perf_get_gating_prod();
slcg_gr_load_gating_prod.gating_funcs[3] =
g->ops.cg.slcg_perf_load_gating_prod;
slcg_gr_load_gating_prod.domain_desc_sizes[3] =
gv11b_slcg_perf_gating_prod_size();
slcg_gr_load_gating_prod.domain_descs[4] =
gv11b_slcg_xbar_get_gating_prod();
slcg_gr_load_gating_prod.gating_funcs[4] =
g->ops.cg.slcg_xbar_load_gating_prod;
slcg_gr_load_gating_prod.domain_desc_sizes[4] =
gv11b_slcg_xbar_gating_prod_size();
slcg_gr_load_gating_prod.domain_descs[5] =
gv11b_slcg_hshub_get_gating_prod();
slcg_gr_load_gating_prod.gating_funcs[5] =
g->ops.cg.slcg_hshub_load_gating_prod;
slcg_gr_load_gating_prod.domain_desc_sizes[5] =
gv11b_slcg_hshub_gating_prod_size();
}
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);
nvgpu_posix_io_record_access(g, access);
}
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 cg_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,
};
static int init_test_env(struct unit_module *m, struct gk20a *g, void *args)
{
nvgpu_posix_register_io(g, &cg_callbacks);
/*
* Fuse register fuse_opt_priv_sec_en_r() is read during init_hal hence
* add it to reg space
*/
if (nvgpu_posix_io_add_reg_space(g,
fuse_opt_priv_sec_en_r(), 0x4) != 0) {
unit_err(m, "Add reg space failed!\n");
return UNIT_FAIL;
}
if (nvgpu_posix_io_add_reg_space(g,
fuse_opt_ecc_en_r(), 0x4) != 0) {
unit_err(m, "Add reg space failed!\n");
return UNIT_FAIL;
}
if (nvgpu_posix_io_add_reg_space(g,
fuse_opt_feature_fuses_override_disable_r(), 0x4) != 0) {
unit_err(m, "Add reg space failed!\n");
return UNIT_FAIL;
}
if (nvgpu_posix_io_add_reg_space(g,
gr_fecs_feature_override_ecc_r(), 0x4) != 0) {
unit_err(m, "Add reg space failed!\n");
return UNIT_FAIL;
}
if (nvgpu_posix_io_add_reg_space(g,
gr_fecs_feature_override_ecc_1_r(), 0x4) != 0) {
unit_err(m, "Add reg space failed!\n");
return UNIT_FAIL;
}
gv11b_init_hal(g);
init_blcg_fb_ltc_data(g);
init_blcg_fifo_data(g);
init_blcg_pmu_data(g);
init_blcg_ce_data(g);
init_blcg_gr_data(g);
init_blcg_gr_load_gating_data(g);
init_slcg_fb_ltc_data(g);
init_slcg_priring_data(g);
init_slcg_fifo_data(g);
init_slcg_pmu_data(g);
init_slcg_therm_data(g);
init_slcg_ce2_data(g);
init_slcg_gr_load_gating_data(g);
return UNIT_SUCCESS;
}
static int add_domain_gating_regs(struct gk20a *g,
const struct gating_desc *desc, u32 size)
{
int err = 0;
u32 i, j;
for (i = 0; i < size; i++) {
if (nvgpu_posix_io_add_reg_space(g, desc[i].addr, 0x4) != 0) {
err = -ENOMEM;
goto clean_regs;
}
}
return 0;
clean_regs:
for (j = 0; j < i; j++) {
nvgpu_posix_io_delete_reg_space(g, desc[j].addr);
}
return err;
}
static void delete_domain_gating_regs(struct gk20a *g,
const struct gating_desc *desc, u32 size)
{
u32 i;
for (i = 0; i < size; i++) {
nvgpu_posix_io_delete_reg_space(g, desc[i].addr);
}
}
static void invalid_load_enabled(struct gk20a *g,
struct cg_test_data *test_data)
{
u32 i, j;
for (i = 0; i < test_data->domain_count; i++) {
for (j = 0; j < test_data->domain_desc_sizes[i]; j++) {
nvgpu_writel(g, test_data->domain_descs[i][j].addr,
0xdeadbeed);
}
}
}
static int verify_load_enabled(struct gk20a *g, struct cg_test_data *test_data,
bool prod)
{
u32 i, j, value;
int mismatch = 0;
for (i = 0; i < test_data->domain_count; i++) {
for (j = 0; j < test_data->domain_desc_sizes[i]; j++) {
value =
nvgpu_readl(g, test_data->domain_descs[i][j].addr);
if (prod == true &&
value != test_data->domain_descs[i][j].prod) {
mismatch = 1;
goto out;
} else if (prod == false &&
value != test_data->domain_descs[i][j].disable) {
mismatch = 1;
goto out;
}
}
}
out:
return mismatch;
}
static void load_test_data_non_prod(struct gk20a *g,
struct cg_test_data *test_data)
{
u32 i;
for (i = 0; i < test_data->domain_count; i++) {
test_data->gating_funcs[i](g, false);
}
}
int test_cg(struct unit_module *m, struct gk20a *g, void *args)
{
struct cg_test_data *test_data = (struct cg_test_data *) args;
struct gpu_ops gops_temp;
u32 i;
int err;
for (i = 0; i < test_data->domain_count; i++) {
err = add_domain_gating_regs(g, test_data->domain_descs[i],
test_data->domain_desc_sizes[i]);
if (err != 0) {
return UNIT_FAIL;
}
}
invalid_load_enabled(g, test_data);
/**
* Test scenario where enabled flag and platform capability are
* not set.
*/
test_data->load_enable(g);
err = verify_load_enabled(g, test_data, true);
if (err == 0) {
unit_err(m, "enabled flag and platform capability "
"not yet set\n");
return UNIT_FAIL;
}
/** Tests if platform capability is checked setting enabled flag. */
nvgpu_set_enabled(g, test_data->cg_type, true);
test_data->load_enable(g);
err = verify_load_enabled(g, test_data, true);
if (err == 0) {
unit_err(m, "platform capability not yet set\n");
return UNIT_FAIL;
}
/** Tests if enabled flag is checked setting platform capability. */
nvgpu_set_enabled(g, test_data->cg_type, false);
if (test_data->cg_type == NVGPU_GPU_CAN_BLCG) {
g->blcg_enabled = true;
} else if (test_data->cg_type == NVGPU_GPU_CAN_SLCG) {
g->slcg_enabled = true;
}
test_data->load_enable(g);
err = verify_load_enabled(g, test_data, true);
if (err == 0) {
unit_err(m, "enabled flag not yet set\n");
return UNIT_FAIL;
}
/** Tests if gating registers are setup as expected. */
nvgpu_set_enabled(g, test_data->cg_type, true);
test_data->load_enable(g);
err = verify_load_enabled(g, test_data, true);
if (err != 0) {
unit_err(m, "gating registers prod mismatch\n");
return UNIT_FAIL;
}
load_test_data_non_prod(g, test_data);
err = verify_load_enabled(g, test_data, false);
if (err != 0) {
unit_err(m, "gating registers disable mismatch\n");
return UNIT_FAIL;
}
/* Tests if CG hals are checked for NULL before invoking. */
memcpy((u8 *)&gops_temp, (u8 *)&g->ops, sizeof(struct gpu_ops));
memset(&g->ops, 0, sizeof(struct gpu_ops));
invalid_load_enabled(g, test_data);
test_data->load_enable(g);
err = verify_load_enabled(g, test_data, true);
if (err == 0) {
unit_err(m, "CG hals not initialized\n");
return UNIT_FAIL;
}
memcpy((u8 *)&g->ops, (u8 *)&gops_temp, sizeof(struct gpu_ops));
/** Cleanup */
for (i = 0; i < test_data->domain_count; i++) {
delete_domain_gating_regs(g, test_data->domain_descs[i],
test_data->domain_desc_sizes[i]);
}
nvgpu_set_enabled(g, test_data->cg_type, false);
g->blcg_enabled = false;
g->slcg_enabled = false;
/* Check that no invalid register access occurred */
if (nvgpu_posix_io_get_error_code(g) != 0) {
unit_return_fail(m, "Invalid register accessed\n");
}
return UNIT_SUCCESS;
}
static int elcg_add_engine_therm_regs(struct gk20a *g)
{
u32 i;
const struct nvgpu_device *dev;
struct nvgpu_fifo *f = &g->fifo;
for (i = 0U; i < f->num_engines; i++) {
dev = f->active_engines[i];
if (nvgpu_posix_io_add_reg_space(g,
therm_gate_ctrl_r(dev->engine_id), 0x4) != 0) {
return UNIT_FAIL;
}
}
return UNIT_SUCCESS;
}
static void elcg_delete_engine_therm_regs(struct gk20a *g)
{
u32 i;
const struct nvgpu_device *dev;
struct nvgpu_fifo *f = &g->fifo;
for (i = 0U; i < f->num_engines; i++) {
dev = f->active_engines[i];
nvgpu_posix_io_delete_reg_space(g,
therm_gate_ctrl_r(dev->engine_id));
}
}
static int verify_elcg_status(struct gk20a *g, u32 cg_mode)
{
u32 i;
const struct nvgpu_device *dev;
struct nvgpu_fifo *f = &g->fifo;
int err = UNIT_SUCCESS;
u32 gate_r;
for (i = 0; i < f->num_engines; i++) {
dev = f->active_engines[i];
gate_r = nvgpu_readl(g, therm_gate_ctrl_r(dev->engine_id));
if (cg_mode == ELCG_RUN) {
if (get_field(gate_r,
therm_gate_ctrl_eng_clk_m()) !=
therm_gate_ctrl_eng_clk_run_f()) {
err = UNIT_FAIL;
break;
}
if (get_field(gate_r,
therm_gate_ctrl_idle_holdoff_m()) !=
therm_gate_ctrl_idle_holdoff_on_f()) {
err = UNIT_FAIL;
break;
}
} else if (cg_mode == ELCG_AUTO) {
if (get_field(gate_r,
therm_gate_ctrl_eng_clk_m()) !=
therm_gate_ctrl_eng_clk_auto_f()) {
err = UNIT_FAIL;
break;
}
}
}
return err;
}
static int test_elcg_api(struct gk20a *g, int exp_err)
{
int err;
nvgpu_cg_elcg_enable_no_wait(g);
err = verify_elcg_status(g, ELCG_AUTO);
if (err != exp_err) {
return UNIT_FAIL;
}
nvgpu_cg_elcg_disable_no_wait(g);
err = verify_elcg_status(g, ELCG_RUN);
if (err != exp_err) {
return UNIT_FAIL;
}
return UNIT_SUCCESS;
}
int test_elcg(struct unit_module *m, struct gk20a *g, void *args)
{
int err;
err = test_fifo_init_support(m, g, NULL);
if (err != 0) {
unit_return_fail(m, "failed to init fifo support\n");
return err;
}
err = elcg_add_engine_therm_regs(g);
if (err != 0) {
unit_return_fail(m, "failed to add engine therm registers\n");
return err;
}
if (test_elcg_api(g, UNIT_FAIL) != UNIT_SUCCESS) {
unit_return_fail(m, "enabled flag not yet set\n");
}
nvgpu_set_enabled(g, NVGPU_GPU_CAN_ELCG, true);
if (test_elcg_api(g, UNIT_FAIL) != UNIT_SUCCESS) {
unit_return_fail(m, "platform capability not yet set\n");
}
g->elcg_enabled = true;
if (test_elcg_api(g, UNIT_SUCCESS) != UNIT_SUCCESS) {
unit_return_fail(m,
"elcg enable disable not setup correctly\n");
}
/* Check that no invalid register access occurred */
if (nvgpu_posix_io_get_error_code(g) != 0) {
unit_return_fail(m, "Invalid register accessed\n");
}
elcg_delete_engine_therm_regs(g);
err = test_fifo_remove_support(m, g, NULL);
if (err != 0) {
unit_return_fail(m, "failed to remove fifo support\n");
return err;
}
return UNIT_SUCCESS;
}
struct unit_module_test cg_tests[] = {
UNIT_TEST(init, init_test_env, NULL, 0),
UNIT_TEST(blcg_fb_ltc, test_cg, &blcg_fb_ltc, 0),
UNIT_TEST(blcg_fifo, test_cg, &blcg_fifo, 0),
UNIT_TEST(blcg_ce, test_cg, &blcg_ce, 0),
UNIT_TEST(blcg_pmu, test_cg, &blcg_pmu, 0),
UNIT_TEST(blcg_gr, test_cg, &blcg_gr, 0),
UNIT_TEST(slcg_fb_ltc, test_cg, &slcg_fb_ltc, 0),
UNIT_TEST(slcg_priring, test_cg, &slcg_priring, 0),
UNIT_TEST(slcg_fifo, test_cg, &slcg_fifo, 0),
UNIT_TEST(slcg_pmu, test_cg, &slcg_pmu, 0),
UNIT_TEST(slcg_therm, test_cg, &slcg_therm, 0),
UNIT_TEST(slcg_ce2, test_cg, &slcg_ce2, 0),
UNIT_TEST(slcg_gr_load_gating_prod, test_cg,
&slcg_gr_load_gating_prod, 0),
UNIT_TEST(blcg_gr_load_gating_prod, test_cg,
&blcg_gr_load_gating_prod, 0),
UNIT_TEST(elcg, test_elcg, NULL, 0),
};
UNIT_MODULE(cg, cg_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,122 @@
/*
* 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.
*/
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-cg
* @{
*
* Software Unit Test Specification for cg
*/
/**
* Test specification for: test_cg
*
* Description: The cg unit shall be able to setup the clock gating register
* values as specified in the hal reglist structures for BLCG/SLCG.
*
* Test Type: Feature
*
* Targets: nvgpu_cg_blcg_fb_ltc_load_enable, nvgpu_cg_blcg_fifo_load_enable,
* nvgpu_cg_blcg_ce_load_enable, nvgpu_cg_blcg_pmu_load_enable,
* nvgpu_cg_blcg_gr_load_enable, nvgpu_cg_slcg_fb_ltc_load_enable,
* nvgpu_cg_slcg_priring_load_enable, nvgpu_cg_slcg_fifo_load_enable,
* nvgpu_cg_slcg_pmu_load_enable, nvgpu_cg_slcg_therm_load_enable,
* nvgpu_cg_slcg_ce2_load_enable, nvgpu_cg_init_gr_load_gating_prod
*
* Input: The struct specifying type of clock gating, target nvgpu routine
* that handles the setup, clock gating domain descriptors.
*
* Steps:
* - Initialize the test environment:
* - Register read/write IO callbacks.
* - Add relevant fuse registers to the register space.
* - Initialize hal to setup the hal functions.
* - Initialize slcg and blcg gating register data by querying through
* nvgpu exported functions.
* - Add the domain gating registers to the register space.
* - Load invalid values in the gating registers.
* - Invoke the nvgpu function to load the clock gating values.
* - Verify that load is not enabled as BLCG/SLCG enabled flag isn't set.
* - Enable BLCG/SLCG enabled flag.
* - Invoke the nvgpu function to load the clock gating values.
* - Verify that load is not enabled as platform capability isn't set.
* - Disable BLCG/SLCG enabled flag.
* - Set the platform capability.
* - Invoke the nvgpu function to load the clock gating values.
* - Verify that load is not enabled as enabled flag isn't set.
* - Enable BLCG/SLCG enabled flag.
* - Invoke the nvgpu function to load the clock gating values.
* - Verify that load is enabled.
* - Invoke the nvgpu functions to load the non-prod clock gating values.
* - Verify that load is not enabled.
* - Set all CG gpu_ops to NULL.
* - Invoke the nvgpu function to load the clock gating values.
* - Verify that load is not enabled as HALs are not set.
* - Restore the CG gpu_ops.
* - Any invalid accesses by nvgpu will be caught through ABORTs and
* test fails if ABORTs are encountered.
* - Delete domain gating registers from the registere space.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_cg(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_elcg
*
* Description: The cg unit shall be able to setup the engine therm register
* values to enable/disable ELCG.
*
* Test Type: Feature
*
* Targets: nvgpu_cg_elcg_enable_no_wait, nvgpu_cg_elcg_disable_no_wait
*
* Input: None
*
* Steps:
* - Initialize the test environment:
* - Register read/write IO callbacks.
* - Add relevant fuse registers to the register space.
* - Initialize hal to setup the hal functions.
* - Initialize fifo support to configure ELCG at engine level.
* - Add the engine therm registers to the register space.
* - Invoke the nvgpu function to enable/disable ELCG.
* - Verify that cg mode isn't set in therm registers as ELCG enabled flag
* isn't set.
* - Enable ELCG enabled flag.
* - Invoke the nvgpu function to enable/disable ELCG.
* - Verify that cg mode isn't set in therm registers as ELCG platform
* capability isn't set.
* - Set the platform capability.
* - Invoke the nvgpu function to enable/disable ELCG.
* - Verify that cg mode is set in therm registers.
* - Any invalid accesses by nvgpu will be caught through ABORTs and
* test fails if ABORTs are encountered.
* - Delete engine therm registers from the registere space.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_elcg(struct unit_module *m, struct gk20a *g, void *args);

View File

@@ -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-class.o
MODULE = class
include ../Makefile.units

View File

@@ -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=class
include $(NV_COMPONENT_DIR)/../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -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=class
NVGPU_UNIT_SRCS=nvgpu-class.c
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,155 @@
/*
* Copyright (c) 2019-2021, 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/class.h>
#include "hal/class/class_gv11b.h"
#include "nvgpu-class.h"
u32 valid_compute_classes[] = {
0xC3C0U, /* VOLTA_COMPUTE_A */
};
u32 invalid_compute_classes[] = {
0xC397U, /* VOLTA_A */
0xC3B5U, /* VOLTA_DMA_COPY_A */
0xC36FU, /* VOLTA_CHANNEL_GPFIFO_A */
0xC0B5U, /* PASCAL_DMA_COPY_A */
0xC06FU, /* PASCAL_CHANNEL_GPFIFO_A */
0xB06FU, /* MAXWELL_CHANNEL_GPFIFO_A */
0xB0B5U, /* MAXWELL_DMA_COPY_A */
0xA140U, /* KEPLER_INLINE_TO_MEMORY_B */
0xA0B5U, /* KEPLER_DMA_COPY_A */
0xC097U, /* PASCAL_A */
0xC0C0U, /* PASCAL_COMPUTE_A */
0xB1C0U, /* MAXWELL_COMPUTE_B */
0xB197U, /* MAXWELL_B */
0x902DU, /* FERMI_TWOD_A */
0x1234U, /* random value */
0x76543210U, /* random value */
0x0000U, /* BVEC test value */
0xB000U, /* BVEC test value */
0xC3BFU, /* BVEC test value */
0xC3C1U, /* BVEC test value */
0xD000U, /* BVEC test value */
0xFFFFFFFFU, /* BVEC test value */
};
u32 valid_classes[] = {
0xC36FU, /* VOLTA_CHANNEL_GPFIFO_A */
0xC397U, /* VOLTA_A */
0xC3B5U, /* VOLTA_DMA_COPY_A */
0xC3C0U, /* VOLTA_COMPUTE_A */
};
u32 invalid_classes[] = {
0x1234U, /* random value */
0xC097U, /* PASCAL_A */
0xC0C0U, /* PASCAL_COMPUTE_A */
0xB1C0U, /* MAXWELL_COMPUTE_B */
0xB197U, /* MAXWELL_B */
0x902DU, /* FERMI_TWOD_A */
0xC0B5U, /* PASCAL_DMA_COPY_A */
0xC06FU, /* PASCAL_CHANNEL_GPFIFO_A */
0xB06FU, /* MAXWELL_CHANNEL_GPFIFO_A */
0xB0B5U, /* MAXWELL_DMA_COPY_A */
0xA140U, /* KEPLER_INLINE_TO_MEMORY_B */
0xA0B5U, /* KEPLER_DMA_COPY_A */
0x76543210U, /* random value */
0x0000U, /* BVEC test value */
0xB000U, /* BVEC test value */
0xC36EU, /* BVEC test value */
0xC370U, /* BVEC test value */
0xC396U, /* BVEC test value */
0xC398U, /* BVEC test value */
0xC3B4U, /* BVEC test value */
0xC3B6U, /* BVEC test value */
0xC3BFU, /* BVEC test value */
0xC3C1U, /* BVEC test value */
0xD000U, /* BVEC test value */
0xFFFFFFFFU, /* BVEC test value */
};
int class_validate_setup(struct unit_module *m, struct gk20a *g, void *args)
{
bool valid = false;
u32 i;
/* Init HAL */
g->ops.gpu_class.is_valid_compute = gv11b_class_is_valid_compute;
g->ops.gpu_class.is_valid = gv11b_class_is_valid;
for (i = 0;
i < sizeof(valid_compute_classes)/sizeof(u32);
i++) {
valid = g->ops.gpu_class.is_valid_compute(
valid_compute_classes[i]);
if (!valid) {
goto fail;
}
}
for (i = 0;
i < sizeof(invalid_compute_classes)/sizeof(u32);
i++) {
valid = g->ops.gpu_class.is_valid_compute(
invalid_compute_classes[i]);
if (valid) {
goto fail;
}
}
for (i = 0;
i < sizeof(valid_classes)/sizeof(u32);
i++) {
valid = g->ops.gpu_class.is_valid(valid_classes[i]);
if (!valid) {
goto fail;
}
}
for (i = 0;
i < sizeof(invalid_classes)/sizeof(u32);
i++) {
valid = g->ops.gpu_class.is_valid(invalid_classes[i]);
if (valid) {
goto fail;
}
}
return UNIT_SUCCESS;
fail:
unit_err(m, "%s: failed to validate class API\n", __func__);
return UNIT_FAIL;
}
struct unit_module_test class_tests[] = {
UNIT_TEST(class_validate, class_validate_setup, NULL, 0),
};
UNIT_MODULE(class, class_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2019-2021, 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_CLASS_H
#define UNIT_NVGPU_CLASS_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-class
* @{
*
* Software Unit Test Specification for nvgpu.common.class
*/
/**
* Test specification for: class_validate
*
* Description: Validate common.class unit API.
*
* Test Type: Feature, Boundary Values
*
* Targets: gops_class.is_valid, gv11b_class_is_valid
* Equivalence classes:
* Variable: class_num
* - Valid : { 0xC3C0U }, { 0xC3B5U }, { 0xC36FU }, { 0xC397U }
*
* Targets: gops_class.is_valid_compute, gv11b_class_is_valid_compute,
* Equivalence classes:
* Variable: class_num
* - Valid : { 0xC3C0U }
*
* Input: None
*
* Steps:
* - Initialize common.class HAL function pointers.
* - Validate common.class unit API with below positive/negative data
* sets.
*
* - g->ops.gpu_class.is_valid_compute()
* Pass data set of supported compute classes and ensure API
* returns success in each case.
*
* - g->ops.gpu_class.is_valid_compute()
* Pass data set of unsupported compute classes and ensure API
* returns failure in each case.
*
* - g->ops.gpu_class.is_valid()
* Pass data set of all supported classes and ensure API
* returns success in each case.
*
* - g->ops.gpu_class.is_valid()
* Pass data set of unsupported classes and ensure API
* returns failure in each case.
*
* Output:
* Returns PASS if above validation was performed successfully. FAIL
* otherwise.
*/
int class_validate_setup(struct unit_module *m, struct gk20a *g, void *args);
#endif /* UNIT_NVGPU_CLASS_H */

View File

@@ -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-ecc.o
MODULE = ecc
include ../Makefile.units

View File

@@ -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-ecc
include $(NV_COMPONENT_DIR)/../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -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-ecc
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,253 @@
/*
* Copyright (c) 2019-2021, 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/ecc.h>
#include <nvgpu/ltc.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include <common/gr/gr_priv.h>
#include "nvgpu-ecc.h"
static void mock_ecc_free(struct gk20a *g) {
}
int test_ecc_init_support(struct unit_module *m, struct gk20a *g,
void *args)
{
/*
* Case #1:
* - First time ecc intialization.
* - "nvgpu_ecc_init_support" should perform init and return 0.
*/
g->ecc.initialized = false;
if (nvgpu_ecc_init_support(g) != 0) {
return UNIT_FAIL;
}
/*
* Case #2:
* - Second time ecc intialization.
* - "nvgpu_ecc_init_support" should skip init but return 0.
*/
g->ecc.initialized = true;
if (nvgpu_ecc_init_support(g) != 0) {
return UNIT_FAIL;
}
return UNIT_SUCCESS;
}
int test_ecc_finalize_support(struct unit_module *m, struct gk20a *g,
void *args)
{
/*
* Case #1:
* - First time ecc intialization.
* - "nvgpu_ecc_finalize_support" should perform init and return 0.
*/
g->ecc.initialized = false;
if (nvgpu_ecc_finalize_support(g) != 0) {
return UNIT_FAIL;
}
/*
* Case #2:
* - Second time ecc intialization.
* - "nvgpu_ecc_finalize_support" should skip init but return 0.
*/
g->ecc.initialized = true;
if (nvgpu_ecc_finalize_support(g) != 0) {
return UNIT_FAIL;
}
return UNIT_SUCCESS;
}
int test_ecc_counter_init(struct unit_module *m, struct gk20a *g,
void *args)
{
int ret = UNIT_SUCCESS;
struct nvgpu_ecc_stat *stat = NULL;
char *name;
struct nvgpu_posix_fault_inj *kmem_fi =
nvgpu_kmem_get_fault_injection();
/*
* Test setup:
* - Allocate memory for ecc counter name.
* - Initialize ecc support.
*/
name = nvgpu_kzalloc(g, NVGPU_ECC_STAT_NAME_MAX_SIZE + 1);
if (name == NULL) {
return UNIT_FAIL;
}
if (nvgpu_ecc_init_support(g) != 0) {
ret = UNIT_FAIL;
goto cleanup;
}
/*
* Case #1:
* - Initialize "name" with valid length string.
* - "nvgpu_ecc_counter_init" should return 0.
*/
strcpy(name, "test_counter");
if (nvgpu_ecc_counter_init(g, &stat, name) != 0) {
ret = UNIT_FAIL;
goto cleanup;
}
nvgpu_ecc_counter_deinit(g, &stat);
/*
* Case #2:
* - Inject SW fault to cause "nvgpu_kzalloc" failure.
* - "nvgpu_ecc_counter_init" should return -ENOMEM.
*/
nvgpu_posix_enable_fault_injection(kmem_fi, true, 0);
if (nvgpu_ecc_counter_init(g, &stat, name) != -ENOMEM) {
ret = UNIT_FAIL;
goto cleanup;
}
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
/*
* Case #3:
* - Intialize "name" with string of length greater than
* NVGPU_ECC_STAT_NAME_MAX_SIZE.
* - "nvgpu_ecc_counter_init" should return 0, with a truncated
* counter name.
*/
memset(name, NVGPU_ECC_STAT_NAME_MAX_SIZE, 'a');
if (nvgpu_ecc_counter_init(g, &stat, name) != 0) {
ret = UNIT_FAIL;
goto cleanup;
}
nvgpu_ecc_counter_deinit(g, &stat);
if (!nvgpu_list_empty(&g->ecc.stats_list)) {
ret = UNIT_FAIL;
goto cleanup;
}
cleanup:
if (stat != NULL) {
nvgpu_ecc_counter_deinit(g, &stat);
}
nvgpu_kfree(g, name);
return ret;
}
int test_ecc_free(struct unit_module *m, struct gk20a *g,
void *args)
{
int ret = UNIT_SUCCESS;
if (nvgpu_ecc_init_support(g) != 0) {
return UNIT_FAIL;
}
/*
* Setup:
* - allocate memory for gr and clear it to zero.
* - set gr->config to NULL to return immediately from
* nvgpu_gr_ecc_free.
* - Allocate memory for ltc and clear it to zero, this should set
* the ltc_Count and slice_per_ltc to 0.
*/
g->gr = nvgpu_kzalloc(g, sizeof(*g->gr));
if (g->gr == NULL) {
return UNIT_FAIL;
}
g->ltc = nvgpu_kzalloc(g, sizeof(*g->ltc));
if (g->ltc == NULL) {
nvgpu_kfree(g, g->gr);
return UNIT_FAIL;
}
/*
* Case #1:
* - fb, fpba and pmu ecc HALs have ecc free handles set to NULL.
* - "nvgpu_ecc_free" should skip freeing ecc counters for fb, fpba,
* pmu and return without faulting.
*/
g->ops.fb.ecc.free = NULL;
g->ops.pmu.ecc_free = NULL;
g->ecc.ltc.ecc_sec_count = nvgpu_kzalloc(g,
sizeof(*g->ecc.ltc.ecc_sec_count));
g->ecc.ltc.ecc_ded_count = nvgpu_kzalloc(g,
sizeof(*g->ecc.ltc.ecc_ded_count));
if (g->ecc.ltc.ecc_sec_count == NULL
|| g->ecc.ltc.ecc_ded_count == NULL) {
ret = UNIT_FAIL;
goto cleanup;
}
nvgpu_ecc_free(g);
/*
* Case #2:
* - fb and pmu ecc HALs have ecc free handles are set.
* - "nvgpu_ecc_free" should return without faulting.
*/
g->ops.fb.ecc.free = mock_ecc_free;
g->ops.pmu.ecc_free = mock_ecc_free;
g->ecc.ltc.ecc_sec_count = nvgpu_kzalloc(g,
sizeof(*g->ecc.ltc.ecc_sec_count));
g->ecc.ltc.ecc_ded_count = nvgpu_kzalloc(g,
sizeof(*g->ecc.ltc.ecc_ded_count));
if (g->ecc.ltc.ecc_sec_count == NULL
|| g->ecc.ltc.ecc_ded_count == NULL) {
ret = UNIT_FAIL;
goto cleanup;
}
nvgpu_ecc_free(g);
g->ecc.ltc.ecc_sec_count = NULL;
g->ecc.ltc.ecc_ded_count = NULL;
cleanup:
if (g->ecc.ltc.ecc_sec_count != NULL) {
nvgpu_kfree(g, g->ecc.ltc.ecc_sec_count);
}
if (g->ecc.ltc.ecc_ded_count != NULL) {
nvgpu_kfree(g, g->ecc.ltc.ecc_ded_count);
}
nvgpu_kfree(g, g->gr);
nvgpu_kfree(g, g->ltc);
return ret;
}
struct unit_module_test ecc_tests[] = {
UNIT_TEST(ecc_init_support, test_ecc_init_support, NULL, 0),
UNIT_TEST(ecc_finalize_support, test_ecc_finalize_support, NULL, 0),
UNIT_TEST(ecc_counter_init, test_ecc_counter_init, NULL, 0),
UNIT_TEST(ecc_free, test_ecc_free, NULL, 0),
};
UNIT_MODULE(ecc, ecc_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,161 @@
/*
* Copyright (c) 2019-2021, 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_ECC_H
#define UNIT_NVGPU_ECC_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-ecc
* @{
*
* Software Unit Test Specification for nvgpu.common.ecc
*/
/**
* Test specification for: test_ecc_init_support
*
* Description: Verify the "nvgpu_ecc_init_support" API.
*
* Test Type: Feature Based
*
* Targets: nvgpu_ecc_init_support, gops_ecc.ecc_init_support
*
* Input: None
*
* Steps:
* - Test case #1
* - Fresh initalization, ecc.initialized = false.
* - "nvgpu_ecc_init_support" should succeed and return 0.
* - Test case #2
* - Re-initialization, ecc.initailiziation = true.
* - "nvgpu_ecc_init_support" will succeed but skip init and return 0.
*
* Output:
* - UNIT_FAIL if "nvgpu_ecc_init_support" fails with non-zero return value.
* - UNIT_SUCCESS otherwise
*/
int test_ecc_init_support(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for: test_ecc_finalize_support
*
* Description: Verify the "nvgpu_ecc_finalize_support" API.
*
* Test Type: Feature Based
*
* Targets: nvgpu_ecc_finalize_support, gops_ecc.ecc_finalize_support
*
* Input: None
*
* Steps:
* - Test case #1
* - Fresh initalization, ecc.initialized = false.
* - "nvgpu_ecc_finalize_support" should succeed and return 0.
* - Test case #2
* - Re-initialization, ecc.initailiziation = true.
* - "nvgpu_ecc_finalize_support" will succeed but skip init and return 0.
*
* Output:
* - UNIT_FAIL if "nvgpu_ecc_finalize_support" fails with non-zero return value.
* - UNIT_SUCCESS otherwise
*/
int test_ecc_finalize_support(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for: test_ecc_counter_init
*
* Description: Verify "nvgpu_ecc_counter_init" API.
*
* Test Type: Feature Based
*
* Targets: nvgpu_ecc_counter_init, nvgpu_ecc_stat_add
*
* Input: nvgpu_ecc_init_support
*
* Steps:
* - Invokes "nvgpu_ecc_init_support".
* - Allocate memory for counter name string.
* - Test case #1
* - Invokes "nvgpu_ecc_counter_init" with valid counter name("test_counter")
* - "nvgpu_ecc_counter_init" should succeed and return 0.
* - Test case #2
* - Inject memory allocation fault
* - "nvgpu_ecc_counter_init" should return -ENOMEM
* - Test Case #3
* - Set counter name to string with invalid length equal to
* NVGPU_ECC_STAT_NAME_MAX_SIZE.
* - "nvgpu_ecc_counter_init" will truncate the counter name and return 0.
* - Test case #4
* - Verify that the g->ecc.stats_list is empty.
*
* Output:
* - UNIT_FAIL under the following conditions:
* - Counter name memory allocation failed.
* - "nvgpu_ecc_init_support" failed.
* - "nvgpu_ecc_counter_init" failed.
* - UNIT_SUCCESS otherwise
*/
int test_ecc_counter_init(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for: test_ecc_free
*
* Description: Verify "nvgpu_ecc_free" API.
*
* Test Type: Feature Based
*
* Targets: nvgpu_ecc_free
*
* Input: nvgpu_ecc_init_support
*
* Steps:
* - Do the following setup
* - "nvgpu_ecc_init_support".
* - assign respective HALs and allocate memory for g->ltc and g->gr.
* - Test case #1
* - Invokes "nvgpu_ecc_free" with unassigned fb_ecc_free, fbpa_ecc_free
* and pmu.ecc_free HALs.
* - "nvgpu_ecc_free" should succeed without faulting.
* - Test case #2
* - Invokes "nvgpu_ecc_free" with uassigned fb_ecc_free, fbpa_ecc_free
* and pmu.ecc_free HALs.
* - "nvgpu_ecc_free" should succeed without faulting.
*
* Output:
* - UNIT_FAIL under the following conditions:
* - "nvgpu_ecc_init_support" failed.
* - Memory allocation failed for either g->gr or g->ltc.
* - Memory allocation failed for either ltc.ecc_sec/ded_count.
*
* - UNIT_SUCCESS otherwise
*/
int test_ecc_free(struct unit_module *m,
struct gk20a *g, void *args);
#endif /* UNIT_NVGPU_ECC_H */

View File

@@ -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-enabled.o
MODULE = nvgpu-enabled
include ../Makefile.units

View File

@@ -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-enabled
include $(NV_COMPONENT_DIR)/../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -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-enabled
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,131 @@
/*
* 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 <stdlib.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/enabled.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include "nvgpu-enabled.h"
static unsigned long *original_enabled_flags;
int test_nvgpu_init_enabled_flags(struct unit_module *m,
struct gk20a *g, void *args)
{
int err;
struct nvgpu_posix_fault_inj *kmem_fi =
nvgpu_kmem_get_fault_injection();
original_enabled_flags = g->enabled_flags;
/*
* Test 1 - Enable SW fault injection and check that init function
* fails with -ENOMEM.
*/
nvgpu_posix_enable_fault_injection(kmem_fi, true, 0);
err = nvgpu_init_enabled_flags(g);
if (err != -ENOMEM) {
g->enabled_flags = original_enabled_flags;
unit_return_fail(m,
"enabled_flags init didn't fail as expected\n");
}
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
/*
* Test 2 - Check that enabled_flags are inited successfully
* Use these flags (allocated memory) for next tests in module.
*/
err = nvgpu_init_enabled_flags(g);
if (err != 0) {
g->enabled_flags = original_enabled_flags;
unit_return_fail(m, "enabled_flags init failed\n");
}
return UNIT_SUCCESS;
}
int test_nvgpu_enabled_flags_false_check(struct unit_module *m,
struct gk20a *g, void *args)
{
u32 i;
u32 n = NVGPU_MAX_ENABLED_BITS;
for (i = 1U; i < n; i++) { /* First flag is index 1 */
if (nvgpu_is_enabled(g, i)) {
g->enabled_flags = original_enabled_flags;
unit_return_fail(m,
"enabled_flag %u inited to non-zero value\n", i);
}
}
return UNIT_SUCCESS;
}
int test_nvgpu_set_enabled(struct unit_module *m,
struct gk20a *g, void *args)
{
u32 i;
u32 n = NVGPU_MAX_ENABLED_BITS;
for (i = 1U; i < n; i++) { /* First flag is index 1 */
nvgpu_set_enabled(g, i, true);
if (!nvgpu_is_enabled(g, i)) {
g->enabled_flags = original_enabled_flags;
unit_return_fail(m,
"enabled_flag %u could not be enabled\n", i);
}
nvgpu_set_enabled(g, i, false);
if (nvgpu_is_enabled(g, i)) {
g->enabled_flags = original_enabled_flags;
unit_return_fail(m,
"enabled_flag %u could not be disabled\n", i);
}
}
return UNIT_SUCCESS;
}
int test_nvgpu_free_enabled_flags(struct unit_module *m,
struct gk20a *g, void *args)
{
nvgpu_free_enabled_flags(g);
g->enabled_flags = original_enabled_flags;
return UNIT_SUCCESS;
}
struct unit_module_test enabled_tests[] = {
/*
* Init test should run first in order to use newly allocated memory.
*/
UNIT_TEST(init, test_nvgpu_init_enabled_flags, NULL, 0),
UNIT_TEST(enabled_flags_false_check, test_nvgpu_enabled_flags_false_check, NULL, 0),
UNIT_TEST(set_enabled, test_nvgpu_set_enabled, NULL, 0),
UNIT_TEST(free, test_nvgpu_free_enabled_flags, NULL, 0),
};
UNIT_MODULE(enabled, enabled_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2019-2020, 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_ENABLED_H
#define UNIT_NVGPU_ENABLED_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-enabled
* @{
*
* Software Unit Test Specification for enabled
*/
/**
* Test specification for: test_nvgpu_init_enabled_flags
*
* Description: Initialize GPU enabled_flags
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_init_enabled_flags
*
* Input: None
*
* Steps:
* - GPU structure contains enabled_flags initialized at boot
* - Store already created enabled_flags pointer in a global variable
* - Initialize enabled_flags for this unit test
* - New created enabled_flags are set to false
* - Check if return value indicates success
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_init_enabled_flags(struct unit_module *m, struct gk20a *g,
void *args);
/**
* Test specification for: test_nvgpu_enabled_flags_false_check
*
* Description: Check if enabled_flags are set to false.
*
* Test Type: Feature
*
* Targets: nvgpu_is_enabled
*
* Input: test_nvgpu_init_enabled_flags
*
* Steps:
* - Check flag value
* - As flags are allocated for unit test, flag value is expected to be false
* - Iterate over each flag and check if flag value is false
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_enabled_flags_false_check(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for: test_nvgpu_set_enabled
*
* Description: Set and reset enabled_flags
*
* Test Type: Feature
*
* Targets: nvgpu_is_enabled, nvgpu_set_enabled
*
* Input: test_nvgpu_init_enabled_flags
*
* Steps:
* - Set and reset each flag
* - Iterate over a flag 'i' and set it to true
* - Check if flag 'i' value is true
* - Reset value of flag 'i' to false
* - Check if flag 'i' value is false
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_set_enabled(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_nvgpu_free_enabled_flags
*
* Description: Free enabled_flags
*
* Test Type: Feature
*
* Targets: nvgpu_free_enabled_flags
*
* Input: test_nvgpu_init_enabled_flags
*
* Steps:
* - Free enabled_flag memory
* - Free enabled_flags allocated for this unit test
* - Restore originally created enabled_flags pointer
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_free_enabled_flags(struct unit_module *m,
struct gk20a *g, void *args);
#endif /* UNIT_NVGPU_ENABLED_H */

View File

@@ -0,0 +1,27 @@
# 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 = falcon_utf.o
MODULE = falcon_utf
include ../Makefile.units

View File

@@ -0,0 +1,29 @@
################################### 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
#
# libfalcon_utf interface makefile fragment
#
###############################################################################
ifdef NV_INTERFACE_FLAG_SHARED_LIBRARY_SECTION
NV_INTERFACE_NAME := falcon_utf
NV_INTERFACE_EXPORTS := lib$(NV_INTERFACE_NAME)
NV_INTERFACE_SONAME := lib$(NV_INTERFACE_NAME).so
endif
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,26 @@
################################### 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
#
# Component makefile for compiling falcon_utf common tests.
#
###############################################################################
NVGPU_UNIT_NAME = falcon_utf
NVGPU_UNIT_SRCS = falcon_utf.c
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -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 = falcon.o
MODULE = falcon
LIB_PATHS += -lfalcon_utf
include ../../Makefile.units
lib$(MODULE).so: falcon_utf
falcon_utf:
$(MAKE) -C ..

View File

@@ -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=falcon
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,27 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019-2020 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=falcon
NVGPU_UNIT_SRCS=falcon.c
NVGPU_UNIT_INTERFACE_DIRS := \
$(NV_COMPONENT_DIR)/..
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,514 @@
/*
* Copyright (c) 2019-2020, 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.
*/
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-falcon
* @{
*
* Software Unit Test Specification for falcon
*/
/**
* Test specification for: test_falcon_sw_init_free
*
* Description: The falcon unit shall be able to initialize the falcon's
* base register address, required software setup for valid falcon ID.
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_falcon_get_instance, nvgpu_falcon_sw_init,
* nvgpu_falcon_sw_free, gops_pmu.falcon_base_addr,
* gv11b_pmu_falcon_base_addr, gops_pmu.setup_apertures,
* gv11b_setup_apertures, gops_pmu.flcn_setup_boot_config,
* gv11b_pmu_flcn_setup_boot_config
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_sw_init with valid falcon ID before initializing HAL.
* - Verify that falcon initialization fails since valid gpu_arch|impl
* are not initialized.
* - Invoke nvgpu_falcon_sw_free with above falcon ID.
* - Initialize the test environment:
* - Register read/write IO callbacks that handle falcon IO as well.
* - Add relevant fuse registers to the register space.
* - Initialize hal to setup the hal functions.
* - Initialize UTF (Unit Test Framework) falcon structures for PMU and
* GPCCS falcons.
* - Create and initialize test buffer with random data.
* - Invoke nvgpu_falcon_sw_init with invalid falcon ID.
* - Verify that falcon initialization fails.
* - Invoke nvgpu_falcon_sw_free with above falcon ID.
* - Invoke nvgpu_falcon_sw_init with valid falcon ID.
* - Verify that falcon initialization succeeds.
* - Invoke nvgpu_falcon_sw_free with above falcon ID.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_sw_init_free(struct unit_module *m, struct gk20a *g,
void *__args);
/**
* Test specification for: test_falcon_get_id
*
* Description: The falcon unit shall be able to return the falcon ID
* for the falcon.
*
* Test Type: Feature
*
* Targets: nvgpu_falcon_get_id
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_get_id with the gpccs falcon struct.
* - Verify that return falcon ID is #FALCON_ID_GPCCS.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_get_id(struct unit_module *m, struct gk20a *g,
void *__args);
/**
* Test specification for: test_falcon_reset
*
* Description: The falcon unit shall be able to reset the falcon CPU or trigger
* engine specific reset for valid falcon ID.
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_falcon_reset, gops_falcon.reset, gk20a_falcon_reset
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_reset with NULL falcon pointer.
* - Verify that reset fails with -EINVAL return value.
* - Invoke nvgpu_falcon_reset with uninitialized falcon struct.
* - Verify that reset fails with -EINVAL return value.
* - Invoke nvgpu_falcon_reset with valid falcon ID.
* - Verify that falcon initialization succeeds and check that bit
* falcon_cpuctl_hreset_f is set in falcon_cpuctl register.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_reset(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_falcon_mem_scrub
*
* Description: The falcon unit shall be able to check and return the falcon
* memory scrub status.
*
* Test Type: Feature, Error guessing, Error injection
*
* Targets: nvgpu_falcon_mem_scrub_wait, gops_falcon.is_falcon_scrubbing_done,
* gk20a_is_falcon_scrubbing_done
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_mem_scrub_wait with uninitialized falcon struct.
* - Verify that wait fails with -EINVAL return value.
* - Invoke nvgpu_falcon_mem_scrub_wait with initialized falcon struct where
* underlying falcon's memory scrub is completed.
* - Verify that wait succeeds with 0 return value.
* - Invoke nvgpu_falcon_mem_scrub_wait with initialized falcon struct where
* underlying falcon's memory scrub is yet to complete.
* - Verify that wait fails with -ETIMEDOUT return value.
* - Enable fault injection for the timer init call for branch coverage.
* - Verify that wait fails with -ETIMEDOUT return value.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_mem_scrub(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_falcon_idle
*
* Description: The falcon unit shall be able to check and return the falcon
* idle status.
*
* Test Type: Feature, Error guessing, Error injection
*
* Input: None.
*
* Targets: nvgpu_falcon_wait_idle, gops_falcon.is_falcon_idle,
* gk20a_is_falcon_idle
*
* Steps:
* - Invoke nvgpu_falcon_wait_idle with uninitialized falcon struct.
* - Verify that wait fails with -EINVAL return value.
* - Invoke nvgpu_falcon_wait_idle with initialized falcon struct where
* underlying falcon is idle.
* - Verify that wait succeeds with 0 return value.
* - Invoke nvgpu_falcon_wait_idle with initialized falcon struct where
* underlying falcon's ext units are busy but falcon CPU is idle.
* - Verify that wait fails with -ETIMEDOUT return value.
* - Invoke nvgpu_falcon_wait_idle with initialized falcon struct where
* underlying falcon is not idle.
* - Verify that wait fails with -ETIMEDOUT return value.
* - Enable fault injection for the timer init call for branch coverage.
* - Verify that wait fails with -ETIMEDOUT return value.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_idle(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_falcon_halt
*
* Description: The falcon unit shall be able to check and return the falcon
* halt status.
*
* Test Type: Feature, Error guessing, Error injection
*
* Targets: nvgpu_falcon_wait_for_halt, gops_falcon.is_falcon_cpu_halted,
* gk20a_is_falcon_cpu_halted
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_wait_for_halt with uninitialized falcon struct.
* - Verify that wait fails with -EINVAL return value.
* - Invoke nvgpu_falcon_wait_for_halt with initialized falcon struct where
* underlying falcon is halted.
* - Verify that wait succeeds with 0 return value.
* - Invoke nvgpu_falcon_wait_for_halt with initialized falcon struct where
* underlying falcon is not halted.
* - Verify that wait fails with -ETIMEDOUT return value.
* - Enable fault injection for the timer init call for branch coverage.
* - Verify that wait fails with -ETIMEDOUT return value.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_halt(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_falcon_mem_rw_init
*
* Description: The falcon unit shall be able to write to falcon's IMEM and
* DMEM.
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_falcon_copy_to_imem, nvgpu_falcon_copy_to_dmem,
* gops_falcon.copy_to_imem, gops_falcon.copy_to_dmem,
* gk20a_falcon_copy_to_imem, gk20a_falcon_copy_to_dmem
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_copy_to_imem and nvgpu_falcon_copy_to_dmem with
* uninitialized falcon struct with sample random data.
* - Verify that writes fail with -EINVAL return value in both cases.
* - Invoke nvgpu_falcon_copy_to_imem and nvgpu_falcon_copy_to_dmem with
* initialized falcon struct with sample random data.
* - Verify that writes succeed with 0 return value in both cases.
* - Invoke nvgpu_falcon_copy_to_imem and nvgpu_falcon_copy_to_dmem with
* initialized falcon struct with sample random data of size that is
* not multiple of words.
* - Verify that writes succeed with 0 return value in both cases.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_mem_rw_init(struct unit_module *m, struct gk20a *g,
void *__args);
/**
* Test specification for: test_falcon_mem_rw_range
*
* Description: The falcon unit shall be able to write to falcon's IMEM and
* DMEM in accessible range.
*
* Test Type: Feature, Boundary values
*
* Targets: nvgpu_falcon_copy_to_imem, nvgpu_falcon_copy_to_dmem,
* gops_falcon.copy_to_imem, gops_falcon.copy_to_dmem,
* gops_falcon.get_mem_size, gk20a_falcon_copy_to_imem,
* gk20a_falcon_copy_to_dmem, gk20a_falcon_get_mem_size
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_copy_to_imem and nvgpu_falcon_copy_to_dmem with
* initialized falcon struct with sample random data and valid range.
* - Verify that writes succeed with 0 return value in both cases.
* - Invoke nvgpu_falcon_copy_to_imem and nvgpu_falcon_copy_to_dmem with
* initialized falcon struct with sample random data and invalid range
* with valid and invalid offset.
* - Verify that writes fail with -EINVAL return value in both cases.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_mem_rw_range(struct unit_module *m, struct gk20a *g,
void *__args);
/**
* Test specification for: test_falcon_mem_rw_fault
*
* Description: The falcon unit shall fail the call to copy to DMEM when
* DMEMC reads return invalid value due to HW fault.
*
* Test Type: Error injection
*
* Targets: nvgpu_falcon_copy_to_dmem, gops_falcon.copy_to_dmem,
* gk20a_falcon_copy_to_dmem
*
* Input: None.
*
* Steps:
* - Enable the falcon DMEMC read fault.
* - Invoke nvgpu_falcon_copy_to_dmem with initialized falcon struct with
* sample random data and valid range.
* - Disable the falcon DMEMC read fault.
* - Verify that writes failed.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_mem_rw_fault(struct unit_module *m, struct gk20a *g,
void *__args);
/**
* Test specification for: test_falcon_mem_rw_aligned
*
* Description: The falcon unit shall be able to write to falcon's IMEM and
* DMEM only at aligned offsets.
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_falcon_copy_to_imem, nvgpu_falcon_copy_to_dmem,
* gops_falcon.copy_to_imem, gops_falcon.copy_to_dmem,
* gk20a_falcon_copy_to_imem, gk20a_falcon_copy_to_dmem
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_copy_to_imem and nvgpu_falcon_copy_to_dmem with
* initialized falcon struct with sample random data and 4-byte aligned
* offset.
* - Verify that writes succeed with 0 return value in both cases.
* - Invoke nvgpu_falcon_copy_to_imem and nvgpu_falcon_copy_to_dmem with
* initialized falcon struct with sample random data and non 4-byte
* aligned offset.
* - Verify that writes fail with -EINVAL return value in both cases.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_mem_rw_aligned(struct unit_module *m, struct gk20a *g,
void *__args);
/**
* Test specification for: test_falcon_mem_rw_zero
*
* Description: The falcon unit shall fail the API call to write zero
* bytes to falcon memory.
*
* Test Type: Error guessing
*
* Targets: nvgpu_falcon_copy_to_imem, nvgpu_falcon_copy_to_dmem,
* gops_falcon.copy_to_imem, gops_falcon.copy_to_dmem,
* gk20a_falcon_copy_to_imem, gk20a_falcon_copy_to_dmem
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_copy_to_imem and nvgpu_falcon_copy_to_dmem with
* initialized falcon struct with sample random data and zero bytes.
* - Verify that writes fail with -EINVAL return value in both cases.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_mem_rw_zero(struct unit_module *m, struct gk20a *g,
void *__args);
/**
* Test specification for: test_falcon_mailbox
*
* Description: The falcon unit shall read and write value of falcon's mailbox
* registers.
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_falcon_mailbox_read, nvgpu_falcon_mailbox_write,
* gops_falcon.mailbox_read, gops_falcon.mailbox_write,
* gk20a_falcon_mailbox_read, gk20a_falcon_mailbox_write
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_mailbox_read and nvgpu_falcon_mailbox_write with
* uninitialized falcon struct.
* - Verify that read returns zero.
* - Write a sample value to mailbox registers and read using the nvgpu APIs.
* - Verify the value by reading the registers through IO accessor.
* - Read/Write value from invalid mailbox register of initialized falcon.
* - Verify that read returns zero.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_mailbox(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_falcon_bootstrap
*
* Description: The falcon unit shall configure the bootstrap parameters into
* falcon memory and registers.
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_falcon_hs_ucode_load_bootstrap, gops_falcon.bootstrap,
* gk20a_falcon_bootstrap
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_hs_ucode_load_bootstrap with uninitialized
* falcon struct.
* - Verify that call fails with -EINVAL return value.
* - Fetch the ACR firmware from filesystem.
* - Invoke nvgpu_falcon_hs_ucode_load_bootstrap with initialized falcon struct.
* Fail the falcon reset by failing mem scrub wait.
* - Verify that bootstrap fails.
* - Invoke nvgpu_falcon_hs_ucode_load_bootstrap with initialized falcon struct.
* Fail the imem copy for non-secure code by setting invalid size in ucode
* header.
* - Verify that bootstrap fails.
* - Invoke nvgpu_falcon_hs_ucode_load_bootstrap with initialized falcon struct.
* Fail the imem copy for secure code by setting invalid size in ucode header.
* - Verify that bootstrap fails.
* - Invoke nvgpu_falcon_hs_ucode_load_bootstrap with initialized falcon struct.
* Fail the imem copy for secure code by setting invalid size in ucode header.
* - Verify that bootstrap fails.
* - Invoke nvgpu_falcon_hs_ucode_load_bootstrap with initialized falcon struct.
* Fail the dmem copy setting invalid dmem size in ucode header.
* - Verify that bootstrap fails.
* - Invoke nvgpu_falcon_hs_ucode_load_bootstrap with initialized falcon struct.
* - Verify that bootstrap succeeds and verify the expected state of registers
* falcon_dmactl_r, falcon_falcon_bootvec_r, falcon_falcon_cpuctl_r.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_bootstrap(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_falcon_mem_rw_unaligned_cpu_buffer
*
* Description: The falcon unit shall be able to read/write from/to falcon's
* IMEM and DMEM from memory buffer that is unaligned.
*
* Test Type: Feature
*
* Targets: nvgpu_falcon_copy_to_imem, nvgpu_falcon_copy_to_dmem,
* gops_falcon.copy_to_imem, gops_falcon.copy_to_dmem,
* gk20a_falcon_copy_to_imem, gk20a_falcon_copy_to_dmem
*
* Input: None.
*
* Steps:
* - Initialize unaligned random data memory buffer and set size.
* - Invoke nvgpu_falcon_copy_to_imem and nvgpu_falcon_copy_to_dmem with
* initialized falcon struct with above initialized sample random data
* and valid range.
* - Verify that writes succeed with 0 return value in both cases.
* - Write data of size 1K to valid range in imem/dmem from unaligned data
* to verify the buffering logic and cover branches in
* falcon_copy_to_dmem|imem_unaligned_src.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_mem_rw_unaligned_cpu_buffer(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_falcon_mem_rw_inval_port
*
* Description: The falcon unit shall not be able to read/write from/to falcon's
* memory from invalid port.
*
* Test Type: Error guessing
*
* Targets: nvgpu_falcon_copy_to_imem, gops_falcon.copy_to_imem,
* gops_falcon.get_ports_count, gk20a_falcon_copy_to_imem,
* gk20a_falcon_get_ports_count
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_copy_to_imem and nvgpu_falcon_copy_from_imem with
* initialized falcon struct with initialized sample random data, valid
* range but invalid port.
* - Verify that return value is -EINVAL.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_mem_rw_inval_port(struct unit_module *m, struct gk20a *g,
void *__args);
/**
* Test specification for: test_falcon_irq
*
* Description: The falcon unit shall be able to set or clear the falcon irq
* mask and destination registers for supported falcons.
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_falcon_set_irq, gops_falcon.set_irq,
* gk20a_falcon_set_irq
*
* Input: None.
*
* Steps:
* - Invoke nvgpu_falcon_set_irq with uninitialized falcon struct.
* - Invoke nvgpu_falcon_set_irq with initialized falcon struct where
* underlying falcon has interrupt support disabled.
* - Invoke nvgpu_falcon_set_irq to enable the interrupts with
* initialized falcon struct and sample interrupt mask and
* destination values and the underlying falcon has
* interrupt support enabled.
* - Verify that falcon_irqmset_r and falcon_irqdest_r are set as
* expected.
* - Invoke nvgpu_falcon_set_irq to disable the interrupts with
* initialized falcon struct and the underlying falcon has
* interrupt support enabled.
* - Verify that falcon_irqmclr_r is set to 0xffffffff.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_falcon_irq(struct unit_module *m, struct gk20a *g, void *__args);

View File

@@ -0,0 +1,255 @@
/*
* Copyright (c) 2019-2020, 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 <unit/io.h>
#include <nvgpu/falcon.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/kmem.h>
#include <nvgpu/hw/gm20b/hw_falcon_gm20b.h>
#include "falcon_utf.h"
#include <nvgpu/posix/posix-fault-injection.h>
struct nvgpu_posix_fault_inj *nvgpu_utf_falcon_memcpy_get_fault_injection(void)
{
struct nvgpu_posix_fault_inj_container *c =
nvgpu_posix_fault_injection_get_container();
return &c->falcon_memcpy_fi;
}
void nvgpu_utf_falcon_writel_access_reg_fn(struct gk20a *g,
struct utf_falcon *flcn,
struct nvgpu_reg_access *access)
{
u32 addr_mask = falcon_falcon_dmemc_offs_m() |
falcon_falcon_dmemc_blk_m();
u32 flcn_base;
u32 ctrl_r;
u32 offset;
flcn_base = flcn->flcn->flcn_base;
if (access->addr == (flcn_base + falcon_falcon_imemd_r(0))) {
ctrl_r = nvgpu_posix_io_readl_reg_space(g,
flcn_base + falcon_falcon_imemc_r(0));
if (ctrl_r & falcon_falcon_imemc_aincw_f(1)) {
offset = ctrl_r & addr_mask;
*((u32 *) ((u8 *)flcn->imem + offset)) = access->value;
offset += 4U;
ctrl_r &= ~(addr_mask);
ctrl_r |= offset;
nvgpu_posix_io_writel_reg_space(g,
flcn_base + falcon_falcon_imemc_r(0), ctrl_r);
}
} else if (access->addr == (flcn_base + falcon_falcon_dmemd_r(0))) {
ctrl_r = nvgpu_posix_io_readl_reg_space(g,
flcn_base + falcon_falcon_dmemc_r(0));
if (ctrl_r & falcon_falcon_dmemc_aincw_f(1)) {
offset = ctrl_r & addr_mask;
*((u32 *) ((u8 *)flcn->dmem + offset)) = access->value;
offset += 4U;
ctrl_r &= ~(addr_mask);
ctrl_r |= offset;
nvgpu_posix_io_writel_reg_space(g,
flcn_base + falcon_falcon_dmemc_r(0), ctrl_r);
}
} else if (access->addr == (flcn_base + falcon_falcon_cpuctl_r())) {
if (access->value == falcon_falcon_cpuctl_halt_intr_m()) {
access->value = nvgpu_posix_io_readl_reg_space(g,
access->addr);
access->value |= falcon_falcon_cpuctl_halt_intr_m();
nvgpu_posix_io_writel_reg_space(g, access->addr,
access->value);
} else if (access->value == falcon_falcon_cpuctl_startcpu_f(1)) {
access->value = nvgpu_posix_io_readl_reg_space(g,
access->addr);
access->value |= falcon_falcon_cpuctl_startcpu_f(1);
nvgpu_posix_io_writel_reg_space(g, access->addr,
access->value);
/* set falcon mailbox0 to value 0 */
nvgpu_posix_io_writel_reg_space(g, flcn_base +
falcon_falcon_mailbox0_r(), 0);
}
}
nvgpu_posix_io_writel_reg_space(g, access->addr, access->value);
}
void nvgpu_utf_falcon_readl_access_reg_fn(struct gk20a *g,
struct utf_falcon *flcn,
struct nvgpu_reg_access *access)
{
u32 addr_mask = falcon_falcon_dmemc_offs_m() |
falcon_falcon_dmemc_blk_m();
u32 flcn_base;
u32 ctrl_r;
u32 offset;
flcn_base = flcn->flcn->flcn_base;
if (access->addr == (flcn_base + falcon_falcon_imemd_r(0))) {
ctrl_r = nvgpu_posix_io_readl_reg_space(g,
flcn_base + falcon_falcon_imemc_r(0));
if (ctrl_r & falcon_falcon_dmemc_aincr_f(1)) {
offset = ctrl_r & addr_mask;
access->value = *((u32 *) ((u8 *)flcn->imem + offset));
offset += 4U;
ctrl_r &= ~(addr_mask);
ctrl_r |= offset;
nvgpu_posix_io_writel_reg_space(g,
flcn_base + falcon_falcon_imemc_r(0), ctrl_r);
}
} else if (access->addr == (flcn_base + falcon_falcon_dmemd_r(0))) {
ctrl_r = nvgpu_posix_io_readl_reg_space(g,
flcn_base + falcon_falcon_dmemc_r(0));
if (ctrl_r & falcon_falcon_dmemc_aincr_f(1)) {
offset = ctrl_r & addr_mask;
access->value = *((u32 *) ((u8 *)flcn->dmem + offset));
offset += 4U;
ctrl_r &= ~(addr_mask);
ctrl_r |= offset;
nvgpu_posix_io_writel_reg_space(g,
flcn_base + falcon_falcon_dmemc_r(0), ctrl_r);
}
} else if (access->addr == (flcn_base + falcon_falcon_dmemc_r(0))) {
ctrl_r = nvgpu_posix_io_readl_reg_space(g,
flcn_base + falcon_falcon_dmemc_r(0));
if (nvgpu_posix_fault_injection_handle_call(
nvgpu_utf_falcon_memcpy_get_fault_injection())) {
access->value = 0;
return;
}
access->value = ctrl_r & addr_mask;
} else {
access->value = nvgpu_posix_io_readl_reg_space(g, access->addr);
}
}
struct utf_falcon *nvgpu_utf_falcon_init(struct unit_module *m,
struct gk20a *g, u32 flcn_id)
{
struct utf_falcon *utf_flcn;
struct nvgpu_falcon *flcn;
u32 flcn_size;
u32 flcn_base;
u32 hwcfg_r, hwcfg1_r, ports;
if (nvgpu_falcon_sw_init(g, flcn_id) != 0) {
unit_err(m, "nvgpu Falcon init failed!\n");
return NULL;
}
flcn = nvgpu_falcon_get_instance(g, flcn_id);
utf_flcn = (struct utf_falcon *) malloc(sizeof(struct utf_falcon));
if (!utf_flcn) {
return NULL;
}
utf_flcn->flcn = flcn;
flcn_base = flcn->flcn_base;
if (nvgpu_posix_io_add_reg_space(g,
flcn_base,
UTF_FALCON_MAX_REG_OFFSET) != 0) {
unit_err(m, "Falcon add reg space failed!\n");
goto out;
}
/*
* Initialize IMEM & DMEM size that will be needed by NvGPU for
* bounds check.
*/
hwcfg_r = flcn_base + falcon_falcon_hwcfg_r();
flcn_size = UTF_FALCON_IMEM_DMEM_SIZE / FALCON_BLOCK_SIZE;
flcn_size = (flcn_size << 9) | flcn_size;
nvgpu_posix_io_writel_reg_space(g, hwcfg_r, flcn_size);
/* set imem and dmem ports count. */
hwcfg1_r = flcn_base + falcon_falcon_hwcfg1_r();
ports = (1 << 8) | (1 << 12);
nvgpu_posix_io_writel_reg_space(g, hwcfg1_r, ports);
utf_flcn->imem = (u32 *) nvgpu_kzalloc(g, UTF_FALCON_IMEM_DMEM_SIZE);
if (utf_flcn->imem == NULL) {
unit_err(m, "Falcon imem alloc failed!\n");
goto out_reg_space;
}
utf_flcn->dmem = (u32 *) nvgpu_kzalloc(g, UTF_FALCON_IMEM_DMEM_SIZE);
if (utf_flcn->dmem == NULL) {
unit_err(m, "Falcon dmem alloc failed!\n");
goto free_imem;
}
return utf_flcn;
free_imem:
nvgpu_kfree(g, utf_flcn->imem);
out_reg_space:
nvgpu_posix_io_delete_reg_space(g, flcn_base);
out:
nvgpu_falcon_sw_free(g, flcn_id);
free(utf_flcn);
return NULL;
}
void nvgpu_utf_falcon_free(struct gk20a *g, struct utf_falcon *utf_flcn)
{
if (utf_flcn == NULL || utf_flcn->flcn == NULL)
return;
nvgpu_kfree(g, utf_flcn->dmem);
nvgpu_kfree(g, utf_flcn->imem);
nvgpu_posix_io_delete_reg_space(g, utf_flcn->flcn->flcn_base);
nvgpu_falcon_sw_free(g, utf_flcn->flcn->flcn_id);
free(utf_flcn);
}
void nvgpu_utf_falcon_set_dmactl(struct gk20a *g, struct utf_falcon *utf_flcn,
u32 reg_data)
{
u32 flcn_base;
flcn_base = utf_flcn->flcn->flcn_base;
nvgpu_posix_io_writel_reg_space(g,
flcn_base + falcon_falcon_dmactl_r(), reg_data);
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2019-2020, 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 __FALCON_UTF_H__
#define __FALCON_UTF_H__
#include <nvgpu/posix/types.h>
#include <nvgpu/posix/io.h>
#define UTF_FALCON_MAX_REG_OFFSET 0x400
#define UTF_FALCON_IMEM_DMEM_SIZE (127 * 1024)
struct gk20a;
struct nvgpu_falcon;
struct utf_falcon {
struct nvgpu_falcon *flcn;
u32 *imem;
u32 *dmem;
};
struct nvgpu_posix_fault_inj *nvgpu_utf_falcon_memcpy_get_fault_injection(void);
void nvgpu_utf_falcon_writel_access_reg_fn(struct gk20a *g,
struct utf_falcon *flcn,
struct nvgpu_reg_access *access);
void nvgpu_utf_falcon_readl_access_reg_fn(struct gk20a *g,
struct utf_falcon *flcn,
struct nvgpu_reg_access *access);
struct utf_falcon *nvgpu_utf_falcon_init(struct unit_module *m,
struct gk20a *g, u32 flcn_id);
void nvgpu_utf_falcon_free(struct gk20a *g, struct utf_falcon *utf_flcn);
void nvgpu_utf_falcon_set_dmactl(struct gk20a *g, struct utf_falcon *utf_flcn,
u32 reg_data);
#endif

View File

@@ -0,0 +1,28 @@
#
# Copyright (c) 2019-2020, 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.
#
nvgpu_utf_falcon_free
nvgpu_utf_falcon_init
nvgpu_utf_falcon_readl_access_reg_fn
nvgpu_utf_falcon_set_dmactl
nvgpu_utf_falcon_writel_access_reg_fn
nvgpu_utf_falcon_memcpy_get_fault_injection

View File

@@ -0,0 +1,27 @@
# 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 = fb_fusa.o fb_gv11b_fusa.o fb_gm20b_fusa.o fb_mmu_fault_gv11b_fusa.o \
fb_intr_gv11b_fusa.o
MODULE = fb
include ../Makefile.units

View File

@@ -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=fb
include $(NV_COMPONENT_DIR)/../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,25 @@
################################### 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=fb
NVGPU_UNIT_SRCS=fb_fusa.c fb_gv11b_fusa.c fb_gm20b_fusa.c \
fb_mmu_fault_gv11b_fusa.c fb_intr_gv11b_fusa.c
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,159 @@
/*
* Copyright (c) 2019-2020, 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/io.h>
#include "hal/fb/intr/fb_intr_gv11b.h"
#include <nvgpu/hw/gv11b/hw_fb_gv11b.h>
#include <nvgpu/hw/gv11b/hw_mc_gv11b.h>
#include "fb_fusa.h"
static bool intercept_mmu_invalidate;
static u32 intercept_fb_mmu_ctrl_r;
void helper_intercept_mmu_write(u32 val)
{
intercept_fb_mmu_ctrl_r = val;
intercept_mmu_invalidate = true;
}
/*
* Write callback (for all nvgpu_writel calls).
*/
static void writel_access_reg_fn(struct gk20a *g,
struct nvgpu_reg_access *access)
{
if (intercept_mmu_invalidate &&
(access->addr == fb_mmu_invalidate_pdb_r())) {
intercept_mmu_invalidate = false;
nvgpu_writel(g, fb_mmu_ctrl_r(), intercept_fb_mmu_ctrl_r);
}
nvgpu_posix_io_writel_reg_space(g, access->addr, access->value);
nvgpu_posix_io_record_access(g, access);
}
/*
* Read callback, similar to the write callback above.
*/
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);
}
/*
* Define all the callbacks to be used during the test. Typically all
* write operations use the same callback, likewise for all read operations.
*/
static struct nvgpu_posix_io_callbacks fb_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,
};
static int fb_gv11b_init(struct unit_module *m, struct gk20a *g, void *args)
{
nvgpu_posix_register_io(g, &fb_callbacks);
/* Register space: FB */
if (nvgpu_posix_io_add_reg_space(g, fb_niso_intr_r(), SZ_4K) != 0) {
unit_return_fail(m, "nvgpu_posix_io_add_reg_space failed FB\n");
}
/* Register space: MC_INTR */
if (nvgpu_posix_io_add_reg_space(g, mc_intr_r(0), SZ_1K) != 0) {
unit_return_fail(m, "nvgpu_posix_io_add_reg_space failed MC\n");
}
/* Register space: HSHUB */
if (nvgpu_posix_io_add_reg_space(g, fb_hshub_num_active_ltcs_r(),
SZ_256) != 0) {
unit_return_fail(m,
"nvgpu_posix_io_add_reg_space failed HSHUB\n");
}
/* Register space: FBHUB */
if (nvgpu_posix_io_add_reg_space(g, fb_fbhub_num_active_ltcs_r(),
SZ_256) != 0) {
unit_return_fail(m,
"nvgpu_posix_io_add_reg_space failed FBHUB\n");
}
return UNIT_SUCCESS;
}
static int fb_gv11b_cleanup(struct unit_module *m, struct gk20a *g, void *args)
{
/* Unregister space: FB */
nvgpu_posix_io_delete_reg_space(g, fb_niso_intr_r());
nvgpu_posix_io_delete_reg_space(g, mc_intr_r(0));
nvgpu_posix_io_delete_reg_space(g, fb_hshub_num_active_ltcs_r());
nvgpu_posix_io_delete_reg_space(g, fb_fbhub_num_active_ltcs_r());
return UNIT_SUCCESS;
}
struct unit_module_test fb_tests[] = {
UNIT_TEST(fb_gv11b_init, fb_gv11b_init, NULL, 0),
UNIT_TEST(fb_gv11b_init_test, fb_gv11b_init_test, NULL, 0),
UNIT_TEST(fb_gm20b_tlb_invalidate_test, fb_gm20b_tlb_invalidate_test,
NULL, 0),
UNIT_TEST(fb_gm20b_mmu_ctrl_test, fb_gm20b_mmu_ctrl_test, NULL, 0),
UNIT_TEST(fb_mmu_fault_gv11b_init_test, fb_mmu_fault_gv11b_init_test,
NULL, 0),
UNIT_TEST(fb_mmu_fault_gv11b_buffer_test,
fb_mmu_fault_gv11b_buffer_test, NULL, 0),
UNIT_TEST(fb_mmu_fault_gv11b_snap_reg, fb_mmu_fault_gv11b_snap_reg,
NULL, 0),
UNIT_TEST(fb_mmu_fault_gv11b_handle_fault,
fb_mmu_fault_gv11b_handle_fault, NULL, 0),
UNIT_TEST(fb_mmu_fault_gv11b_handle_bar2_fault,
fb_mmu_fault_gv11b_handle_bar2_fault, NULL, 2),
UNIT_TEST(fb_intr_gv11b_init_test, fb_intr_gv11b_init_test, NULL, 0),
UNIT_TEST(fb_intr_gv11b_isr_test, fb_intr_gv11b_isr_test, NULL, 0),
UNIT_TEST(fb_intr_gv11b_ecc_test_L2TLB, fb_intr_gv11b_ecc_test,
(void *) TEST_ECC_L2TLB, 0),
UNIT_TEST(fb_intr_gv11b_ecc_test_HUBTLB, fb_intr_gv11b_ecc_test,
(void *) TEST_ECC_HUBTLB, 0),
UNIT_TEST(fb_intr_gv11b_ecc_test_FILLUNIT, fb_intr_gv11b_ecc_test,
(void *) TEST_ECC_FILLUNIT, 0),
UNIT_TEST(fb_gv11b_cleanup, fb_gv11b_cleanup, NULL, 0),
};
UNIT_MODULE(fb, fb_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,406 @@
/*
* 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_FB_H
#define UNIT_NVGPU_FB_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-fb
* @{
*
* Software Unit Test Specification for nvgpu.hal.fb
*/
/**
* Test specification for: fb_gv11b_init_test
*
* Description: Tests the init HALs for GV11B.
*
* Targets: nvgpu_ecc_init_support, gv11b_fb_init_hw, gv11b_fb_init_fs_state,
* gv11b_fb_ecc_init, gv11b_fb_ecc_free, gops_fb.fb_ecc_free,
* gops_fb.fb_ecc_init, gops_ecc.ecc_init_support, gops_fb.init_hw,
* gops_fb.init_fs_state, gm20b_fb_init_hw
*
* Test Type: Feature, Other (setup), Error injection
*
* Input: None
*
* Steps:
* - Set up the ops function pointer for all the HALs under test.
* - Initialize the g->mm structure with arbitrary addresses.
* - Call the ecc_init_support HAL to initialize ECC support.
* - Call the init_hw HAL and ensure the FB_NISO mask was set.
* - Call the init_fs_state HAL and ensure atomic mode was set in the MMU
* control register.
* - Perform dynamic memory error injection on the fb_ecc_init HAL to ensure
* it fails as expected.
* - Call the fb_ecc_init HAL and ensure it succeeds.
* - Call the fb_ecc_free HAL to free dynamic memory.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int fb_gv11b_init_test(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: fb_gm20b_tlb_invalidate_test
*
* Description: .
*
* Targets: gm20b_fb_tlb_invalidate, gops_fb.tlb_invalidate
*
* Test Type: Feature, Error injection
*
* Input: None
*
* Steps:
* - Initialize ops.fb.tlb_invalidate pointer to gm20b_fb_tlb_invalidate HAL.
* - Create a test nvgpu_mem PDB with SYSMEM aperture.
* - While the NVGPU is powered off, call gm20b_fb_tlb_invalidate and ensure
* it returned success.
* - The power on state of NVGPU.
* - Enable timer error injection (1st occurnce), call gm20b_fb_tlb_invalidate
* and ensure it failed.
* - Call gm20b_fb_tlb_invalidate again and check that it still failed (because
* the fb_mmu_ctrl_r register is not set properly)
* - Set the fb_mmu_ctrl_pri_fifo_space_v bit in fb_mmu_ctrl_r register.
* - Enable timer error injection (2nd occurnce), call gm20b_fb_tlb_invalidate
* and ensure it failed.
* - Using an helper during register writes, intercept writes to fb_mmu_ctrl_r
* to cause a timeout after the MMU invalidate. Ensure that
* gm20b_fb_tlb_invalidate returns a failure.
* - Set the fb_mmu_ctrl_pri_fifo_space_v bit again, and set the intercept
* helper to write the fb_mmu_ctrl_pri_fifo_empty_v bit upon a write to
* fb_mmu_ctrl_r. Ensure that gm20b_fb_tlb_invalidate succeeds.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int fb_gm20b_tlb_invalidate_test(struct unit_module *m, struct gk20a *g,
void *args);
/**
* Test specification for: fb_gm20b_mmu_ctrl_test
*
* Description: Test GM20B HALs targeting MMU features.
*
* Targets: gm20b_fb_mmu_ctrl, gm20b_fb_mmu_debug_ctrl, gm20b_fb_mmu_debug_wr,
* gm20b_fb_mmu_debug_rd, gm20b_fb_vpr_info_fetch, gm20b_fb_dump_vpr_info,
* gm20b_fb_dump_wpr_info, gm20b_fb_read_wpr_info, gops_fb.mmu_ctrl,
* gops_fb.mmu_debug_wr, gops_fb.mmu_debug_ctrl, gops_fb.mmu_debug_rd,
* gops_fb.vpr_info_fetch, gops_fb.dump_wpr_info, gops_fb.dump_vpr_info,
* gops_fb.read_wpr_info
*
* Test Type: Feature, Error injection
*
* Input: None
*
* Steps:
* - Set up the ops function pointer for all the HALs under test.
* - Program an arbitrary value in the fb_mmu_ctrl_r register and ensure the
* gm20b_fb_mmu_ctrl HAL returns the same value.
* - Program an arbitrary value in the fb_mmu_debug_ctrl_r register and ensure
* the gm20b_fb_mmu_debug_ctrl HAL returns the same value.
* - Program an arbitrary value in the fb_mmu_debug_wr_r register and ensure the
* gm20b_fb_mmu_debug_wr HAL returns the same value.
* - Program an arbitrary value in the fb_mmu_debug_rd_r register and ensure the
* gm20b_fb_mmu_debug_rd HAL returns the same value.
* - Call the VPR/WPR dump operations for code coverage. Ensure that none of
* those operations cause a crash.
* - Enable timer error injection (1st occurnce), call gm20b_fb_vpr_info_fetch
* and ensure it failed.
* - Write in the fb_mmu_vpr_info register so that calling
* gm20b_fb_vpr_info_fetch triggers timeout in the
* gm20b_fb_vpr_info_fetch_wait function. Ensure the return values reflects
* a timeout.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int fb_gm20b_mmu_ctrl_test(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: fb_mmu_fault_gv11b_init_test
*
* Description: Init test to setup HAL pointers for FB_MMU fault testing.
*
* Targets: gv11b_fb_read_mmu_fault_buffer_size,
* gv11b_fb_read_mmu_fault_buffer_put, gv11b_fb_write_mmu_fault_status,
* gv11b_fb_read_mmu_fault_buffer_get
*
* Test Type: Init
*
* Input: None
*
* Steps:
* - Set up the ops function pointer for all the HALs under test.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int fb_mmu_fault_gv11b_init_test(struct unit_module *m, struct gk20a *g,
void *args);
/**
* Test specification for: fb_mmu_fault_gv11b_buffer_test
*
* Description: Ensure all HAL functions work without causing an ABORT.
*
* Targets: gv11b_fb_is_fault_buf_enabled, gv11b_fb_fault_buffer_get_ptr_update,
* gv11b_fb_write_mmu_fault_buffer_size, gv11b_fb_fault_buf_set_state_hw,
* gv11b_fb_read_mmu_fault_status, gv11b_fb_fault_buf_configure_hw,
* gv11b_fb_is_fault_buffer_empty, gv11b_fb_read_mmu_fault_addr_lo_hi,
* gops_fb.fault_buf_configure_hw, gops_fb.fault_buf_set_state_hw,
* gv11b_fb_fault_buffer_size_val, gv11b_fb_read_mmu_fault_inst_lo_hi,
* gv11b_fb_read_mmu_fault_info
*
* Test Type: Feature, Error injection
*
* Input: fb_mmu_fault_gv11b_init_test
*
* Steps:
* - Call gv11b_fb_fault_buffer_get_ptr_update.
* - Set the overflow bit in the fb_mmu_fault_buffer_get_r(0) register, and call
* gv11b_fb_fault_buffer_get_ptr_update.
* - Call gv11b_fb_fault_buffer_size_val and check that the fault buffer is
* empty.
* - Call the gv11b_fb_fault_buf_configure_hw HAL and enable fault buffer.
* - Enable fault buffer again which shouldn't cause any crash.
* - While trying to disable the fault buffer, trigger a failure of
* nvgpu_timeout_init.
* - Disable the fault buffer.
* - Enable fault buffer, set the busy bit in fb_mmu_fault_status_r register,
* disable the fault buffer which should cause an internal timeout. Ensure
* that the fault buffer is disabled anyway.
* - Write test values in the fb_mmu_fault_addr_lo_r / fb_mmu_fault_addr_hi_r
* registers, call gv11b_fb_read_mmu_fault_addr_lo_hi and ensure the
* returned values match the test values.
* - Write test values in the fb_mmu_fault_inst_lo_r / fb_mmu_fault_inst_hi_r
* registers, call gv11b_fb_read_mmu_fault_inst_lo_hi and ensure the
* returned values match the test values.
* - Call the gv11b_fb_read_mmu_fault_info HAL and ensure it returns the same
* value as in the fb_mmu_fault_info_r register.
* - Call the gv11b_fb_write_mmu_fault_status HAL to write a test value, then
* read the fb_mmu_fault_status_r register to ensure it is the same value.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int fb_mmu_fault_gv11b_buffer_test(struct unit_module *m, struct gk20a *g,
void *args);
/**
* Test specification for: fb_mmu_fault_gv11b_snap_reg
*
* Description: Test that gv11b_mm_copy_from_fault_snap_reg behaves correctly
* if the reported fault is valid/invalid.
*
* Targets: gv11b_mm_copy_from_fault_snap_reg
*
* Test Type: Feature
*
* Input: fb_mmu_fault_gv11b_init_test
*
* Steps:
* - Create a test mmu_fault_info instance.
* - Call gv11b_mm_copy_from_fault_snap_reg with an invalid fault bit and
* ensure the chid of the mmu_fault_info was just set to a default value of 0.
* - Call gv11b_mm_copy_from_fault_snap_reg again with a valid fault bit and
* ensure the chid of the mmu_fault_info is now set to
* NVGPU_INVALID_CHANNEL_ID.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int fb_mmu_fault_gv11b_snap_reg(struct unit_module *m, struct gk20a *g,
void *args);
/**
* Test specification for: fb_mmu_fault_gv11b_handle_fault
*
* Description: Test the gv11b_fb_handle_mmu_fault HAL for all supported
* interrupt statuses.
*
* Targets: gv11b_fb_handle_mmu_fault, gv11b_fb_fault_buf_set_state_hw
*
* Test Type: Feature
*
* Input: fb_mmu_fault_gv11b_init_test
*
* Steps:
* - Call gv11b_fb_handle_mmu_fault with an interrupt source set to "other"
* and ensure it was handled by checking the "valid_clear" bit of the
* fb_mmu_fault_status_r register.
* - Enable the fault buffer.
* - Set interrupt source as dropped and ensure it is handled by
* gv11b_fb_handle_mmu_fault.
* - Repeat with a source as non-replayable.
* - Repeat with a source as non-replayable and overflow.
* - Repeat with a source as overflow and corrupted getptr.
* - Disable the fault buffer.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int fb_mmu_fault_gv11b_handle_fault(struct unit_module *m, struct gk20a *g,
void *args);
/**
* Test specification for: fb_mmu_fault_gv11b_handle_bar2_fault
*
* Description: Test the gv11b_fb_handle_bar2_fault HAL for all supported
* interrupt statuses.
*
* Targets: gv11b_fb_handle_bar2_fault, gv11b_fb_mmu_fault_info_dump,
* gv11b_fb_fault_buf_set_state_hw
*
* Test Type: Feature, Error injection
*
* Input: fb_mmu_fault_gv11b_init_test
*
* Steps:
* - Create zero'ed test instances of mmu_fault_info and nvgpu_channel.
* - Call gv11b_fb_handle_bar2_fault with a fault_status of 0.
* - Ensure the gv11b_fb_mmu_fault_info_dump HAL does not cause a crash when
* called with a NULL pointer or a zero'ed out mmu_fault_info structure.
* - Set the minimum set of properties in the mmu_fault_info structure (valid
* and a pointer to the channel)
* - Call the gv11b_fb_mmu_fault_info_dump and ensure it doesn't cause a crash.
* - Set the fault_status to non-replayable and call gv11b_fb_handle_bar2_fault.
* - Set the g->ops.bus.bar2_bind HAL to report a failure and call
* gv11b_fb_handle_bar2_fault again.
* - Repeat with the fault buffer disabled.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int fb_mmu_fault_gv11b_handle_bar2_fault(struct unit_module *m, struct gk20a *g,
void *args);
/**
* Test specification for: fb_intr_gv11b_init_test
*
* Description: Init test to setup HAL pointers for FB_INTR testing.
*
* Targets: None
*
* Test Type: Init
*
* Input: None
*
* Steps:
* - Set up the ops function pointer for all the HALs under test.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int fb_intr_gv11b_init_test(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: fb_intr_gv11b_isr_test
*
* Description: Test ISR handling with all supported types of interrupts.
*
* Targets: gv11b_fb_intr_enable, gv11b_fb_intr_disable, gv11b_fb_intr_isr,
* gv11b_fb_intr_is_mmu_fault_pending, gops_fb_intr.is_mmu_fault_pending,
* gops_fb_intr.enable, gops_fb_intr.disable, gops_fb_intr.isr
*
* Test Type: Feature
*
* Input: fb_intr_gv11b_init_test
*
* Steps:
* - Mask all interrupts in the fb_niso_intr_en_set_r register.
* - Call the gv11b_fb_intr_enable HAL and ensure several interrupts are
* unmasked.
* - Set the fb_niso_intr_r register to 0 (no interrupt), and ensure that
* gv11b_fb_intr_is_mmu_fault_pending indicates that no fault is pending.
* - Call the gv11b_fb_intr_isr HAL.
* - Set interrupt source as "access counter notify/error" and call the
* gv11b_fb_intr_isr HAL (this will only cause a nvgpu_info call)
* - Set interrupt source as "MMU fault" and ensure that
* gv11b_fb_intr_is_mmu_fault_pending indicates that a fault is pending.
* - Set interrupt source as "ECC fault" and call the gv11b_fb_intr_isr HAL
* (further ECC testing is done in other tests).
* - Use the gv11b_fb_intr_disable HAL to disable interrupts.
* - Ensure that what was written in the clear register matches the interrupts
* that were enabled at the beginning of this test.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int fb_intr_gv11b_isr_test(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: fb_intr_gv11b_ecc_test
*
* Description: Tests handling of ECC errors.
*
* Targets: gv11b_fb_ecc_init, gv11b_fb_intr_isr, gv11b_fb_intr_handle_ecc,
* gv11b_fb_ecc_free
*
* Test Type: Feature
*
* Input: fb_intr_gv11b_init_test, args as a subcase with one of these values:
* - TEST_ECC_L2TLB
* - TEST_ECC_HUBTLB
* - TEST_ECC_FILLUNIT
*
* Steps:
* - Based on the subcase passed as an argument to this test, select the
* appropriate values for each HW unit:
* - Address of the status register
* - Address of the corrected error count register
* - Address of the uncorrected error count register
* - Expected status mask for corrected errors
* - Expected status mask for uncorrected errors
* - Expected status mask for corrected errors overflow
* - Expected status mask for uncorrected errors overflow
* - Call the gv11b_fb_ecc_init HAL.
* - Test the hanlding of ISRs in the following cases:
* - Corrected error
* - Uncorrected error
* - Corrected error and overflow (with >0 number of errors)
* - Uncorrected error and overflow (with >0 number of errors)
* - Corrected and uncorrected with overflow and 0 errors.
* - In the case of FILLUNIT, also test the case of corrected and uncorrected
* PDE0 errors.
* - Clear the interrupt status register.
* - Call the gv11b_fb_ecc_free HAL.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int fb_intr_gv11b_ecc_test(struct unit_module *m, struct gk20a *g, void *args);
/* Values below are used by the fb_intr_gv11b_ecc_test test. */
#define TEST_ECC_L2TLB 1U
#define TEST_ECC_HUBTLB 2U
#define TEST_ECC_FILLUNIT 3U
/* Helper function to intercept writes to the MMU status register. */
void helper_intercept_mmu_write(u32 val);
/** @} */
#endif /* UNIT_NVGPU_FB_H */

View File

@@ -0,0 +1,192 @@
/*
* 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/io.h>
#include <nvgpu/nvgpu_init.h>
#include "hal/mc/mc_gp10b.h"
#include "hal/fb/fb_gm20b.h"
#include "hal/fb/fb_gv11b.h"
#include "hal/fb/intr/fb_intr_gv11b.h"
#include <nvgpu/hw/gv11b/hw_fb_gv11b.h>
#include "fb_fusa.h"
#define TEST_REG_VALUE 0x8080A0A0
int fb_gm20b_tlb_invalidate_test(struct unit_module *m, struct gk20a *g,
void *args)
{
int err;
struct nvgpu_mem pdb = {0};
struct nvgpu_posix_fault_inj *timer_fi =
nvgpu_timers_get_fault_injection();
/* Define the operations being tested in this unit test */
g->ops.fb.tlb_invalidate = gm20b_fb_tlb_invalidate;
/* Setup PDB */
pdb.aperture = APERTURE_SYSMEM;
/* First NVGPU is powered off */
err = g->ops.fb.tlb_invalidate(g, &pdb);
if (err != 0) {
unit_return_fail(m, "tlb_invalidate failed (1)\n");
}
/* Set NVGPU as powered on */
g->power_on_state = NVGPU_STATE_POWERED_ON;
/* Timeout init fault injection (MMU FIFO space) */
nvgpu_posix_enable_fault_injection(timer_fi, true, 0);
err = g->ops.fb.tlb_invalidate(g, &pdb);
if (err != -ETIMEDOUT) {
unit_return_fail(m,
"tlb_invalidate did not fail as expected (1)\n");
}
nvgpu_posix_enable_fault_injection(timer_fi, false, 0);
/* Timeout fail on fb_mmu_ctrl_r() read */
err = g->ops.fb.tlb_invalidate(g, &pdb);
if (err != -ETIMEDOUT) {
unit_return_fail(m,
"tlb_invalidate did not fail as expected (2)\n");
}
/*
* Prevent timeout on fb_mmu_ctrl_r() by setting a non-zero value in
* the fb_mmu_ctrl_pri_fifo_space_v field.
*/
nvgpu_writel(g, fb_mmu_ctrl_r(), 1 << 16U);
/* Timeout init fault injection (MMU invalidate) */
nvgpu_posix_enable_fault_injection(timer_fi, true, 1);
err = g->ops.fb.tlb_invalidate(g, &pdb);
if (err != -ETIMEDOUT) {
unit_return_fail(m,
"tlb_invalidate did not fail as expected (3)\n");
}
nvgpu_posix_enable_fault_injection(timer_fi, false, 0);
/*
* Timeout on fb_mmu_ctrl_r read after MMU invalidate (does not return
* a failure)
*/
helper_intercept_mmu_write(0);
err = g->ops.fb.tlb_invalidate(g, &pdb);
if (err != 0) {
unit_return_fail(m, "tlb_invalidate failed (2)\n");
}
/* Success */
nvgpu_writel(g, fb_mmu_ctrl_r(), 1 << 16U);
helper_intercept_mmu_write(1 << 15U);
err = g->ops.fb.tlb_invalidate(g, &pdb);
if (err != 0) {
unit_return_fail(m, "tlb_invalidate failed (3)\n");
}
return UNIT_SUCCESS;
}
int fb_gm20b_mmu_ctrl_test(struct unit_module *m, struct gk20a *g, void *args)
{
int err;
u64 wpr_base, wpr_size;
struct nvgpu_posix_fault_inj *timer_fi =
nvgpu_timers_get_fault_injection();
/* Define the operations being tested in this unit test */
g->ops.fb.mmu_ctrl = gm20b_fb_mmu_ctrl;
g->ops.fb.mmu_debug_ctrl = gm20b_fb_mmu_debug_ctrl;
g->ops.fb.mmu_debug_wr = gm20b_fb_mmu_debug_wr;
g->ops.fb.mmu_debug_rd = gm20b_fb_mmu_debug_rd;
g->ops.fb.vpr_info_fetch = gm20b_fb_vpr_info_fetch;
g->ops.fb.dump_vpr_info = gm20b_fb_dump_vpr_info;
g->ops.fb.dump_wpr_info = gm20b_fb_dump_wpr_info;
g->ops.fb.read_wpr_info = gm20b_fb_read_wpr_info;
/* g->ops.mmu_ctrl must return the value in fb_mmu_ctrl_r */
nvgpu_writel(g, fb_mmu_ctrl_r(), TEST_REG_VALUE);
if (g->ops.fb.mmu_ctrl(g) != TEST_REG_VALUE) {
unit_return_fail(m, "ops.mmu_ctrl: incorrect value\n");
}
/* g->ops.mmu_debug_ctrl must return the value in fb_mmu_debug_ctrl_r */
nvgpu_writel(g, fb_mmu_debug_ctrl_r(), TEST_REG_VALUE);
if (g->ops.fb.mmu_debug_ctrl(g) != TEST_REG_VALUE) {
unit_return_fail(m, "ops.mmu_debug_ctrl: incorrect value\n");
}
/* g->ops.mmu_debug_wr must return the value in fb_mmu_debug_wr_r */
nvgpu_writel(g, fb_mmu_debug_wr_r(), TEST_REG_VALUE);
if (g->ops.fb.mmu_debug_wr(g) != TEST_REG_VALUE) {
unit_return_fail(m, "ops.mmu_debug_wr: incorrect value\n");
}
/* g->ops.mmu_debug_rd must return the value in fb_mmu_debug_rd_r */
nvgpu_writel(g, fb_mmu_debug_rd_r(), TEST_REG_VALUE);
if (g->ops.fb.mmu_debug_rd(g) != TEST_REG_VALUE) {
unit_return_fail(m, "ops.mmu_debug_rd: incorrect value\n");
}
/* For code coverage, run the VPR/WPR dump ops */
g->ops.fb.dump_vpr_info(g);
g->ops.fb.dump_wpr_info(g);
g->ops.fb.read_wpr_info(g, &wpr_base, &wpr_size);
g->ops.fb.vpr_info_fetch(g);
/* Error injection for g->ops.fb.vpr_info_fetch */
nvgpu_posix_enable_fault_injection(timer_fi, true, 0);
err = g->ops.fb.vpr_info_fetch(g);
nvgpu_posix_enable_fault_injection(timer_fi, false, 0);
if (err != -ETIMEDOUT) {
unit_return_fail(m,
"vpr_info_fetch did not fail as expected (1)\n");
}
nvgpu_posix_enable_fault_injection(timer_fi, true, 1);
err = g->ops.fb.vpr_info_fetch(g);
nvgpu_posix_enable_fault_injection(timer_fi, false, 0);
if (err != -ETIMEDOUT) {
unit_return_fail(m,
"vpr_info_fetch did not fail as expected (2)\n");
}
/*
* Trigger timeout in the gm20b_fb_vpr_info_fetch_wait function on
* fb_mmu_vpr_info_fetch_v(val) == fb_mmu_vpr_info_fetch_false_v()
*/
nvgpu_writel(g, fb_mmu_vpr_info_r(), 1 << 2U);
err = g->ops.fb.vpr_info_fetch(g);
if (err != -ETIMEDOUT) {
unit_return_fail(m,
"vpr_info_fetch did not fail as expected (3)\n");
}
return UNIT_SUCCESS;
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2019-2021, 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/io.h>
#include <nvgpu/cic.h>
#include <nvgpu/nvgpu_init.h>
#include "hal/mc/mc_gp10b.h"
#include "hal/fb/fb_gm20b.h"
#include "hal/fb/fb_gv11b.h"
#include "hal/fb/ecc/fb_ecc_gv11b.h"
#include "hal/fb/intr/fb_intr_gv11b.h"
#include "hal/fb/intr/fb_intr_ecc_gv11b.h"
#include "hal/cic/cic_gv11b.h"
#include <nvgpu/hw/gv11b/hw_fb_gv11b.h>
#include "fb_fusa.h"
int fb_gv11b_init_test(struct unit_module *m, struct gk20a *g, void *args)
{
int err;
struct nvgpu_posix_fault_inj *kmem_fi =
nvgpu_kmem_get_fault_injection();
/* Define the operations being targeted in this unit test */
g->ops.ecc.ecc_init_support = nvgpu_ecc_init_support;
g->ops.fb.init_hw = gv11b_fb_init_hw;
g->ops.fb.init_fs_state = gv11b_fb_init_fs_state;
g->ops.fb.set_atomic_mode = gv11b_fb_set_atomic_mode;
g->ops.fb.ecc.init = gv11b_fb_ecc_init;
g->ops.fb.ecc.free = gv11b_fb_ecc_free;
g->ops.fb.ecc.l2tlb_error_mask = gv11b_fb_ecc_l2tlb_error_mask;
g->ops.fb.intr.handle_ecc = gv11b_fb_intr_handle_ecc,
g->ops.fb.intr.handle_ecc_l2tlb = gv11b_fb_intr_handle_ecc_l2tlb,
g->ops.fb.intr.handle_ecc_hubtlb = gv11b_fb_intr_handle_ecc_hubtlb,
g->ops.fb.intr.handle_ecc_fillunit = gv11b_fb_intr_handle_ecc_fillunit,
/* Other HALs */
g->ops.mc.intr_stall_unit_config = mc_gp10b_intr_stall_unit_config;
g->ops.mc.intr_nonstall_unit_config =
mc_gp10b_intr_nonstall_unit_config;
g->ops.fb.intr.enable = gv11b_fb_intr_enable;
g->ops.cic.init = gv11b_cic_init;
g->ops.cic.report_err = nvgpu_cic_report_err_safety_services;
/*
* Define some arbitrary addresses for test purposes.
* Note: no need to malloc any memory as this unit only needs to trigger
* MMU faults via register mocking. No other memory accesses are done.
*/
g->mm.sysmem_flush.cpu_va = (void *) 0x10000000;
g->mm.mmu_wr_mem.cpu_va = (void *) 0x20000000;
g->mm.mmu_wr_mem.aperture = APERTURE_SYSMEM;
g->mm.mmu_rd_mem.cpu_va = (void *) 0x30000000;
g->mm.mmu_rd_mem.aperture = APERTURE_SYSMEM;
if (nvgpu_cic_init_common(g) != 0) {
unit_return_fail(m, "CIC init failed\n");
}
g->ops.ecc.ecc_init_support(g);
nvgpu_writel(g, fb_niso_intr_en_set_r(0), 0);
g->ops.fb.init_hw(g);
/* Ensure that g->ops.fb.intr.enable set up a mask */
if (nvgpu_readl(g, fb_niso_intr_en_set_r(0)) == 0) {
unit_return_fail(m, "FB_NISO mask not set\n");
}
g->ops.fb.init_fs_state(g);
g->ops.fb.set_atomic_mode(g);
/* Ensure atomic mode was enabled */
if ((nvgpu_readl(g, fb_mmu_ctrl_r()) &
fb_mmu_ctrl_atomic_capability_mode_m()) == 0) {
unit_return_fail(m, "Atomic mode not set\n");
}
/* For branch coverage */
nvgpu_set_enabled(g, NVGPU_SEC_PRIVSECURITY, true);
g->ops.fb.init_fs_state(g);
nvgpu_set_enabled(g, NVGPU_SEC_PRIVSECURITY, false);
/*
* gv11b_fb_ecc_init initializes 5 structures via kmem. Test the failure
* of all of them.
*/
for (int i = 0; i < 5; i++) {
nvgpu_posix_enable_fault_injection(kmem_fi, true, i);
err = g->ops.fb.ecc.init(g);
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
if (err != -ENOMEM) {
unit_return_fail(m, "gv11b_fb_ecc_init did not fail as expected (%d)\n", i);
}
g->ops.ecc.ecc_init_support(g);
}
err = g->ops.fb.ecc.init(g);
if (err != 0) {
unit_return_fail(m, "gv11b_fb_ecc_init failed\n");
}
g->ops.fb.ecc.free(g);
return UNIT_SUCCESS;
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2019-2020, 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/sizes.h>
#include <nvgpu/io.h>
#include <nvgpu/nvgpu_init.h>
#include "hal/mc/mc_gp10b.h"
#include "hal/fb/fb_gm20b.h"
#include "hal/fb/fb_gv11b.h"
#include "hal/fb/fb_mmu_fault_gv11b.h"
#include "hal/fb/ecc/fb_ecc_gv11b.h"
#include "hal/fb/intr/fb_intr_gv11b.h"
#include "hal/fb/intr/fb_intr_ecc_gv11b.h"
#include <nvgpu/hw/gv11b/hw_fb_gv11b.h>
#include <nvgpu/hw/gv11b/hw_mc_gv11b.h>
#include "fb_fusa.h"
/* Arbitrary number of errors */
#define ECC_ERRORS 15U
int fb_intr_gv11b_init_test(struct unit_module *m, struct gk20a *g, void *args)
{
/* HALs under test */
g->ops.fb.ecc.init = gv11b_fb_ecc_init;
g->ops.fb.ecc.free = gv11b_fb_ecc_free;
g->ops.fb.ecc.l2tlb_error_mask = gv11b_fb_ecc_l2tlb_error_mask;
g->ops.fb.intr.handle_ecc = gv11b_fb_intr_handle_ecc;
g->ops.fb.intr.handle_ecc_l2tlb = gv11b_fb_intr_handle_ecc_l2tlb;
g->ops.fb.intr.handle_ecc_hubtlb = gv11b_fb_intr_handle_ecc_hubtlb;
g->ops.fb.intr.handle_ecc_fillunit = gv11b_fb_intr_handle_ecc_fillunit;
return UNIT_SUCCESS;
}
int fb_intr_gv11b_isr_test(struct unit_module *m, struct gk20a *g, void *args)
{
/* Mask all interrupts */
nvgpu_writel(g, fb_niso_intr_en_set_r(0), 0);
/* Enable interrupts */
gv11b_fb_intr_enable(g);
if (nvgpu_readl(g, fb_niso_intr_en_set_r(0)) == 0) {
unit_return_fail(m, "FB_INTR not unmasked\n");
}
/* Set INTR status register to 0, i.e. no interrupt */
nvgpu_writel(g, fb_niso_intr_r(), 0);
if (gv11b_fb_intr_is_mmu_fault_pending(g)) {
unit_return_fail(m, "MMU fault should NOT be pending\n");
}
gv11b_fb_intr_isr(g, 0U);
/* Hub access counter notify/error: just causes a nvgpu_info call */
nvgpu_writel(g, fb_niso_intr_r(),
fb_niso_intr_hub_access_counter_notify_m());
gv11b_fb_intr_isr(g, 0U);
/* MMU fault: testing of MMU fault handling is done in other tests */
nvgpu_writel(g, fb_niso_intr_r(),
fb_niso_intr_mmu_other_fault_notify_m());
if (!gv11b_fb_intr_is_mmu_fault_pending(g)) {
unit_return_fail(m, "MMU fault should be pending\n");
}
gv11b_fb_intr_isr(g, 0U);
/* ECC fault: testing of ECC fault handling is done in other tests */
nvgpu_writel(g, fb_niso_intr_r(),
fb_niso_intr_mmu_ecc_uncorrected_error_notify_pending_f());
gv11b_fb_intr_isr(g, 0U);
/* Disable interrupts */
gv11b_fb_intr_disable(g);
/*
* In real HW it may not be possible to read the set/clear registers but
* here we can, and what was programmed in the set register should be
* the same as what was programmed in the clear register.
*/
if (nvgpu_readl(g, fb_niso_intr_en_set_r(0)) !=
nvgpu_readl(g, fb_niso_intr_en_clr_r(0))) {
unit_return_fail(m, "FB_INTR set/clear mismatch\n");
}
return UNIT_SUCCESS;
}
struct gv11b_ecc_test_parameters {
u32 status_reg;
u32 corrected_err_reg;
u32 uncorrected_err_reg;
u32 corrected_status, uncorrected_status;
u32 corrected_overflow, uncorrected_overflow;
};
static struct gv11b_ecc_test_parameters l2tlb_parameters = {
.status_reg = fb_mmu_l2tlb_ecc_status_r(),
.corrected_err_reg = fb_mmu_l2tlb_ecc_corrected_err_count_r(),
.uncorrected_err_reg = fb_mmu_l2tlb_ecc_uncorrected_err_count_r(),
.corrected_status = fb_mmu_l2tlb_ecc_status_corrected_err_l2tlb_sa_data_m(),
.uncorrected_status = fb_mmu_l2tlb_ecc_status_uncorrected_err_l2tlb_sa_data_m(),
.corrected_overflow = fb_mmu_l2tlb_ecc_status_corrected_err_total_counter_overflow_m(),
.uncorrected_overflow = fb_mmu_l2tlb_ecc_status_uncorrected_err_total_counter_overflow_m(),
};
static struct gv11b_ecc_test_parameters hubtlb_parameters = {
.status_reg = fb_mmu_hubtlb_ecc_status_r(),
.corrected_err_reg = fb_mmu_hubtlb_ecc_corrected_err_count_r(),
.uncorrected_err_reg = fb_mmu_hubtlb_ecc_uncorrected_err_count_r(),
.corrected_status = fb_mmu_hubtlb_ecc_status_corrected_err_sa_data_m(),
.uncorrected_status = fb_mmu_hubtlb_ecc_status_uncorrected_err_sa_data_m(),
.corrected_overflow = fb_mmu_hubtlb_ecc_status_corrected_err_total_counter_overflow_m(),
.uncorrected_overflow = fb_mmu_hubtlb_ecc_status_uncorrected_err_total_counter_overflow_m(),
};
static struct gv11b_ecc_test_parameters fillunit_parameters = {
.status_reg = fb_mmu_fillunit_ecc_status_r(),
.corrected_err_reg = fb_mmu_fillunit_ecc_corrected_err_count_r(),
.uncorrected_err_reg = fb_mmu_fillunit_ecc_uncorrected_err_count_r(),
.corrected_status = fb_mmu_fillunit_ecc_status_corrected_err_pte_data_m(),
.uncorrected_status = fb_mmu_fillunit_ecc_status_uncorrected_err_pte_data_m(),
.corrected_overflow = fb_mmu_fillunit_ecc_status_corrected_err_total_counter_overflow_m(),
.uncorrected_overflow = fb_mmu_fillunit_ecc_status_uncorrected_err_total_counter_overflow_m(),
};
int fb_intr_gv11b_ecc_test(struct unit_module *m, struct gk20a *g, void *args)
{
struct gv11b_ecc_test_parameters *p;
u64 subcase = (u64) args;
switch (subcase) {
case TEST_ECC_L2TLB:
p = &l2tlb_parameters;
break;
case TEST_ECC_HUBTLB:
p = &hubtlb_parameters;
break;
case TEST_ECC_FILLUNIT:
p = &fillunit_parameters;
break;
default:
unit_return_fail(m, "Invalid subcase\n");
}
g->ops.fb.ecc.init(g);
/* Set the interrupt status as corrected */
nvgpu_writel(g, p->status_reg, p->corrected_status);
EXPECT_BUG(gv11b_fb_intr_isr(g, 0U));
/* Set the interrupt status as uncorrected */
nvgpu_writel(g, p->status_reg, p->uncorrected_status);
gv11b_fb_intr_isr(g, 0U);
/* Set arbitrary number of corrected and uncorrected errors */
nvgpu_writel(g, p->corrected_err_reg, ECC_ERRORS);
nvgpu_writel(g, p->uncorrected_err_reg, ECC_ERRORS);
gv11b_fb_intr_isr(g, 0U);
/* Same but with corrected overflow bit set */
nvgpu_writel(g, p->status_reg, 1 | p->corrected_overflow);
nvgpu_writel(g, p->corrected_err_reg, ECC_ERRORS);
nvgpu_writel(g, p->uncorrected_err_reg, ECC_ERRORS);
EXPECT_BUG(gv11b_fb_intr_isr(g, 0U));
/* Same but with uncorrected overflow bit set */
nvgpu_writel(g, p->status_reg, 1 | p->uncorrected_overflow);
nvgpu_writel(g, p->corrected_err_reg, ECC_ERRORS);
nvgpu_writel(g, p->uncorrected_err_reg, ECC_ERRORS);
EXPECT_BUG(gv11b_fb_intr_isr(g, 0U));
/* Both overflow but error counts at 0 */
nvgpu_writel(g, p->status_reg, 1 | p->corrected_overflow |
p->uncorrected_overflow);
nvgpu_writel(g, p->corrected_err_reg, 0);
nvgpu_writel(g, p->uncorrected_err_reg, 0);
EXPECT_BUG(gv11b_fb_intr_isr(g, 0U));
/* Extra case for fillunit */
if (subcase == TEST_ECC_FILLUNIT) {
/* PDE0 */
nvgpu_writel(g, p->status_reg,
fb_mmu_fillunit_ecc_status_corrected_err_pde0_data_m() |
fb_mmu_fillunit_ecc_status_uncorrected_err_pde0_data_m());
EXPECT_BUG(gv11b_fb_intr_isr(g, 0U));
}
/* Clear interrupt status */
nvgpu_writel(g, p->status_reg, 0);
g->ops.fb.ecc.free(g);
return UNIT_SUCCESS;
}

View File

@@ -0,0 +1,325 @@
/*
* Copyright (c) 2019-2020, 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include <unistd.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/io.h>
#include <nvgpu/nvgpu_init.h>
#include "hal/mc/mc_gp10b.h"
#include "hal/fb/fb_gm20b.h"
#include "hal/fb/fb_gv11b.h"
#include "hal/fb/fb_mmu_fault_gv11b.h"
#include "hal/fb/intr/fb_intr_gv11b.h"
#include "hal/mm/mmu_fault/mmu_fault_gv11b.h"
#include <nvgpu/hw/gv11b/hw_fb_gv11b.h>
#include "fb_fusa.h"
#define FAULT_STATUS_TEST_VAL 0x101U
#define TEST_VALUE_1 0x80801234
#define TEST_VALUE_2 0xABCD4567
static u32 hal_channel_count(struct gk20a *g)
{
/* Reasonable channel count for the purpose of this test */
return 0x00000200U;
}
static void hal_bar2_fault_nop(struct gk20a *g)
{
/* no-op */
}
static int hal_bar2_bind_nop(struct gk20a *g, struct nvgpu_mem *bar2_inst)
{
/* no-op */
return 0;
}
static int hal_bar2_bind_fail(struct gk20a *g, struct nvgpu_mem *bar2_inst)
{
return -1;
}
static u32 hal_fifo_mmu_fault_id_to_pbdma_id(struct gk20a *g, u32 mmu_fault_id)
{
return INVAL_ID;
}
int fb_mmu_fault_gv11b_init_test(struct unit_module *m, struct gk20a *g,
void *args)
{
/* HALs under test */
g->ops.fb.read_mmu_fault_buffer_size =
gv11b_fb_read_mmu_fault_buffer_size;
g->ops.fb.read_mmu_fault_buffer_get =
gv11b_fb_read_mmu_fault_buffer_get;
g->ops.fb.read_mmu_fault_buffer_put =
gv11b_fb_read_mmu_fault_buffer_put;
g->ops.fb.write_mmu_fault_buffer_get =
fb_gv11b_write_mmu_fault_buffer_get;
g->ops.fb.is_fault_buf_enabled = gv11b_fb_is_fault_buf_enabled;
g->ops.fb.fault_buf_set_state_hw = gv11b_fb_fault_buf_set_state_hw;
g->ops.fb.write_mmu_fault_buffer_size =
gv11b_fb_write_mmu_fault_buffer_size;
g->ops.fb.read_mmu_fault_status = gv11b_fb_read_mmu_fault_status;
g->ops.fb.fault_buf_configure_hw = gv11b_fb_fault_buf_configure_hw;
g->ops.fb.write_mmu_fault_buffer_lo_hi =
gv11b_fb_write_mmu_fault_buffer_lo_hi;
g->ops.fb.read_mmu_fault_addr_lo_hi =
gv11b_fb_read_mmu_fault_addr_lo_hi;
g->ops.fb.read_mmu_fault_inst_lo_hi =
gv11b_fb_read_mmu_fault_inst_lo_hi;
g->ops.fb.read_mmu_fault_info = gv11b_fb_read_mmu_fault_info;
g->ops.fb.write_mmu_fault_status = gv11b_fb_write_mmu_fault_status;
/* Other HALs that are needed */
g->ops.channel.count = hal_channel_count;
g->ops.ce.mthd_buffer_fault_in_bar2_fault = hal_bar2_fault_nop;
g->ops.bus.bar2_bind = hal_bar2_bind_nop;
g->ops.fifo.mmu_fault_id_to_pbdma_id =
hal_fifo_mmu_fault_id_to_pbdma_id;
g->ops.mm.mmu_fault.parse_mmu_fault_info =
gv11b_mm_mmu_fault_parse_mmu_fault_info;
return UNIT_SUCCESS;
}
int fb_mmu_fault_gv11b_buffer_test(struct unit_module *m, struct gk20a *g,
void *args)
{
u32 get_idx;
u32 val;
u32 lo, hi;
struct nvgpu_posix_fault_inj *timers_fi =
nvgpu_timers_get_fault_injection();
if (g->ops.fb.is_fault_buf_enabled(g, 0)) {
unit_return_fail(m, "fault buffer not disabled as expected\n");
}
/* Standard case */
gv11b_fb_fault_buffer_get_ptr_update(g, 0, 0);
/* Overflow situation */
nvgpu_writel(g, fb_mmu_fault_buffer_get_r(0),
fb_mmu_fault_buffer_get_overflow_m());
gv11b_fb_fault_buffer_get_ptr_update(g, 0, 0);
gv11b_fb_fault_buffer_size_val(g, 0);
if (!gv11b_fb_is_fault_buffer_empty(g, 0, &get_idx)) {
unit_return_fail(m, "fault buffer not empty as expected\n");
}
/* Fault buffer hw setup */
g->ops.fb.fault_buf_configure_hw(g, 0);
/* Enable fault buffer */
g->ops.fb.fault_buf_set_state_hw(g, 0, NVGPU_MMU_FAULT_BUF_ENABLED);
/* Enabling again shouldn't cause an issue */
g->ops.fb.fault_buf_set_state_hw(g, 0, NVGPU_MMU_FAULT_BUF_ENABLED);
/* Make nvgpu_timeout_init fail during disable operation */
nvgpu_posix_enable_fault_injection(timers_fi, true, 0);
g->ops.fb.fault_buf_set_state_hw(g, 0, NVGPU_MMU_FAULT_BUF_DISABLED);
nvgpu_posix_enable_fault_injection(timers_fi, false, 0);
/* Disable */
g->ops.fb.fault_buf_set_state_hw(g, 0, NVGPU_MMU_FAULT_BUF_DISABLED);
/* Try to disable again, but cause a timeout as fault status is set */
g->ops.fb.fault_buf_set_state_hw(g, 0, NVGPU_MMU_FAULT_BUF_ENABLED);
nvgpu_writel(g, fb_mmu_fault_status_r(),
fb_mmu_fault_status_busy_true_f());
g->ops.fb.fault_buf_set_state_hw(g, 0, NVGPU_MMU_FAULT_BUF_DISABLED);
if (g->ops.fb.is_fault_buf_enabled(g, 0)) {
unit_return_fail(m, "fault buffer not disabled as expected\n");
}
nvgpu_writel(g, fb_mmu_fault_addr_lo_r(), TEST_VALUE_1);
nvgpu_writel(g, fb_mmu_fault_addr_hi_r(), TEST_VALUE_2);
g->ops.fb.read_mmu_fault_addr_lo_hi(g, &lo, &hi);
if ((lo != TEST_VALUE_1) || (hi != TEST_VALUE_2)) {
unit_return_fail(m, "Invalid MMU fault address\n");
}
nvgpu_writel(g, fb_mmu_fault_inst_lo_r(), TEST_VALUE_1);
nvgpu_writel(g, fb_mmu_fault_inst_hi_r(), TEST_VALUE_2);
g->ops.fb.read_mmu_fault_inst_lo_hi(g, &lo, &hi);
if ((lo != TEST_VALUE_1) || (hi != TEST_VALUE_2)) {
unit_return_fail(m, "Invalid MMU fault inst\n");
}
val = g->ops.fb.read_mmu_fault_info(g);
if (val != nvgpu_readl(g, fb_mmu_fault_info_r())) {
unit_return_fail(m, "invalid fb_mmu_fault_info_r value\n");
}
g->ops.fb.write_mmu_fault_status(g, FAULT_STATUS_TEST_VAL);
if (nvgpu_readl(g, fb_mmu_fault_status_r()) != FAULT_STATUS_TEST_VAL) {
unit_return_fail(m, "invalid fb_mmu_fault_status_r value\n");
}
return UNIT_SUCCESS;
}
int fb_mmu_fault_gv11b_snap_reg(struct unit_module *m, struct gk20a *g,
void *args)
{
struct mmu_fault_info mmufault;
/* Not a valid fault, chid should just be zero'ed out by memset */
gv11b_mm_copy_from_fault_snap_reg(g, 0, &mmufault);
if (mmufault.chid != 0) {
unit_return_fail(m, "chid updated for invalid fault\n");
}
/* Valid fault */
gv11b_mm_copy_from_fault_snap_reg(g, fb_mmu_fault_status_valid_set_f(),
&mmufault);
if (mmufault.chid != NVGPU_INVALID_CHANNEL_ID) {
unit_return_fail(m, "chid NOT updated for valid fault\n");
}
return UNIT_SUCCESS;
}
static bool helper_is_intr_cleared(struct gk20a *g)
{
return (nvgpu_readl(g, fb_mmu_fault_status_r()) ==
fb_mmu_fault_status_valid_clear_f());
}
int fb_mmu_fault_gv11b_handle_fault(struct unit_module *m, struct gk20a *g,
void *args)
{
u32 niso_intr;
/* Set interrupt source as "other" and handle it */
niso_intr = fb_niso_intr_mmu_other_fault_notify_m();
nvgpu_writel(g, fb_mmu_fault_status_r(), 0);
gv11b_fb_handle_mmu_fault(g, niso_intr);
if (!helper_is_intr_cleared(g)) {
unit_return_fail(m, "unhandled interrupt (1)\n");
}
/* Enable fault buffer */
g->ops.fb.fault_buf_set_state_hw(g, 0, NVGPU_MMU_FAULT_BUF_ENABLED);
/* Handle again for branch coverage */
gv11b_fb_handle_mmu_fault(g, niso_intr);
/* Set a valid dropped status and handle again */
nvgpu_writel(g, fb_mmu_fault_status_r(),
fb_mmu_fault_status_dropped_bar1_phys_set_f());
gv11b_fb_handle_mmu_fault(g, niso_intr);
if (!helper_is_intr_cleared(g)) {
unit_return_fail(m, "unhandled interrupt (2)\n");
}
/* Now set interrupt source as a non-replayable fault and handle it */
niso_intr = fb_niso_intr_mmu_nonreplayable_fault_notify_m();
nvgpu_writel(g, fb_mmu_fault_status_r(), 0);
gv11b_fb_handle_mmu_fault(g, niso_intr);
if (!helper_is_intr_cleared(g)) {
unit_return_fail(m, "unhandled interrupt (3)\n");
}
/* Now set source as non-replayable and overflow then handle it */
niso_intr = fb_niso_intr_mmu_nonreplayable_fault_notify_m() |
fb_niso_intr_mmu_nonreplayable_fault_overflow_m();
nvgpu_writel(g, fb_mmu_fault_status_r(), 0);
gv11b_fb_handle_mmu_fault(g, niso_intr);
if (!helper_is_intr_cleared(g)) {
unit_return_fail(m, "unhandled interrupt (4)\n");
}
/* Same case but ensure fault status register is also set properly */
nvgpu_writel(g, fb_mmu_fault_status_r(),
fb_mmu_fault_status_non_replayable_overflow_m());
gv11b_fb_handle_mmu_fault(g, niso_intr);
if (!helper_is_intr_cleared(g)) {
unit_return_fail(m, "unhandled interrupt (5)\n");
}
/* Case where getptr is reported as corrupted */
nvgpu_writel(g, fb_mmu_fault_status_r(),
fb_mmu_fault_status_non_replayable_overflow_m() |
fb_mmu_fault_status_non_replayable_getptr_corrupted_m());
gv11b_fb_handle_mmu_fault(g, niso_intr);
if (!helper_is_intr_cleared(g)) {
unit_return_fail(m, "unhandled interrupt (6)\n");
}
g->ops.fb.fault_buf_set_state_hw(g, 0, NVGPU_MMU_FAULT_BUF_DISABLED);
return UNIT_SUCCESS;
}
int fb_mmu_fault_gv11b_handle_bar2_fault(struct unit_module *m, struct gk20a *g,
void *args)
{
struct mmu_fault_info mmufault;
struct nvgpu_channel refch;
u32 fault_status = 0;
static const char *const error_str = "test error";
(void) memset(&mmufault, 0, sizeof(mmufault));
(void) memset(&refch, 0, sizeof(refch));
gv11b_fb_handle_bar2_fault(g, &mmufault, fault_status);
/* Set the minimum mmufault struct to handle the fault */
/* First cover some error cases */
gv11b_fb_mmu_fault_info_dump(g, NULL);
gv11b_fb_mmu_fault_info_dump(g, &mmufault);
/* Now set it up properly */
mmufault.valid = true;
mmufault.refch = &refch;
mmufault.fault_type_desc = error_str;
mmufault.client_type_desc = error_str;
mmufault.client_id_desc = error_str;
gv11b_fb_mmu_fault_info_dump(g, &mmufault);
fault_status = fb_mmu_fault_status_non_replayable_error_m();
g->ops.fb.fault_buf_set_state_hw(g, 0, NVGPU_MMU_FAULT_BUF_ENABLED);
gv11b_fb_handle_bar2_fault(g, &mmufault, fault_status);
/* Case where g->ops.bus.bar2_bind fails */
g->ops.bus.bar2_bind = hal_bar2_bind_fail;
g->ops.fb.fault_buf_set_state_hw(g, 0, NVGPU_MMU_FAULT_BUF_ENABLED);
gv11b_fb_handle_bar2_fault(g, &mmufault, fault_status);
g->ops.bus.bar2_bind = hal_bar2_bind_nop;
/* Case where fault buffer is not enabled */
g->ops.fb.fault_buf_set_state_hw(g, 0, NVGPU_MMU_FAULT_BUF_DISABLED);
gv11b_fb_handle_bar2_fault(g, &mmufault, fault_status);
return UNIT_SUCCESS;
}

View File

@@ -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-fbp.o
MODULE = fbp
include ../Makefile.units

View File

@@ -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=fbp
include $(NV_COMPONENT_DIR)/../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -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=fbp
NVGPU_UNIT_SRCS=nvgpu-fbp.c
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,222 @@
/*
* Copyright (c) 2019-2020, 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/fbp.h>
#include <hal/top/top_gm20b.h>
#include <hal/fuse/fuse_gm20b.h>
#include <nvgpu/hw/gv11b/hw_top_gv11b.h>
#include <nvgpu/hw/gv11b/hw_fuse_gv11b.h>
#include "nvgpu-fbp.h"
/*
* 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)
{
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,
};
int test_fbp_setup(struct unit_module *m, struct gk20a *g, void *args)
{
/* Init HAL */
g->ops.top.get_max_fbps_count = gm20b_top_get_max_fbps_count;
g->ops.fuse.fuse_status_opt_fbp = gm20b_fuse_status_opt_fbp;
/* Map register space for FUSE_STATUS_OPT_FBP */
if (nvgpu_posix_io_add_reg_space(g, fuse_status_opt_fbp_r(), 0x4)
!= 0) {
unit_err(m, "%s: failed to register NV_FUSE space\n", __func__);
return UNIT_FAIL;
}
/* Map register space for TOP_SCAL_NUM_FBPS */
if (nvgpu_posix_io_add_reg_space(g, top_num_fbps_r(), 0x4) != 0) {
unit_err(m, "%s: failed to register NV_TOP space\n", __func__);
return UNIT_FAIL;
}
(void)nvgpu_posix_register_io(g, &test_reg_callbacks);
return UNIT_SUCCESS;
}
int test_fbp_free_reg_space(struct unit_module *m, struct gk20a *g, void *args)
{
/* Free register space */
nvgpu_posix_io_delete_reg_space(g, fuse_status_opt_fbp_r());
nvgpu_posix_io_delete_reg_space(g, top_num_fbps_r());
return UNIT_SUCCESS;
}
int test_fbp_init_and_query(struct unit_module *m, struct gk20a *g,
void *args)
{
int ret = UNIT_SUCCESS;
int val = 0;
u32 fbp_en_mask;
u32 max_fbps_count;
struct nvgpu_fbp *fbp = g->fbp;
struct nvgpu_posix_fault_inj *kmem_fi =
nvgpu_kmem_get_fault_injection();
/* First, cover the memory allocation failure path. */
nvgpu_posix_enable_fault_injection(kmem_fi, true, 0);
/* Call fbp_init_support and confirm it returns -ENOMEM. */
val = nvgpu_fbp_init_support(g);
if (val != -ENOMEM) {
unit_err(m,
"%s: fbp_init_support did not fail due to memory allocation.\n",
__func__);
return UNIT_FAIL;
}
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
/* Initialize the FBP floorsweeping status in fuse to 0xE1. */
fbp_en_mask = 0xE1U;
nvgpu_posix_io_writel_reg_space(g, fuse_status_opt_fbp_r(),
fbp_en_mask);
/* Initialize the maximum number of FBPs to 8. */
max_fbps_count = 8U;
nvgpu_posix_io_writel_reg_space(g, top_num_fbps_r(), max_fbps_count);
/* Call fbp_init_support to initialize g->fbp */
val = nvgpu_fbp_init_support(g);
if (val != 0) {
unit_err(m, "%s: Failed to initialize g->fbp.\n", __func__);
return UNIT_FAIL;
}
fbp = g->fbp;
/* Check if the max_fbps_count is read correctly. */
max_fbps_count = nvgpu_fbp_get_max_fbps_count(fbp);
if (max_fbps_count != 8U) {
unit_err(m, "%s: fbp->max_fbps_count is incorrect.\n",
__func__);
return UNIT_FAIL;
}
/* Check if the FBP en_mask is calculated correctly.
* Note: 0:enable and 1:disable in value read from fuse.
* so we've to flip the bits and also set unused bits to zero.
*/
fbp_en_mask = nvgpu_fbp_get_fbp_en_mask(fbp);
if (fbp_en_mask != 0x1EU) {
unit_err(m, "%s: fbp->fbp_en_mask is incorrect.\n", __func__);
return UNIT_FAIL;
}
/* Initialize the FBP floorsweeping status in fuse to 5.
* Use different value than above to check if init occurs once.
*/
max_fbps_count = 5U;
nvgpu_posix_io_writel_reg_space(g, top_num_fbps_r(), max_fbps_count);
/* Call fbp_init_support again to ensure the initialization is
* done once.
*/
val = nvgpu_fbp_init_support(g);
if (val != 0) {
unit_err(m, "%s: Failed to initialize g->fbp.\n", __func__);
return UNIT_FAIL;
}
/* Check if the max_fbps_count is NOT set to 5. */
max_fbps_count = nvgpu_fbp_get_max_fbps_count(fbp);
if (max_fbps_count == 5U) {
unit_err(m, "%s: g->fbp initialized again.\n", __func__);
return UNIT_FAIL;
}
return ret;
}
int test_fbp_remove_support(struct unit_module *m, struct gk20a *g, void *args)
{
int ret = UNIT_SUCCESS;
/* Confirm if g->fbp != NULL before calling fbp_remov_support API. */
if (g->fbp == NULL) {
unit_err(m, "%s: g->fbp is uninitialized.\n", __func__);
return UNIT_FAIL;
}
/* Call fbp_remove_support to cleanup the saved FBP data */
nvgpu_fbp_remove_support(g);
/* Confirm if g->fbp == NULL after cleanup. */
if (g->fbp != NULL) {
unit_err(m, "%s: g->fbp is not cleaned up.\n", __func__);
return UNIT_FAIL;
}
/*
* Call fbp_remove_support with fbp pointer set to NULL for branch
* coverage.
*/
nvgpu_fbp_remove_support(g);
return ret;
}
struct unit_module_test fbp_tests[] = {
UNIT_TEST(fbp_setup, test_fbp_setup, NULL, 0),
UNIT_TEST(fbp_init_and_query, test_fbp_init_and_query, NULL, 0),
UNIT_TEST(fbp_remove_support, test_fbp_remove_support, NULL, 0),
UNIT_TEST(fbp_free_reg_space, test_fbp_free_reg_space, NULL, 0),
};
UNIT_MODULE(fbp, fbp_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,127 @@
/*
* 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_FBP_H
#define UNIT_NVGPU_FBP_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-fbp
* @{
*
* Software Unit Test Specification for nvgpu.common.fbp
*/
/**
* Test specification for: test_fbp_setup
*
* Description: Setup prerequisites for tests.
*
* Test Type: Other (setup)
*
* Input: None
*
* Steps:
* - Initialize HAL function pointers.
* - Map the register space for NV_TOP and NV_FUSE.
* - Register read/write callback functions.
*
* Output:
* - UNIT_FAIL if encounters an error creating register space;
* - UNIT_SUCCESS otherwise
*/
int test_fbp_setup(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_fbp_free_reg_space
*
* Description: Free resources from test_setup()
*
* Test Type: Other (cleanup)
*
* Input: test_fbp_setup() has been executed.
*
* Steps:
* - Free up NV_TOP and NV_FUSE register space.
*
* Output:
* - UNIT_SUCCESS
*/
int test_fbp_free_reg_space(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_fbp_init_and_query
*
* Description: Verify the FBP init and config query APIs exposed by common.fbp.
*
* Test Type: Feature
*
* Targets: nvgpu_fbp_init_support, nvgpu_fbp_get_max_fbps_count, nvgpu_fbp_get_fbp_en_mask
*
* Input: test_fbp_setup() has been executed.
*
* Steps:
* - Initialize the FBP floorsweeping status in fuse to 0xE1 by writing to fuse
* register fuse_status_opt_fbp_r().
* - Initialize the maximum number of FBPs to 8 by writing to Top register
* top_num_fbps_r().
* - Call nvgpu_fbp_init_support to initialize g->fbp.
* - Read the g->fbp->max_fbp_count using nvgpu_fbp_get_max_fbps_count().
* - Check if the max_fbps_count is initialized and read back correctly.
* - Read the g->fbp->fbp_en_mask using nvgpu_fbp_get_fbp_en_mask().
* - Check if the FBP en_mask is calculated correctly and read back right too.
* - Initialize the FBP floorsweeping status in fuse to 5(Use different value
* than before to check if init occurs once.
* - Call fbp_init_support again to ensure the initialization is done once.
* - Check if the max_fbps_count is NOT set to new value(5).
*
* Output:
* - UNIT_FAIL if above API fails to init g->fbp or read back values from g->fbp
* - UNIT_SUCCESS otherwise
*/
int test_fbp_init_and_query(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_fbp_remove_support
*
* Description: Verify the nvgpu_fbp_remove_support exposed by common.fbp.
*
* Test Type: Feature
*
* Targets: nvgpu_fbp_remove_support
*
* Input: test_fbp_init_and_query() has been executed.
*
* Steps:
* - Confirm if g->fbp != NULL before calling fbp_remov_support API.
* - Call fbp_remove_support to cleanup the saved FBP data.
* - Confirm if g->fbp == NULL after cleanup.
* - Call fbp_remove_support with fbp pointer set to NULL for branch coverage.
*
* Output:
* - UNIT_FAIL if above API fails to cleanup g->fbp;
* - UNIT_SUCCESS otherwise
*/
int test_fbp_remove_support(struct unit_module *m, struct gk20a *g, void *args);
#endif /* UNIT_NVGPU_FBP_H */

View File

@@ -0,0 +1,27 @@
# Copyright (c) 2019-2020, 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-fifo-common.o nvgpu-fifo-gv11b.o
MODULE = nvgpu-fifo-common
include ../Makefile.units

View File

@@ -0,0 +1,29 @@
################################### 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
#
# libnvgpu-fifo interface makefile fragment
#
###############################################################################
ifdef NV_INTERFACE_FLAG_SHARED_LIBRARY_SECTION
NV_INTERFACE_NAME := nvgpu-fifo-common
NV_INTERFACE_EXPORTS := lib$(NV_INTERFACE_NAME)
NV_INTERFACE_SONAME := lib$(NV_INTERFACE_NAME).so
endif
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,26 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019-2020 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
#
# Component makefile for compiling nvgpu-fifo common tests.
#
###############################################################################
NVGPU_UNIT_NAME = nvgpu-fifo-common
NVGPU_UNIT_SRCS = nvgpu-fifo-common.c nvgpu-fifo-gv11b.c
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -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-channel.o
MODULE = nvgpu-channel
LIB_PATHS += -lnvgpu-fifo-common
include ../../Makefile.units
lib$(MODULE).so: fifo
fifo:
$(MAKE) -C ..

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2018-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-channel
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,39 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019-2020, 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-channel
NVGPU_UNIT_SRCS = nvgpu-channel.c
NVGPU_UNIT_INTERFACE_DIRS := \
$(NV_COMPONENT_DIR)/..
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,32 @@
# 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-channel-gk20a.o
MODULE = nvgpu-channel-gk20a
LIB_PATHS += -lnvgpu-fifo-common
include ../../../Makefile.units
lib$(MODULE).so: fifo
fifo:
$(MAKE) -C ../..

Some files were not shown because too many files have changed in this diff Show More