aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdkfd
diff options
context:
space:
mode:
authorYair Shachar <yair.shachar@amd.com>2015-05-20 07:09:39 -0400
committerOded Gabbay <oded.gabbay@gmail.com>2015-06-03 04:34:35 -0400
commitf8bd13338a9a42358158954251969e66934ec3d1 (patch)
treeaf276c178c11f7aeba8597ec2f6acc912745166a /drivers/gpu/drm/amd/amdkfd
parent9448458998e27be7fcb9ebc58200be45a6429451 (diff)
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>
Diffstat (limited to 'drivers/gpu/drm/amd/amdkfd')
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_chardev.c102
1 files changed, 101 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 9e5261de0716..96c904b3acb7 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,
528static int kfd_ioctl_dbg_address_watch(struct file *filep, 528static int kfd_ioctl_dbg_address_watch(struct file *filep,
529 struct kfd_process *p, void *data) 529 struct kfd_process *p, void *data)
530{ 530{
531 long status = -EFAULT; 531 struct kfd_ioctl_dbg_address_watch_args *args = data;
532 struct kfd_dev *dev;
533 struct dbg_address_watch_info aw_info;
534 unsigned char *args_buff;
535 long status;
536 void __user *cmd_from_user;
537 uint64_t watch_mask_value = 0;
538 unsigned int args_idx = 0;
539
540 memset((void *) &aw_info, 0, sizeof(struct dbg_address_watch_info));
541
542 dev = kfd_device_by_id(args->gpu_id);
543 if (dev == NULL)
544 return -EINVAL;
545
546 if (dev->device_info->asic_family == CHIP_CARRIZO) {
547 pr_debug("kfd_ioctl_dbg_wave_control not supported on CZ\n");
548 return -EINVAL;
549 }
550
551 cmd_from_user = (void __user *) args->content_ptr;
552
553 /* Validate arguments */
554
555 if ((args->buf_size_in_bytes > MAX_ALLOWED_AW_BUFF_SIZE) ||
556 (args->buf_size_in_bytes <= sizeof(*args)) ||
557 (cmd_from_user == NULL))
558 return -EINVAL;
559
560 /* this is the actual buffer to work with */
561
562 args_buff = kmalloc(args->buf_size_in_bytes -
563 sizeof(*args), GFP_KERNEL);
564 if (args_buff == NULL)
565 return -ENOMEM;
566
567 status = copy_from_user(args_buff, cmd_from_user,
568 args->buf_size_in_bytes - sizeof(*args));
569
570 if (status != 0) {
571 pr_debug("Failed to copy address watch user data\n");
572 kfree(args_buff);
573 return -EINVAL;
574 }
575
576 aw_info.process = p;
577
578 aw_info.num_watch_points = *((uint32_t *)(&args_buff[args_idx]));
579 args_idx += sizeof(aw_info.num_watch_points);
580
581 aw_info.watch_mode = (enum HSA_DBG_WATCH_MODE *) &args_buff[args_idx];
582 args_idx += sizeof(enum HSA_DBG_WATCH_MODE) * aw_info.num_watch_points;
583
584 /*
585 * set watch address base pointer to point on the array base
586 * within args_buff
587 */
588 aw_info.watch_address = (uint64_t *) &args_buff[args_idx];
589
590 /* skip over the addresses buffer */
591 args_idx += sizeof(aw_info.watch_address) * aw_info.num_watch_points;
592
593 if (args_idx >= args->buf_size_in_bytes) {
594 kfree(args_buff);
595 return -EINVAL;
596 }
597
598 watch_mask_value = (uint64_t) args_buff[args_idx];
599
600 if (watch_mask_value > 0) {
601 /*
602 * There is an array of masks.
603 * set watch mask base pointer to point on the array base
604 * within args_buff
605 */
606 aw_info.watch_mask = (uint64_t *) &args_buff[args_idx];
607
608 /* skip over the masks buffer */
609 args_idx += sizeof(aw_info.watch_mask) *
610 aw_info.num_watch_points;
611 } else {
612 /* just the NULL mask, set to NULL and skip over it */
613 aw_info.watch_mask = NULL;
614 args_idx += sizeof(aw_info.watch_mask);
615 }
616
617 if (args_idx > args->buf_size_in_bytes) {
618 kfree(args_buff);
619 return -EINVAL;
620 }
621
622 /* Currently HSA Event is not supported for DBG */
623 aw_info.watch_event = NULL;
624
625 mutex_lock(kfd_get_dbgmgr_mutex());
626
627 status = kfd_dbgmgr_address_watch(dev->dbgmgr, &aw_info);
628
629 mutex_unlock(kfd_get_dbgmgr_mutex());
630
631 kfree(args_buff);
532 632
533 return status; 633 return status;
534} 634}