diff --git a/userspace/units/fb/fb_fusa.h b/userspace/units/fb/fb_fusa.h index 53d7a41ed..da48fb0f9 100644 --- a/userspace/units/fb/fb_fusa.h +++ b/userspace/units/fb/fb_fusa.h @@ -175,7 +175,7 @@ int fb_mmu_fault_gv11b_init_test(struct unit_module *m, struct gk20a *g, * gv11b_fb_fault_buffer_size_val, gv11b_fb_read_mmu_fault_inst_lo_hi, * gv11b_fb_read_mmu_fault_info * - * Test Type: Feature + * Test Type: Feature, Error injection * * Input: fb_mmu_fault_gv11b_init_test * @@ -187,6 +187,8 @@ int fb_mmu_fault_gv11b_init_test(struct unit_module *m, struct gk20a *g, * 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 @@ -273,7 +275,7 @@ int fb_mmu_fault_gv11b_handle_fault(struct unit_module *m, struct gk20a *g, * Targets: gv11b_fb_handle_bar2_fault, gv11b_fb_mmu_fault_info_dump, * gv11b_fb_fault_buf_set_state_hw * - * Test Type: Feature + * Test Type: Feature, Error injection * * Input: fb_mmu_fault_gv11b_init_test * @@ -286,6 +288,8 @@ int fb_mmu_fault_gv11b_handle_fault(struct unit_module *m, struct gk20a *g, * 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 diff --git a/userspace/units/fb/fb_gm20b_fusa.c b/userspace/units/fb/fb_gm20b_fusa.c index a5d76f0b7..c61f1f5e6 100644 --- a/userspace/units/fb/fb_gm20b_fusa.c +++ b/userspace/units/fb/fb_gm20b_fusa.c @@ -169,6 +169,14 @@ int fb_gm20b_mmu_ctrl_test(struct unit_module *m, struct gk20a *g, void *args) "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() @@ -177,7 +185,7 @@ int fb_gm20b_mmu_ctrl_test(struct unit_module *m, struct gk20a *g, void *args) 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"); + "vpr_info_fetch did not fail as expected (3)\n"); } return UNIT_SUCCESS; diff --git a/userspace/units/fb/fb_mmu_fault_gv11b_fusa.c b/userspace/units/fb/fb_mmu_fault_gv11b_fusa.c index ac626a0f1..1af9e7523 100644 --- a/userspace/units/fb/fb_mmu_fault_gv11b_fusa.c +++ b/userspace/units/fb/fb_mmu_fault_gv11b_fusa.c @@ -59,6 +59,11 @@ static int hal_bar2_bind_nop(struct gk20a *g, struct nvgpu_mem *bar2_inst) 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; @@ -107,6 +112,8 @@ int fb_mmu_fault_gv11b_buffer_test(struct unit_module *m, struct gk20a *g, 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"); @@ -134,6 +141,11 @@ int fb_mmu_fault_gv11b_buffer_test(struct unit_module *m, struct gk20a *g, /* 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); @@ -247,7 +259,6 @@ int fb_mmu_fault_gv11b_handle_fault(struct unit_module *m, struct gk20a *g, /* 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"); @@ -257,7 +268,6 @@ int fb_mmu_fault_gv11b_handle_fault(struct unit_module *m, struct gk20a *g, 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"); @@ -298,6 +308,12 @@ int fb_mmu_fault_gv11b_handle_bar2_fault(struct unit_module *m, struct gk20a *g, 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);