brintos

brintos / linux-shallow public Read only

0
0
Text · 27.3 KiB · 9745f88 Raw
955 lines · c
1/*2 * Copyright © 2014 Broadcom3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice (including the next12 * paragraph) shall be included in all copies or substantial portions of the13 * Software.14 *15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS21 * IN THE SOFTWARE.22 */23 24/**25 * DOC: Shader validator for VC4.26 *27 * Since the VC4 has no IOMMU between it and system memory, a user28 * with access to execute shaders could escalate privilege by29 * overwriting system memory (using the VPM write address register in30 * the general-purpose DMA mode) or reading system memory it shouldn't31 * (reading it as a texture, uniform data, or direct-addressed TMU32 * lookup).33 *34 * The shader validator walks over a shader's BO, ensuring that its35 * accesses are appropriately bounded, and recording where texture36 * accesses are made so that we can do relocations for them in the37 * uniform stream.38 *39 * Shader BO are immutable for their lifetimes (enforced by not40 * allowing mmaps, GEM prime export, or rendering to from a CL), so41 * this validation is only performed at BO creation time.42 */43 44#include "vc4_drv.h"45#include "vc4_qpu_defines.h"46 47#define LIVE_REG_COUNT (32 + 32 + 4)48 49struct vc4_shader_validation_state {50	/* Current IP being validated. */51	uint32_t ip;52 53	/* IP at the end of the BO, do not read shader[max_ip] */54	uint32_t max_ip;55 56	uint64_t *shader;57 58	struct vc4_texture_sample_info tmu_setup[2];59	int tmu_write_count[2];60 61	/* For registers that were last written to by a MIN instruction with62	 * one argument being a uniform, the address of the uniform.63	 * Otherwise, ~0.64	 *65	 * This is used for the validation of direct address memory reads.66	 */67	uint32_t live_min_clamp_offsets[LIVE_REG_COUNT];68	bool live_max_clamp_regs[LIVE_REG_COUNT];69	uint32_t live_immediates[LIVE_REG_COUNT];70 71	/* Bitfield of which IPs are used as branch targets.72	 *73	 * Used for validation that the uniform stream is updated at the right74	 * points and clearing the texturing/clamping state.75	 */76	unsigned long *branch_targets;77 78	/* Set when entering a basic block, and cleared when the uniform79	 * address update is found.  This is used to make sure that we don't80	 * read uniforms when the address is undefined.81	 */82	bool needs_uniform_address_update;83 84	/* Set when we find a backwards branch.  If the branch is backwards,85	 * the taraget is probably doing an address reset to read uniforms,86	 * and so we need to be sure that a uniforms address is present in the87	 * stream, even if the shader didn't need to read uniforms in later88	 * basic blocks.89	 */90	bool needs_uniform_address_for_loop;91 92	/* Set when we find an instruction writing the top half of the93	 * register files.  If we allowed writing the unusable regs in94	 * a threaded shader, then the other shader running on our95	 * QPU's clamp validation would be invalid.96	 */97	bool all_registers_used;98};99 100static uint32_t101waddr_to_live_reg_index(uint32_t waddr, bool is_b)102{103	if (waddr < 32) {104		if (is_b)105			return 32 + waddr;106		else107			return waddr;108	} else if (waddr <= QPU_W_ACC3) {109		return 64 + waddr - QPU_W_ACC0;110	} else {111		return ~0;112	}113}114 115static uint32_t116raddr_add_a_to_live_reg_index(uint64_t inst)117{118	uint32_t sig = QPU_GET_FIELD(inst, QPU_SIG);119	uint32_t add_a = QPU_GET_FIELD(inst, QPU_ADD_A);120	uint32_t raddr_a = QPU_GET_FIELD(inst, QPU_RADDR_A);121	uint32_t raddr_b = QPU_GET_FIELD(inst, QPU_RADDR_B);122 123	if (add_a == QPU_MUX_A)124		return raddr_a;125	else if (add_a == QPU_MUX_B && sig != QPU_SIG_SMALL_IMM)126		return 32 + raddr_b;127	else if (add_a <= QPU_MUX_R3)128		return 64 + add_a;129	else130		return ~0;131}132 133static bool134live_reg_is_upper_half(uint32_t lri)135{136	return	(lri >= 16 && lri < 32) ||137		(lri >= 32 + 16 && lri < 32 + 32);138}139 140static bool141is_tmu_submit(uint32_t waddr)142{143	return (waddr == QPU_W_TMU0_S ||144		waddr == QPU_W_TMU1_S);145}146 147static bool148is_tmu_write(uint32_t waddr)149{150	return (waddr >= QPU_W_TMU0_S &&151		waddr <= QPU_W_TMU1_B);152}153 154static bool155record_texture_sample(struct vc4_validated_shader_info *validated_shader,156		      struct vc4_shader_validation_state *validation_state,157		      int tmu)158{159	uint32_t s = validated_shader->num_texture_samples;160	int i;161	struct vc4_texture_sample_info *temp_samples;162 163	temp_samples = krealloc(validated_shader->texture_samples,164				(s + 1) * sizeof(*temp_samples),165				GFP_KERNEL);166	if (!temp_samples)167		return false;168 169	memcpy(&temp_samples[s],170	       &validation_state->tmu_setup[tmu],171	       sizeof(*temp_samples));172 173	validated_shader->num_texture_samples = s + 1;174	validated_shader->texture_samples = temp_samples;175 176	for (i = 0; i < 4; i++)177		validation_state->tmu_setup[tmu].p_offset[i] = ~0;178 179	return true;180}181 182static bool183check_tmu_write(struct vc4_validated_shader_info *validated_shader,184		struct vc4_shader_validation_state *validation_state,185		bool is_mul)186{187	uint64_t inst = validation_state->shader[validation_state->ip];188	uint32_t waddr = (is_mul ?189			  QPU_GET_FIELD(inst, QPU_WADDR_MUL) :190			  QPU_GET_FIELD(inst, QPU_WADDR_ADD));191	uint32_t raddr_a = QPU_GET_FIELD(inst, QPU_RADDR_A);192	uint32_t raddr_b = QPU_GET_FIELD(inst, QPU_RADDR_B);193	int tmu = waddr > QPU_W_TMU0_B;194	bool submit = is_tmu_submit(waddr);195	bool is_direct = submit && validation_state->tmu_write_count[tmu] == 0;196	uint32_t sig = QPU_GET_FIELD(inst, QPU_SIG);197 198	if (is_direct) {199		uint32_t add_b = QPU_GET_FIELD(inst, QPU_ADD_B);200		uint32_t clamp_reg, clamp_offset;201 202		if (sig == QPU_SIG_SMALL_IMM) {203			DRM_DEBUG("direct TMU read used small immediate\n");204			return false;205		}206 207		/* Make sure that this texture load is an add of the base208		 * address of the UBO to a clamped offset within the UBO.209		 */210		if (is_mul ||211		    QPU_GET_FIELD(inst, QPU_OP_ADD) != QPU_A_ADD) {212			DRM_DEBUG("direct TMU load wasn't an add\n");213			return false;214		}215 216		/* We assert that the clamped address is the first217		 * argument, and the UBO base address is the second argument.218		 * This is arbitrary, but simpler than supporting flipping the219		 * two either way.220		 */221		clamp_reg = raddr_add_a_to_live_reg_index(inst);222		if (clamp_reg == ~0) {223			DRM_DEBUG("direct TMU load wasn't clamped\n");224			return false;225		}226 227		clamp_offset = validation_state->live_min_clamp_offsets[clamp_reg];228		if (clamp_offset == ~0) {229			DRM_DEBUG("direct TMU load wasn't clamped\n");230			return false;231		}232 233		/* Store the clamp value's offset in p1 (see reloc_tex() in234		 * vc4_validate.c).235		 */236		validation_state->tmu_setup[tmu].p_offset[1] =237			clamp_offset;238 239		if (!(add_b == QPU_MUX_A && raddr_a == QPU_R_UNIF) &&240		    !(add_b == QPU_MUX_B && raddr_b == QPU_R_UNIF)) {241			DRM_DEBUG("direct TMU load didn't add to a uniform\n");242			return false;243		}244 245		validation_state->tmu_setup[tmu].is_direct = true;246	} else {247		if (raddr_a == QPU_R_UNIF || (sig != QPU_SIG_SMALL_IMM &&248					      raddr_b == QPU_R_UNIF)) {249			DRM_DEBUG("uniform read in the same instruction as "250				  "texture setup.\n");251			return false;252		}253	}254 255	if (validation_state->tmu_write_count[tmu] >= 4) {256		DRM_DEBUG("TMU%d got too many parameters before dispatch\n",257			  tmu);258		return false;259	}260	validation_state->tmu_setup[tmu].p_offset[validation_state->tmu_write_count[tmu]] =261		validated_shader->uniforms_size;262	validation_state->tmu_write_count[tmu]++;263	/* Since direct uses a RADDR uniform reference, it will get counted in264	 * check_instruction_reads()265	 */266	if (!is_direct) {267		if (validation_state->needs_uniform_address_update) {268			DRM_DEBUG("Texturing with undefined uniform address\n");269			return false;270		}271 272		validated_shader->uniforms_size += 4;273	}274 275	if (submit) {276		if (!record_texture_sample(validated_shader,277					   validation_state, tmu)) {278			return false;279		}280 281		validation_state->tmu_write_count[tmu] = 0;282	}283 284	return true;285}286 287static bool require_uniform_address_uniform(struct vc4_validated_shader_info *validated_shader)288{289	uint32_t o = validated_shader->num_uniform_addr_offsets;290	uint32_t num_uniforms = validated_shader->uniforms_size / 4;291 292	validated_shader->uniform_addr_offsets =293		krealloc(validated_shader->uniform_addr_offsets,294			 (o + 1) *295			 sizeof(*validated_shader->uniform_addr_offsets),296			 GFP_KERNEL);297	if (!validated_shader->uniform_addr_offsets)298		return false;299 300	validated_shader->uniform_addr_offsets[o] = num_uniforms;301	validated_shader->num_uniform_addr_offsets++;302 303	return true;304}305 306static bool307validate_uniform_address_write(struct vc4_validated_shader_info *validated_shader,308			       struct vc4_shader_validation_state *validation_state,309			       bool is_mul)310{311	uint64_t inst = validation_state->shader[validation_state->ip];312	u32 add_b = QPU_GET_FIELD(inst, QPU_ADD_B);313	u32 raddr_a = QPU_GET_FIELD(inst, QPU_RADDR_A);314	u32 raddr_b = QPU_GET_FIELD(inst, QPU_RADDR_B);315	u32 add_lri = raddr_add_a_to_live_reg_index(inst);316	/* We want our reset to be pointing at whatever uniform follows the317	 * uniforms base address.318	 */319	u32 expected_offset = validated_shader->uniforms_size + 4;320 321	/* We only support absolute uniform address changes, and we322	 * require that they be in the current basic block before any323	 * of its uniform reads.324	 *325	 * One could potentially emit more efficient QPU code, by326	 * noticing that (say) an if statement does uniform control327	 * flow for all threads and that the if reads the same number328	 * of uniforms on each side.  However, this scheme is easy to329	 * validate so it's all we allow for now.330	 */331	switch (QPU_GET_FIELD(inst, QPU_SIG)) {332	case QPU_SIG_NONE:333	case QPU_SIG_SCOREBOARD_UNLOCK:334	case QPU_SIG_COLOR_LOAD:335	case QPU_SIG_LOAD_TMU0:336	case QPU_SIG_LOAD_TMU1:337		break;338	default:339		DRM_DEBUG("uniforms address change must be "340			  "normal math\n");341		return false;342	}343 344	if (is_mul || QPU_GET_FIELD(inst, QPU_OP_ADD) != QPU_A_ADD) {345		DRM_DEBUG("Uniform address reset must be an ADD.\n");346		return false;347	}348 349	if (QPU_GET_FIELD(inst, QPU_COND_ADD) != QPU_COND_ALWAYS) {350		DRM_DEBUG("Uniform address reset must be unconditional.\n");351		return false;352	}353 354	if (QPU_GET_FIELD(inst, QPU_PACK) != QPU_PACK_A_NOP &&355	    !(inst & QPU_PM)) {356		DRM_DEBUG("No packing allowed on uniforms reset\n");357		return false;358	}359 360	if (add_lri == -1) {361		DRM_DEBUG("First argument of uniform address write must be "362			  "an immediate value.\n");363		return false;364	}365 366	if (validation_state->live_immediates[add_lri] != expected_offset) {367		DRM_DEBUG("Resetting uniforms with offset %db instead of %db\n",368			  validation_state->live_immediates[add_lri],369			  expected_offset);370		return false;371	}372 373	if (!(add_b == QPU_MUX_A && raddr_a == QPU_R_UNIF) &&374	    !(add_b == QPU_MUX_B && raddr_b == QPU_R_UNIF)) {375		DRM_DEBUG("Second argument of uniform address write must be "376			  "a uniform.\n");377		return false;378	}379 380	validation_state->needs_uniform_address_update = false;381	validation_state->needs_uniform_address_for_loop = false;382	return require_uniform_address_uniform(validated_shader);383}384 385static bool386check_reg_write(struct vc4_validated_shader_info *validated_shader,387		struct vc4_shader_validation_state *validation_state,388		bool is_mul)389{390	uint64_t inst = validation_state->shader[validation_state->ip];391	uint32_t waddr = (is_mul ?392			  QPU_GET_FIELD(inst, QPU_WADDR_MUL) :393			  QPU_GET_FIELD(inst, QPU_WADDR_ADD));394	uint32_t sig = QPU_GET_FIELD(inst, QPU_SIG);395	bool ws = inst & QPU_WS;396	bool is_b = is_mul ^ ws;397	u32 lri = waddr_to_live_reg_index(waddr, is_b);398 399	if (lri != -1) {400		uint32_t cond_add = QPU_GET_FIELD(inst, QPU_COND_ADD);401		uint32_t cond_mul = QPU_GET_FIELD(inst, QPU_COND_MUL);402 403		if (sig == QPU_SIG_LOAD_IMM &&404		    QPU_GET_FIELD(inst, QPU_PACK) == QPU_PACK_A_NOP &&405		    ((is_mul && cond_mul == QPU_COND_ALWAYS) ||406		     (!is_mul && cond_add == QPU_COND_ALWAYS))) {407			validation_state->live_immediates[lri] =408				QPU_GET_FIELD(inst, QPU_LOAD_IMM);409		} else {410			validation_state->live_immediates[lri] = ~0;411		}412 413		if (live_reg_is_upper_half(lri))414			validation_state->all_registers_used = true;415	}416 417	switch (waddr) {418	case QPU_W_UNIFORMS_ADDRESS:419		if (is_b) {420			DRM_DEBUG("relative uniforms address change "421				  "unsupported\n");422			return false;423		}424 425		return validate_uniform_address_write(validated_shader,426						      validation_state,427						      is_mul);428 429	case QPU_W_TLB_COLOR_MS:430	case QPU_W_TLB_COLOR_ALL:431	case QPU_W_TLB_Z:432		/* These only interact with the tile buffer, not main memory,433		 * so they're safe.434		 */435		return true;436 437	case QPU_W_TMU0_S:438	case QPU_W_TMU0_T:439	case QPU_W_TMU0_R:440	case QPU_W_TMU0_B:441	case QPU_W_TMU1_S:442	case QPU_W_TMU1_T:443	case QPU_W_TMU1_R:444	case QPU_W_TMU1_B:445		return check_tmu_write(validated_shader, validation_state,446				       is_mul);447 448	case QPU_W_HOST_INT:449	case QPU_W_TMU_NOSWAP:450	case QPU_W_TLB_ALPHA_MASK:451	case QPU_W_MUTEX_RELEASE:452		/* XXX: I haven't thought about these, so don't support them453		 * for now.454		 */455		DRM_DEBUG("Unsupported waddr %d\n", waddr);456		return false;457 458	case QPU_W_VPM_ADDR:459		DRM_DEBUG("General VPM DMA unsupported\n");460		return false;461 462	case QPU_W_VPM:463	case QPU_W_VPMVCD_SETUP:464		/* We allow VPM setup in general, even including VPM DMA465		 * configuration setup, because the (unsafe) DMA can only be466		 * triggered by QPU_W_VPM_ADDR writes.467		 */468		return true;469 470	case QPU_W_TLB_STENCIL_SETUP:471		return true;472	}473 474	return true;475}476 477static void478track_live_clamps(struct vc4_validated_shader_info *validated_shader,479		  struct vc4_shader_validation_state *validation_state)480{481	uint64_t inst = validation_state->shader[validation_state->ip];482	uint32_t op_add = QPU_GET_FIELD(inst, QPU_OP_ADD);483	uint32_t waddr_add = QPU_GET_FIELD(inst, QPU_WADDR_ADD);484	uint32_t waddr_mul = QPU_GET_FIELD(inst, QPU_WADDR_MUL);485	uint32_t cond_add = QPU_GET_FIELD(inst, QPU_COND_ADD);486	uint32_t add_a = QPU_GET_FIELD(inst, QPU_ADD_A);487	uint32_t add_b = QPU_GET_FIELD(inst, QPU_ADD_B);488	uint32_t raddr_a = QPU_GET_FIELD(inst, QPU_RADDR_A);489	uint32_t raddr_b = QPU_GET_FIELD(inst, QPU_RADDR_B);490	uint32_t sig = QPU_GET_FIELD(inst, QPU_SIG);491	bool ws = inst & QPU_WS;492	uint32_t lri_add_a, lri_add, lri_mul;493	bool add_a_is_min_0;494 495	/* Check whether OP_ADD's A argumennt comes from a live MAX(x, 0),496	 * before we clear previous live state.497	 */498	lri_add_a = raddr_add_a_to_live_reg_index(inst);499	add_a_is_min_0 = (lri_add_a != ~0 &&500			  validation_state->live_max_clamp_regs[lri_add_a]);501 502	/* Clear live state for registers written by our instruction. */503	lri_add = waddr_to_live_reg_index(waddr_add, ws);504	lri_mul = waddr_to_live_reg_index(waddr_mul, !ws);505	if (lri_mul != ~0) {506		validation_state->live_max_clamp_regs[lri_mul] = false;507		validation_state->live_min_clamp_offsets[lri_mul] = ~0;508	}509	if (lri_add != ~0) {510		validation_state->live_max_clamp_regs[lri_add] = false;511		validation_state->live_min_clamp_offsets[lri_add] = ~0;512	} else {513		/* Nothing further to do for live tracking, since only ADDs514		 * generate new live clamp registers.515		 */516		return;517	}518 519	/* Now, handle remaining live clamp tracking for the ADD operation. */520 521	if (cond_add != QPU_COND_ALWAYS)522		return;523 524	if (op_add == QPU_A_MAX) {525		/* Track live clamps of a value to a minimum of 0 (in either526		 * arg).527		 */528		if (sig != QPU_SIG_SMALL_IMM || raddr_b != 0 ||529		    (add_a != QPU_MUX_B && add_b != QPU_MUX_B)) {530			return;531		}532 533		validation_state->live_max_clamp_regs[lri_add] = true;534	} else if (op_add == QPU_A_MIN) {535		/* Track live clamps of a value clamped to a minimum of 0 and536		 * a maximum of some uniform's offset.537		 */538		if (!add_a_is_min_0)539			return;540 541		if (!(add_b == QPU_MUX_A && raddr_a == QPU_R_UNIF) &&542		    !(add_b == QPU_MUX_B && raddr_b == QPU_R_UNIF &&543		      sig != QPU_SIG_SMALL_IMM)) {544			return;545		}546 547		validation_state->live_min_clamp_offsets[lri_add] =548			validated_shader->uniforms_size;549	}550}551 552static bool553check_instruction_writes(struct vc4_validated_shader_info *validated_shader,554			 struct vc4_shader_validation_state *validation_state)555{556	uint64_t inst = validation_state->shader[validation_state->ip];557	uint32_t waddr_add = QPU_GET_FIELD(inst, QPU_WADDR_ADD);558	uint32_t waddr_mul = QPU_GET_FIELD(inst, QPU_WADDR_MUL);559	bool ok;560 561	if (is_tmu_write(waddr_add) && is_tmu_write(waddr_mul)) {562		DRM_DEBUG("ADD and MUL both set up textures\n");563		return false;564	}565 566	ok = (check_reg_write(validated_shader, validation_state, false) &&567	      check_reg_write(validated_shader, validation_state, true));568 569	track_live_clamps(validated_shader, validation_state);570 571	return ok;572}573 574static bool575check_branch(uint64_t inst,576	     struct vc4_validated_shader_info *validated_shader,577	     struct vc4_shader_validation_state *validation_state,578	     int ip)579{580	int32_t branch_imm = QPU_GET_FIELD(inst, QPU_BRANCH_TARGET);581	uint32_t waddr_add = QPU_GET_FIELD(inst, QPU_WADDR_ADD);582	uint32_t waddr_mul = QPU_GET_FIELD(inst, QPU_WADDR_MUL);583 584	if ((int)branch_imm < 0)585		validation_state->needs_uniform_address_for_loop = true;586 587	/* We don't want to have to worry about validation of this, and588	 * there's no need for it.589	 */590	if (waddr_add != QPU_W_NOP || waddr_mul != QPU_W_NOP) {591		DRM_DEBUG("branch instruction at %d wrote a register.\n",592			  validation_state->ip);593		return false;594	}595 596	return true;597}598 599static bool600check_instruction_reads(struct vc4_validated_shader_info *validated_shader,601			struct vc4_shader_validation_state *validation_state)602{603	uint64_t inst = validation_state->shader[validation_state->ip];604	uint32_t raddr_a = QPU_GET_FIELD(inst, QPU_RADDR_A);605	uint32_t raddr_b = QPU_GET_FIELD(inst, QPU_RADDR_B);606	uint32_t sig = QPU_GET_FIELD(inst, QPU_SIG);607 608	if (raddr_a == QPU_R_UNIF ||609	    (raddr_b == QPU_R_UNIF && sig != QPU_SIG_SMALL_IMM)) {610		/* This can't overflow the uint32_t, because we're reading 8611		 * bytes of instruction to increment by 4 here, so we'd612		 * already be OOM.613		 */614		validated_shader->uniforms_size += 4;615 616		if (validation_state->needs_uniform_address_update) {617			DRM_DEBUG("Uniform read with undefined uniform "618				  "address\n");619			return false;620		}621	}622 623	if ((raddr_a >= 16 && raddr_a < 32) ||624	    (raddr_b >= 16 && raddr_b < 32 && sig != QPU_SIG_SMALL_IMM)) {625		validation_state->all_registers_used = true;626	}627 628	return true;629}630 631/* Make sure that all branches are absolute and point within the shader, and632 * note their targets for later.633 */634static bool635vc4_validate_branches(struct vc4_shader_validation_state *validation_state)636{637	uint32_t max_branch_target = 0;638	int ip;639	int last_branch = -2;640 641	for (ip = 0; ip < validation_state->max_ip; ip++) {642		uint64_t inst = validation_state->shader[ip];643		int32_t branch_imm = QPU_GET_FIELD(inst, QPU_BRANCH_TARGET);644		uint32_t sig = QPU_GET_FIELD(inst, QPU_SIG);645		uint32_t after_delay_ip = ip + 4;646		uint32_t branch_target_ip;647 648		if (sig == QPU_SIG_PROG_END) {649			/* There are two delay slots after program end is650			 * signaled that are still executed, then we're651			 * finished.  validation_state->max_ip is the652			 * instruction after the last valid instruction in the653			 * program.654			 */655			validation_state->max_ip = ip + 3;656			continue;657		}658 659		if (sig != QPU_SIG_BRANCH)660			continue;661 662		if (ip - last_branch < 4) {663			DRM_DEBUG("Branch at %d during delay slots\n", ip);664			return false;665		}666		last_branch = ip;667 668		if (inst & QPU_BRANCH_REG) {669			DRM_DEBUG("branching from register relative "670				  "not supported\n");671			return false;672		}673 674		if (!(inst & QPU_BRANCH_REL)) {675			DRM_DEBUG("relative branching required\n");676			return false;677		}678 679		/* The actual branch target is the instruction after the delay680		 * slots, plus whatever byte offset is in the low 32 bits of681		 * the instruction.  Make sure we're not branching beyond the682		 * end of the shader object.683		 */684		if (branch_imm % sizeof(inst) != 0) {685			DRM_DEBUG("branch target not aligned\n");686			return false;687		}688 689		branch_target_ip = after_delay_ip + (branch_imm >> 3);690		if (branch_target_ip >= validation_state->max_ip) {691			DRM_DEBUG("Branch at %d outside of shader (ip %d/%d)\n",692				  ip, branch_target_ip,693				  validation_state->max_ip);694			return false;695		}696		set_bit(branch_target_ip, validation_state->branch_targets);697 698		/* Make sure that the non-branching path is also not outside699		 * the shader.700		 */701		if (after_delay_ip >= validation_state->max_ip) {702			DRM_DEBUG("Branch at %d continues past shader end "703				  "(%d/%d)\n",704				  ip, after_delay_ip, validation_state->max_ip);705			return false;706		}707		set_bit(after_delay_ip, validation_state->branch_targets);708		max_branch_target = max(max_branch_target, after_delay_ip);709	}710 711	if (max_branch_target > validation_state->max_ip - 3) {712		DRM_DEBUG("Branch landed after QPU_SIG_PROG_END");713		return false;714	}715 716	return true;717}718 719/* Resets any known state for the shader, used when we may be branched to from720 * multiple locations in the program (or at shader start).721 */722static void723reset_validation_state(struct vc4_shader_validation_state *validation_state)724{725	int i;726 727	for (i = 0; i < 8; i++)728		validation_state->tmu_setup[i / 4].p_offset[i % 4] = ~0;729 730	for (i = 0; i < LIVE_REG_COUNT; i++) {731		validation_state->live_min_clamp_offsets[i] = ~0;732		validation_state->live_max_clamp_regs[i] = false;733		validation_state->live_immediates[i] = ~0;734	}735}736 737static bool738texturing_in_progress(struct vc4_shader_validation_state *validation_state)739{740	return (validation_state->tmu_write_count[0] != 0 ||741		validation_state->tmu_write_count[1] != 0);742}743 744static bool745vc4_handle_branch_target(struct vc4_shader_validation_state *validation_state)746{747	uint32_t ip = validation_state->ip;748 749	if (!test_bit(ip, validation_state->branch_targets))750		return true;751 752	if (texturing_in_progress(validation_state)) {753		DRM_DEBUG("Branch target landed during TMU setup\n");754		return false;755	}756 757	/* Reset our live values tracking, since this instruction may have758	 * multiple predecessors.759	 *760	 * One could potentially do analysis to determine that, for761	 * example, all predecessors have a live max clamp in the same762	 * register, but we don't bother with that.763	 */764	reset_validation_state(validation_state);765 766	/* Since we've entered a basic block from potentially multiple767	 * predecessors, we need the uniforms address to be updated before any768	 * unforms are read.  We require that after any branch point, the next769	 * uniform to be loaded is a uniform address offset.  That uniform's770	 * offset will be marked by the uniform address register write771	 * validation, or a one-off the end-of-program check.772	 */773	validation_state->needs_uniform_address_update = true;774 775	return true;776}777 778struct vc4_validated_shader_info *779vc4_validate_shader(struct drm_gem_dma_object *shader_obj)780{781	struct vc4_dev *vc4 = to_vc4_dev(shader_obj->base.dev);782	bool found_shader_end = false;783	int shader_end_ip = 0;784	uint32_t last_thread_switch_ip = -3;785	uint32_t ip;786	struct vc4_validated_shader_info *validated_shader = NULL;787	struct vc4_shader_validation_state validation_state;788 789	if (WARN_ON_ONCE(vc4->is_vc5))790		return NULL;791 792	memset(&validation_state, 0, sizeof(validation_state));793	validation_state.shader = shader_obj->vaddr;794	validation_state.max_ip = shader_obj->base.size / sizeof(uint64_t);795 796	reset_validation_state(&validation_state);797 798	validation_state.branch_targets =799		kcalloc(BITS_TO_LONGS(validation_state.max_ip),800			sizeof(unsigned long), GFP_KERNEL);801	if (!validation_state.branch_targets)802		goto fail;803 804	validated_shader = kcalloc(1, sizeof(*validated_shader), GFP_KERNEL);805	if (!validated_shader)806		goto fail;807 808	if (!vc4_validate_branches(&validation_state))809		goto fail;810 811	for (ip = 0; ip < validation_state.max_ip; ip++) {812		uint64_t inst = validation_state.shader[ip];813		uint32_t sig = QPU_GET_FIELD(inst, QPU_SIG);814 815		validation_state.ip = ip;816 817		if (!vc4_handle_branch_target(&validation_state))818			goto fail;819 820		if (ip == last_thread_switch_ip + 3) {821			/* Reset r0-r3 live clamp data */822			int i;823 824			for (i = 64; i < LIVE_REG_COUNT; i++) {825				validation_state.live_min_clamp_offsets[i] = ~0;826				validation_state.live_max_clamp_regs[i] = false;827				validation_state.live_immediates[i] = ~0;828			}829		}830 831		switch (sig) {832		case QPU_SIG_NONE:833		case QPU_SIG_WAIT_FOR_SCOREBOARD:834		case QPU_SIG_SCOREBOARD_UNLOCK:835		case QPU_SIG_COLOR_LOAD:836		case QPU_SIG_LOAD_TMU0:837		case QPU_SIG_LOAD_TMU1:838		case QPU_SIG_PROG_END:839		case QPU_SIG_SMALL_IMM:840		case QPU_SIG_THREAD_SWITCH:841		case QPU_SIG_LAST_THREAD_SWITCH:842			if (!check_instruction_writes(validated_shader,843						      &validation_state)) {844				DRM_DEBUG("Bad write at ip %d\n", ip);845				goto fail;846			}847 848			if (!check_instruction_reads(validated_shader,849						     &validation_state))850				goto fail;851 852			if (sig == QPU_SIG_PROG_END) {853				found_shader_end = true;854				shader_end_ip = ip;855			}856 857			if (sig == QPU_SIG_THREAD_SWITCH ||858			    sig == QPU_SIG_LAST_THREAD_SWITCH) {859				validated_shader->is_threaded = true;860 861				if (ip < last_thread_switch_ip + 3) {862					DRM_DEBUG("Thread switch too soon after "863						  "last switch at ip %d\n", ip);864					goto fail;865				}866				last_thread_switch_ip = ip;867			}868 869			break;870 871		case QPU_SIG_LOAD_IMM:872			if (!check_instruction_writes(validated_shader,873						      &validation_state)) {874				DRM_DEBUG("Bad LOAD_IMM write at ip %d\n", ip);875				goto fail;876			}877			break;878 879		case QPU_SIG_BRANCH:880			if (!check_branch(inst, validated_shader,881					  &validation_state, ip))882				goto fail;883 884			if (ip < last_thread_switch_ip + 3) {885				DRM_DEBUG("Branch in thread switch at ip %d",886					  ip);887				goto fail;888			}889 890			break;891		default:892			DRM_DEBUG("Unsupported QPU signal %d at "893				  "instruction %d\n", sig, ip);894			goto fail;895		}896 897		/* There are two delay slots after program end is signaled898		 * that are still executed, then we're finished.899		 */900		if (found_shader_end && ip == shader_end_ip + 2)901			break;902	}903 904	if (ip == validation_state.max_ip) {905		DRM_DEBUG("shader failed to terminate before "906			  "shader BO end at %zd\n",907			  shader_obj->base.size);908		goto fail;909	}910 911	/* Might corrupt other thread */912	if (validated_shader->is_threaded &&913	    validation_state.all_registers_used) {914		DRM_DEBUG("Shader uses threading, but uses the upper "915			  "half of the registers, too\n");916		goto fail;917	}918 919	/* If we did a backwards branch and we haven't emitted a uniforms920	 * reset since then, we still need the uniforms stream to have the921	 * uniforms address available so that the backwards branch can do its922	 * uniforms reset.923	 *924	 * We could potentially prove that the backwards branch doesn't925	 * contain any uses of uniforms until program exit, but that doesn't926	 * seem to be worth the trouble.927	 */928	if (validation_state.needs_uniform_address_for_loop) {929		if (!require_uniform_address_uniform(validated_shader))930			goto fail;931		validated_shader->uniforms_size += 4;932	}933 934	/* Again, no chance of integer overflow here because the worst case935	 * scenario is 8 bytes of uniforms plus handles per 8-byte936	 * instruction.937	 */938	validated_shader->uniforms_src_size =939		(validated_shader->uniforms_size +940		 4 * validated_shader->num_texture_samples);941 942	kfree(validation_state.branch_targets);943 944	return validated_shader;945 946fail:947	kfree(validation_state.branch_targets);948	if (validated_shader) {949		kfree(validated_shader->uniform_addr_offsets);950		kfree(validated_shader->texture_samples);951		kfree(validated_shader);952	}953	return NULL;954}955