MALI: utgard: upgrade DDK to r6p1-01rel0
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / linux / mali_ukk_mem.c
1 /*
2  * Copyright (C) 2010-2016 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 <asm/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
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
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
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
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
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
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
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
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(VERIFY_WRITE, kargs.dest, kargs.size)
206             || !access_ok(VERIFY_READ, 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
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
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(VERIFY_WRITE, 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
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