import OT_8063_20170412 mali driver
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / gpu / mt8127 / mali / mali / linux / mali_ukk_mem.c
index 6baf151a615a0e08047498ccb721202be306e4a4..8e3f117c432218053cc10c4baa22a0bd41533832 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This confidential and proprietary software may be used only as
  * authorised by a licensing agreement from ARM Limited
- * (C) COPYRIGHT 2008-2013 ARM Limited
+ * (C) COPYRIGHT 2008-2015 ARM Limited
  * ALL RIGHTS RESERVED
  * The entire notice above must be reproduced on all authorised
  * copies and copies may only be made to the extent permitted
 #include "mali_session.h"
 #include "mali_ukk_wrappers.h"
 
-int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs)
+int mem_alloc_wrapper(struct mali_session_data *session_data, _mali_uk_alloc_mem_s __user *uargs)
 {
-       _mali_uk_mem_write_safe_s kargs;
+       _mali_uk_alloc_mem_s kargs;
        _mali_osk_errcode_t err;
 
        MALI_CHECK_NON_NULL(uargs, -EINVAL);
        MALI_CHECK_NON_NULL(session_data, -EINVAL);
 
-       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_mem_write_safe_s))) {
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_alloc_mem_s))) {
                return -EFAULT;
        }
+       kargs.ctx = (uintptr_t)session_data;
 
-       kargs.ctx = session_data;
+       err = _mali_ukk_mem_allocate(&kargs);
 
-       /* Check if we can access the buffers */
-       if (!access_ok(VERIFY_WRITE, kargs.dest, kargs.size)
-           || !access_ok(VERIFY_READ, kargs.src, kargs.size)) {
-               return -EINVAL;
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
        }
 
-       /* Check if size wraps */
-       if ((kargs.size + kargs.dest) <= kargs.dest
-           || (kargs.size + kargs.src) <= kargs.src) {
-               return -EINVAL;
+       if (0 != put_user(kargs.backend_handle, &uargs->backend_handle)) {
+               return -EFAULT;
        }
 
-       err = _mali_ukk_mem_write_safe(&kargs);
+       return 0;
+}
+
+int mem_free_wrapper(struct mali_session_data *session_data, _mali_uk_free_mem_s __user *uargs)
+{
+       _mali_uk_free_mem_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_free_mem_s))) {
+               return -EFAULT;
+       }
+       kargs.ctx = (uintptr_t)session_data;
+
+       err = _mali_ukk_mem_free(&kargs);
+
        if (_MALI_OSK_ERR_OK != err) {
                return map_errcode(err);
        }
 
-       if (0 != put_user(kargs.size, &uargs->size)) {
+       if (0 != put_user(kargs.free_pages_nr, &uargs->free_pages_nr)) {
                return -EFAULT;
        }
 
        return 0;
 }
 
-int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument)
+int mem_bind_wrapper(struct mali_session_data *session_data, _mali_uk_bind_mem_s __user *uargs)
 {
-       _mali_uk_map_external_mem_s uk_args;
-       _mali_osk_errcode_t err_code;
+       _mali_uk_bind_mem_s kargs;
+       _mali_osk_errcode_t err;
 
-       /* validate input */
-       /* the session_data pointer was validated by caller */
-       MALI_CHECK_NON_NULL( argument, -EINVAL);
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
 
-       /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
-       if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_map_external_mem_s)) ) {
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_bind_mem_s))) {
                return -EFAULT;
        }
+       kargs.ctx = (uintptr_t)session_data;
 
-       uk_args.ctx = session_data;
-       err_code = _mali_ukk_map_external_mem( &uk_args );
+       err = _mali_ukk_mem_bind(&kargs);
 
-       if (0 != put_user(uk_args.cookie, &argument->cookie)) {
-               if (_MALI_OSK_ERR_OK == err_code) {
-                       /* Rollback */
-                       _mali_uk_unmap_external_mem_s uk_args_unmap;
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       return 0;
+}
 
-                       uk_args_unmap.ctx = session_data;
-                       uk_args_unmap.cookie = uk_args.cookie;
-                       err_code = _mali_ukk_unmap_external_mem( &uk_args_unmap );
-                       if (_MALI_OSK_ERR_OK != err_code) {
-                               MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_unmap_external_mem, as a result of failing put_user(), failed\n"));
-                       }
-               }
+int mem_unbind_wrapper(struct mali_session_data *session_data, _mali_uk_unbind_mem_s __user *uargs)
+{
+       _mali_uk_unbind_mem_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_unbind_mem_s))) {
                return -EFAULT;
        }
+       kargs.ctx = (uintptr_t)session_data;
+
+       err = _mali_ukk_mem_unbind(&kargs);
+
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
 
