From dc4cb04ee516c5e17181cf04d932dcc2da533388 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 25 Apr 2018 13:51:47 -0700 Subject: [PATCH] broadcom/vc5: Add QPU validation for register writes after thrend. The next shader gets to start writing the register file during these slots, so make sure we don't stomp over them. The only case of hitting this that I could imagine would be dead writes. --- src/broadcom/compiler/qpu_validate.c | 34 +++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/broadcom/compiler/qpu_validate.c b/src/broadcom/compiler/qpu_validate.c index 4ef587c1d52..492f2e64d09 100644 --- a/src/broadcom/compiler/qpu_validate.c +++ b/src/broadcom/compiler/qpu_validate.c @@ -41,7 +41,15 @@ struct v3d_qpu_validate_state { int last_sfu_write; int last_branch_ip; int last_thrsw_ip; + + /* Set when we've found the last-THRSW signal, or if we were started + * in single-segment mode. + */ bool last_thrsw_found; + + /* Set when we've found the THRSW after the last THRSW */ + bool thrend_found; + int thrsw_count; }; @@ -204,6 +212,9 @@ qpu_validate_inst(struct v3d_qpu_validate_state *state, struct qinst *qinst) if (in_branch_delay_slots(state)) fail_instr(state, "THRSW in a branch delay slot."); + if (state->last_thrsw_found) + state->thrend_found = true; + if (state->last_thrsw_ip == state->ip - 1) { /* If it's the second THRSW in a row, then it's just a * last-thrsw signal. @@ -221,6 +232,23 @@ qpu_validate_inst(struct v3d_qpu_validate_state *state, struct qinst *qinst) } } + if (state->thrend_found && + state->last_thrsw_ip - state->ip <= 2 && + inst->type == V3D_QPU_INSTR_TYPE_ALU) { + if ((inst->alu.add.op != V3D_QPU_A_NOP && + !inst->alu.add.magic_write)) { + fail_instr(state, "RF write after THREND"); + } + + if ((inst->alu.mul.op != V3D_QPU_M_NOP && + !inst->alu.mul.magic_write)) { + fail_instr(state, "RF write after THREND"); + } + + if (v3d_qpu_sig_writes_address(devinfo, &inst->sig)) + fail_instr(state, "RF write after THREND"); + } + if (inst->type == V3D_QPU_INSTR_TYPE_BRANCH) { if (in_branch_delay_slots(state)) fail_instr(state, "branch in a branch delay slot."); @@ -262,6 +290,8 @@ qpu_validate(struct v3d_compile *c) .last_thrsw_ip = -10, .last_branch_ip = -10, .ip = 0, + + .last_thrsw_found = !c->last_thrsw, }; vir_for_each_block(block, c) { @@ -273,8 +303,6 @@ qpu_validate(struct v3d_compile *c) "thread switch found without last-THRSW in program"); } - if (state.thrsw_count == 0 || - (state.last_thrsw_found && state.thrsw_count == 1)) { + if (!state.thrend_found) fail_instr(&state, "No program-end THRSW found"); - } } -- 2.30.2