2 * Copyright (C) 2010 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.
12 #include "mali_osk_list.h"
14 #include "ump_uk_types.h"
15 #include "ump_kernel_interface.h"
16 #include "ump_kernel_common.h"
18 #include <asm/cacheflush.h>
22 /* ---------------- UMP kernel space API functions follows ---------------- */
26 UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(ump_dd_handle memh)
28 ump_dd_mem * mem = (ump_dd_mem *)memh;
30 DEBUG_ASSERT_POINTER(mem);
32 DBG_MSG(5, ("Returning secure ID. ID: %u\n", mem->secure_id));
34 return mem->secure_id;
39 UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id)
43 _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
45 DBG_MSG(5, ("Getting handle from secure ID. ID: %u\n", secure_id));
46 if (0 != ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem))
48 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
49 DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id));
50 return UMP_DD_HANDLE_INVALID;
53 ump_dd_reference_add(mem);
55 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
57 return (ump_dd_handle)mem;
60 UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id)
64 _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
66 DBG_MSG(5, ("Getting handle from secure ID. ID: %u\n", secure_id));
67 if (0 != ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem))
69 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
70 DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id));
71 return UMP_DD_HANDLE_INVALID;
74 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
76 return (ump_dd_handle)mem;
79 UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle memh)
81 ump_dd_mem * mem = (ump_dd_mem*) memh;
83 DEBUG_ASSERT_POINTER(mem);
85 return mem->nr_blocks;
90 UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle memh, ump_dd_physical_block * blocks, unsigned long num_blocks)
92 ump_dd_mem * mem = (ump_dd_mem *)memh;
94 DEBUG_ASSERT_POINTER(mem);
98 DBG_MSG(1, ("NULL parameter in ump_dd_phys_blocks_get()\n"));
99 return UMP_DD_INVALID;
102 if (mem->nr_blocks != num_blocks)
104 DBG_MSG(1, ("Specified number of blocks do not match actual number of blocks\n"));
105 return UMP_DD_INVALID;
108 DBG_MSG(5, ("Returning physical block information. ID: %u\n", mem->secure_id));
110 _mali_osk_memcpy(blocks, mem->block_array, sizeof(ump_dd_physical_block) * mem->nr_blocks);
112 return UMP_DD_SUCCESS;
117 UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle memh, unsigned long index, ump_dd_physical_block * block)
119 ump_dd_mem * mem = (ump_dd_mem *)memh;
121 DEBUG_ASSERT_POINTER(mem);
125 DBG_MSG(1, ("NULL parameter in ump_dd_phys_block_get()\n"));
126 return UMP_DD_INVALID;
129 if (index >= mem->nr_blocks)
131 DBG_MSG(5, ("Invalid index specified in ump_dd_phys_block_get()\n"));
132 return UMP_DD_INVALID;
135 DBG_MSG(5, ("Returning physical block information. ID: %u, index: %lu\n", mem->secure_id, index));
137 *block = mem->block_array[index];
139 return UMP_DD_SUCCESS;
144 UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle memh)
146 ump_dd_mem * mem = (ump_dd_mem*)memh;
148 DEBUG_ASSERT_POINTER(mem);
150 DBG_MSG(5, ("Returning size. ID: %u, size: %lu\n", mem->secure_id, mem->size_bytes));
152 return mem->size_bytes;
157 UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle memh)
159 ump_dd_mem * mem = (ump_dd_mem*)memh;
162 DEBUG_ASSERT_POINTER(mem);
164 new_ref = _ump_osk_atomic_inc_and_read(&mem->ref_count);
166 DBG_MSG(4, ("Memory reference incremented. ID: %u, new value: %d\n", mem->secure_id, new_ref));
171 UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle memh)
174 ump_dd_mem * mem = (ump_dd_mem*)memh;
176 DEBUG_ASSERT_POINTER(mem);
178 /* We must hold this mutex while doing the atomic_dec_and_read, to protect
179 that elements in the ump_descriptor_mapping table is always valid. If they
180 are not, userspace may accidently map in this secure_ids right before its freed
181 giving a mapped backdoor into unallocated memory.*/
182 _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
184 new_ref = _ump_osk_atomic_dec_and_read(&mem->ref_count);
186 DBG_MSG(4, ("Memory reference decremented. ID: %u, new value: %d\n", mem->secure_id, new_ref));
190 DBG_MSG(3, ("Final release of memory. ID: %u\n", mem->secure_id));
192 ump_descriptor_mapping_free(device.secure_id_map, (int)mem->secure_id);
194 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
195 mem->release_func(mem->ctx, mem);
200 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
206 /* --------------- Handling of user space requests follows --------------- */
209 _mali_osk_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args )
211 ump_session_data * session_data;
213 DEBUG_ASSERT_POINTER( args );
214 DEBUG_ASSERT_POINTER( args->ctx );
216 session_data = (ump_session_data *)args->ctx;
218 /* check compatability */
219 if (args->version == UMP_IOCTL_API_VERSION)
221 DBG_MSG(3, ("API version set to newest %d (compatible)\n", GET_VERSION(args->version)));
222 args->compatible = 1;
223 session_data->api_version = args->version;
225 else if (args->version == MAKE_VERSION_ID(1))
227 DBG_MSG(2, ("API version set to depricated: %d (compatible)\n", GET_VERSION(args->version)));
228 args->compatible = 1;
229 session_data->api_version = args->version;
233 DBG_MSG(2, ("API version set to %d (incompatible with client version %d)\n", GET_VERSION(UMP_IOCTL_API_VERSION), GET_VERSION(args->version)));
234 args->compatible = 0;
235 args->version = UMP_IOCTL_API_VERSION; /* report our version */
238 return _MALI_OSK_ERR_OK;
242 _mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info )
244 ump_session_memory_list_element * session_memory_element;
245 ump_session_memory_list_element * tmp;
246 ump_session_data * session_data;
247 _mali_osk_errcode_t ret = _MALI_OSK_ERR_INVALID_FUNC;
250 DEBUG_ASSERT_POINTER( release_info );
251 DEBUG_ASSERT_POINTER( release_info->ctx );
253 /* Retreive the session data */
254 session_data = (ump_session_data*)release_info->ctx;
256 /* If there are many items in the memory session list we
257 * could be de-referencing this pointer a lot so keep a local copy
259 secure_id = release_info->secure_id;
261 DBG_MSG(4, ("Releasing memory with IOCTL, ID: %u\n", secure_id));
263 /* Iterate through the memory list looking for the requested secure ID */
264 _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
265 _MALI_OSK_LIST_FOREACHENTRY(session_memory_element, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list)
267 if ( session_memory_element->mem->secure_id == secure_id)
269 ump_dd_mem *release_mem;
271 release_mem = session_memory_element->mem;
272 _mali_osk_list_del(&session_memory_element->list);
273 ump_dd_reference_release(release_mem);
274 _mali_osk_free(session_memory_element);
276 ret = _MALI_OSK_ERR_OK;
281 _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
282 DBG_MSG_IF(1, _MALI_OSK_ERR_OK != ret, ("UMP memory with ID %u does not belong to this session.\n", secure_id));
284 DBG_MSG(4, ("_ump_ukk_release() returning 0x%x\n", ret));
288 _mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction )
291 _mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT;
293 DEBUG_ASSERT_POINTER( user_interaction );
295 /* We lock the mappings so things don't get removed while we are looking for the memory */
296 _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
297 if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)user_interaction->secure_id, (void**)&mem))
299 user_interaction->size = mem->size_bytes;
300 DBG_MSG(4, ("Returning size. ID: %u, size: %lu ", (ump_secure_id)user_interaction->secure_id, (unsigned long)user_interaction->size));
301 ret = _MALI_OSK_ERR_OK;
305 user_interaction->size = 0;
306 DBG_MSG(1, ("Failed to look up mapping in ump_ioctl_size_get(). ID: %u\n", (ump_secure_id)user_interaction->secure_id));
309 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
315 void _ump_ukk_msync( _ump_uk_msync_s *args )
317 ump_dd_mem * mem = NULL;
319 if (args->op == _UMP_UK_MSYNC_CLEAN_ALL_AND_INVALIDATE_ALL)
321 __cpuc_flush_kern_all();
322 smp_call_function(__cpuc_flush_kern_all, NULL, 1);
327 _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
328 ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem);
329 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
333 DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_msync(). ID: %u\n", (ump_secure_id)args->secure_id));
337 /* Returns the cache settings back to Userspace */
338 args->is_cached=mem->is_cached;
340 /* If this flag is the only one set, we should not do the actual flush, only the readout */
341 if ( _UMP_UK_MSYNC_READOUT_CACHE_ENABLED==args->op )
343 DBG_MSG(3, ("_ump_ukk_msync READOUT ID: %u Enabled: %d\n", (ump_secure_id)args->secure_id, mem->is_cached));
347 /* Nothing to do if the memory is not caches */
348 if ( 0==mem->is_cached )
350 DBG_MSG(3, ("_ump_ukk_msync IGNORING ID: %u Enabled: %d OP: %d\n", (ump_secure_id)args->secure_id, mem->is_cached, args->op));
353 DBG_MSG(3, ("_ump_ukk_msync FLUSHING ID: %u Enabled: %d OP: %d\n", (ump_secure_id)args->secure_id, mem->is_cached, args->op));
355 /* The actual cache flush - Implemented for each OS*/
356 _ump_osk_msync( mem , args->op, (u32)args->mapping, (u32)args->address, args->size);