mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	drm/amdkfd: Add wave control operation to debugger
The wave control operation supports several command types executed upon existing wave fronts that belong to the currently debugged process. The available commands are: HALT - Freeze wave front(s) execution RESUME - Resume freezed wave front(s) execution KILL - Kill existing wave front(s) Signed-off-by: Yair Shachar <yair.shachar@amd.com> Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
This commit is contained in:
		
							parent
							
								
									fbeb661bfa
								
							
						
					
					
						commit
						788bf83db3
					
				| @ -47,6 +47,125 @@ static void dbgdev_address_watch_disable_nodiq(struct kfd_dev *dev) | |||||||
| 	dev->kfd2kgd->address_watch_disable(dev->kgd); | 	dev->kfd2kgd->address_watch_disable(dev->kgd); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int dbgdev_diq_submit_ib(struct kfd_dbgdev *dbgdev, | ||||||
|  | 				unsigned int pasid, uint64_t vmid0_address, | ||||||
|  | 				uint32_t *packet_buff, size_t size_in_bytes) | ||||||
|  | { | ||||||
|  | 	struct pm4__release_mem *rm_packet; | ||||||
|  | 	struct pm4__indirect_buffer_pasid *ib_packet; | ||||||
|  | 	struct kfd_mem_obj *mem_obj; | ||||||
|  | 	size_t pq_packets_size_in_bytes; | ||||||
|  | 	union ULARGE_INTEGER *largep; | ||||||
|  | 	union ULARGE_INTEGER addr; | ||||||
|  | 	struct kernel_queue *kq; | ||||||
|  | 	uint64_t *rm_state; | ||||||
|  | 	unsigned int *ib_packet_buff; | ||||||
|  | 	int status; | ||||||
|  | 
 | ||||||
|  | 	BUG_ON(!dbgdev || !dbgdev->kq || !packet_buff || !size_in_bytes); | ||||||
|  | 
 | ||||||
|  | 	kq = dbgdev->kq; | ||||||
|  | 
 | ||||||
|  | 	pq_packets_size_in_bytes = sizeof(struct pm4__release_mem) + | ||||||
|  | 				sizeof(struct pm4__indirect_buffer_pasid); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * We acquire a buffer from DIQ | ||||||
|  | 	 * The receive packet buff will be sitting on the Indirect Buffer | ||||||
|  | 	 * and in the PQ we put the IB packet + sync packet(s). | ||||||
|  | 	 */ | ||||||
|  | 	status = kq->ops.acquire_packet_buffer(kq, | ||||||
|  | 				pq_packets_size_in_bytes / sizeof(uint32_t), | ||||||
|  | 				&ib_packet_buff); | ||||||
|  | 	if (status != 0) { | ||||||
|  | 		pr_err("amdkfd: acquire_packet_buffer failed\n"); | ||||||
|  | 		return status; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	memset(ib_packet_buff, 0, pq_packets_size_in_bytes); | ||||||
|  | 
 | ||||||
|  | 	ib_packet = (struct pm4__indirect_buffer_pasid *) (ib_packet_buff); | ||||||
|  | 
 | ||||||
|  | 	ib_packet->header.count = 3; | ||||||
|  | 	ib_packet->header.opcode = IT_INDIRECT_BUFFER_PASID; | ||||||
|  | 	ib_packet->header.type = PM4_TYPE_3; | ||||||
|  | 
 | ||||||
|  | 	largep = (union ULARGE_INTEGER *) &vmid0_address; | ||||||
|  | 
 | ||||||
|  | 	ib_packet->bitfields2.ib_base_lo = largep->u.low_part >> 2; | ||||||
|  | 	ib_packet->bitfields3.ib_base_hi = largep->u.high_part; | ||||||
|  | 
 | ||||||
|  | 	ib_packet->control = (1 << 23) | (1 << 31) | | ||||||
|  | 			((size_in_bytes / sizeof(uint32_t)) & 0xfffff); | ||||||
|  | 
 | ||||||
|  | 	ib_packet->bitfields5.pasid = pasid; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * for now we use release mem for GPU-CPU synchronization | ||||||
|  | 	 * Consider WaitRegMem + WriteData as a better alternative | ||||||
|  | 	 * we get a GART allocations ( gpu/cpu mapping), | ||||||
|  | 	 * for the sync variable, and wait until: | ||||||
|  | 	 * (a) Sync with HW | ||||||
|  | 	 * (b) Sync var is written by CP to mem. | ||||||
|  | 	 */ | ||||||
|  | 	rm_packet = (struct pm4__release_mem *) (ib_packet_buff + | ||||||
|  | 			(sizeof(struct pm4__indirect_buffer_pasid) / | ||||||
|  | 					sizeof(unsigned int))); | ||||||
|  | 
 | ||||||
|  | 	status = kfd_gtt_sa_allocate(dbgdev->dev, sizeof(uint64_t), | ||||||
|  | 					&mem_obj); | ||||||
|  | 
 | ||||||
|  | 	if (status != 0) { | ||||||
|  | 		pr_err("amdkfd: Failed to allocate GART memory\n"); | ||||||
|  | 		kq->ops.rollback_packet(kq); | ||||||
|  | 		return status; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	rm_state = (uint64_t *) mem_obj->cpu_ptr; | ||||||
|  | 
 | ||||||
|  | 	*rm_state = QUEUESTATE__ACTIVE_COMPLETION_PENDING; | ||||||
|  | 
 | ||||||
|  | 	rm_packet->header.opcode = IT_RELEASE_MEM; | ||||||
|  | 	rm_packet->header.type = PM4_TYPE_3; | ||||||
|  | 	rm_packet->header.count = sizeof(struct pm4__release_mem) / | ||||||
|  | 					sizeof(unsigned int) - 2; | ||||||
|  | 
 | ||||||
|  | 	rm_packet->bitfields2.event_type = CACHE_FLUSH_AND_INV_TS_EVENT; | ||||||
|  | 	rm_packet->bitfields2.event_index = | ||||||
|  | 				event_index___release_mem__end_of_pipe; | ||||||
|  | 
 | ||||||
|  | 	rm_packet->bitfields2.cache_policy = cache_policy___release_mem__lru; | ||||||
|  | 	rm_packet->bitfields2.atc = 0; | ||||||
|  | 	rm_packet->bitfields2.tc_wb_action_ena = 1; | ||||||
|  | 
 | ||||||
|  | 	addr.quad_part = mem_obj->gpu_addr; | ||||||
|  | 
 | ||||||
|  | 	rm_packet->bitfields4.address_lo_32b = addr.u.low_part >> 2; | ||||||
|  | 	rm_packet->address_hi = addr.u.high_part; | ||||||
|  | 
 | ||||||
|  | 	rm_packet->bitfields3.data_sel = | ||||||
|  | 				data_sel___release_mem__send_64_bit_data; | ||||||
|  | 
 | ||||||
|  | 	rm_packet->bitfields3.int_sel = | ||||||
|  | 			int_sel___release_mem__send_data_after_write_confirm; | ||||||
|  | 
 | ||||||
|  | 	rm_packet->bitfields3.dst_sel = | ||||||
|  | 			dst_sel___release_mem__memory_controller; | ||||||
|  | 
 | ||||||
|  | 	rm_packet->data_lo = QUEUESTATE__ACTIVE; | ||||||
|  | 
 | ||||||
|  | 	kq->ops.submit_packet(kq); | ||||||
|  | 
 | ||||||
|  | 	/* Wait till CP writes sync code: */ | ||||||
|  | 	status = amdkfd_fence_wait_timeout( | ||||||
|  | 			(unsigned int *) rm_state, | ||||||
|  | 			QUEUESTATE__ACTIVE, 1500); | ||||||
|  | 
 | ||||||
|  | 	kfd_gtt_sa_free(dbgdev->dev, mem_obj); | ||||||
|  | 
 | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int dbgdev_register_nodiq(struct kfd_dbgdev *dbgdev) | static int dbgdev_register_nodiq(struct kfd_dbgdev *dbgdev) | ||||||
| { | { | ||||||
| 	BUG_ON(!dbgdev); | 	BUG_ON(!dbgdev); | ||||||
| @ -117,6 +236,290 @@ static int dbgdev_unregister_diq(struct kfd_dbgdev *dbgdev) | |||||||
| 	return status; | 	return status; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int dbgdev_wave_control_set_registers( | ||||||
|  | 				struct dbg_wave_control_info *wac_info, | ||||||
|  | 				union SQ_CMD_BITS *in_reg_sq_cmd, | ||||||
|  | 				union GRBM_GFX_INDEX_BITS *in_reg_gfx_index) | ||||||
|  | { | ||||||
|  | 	int status; | ||||||
|  | 	union SQ_CMD_BITS reg_sq_cmd; | ||||||
|  | 	union GRBM_GFX_INDEX_BITS reg_gfx_index; | ||||||
|  | 	struct HsaDbgWaveMsgAMDGen2 *pMsg; | ||||||
|  | 
 | ||||||
|  | 	BUG_ON(!wac_info || !in_reg_sq_cmd || !in_reg_gfx_index); | ||||||
|  | 
 | ||||||
|  | 	reg_sq_cmd.u32All = 0; | ||||||
|  | 	reg_gfx_index.u32All = 0; | ||||||
|  | 	pMsg = &wac_info->dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2; | ||||||
|  | 
 | ||||||
|  | 	switch (wac_info->mode) { | ||||||
|  | 	/* Send command to single wave */ | ||||||
|  | 	case HSA_DBG_WAVEMODE_SINGLE: | ||||||
|  | 		/*
 | ||||||
|  | 		 * Limit access to the process waves only, | ||||||
|  | 		 * by setting vmid check | ||||||
|  | 		 */ | ||||||
|  | 		reg_sq_cmd.bits.check_vmid = 1; | ||||||
|  | 		reg_sq_cmd.bits.simd_id = pMsg->ui32.SIMD; | ||||||
|  | 		reg_sq_cmd.bits.wave_id = pMsg->ui32.WaveId; | ||||||
|  | 		reg_sq_cmd.bits.mode = SQ_IND_CMD_MODE_SINGLE; | ||||||
|  | 
 | ||||||
|  | 		reg_gfx_index.bits.sh_index = pMsg->ui32.ShaderArray; | ||||||
|  | 		reg_gfx_index.bits.se_index = pMsg->ui32.ShaderEngine; | ||||||
|  | 		reg_gfx_index.bits.instance_index = pMsg->ui32.HSACU; | ||||||
|  | 
 | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	/* Send command to all waves with matching VMID */ | ||||||
|  | 	case HSA_DBG_WAVEMODE_BROADCAST_PROCESS: | ||||||
|  | 
 | ||||||
|  | 		reg_gfx_index.bits.sh_broadcast_writes = 1; | ||||||
|  | 		reg_gfx_index.bits.se_broadcast_writes = 1; | ||||||
|  | 		reg_gfx_index.bits.instance_broadcast_writes = 1; | ||||||
|  | 
 | ||||||
|  | 		reg_sq_cmd.bits.mode = SQ_IND_CMD_MODE_BROADCAST; | ||||||
|  | 
 | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	/* Send command to all CU waves with matching VMID */ | ||||||
|  | 	case HSA_DBG_WAVEMODE_BROADCAST_PROCESS_CU: | ||||||
|  | 
 | ||||||
|  | 		reg_sq_cmd.bits.check_vmid = 1; | ||||||
|  | 		reg_sq_cmd.bits.mode = SQ_IND_CMD_MODE_BROADCAST; | ||||||
|  | 
 | ||||||
|  | 		reg_gfx_index.bits.sh_index = pMsg->ui32.ShaderArray; | ||||||
|  | 		reg_gfx_index.bits.se_index = pMsg->ui32.ShaderEngine; | ||||||
|  | 		reg_gfx_index.bits.instance_index = pMsg->ui32.HSACU; | ||||||
|  | 
 | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	default: | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch (wac_info->operand) { | ||||||
|  | 	case HSA_DBG_WAVEOP_HALT: | ||||||
|  | 		reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_HALT; | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	case HSA_DBG_WAVEOP_RESUME: | ||||||
|  | 		reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_RESUME; | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	case HSA_DBG_WAVEOP_KILL: | ||||||
|  | 		reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_KILL; | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	case HSA_DBG_WAVEOP_DEBUG: | ||||||
|  | 		reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_DEBUG; | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	case HSA_DBG_WAVEOP_TRAP: | ||||||
|  | 		if (wac_info->trapId < MAX_TRAPID) { | ||||||
|  | 			reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_TRAP; | ||||||
|  | 			reg_sq_cmd.bits.trap_id = wac_info->trapId; | ||||||
|  | 		} else { | ||||||
|  | 			status = -EINVAL; | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	default: | ||||||
|  | 		status = -EINVAL; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (status == 0) { | ||||||
|  | 		*in_reg_sq_cmd = reg_sq_cmd; | ||||||
|  | 		*in_reg_gfx_index = reg_gfx_index; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int dbgdev_wave_control_diq(struct kfd_dbgdev *dbgdev, | ||||||
|  | 					struct dbg_wave_control_info *wac_info) | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | 	int status; | ||||||
|  | 	union SQ_CMD_BITS reg_sq_cmd; | ||||||
|  | 	union GRBM_GFX_INDEX_BITS reg_gfx_index; | ||||||
|  | 	struct kfd_mem_obj *mem_obj; | ||||||
|  | 	uint32_t *packet_buff_uint; | ||||||
|  | 	struct pm4__set_config_reg *packets_vec; | ||||||
|  | 	size_t ib_size = sizeof(struct pm4__set_config_reg) * 3; | ||||||
|  | 
 | ||||||
|  | 	BUG_ON(!dbgdev || !wac_info); | ||||||
|  | 
 | ||||||
|  | 	reg_sq_cmd.u32All = 0; | ||||||
|  | 
 | ||||||
|  | 	status = dbgdev_wave_control_set_registers(wac_info, ®_sq_cmd, | ||||||
|  | 							®_gfx_index); | ||||||
|  | 	if (status) { | ||||||
|  | 		pr_err("amdkfd: Failed to set wave control registers\n"); | ||||||
|  | 		return status; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* we do not control the VMID in DIQ,so reset it to a known value */ | ||||||
|  | 	reg_sq_cmd.bits.vm_id = 0; | ||||||
|  | 
 | ||||||
|  | 	pr_debug("\t\t %30s\n", "* * * * * * * * * * * * * * * * * *"); | ||||||
|  | 
 | ||||||
|  | 	pr_debug("\t\t mode      is: %u\n", wac_info->mode); | ||||||
|  | 	pr_debug("\t\t operand   is: %u\n", wac_info->operand); | ||||||
|  | 	pr_debug("\t\t trap id   is: %u\n", wac_info->trapId); | ||||||
|  | 	pr_debug("\t\t msg value is: %u\n", | ||||||
|  | 			wac_info->dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2.Value); | ||||||
|  | 	pr_debug("\t\t vmid      is: N/A\n"); | ||||||
|  | 
 | ||||||
|  | 	pr_debug("\t\t chk_vmid  is : %u\n", reg_sq_cmd.bitfields.check_vmid); | ||||||
|  | 	pr_debug("\t\t command   is : %u\n", reg_sq_cmd.bitfields.cmd); | ||||||
|  | 	pr_debug("\t\t queue id  is : %u\n", reg_sq_cmd.bitfields.queue_id); | ||||||
|  | 	pr_debug("\t\t simd id   is : %u\n", reg_sq_cmd.bitfields.simd_id); | ||||||
|  | 	pr_debug("\t\t mode      is : %u\n", reg_sq_cmd.bitfields.mode); | ||||||
|  | 	pr_debug("\t\t vm_id     is : %u\n", reg_sq_cmd.bitfields.vm_id); | ||||||
|  | 	pr_debug("\t\t wave_id   is : %u\n", reg_sq_cmd.bitfields.wave_id); | ||||||
|  | 
 | ||||||
|  | 	pr_debug("\t\t ibw       is : %u\n", | ||||||
|  | 			reg_gfx_index.bitfields.instance_broadcast_writes); | ||||||
|  | 	pr_debug("\t\t ii        is : %u\n", | ||||||
|  | 			reg_gfx_index.bitfields.instance_index); | ||||||
|  | 	pr_debug("\t\t sebw      is : %u\n", | ||||||
|  | 			reg_gfx_index.bitfields.se_broadcast_writes); | ||||||
|  | 	pr_debug("\t\t se_ind    is : %u\n", reg_gfx_index.bitfields.se_index); | ||||||
|  | 	pr_debug("\t\t sh_ind    is : %u\n", reg_gfx_index.bitfields.sh_index); | ||||||
|  | 	pr_debug("\t\t sbw       is : %u\n", | ||||||
|  | 			reg_gfx_index.bitfields.sh_broadcast_writes); | ||||||
|  | 
 | ||||||
|  | 	pr_debug("\t\t %30s\n", "* * * * * * * * * * * * * * * * * *"); | ||||||
|  | 
 | ||||||
|  | 	status = kfd_gtt_sa_allocate(dbgdev->dev, ib_size, &mem_obj); | ||||||
|  | 
 | ||||||
|  | 	if (status != 0) { | ||||||
|  | 		pr_err("amdkfd: Failed to allocate GART memory\n"); | ||||||
|  | 		return status; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	packet_buff_uint = mem_obj->cpu_ptr; | ||||||
|  | 
 | ||||||
|  | 	memset(packet_buff_uint, 0, ib_size); | ||||||
|  | 
 | ||||||
|  | 	packets_vec =  (struct pm4__set_config_reg *) packet_buff_uint; | ||||||
|  | 	packets_vec[0].header.count = 1; | ||||||
|  | 	packets_vec[0].header.opcode = IT_SET_UCONFIG_REG; | ||||||
|  | 	packets_vec[0].header.type = PM4_TYPE_3; | ||||||
|  | 	packets_vec[0].bitfields2.reg_offset = | ||||||
|  | 			GRBM_GFX_INDEX / (sizeof(uint32_t)) - | ||||||
|  | 				USERCONFIG_REG_BASE; | ||||||
|  | 
 | ||||||
|  | 	packets_vec[0].bitfields2.insert_vmid = 0; | ||||||
|  | 	packets_vec[0].reg_data[0] = reg_gfx_index.u32All; | ||||||
|  | 
 | ||||||
|  | 	packets_vec[1].header.count = 1; | ||||||
|  | 	packets_vec[1].header.opcode = IT_SET_CONFIG_REG; | ||||||
|  | 	packets_vec[1].header.type = PM4_TYPE_3; | ||||||
|  | 	packets_vec[1].bitfields2.reg_offset = SQ_CMD / (sizeof(uint32_t)) - | ||||||
|  | 						CONFIG_REG_BASE; | ||||||
|  | 
 | ||||||
|  | 	packets_vec[1].bitfields2.vmid_shift = SQ_CMD_VMID_OFFSET; | ||||||
|  | 	packets_vec[1].bitfields2.insert_vmid = 1; | ||||||
|  | 	packets_vec[1].reg_data[0] = reg_sq_cmd.u32All; | ||||||
|  | 
 | ||||||
|  | 	/* Restore the GRBM_GFX_INDEX register */ | ||||||
|  | 
 | ||||||
|  | 	reg_gfx_index.u32All = 0; | ||||||
|  | 	reg_gfx_index.bits.sh_broadcast_writes = 1; | ||||||
|  | 	reg_gfx_index.bits.instance_broadcast_writes = 1; | ||||||
|  | 	reg_gfx_index.bits.se_broadcast_writes = 1; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	packets_vec[2].ordinal1 = packets_vec[0].ordinal1; | ||||||
|  | 	packets_vec[2].bitfields2.reg_offset = | ||||||
|  | 				GRBM_GFX_INDEX / (sizeof(uint32_t)) - | ||||||
|  | 					USERCONFIG_REG_BASE; | ||||||
|  | 
 | ||||||
|  | 	packets_vec[2].bitfields2.insert_vmid = 0; | ||||||
|  | 	packets_vec[2].reg_data[0] = reg_gfx_index.u32All; | ||||||
|  | 
 | ||||||
|  | 	status = dbgdev_diq_submit_ib( | ||||||
|  | 			dbgdev, | ||||||
|  | 			wac_info->process->pasid, | ||||||
|  | 			mem_obj->gpu_addr, | ||||||
|  | 			packet_buff_uint, | ||||||
|  | 			ib_size); | ||||||
|  | 
 | ||||||
|  | 	if (status != 0) | ||||||
|  | 		pr_err("amdkfd: Failed to submit IB to DIQ\n"); | ||||||
|  | 
 | ||||||
|  | 	kfd_gtt_sa_free(dbgdev->dev, mem_obj); | ||||||
|  | 
 | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int dbgdev_wave_control_nodiq(struct kfd_dbgdev *dbgdev, | ||||||
|  | 					struct dbg_wave_control_info *wac_info) | ||||||
|  | { | ||||||
|  | 	int status; | ||||||
|  | 	union SQ_CMD_BITS reg_sq_cmd; | ||||||
|  | 	union GRBM_GFX_INDEX_BITS reg_gfx_index; | ||||||
|  | 	struct kfd_process_device *pdd; | ||||||
|  | 
 | ||||||
|  | 	BUG_ON(!dbgdev || !dbgdev->dev || !wac_info); | ||||||
|  | 
 | ||||||
|  | 	reg_sq_cmd.u32All = 0; | ||||||
|  | 
 | ||||||
|  | 	/* taking the VMID for that process on the safe way using PDD */ | ||||||
|  | 	pdd = kfd_get_process_device_data(dbgdev->dev, wac_info->process); | ||||||
|  | 
 | ||||||
|  | 	if (!pdd) { | ||||||
|  | 		pr_err("amdkfd: Failed to get pdd for wave control no DIQ\n"); | ||||||
|  | 		return -EFAULT; | ||||||
|  | 	} | ||||||
|  | 	status = dbgdev_wave_control_set_registers(wac_info, ®_sq_cmd, | ||||||
|  | 							®_gfx_index); | ||||||
|  | 	if (status) { | ||||||
|  | 		pr_err("amdkfd: Failed to set wave control registers\n"); | ||||||
|  | 		return status; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* for non DIQ we need to patch the VMID: */ | ||||||
|  | 
 | ||||||
|  | 	reg_sq_cmd.bits.vm_id = pdd->qpd.vmid; | ||||||
|  | 
 | ||||||
|  | 	pr_debug("\t\t %30s\n", "* * * * * * * * * * * * * * * * * *"); | ||||||
|  | 
 | ||||||
|  | 	pr_debug("\t\t mode      is: %u\n", wac_info->mode); | ||||||
|  | 	pr_debug("\t\t operand   is: %u\n", wac_info->operand); | ||||||
|  | 	pr_debug("\t\t trap id   is: %u\n", wac_info->trapId); | ||||||
|  | 	pr_debug("\t\t msg value is: %u\n", | ||||||
|  | 			wac_info->dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2.Value); | ||||||
|  | 	pr_debug("\t\t vmid      is: %u\n", pdd->qpd.vmid); | ||||||
|  | 
 | ||||||
|  | 	pr_debug("\t\t chk_vmid  is : %u\n", reg_sq_cmd.bitfields.check_vmid); | ||||||
|  | 	pr_debug("\t\t command   is : %u\n", reg_sq_cmd.bitfields.cmd); | ||||||
|  | 	pr_debug("\t\t queue id  is : %u\n", reg_sq_cmd.bitfields.queue_id); | ||||||
|  | 	pr_debug("\t\t simd id   is : %u\n", reg_sq_cmd.bitfields.simd_id); | ||||||
|  | 	pr_debug("\t\t mode      is : %u\n", reg_sq_cmd.bitfields.mode); | ||||||
|  | 	pr_debug("\t\t vm_id     is : %u\n", reg_sq_cmd.bitfields.vm_id); | ||||||
|  | 	pr_debug("\t\t wave_id   is : %u\n", reg_sq_cmd.bitfields.wave_id); | ||||||
|  | 
 | ||||||
|  | 	pr_debug("\t\t ibw       is : %u\n", | ||||||
|  | 			reg_gfx_index.bitfields.instance_broadcast_writes); | ||||||
|  | 	pr_debug("\t\t ii        is : %u\n", | ||||||
|  | 			reg_gfx_index.bitfields.instance_index); | ||||||
|  | 	pr_debug("\t\t sebw      is : %u\n", | ||||||
|  | 			reg_gfx_index.bitfields.se_broadcast_writes); | ||||||
|  | 	pr_debug("\t\t se_ind    is : %u\n", reg_gfx_index.bitfields.se_index); | ||||||
|  | 	pr_debug("\t\t sh_ind    is : %u\n", reg_gfx_index.bitfields.sh_index); | ||||||
|  | 	pr_debug("\t\t sbw       is : %u\n", | ||||||
|  | 			reg_gfx_index.bitfields.sh_broadcast_writes); | ||||||
|  | 
 | ||||||
|  | 	pr_debug("\t\t %30s\n", "* * * * * * * * * * * * * * * * * *"); | ||||||
|  | 
 | ||||||
|  | 	return dbgdev->dev->kfd2kgd->wave_control_execute(dbgdev->dev->kgd, | ||||||
|  | 							reg_gfx_index.u32All, | ||||||
|  | 							reg_sq_cmd.u32All); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void kfd_dbgdev_init(struct kfd_dbgdev *pdbgdev, struct kfd_dev *pdev, | void kfd_dbgdev_init(struct kfd_dbgdev *pdbgdev, struct kfd_dev *pdev, | ||||||
| 			enum DBGDEV_TYPE type) | 			enum DBGDEV_TYPE type) | ||||||
| { | { | ||||||
| @ -131,11 +534,13 @@ void kfd_dbgdev_init(struct kfd_dbgdev *pdbgdev, struct kfd_dev *pdev, | |||||||
| 	case DBGDEV_TYPE_NODIQ: | 	case DBGDEV_TYPE_NODIQ: | ||||||
| 		pdbgdev->dbgdev_register = dbgdev_register_nodiq; | 		pdbgdev->dbgdev_register = dbgdev_register_nodiq; | ||||||
| 		pdbgdev->dbgdev_unregister = dbgdev_unregister_nodiq; | 		pdbgdev->dbgdev_unregister = dbgdev_unregister_nodiq; | ||||||
|  | 		pdbgdev->dbgdev_wave_control = dbgdev_wave_control_nodiq; | ||||||
| 		break; | 		break; | ||||||
| 	case DBGDEV_TYPE_DIQ: | 	case DBGDEV_TYPE_DIQ: | ||||||
| 	default: | 	default: | ||||||
| 		pdbgdev->dbgdev_register = dbgdev_register_diq; | 		pdbgdev->dbgdev_register = dbgdev_register_diq; | ||||||
| 		pdbgdev->dbgdev_unregister = dbgdev_unregister_diq; | 		pdbgdev->dbgdev_unregister = dbgdev_unregister_diq; | ||||||
|  | 		pdbgdev->dbgdev_wave_control =  dbgdev_wave_control_diq; | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -133,3 +133,19 @@ long kfd_dbgmgr_unregister(struct kfd_dbgmgr *pmgr, struct kfd_process *p) | |||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | long kfd_dbgmgr_wave_control(struct kfd_dbgmgr *pmgr, | ||||||
|  | 				struct dbg_wave_control_info *wac_info) | ||||||
|  | { | ||||||
|  | 	BUG_ON(!pmgr || !pmgr->dbgdev || !wac_info); | ||||||
|  | 
 | ||||||
|  | 	/* Is the requests coming from the already registered process? */ | ||||||
|  | 	if (pmgr->pasid != wac_info->process->pasid) { | ||||||
|  | 		pr_debug("H/W debugger support was not registered for requester pasid %d\n", | ||||||
|  | 				wac_info->process->pasid); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return (long) pmgr->dbgdev->dbgdev_wave_control(pmgr->dbgdev, wac_info); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -268,6 +268,8 @@ struct kfd_dbgdev { | |||||||
| 	/* virtualized function pointers to device dbg */ | 	/* virtualized function pointers to device dbg */ | ||||||
| 	int (*dbgdev_register)(struct kfd_dbgdev *dbgdev); | 	int (*dbgdev_register)(struct kfd_dbgdev *dbgdev); | ||||||
| 	int (*dbgdev_unregister)(struct kfd_dbgdev *dbgdev); | 	int (*dbgdev_unregister)(struct kfd_dbgdev *dbgdev); | ||||||
|  | 	int (*dbgdev_wave_control)(struct kfd_dbgdev *dbgdev, | ||||||
|  | 				struct dbg_wave_control_info *wac_info); | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -283,5 +285,6 @@ void kfd_dbgmgr_destroy(struct kfd_dbgmgr *pmgr); | |||||||
| bool kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev); | bool kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev); | ||||||
| long kfd_dbgmgr_register(struct kfd_dbgmgr *pmgr, struct kfd_process *p); | long kfd_dbgmgr_register(struct kfd_dbgmgr *pmgr, struct kfd_process *p); | ||||||
| long kfd_dbgmgr_unregister(struct kfd_dbgmgr *pmgr, struct kfd_process *p); | long kfd_dbgmgr_unregister(struct kfd_dbgmgr *pmgr, struct kfd_process *p); | ||||||
| 
 | long kfd_dbgmgr_wave_control(struct kfd_dbgmgr *pmgr, | ||||||
|  | 				struct dbg_wave_control_info *wac_info); | ||||||
| #endif /* KFD_DBGMGR_H_ */ | #endif /* KFD_DBGMGR_H_ */ | ||||||
|  | |||||||
| @ -915,7 +915,7 @@ out: | |||||||
| 	return retval; | 	return retval; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int amdkfd_fence_wait_timeout(unsigned int *fence_addr, | int amdkfd_fence_wait_timeout(unsigned int *fence_addr, | ||||||
| 				unsigned int fence_value, | 				unsigned int fence_value, | ||||||
| 				unsigned long timeout) | 				unsigned long timeout) | ||||||
| { | { | ||||||
|  | |||||||
| @ -656,6 +656,10 @@ int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid, | |||||||
| struct kernel_queue *pqm_get_kernel_queue(struct process_queue_manager *pqm, | struct kernel_queue *pqm_get_kernel_queue(struct process_queue_manager *pqm, | ||||||
| 						unsigned int qid); | 						unsigned int qid); | ||||||
| 
 | 
 | ||||||
|  | int amdkfd_fence_wait_timeout(unsigned int *fence_addr, | ||||||
|  | 				unsigned int fence_value, | ||||||
|  | 				unsigned long timeout); | ||||||
|  | 
 | ||||||
| /* Packet Manager */ | /* Packet Manager */ | ||||||
| 
 | 
 | ||||||
| #define KFD_HIQ_TIMEOUT (500) | #define KFD_HIQ_TIMEOUT (500) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Yair Shachar
						Yair Shachar