123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- /*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
- *
- * This program is free software and is provided to you under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
- *
- * A copy of the licence is included with the program, and can also be obtained from Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
- #include "mali_kernel_common.h"
- #include "mali_osk.h"
- #include "mali_osk_bitops.h"
- #include "mali_osk_list.h"
- #include "ump_osk.h"
- #include "ump_uk_types.h"
- #include "ump_ukk.h"
- #include "ump_kernel_common.h"
- #include "ump_kernel_descriptor_mapping.h"
- #include "ump_kernel_memory_backend.h"
- /**
- * Define the initial and maximum size of number of secure_ids on the system
- */
- #define UMP_SECURE_ID_TABLE_ENTRIES_INITIAL (128 )
- #define UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM (4096 )
- /**
- * Define the initial and maximum size of the ump_session_data::cookies_map,
- * which is a \ref ump_descriptor_mapping. This limits how many secure_ids
- * may be mapped into a particular process using _ump_ukk_map_mem().
- */
- #define UMP_COOKIES_PER_SESSION_INITIAL (UMP_SECURE_ID_TABLE_ENTRIES_INITIAL )
- #define UMP_COOKIES_PER_SESSION_MAXIMUM (UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM)
- struct ump_dev device;
- _mali_osk_errcode_t ump_kernel_constructor(void)
- {
- _mali_osk_errcode_t err;
- /* Perform OS Specific initialization */
- err = _ump_osk_init();
- if( _MALI_OSK_ERR_OK != err )
- {
- MSG_ERR(("Failed to initiaze the UMP Device Driver"));
- return err;
- }
- /* Init the global device */
- _mali_osk_memset(&device, 0, sizeof(device) );
- /* Create the descriptor map, which will be used for mapping secure ID to ump_dd_mem structs */
- device.secure_id_map_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0 , 0);
- if (NULL == device.secure_id_map_lock)
- {
- MSG_ERR(("Failed to create OSK lock for secure id lookup table\n"));
- return _MALI_OSK_ERR_NOMEM;
- }
- device.secure_id_map = ump_descriptor_mapping_create(UMP_SECURE_ID_TABLE_ENTRIES_INITIAL, UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM);
- if (NULL == device.secure_id_map)
- {
- _mali_osk_lock_term(device.secure_id_map_lock);
- MSG_ERR(("Failed to create secure id lookup table\n"));
- return _MALI_OSK_ERR_NOMEM;
- }
- /* Init memory backend */
- device.backend = ump_memory_backend_create();
- if (NULL == device.backend)
- {
- MSG_ERR(("Failed to create memory backend\n"));
- _mali_osk_lock_term(device.secure_id_map_lock);
- ump_descriptor_mapping_destroy(device.secure_id_map);
- return _MALI_OSK_ERR_NOMEM;
- }
- return _MALI_OSK_ERR_OK;
- }
- void ump_kernel_destructor(void)
- {
- DEBUG_ASSERT_POINTER(device.secure_id_map);
- DEBUG_ASSERT_POINTER(device.secure_id_map_lock);
- _mali_osk_lock_term(device.secure_id_map_lock);
- device.secure_id_map_lock = NULL;
- ump_descriptor_mapping_destroy(device.secure_id_map);
- device.secure_id_map = NULL;
- device.backend->shutdown(device.backend);
- device.backend = NULL;
- ump_memory_backend_destroy();
- _ump_osk_term();
- }
- /** Creates a new UMP session
- */
- _mali_osk_errcode_t _ump_ukk_open( void** context )
- {
- struct ump_session_data * session_data;
- /* allocated struct to track this session */
- session_data = (struct ump_session_data *)_mali_osk_malloc(sizeof(struct ump_session_data));
- if (NULL == session_data)
- {
- MSG_ERR(("Failed to allocate ump_session_data in ump_file_open()\n"));
- return _MALI_OSK_ERR_NOMEM;
- }
- session_data->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0);
- if( NULL == session_data->lock )
- {
- MSG_ERR(("Failed to initialize lock for ump_session_data in ump_file_open()\n"));
- _mali_osk_free(session_data);
- return _MALI_OSK_ERR_NOMEM;
- }
- session_data->cookies_map = ump_descriptor_mapping_create( UMP_COOKIES_PER_SESSION_INITIAL, UMP_COOKIES_PER_SESSION_MAXIMUM );
- if ( NULL == session_data->cookies_map )
- {
- MSG_ERR(("Failed to create descriptor mapping for _ump_ukk_map_mem cookies\n"));
- _mali_osk_lock_term( session_data->lock );
- _mali_osk_free( session_data );
- return _MALI_OSK_ERR_NOMEM;
- }
- _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_list);
- _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_mappings_list);
- /* Since initial version of the UMP interface did not use the API_VERSION ioctl we have to assume
- that it is this version, and not the "latest" one: UMP_IOCTL_API_VERSION
- Current and later API versions would do an additional call to this IOCTL and update this variable
- to the correct one.*/
- session_data->api_version = MAKE_VERSION_ID(1);
- *context = (void*)session_data;
- session_data->cache_operations_ongoing = 0 ;
- session_data->has_pending_level1_cache_flush = 0;
- DBG_MSG(2, ("New session opened\n"));
- return _MALI_OSK_ERR_OK;
- }
- _mali_osk_errcode_t _ump_ukk_close( void** context )
- {
- struct ump_session_data * session_data;
- ump_session_memory_list_element * item;
- ump_session_memory_list_element * tmp;
- session_data = (struct ump_session_data *)*context;
- if (NULL == session_data)
- {
- MSG_ERR(("Session data is NULL in _ump_ukk_close()\n"));
- return _MALI_OSK_ERR_INVALID_ARGS;
- }
- /* Unmap any descriptors mapped in. */
- if (0 == _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list))
- {
- ump_memory_allocation *descriptor;
- ump_memory_allocation *temp;
- DBG_MSG(1, ("Memory mappings found on session usage list during session termination\n"));
- /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */
- _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->list_head_session_memory_mappings_list, ump_memory_allocation, list)
- {
- _ump_uk_unmap_mem_s unmap_args;
- DBG_MSG(4, ("Freeing block with phys address 0x%x size 0x%x mapped in user space at 0x%x\n",
- descriptor->phys_addr, descriptor->size, descriptor->mapping));
- unmap_args.ctx = (void*)session_data;
- unmap_args.mapping = descriptor->mapping;
- unmap_args.size = descriptor->size;
- unmap_args._ukk_private = NULL; /* NOTE: unused */
- unmap_args.cookie = descriptor->cookie;
- /* NOTE: This modifies the list_head_session_memory_mappings_list */
- _ump_ukk_unmap_mem( &unmap_args );
- }
- }
- /* ASSERT that we really did free everything, because _ump_ukk_unmap_mem()
- * can fail silently. */
- DEBUG_ASSERT( _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list) );
- _MALI_OSK_LIST_FOREACHENTRY(item, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list)
- {
- _mali_osk_list_del(&item->list);
- DBG_MSG(2, ("Releasing UMP memory %u as part of file close\n", item->mem->secure_id));
- ump_dd_reference_release(item->mem);
- _mali_osk_free(item);
- }
- ump_descriptor_mapping_destroy( session_data->cookies_map );
- _mali_osk_lock_term(session_data->lock);
- _mali_osk_free(session_data);
- DBG_MSG(2, ("Session closed\n"));
- return _MALI_OSK_ERR_OK;
- }
- _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args )
- {
- struct ump_session_data * session_data;
- ump_memory_allocation * descriptor; /* Describes current mapping of memory */
- _mali_osk_errcode_t err;
- unsigned long offset = 0;
- unsigned long left;
- ump_dd_handle handle; /* The real UMP handle for this memory. Its real datatype is ump_dd_mem* */
- ump_dd_mem * mem; /* The real UMP memory. It is equal to the handle, but with exposed struct */
- u32 block;
- int map_id;
- session_data = (ump_session_data *)args->ctx;
- if( NULL == session_data )
- {
- MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
- return _MALI_OSK_ERR_INVALID_ARGS;
- }
- descriptor = (ump_memory_allocation*) _mali_osk_calloc( 1, sizeof(ump_memory_allocation));
- if (NULL == descriptor)
- {
- MSG_ERR(("ump_ukk_map_mem: descriptor allocation failed\n"));
- return _MALI_OSK_ERR_NOMEM;
- }
- handle = ump_dd_handle_create_from_secure_id(args->secure_id);
- if ( UMP_DD_HANDLE_INVALID == handle)
- {
- _mali_osk_free(descriptor);
- DBG_MSG(1, ("Trying to map unknown secure ID %u\n", args->secure_id));
- return _MALI_OSK_ERR_FAULT;
- }
- mem = (ump_dd_mem*)handle;
- DEBUG_ASSERT(mem);
- if (mem->size_bytes != args->size)
- {
- _mali_osk_free(descriptor);
- ump_dd_reference_release(handle);
- DBG_MSG(1, ("Trying to map too much or little. ID: %u, virtual size=%lu, UMP size: %lu\n", args->secure_id, args->size, mem->size_bytes));
- return _MALI_OSK_ERR_FAULT;
- }
- map_id = ump_descriptor_mapping_allocate_mapping( session_data->cookies_map, (void*) descriptor );
- if (map_id < 0)
- {
- _mali_osk_free(descriptor);
- ump_dd_reference_release(handle);
- DBG_MSG(1, ("ump_ukk_map_mem: unable to allocate a descriptor_mapping for return cookie\n"));
- return _MALI_OSK_ERR_NOMEM;
- }
- descriptor->size = args->size;
- descriptor->handle = handle;
- descriptor->phys_addr = args->phys_addr;
- descriptor->process_mapping_info = args->_ukk_private;
- descriptor->ump_session = session_data;
- descriptor->cookie = (u32)map_id;
- if ( mem->is_cached )
- {
- descriptor->is_cached = 1;
- args->is_cached = 1;
- DBG_MSG(3, ("Mapping UMP secure_id: %d as cached.\n", args->secure_id));
- }
- else
- {
- descriptor->is_cached = 0;
- args->is_cached = 0;
- DBG_MSG(3, ("Mapping UMP secure_id: %d as Uncached.\n", args->secure_id));
- }
- _mali_osk_list_init( &descriptor->list );
- err = _ump_osk_mem_mapregion_init( descriptor );
- if( _MALI_OSK_ERR_OK != err )
- {
- DBG_MSG(1, ("Failed to initialize memory mapping in _ump_ukk_map_mem(). ID: %u\n", args->secure_id));
- ump_descriptor_mapping_free( session_data->cookies_map, map_id );
- _mali_osk_free(descriptor);
- ump_dd_reference_release(mem);
- return err;
- }
- DBG_MSG(4, ("Mapping virtual to physical memory: ID: %u, size:%lu, first physical addr: 0x%08lx, number of regions: %lu\n",
- mem->secure_id,
- mem->size_bytes,
- ((NULL != mem->block_array) ? mem->block_array->addr : 0),
- mem->nr_blocks));
- left = descriptor->size;
- /* loop over all blocks and map them in */
- for (block = 0; block < mem->nr_blocks; block++)
- {
- unsigned long size_to_map;
- if (left > mem->block_array[block].size)
- {
- size_to_map = mem->block_array[block].size;
- }
- else
- {
- size_to_map = left;
- }
- if (_MALI_OSK_ERR_OK != _ump_osk_mem_mapregion_map(descriptor, offset, (u32 *)&(mem->block_array[block].addr), size_to_map ) )
- {
- DBG_MSG(1, ("WARNING: _ump_ukk_map_mem failed to map memory into userspace\n"));
- ump_descriptor_mapping_free( session_data->cookies_map, map_id );
- ump_dd_reference_release(mem);
- _ump_osk_mem_mapregion_term( descriptor );
- _mali_osk_free(descriptor);
- return _MALI_OSK_ERR_FAULT;
- }
- left -= size_to_map;
- offset += size_to_map;
- }
- /* Add to the ump_memory_allocation tracking list */
- _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- _mali_osk_list_add( &descriptor->list, &session_data->list_head_session_memory_mappings_list );
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- args->mapping = descriptor->mapping;
- args->cookie = descriptor->cookie;
- return _MALI_OSK_ERR_OK;
- }
- void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args )
- {
- struct ump_session_data * session_data;
- ump_memory_allocation * descriptor;
- ump_dd_handle handle;
- session_data = (ump_session_data *)args->ctx;
- if( NULL == session_data )
- {
- MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
- return;
- }
- if (0 != ump_descriptor_mapping_get( session_data->cookies_map, (int)args->cookie, (void**)&descriptor) )
- {
- MSG_ERR(("_ump_ukk_map_mem: cookie 0x%X not found for this session\n", args->cookie ));
- return;
- }
- DEBUG_ASSERT_POINTER(descriptor);
- handle = descriptor->handle;
- if ( UMP_DD_HANDLE_INVALID == handle)
- {
- DBG_MSG(1, ("WARNING: Trying to unmap unknown handle: UNKNOWN\n"));
- return;
- }
- /* Remove the ump_memory_allocation from the list of tracked mappings */
- _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- _mali_osk_list_del( &descriptor->list );
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- ump_descriptor_mapping_free( session_data->cookies_map, (int)args->cookie );
- ump_dd_reference_release(handle);
- _ump_osk_mem_mapregion_term( descriptor );
- _mali_osk_free(descriptor);
- }
- u32 _ump_ukk_report_memory_usage( void )
- {
- if(device.backend->stat)
- return device.backend->stat(device.backend);
- else
- return 0;
- }
|