mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
gpu: nvgpu: unit: add fb HAL unit tests
Unit tests covering the FB related HALs. JIRA NVGPU-932 Change-Id: I46de25ea2a495e22ca6485d1fae1778261a804bd Signed-off-by: Nicolas Benech <nbenech@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2259666 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Alex Waterman
parent
ce6fc269a1
commit
92d5c53c59
@@ -70,6 +70,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/mm/mm
|
|||||||
NV_REPOSITORY_COMPONENTS += userspace/units/mm/page_table_faults
|
NV_REPOSITORY_COMPONENTS += userspace/units/mm/page_table_faults
|
||||||
NV_REPOSITORY_COMPONENTS += userspace/units/mm/vm
|
NV_REPOSITORY_COMPONENTS += userspace/units/mm/vm
|
||||||
NV_REPOSITORY_COMPONENTS += userspace/units/netlist
|
NV_REPOSITORY_COMPONENTS += userspace/units/netlist
|
||||||
|
NV_REPOSITORY_COMPONENTS += userspace/units/fb
|
||||||
NV_REPOSITORY_COMPONENTS += userspace/units/fbp
|
NV_REPOSITORY_COMPONENTS += userspace/units/fbp
|
||||||
NV_REPOSITORY_COMPONENTS += userspace/units/fifo
|
NV_REPOSITORY_COMPONENTS += userspace/units/fifo
|
||||||
NV_REPOSITORY_COMPONENTS += userspace/units/fifo/channel
|
NV_REPOSITORY_COMPONENTS += userspace/units/fifo/channel
|
||||||
|
|||||||
@@ -3,10 +3,7 @@
|
|||||||
bitmap_find_next_zero_area_off
|
bitmap_find_next_zero_area_off
|
||||||
bug_handler_cancel
|
bug_handler_cancel
|
||||||
bug_handler_register
|
bug_handler_register
|
||||||
gv11b_fb_read_mmu_fault_buffer_size
|
fb_gv11b_write_mmu_fault_buffer_get
|
||||||
gv11b_fb_read_mmu_fault_status
|
|
||||||
gv11b_fb_write_mmu_fault_buffer_lo_hi
|
|
||||||
gv11b_fb_write_mmu_fault_buffer_size
|
|
||||||
find_first_bit
|
find_first_bit
|
||||||
find_first_zero_bit
|
find_first_zero_bit
|
||||||
find_next_bit
|
find_next_bit
|
||||||
@@ -39,7 +36,15 @@ gk20a_vm_release_share
|
|||||||
gm20b_channel_bind
|
gm20b_channel_bind
|
||||||
gm20b_channel_force_ctx_reload
|
gm20b_channel_force_ctx_reload
|
||||||
gm20b_device_info_parse_enum
|
gm20b_device_info_parse_enum
|
||||||
|
gm20b_fb_dump_vpr_info
|
||||||
|
gm20b_fb_dump_wpr_info
|
||||||
|
gm20b_fb_mmu_ctrl
|
||||||
|
gm20b_fb_mmu_debug_ctrl
|
||||||
|
gm20b_fb_mmu_debug_rd
|
||||||
|
gm20b_fb_mmu_debug_wr
|
||||||
|
gm20b_fb_read_wpr_info
|
||||||
gm20b_fb_tlb_invalidate
|
gm20b_fb_tlb_invalidate
|
||||||
|
gm20b_fb_vpr_info_fetch
|
||||||
gm20b_gr_falcon_get_fecs_ctx_state_store_major_rev_id
|
gm20b_gr_falcon_get_fecs_ctx_state_store_major_rev_id
|
||||||
gm20b_is_engine_gr
|
gm20b_is_engine_gr
|
||||||
gm20b_mm_get_big_page_sizes
|
gm20b_mm_get_big_page_sizes
|
||||||
@@ -100,13 +105,33 @@ gv11b_channel_debug_dump
|
|||||||
gv11b_channel_read_state
|
gv11b_channel_read_state
|
||||||
gv11b_channel_reset_faulted
|
gv11b_channel_reset_faulted
|
||||||
gv11b_channel_unbind
|
gv11b_channel_unbind
|
||||||
gv11b_fb_intr_enable
|
gv11b_fb_ecc_free
|
||||||
|
gv11b_fb_ecc_init
|
||||||
gv11b_fb_fault_buf_configure_hw
|
gv11b_fb_fault_buf_configure_hw
|
||||||
gv11b_fb_fault_buf_set_state_hw
|
gv11b_fb_fault_buf_set_state_hw
|
||||||
|
gv11b_fb_fault_buffer_get_ptr_update
|
||||||
|
gv11b_fb_fault_buffer_size_val
|
||||||
|
gv11b_fb_handle_bar2_fault
|
||||||
|
gv11b_fb_handle_mmu_fault
|
||||||
|
gv11b_fb_init_fs_state
|
||||||
gv11b_fb_init_hw
|
gv11b_fb_init_hw
|
||||||
gv11b_fb_is_fault_buf_enabled
|
|
||||||
gv11b_fb_intr_disable
|
gv11b_fb_intr_disable
|
||||||
|
gv11b_fb_intr_enable
|
||||||
gv11b_fb_intr_is_mmu_fault_pending
|
gv11b_fb_intr_is_mmu_fault_pending
|
||||||
|
gv11b_fb_intr_isr
|
||||||
|
gv11b_fb_is_fault_buf_enabled
|
||||||
|
gv11b_fb_is_fault_buffer_empty
|
||||||
|
gv11b_fb_mmu_fault_info_dump
|
||||||
|
gv11b_fb_read_mmu_fault_addr_lo_hi
|
||||||
|
gv11b_fb_read_mmu_fault_buffer_get
|
||||||
|
gv11b_fb_read_mmu_fault_buffer_put
|
||||||
|
gv11b_fb_read_mmu_fault_buffer_size
|
||||||
|
gv11b_fb_read_mmu_fault_info
|
||||||
|
gv11b_fb_read_mmu_fault_inst_lo_hi
|
||||||
|
gv11b_fb_read_mmu_fault_status
|
||||||
|
gv11b_fb_write_mmu_fault_buffer_lo_hi
|
||||||
|
gv11b_fb_write_mmu_fault_buffer_size
|
||||||
|
gv11b_fb_write_mmu_fault_status
|
||||||
gv11b_fifo_handle_sched_error
|
gv11b_fifo_handle_sched_error
|
||||||
gv11b_fifo_intr_0_enable
|
gv11b_fifo_intr_0_enable
|
||||||
gv11b_fifo_intr_0_isr
|
gv11b_fifo_intr_0_isr
|
||||||
@@ -119,6 +144,7 @@ gv11b_init_fifo_reset_enable_hw
|
|||||||
gv11b_init_fifo_setup_hw
|
gv11b_init_fifo_setup_hw
|
||||||
gv11b_init_hal
|
gv11b_init_hal
|
||||||
gv11b_is_fault_engine_subid_gpc
|
gv11b_is_fault_engine_subid_gpc
|
||||||
|
gv11b_mm_copy_from_fault_snap_reg
|
||||||
gv11b_mm_is_bar1_supported
|
gv11b_mm_is_bar1_supported
|
||||||
gv11b_mm_init_inst_block
|
gv11b_mm_init_inst_block
|
||||||
gv11b_mm_l2_flush
|
gv11b_mm_l2_flush
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ UNITS := \
|
|||||||
$(UNIT_SRC)/mm/nvgpu_mem \
|
$(UNIT_SRC)/mm/nvgpu_mem \
|
||||||
$(UNIT_SRC)/mm/vm \
|
$(UNIT_SRC)/mm/vm \
|
||||||
$(UNIT_SRC)/netlist \
|
$(UNIT_SRC)/netlist \
|
||||||
|
$(UNIT_SRC)/fb \
|
||||||
$(UNIT_SRC)/fbp \
|
$(UNIT_SRC)/fbp \
|
||||||
$(UNIT_SRC)/fifo \
|
$(UNIT_SRC)/fifo \
|
||||||
$(UNIT_SRC)/fifo/fifo/gk20a \
|
$(UNIT_SRC)/fifo/fifo/gk20a \
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
* - @ref SWUTS-mm-page_table_faults
|
* - @ref SWUTS-mm-page_table_faults
|
||||||
* - @ref SWUTS-mm-mm
|
* - @ref SWUTS-mm-mm
|
||||||
* - @ref SWUTS-mm-vm
|
* - @ref SWUTS-mm-vm
|
||||||
|
* - @ref SWUTS-fb
|
||||||
* - @ref SWUTS-fbp
|
* - @ref SWUTS-fbp
|
||||||
* - @ref SWUTS-fuse
|
* - @ref SWUTS-fuse
|
||||||
* - @ref SWUTS-posix-bitops
|
* - @ref SWUTS-posix-bitops
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ INPUT += ../../../userspace/units/interface/rbtree/rbtree.h
|
|||||||
INPUT += ../../../userspace/units/falcon/falcon_tests/nvgpu-falcon.h
|
INPUT += ../../../userspace/units/falcon/falcon_tests/nvgpu-falcon.h
|
||||||
INPUT += ../../../userspace/units/netlist/nvgpu-netlist.h
|
INPUT += ../../../userspace/units/netlist/nvgpu-netlist.h
|
||||||
INPUT += ../../../userspace/units/fbp/nvgpu-fbp.h
|
INPUT += ../../../userspace/units/fbp/nvgpu-fbp.h
|
||||||
|
INPUT += ../../../userspace/units/fb/fb_fusa.h
|
||||||
INPUT += ../../../userspace/units/fifo/channel/nvgpu-channel.h
|
INPUT += ../../../userspace/units/fifo/channel/nvgpu-channel.h
|
||||||
INPUT += ../../../userspace/units/fifo/channel/gk20a/nvgpu-channel-gk20a.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/gm20b/nvgpu-channel-gm20b.h
|
||||||
|
|||||||
27
userspace/units/fb/Makefile
Normal file
27
userspace/units/fb/Makefile
Normal 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
|
||||||
23
userspace/units/fb/Makefile.interface.tmk
Normal file
23
userspace/units/fb/Makefile.interface.tmk
Normal 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:
|
||||||
25
userspace/units/fb/Makefile.tmk
Normal file
25
userspace/units/fb/Makefile.tmk
Normal 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:
|
||||||
158
userspace/units/fb/fb_fusa.c
Normal file
158
userspace/units/fb/fb_fusa.c
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* 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 "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);
|
||||||
|
nvgpu_posix_io_init_reg_space(g);
|
||||||
|
|
||||||
|
/* 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, 0),
|
||||||
|
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);
|
||||||
389
userspace/units/fb/fb_fusa.h
Normal file
389
userspace/units/fb/fb_fusa.h
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Test Type: Feature based, Init, 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
|
||||||
|
*
|
||||||
|
* Test Type: Feature based, 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
|
||||||
|
*
|
||||||
|
* Test Type: Feature based, 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: 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_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
|
||||||
|
*
|
||||||
|
* Test Type: Feature based
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* - 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 based
|
||||||
|
*
|
||||||
|
* 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 based
|
||||||
|
*
|
||||||
|
* 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 based
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* - 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
|
||||||
|
*
|
||||||
|
* Test Type: Feature based
|
||||||
|
*
|
||||||
|
* 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 based
|
||||||
|
*
|
||||||
|
* 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 */
|
||||||
184
userspace/units/fb/fb_gm20b_fusa.c
Normal file
184
userspace/units/fb/fb_gm20b_fusa.c
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 (2)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNIT_SUCCESS;
|
||||||
|
}
|
||||||
112
userspace/units/fb/fb_gv11b_fusa.c
Normal file
112
userspace/units/fb/fb_gv11b_fusa.c
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
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.fb_ecc_init = gv11b_fb_ecc_init;
|
||||||
|
g->ops.fb.fb_ecc_free = gv11b_fb_ecc_free;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
/* 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.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = g->ops.fb.fb_ecc_init(g);
|
||||||
|
if (err != 0) {
|
||||||
|
unit_return_fail(m, "gv11b_fb_ecc_init failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
g->ops.fb.fb_ecc_free(g);
|
||||||
|
|
||||||
|
return UNIT_SUCCESS;
|
||||||
|
}
|
||||||
211
userspace/units/fb/fb_intr_gv11b_fusa.c
Normal file
211
userspace/units/fb/fb_intr_gv11b_fusa.c
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* 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/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/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"
|
||||||
|
|
||||||
|
/* 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.fb_ecc_init = gv11b_fb_ecc_init;
|
||||||
|
g->ops.fb.fb_ecc_free = gv11b_fb_ecc_free;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* 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.fb_ecc_init(g);
|
||||||
|
|
||||||
|
/* Set the interrupt status as corrected */
|
||||||
|
nvgpu_writel(g, p->status_reg, p->corrected_status);
|
||||||
|
gv11b_fb_intr_isr(g);
|
||||||
|
|
||||||
|
/* Set the interrupt status as uncorrected */
|
||||||
|
nvgpu_writel(g, p->status_reg, p->uncorrected_status);
|
||||||
|
gv11b_fb_intr_isr(g);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
gv11b_fb_intr_isr(g);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
gv11b_fb_intr_isr(g);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
gv11b_fb_intr_isr(g);
|
||||||
|
|
||||||
|
/* 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());
|
||||||
|
gv11b_fb_intr_isr(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear interrupt status */
|
||||||
|
nvgpu_writel(g, p->status_reg, 0);
|
||||||
|
|
||||||
|
g->ops.fb.fb_ecc_free(g);
|
||||||
|
|
||||||
|
return UNIT_SUCCESS;
|
||||||
|
}
|
||||||
301
userspace/units/fb/fb_mmu_fault_gv11b_fusa.c
Normal file
301
userspace/units/fb/fb_mmu_fault_gv11b_fusa.c
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
/*
|
||||||
|
* 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 <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 <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 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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());
|
||||||
|
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 (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());
|
||||||
|
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 (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;
|
||||||
|
|
||||||
|
(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;
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user