2 * Copyright (C) 2010-2014 ARM Limited. All rights reserved.
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.
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.
10 #include <linux/fs.h> /* file system operations */
11 #include <asm/uaccess.h> /* user space access */
15 #include "mali_kernel_common.h"
16 #include "mali_session.h"
17 #include "mali_ukk_wrappers.h"
19 int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs)
21 _mali_uk_init_mem_s kargs;
22 _mali_osk_errcode_t err;
24 MALI_CHECK_NON_NULL(uargs, -EINVAL);
26 kargs.ctx = (uintptr_t)session_data;
27 err = _mali_ukk_init_mem(&kargs);
28 if (_MALI_OSK_ERR_OK != err)
30 return map_errcode(err);
33 if (0 != put_user(kargs.mali_address_base, &uargs->mali_address_base)) goto mem_init_rollback;
34 if (0 != put_user(kargs.memory_size, &uargs->memory_size)) goto mem_init_rollback;
40 _mali_uk_term_mem_s kargs;
41 kargs.ctx = (uintptr_t)session_data;
42 err = _mali_ukk_term_mem(&kargs);
43 if (_MALI_OSK_ERR_OK != err)
45 MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_init_mem, as a result of failing put_user(), failed\n"));
51 int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs)
53 _mali_uk_term_mem_s kargs;
54 _mali_osk_errcode_t err;
56 MALI_CHECK_NON_NULL(uargs, -EINVAL);
58 kargs.ctx = (uintptr_t)session_data;
59 err = _mali_ukk_term_mem(&kargs);
60 if (_MALI_OSK_ERR_OK != err)
62 return map_errcode(err);
68 int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs)
70 _mali_uk_mem_write_safe_s kargs;
71 _mali_osk_errcode_t err;
73 MALI_CHECK_NON_NULL(uargs, -EINVAL);
74 MALI_CHECK_NON_NULL(session_data, -EINVAL);
76 if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_mem_write_safe_s))) {
80 kargs.ctx = (uintptr_t)session_data;
82 /* Check if we can access the buffers */
83 if (!access_ok(VERIFY_WRITE, kargs.dest, kargs.size)
84 || !access_ok(VERIFY_READ, kargs.src, kargs.size)) {
88 /* Check if size wraps */
89 if ((kargs.size + kargs.dest) <= kargs.dest
90 || (kargs.size + kargs.src) <= kargs.src) {
94 err = _mali_ukk_mem_write_safe(&kargs);
95 if (_MALI_OSK_ERR_OK != err) {
96 return map_errcode(err);
99 if (0 != put_user(kargs.size, &uargs->size)) {
106 int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user *argument)
108 _mali_uk_map_external_mem_s uk_args;
109 _mali_osk_errcode_t err_code;
112 /* the session_data pointer was validated by caller */
113 MALI_CHECK_NON_NULL(argument, -EINVAL);
115 /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
116 if (0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_map_external_mem_s))) {
120 uk_args.ctx = (uintptr_t)session_data;
121 err_code = _mali_ukk_map_external_mem(&uk_args);
123 if (0 != put_user(uk_args.cookie, &argument->cookie)) {
124 if (_MALI_OSK_ERR_OK == err_code) {
126 _mali_uk_unmap_external_mem_s uk_args_unmap;
128 uk_args_unmap.ctx = (uintptr_t)session_data;
129 uk_args_unmap.cookie = uk_args.cookie;
130 err_code = _mali_ukk_unmap_external_mem(&uk_args_unmap);
131 if (_MALI_OSK_ERR_OK != err_code) {
132 MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_unmap_external_mem, as a result of failing put_user(), failed\n"));
138 /* Return the error that _mali_ukk_free_big_block produced */
139 return map_errcode(err_code);
142 int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user *argument)
144 _mali_uk_unmap_external_mem_s uk_args;
145 _mali_osk_errcode_t err_code;
148 /* the session_data pointer was validated by caller */
149 MALI_CHECK_NON_NULL(argument, -EINVAL);
151 /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
152 if (0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_unmap_external_mem_s))) {
156 uk_args.ctx = (uintptr_t)session_data;
157 err_code = _mali_ukk_unmap_external_mem(&uk_args);
159 /* Return the error that _mali_ukk_free_big_block produced */
160 return map_errcode(err_code);
163 #if defined(CONFIG_MALI400_UMP)
164 int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user *argument)
166 _mali_uk_release_ump_mem_s uk_args;
167 _mali_osk_errcode_t err_code;
170 /* the session_data pointer was validated by caller */
171 MALI_CHECK_NON_NULL(argument, -EINVAL);
173 /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
174 if (0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_release_ump_mem_s))) {
178 uk_args.ctx = (uintptr_t)session_data;
179 err_code = _mali_ukk_release_ump_mem(&uk_args);
181 /* Return the error that _mali_ukk_free_big_block produced */
182 return map_errcode(err_code);
185 int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user *argument)
187 _mali_uk_attach_ump_mem_s uk_args;
188 _mali_osk_errcode_t err_code;
191 /* the session_data pointer was validated by caller */
192 MALI_CHECK_NON_NULL(argument, -EINVAL);
194 /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
195 if (0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_attach_ump_mem_s))) {
199 uk_args.ctx = (uintptr_t)session_data;
200 err_code = _mali_ukk_attach_ump_mem(&uk_args);
202 if (0 != put_user(uk_args.cookie, &argument->cookie)) {
203 if (_MALI_OSK_ERR_OK == err_code) {
205 _mali_uk_release_ump_mem_s uk_args_unmap;
207 uk_args_unmap.ctx = (uintptr_t)session_data;
208 uk_args_unmap.cookie = uk_args.cookie;
209 err_code = _mali_ukk_release_ump_mem(&uk_args_unmap);
210 if (_MALI_OSK_ERR_OK != err_code) {
211 MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_attach_mem, as a result of failing put_user(), failed\n"));
217 /* Return the error that _mali_ukk_map_external_ump_mem produced */
218 return map_errcode(err_code);
220 #endif /* CONFIG_MALI400_UMP */
222 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)
224 _mali_uk_query_mmu_page_table_dump_size_s kargs;
225 _mali_osk_errcode_t err;
227 MALI_CHECK_NON_NULL(uargs, -EINVAL);
228 MALI_CHECK_NON_NULL(session_data, -EINVAL);
230 kargs.ctx = (uintptr_t)session_data;
232 err = _mali_ukk_query_mmu_page_table_dump_size(&kargs);
233 if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
235 if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT;
240 int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user *uargs)
242 _mali_uk_dump_mmu_page_table_s kargs;
243 _mali_osk_errcode_t err;
244 void __user *user_buffer;
249 MALI_CHECK_NON_NULL(uargs, -EINVAL);
250 /* the session_data pointer was validated by caller */
252 if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_dump_mmu_page_table_s)))
255 user_buffer = (void __user *)(uintptr_t)kargs.buffer;
256 if (!access_ok(VERIFY_WRITE, user_buffer, kargs.size))
259 /* allocate temporary buffer (kernel side) to store mmu page table info */
262 /* Allow at most 8MiB buffers, this is more than enough to dump a fully
263 * populated page table. */
264 if (kargs.size > SZ_8M)
267 buffer = (void *)(uintptr_t)_mali_osk_valloc(kargs.size);
268 if (NULL == buffer) {
273 kargs.ctx = (uintptr_t)session_data;
274 kargs.buffer = (uintptr_t)buffer;
275 err = _mali_ukk_dump_mmu_page_table(&kargs);
276 if (_MALI_OSK_ERR_OK != err) {
277 rc = map_errcode(err);
281 /* copy mmu page table info back to user space and update pointers */
282 if (0 != copy_to_user(user_buffer, buffer, kargs.size))
285 kargs.register_writes = kargs.register_writes -
286 (uintptr_t)buffer + (uintptr_t)user_buffer;
287 kargs.page_table_dump = kargs.page_table_dump -
288 (uintptr_t)buffer + (uintptr_t)user_buffer;
290 if (0 != copy_to_user(uargs, &kargs, sizeof(kargs)))
296 if (buffer) _mali_osk_vfree(buffer);
300 #if TIZEN_GLES_MEM_PROFILE
301 int mem_profile_gles_mem(struct mali_session_data *session_data,
302 _mali_uk_gles_mem_profiler_s __user *uargs)
304 _mali_uk_gles_mem_profiler_s kargs;
305 struct mali_session_gles_mem_profile_info *info;
306 struct mali_session_gles_mem_profile_api_info *api, *tmp;
307 mali_bool flag = MALI_FALSE;
309 MALI_CHECK_NON_NULL(uargs, -EINVAL);
310 MALI_CHECK_NON_NULL(session_data, -EINVAL);
312 if (copy_from_user(&kargs, uargs, sizeof(_mali_uk_gles_mem_profiler_s)))
315 kargs.ctx = (uintptr_t)session_data;
317 info = &session_data->gles_mem_profile_info[kargs.type];
319 MALI_PRINT_ERROR(("No info is available. Something wrong"));
323 _MALI_OSK_LIST_FOREACHENTRY(api, tmp, &(info->api_head),
324 struct mali_session_gles_mem_profile_api_info, link) {
325 if (api->id == (u16)kargs.entrypoint) {
326 /* This API is recorded already. Update it. */
327 api->size += kargs.size;
328 info->size += kargs.size;
334 if (flag == MALI_FALSE) {
336 * This is the first time the API is recorded for this info.
339 api = (struct mali_session_gles_mem_profile_api_info *)
341 sizeof(struct mali_session_gles_mem_profile_api_info));
343 MALI_PRINT_ERROR(("Alloc failure"));
346 memcpy(&api->api, &kargs.api, sizeof(api->api));
348 api->id = (u16)kargs.entrypoint;
349 api->size += kargs.size;
350 info->size += kargs.size;
352 mali_session_gles_mem_profile_api_add(info, api,