-       /* Return the error that _mali_ukk_free_big_block produced */
-       return map_errcode(err_code);
+       return 0;
 }
 
-int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument)
+
+int mem_cow_wrapper(struct mali_session_data *session_data, _mali_uk_cow_mem_s __user *uargs)
 {
-       _mali_uk_unmap_external_mem_s uk_args;
-       _mali_osk_errcode_t err_code;
+       _mali_uk_cow_mem_s kargs;
+       _mali_osk_errcode_t err;
 
-       /* validate input */
-       /* the session_data pointer was validated by caller */
-       MALI_CHECK_NON_NULL( argument, -EINVAL);
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
 
-       /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
-       if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_unmap_external_mem_s)) ) {
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_cow_mem_s))) {
                return -EFAULT;
        }
+       kargs.ctx = (uintptr_t)session_data;
+
+       err = _mali_ukk_mem_cow(&kargs);
+
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
 
-       uk_args.ctx = session_data;
-       err_code = _mali_ukk_unmap_external_mem( &uk_args );
+       if (0 != put_user(kargs.backend_handle, &uargs->backend_handle)) {
+               return -EFAULT;
+       }
 
-       /* Return the error that _mali_ukk_free_big_block produced */
-       return map_errcode(err_code);
+       return 0;
 }
 
-#if defined(CONFIG_MALI400_UMP)
-int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument)
+int mem_cow_modify_range_wrapper(struct mali_session_data *session_data, _mali_uk_cow_modify_range_s __user *uargs)
 {
-       _mali_uk_release_ump_mem_s uk_args;
-       _mali_osk_errcode_t err_code;
+       _mali_uk_cow_modify_range_s kargs;
+       _mali_osk_errcode_t err;
 
-       /* validate input */
-       /* the session_data pointer was validated by caller */
-       MALI_CHECK_NON_NULL( argument, -EINVAL);
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
 
-       /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
-       if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_release_ump_mem_s)) ) {
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_cow_modify_range_s))) {
                return -EFAULT;
        }
+       kargs.ctx = (uintptr_t)session_data;
 
-       uk_args.ctx = session_data;
-       err_code = _mali_ukk_release_ump_mem( &uk_args );
+       err = _mali_ukk_mem_cow_modify_range(&kargs);
 
-       /* Return the error that _mali_ukk_free_big_block produced */
-       return map_errcode(err_code);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       if (0 != put_user(kargs.change_pages_nr, &uargs->change_pages_nr)) {
+               return -EFAULT;
+       }
+       return 0;
 }
 
-int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument)
+int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user *uargs)
 {
-       _mali_uk_attach_ump_mem_s uk_args;
-       _mali_osk_errcode_t err_code;
+       _mali_uk_mem_write_safe_s kargs;
+       _mali_osk_errcode_t err;
 
-       /* validate input */
-       /* the session_data pointer was validated by caller */
-       MALI_CHECK_NON_NULL( argument, -EINVAL);
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
 
-       /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
-       if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_attach_ump_mem_s)) ) {
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_mem_write_safe_s))) {
                return -EFAULT;
        }
 
-       uk_args.ctx = session_data;
-       err_code = _mali_ukk_attach_ump_mem( &uk_args );
+       kargs.ctx = (uintptr_t)session_data;
 
-       if (0 != put_user(uk_args.cookie, &argument->cookie)) {
-               if (_MALI_OSK_ERR_OK == err_code) {
-                       /* Rollback */
-                       _mali_uk_release_ump_mem_s uk_args_unmap;
+       /* Check if we can access the buffers */
+       if (!access_ok(VERIFY_WRITE, kargs.dest, kargs.size)
+           || !access_ok(VERIFY_READ, kargs.src, kargs.size)) {
+               return -EINVAL;
+       }
 
-                       uk_args_unmap.ctx = session_data;
-                       uk_args_unmap.cookie = uk_args.cookie;
-                       err_code = _mali_ukk_release_ump_mem( &uk_args_unmap );
-                       if (_MALI_OSK_ERR_OK != err_code) {
-                               MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_attach_mem, as a result of failing put_user(), failed\n"));
-                       }
-               }
+       /* Check if size wraps */
+       if ((kargs.size + kargs.dest) <= kargs.dest
+           || (kargs.size + kargs.src) <= kargs.src) {
+               return -EINVAL;
+       }
+
+       err = _mali_ukk_mem_write_safe(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       if (0 != put_user(kargs.size, &uargs->size)) {
                return -EFAULT;
        }
 
-       /* Return the error that _mali_ukk_map_external_ump_mem produced */
-       return map_errcode(err_code);
+       return 0;
 }
-#endif /* CONFIG_MALI400_UMP */
 
-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)
+
+
+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)
 {
        _mali_uk_query_mmu_page_table_dump_size_s kargs;
        _mali_osk_errcode_t err;
@@ -178,7 +212,7 @@ int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session
        MALI_CHECK_NON_NULL(uargs, -EINVAL);
        MALI_CHECK_NON_NULL(session_data, -EINVAL);
 
-       kargs.ctx = session_data;
+       kargs.ctx = (uintptr_t)session_data;
 
        err = _mali_ukk_query_mmu_page_table_dump_size(&kargs);
        if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
@@ -188,35 +222,41 @@ int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session
        return 0;
 }
 
