diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0137-drm-amdkfd-Implement-address-watch-debugger-IOCTL.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0137-drm-amdkfd-Implement-address-watch-debugger-IOCTL.patch | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0137-drm-amdkfd-Implement-address-watch-debugger-IOCTL.patch b/common/recipes-kernel/linux/files/0137-drm-amdkfd-Implement-address-watch-debugger-IOCTL.patch new file mode 100644 index 00000000..697ce81d --- /dev/null +++ b/common/recipes-kernel/linux/files/0137-drm-amdkfd-Implement-address-watch-debugger-IOCTL.patch @@ -0,0 +1,134 @@ +From f8bd13338a9a42358158954251969e66934ec3d1 Mon Sep 17 00:00:00 2001 +From: Yair Shachar <yair.shachar@amd.com> +Date: Wed, 20 May 2015 14:09:39 +0300 +Subject: [PATCH 0137/1050] drm/amdkfd: Implement address watch 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> +--- + drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 102 ++++++++++++++++++++++++++++++- + 1 file changed, 101 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +index 9e5261d..96c904b 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +@@ -528,7 +528,107 @@ static int kfd_ioctl_dbg_unrgesiter(struct file *filep, + static int kfd_ioctl_dbg_address_watch(struct file *filep, + struct kfd_process *p, void *data) + { +- long status = -EFAULT; ++ struct kfd_ioctl_dbg_address_watch_args *args = data; ++ struct kfd_dev *dev; ++ struct dbg_address_watch_info aw_info; ++ unsigned char *args_buff; ++ long status; ++ void __user *cmd_from_user; ++ uint64_t watch_mask_value = 0; ++ unsigned int args_idx = 0; ++ ++ memset((void *) &aw_info, 0, sizeof(struct dbg_address_watch_info)); ++ ++ 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; ++ } ++ ++ cmd_from_user = (void __user *) args->content_ptr; ++ ++ /* Validate arguments */ ++ ++ if ((args->buf_size_in_bytes > MAX_ALLOWED_AW_BUFF_SIZE) || ++ (args->buf_size_in_bytes <= sizeof(*args)) || ++ (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; ++ ++ status = copy_from_user(args_buff, cmd_from_user, ++ args->buf_size_in_bytes - sizeof(*args)); ++ ++ if (status != 0) { ++ pr_debug("Failed to copy address watch user data\n"); ++ kfree(args_buff); ++ return -EINVAL; ++ } ++ ++ aw_info.process = p; ++ ++ aw_info.num_watch_points = *((uint32_t *)(&args_buff[args_idx])); ++ args_idx += sizeof(aw_info.num_watch_points); ++ ++ aw_info.watch_mode = (enum HSA_DBG_WATCH_MODE *) &args_buff[args_idx]; ++ args_idx += sizeof(enum HSA_DBG_WATCH_MODE) * aw_info.num_watch_points; ++ ++ /* ++ * set watch address base pointer to point on the array base ++ * within args_buff ++ */ ++ aw_info.watch_address = (uint64_t *) &args_buff[args_idx]; ++ ++ /* skip over the addresses buffer */ ++ args_idx += sizeof(aw_info.watch_address) * aw_info.num_watch_points; ++ ++ if (args_idx >= args->buf_size_in_bytes) { ++ kfree(args_buff); ++ return -EINVAL; ++ } ++ ++ watch_mask_value = (uint64_t) args_buff[args_idx]; ++ ++ if (watch_mask_value > 0) { ++ /* ++ * There is an array of masks. ++ * set watch mask base pointer to point on the array base ++ * within args_buff ++ */ ++ aw_info.watch_mask = (uint64_t *) &args_buff[args_idx]; ++ ++ /* skip over the masks buffer */ ++ args_idx += sizeof(aw_info.watch_mask) * ++ aw_info.num_watch_points; ++ } else { ++ /* just the NULL mask, set to NULL and skip over it */ ++ aw_info.watch_mask = NULL; ++ args_idx += sizeof(aw_info.watch_mask); ++ } ++ ++ if (args_idx > args->buf_size_in_bytes) { ++ kfree(args_buff); ++ return -EINVAL; ++ } ++ ++ /* Currently HSA Event is not supported for DBG */ ++ aw_info.watch_event = NULL; ++ ++ mutex_lock(kfd_get_dbgmgr_mutex()); ++ ++ status = kfd_dbgmgr_address_watch(dev->dbgmgr, &aw_info); ++ ++ mutex_unlock(kfd_get_dbgmgr_mutex()); ++ ++ kfree(args_buff); + + return status; + } +-- +1.9.1 + |