/*
* 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;
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);
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);
}
/* 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;
+}
+