-int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs)
+int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user *uargs)
 {
        _mali_uk_dump_mmu_page_table_s kargs;
        _mali_osk_errcode_t err;
-       void *buffer;
+       void __user *user_buffer;
+       void *buffer = NULL;
        int rc = -EFAULT;
 
        /* validate input */
        MALI_CHECK_NON_NULL(uargs, -EINVAL);
        /* the session_data pointer was validated by caller */
 
-       kargs.buffer = NULL;
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_dump_mmu_page_table_s)))
+               goto err_exit;
 
-       /* get location of user buffer */
-       if (0 != get_user(buffer, &uargs->buffer)) goto err_exit;
-       /* get size of mmu page table info buffer from user space */
-       if ( 0 != get_user(kargs.size, &uargs->size) ) goto err_exit;
-       /* verify we can access the whole of the user buffer */
-       if (!access_ok(VERIFY_WRITE, buffer, kargs.size)) goto err_exit;
+       user_buffer = (void __user *)(uintptr_t)kargs.buffer;
+       if (!access_ok(VERIFY_WRITE, user_buffer, kargs.size))
+               goto err_exit;
 
        /* allocate temporary buffer (kernel side) to store mmu page table info */
-       MALI_CHECK(kargs.size > 0, -ENOMEM);
-       kargs.buffer = _mali_osk_valloc(kargs.size);
-       if (NULL == kargs.buffer) {
+       if (kargs.size <= 0)
+               return -EINVAL;
+       /* Allow at most 8MiB buffers, this is more than enough to dump a fully
+        * populated page table. */
+       if (kargs.size > SZ_8M)
+               return -EINVAL;
+
+       buffer = (void *)(uintptr_t)_mali_osk_valloc(kargs.size);
+       if (NULL == buffer) {
                rc = -ENOMEM;
                goto err_exit;
        }
 
-       kargs.ctx = session_data;
+       kargs.ctx = (uintptr_t)session_data;
+       kargs.buffer = (uintptr_t)buffer;
        err = _mali_ukk_dump_mmu_page_table(&kargs);
        if (_MALI_OSK_ERR_OK != err) {
                rc = map_errcode(err);
@@ -224,14 +264,47 @@ int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mal
        }
 
        /* copy mmu page table info back to user space and update pointers */
-       if (0 != copy_to_user(uargs->buffer, kargs.buffer, kargs.size) ) goto err_exit;
-       if (0 != put_user((kargs.register_writes - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->register_writes)) goto err_exit;
-       if (0 != put_user((kargs.page_table_dump - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->page_table_dump)) goto err_exit;
-       if (0 != put_user(kargs.register_writes_size, &uargs->register_writes_size)) goto err_exit;
-       if (0 != put_user(kargs.page_table_dump_size, &uargs->page_table_dump_size)) goto err_exit;
+       if (0 != copy_to_user(user_buffer, buffer, kargs.size))
+               goto err_exit;
+
+       kargs.register_writes = kargs.register_writes -
+                               (uintptr_t)buffer + (uintptr_t)user_buffer;
+       kargs.page_table_dump = kargs.page_table_dump -
+                               (uintptr_t)buffer + (uintptr_t)user_buffer;
+
+       if (0 != copy_to_user(uargs, &kargs, sizeof(kargs)))
+               goto err_exit;
+
        rc = 0;
 
 err_exit:
-       if (kargs.buffer) _mali_osk_vfree(kargs.buffer);
+       if (buffer) _mali_osk_vfree(buffer);
        return rc;
 }
+
+int mem_usage_get_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_memory_usage_get_s __user *uargs)
+{
+       _mali_osk_errcode_t err;
+       _mali_uk_profiling_memory_usage_get_s kargs;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_memory_usage_get_s))) {
+               return -EFAULT;
+       }
+
+       kargs.ctx = (uintptr_t)session_data;
+       err = _mali_ukk_mem_usage_get(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       kargs.ctx = (uintptr_t)NULL; /* prevent kernel address to be returned to user space */
+       if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_profiling_memory_usage_get_s))) {
+               return -EFAULT;
+       }
+
+       return 0;
+}
+