ump_kernel_common.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
  3. *
  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.
  6. *
  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.
  9. */
  10. #include "mali_kernel_common.h"
  11. #include "mali_osk.h"
  12. #include "mali_osk_bitops.h"
  13. #include "mali_osk_list.h"
  14. #include "ump_osk.h"
  15. #include "ump_uk_types.h"
  16. #include "ump_ukk.h"
  17. #include "ump_kernel_common.h"
  18. #include "ump_kernel_descriptor_mapping.h"
  19. #include "ump_kernel_memory_backend.h"
  20. /**
  21. * Define the initial and maximum size of number of secure_ids on the system
  22. */
  23. #define UMP_SECURE_ID_TABLE_ENTRIES_INITIAL (128 )
  24. #define UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM (4096 )
  25. /**
  26. * Define the initial and maximum size of the ump_session_data::cookies_map,
  27. * which is a \ref ump_descriptor_mapping. This limits how many secure_ids
  28. * may be mapped into a particular process using _ump_ukk_map_mem().
  29. */
  30. #define UMP_COOKIES_PER_SESSION_INITIAL (UMP_SECURE_ID_TABLE_ENTRIES_INITIAL )
  31. #define UMP_COOKIES_PER_SESSION_MAXIMUM (UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM)
  32. struct ump_dev device;
  33. _mali_osk_errcode_t ump_kernel_constructor(void)
  34. {
  35. _mali_osk_errcode_t err;
  36. /* Perform OS Specific initialization */
  37. err = _ump_osk_init();
  38. if( _MALI_OSK_ERR_OK != err )
  39. {
  40. MSG_ERR(("Failed to initiaze the UMP Device Driver"));
  41. return err;
  42. }
  43. /* Init the global device */
  44. _mali_osk_memset(&device, 0, sizeof(device) );
  45. /* Create the descriptor map, which will be used for mapping secure ID to ump_dd_mem structs */
  46. device.secure_id_map_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0 , 0);
  47. if (NULL == device.secure_id_map_lock)
  48. {
  49. MSG_ERR(("Failed to create OSK lock for secure id lookup table\n"));
  50. return _MALI_OSK_ERR_NOMEM;
  51. }
  52. device.secure_id_map = ump_descriptor_mapping_create(UMP_SECURE_ID_TABLE_ENTRIES_INITIAL, UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM);
  53. if (NULL == device.secure_id_map)
  54. {
  55. _mali_osk_lock_term(device.secure_id_map_lock);
  56. MSG_ERR(("Failed to create secure id lookup table\n"));
  57. return _MALI_OSK_ERR_NOMEM;
  58. }
  59. /* Init memory backend */
  60. device.backend = ump_memory_backend_create();
  61. if (NULL == device.backend)
  62. {
  63. MSG_ERR(("Failed to create memory backend\n"));
  64. _mali_osk_lock_term(device.secure_id_map_lock);
  65. ump_descriptor_mapping_destroy(device.secure_id_map);
  66. return _MALI_OSK_ERR_NOMEM;
  67. }
  68. return _MALI_OSK_ERR_OK;
  69. }
  70. void ump_kernel_destructor(void)
  71. {
  72. DEBUG_ASSERT_POINTER(device.secure_id_map);
  73. DEBUG_ASSERT_POINTER(device.secure_id_map_lock);
  74. _mali_osk_lock_term(device.secure_id_map_lock);
  75. device.secure_id_map_lock = NULL;
  76. ump_descriptor_mapping_destroy(device.secure_id_map);
  77. device.secure_id_map = NULL;
  78. device.backend->shutdown(device.backend);
  79. device.backend = NULL;
  80. ump_memory_backend_destroy();
  81. _ump_osk_term();
  82. }
  83. /** Creates a new UMP session
  84. */
  85. _mali_osk_errcode_t _ump_ukk_open( void** context )
  86. {
  87. struct ump_session_data * session_data;
  88. /* allocated struct to track this session */
  89. session_data = (struct ump_session_data *)_mali_osk_malloc(sizeof(struct ump_session_data));
  90. if (NULL == session_data)
  91. {
  92. MSG_ERR(("Failed to allocate ump_session_data in ump_file_open()\n"));
  93. return _MALI_OSK_ERR_NOMEM;
  94. }
  95. session_data->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0);
  96. if( NULL == session_data->lock )
  97. {
  98. MSG_ERR(("Failed to initialize lock for ump_session_data in ump_file_open()\n"));
  99. _mali_osk_free(session_data);
  100. return _MALI_OSK_ERR_NOMEM;
  101. }
  102. session_data->cookies_map = ump_descriptor_mapping_create( UMP_COOKIES_PER_SESSION_INITIAL, UMP_COOKIES_PER_SESSION_MAXIMUM );
  103. if ( NULL == session_data->cookies_map )
  104. {
  105. MSG_ERR(("Failed to create descriptor mapping for _ump_ukk_map_mem cookies\n"));
  106. _mali_osk_lock_term( session_data->lock );
  107. _mali_osk_free( session_data );
  108. return _MALI_OSK_ERR_NOMEM;
  109. }
  110. _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_list);
  111. _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_mappings_list);
  112. /* Since initial version of the UMP interface did not use the API_VERSION ioctl we have to assume
  113. that it is this version, and not the "latest" one: UMP_IOCTL_API_VERSION
  114. Current and later API versions would do an additional call to this IOCTL and update this variable
  115. to the correct one.*/
  116. session_data->api_version = MAKE_VERSION_ID(1);
  117. *context = (void*)session_data;
  118. session_data->cache_operations_ongoing = 0 ;
  119. session_data->has_pending_level1_cache_flush = 0;
  120. DBG_MSG(2, ("New session opened\n"));
  121. return _MALI_OSK_ERR_OK;
  122. }
  123. _mali_osk_errcode_t _ump_ukk_close( void** context )
  124. {
  125. struct ump_session_data * session_data;
  126. ump_session_memory_list_element * item;
  127. ump_session_memory_list_element * tmp;
  128. session_data = (struct ump_session_data *)*context;
  129. if (NULL == session_data)
  130. {
  131. MSG_ERR(("Session data is NULL in _ump_ukk_close()\n"));
  132. return _MALI_OSK_ERR_INVALID_ARGS;
  133. }
  134. /* Unmap any descriptors mapped in. */
  135. if (0 == _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list))
  136. {
  137. ump_memory_allocation *descriptor;
  138. ump_memory_allocation *temp;
  139. DBG_MSG(1, ("Memory mappings found on session usage list during session termination\n"));
  140. /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */
  141. _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->list_head_session_memory_mappings_list, ump_memory_allocation, list)
  142. {
  143. _ump_uk_unmap_mem_s unmap_args;
  144. DBG_MSG(4, ("Freeing block with phys address 0x%x size 0x%x mapped in user space at 0x%x\n",
  145. descriptor->phys_addr, descriptor->size, descriptor->mapping));
  146. unmap_args.ctx = (void*)session_data;
  147. unmap_args.mapping = descriptor->mapping;
  148. unmap_args.size = descriptor->size;
  149. unmap_args._ukk_private = NULL; /* NOTE: unused */
  150. unmap_args.cookie = descriptor->cookie;
  151. /* NOTE: This modifies the list_head_session_memory_mappings_list */
  152. _ump_ukk_unmap_mem( &unmap_args );
  153. }
  154. }
  155. /* ASSERT that we really did free everything, because _ump_ukk_unmap_mem()
  156. * can fail silently. */
  157. DEBUG_ASSERT( _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list) );
  158. _MALI_OSK_LIST_FOREACHENTRY(item, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list)
  159. {
  160. _mali_osk_list_del(&item->list);
  161. DBG_MSG(2, ("Releasing UMP memory %u as part of file close\n", item->mem->secure_id));
  162. ump_dd_reference_release(item->mem);
  163. _mali_osk_free(item);
  164. }
  165. ump_descriptor_mapping_destroy( session_data->cookies_map );
  166. _mali_osk_lock_term(session_data->lock);
  167. _mali_osk_free(session_data);
  168. DBG_MSG(2, ("Session closed\n"));
  169. return _MALI_OSK_ERR_OK;
  170. }
  171. _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args )
  172. {
  173. struct ump_session_data * session_data;
  174. ump_memory_allocation * descriptor; /* Describes current mapping of memory */
  175. _mali_osk_errcode_t err;
  176. unsigned long offset = 0;
  177. unsigned long left;
  178. ump_dd_handle handle; /* The real UMP handle for this memory. Its real datatype is ump_dd_mem* */
  179. ump_dd_mem * mem; /* The real UMP memory. It is equal to the handle, but with exposed struct */
  180. u32 block;
  181. int map_id;
  182. session_data = (ump_session_data *)args->ctx;
  183. if( NULL == session_data )
  184. {
  185. MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
  186. return _MALI_OSK_ERR_INVALID_ARGS;
  187. }
  188. descriptor = (ump_memory_allocation*) _mali_osk_calloc( 1, sizeof(ump_memory_allocation));
  189. if (NULL == descriptor)
  190. {
  191. MSG_ERR(("ump_ukk_map_mem: descriptor allocation failed\n"));
  192. return _MALI_OSK_ERR_NOMEM;
  193. }
  194. handle = ump_dd_handle_create_from_secure_id(args->secure_id);
  195. if ( UMP_DD_HANDLE_INVALID == handle)
  196. {
  197. _mali_osk_free(descriptor);
  198. DBG_MSG(1, ("Trying to map unknown secure ID %u\n", args->secure_id));
  199. return _MALI_OSK_ERR_FAULT;
  200. }
  201. mem = (ump_dd_mem*)handle;
  202. DEBUG_ASSERT(mem);
  203. if (mem->size_bytes != args->size)
  204. {
  205. _mali_osk_free(descriptor);
  206. ump_dd_reference_release(handle);
  207. 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));
  208. return _MALI_OSK_ERR_FAULT;
  209. }
  210. map_id = ump_descriptor_mapping_allocate_mapping( session_data->cookies_map, (void*) descriptor );
  211. if (map_id < 0)
  212. {
  213. _mali_osk_free(descriptor);
  214. ump_dd_reference_release(handle);
  215. DBG_MSG(1, ("ump_ukk_map_mem: unable to allocate a descriptor_mapping for return cookie\n"));
  216. return _MALI_OSK_ERR_NOMEM;
  217. }
  218. descriptor->size = args->size;
  219. descriptor->handle = handle;
  220. descriptor->phys_addr = args->phys_addr;
  221. descriptor->process_mapping_info = args->_ukk_private;
  222. descriptor->ump_session = session_data;
  223. descriptor->cookie = (u32)map_id;
  224. if ( mem->is_cached )
  225. {
  226. descriptor->is_cached = 1;
  227. args->is_cached = 1;
  228. DBG_MSG(3, ("Mapping UMP secure_id: %d as cached.\n", args->secure_id));
  229. }
  230. else
  231. {
  232. descriptor->is_cached = 0;
  233. args->is_cached = 0;
  234. DBG_MSG(3, ("Mapping UMP secure_id: %d as Uncached.\n", args->secure_id));
  235. }
  236. _mali_osk_list_init( &descriptor->list );
  237. err = _ump_osk_mem_mapregion_init( descriptor );
  238. if( _MALI_OSK_ERR_OK != err )
  239. {
  240. DBG_MSG(1, ("Failed to initialize memory mapping in _ump_ukk_map_mem(). ID: %u\n", args->secure_id));
  241. ump_descriptor_mapping_free( session_data->cookies_map, map_id );
  242. _mali_osk_free(descriptor);
  243. ump_dd_reference_release(mem);
  244. return err;
  245. }
  246. DBG_MSG(4, ("Mapping virtual to physical memory: ID: %u, size:%lu, first physical addr: 0x%08lx, number of regions: %lu\n",
  247. mem->secure_id,
  248. mem->size_bytes,
  249. ((NULL != mem->block_array) ? mem->block_array->addr : 0),
  250. mem->nr_blocks));
  251. left = descriptor->size;
  252. /* loop over all blocks and map them in */
  253. for (block = 0; block < mem->nr_blocks; block++)
  254. {
  255. unsigned long size_to_map;
  256. if (left > mem->block_array[block].size)
  257. {
  258. size_to_map = mem->block_array[block].size;
  259. }
  260. else
  261. {
  262. size_to_map = left;
  263. }
  264. if (_MALI_OSK_ERR_OK != _ump_osk_mem_mapregion_map(descriptor, offset, (u32 *)&(mem->block_array[block].addr), size_to_map ) )
  265. {
  266. DBG_MSG(1, ("WARNING: _ump_ukk_map_mem failed to map memory into userspace\n"));
  267. ump_descriptor_mapping_free( session_data->cookies_map, map_id );
  268. ump_dd_reference_release(mem);
  269. _ump_osk_mem_mapregion_term( descriptor );
  270. _mali_osk_free(descriptor);
  271. return _MALI_OSK_ERR_FAULT;
  272. }
  273. left -= size_to_map;
  274. offset += size_to_map;
  275. }
  276. /* Add to the ump_memory_allocation tracking list */
  277. _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
  278. _mali_osk_list_add( &descriptor->list, &session_data->list_head_session_memory_mappings_list );
  279. _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
  280. args->mapping = descriptor->mapping;
  281. args->cookie = descriptor->cookie;
  282. return _MALI_OSK_ERR_OK;
  283. }
  284. void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args )
  285. {
  286. struct ump_session_data * session_data;
  287. ump_memory_allocation * descriptor;
  288. ump_dd_handle handle;
  289. session_data = (ump_session_data *)args->ctx;
  290. if( NULL == session_data )
  291. {
  292. MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
  293. return;
  294. }
  295. if (0 != ump_descriptor_mapping_get( session_data->cookies_map, (int)args->cookie, (void**)&descriptor) )
  296. {
  297. MSG_ERR(("_ump_ukk_map_mem: cookie 0x%X not found for this session\n", args->cookie ));
  298. return;
  299. }
  300. DEBUG_ASSERT_POINTER(descriptor);
  301. handle = descriptor->handle;
  302. if ( UMP_DD_HANDLE_INVALID == handle)
  303. {
  304. DBG_MSG(1, ("WARNING: Trying to unmap unknown handle: UNKNOWN\n"));
  305. return;
  306. }
  307. /* Remove the ump_memory_allocation from the list of tracked mappings */
  308. _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
  309. _mali_osk_list_del( &descriptor->list );
  310. _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
  311. ump_descriptor_mapping_free( session_data->cookies_map, (int)args->cookie );
  312. ump_dd_reference_release(handle);
  313. _ump_osk_mem_mapregion_term( descriptor );
  314. _mali_osk_free(descriptor);
  315. }
  316. u32 _ump_ukk_report_memory_usage( void )
  317. {
  318. if(device.backend->stat)
  319. return device.backend->stat(device.backend);
  320. else
  321. return 0;
  322. }