aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0137-drm-amdkfd-Implement-address-watch-debugger-IOCTL.patch
diff options
context:
space:
mode:
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.patch134
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
+