diff --git a/drivers/gpu/nvgpu/common/falcon/falcon.c b/drivers/gpu/nvgpu/common/falcon/falcon.c index c30a57874..54e44d317 100644 --- a/drivers/gpu/nvgpu/common/falcon/falcon.c +++ b/drivers/gpu/nvgpu/common/falcon/falcon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-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"), @@ -164,7 +164,7 @@ int nvgpu_falcon_mem_scrub_wait(struct nvgpu_falcon *flcn) do { if (g->ops.falcon.is_falcon_scrubbing_done(flcn)) { - goto exit; + break; } nvgpu_udelay(MEM_SCRUBBING_TIMEOUT_DEFAULT); } while (nvgpu_timeout_expired(&timeout) == 0); @@ -173,7 +173,6 @@ int nvgpu_falcon_mem_scrub_wait(struct nvgpu_falcon *flcn) status = -ETIMEDOUT; } -exit: return status; } diff --git a/drivers/gpu/nvgpu/include/nvgpu/posix/posix-fault-injection.h b/drivers/gpu/nvgpu/include/nvgpu/posix/posix-fault-injection.h index 035f1c3c0..72a447719 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/posix/posix-fault-injection.h +++ b/drivers/gpu/nvgpu/include/nvgpu/posix/posix-fault-injection.h @@ -48,6 +48,7 @@ struct nvgpu_posix_fault_inj_container { struct nvgpu_posix_fault_inj dma_fi; struct nvgpu_posix_fault_inj queue_out_fi; struct nvgpu_posix_fault_inj timers_fi; + struct nvgpu_posix_fault_inj falcon_memcpy_fi; /* qnx */ struct nvgpu_posix_fault_inj sdl_nvguard_fi; diff --git a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export index 57a060c85..dd6525e63 100644 --- a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export +++ b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export @@ -1,4 +1,4 @@ -# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. bitmap_find_next_zero_area_off bug_handler_cancel @@ -587,6 +587,8 @@ nvgpu_pmu_reset nvgpu_posix_bug nvgpu_posix_cleanup nvgpu_posix_enable_fault_injection +nvgpu_posix_fault_injection_get_container +nvgpu_posix_fault_injection_handle_call nvgpu_posix_ffs nvgpu_posix_fls nvgpu_posix_init_fault_injection diff --git a/userspace/required_tests.json b/userspace/required_tests.json index 1fecb8a5d..481e5125c 100644 --- a/userspace/required_tests.json +++ b/userspace/required_tests.json @@ -593,6 +593,12 @@ "unit": "falcon", "test_level": 0 }, + { + "test": "test_falcon_mem_rw_fault", + "case": "falcon_mem_rw_fault", + "unit": "falcon", + "test_level": 0 + }, { "test": "test_falcon_mem_rw_init", "case": "falcon_mem_rw_init", diff --git a/userspace/units/falcon/falcon_tests/falcon.c b/userspace/units/falcon/falcon_tests/falcon.c index 7fac36f72..6c9354169 100644 --- a/userspace/units/falcon/falcon_tests/falcon.c +++ b/userspace/units/falcon/falcon_tests/falcon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * 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"), @@ -964,6 +964,38 @@ int test_falcon_mem_rw_range(struct unit_module *m, struct gk20a *g, return UNIT_SUCCESS; } +/* + * Writing data to falcon's DMEM should not succeed when DMEMC + * read returns invalid value due to HW fault. + */ +int test_falcon_mem_rw_fault(struct unit_module *m, struct gk20a *g, + void *__args) +{ + struct nvgpu_posix_fault_inj *falcon_memcpy_fi = + nvgpu_utf_falcon_memcpy_get_fault_injection(); + u32 byte_cnt = RAND_DATA_SIZE; + u32 dst = 0; + int err = UNIT_FAIL; + + if (pmu_flcn == NULL || !pmu_flcn->is_falcon_supported) { + unit_return_fail(m, "test environment not initialized."); + } + + /* cause write failure */ + nvgpu_posix_enable_fault_injection(falcon_memcpy_fi, true, 0); + unit_info(m, "Writing %d bytes to dmem with hw fault injected.\n", + byte_cnt); + err = nvgpu_falcon_copy_to_dmem(pmu_flcn, dst, (u8 *) rand_test_data, + byte_cnt, 0); + nvgpu_posix_enable_fault_injection(falcon_memcpy_fi, false, 0); + + if (err == 0) { + unit_return_fail(m, "Copy to DMEM succeeded with faulty hw.\n"); + } + + return UNIT_SUCCESS; +} + /* * Valid/Invalid: Reading and writing data at offset that is word (4-byte) * aligned data should work and fail otherwise. @@ -1353,6 +1385,7 @@ struct unit_module_test falcon_tests[] = { UNIT_TEST(falcon_mem_rw_unaligned_cpu_buffer, test_falcon_mem_rw_unaligned_cpu_buffer, NULL, 0), UNIT_TEST(falcon_mem_rw_range, test_falcon_mem_rw_range, NULL, 0), + UNIT_TEST(falcon_mem_rw_fault, test_falcon_mem_rw_fault, NULL, 0), UNIT_TEST(falcon_mem_rw_aligned, test_falcon_mem_rw_aligned, NULL, 0), UNIT_TEST(falcon_mem_rw_zero, test_falcon_mem_rw_zero, NULL, 0), UNIT_TEST(falcon_mailbox, test_falcon_mailbox, NULL, 0), diff --git a/userspace/units/falcon/falcon_tests/nvgpu-falcon.h b/userspace/units/falcon/falcon_tests/nvgpu-falcon.h index 6af5ffef3..1145985d3 100644 --- a/userspace/units/falcon/falcon_tests/nvgpu-falcon.h +++ b/userspace/units/falcon/falcon_tests/nvgpu-falcon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * 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"), @@ -216,6 +216,29 @@ int test_falcon_mem_rw_init(struct unit_module *m, struct gk20a *g, 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 + * + * 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 * diff --git a/userspace/units/falcon/falcon_utf.c b/userspace/units/falcon/falcon_utf.c index d7f382c6f..583902214 100644 --- a/userspace/units/falcon/falcon_utf.c +++ b/userspace/units/falcon/falcon_utf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * 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"), @@ -29,6 +29,16 @@ #include "falcon_utf.h" +#include + +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) @@ -139,6 +149,12 @@ void nvgpu_utf_falcon_readl_access_reg_fn(struct gk20a *g, 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); diff --git a/userspace/units/falcon/falcon_utf.h b/userspace/units/falcon/falcon_utf.h index 3ca6cb73e..520213ab7 100644 --- a/userspace/units/falcon/falcon_utf.h +++ b/userspace/units/falcon/falcon_utf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * 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"), @@ -38,6 +38,8 @@ struct utf_falcon { 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); diff --git a/userspace/units/falcon/libfalcon_utf.export b/userspace/units/falcon/libfalcon_utf.export index 50a81d377..b29689d2a 100644 --- a/userspace/units/falcon/libfalcon_utf.export +++ b/userspace/units/falcon/libfalcon_utf.export @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +# 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"), @@ -25,3 +25,4 @@ 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