drm/amdkfd: Implement wave control debugger IOCTL
v2: - rename get_dbgmgr_mutex to kfd_get_dbgmgr_mutex to namespace it - change void* to uint64_t inside ioctl arguments - use kmalloc instead of kzalloc because we use copy_from_user immediately after it Signed-off-by: Yair Shachar <yair.shachar@amd.com> Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
This commit is contained in:
parent
037ed9a2ac
commit
9448458998
|
@ -537,7 +537,93 @@ static int kfd_ioctl_dbg_address_watch(struct file *filep,
|
|||
static int kfd_ioctl_dbg_wave_control(struct file *filep,
|
||||
struct kfd_process *p, void *data)
|
||||
{
|
||||
long status = -EFAULT;
|
||||
struct kfd_ioctl_dbg_wave_control_args *args = data;
|
||||
struct kfd_dev *dev;
|
||||
struct dbg_wave_control_info wac_info;
|
||||
unsigned char *args_buff;
|
||||
uint32_t computed_buff_size;
|
||||
long status;
|
||||
void __user *cmd_from_user;
|
||||
unsigned int args_idx = 0;
|
||||
|
||||
memset((void *) &wac_info, 0, sizeof(struct dbg_wave_control_info));
|
||||
|
||||
/* we use compact form, independent of the packing attribute value */
|
||||
computed_buff_size = sizeof(*args) +
|
||||
sizeof(wac_info.mode) +
|
||||
sizeof(wac_info.operand) +
|
||||
sizeof(wac_info.dbgWave_msg.DbgWaveMsg) +
|
||||
sizeof(wac_info.dbgWave_msg.MemoryVA) +
|
||||
sizeof(wac_info.trapId);
|
||||
|
||||
dev = kfd_device_by_id(args->gpu_id);
|
||||
if (dev == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (dev->device_info->asic_family == CHIP_CARRIZO) {
|
||||
pr_debug("kfd_ioctl_dbg_wave_control not supported on CZ\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* input size must match the computed "compact" size */
|
||||
if (args->buf_size_in_bytes != computed_buff_size) {
|
||||
pr_debug("size mismatch, computed : actual %u : %u\n",
|
||||
args->buf_size_in_bytes, computed_buff_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd_from_user = (void __user *) args->content_ptr;
|
||||
|
||||
if (cmd_from_user == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* this is the actual buffer to work with */
|
||||
|
||||
args_buff = kmalloc(args->buf_size_in_bytes - sizeof(*args),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (args_buff == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Now copy the entire buffer from user */
|
||||
status = copy_from_user(args_buff, cmd_from_user,
|
||||
args->buf_size_in_bytes - sizeof(*args));
|
||||
if (status != 0) {
|
||||
pr_debug("Failed to copy wave control user data\n");
|
||||
kfree(args_buff);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* move ptr to the start of the "pay-load" area */
|
||||
wac_info.process = p;
|
||||
|
||||
wac_info.operand = *((enum HSA_DBG_WAVEOP *)(&args_buff[args_idx]));
|
||||
args_idx += sizeof(wac_info.operand);
|
||||
|
||||
wac_info.mode = *((enum HSA_DBG_WAVEMODE *)(&args_buff[args_idx]));
|
||||
args_idx += sizeof(wac_info.mode);
|
||||
|
||||
wac_info.trapId = *((uint32_t *)(&args_buff[args_idx]));
|
||||
args_idx += sizeof(wac_info.trapId);
|
||||
|
||||
wac_info.dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2.Value =
|
||||
*((uint32_t *)(&args_buff[args_idx]));
|
||||
wac_info.dbgWave_msg.MemoryVA = NULL;
|
||||
|
||||
mutex_lock(kfd_get_dbgmgr_mutex());
|
||||
|
||||
pr_debug("Calling dbg manager process %p, operand %u, mode %u, trapId %u, message %u\n",
|
||||
wac_info.process, wac_info.operand,
|
||||
wac_info.mode, wac_info.trapId,
|
||||
wac_info.dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2.Value);
|
||||
|
||||
status = kfd_dbgmgr_wave_control(dev->dbgmgr, &wac_info);
|
||||
|
||||
pr_debug("Returned status of dbg manager is %ld\n", status);
|
||||
|
||||
mutex_unlock(kfd_get_dbgmgr_mutex());
|
||||
|
||||
kfree(args_buff);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue