xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/mali400/mali/linux/mali_ukk_mem.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2010-2017 ARM Limited. All rights reserved.
3  *
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  *
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10 #include <linux/fs.h>       /* file system operations */
11 #include <linux/uaccess.h>  /* user space access */
12 
13 #include "mali_ukk.h"
14 #include "mali_osk.h"
15 #include "mali_kernel_common.h"
16 #include "mali_session.h"
17 #include "mali_ukk_wrappers.h"
18 
mem_alloc_wrapper(struct mali_session_data * session_data,_mali_uk_alloc_mem_s __user * uargs)19 int mem_alloc_wrapper(struct mali_session_data *session_data, _mali_uk_alloc_mem_s __user *uargs)
20 {
21 	_mali_uk_alloc_mem_s kargs;
22 	_mali_osk_errcode_t err;
23 
24 	MALI_CHECK_NON_NULL(uargs, -EINVAL);
25 	MALI_CHECK_NON_NULL(session_data, -EINVAL);
26 
27 	if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_alloc_mem_s))) {
28 		return -EFAULT;
29 	}
30 	kargs.ctx = (uintptr_t)session_data;
31 
32 	err = _mali_ukk_mem_allocate(&kargs);
33 
34 	if (_MALI_OSK_ERR_OK != err) {
35 		return map_errcode(err);
36 	}
37 
38 	if (0 != put_user(kargs.backend_handle, &uargs->backend_handle)) {
39 		return -EFAULT;
40 	}
41 
42 	return 0;
43 }
44 
mem_free_wrapper(struct mali_session_data * session_data,_mali_uk_free_mem_s __user * uargs)45 int mem_free_wrapper(struct mali_session_data *session_data, _mali_uk_free_mem_s __user *uargs)
46 {
47 	_mali_uk_free_mem_s kargs;
48 	_mali_osk_errcode_t err;
49 
50 	MALI_CHECK_NON_NULL(uargs, -EINVAL);
51 	MALI_CHECK_NON_NULL(session_data, -EINVAL);
52 
53 	if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_free_mem_s))) {
54 		return -EFAULT;
55 	}
56 	kargs.ctx = (uintptr_t)session_data;
57 
58 	err = _mali_ukk_mem_free(&kargs);
59 
60 	if (_MALI_OSK_ERR_OK != err) {
61 		return map_errcode(err);
62 	}
63 
64 	if (0 != put_user(kargs.free_pages_nr, &uargs->free_pages_nr)) {
65 		return -EFAULT;
66 	}
67 
68 	return 0;
69 }
70 
mem_bind_wrapper(struct mali_session_data * session_data,_mali_uk_bind_mem_s __user * uargs)71 int mem_bind_wrapper(struct mali_session_data *session_data, _mali_uk_bind_mem_s __user *uargs)
72 {
73 	_mali_uk_bind_mem_s kargs;
74 	_mali_osk_errcode_t err;
75 
76 	MALI_CHECK_NON_NULL(uargs, -EINVAL);
77 	MALI_CHECK_NON_NULL(session_data, -EINVAL);
78 
79 	if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_bind_mem_s))) {
80 		return -EFAULT;
81 	}
82 	kargs.ctx = (uintptr_t)session_data;
83 
84 	err = _mali_ukk_mem_bind(&kargs);
85 
86 	if (_MALI_OSK_ERR_OK != err) {
87 		return map_errcode(err);
88 	}
89 
90 	return 0;
91 }
92 
mem_unbind_wrapper(struct mali_session_data * session_data,_mali_uk_unbind_mem_s __user * uargs)93 int mem_unbind_wrapper(struct mali_session_data *session_data, _mali_uk_unbind_mem_s __user *uargs)
94 {
95 	_mali_uk_unbind_mem_s kargs;
96 	_mali_osk_errcode_t err;
97 
98 	MALI_CHECK_NON_NULL(uargs, -EINVAL);
99 	MALI_CHECK_NON_NULL(session_data, -EINVAL);
100 
101 	if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_unbind_mem_s))) {
102 		return -EFAULT;
103 	}
104 	kargs.ctx = (uintptr_t)session_data;
105 
106 	err = _mali_ukk_mem_unbind(&kargs);
107 
108 	if (_MALI_OSK_ERR_OK != err) {
109 		return map_errcode(err);
110 	}
111 
112 	return 0;
113 }
114 
115 
mem_cow_wrapper(struct mali_session_data * session_data,_mali_uk_cow_mem_s __user * uargs)116 int mem_cow_wrapper(struct mali_session_data *session_data, _mali_uk_cow_mem_s __user *uargs)
117 {
118 	_mali_uk_cow_mem_s kargs;
119 	_mali_osk_errcode_t err;
120 
121 	MALI_CHECK_NON_NULL(uargs, -EINVAL);
122 	MALI_CHECK_NON_NULL(session_data, -EINVAL);
123 
124 	if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_cow_mem_s))) {
125 		return -EFAULT;
126 	}
127 	kargs.ctx = (uintptr_t)session_data;
128 
129 	err = _mali_ukk_mem_cow(&kargs);
130 
131 	if (_MALI_OSK_ERR_OK != err) {
132 		return map_errcode(err);
133 	}
134 
135 	if (0 != put_user(kargs.backend_handle, &uargs->backend_handle)) {
136 		return -EFAULT;
137 	}
138 
139 	return 0;
140 }
141 
mem_cow_modify_range_wrapper(struct mali_session_data * session_data,_mali_uk_cow_modify_range_s __user * uargs)142 int mem_cow_modify_range_wrapper(struct mali_session_data *session_data, _mali_uk_cow_modify_range_s __user *uargs)
143 {
144 	_mali_uk_cow_modify_range_s kargs;
145 	_mali_osk_errcode_t err;
146 
147 	MALI_CHECK_NON_NULL(uargs, -EINVAL);
148 	MALI_CHECK_NON_NULL(session_data, -EINVAL);
149 
150 	if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_cow_modify_range_s))) {
151 		return -EFAULT;
152 	}
153 	kargs.ctx = (uintptr_t)session_data;
154 
155 	err = _mali_ukk_mem_cow_modify_range(&kargs);
156 
157 	if (_MALI_OSK_ERR_OK != err) {
158 		return map_errcode(err);
159 	}
160 
161 	if (0 != put_user(kargs.change_pages_nr, &uargs->change_pages_nr)) {
162 		return -EFAULT;
163 	}
164 	return 0;
165 }
166 
167 
mem_resize_mem_wrapper(struct mali_session_data * session_data,_mali_uk_mem_resize_s __user * uargs)168 int mem_resize_mem_wrapper(struct mali_session_data *session_data, _mali_uk_mem_resize_s __user *uargs)
169 {
170 	_mali_uk_mem_resize_s kargs;
171 	_mali_osk_errcode_t err;
172 
173 	MALI_CHECK_NON_NULL(uargs, -EINVAL);
174 	MALI_CHECK_NON_NULL(session_data, -EINVAL);
175 
176 	if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_mem_resize_s))) {
177 		return -EFAULT;
178 	}
179 	kargs.ctx = (uintptr_t)session_data;
180 
181 	err = _mali_ukk_mem_resize(&kargs);
182 
183 	if (_MALI_OSK_ERR_OK != err) {
184 		return map_errcode(err);
185 	}
186 
187 	return 0;
188 }
189 
mem_write_safe_wrapper(struct mali_session_data * session_data,_mali_uk_mem_write_safe_s __user * uargs)190 int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user *uargs)
191 {
192 	_mali_uk_mem_write_safe_s kargs;
193 	_mali_osk_errcode_t err;
194 
195 	MALI_CHECK_NON_NULL(uargs, -EINVAL);
196 	MALI_CHECK_NON_NULL(session_data, -EINVAL);
197 
198 	if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_mem_write_safe_s))) {
199 		return -EFAULT;
200 	}
201 
202 	kargs.ctx = (uintptr_t)session_data;
203 
204 	/* Check if we can access the buffers */
205 	if (!access_ok((const void *)(uintptr_t)kargs.dest, kargs.size) ||
206 	    !access_ok((const void *)(uintptr_t)kargs.src, kargs.size)) {
207 		return -EINVAL;
208 	}
209 
210 	/* Check if size wraps */
211 	if ((kargs.size + kargs.dest) <= kargs.dest
212 	    || (kargs.size + kargs.src) <= kargs.src) {
213 		return -EINVAL;
214 	}
215 
216 	err = _mali_ukk_mem_write_safe(&kargs);
217 	if (_MALI_OSK_ERR_OK != err) {
218 		return map_errcode(err);
219 	}
220 
221 	if (0 != put_user(kargs.size, &uargs->size)) {
222 		return -EFAULT;
223 	}
224 
225 	return 0;
226 }
227 
228 
229 
mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data * session_data,_mali_uk_query_mmu_page_table_dump_size_s __user * uargs)230 int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user *uargs)
231 {
232 	_mali_uk_query_mmu_page_table_dump_size_s kargs;
233 	_mali_osk_errcode_t err;
234 
235 	MALI_CHECK_NON_NULL(uargs, -EINVAL);
236 	MALI_CHECK_NON_NULL(session_data, -EINVAL);
237 
238 	kargs.ctx = (uintptr_t)session_data;
239 
240 	err = _mali_ukk_query_mmu_page_table_dump_size(&kargs);
241 	if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
242 
243 	if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT;
244 
245 	return 0;
246 }
247 
mem_dump_mmu_page_table_wrapper(struct mali_session_data * session_data,_mali_uk_dump_mmu_page_table_s __user * uargs)248 int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user *uargs)
249 {
250 	_mali_uk_dump_mmu_page_table_s kargs;
251 	_mali_osk_errcode_t err;
252 	void __user *user_buffer;
253 	void *buffer = NULL;
254 	int rc = -EFAULT;
255 
256 	/* validate input */
257 	MALI_CHECK_NON_NULL(uargs, -EINVAL);
258 	/* the session_data pointer was validated by caller */
259 
260 	if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_dump_mmu_page_table_s)))
261 		goto err_exit;
262 
263 	user_buffer = (void __user *)(uintptr_t)kargs.buffer;
264 	if (!access_ok(user_buffer, kargs.size))
265 		goto err_exit;
266 
267 	/* allocate temporary buffer (kernel side) to store mmu page table info */
268 	if (kargs.size <= 0)
269 		return -EINVAL;
270 	/* Allow at most 8MiB buffers, this is more than enough to dump a fully
271 	 * populated page table. */
272 	if (kargs.size > SZ_8M)
273 		return -EINVAL;
274 
275 	buffer = (void *)(uintptr_t)_mali_osk_valloc(kargs.size);
276 	if (NULL == buffer) {
277 		rc = -ENOMEM;
278 		goto err_exit;
279 	}
280 
281 	kargs.ctx = (uintptr_t)session_data;
282 	kargs.buffer = (uintptr_t)buffer;
283 	err = _mali_ukk_dump_mmu_page_table(&kargs);
284 	if (_MALI_OSK_ERR_OK != err) {
285 		rc = map_errcode(err);
286 		goto err_exit;
287 	}
288 
289 	/* copy mmu page table info back to user space and update pointers */
290 	if (0 != copy_to_user(user_buffer, buffer, kargs.size))
291 		goto err_exit;
292 
293 	kargs.register_writes = kargs.register_writes -
294 				(uintptr_t)buffer + (uintptr_t)user_buffer;
295 	kargs.page_table_dump = kargs.page_table_dump -
296 				(uintptr_t)buffer + (uintptr_t)user_buffer;
297 
298 	if (0 != copy_to_user(uargs, &kargs, sizeof(kargs)))
299 		goto err_exit;
300 
301 	rc = 0;
302 
303 err_exit:
304 	if (buffer) _mali_osk_vfree(buffer);
305 	return rc;
306 }
307 
mem_usage_get_wrapper(struct mali_session_data * session_data,_mali_uk_profiling_memory_usage_get_s __user * uargs)308 int mem_usage_get_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_memory_usage_get_s __user *uargs)
309 {
310 	_mali_osk_errcode_t err;
311 	_mali_uk_profiling_memory_usage_get_s kargs;
312 
313 	MALI_CHECK_NON_NULL(uargs, -EINVAL);
314 	MALI_CHECK_NON_NULL(session_data, -EINVAL);
315 
316 	if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_memory_usage_get_s))) {
317 		return -EFAULT;
318 	}
319 
320 	kargs.ctx = (uintptr_t)session_data;
321 	err = _mali_ukk_mem_usage_get(&kargs);
322 	if (_MALI_OSK_ERR_OK != err) {
323 		return map_errcode(err);
324 	}
325 
326 	kargs.ctx = (uintptr_t)NULL; /* prevent kernel address to be returned to user space */
327 	if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_profiling_memory_usage_get_s))) {
328 		return -EFAULT;
329 	}
330 
331 	return 0;
332 }
333 
334