2 * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
4 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
7 * A copy of the licence is included with the program, and can also be obtained from Free Software
8 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
11 #include "mali_kernel_common.h"
13 #include "mali_osk_bitops.h"
14 #include "mali_osk_list.h"
16 #include "ump_uk_types.h"
18 #include "ump_kernel_common.h"
19 #include "ump_kernel_descriptor_mapping.h"
20 #include "ump_kernel_memory_backend.h"
25 * Define the initial and maximum size of number of secure_ids on the system
27 #define UMP_SECURE_ID_TABLE_ENTRIES_INITIAL (128 )
28 #define UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM (4096 )
32 * Define the initial and maximum size of the ump_session_data::cookies_map,
33 * which is a \ref ump_descriptor_mapping. This limits how many secure_ids
34 * may be mapped into a particular process using _ump_ukk_map_mem().
37 #define UMP_COOKIES_PER_SESSION_INITIAL (UMP_SECURE_ID_TABLE_ENTRIES_INITIAL )
38 #define UMP_COOKIES_PER_SESSION_MAXIMUM (UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM)
40 struct ump_dev device;
42 _mali_osk_errcode_t ump_kernel_constructor(void)
44 _mali_osk_errcode_t err;
46 /* Perform OS Specific initialization */
47 err = _ump_osk_init();
48 if( _MALI_OSK_ERR_OK != err )
50 MSG_ERR(("Failed to initiaze the UMP Device Driver"));
54 /* Init the global device */
55 _mali_osk_memset(&device, 0, sizeof(device) );
57 /* Create the descriptor map, which will be used for mapping secure ID to ump_dd_mem structs */
58 device.secure_id_map_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0 , 0);
59 if (NULL == device.secure_id_map_lock)
61 MSG_ERR(("Failed to create OSK lock for secure id lookup table\n"));
62 return _MALI_OSK_ERR_NOMEM;
65 device.secure_id_map = ump_descriptor_mapping_create(UMP_SECURE_ID_TABLE_ENTRIES_INITIAL, UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM);
66 if (NULL == device.secure_id_map)
68 _mali_osk_lock_term(device.secure_id_map_lock);
69 MSG_ERR(("Failed to create secure id lookup table\n"));
70 return _MALI_OSK_ERR_NOMEM;
73 /* Init memory backend */
74 device.backend = ump_memory_backend_create();
75 if (NULL == device.backend)
77 MSG_ERR(("Failed to create memory backend\n"));
78 _mali_osk_lock_term(device.secure_id_map_lock);
79 ump_descriptor_mapping_destroy(device.secure_id_map);
80 return _MALI_OSK_ERR_NOMEM;
83 return _MALI_OSK_ERR_OK;
86 void ump_kernel_destructor(void)
88 DEBUG_ASSERT_POINTER(device.secure_id_map);
89 DEBUG_ASSERT_POINTER(device.secure_id_map_lock);
91 _mali_osk_lock_term(device.secure_id_map_lock);
92 device.secure_id_map_lock = NULL;
94 ump_descriptor_mapping_destroy(device.secure_id_map);
95 device.secure_id_map = NULL;
97 device.backend->shutdown(device.backend);
98 device.backend = NULL;
100 ump_memory_backend_destroy();
105 /** Creates a new UMP session
107 _mali_osk_errcode_t _ump_ukk_open( void** context )
109 struct ump_session_data * session_data;
111 /* allocated struct to track this session */
112 session_data = (struct ump_session_data *)_mali_osk_malloc(sizeof(struct ump_session_data));
113 if (NULL == session_data)
115 MSG_ERR(("Failed to allocate ump_session_data in ump_file_open()\n"));
116 return _MALI_OSK_ERR_NOMEM;
119 session_data->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0);
120 if( NULL == session_data->lock )
122 MSG_ERR(("Failed to initialize lock for ump_session_data in ump_file_open()\n"));
123 _mali_osk_free(session_data);
124 return _MALI_OSK_ERR_NOMEM;
127 session_data->cookies_map = ump_descriptor_mapping_create( UMP_COOKIES_PER_SESSION_INITIAL, UMP_COOKIES_PER_SESSION_MAXIMUM );
129 if ( NULL == session_data->cookies_map )
131 MSG_ERR(("Failed to create descriptor mapping for _ump_ukk_map_mem cookies\n"));
133 _mali_osk_lock_term( session_data->lock );
134 _mali_osk_free( session_data );
135 return _MALI_OSK_ERR_NOMEM;
138 _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_list);
140 _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_mappings_list);
142 /* Since initial version of the UMP interface did not use the API_VERSION ioctl we have to assume
143 that it is this version, and not the "latest" one: UMP_IOCTL_API_VERSION
144 Current and later API versions would do an additional call to this IOCTL and update this variable
145 to the correct one.*/
146 session_data->api_version = MAKE_VERSION_ID(1);
148 *context = (void*)session_data;
150 session_data->cache_operations_ongoing = 0 ;
151 session_data->has_pending_level1_cache_flush = 0;
153 DBG_MSG(2, ("New session opened\n"));
155 return _MALI_OSK_ERR_OK;
158 _mali_osk_errcode_t _ump_ukk_close( void** context )
160 struct ump_session_data * session_data;
161 ump_session_memory_list_element * item;
162 ump_session_memory_list_element * tmp;
164 session_data = (struct ump_session_data *)*context;
165 if (NULL == session_data)
167 MSG_ERR(("Session data is NULL in _ump_ukk_close()\n"));
168 return _MALI_OSK_ERR_INVALID_ARGS;
171 /* Unmap any descriptors mapped in. */
172 if (0 == _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list))
174 ump_memory_allocation *descriptor;
175 ump_memory_allocation *temp;
177 DBG_MSG(1, ("Memory mappings found on session usage list during session termination\n"));
179 /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */
180 _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->list_head_session_memory_mappings_list, ump_memory_allocation, list)
182 _ump_uk_unmap_mem_s unmap_args;
183 DBG_MSG(4, ("Freeing block with phys address 0x%x size 0x%x mapped in user space at 0x%x\n",
184 descriptor->phys_addr, descriptor->size, descriptor->mapping));
185 unmap_args.ctx = (void*)session_data;
186 unmap_args.mapping = descriptor->mapping;
187 unmap_args.size = descriptor->size;
188 unmap_args._ukk_private = NULL; /* NOTE: unused */
189 unmap_args.cookie = descriptor->cookie;
191 /* NOTE: This modifies the list_head_session_memory_mappings_list */
192 _ump_ukk_unmap_mem( &unmap_args );
196 /* ASSERT that we really did free everything, because _ump_ukk_unmap_mem()
197 * can fail silently. */
198 DEBUG_ASSERT( _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list) );
200 _MALI_OSK_LIST_FOREACHENTRY(item, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list)
202 _mali_osk_list_del(&item->list);
203 DBG_MSG(2, ("Releasing UMP memory %u as part of file close\n", item->mem->secure_id));
204 ump_dd_reference_release(item->mem);
205 _mali_osk_free(item);
208 ump_descriptor_mapping_destroy( session_data->cookies_map );
210 _mali_osk_lock_term(session_data->lock);
211 _mali_osk_free(session_data);
213 DBG_MSG(2, ("Session closed\n"));
215 return _MALI_OSK_ERR_OK;
218 _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args )
220 struct ump_session_data * session_data;
221 ump_memory_allocation * descriptor; /* Describes current mapping of memory */
222 _mali_osk_errcode_t err;
223 unsigned long offset = 0;
225 ump_dd_handle handle; /* The real UMP handle for this memory. Its real datatype is ump_dd_mem* */
226 ump_dd_mem * mem; /* The real UMP memory. It is equal to the handle, but with exposed struct */
230 session_data = (ump_session_data *)args->ctx;
231 if( NULL == session_data )
233 MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
234 return _MALI_OSK_ERR_INVALID_ARGS;
237 /* SEC kernel stability 2012-02-17 */
238 if (NULL == session_data->cookies_map)
240 MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n"));
241 return _MALI_OSK_ERR_INVALID_ARGS;
243 descriptor = (ump_memory_allocation*) _mali_osk_calloc( 1, sizeof(ump_memory_allocation));
244 if (NULL == descriptor)
246 MSG_ERR(("ump_ukk_map_mem: descriptor allocation failed\n"));
247 return _MALI_OSK_ERR_NOMEM;
250 handle = ump_dd_handle_create_from_secure_id(args->secure_id);
251 if ( UMP_DD_HANDLE_INVALID == handle)
253 _mali_osk_free(descriptor);
254 DBG_MSG(1, ("Trying to map unknown secure ID %u\n", args->secure_id));
255 return _MALI_OSK_ERR_FAULT;
258 mem = (ump_dd_mem*)handle;
260 if (mem->size_bytes != args->size)
262 _mali_osk_free(descriptor);
263 ump_dd_reference_release(handle);
264 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));
265 return _MALI_OSK_ERR_FAULT;
268 map_id = ump_descriptor_mapping_allocate_mapping( session_data->cookies_map, (void*) descriptor );
272 _mali_osk_free(descriptor);
273 ump_dd_reference_release(handle);
274 DBG_MSG(1, ("ump_ukk_map_mem: unable to allocate a descriptor_mapping for return cookie\n"));
276 return _MALI_OSK_ERR_NOMEM;
279 descriptor->size = args->size;
280 descriptor->handle = handle;
281 descriptor->phys_addr = args->phys_addr;
282 descriptor->process_mapping_info = args->_ukk_private;
283 descriptor->ump_session = session_data;
284 descriptor->cookie = (u32)map_id;
286 if ( mem->is_cached )
288 descriptor->is_cached = 1;
290 DBG_MSG(3, ("Mapping UMP secure_id: %d as cached.\n", args->secure_id));
292 else if ( args->is_cached) /* MALI_SEC */
295 descriptor->is_cached = 1;
296 DBG_MSG(3, ("Warning mapping UMP secure_id: %d. As cached, while it was allocated uncached.\n", args->secure_id));
300 descriptor->is_cached = 0;
302 DBG_MSG(3, ("Mapping UMP secure_id: %d as Uncached.\n", args->secure_id));
305 _mali_osk_list_init( &descriptor->list );
307 err = _ump_osk_mem_mapregion_init( descriptor );
308 if( _MALI_OSK_ERR_OK != err )
310 DBG_MSG(1, ("Failed to initialize memory mapping in _ump_ukk_map_mem(). ID: %u\n", args->secure_id));
311 ump_descriptor_mapping_free( session_data->cookies_map, map_id );
312 _mali_osk_free(descriptor);
313 ump_dd_reference_release(mem);
317 DBG_MSG(4, ("Mapping virtual to physical memory: ID: %u, size:%lu, first physical addr: 0x%08lx, number of regions: %lu\n",
320 ((NULL != mem->block_array) ? mem->block_array->addr : 0),
323 left = descriptor->size;
324 /* loop over all blocks and map them in */
325 for (block = 0; block < mem->nr_blocks; block++)
327 unsigned long size_to_map;
329 if (left > mem->block_array[block].size)
331 size_to_map = mem->block_array[block].size;
338 if (_MALI_OSK_ERR_OK != _ump_osk_mem_mapregion_map(descriptor, offset, (u32 *)&(mem->block_array[block].addr), size_to_map ) )
340 DBG_MSG(1, ("WARNING: _ump_ukk_map_mem failed to map memory into userspace\n"));
341 ump_descriptor_mapping_free( session_data->cookies_map, map_id );
342 ump_dd_reference_release(mem);
343 _ump_osk_mem_mapregion_term( descriptor );
344 _mali_osk_free(descriptor);
345 return _MALI_OSK_ERR_FAULT;
348 offset += size_to_map;
351 /* Add to the ump_memory_allocation tracking list */
352 _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
353 _mali_osk_list_add( &descriptor->list, &session_data->list_head_session_memory_mappings_list );
354 _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
356 args->mapping = descriptor->mapping;
357 args->cookie = descriptor->cookie;
359 return _MALI_OSK_ERR_OK;
362 void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args )
364 struct ump_session_data * session_data;
365 ump_memory_allocation * descriptor;
366 ump_dd_handle handle;
368 session_data = (ump_session_data *)args->ctx;
370 if( NULL == session_data )
372 MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
376 /* SEC kernel stability 2012-02-17 */
377 if (NULL == session_data->cookies_map)
379 MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n"));
382 if (0 != ump_descriptor_mapping_get( session_data->cookies_map, (int)args->cookie, (void**)&descriptor) )
384 MSG_ERR(("_ump_ukk_map_mem: cookie 0x%X not found for this session\n", args->cookie ));
388 DEBUG_ASSERT_POINTER(descriptor);
390 handle = descriptor->handle;
391 if ( UMP_DD_HANDLE_INVALID == handle)
393 DBG_MSG(1, ("WARNING: Trying to unmap unknown handle: UNKNOWN\n"));
397 /* Remove the ump_memory_allocation from the list of tracked mappings */
398 _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
399 _mali_osk_list_del( &descriptor->list );
400 _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
402 ump_descriptor_mapping_free( session_data->cookies_map, (int)args->cookie );
404 ump_dd_reference_release(handle);
406 _ump_osk_mem_mapregion_term( descriptor );
407 _mali_osk_free(descriptor);
410 u32 _ump_ukk_report_memory_usage( void )
412 if(device.backend->stat)
413 return device.backend->stat(device.backend);