aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/3142-drm-amdkfd-cma-check-invalid-BO-range.patch
blob: f9d7f74789b03ab351622280afc7e09da4fcf789 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
From dd3cebfd6c74af0f8b50b3c09c24c625dca84528 Mon Sep 17 00:00:00 2001
From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
Date: Wed, 20 Dec 2017 12:38:45 -0500
Subject: [PATCH 3142/4131] drm/amdkfd: cma: check invalid BO range

Also modify error message to indicate CMA operation

BUG: SWDEV-138468

Change-Id: Ie6ee0189f515e00c15832ba5f0fa15812763f9a9
Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 33 ++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index afc4ce2..7fd26ec 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1759,7 +1759,8 @@ static int kfd_ioctl_cross_memory_copy(struct file *filep,
 	struct dma_fence *fence = NULL, *lfence = NULL;
 	uint64_t dst_va_addr;
 	uint64_t copied, total_copied = 0;
-	uint64_t src_offset, dst_offset;
+	uint64_t src_offset, dst_offset, dst_va_addr_end;
+	const char *cma_op;
 	int i, j = 0, err = 0;
 
 	/* Check parameters */
@@ -1830,10 +1831,12 @@ static int kfd_ioctl_cross_memory_copy(struct file *filep,
 	if (KFD_IS_CROSS_MEMORY_WRITE(args->flags)) {
 		src_p = local_p;
 		dst_p = remote_p;
+		cma_op = "WRITE";
 		pr_debug("CMA WRITE: local -> remote\n");
 	} else {
 		src_p = remote_p;
 		dst_p = local_p;
+		cma_op = "READ";
 		pr_debug("CMA READ: remote -> local\n");
 	}
 
@@ -1848,12 +1851,14 @@ static int kfd_ioctl_cross_memory_copy(struct file *filep,
 	 *                             data will be sourced or copied
 	 */
 	dst_va_addr = dst_array[0].va_addr;
+	dst_va_addr_end = dst_va_addr + dst_array[0].size - 1;
 	mutex_lock(&dst_p->mutex);
 	dst_bo = kfd_process_find_bo_from_interval(dst_p,
 			dst_va_addr,
-			dst_va_addr + dst_array[0].size - 1);
+			dst_va_addr_end);
 	mutex_unlock(&dst_p->mutex);
-	if (!dst_bo) {
+	if (!dst_bo || dst_va_addr_end > dst_bo->it.last) {
+		pr_err("CMA %s failed. Invalid dst range\n", cma_op);
 		err = -EFAULT;
 		goto kfd_process_fail;
 	}
@@ -1870,7 +1875,7 @@ static int kfd_ioctl_cross_memory_copy(struct file *filep,
 				src_va_addr_end);
 		mutex_unlock(&src_p->mutex);
 		if (!src_bo || src_va_addr_end > src_bo->it.last) {
-			pr_err("Cross mem copy failed. Invalid range\n");
+			pr_err("CMA %s failed. Invalid src range\n", cma_op);
 			err = -EFAULT;
 			break;
 		}
@@ -1896,7 +1901,7 @@ static int kfd_ioctl_cross_memory_copy(struct file *filep,
 
 			/* Check both BOs belong to same device */
 			if (src_bo->dev->kgd != dst_bo->dev->kgd) {
-				pr_err("Cross Memory failed. Not same device\n");
+				pr_err("CMA %s fail. Not same dev\n", cma_op);
 				err = -EINVAL;
 				break;
 			}
@@ -1915,7 +1920,7 @@ static int kfd_ioctl_cross_memory_copy(struct file *filep,
 				&fence, &copied);
 
 			if (err) {
-				pr_err("GPU Cross mem copy failed\n");
+				pr_err("GPU CMA %s failed\n", cma_op);
 				err = -EFAULT;
 				break;
 			}
@@ -1933,7 +1938,7 @@ static int kfd_ioctl_cross_memory_copy(struct file *filep,
 			dst_offset += copied;
 			src_offset += copied;
 			if (dst_va_addr > dst_bo->it.last + 1) {
-				pr_err("Cross mem copy failed. Memory overflow\n");
+				pr_err("CMA %s fail. Mem overflow\n", cma_op);
 				err = -EFAULT;
 				break;
 			}
@@ -1944,11 +1949,19 @@ static int kfd_ioctl_cross_memory_copy(struct file *filep,
 					break;
 
 				dst_va_addr = dst_array[j].va_addr;
+				dst_va_addr_end = dst_va_addr +
+						  dst_array[j].size - 1;
 				dst_bo = kfd_process_find_bo_from_interval(
 						dst_p,
 						dst_va_addr,
-						dst_va_addr +
-						dst_array[j].size - 1);
+						dst_va_addr_end);
+				if (!dst_bo ||
+				    dst_va_addr_end > dst_bo->it.last) {
+					pr_err("CMA %s failed. Invalid dst range\n",
+					       cma_op);
+					err = -EFAULT;
+					break;
+				}
 				dst_offset = dst_va_addr - dst_bo->it.start;
 			}
 
@@ -1964,7 +1977,7 @@ static int kfd_ioctl_cross_memory_copy(struct file *filep,
 	if (fence) {
 		if (dma_fence_wait_timeout(fence, false, msecs_to_jiffies(1000))
 			< 0)
-			pr_err("Cross mem copy failed. BO timed out\n");
+			pr_err("CMA %s failed. BO timed out\n", cma_op);
 		dma_fence_put(fence);
 	} else if (lfence) {
 		pr_debug("GPU copy fail. But wait for prev DMA to finish\n");
-- 
2.7.4