_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args ) { struct dump_info info = { 0, 0, 0, NULL }; struct mali_session_data * session_data; MALI_DEBUG_ASSERT_POINTER(args); MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); MALI_CHECK_NON_NULL(args->buffer, _MALI_OSK_ERR_INVALID_ARGS); session_data = (struct mali_session_data *)(args->ctx); info.buffer_left = args->size; info.buffer = args->buffer; args->register_writes = info.buffer; MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info)); args->page_table_dump = info.buffer; MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info)); args->register_writes_size = info.register_writes_size; args->page_table_dump_size = info.page_table_dump_size; MALI_SUCCESS; }
_mali_osk_errcode_t _mali_ukk_release_ump_mem(_mali_uk_release_ump_mem_s *args) { mali_mem_allocation * descriptor; struct mali_session_data *session; MALI_DEBUG_ASSERT_POINTER(args); MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); session = (struct mali_session_data *)args->ctx; MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_INVALID_ARGS); if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session->descriptor_mapping, args->cookie, (void**)&descriptor)) { MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release ump memory\n", args->cookie)); MALI_ERROR(_MALI_OSK_ERR_FAULT); } descriptor = mali_descriptor_mapping_free(session->descriptor_mapping, args->cookie); if (NULL != descriptor) { _mali_osk_mutex_wait(session->memory_lock); mali_mem_ump_release(descriptor); _mali_osk_mutex_signal(session->memory_lock); mali_mem_descriptor_destroy(descriptor); } MALI_SUCCESS; }
int soft_job_start_wrapper(struct mali_session_data *session, _mali_uk_soft_job_start_s __user *uargs) { _mali_uk_soft_job_start_s kargs; u32 type, point; u64 user_job; struct mali_timeline_fence fence; struct mali_soft_job *job = NULL; u32 __user *job_id_ptr = NULL; /* If the job was started successfully, 0 is returned. If there was an error, but the job * was started, we return -ENOENT. For anything else returned, the job was not started. */ MALI_CHECK_NON_NULL(uargs, -EINVAL); MALI_CHECK_NON_NULL(session, -EINVAL); MALI_DEBUG_ASSERT_POINTER(session->soft_job_system); if (0 != copy_from_user(&kargs, uargs, sizeof(kargs))) { return -EFAULT; } type = kargs.type; user_job = kargs.user_job; job_id_ptr = (u32 __user *)(uintptr_t)kargs.job_id_ptr; mali_timeline_fence_copy_uk_fence(&fence, &kargs.fence); if ((MALI_SOFT_JOB_TYPE_USER_SIGNALED != type) && (MALI_SOFT_JOB_TYPE_SELF_SIGNALED != type)) { MALI_DEBUG_PRINT_ERROR(("Invalid soft job type specified\n")); return -EINVAL; } /* Create soft job. */ job = mali_soft_job_create(session->soft_job_system, (enum mali_soft_job_type)type, user_job); if (unlikely(NULL == job)) { return map_errcode(_MALI_OSK_ERR_NOMEM); } /* Write job id back to user space. */ if (0 != put_user(job->id, job_id_ptr)) { MALI_PRINT_ERROR(("Mali Soft Job: failed to put job id")); mali_soft_job_destroy(job); return map_errcode(_MALI_OSK_ERR_NOMEM); } /* Start soft job. */ point = mali_soft_job_start(job, &fence); if (0 != put_user(point, &uargs->point)) { /* Let user space know that something failed after the job was started. */ return -ENOENT; } return 0; }
static _mali_osk_errcode_t initialize_subsystems(void) { int i, j; _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; /* default error code */ MALI_CHECK_NON_NULL(system_info_lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 0 ), _MALI_OSK_ERR_FAULT); #ifdef MALI_SESSION_MEMORY_USAGE MALI_CHECK_NON_NULL(session_data_lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 0 ), _MALI_OSK_ERR_FAULT); _MALI_OSK_INIT_LIST_HEAD(&session_data_head); #endif for (i = 0; i < (int)SUBSYSTEMS_COUNT; ++i) { if (NULL != subsystems[i]->startup) { /* the subsystem has a startup function defined */ err = subsystems[i]->startup(i); /* the subsystem identifier is the offset in our subsystems array */ if (_MALI_OSK_ERR_OK != err) goto cleanup; } } for (j = 0; j < (int)SUBSYSTEMS_COUNT; ++j) { if (NULL != subsystems[j]->load_complete) { /* the subsystem has a load_complete function defined */ err = subsystems[j]->load_complete(j); if (_MALI_OSK_ERR_OK != err) goto cleanup; } } /* All systems loaded and resources registered */ /* Build system info */ if (_MALI_OSK_ERR_OK != build_system_info()) goto cleanup; MALI_SUCCESS; /* all ok */ cleanup: /* i is index of subsystem which failed to start, all indices before that has to be shut down */ for (i = i - 1; i >= 0; --i) { /* the subsystem identifier is the offset in our subsystems array */ /* Call possible shutdown notficiation functions */ if (NULL != subsystems[i]->shutdown) subsystems[i]->shutdown(i); } #ifdef MALI_SESSION_MEMORY_USAGE _mali_osk_lock_term( session_data_lock ); #endif _mali_osk_lock_term( system_info_lock ); MALI_ERROR(err); /* err is what the module which failed its startup returned, or the default */ }
int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs) { _mali_osk_errcode_t err; MALI_CHECK_NON_NULL(uargs, -EINVAL); MALI_CHECK_NON_NULL(session_data, -EINVAL); err = _mali_ukk_gp_start_job(session_data, uargs); if (_MALI_OSK_ERR_OK != err) return map_errcode(err); return 0; }
int pp_disable_wb_wrapper(struct mali_session_data *session_data, _mali_uk_pp_disable_wb_s __user *uargs) { _mali_uk_pp_disable_wb_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_pp_disable_wb_s))) return -EFAULT; kargs.ctx = (uintptr_t)session_data; _mali_ukk_pp_job_disable_wb(&kargs); return 0; }
int mem_get_cpu_adjust_wrapper(struct mali_session_data *session_data, _mali_uk_get_cpu_adjust __user *uargs) { _mali_uk_get_cpu_adjust kargs; MALI_CHECK_NON_NULL(uargs, -EINVAL); MALI_CHECK_NON_NULL(session_data, -EINVAL); kargs.ctx = session_data; kargs.value = PHYS_TO_BUS_ADDRESS_ADJUST; if (0 != put_user(kargs.value, &uargs->value)) return -EFAULT; return 0; }
int mem_get_miu1_base_wrapper(struct mali_session_data *session_data, _mali_uk_get_miu1_base __user *uargs) { _mali_uk_get_miu1_base kargs; MALI_CHECK_NON_NULL(uargs, -EINVAL); MALI_CHECK_NON_NULL(session_data, -EINVAL); kargs.ctx = session_data; kargs.addr = MSTAR_MIU1_PHY_BASE; if (0 != put_user(kargs.addr, &uargs->addr)) return -EFAULT; return 0; }
int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs) { _mali_osk_errcode_t err; /* If the job was started successfully, 0 is returned. If there was an error, but the job * was started, we return -ENOENT. For anything else returned, the job was not started. */ MALI_CHECK_NON_NULL(uargs, -EINVAL); MALI_CHECK_NON_NULL(session_data, -EINVAL); err = _mali_ukk_gp_start_job(session_data, uargs); if (_MALI_OSK_ERR_OK != err) return map_errcode(err); return 0; }
_mali_osk_errcode_t _mali_ukk_get_gp_core_version(_mali_uk_get_gp_core_version_s *args) { MALI_DEBUG_ASSERT_POINTER(args); MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); args->version = gp_version; return _MALI_OSK_ERR_OK; }
_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args ) { _mali_osk_notification_t * notification; _mali_osk_notification_queue_t *queue; /* check input */ MALI_DEBUG_ASSERT_POINTER(args); MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); queue = (_mali_osk_notification_queue_t *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_core_id); /* if the queue does not exist we're currently shutting down */ if (NULL == queue) { MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); MALI_SUCCESS; } notification = _mali_osk_notification_create(args->type, 0); if ( NULL == notification) { MALI_PRINT_ERROR( ("Failed to create notification object\n")) ; return _MALI_OSK_ERR_NOMEM; } _mali_osk_notification_queue_send(queue, notification); MALI_SUCCESS; /* all ok */ }
int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs) { _mali_uk_get_pp_core_version_s kargs; _mali_osk_errcode_t err; MALI_CHECK_NON_NULL(uargs, -EINVAL); MALI_CHECK_NON_NULL(session_data, -EINVAL); kargs.ctx = (uintptr_t)session_data; err = _mali_ukk_get_pp_core_version(&kargs); if (_MALI_OSK_ERR_OK != err) return map_errcode(err); if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT; return 0; }
_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores(_mali_uk_get_gp_number_of_cores_s *args) { MALI_DEBUG_ASSERT_POINTER(args); MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); args->number_of_cores = 1; return _MALI_OSK_ERR_OK; }
_mali_osk_errcode_t _mali_ukk_close(void **context) { int i; struct mali_session_data * session_data; MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS); session_data = (struct mali_session_data *)*context; MALI_DEBUG_PRINT(2, ("Session ending\n")); /* end subsystem sessions in the reverse order they where started in */ for (i = SUBSYSTEMS_COUNT - 1; i >= 0; --i) { if (NULL != subsystems[i]->session_end) subsystems[i]->session_end(session_data, &session_data->subsystem_data[i]); } _mali_osk_notification_queue_term(session_data->ioctl_queue); _mali_osk_free(session_data); *context = NULL; MALI_DEBUG_PRINT(2, ("Session has ended\n")); MALI_SUCCESS; }
int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument) { _mali_uk_map_external_mem_s uk_args; _mali_osk_errcode_t err_code; /* validate input */ /* the session_data pointer was validated by caller */ MALI_CHECK_NON_NULL( argument, -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)) ) { return -EFAULT; } uk_args.ctx = session_data; err_code = _mali_ukk_map_external_mem( &uk_args ); 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; 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")); } } return -EFAULT; } /* Return the error that _mali_ukk_free_big_block produced */ return map_errcode(err_code); }
int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs) { _mali_uk_init_mem_s kargs; _mali_osk_errcode_t err; MALI_CHECK_NON_NULL(uargs, -EINVAL); kargs.ctx = session_data; err = _mali_ukk_init_mem(&kargs); if (_MALI_OSK_ERR_OK != err) { return map_errcode(err); } if (0 != put_user(kargs.mali_address_base, &uargs->mali_address_base)) goto mem_init_rollback; if (0 != put_user(kargs.memory_size, &uargs->memory_size)) goto mem_init_rollback; return 0; mem_init_rollback: { _mali_uk_term_mem_s kargs; kargs.ctx = session_data; err = _mali_ukk_term_mem(&kargs); if (_MALI_OSK_ERR_OK != err) { MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_init_mem, as a result of failing put_user(), failed\n")); } } return -EFAULT; }
int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs) { _mali_uk_profiling_get_event_s kargs; _mali_osk_errcode_t err; MALI_CHECK_NON_NULL(uargs, -EINVAL); if (0 != get_user(kargs.index, &uargs->index)) { return -EFAULT; } kargs.ctx = session_data; err = _mali_ukk_profiling_get_event(&kargs); if (_MALI_OSK_ERR_OK != err) { return map_errcode(err); } kargs.ctx = NULL; if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_profiling_get_event_s))) { return -EFAULT; } return 0; }
int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs) { _mali_uk_profiling_start_s kargs; _mali_osk_errcode_t err; MALI_CHECK_NON_NULL(uargs, -EINVAL); if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_start_s))) { return -EFAULT; } kargs.ctx = session_data; err = _mali_ukk_profiling_start(&kargs); if (_MALI_OSK_ERR_OK != err) { return map_errcode(err); } if (0 != put_user(kargs.limit, &uargs->limit)) { return -EFAULT; } return 0; }
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; err = _mali_ukk_query_mmu_page_table_dump_size(&kargs); if (_MALI_OSK_ERR_OK != err) return map_errcode(err); if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT; return 0; }
static _mali_osk_errcode_t mali_kernel_subsystem_core_system_info_fill(_mali_system_info* info) { MALI_CHECK_NON_NULL(info, _MALI_OSK_ERR_INVALID_ARGS); info->drivermode = _MALI_DRIVER_MODE_NORMAL; MALI_SUCCESS; }
int gp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_number_of_cores_s __user *uargs) { _mali_uk_get_gp_number_of_cores_s kargs; _mali_osk_errcode_t err; MALI_CHECK_NON_NULL(uargs, -EINVAL); MALI_CHECK_NON_NULL(session_data, -EINVAL); kargs.ctx = session_data; err = _mali_ukk_get_gp_number_of_cores(&kargs); if (_MALI_OSK_ERR_OK != err) return map_errcode(err); /* no known transactions to roll-back */ if (0 != put_user(kargs.number_of_cores, &uargs->number_of_cores)) return -EFAULT; return 0; }
int gp_suspend_response_wrapper(struct mali_session_data *session_data, _mali_uk_gp_suspend_response_s __user *uargs) { _mali_uk_gp_suspend_response_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_gp_suspend_response_s))) return -EFAULT; kargs.ctx = session_data; err = _mali_ukk_gp_suspend_response(&kargs); if (_MALI_OSK_ERR_OK != err) return map_errcode(err); if (0 != put_user(kargs.cookie, &uargs->cookie)) return -EFAULT; /* no known transactions to roll-back */ return 0; }
_mali_osk_errcode_t mali_memory_bind_ext_mem(mali_mem_allocation *alloc, mali_mem_backend *mem_backend, u32 phys_addr, u32 flag) { struct mali_session_data *session; _mali_osk_errcode_t err; u32 virt, phys, size; MALI_DEBUG_ASSERT_POINTER(mem_backend); MALI_DEBUG_ASSERT_POINTER(alloc); size = alloc->psize; session = (struct mali_session_data *)(uintptr_t)alloc->session; MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_INVALID_ARGS); /* check arguments */ /* NULL might be a valid Mali address */ if (!size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); /* size must be a multiple of the system page size */ if (size % _MALI_OSK_MALI_PAGE_SIZE) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); /* Validate the mali physical range */ if (_MALI_OSK_ERR_OK != mali_mem_validation_check(phys_addr, size)) { return _MALI_OSK_ERR_FAULT; } if (flag & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) { alloc->flags |= MALI_MEM_FLAG_MALI_GUARD_PAGE; } mali_session_memory_lock(session); virt = alloc->mali_vma_node.vm_node.start; phys = phys_addr; err = mali_mem_mali_map_prepare(alloc); if (_MALI_OSK_ERR_OK != err) { mali_session_memory_unlock(session); return _MALI_OSK_ERR_NOMEM; } mali_mmu_pagedir_update(session->page_directory, virt, phys, size, MALI_MMU_FLAGS_DEFAULT); if (alloc->flags & MALI_MEM_FLAG_MALI_GUARD_PAGE) { mali_mmu_pagedir_update(session->page_directory, virt + size, phys, _MALI_OSK_MALI_PAGE_SIZE, MALI_MMU_FLAGS_DEFAULT); } MALI_DEBUG_PRINT(3, ("Requested to map physical memory 0x%x-0x%x into virtual memory 0x%x\n", phys_addr, (phys_addr + size - 1), virt)); session->mali_mem_array[mem_backend->type] += mem_backend->size; mali_session_memory_unlock(session); MALI_SUCCESS; }
int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs) { _mali_uk_mem_write_safe_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))) { return -EFAULT; } kargs.ctx = session_data; /* 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; } /* 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 0; }
int profiling_memory_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); kargs.ctx = (uintptr_t)session_data; err = _mali_ukk_profiling_memory_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; }
_mali_osk_errcode_t _mali_ukk_open(void **context) { int i; _mali_osk_errcode_t err; struct mali_session_data * session_data; /* allocated struct to track this session */ session_data = (struct mali_session_data *)_mali_osk_malloc(sizeof(struct mali_session_data)); MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_NOMEM); _mali_osk_memset(session_data->subsystem_data, 0, sizeof(session_data->subsystem_data)); /* create a response queue for this session */ session_data->ioctl_queue = _mali_osk_notification_queue_init(); if (NULL == session_data->ioctl_queue) { _mali_osk_free(session_data); MALI_ERROR(_MALI_OSK_ERR_NOMEM); } MALI_DEBUG_PRINT(3, ("Session starting\n")); /* call session_begin on all subsystems */ for (i = 0; i < (int)SUBSYSTEMS_COUNT; ++i) { if (NULL != subsystems[i]->session_begin) { /* subsystem has a session_begin */ err = subsystems[i]->session_begin(session_data, &session_data->subsystem_data[i], session_data->ioctl_queue); MALI_CHECK_GOTO(err == _MALI_OSK_ERR_OK, cleanup); } } *context = (void*)session_data; MALI_DEBUG_PRINT(3, ("Session started\n")); MALI_SUCCESS; cleanup: MALI_DEBUG_PRINT(2, ("Session startup failed\n")); /* i is index of subsystem which failed session begin, all indices before that has to be ended */ /* end subsystem sessions in the reverse order they where started in */ for (i = i - 1; i >= 0; --i) { if (NULL != subsystems[i]->session_end) subsystems[i]->session_end(session_data, &session_data->subsystem_data[i]); } _mali_osk_notification_queue_term(session_data->ioctl_queue); _mali_osk_free(session_data); /* return what the subsystem which failed session start returned */ MALI_ERROR(err); }
int mem_get_big_block_wrapper( struct file * filp, _mali_uk_get_big_block_s __user * argument ) { _mali_uk_get_big_block_s uk_args; _mali_osk_errcode_t err_code; /* validate input */ /* the session_data pointer was validated by caller */ MALI_CHECK_NON_NULL( argument, -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_get_big_block_s)) ) { return -EFAULT; } /* This interface inserts something into the ukk_private word */ uk_args.ukk_private = (u32)filp; uk_args.ctx = filp->private_data; err_code = _mali_ukk_get_big_block( &uk_args ); /* Do not leak the private word back into user space */ uk_args.ukk_private = 0; if ( _MALI_OSK_ERR_OK != err_code ) { return map_errcode(err_code); } /* From this point on, we must roll-back any failing action to preserve the * meaning of the U/K interface (e.g. when excluded) */ /* transfer response back to user space */ if ( 0 != copy_to_user(argument, &uk_args, sizeof(_mali_uk_get_big_block_s)) ) { /* Roll-back - the _mali_uk_get_big_block call succeeded, so all * values in uk_args will be correct */ _mali_uk_free_big_block_s uk_args_rollback = {0, }; uk_args_rollback.ctx = uk_args.ctx; uk_args_rollback.cookie = uk_args.cookie; err_code = _mali_ukk_free_big_block( &uk_args_rollback ); if ( _MALI_OSK_ERR_OK != err_code ) { /* error in DEBUG and RELEASE */ MALI_PRINT_ERROR( ("Failed to rollback get_big_block: %.8X\n", (u32)err_code) ); } return -EFAULT; } return 0; }
int request_high_priority_wrapper(struct mali_session_data *session_data, _mali_uk_request_high_priority_s __user *uargs) { _mali_uk_request_high_priority_s kargs; _mali_osk_errcode_t err; MALI_CHECK_NON_NULL(uargs, -EINVAL); kargs.ctx = session_data; err = _mali_ukk_request_high_priority(&kargs); kargs.ctx = NULL; return map_errcode(err); }
int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs) { _mali_uk_gp_start_job_s kargs; _mali_osk_errcode_t err; MALI_CHECK_NON_NULL(uargs, -EINVAL); MALI_CHECK_NON_NULL(session_data, -EINVAL); if (!access_ok(VERIFY_WRITE, uargs, sizeof(_mali_uk_gp_start_job_s))) { return -EFAULT; } if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_start_job_s))) return -EFAULT; kargs.ctx = session_data; err = _mali_ukk_gp_start_job(&kargs); if (_MALI_OSK_ERR_OK != err) return map_errcode(err); kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_gp_start_job_s))) { /* * If this happens, then user space will not know that the job was actually started, * and if we return a queued job, then user space will still think that one is still queued. * This will typically lead to a deadlock in user space. * This could however only happen if user space deliberately passes a user buffer which * passes the access_ok(VERIFY_WRITE) check, but isn't fully writable at the time of copy_to_user(). * The official Mali driver will never attempt to do that, and kernel space should not be affected. * That is why we do not bother to do a complex rollback in this very very very rare case. */ return -EFAULT; } return 0; }