_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;
}
Beispiel #7
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;
}
Beispiel #8
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;
}
Beispiel #9
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;
}
Beispiel #17
0
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;
}
Beispiel #18
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;
}
Beispiel #21
0
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;
}
Beispiel #22
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);
}
Beispiel #27
0
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;
}