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"
12 #include "mali_kernel_descriptor_mapping.h"
13 #include "mali_mem_validation.h"
14 #include "mali_memory.h"
15 #include "mali_mmu_page_directory.h"
16 #include "mali_kernel_memory_engine.h"
17 #include "mali_block_allocator.h"
18 #include "mali_kernel_mem_os.h"
19 #include "mali_session.h"
20 #include "mali_l2_cache.h"
21 #include "mali_scheduler.h"
22 #if defined(CONFIG_MALI400_UMP)
23 #include "ump_kernel_interface.h"
26 /* kernel side OS functions and user-kernel interface */
28 #include "mali_osk_mali.h"
30 #include "mali_osk_list.h"
31 #include "mali_osk_bitops.h"
34 * Per-session memory descriptor mapping table sizes
36 #define MALI_MEM_DESCRIPTORS_INIT 64
37 #define MALI_MEM_DESCRIPTORS_MAX 65536
39 typedef struct dedicated_memory_info
43 struct dedicated_memory_info * next;
44 } dedicated_memory_info;
46 /* types used for external_memory and ump_memory physical memory allocators, which are using the mali_allocation_engine */
47 #if defined(CONFIG_MALI400_UMP)
48 typedef struct ump_mem_allocation
50 mali_allocation_engine * engine;
51 mali_memory_allocation * descriptor;
54 ump_dd_handle ump_mem;
55 } ump_mem_allocation ;
58 typedef struct external_mem_allocation
60 mali_allocation_engine * engine;
61 mali_memory_allocation * descriptor;
64 } external_mem_allocation;
67 * @brief Internal function for unmapping memory
69 * Worker function for unmapping memory from a user-process. We assume that the
70 * session/descriptor's lock was obtained before entry. For example, the
71 * wrapper _mali_ukk_mem_munmap() will lock the descriptor, then call this
72 * function to do the actual unmapping. mali_memory_core_session_end() could
73 * also call this directly (depending on compilation options), having locked
76 * This function will fail if it is unable to put the MMU in stall mode (which
77 * might be the case if a page fault is also being processed).
79 * @param args see _mali_uk_mem_munmap_s in "mali_utgard_uk_types.h"
80 * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
82 static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args );
84 #if defined(CONFIG_MALI400_UMP)
85 static void ump_memory_release(void * ctx, void * handle);
86 static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info);
87 #endif /* CONFIG_MALI400_UMP */
90 static void external_memory_release(void * ctx, void * handle);
91 static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info);
96 /* mali address manager needs to allocate page tables on allocate, write to page table(s) on map, write to page table(s) and release page tables on release */
97 static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor); /* validates the range, allocates memory for the page tables if needed */
98 static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size);
99 static void mali_address_manager_release(mali_memory_allocation * descriptor);
103 typedef struct mali_mmu_page_table_allocation
105 _mali_osk_list_t list;
109 mali_page_table_block pages;
110 } mali_mmu_page_table_allocation;
112 typedef struct mali_mmu_page_table_allocations
114 _mali_osk_lock_t *lock;
115 _mali_osk_list_t partial;
116 _mali_osk_list_t full;
117 /* we never hold on to a empty allocation */
118 } mali_mmu_page_table_allocations;
120 static mali_kernel_mem_address_manager mali_address_manager =
122 mali_address_manager_allocate, /* allocate */
123 mali_address_manager_release, /* release */
124 mali_address_manager_map, /* map_physical */
125 NULL /* unmap_physical not present*/
128 /* the mmu page table cache */
129 static struct mali_mmu_page_table_allocations page_table_cache;
132 static mali_kernel_mem_address_manager process_address_manager =
134 _mali_osk_mem_mapregion_init, /* allocate */
135 _mali_osk_mem_mapregion_term, /* release */
136 _mali_osk_mem_mapregion_map, /* map_physical */
137 _mali_osk_mem_mapregion_unmap /* unmap_physical */
140 static _mali_osk_errcode_t mali_mmu_page_table_cache_create(void);
141 static void mali_mmu_page_table_cache_destroy(void);
143 static mali_allocation_engine memory_engine = NULL;
144 static mali_physical_memory_allocator * physical_memory_allocators = NULL;
146 static dedicated_memory_info * mem_region_registrations = NULL;
148 mali_allocation_engine mali_mem_get_memory_engine(void)
150 return memory_engine;
153 /* called during module init */
154 _mali_osk_errcode_t mali_memory_initialize(void)
156 _mali_osk_errcode_t err;
158 MALI_DEBUG_PRINT(2, ("Memory system initializing\n"));
160 err = mali_mmu_page_table_cache_create();
161 if(_MALI_OSK_ERR_OK != err)
166 memory_engine = mali_allocation_engine_create(&mali_address_manager, &process_address_manager);
167 MALI_CHECK_NON_NULL( memory_engine, _MALI_OSK_ERR_FAULT);
172 /* called if/when our module is unloaded */
173 void mali_memory_terminate(void)
175 MALI_DEBUG_PRINT(2, ("Memory system terminating\n"));
177 mali_mmu_page_table_cache_destroy();
179 while ( NULL != mem_region_registrations)
181 dedicated_memory_info * m;
182 m = mem_region_registrations;
183 mem_region_registrations = m->next;
184 _mali_osk_mem_unreqregion(m->base, m->size);
188 while ( NULL != physical_memory_allocators)
190 mali_physical_memory_allocator * m;
191 m = physical_memory_allocators;
192 physical_memory_allocators = m->next;
196 if (NULL != memory_engine)
198 mali_allocation_engine_destroy(memory_engine);
199 memory_engine = NULL;
203 _mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data * session_data)
205 MALI_DEBUG_PRINT(5, ("Memory session begin\n"));
207 /* create descriptor mapping table */
208 session_data->descriptor_mapping = mali_descriptor_mapping_create(MALI_MEM_DESCRIPTORS_INIT, MALI_MEM_DESCRIPTORS_MAX);
210 if (NULL == session_data->descriptor_mapping)
212 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
215 session_data->memory_lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK
216 | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_MEM_SESSION);
217 if (NULL == session_data->memory_lock)
219 mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
220 _mali_osk_free(session_data);
221 MALI_ERROR(_MALI_OSK_ERR_FAULT);
224 /* Init the session's memory allocation list */
225 _MALI_OSK_INIT_LIST_HEAD( &session_data->memory_head );
227 MALI_DEBUG_PRINT(5, ("MMU session begin: success\n"));
231 static void descriptor_table_cleanup_callback(int descriptor_id, void* map_target)
233 mali_memory_allocation * descriptor;
235 descriptor = (mali_memory_allocation*)map_target;
237 MALI_DEBUG_PRINT(3, ("Cleanup of descriptor %d mapping to 0x%x in descriptor table\n", descriptor_id, map_target));
238 MALI_DEBUG_ASSERT(descriptor);
240 mali_allocation_engine_release_memory(memory_engine, descriptor);
241 _mali_osk_free(descriptor);
244 void mali_memory_session_end(struct mali_session_data *session_data)
246 _mali_osk_errcode_t err = _MALI_OSK_ERR_BUSY;
248 MALI_DEBUG_PRINT(3, ("MMU session end\n"));
250 if (NULL == session_data)
252 MALI_DEBUG_PRINT(1, ("No session data found during session end\n"));
256 while (err == _MALI_OSK_ERR_BUSY)
258 /* Lock the session so we can modify the memory list */
259 _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
260 err = _MALI_OSK_ERR_OK;
262 /* Free all memory engine allocations */
263 if (!_mali_osk_list_empty(&session_data->memory_head))
265 mali_memory_allocation *descriptor;
266 mali_memory_allocation *temp;
267 _mali_uk_mem_munmap_s unmap_args;
269 MALI_DEBUG_PRINT(1, ("Memory found on session usage list during session termination\n"));
271 unmap_args.ctx = session_data;
273 /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */
274 _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->memory_head, mali_memory_allocation, list)
276 MALI_DEBUG_PRINT(4, ("Freeing block with mali address 0x%x size %d mapped in user space at 0x%x\n",
277 descriptor->mali_address, descriptor->size, descriptor->size, descriptor->mapping)
279 /* ASSERT that the descriptor's lock references the correct thing */
280 MALI_DEBUG_ASSERT( descriptor->lock == session_data->memory_lock );
281 /* Therefore, we have already locked the descriptor */
283 unmap_args.size = descriptor->size;
284 unmap_args.mapping = descriptor->mapping;
285 unmap_args.cookie = (u32)descriptor;
288 * This removes the descriptor from the list, and frees the descriptor
290 * Does not handle the _MALI_OSK_SPECIFIC_INDIRECT_MMAP case, since
291 * the only OS we are aware of that requires indirect MMAP also has
292 * implicit mmap cleanup.
294 err = _mali_ukk_mem_munmap_internal( &unmap_args );
296 if (err == _MALI_OSK_ERR_BUSY)
298 _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
301 * We where unable to stall the MMU, probably because we are in page fault handling.
302 * Sleep for a while with the session lock released, then try again.
303 * Abnormal termination of programs with running Mali jobs is a normal reason for this.
305 _mali_osk_time_ubusydelay(10);
306 break; /* Will jump back into: "while (err == _MALI_OSK_ERR_BUSY)" */
311 /* Assert that we really did free everything */
312 MALI_DEBUG_ASSERT( _mali_osk_list_empty(&session_data->memory_head) );
314 if (NULL != session_data->descriptor_mapping)
316 mali_descriptor_mapping_call_for_each(session_data->descriptor_mapping, descriptor_table_cleanup_callback);
317 mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
318 session_data->descriptor_mapping = NULL;
321 _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
324 * @note Could the VMA close handler mean that we use the session data after it was freed?
325 * In which case, would need to refcount the session data, and free on VMA close
329 _mali_osk_lock_term( session_data->memory_lock );
334 _mali_osk_errcode_t mali_memory_core_resource_os_memory(u32 size)
336 mali_physical_memory_allocator * allocator;
337 mali_physical_memory_allocator ** next_allocator_list;
339 u32 alloc_order = 1; /* OS memory has second priority */
341 allocator = mali_os_allocator_create(size, 0 /* cpu_usage_adjust */, "Shared Mali GPU memory");
342 if (NULL == allocator)
344 MALI_DEBUG_PRINT(1, ("Failed to create OS memory allocator\n"));
345 MALI_ERROR(_MALI_OSK_ERR_FAULT);
348 allocator->alloc_order = alloc_order;
350 /* link in the allocator: insertion into ordered list
351 * resources of the same alloc_order will be Last-in-first */
352 next_allocator_list = &physical_memory_allocators;
354 while (NULL != *next_allocator_list &&
355 (*next_allocator_list)->alloc_order < alloc_order )
357 next_allocator_list = &((*next_allocator_list)->next);
360 allocator->next = (*next_allocator_list);
361 (*next_allocator_list) = allocator;
366 _mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size)
368 mali_physical_memory_allocator * allocator;
369 mali_physical_memory_allocator ** next_allocator_list;
370 dedicated_memory_info * cleanup_data;
372 u32 alloc_order = 0; /* Dedicated range has first priority */
374 /* do the low level linux operation first */
376 /* Request ownership of the memory */
377 if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(start, size, "Dedicated Mali GPU memory"))
379 MALI_DEBUG_PRINT(1, ("Failed to request memory region for frame buffer (0x%08X - 0x%08X)\n", start, start + size - 1));
380 MALI_ERROR(_MALI_OSK_ERR_FAULT);
383 /* create generic block allocator object to handle it */
384 allocator = mali_block_allocator_create(start, 0 /* cpu_usage_adjust */, size, "Dedicated Mali GPU memory");
386 if (NULL == allocator)
388 MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n"));
389 _mali_osk_mem_unreqregion(start, size);
390 MALI_ERROR(_MALI_OSK_ERR_FAULT);
393 /* save low level cleanup info */
394 allocator->alloc_order = alloc_order;
396 cleanup_data = _mali_osk_malloc(sizeof(dedicated_memory_info));
398 if (NULL == cleanup_data)
400 _mali_osk_mem_unreqregion(start, size);
401 allocator->destroy(allocator);
402 MALI_ERROR(_MALI_OSK_ERR_FAULT);
405 cleanup_data->base = start;
406 cleanup_data->size = size;
408 cleanup_data->next = mem_region_registrations;
409 mem_region_registrations = cleanup_data;
411 /* link in the allocator: insertion into ordered list
412 * resources of the same alloc_order will be Last-in-first */
413 next_allocator_list = &physical_memory_allocators;
415 while ( NULL != *next_allocator_list &&
416 (*next_allocator_list)->alloc_order < alloc_order )
418 next_allocator_list = &((*next_allocator_list)->next);
421 allocator->next = (*next_allocator_list);
422 (*next_allocator_list) = allocator;
427 #if defined(CONFIG_MALI400_UMP)
428 static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info)
430 ump_dd_handle ump_mem;
433 ump_dd_physical_block * ump_blocks;
434 ump_mem_allocation *ret_allocation;
436 MALI_DEBUG_ASSERT_POINTER(ctx);
437 MALI_DEBUG_ASSERT_POINTER(engine);
438 MALI_DEBUG_ASSERT_POINTER(descriptor);
439 MALI_DEBUG_ASSERT_POINTER(alloc_info);
441 ret_allocation = _mali_osk_malloc( sizeof( ump_mem_allocation ) );
442 if ( NULL==ret_allocation ) return MALI_MEM_ALLOC_INTERNAL_FAILURE;
444 ump_mem = (ump_dd_handle)ctx;
446 MALI_DEBUG_PRINT(4, ("In ump_memory_commit\n"));
448 nr_blocks = ump_dd_phys_block_count_get(ump_mem);
450 MALI_DEBUG_PRINT(4, ("Have %d blocks\n", nr_blocks));
454 MALI_DEBUG_PRINT(1, ("No block count\n"));
455 _mali_osk_free( ret_allocation );
456 return MALI_MEM_ALLOC_INTERNAL_FAILURE;
459 ump_blocks = _mali_osk_malloc(sizeof(*ump_blocks)*nr_blocks );
460 if ( NULL==ump_blocks )
462 _mali_osk_free( ret_allocation );
463 return MALI_MEM_ALLOC_INTERNAL_FAILURE;
466 if (UMP_DD_INVALID == ump_dd_phys_blocks_get(ump_mem, ump_blocks, nr_blocks))
468 _mali_osk_free(ump_blocks);
469 _mali_osk_free( ret_allocation );
470 return MALI_MEM_ALLOC_INTERNAL_FAILURE;
473 /* Store away the initial offset for unmapping purposes */
474 ret_allocation->initial_offset = *offset;
476 for(i=0; i<nr_blocks; ++i)
478 MALI_DEBUG_PRINT(4, ("Mapping in 0x%08x size %d\n", ump_blocks[i].addr , ump_blocks[i].size));
479 if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, ump_blocks[i].addr , 0, ump_blocks[i].size ))
481 u32 size_allocated = *offset - ret_allocation->initial_offset;
482 MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n"));
484 /* unmap all previous blocks (if any) */
485 mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
487 _mali_osk_free(ump_blocks);
488 _mali_osk_free(ret_allocation);
489 return MALI_MEM_ALLOC_INTERNAL_FAILURE;
491 *offset += ump_blocks[i].size;
494 if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
496 /* Map in an extra virtual guard page at the end of the VMA */
497 MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n"));
498 if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, ump_blocks[0].addr , 0, _MALI_OSK_MALI_PAGE_SIZE ))
500 u32 size_allocated = *offset - ret_allocation->initial_offset;
501 MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n"));
503 /* unmap all previous blocks (if any) */
504 mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
506 _mali_osk_free(ump_blocks);
507 _mali_osk_free(ret_allocation);
508 return MALI_MEM_ALLOC_INTERNAL_FAILURE;
510 *offset += _MALI_OSK_MALI_PAGE_SIZE;
513 _mali_osk_free( ump_blocks );
515 ret_allocation->engine = engine;
516 ret_allocation->descriptor = descriptor;
517 ret_allocation->ump_mem = ump_mem;
518 ret_allocation->size_allocated = *offset - ret_allocation->initial_offset;
520 alloc_info->ctx = NULL;
521 alloc_info->handle = ret_allocation;
522 alloc_info->next = NULL;
523 alloc_info->release = ump_memory_release;
525 return MALI_MEM_ALLOC_FINISHED;
528 static void ump_memory_release(void * ctx, void * handle)
530 ump_dd_handle ump_mem;
531 ump_mem_allocation *allocation;
533 allocation = (ump_mem_allocation *)handle;
535 MALI_DEBUG_ASSERT_POINTER( allocation );
537 ump_mem = allocation->ump_mem;
539 MALI_DEBUG_ASSERT(UMP_DD_HANDLE_INVALID!=ump_mem);
541 /* At present, this is a no-op. But, it allows the mali_address_manager to
542 * do unmapping of a subrange in future. */
543 mali_allocation_engine_unmap_physical( allocation->engine,
544 allocation->descriptor,
545 allocation->initial_offset,
546 allocation->size_allocated,
547 (_mali_osk_mem_mapregion_flags_t)0
549 _mali_osk_free( allocation );
552 ump_dd_reference_release(ump_mem) ;
556 _mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args )
558 ump_dd_handle ump_mem;
559 mali_physical_memory_allocator external_memory_allocator;
560 struct mali_session_data *session_data;
561 mali_memory_allocation * descriptor;
564 MALI_DEBUG_ASSERT_POINTER(args);
565 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
567 session_data = (struct mali_session_data *)args->ctx;
568 MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
570 /* check arguments */
571 /* NULL might be a valid Mali address */
572 if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
574 /* size must be a multiple of the system page size */
575 if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
578 ("Requested to map ump memory with secure id %d into virtual memory 0x%08X, size 0x%08X\n",
579 args->secure_id, args->mali_address, args->size));
581 ump_mem = ump_dd_handle_create_from_secure_id( (int)args->secure_id ) ;
583 if ( UMP_DD_HANDLE_INVALID==ump_mem ) MALI_ERROR(_MALI_OSK_ERR_FAULT);
585 descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation));
586 if (NULL == descriptor)
588 ump_dd_reference_release(ump_mem);
589 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
592 descriptor->size = args->size;
593 descriptor->mapping = NULL;
594 descriptor->mali_address = args->mali_address;
595 descriptor->mali_addr_mapping_info = (void*)session_data;
596 descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */
597 descriptor->cache_settings = (u32) MALI_CACHE_STANDARD;
598 descriptor->lock = session_data->memory_lock;
600 if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE)
602 descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE;
604 _mali_osk_list_init( &descriptor->list );
606 if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md))
608 ump_dd_reference_release(ump_mem);
609 _mali_osk_free(descriptor);
610 MALI_ERROR(_MALI_OSK_ERR_FAULT);
613 external_memory_allocator.allocate = ump_memory_commit;
614 external_memory_allocator.allocate_page_table_block = NULL;
615 external_memory_allocator.ctx = ump_mem;
616 external_memory_allocator.name = "UMP Memory";
617 external_memory_allocator.next = NULL;
619 _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
621 if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL))
623 _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
624 mali_descriptor_mapping_free(session_data->descriptor_mapping, md);
625 ump_dd_reference_release(ump_mem);
626 _mali_osk_free(descriptor);
627 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
630 _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
634 MALI_DEBUG_PRINT(5,("Returning from UMP attach\n"));
641 _mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args )
643 mali_memory_allocation * descriptor;
644 struct mali_session_data *session_data;
646 MALI_DEBUG_ASSERT_POINTER(args);
647 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
649 session_data = (struct mali_session_data *)args->ctx;
650 MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
652 if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor))
654 MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release ump memory\n", args->cookie));
655 MALI_ERROR(_MALI_OSK_ERR_FAULT);
658 descriptor = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie);
660 if (NULL != descriptor)
662 _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
664 mali_allocation_engine_release_memory(memory_engine, descriptor);
666 _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
668 _mali_osk_free(descriptor);
674 #endif /* CONFIG_MALI400_UMP */
677 static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info)
680 external_mem_allocation * ret_allocation;
682 MALI_DEBUG_ASSERT_POINTER(ctx);
683 MALI_DEBUG_ASSERT_POINTER(engine);
684 MALI_DEBUG_ASSERT_POINTER(descriptor);
685 MALI_DEBUG_ASSERT_POINTER(alloc_info);
687 ret_allocation = _mali_osk_malloc( sizeof(external_mem_allocation) );
689 if ( NULL == ret_allocation )
691 return MALI_MEM_ALLOC_INTERNAL_FAILURE;
696 ret_allocation->engine = engine;
697 ret_allocation->descriptor = descriptor;
698 ret_allocation->initial_offset = *offset;
700 alloc_info->ctx = NULL;
701 alloc_info->handle = ret_allocation;
702 alloc_info->next = NULL;
703 alloc_info->release = external_memory_release;
705 MALI_DEBUG_PRINT(5, ("External map: mapping phys 0x%08X at mali virtual address 0x%08X staring at offset 0x%08X length 0x%08X\n", data[0], descriptor->mali_address, *offset, data[1]));
707 if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, data[1]))
709 MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n"));
710 _mali_osk_free(ret_allocation);
711 return MALI_MEM_ALLOC_INTERNAL_FAILURE;
715 if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
717 /* Map in an extra virtual guard page at the end of the VMA */
718 MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n"));
719 if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, _MALI_OSK_MALI_PAGE_SIZE))
721 u32 size_allocated = *offset - ret_allocation->initial_offset;
722 MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n"));
724 /* unmap what we previously mapped */
725 mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
726 _mali_osk_free(ret_allocation);
727 return MALI_MEM_ALLOC_INTERNAL_FAILURE;
729 *offset += _MALI_OSK_MALI_PAGE_SIZE;
732 ret_allocation->size = *offset - ret_allocation->initial_offset;
734 return MALI_MEM_ALLOC_FINISHED;
737 static void external_memory_release(void * ctx, void * handle)
739 external_mem_allocation * allocation;
741 allocation = (external_mem_allocation *) handle;
742 MALI_DEBUG_ASSERT_POINTER( allocation );
744 /* At present, this is a no-op. But, it allows the mali_address_manager to
745 * do unmapping of a subrange in future. */
747 mali_allocation_engine_unmap_physical( allocation->engine,
748 allocation->descriptor,
749 allocation->initial_offset,
751 (_mali_osk_mem_mapregion_flags_t)0
754 _mali_osk_free( allocation );
759 _mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args )
761 mali_physical_memory_allocator external_memory_allocator;
762 struct mali_session_data *session_data;
764 mali_memory_allocation * descriptor;
767 MALI_DEBUG_ASSERT_POINTER(args);
768 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
770 session_data = (struct mali_session_data *)args->ctx;
771 MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
773 external_memory_allocator.allocate = external_memory_commit;
774 external_memory_allocator.allocate_page_table_block = NULL;
775 external_memory_allocator.ctx = &info[0];
776 external_memory_allocator.name = "External Memory";
777 external_memory_allocator.next = NULL;
779 /* check arguments */
780 /* NULL might be a valid Mali address */
781 if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
783 /* size must be a multiple of the system page size */
784 if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
787 ("Requested to map physical memory 0x%x-0x%x into virtual memory 0x%x\n",
788 (void*)args->phys_addr,
789 (void*)(args->phys_addr + args->size -1),
790 (void*)args->mali_address)
793 /* Validate the mali physical range */
794 if (_MALI_OSK_ERR_OK != mali_mem_validation_check(args->phys_addr, args->size))
796 return _MALI_OSK_ERR_FAULT;
799 info[0] = args->phys_addr;
800 info[1] = args->size;
802 descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation));
803 if (NULL == descriptor) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
805 descriptor->size = args->size;
806 descriptor->mapping = NULL;
807 descriptor->mali_address = args->mali_address;
808 descriptor->mali_addr_mapping_info = (void*)session_data;
809 descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */
810 descriptor->cache_settings = (u32)MALI_CACHE_STANDARD;
811 descriptor->lock = session_data->memory_lock;
812 if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE)
814 descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE;
816 _mali_osk_list_init( &descriptor->list );
818 _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
820 if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL))
822 _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
823 _mali_osk_free(descriptor);
824 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
827 _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
829 if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md))
831 mali_allocation_engine_release_memory(memory_engine, descriptor);
832 _mali_osk_free(descriptor);
833 MALI_ERROR(_MALI_OSK_ERR_FAULT);
838 MALI_DEBUG_PRINT(5,("Returning from range_map_external_memory\n"));
845 _mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args )
847 mali_memory_allocation * descriptor;
849 struct mali_session_data *session_data;
851 MALI_DEBUG_ASSERT_POINTER(args);
852 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
854 session_data = (struct mali_session_data *)args->ctx;
855 MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
857 if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor))
859 MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to unmap external memory\n", args->cookie));
860 MALI_ERROR(_MALI_OSK_ERR_FAULT);
863 old_value = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie);
865 if (NULL != old_value)
867 _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
869 mali_allocation_engine_release_memory(memory_engine, descriptor);
871 _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
873 _mali_osk_free(descriptor);
879 _mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args )
881 MALI_DEBUG_ASSERT_POINTER(args);
882 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
884 args->memory_size = 2 * 1024 * 1024 * 1024UL; /* 2GB address space */
885 args->mali_address_base = 1 * 1024 * 1024 * 1024UL; /* staring at 1GB, causing this layout: (0-1GB unused)(1GB-3G usage by Mali)(3G-4G unused) */
889 _mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args )
891 MALI_DEBUG_ASSERT_POINTER(args);
892 MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
896 static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor)
898 struct mali_session_data *session_data;
901 MALI_DEBUG_ASSERT_POINTER(descriptor);
903 session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
905 actual_size = descriptor->size;
907 if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
909 actual_size += _MALI_OSK_MALI_PAGE_SIZE;
912 return mali_mmu_pagedir_map(session_data->page_directory, descriptor->mali_address, actual_size);
915 static void mali_address_manager_release(mali_memory_allocation * descriptor)
917 const u32 illegal_mali_address = 0xffffffff;
918 struct mali_session_data *session_data;
919 MALI_DEBUG_ASSERT_POINTER(descriptor);
921 /* It is allowed to call this function several times on the same descriptor.
922 When memory is released we set the illegal_mali_address so we can early out here. */
923 if ( illegal_mali_address == descriptor->mali_address) return;
925 session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
926 mali_mmu_pagedir_unmap(session_data->page_directory, descriptor->mali_address, descriptor->size);
928 descriptor->mali_address = illegal_mali_address ;
931 static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size)
933 struct mali_session_data *session_data;
936 MALI_DEBUG_ASSERT_POINTER(descriptor);
937 MALI_DEBUG_ASSERT_POINTER(phys_addr);
939 session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
940 MALI_DEBUG_ASSERT_POINTER(session_data);
942 mali_address = descriptor->mali_address + offset;
944 MALI_DEBUG_PRINT(7, ("Mali map: mapping 0x%08X to Mali address 0x%08X length 0x%08X\n", *phys_addr, mali_address, size));
946 mali_mmu_pagedir_update(session_data->page_directory, mali_address, *phys_addr, size, descriptor->cache_settings);
951 /* This handler registered to mali_mmap for MMU builds */
952 _mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args )
954 struct mali_session_data *session_data;
955 mali_memory_allocation * descriptor;
958 if (NULL == args) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: args was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); }
960 /* Unpack arguments */
961 session_data = (struct mali_session_data *)args->ctx;
964 if (NULL == session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_FAULT); }
966 descriptor = (mali_memory_allocation*) _mali_osk_calloc( 1, sizeof(mali_memory_allocation) );
967 if (NULL == descriptor) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: descriptor was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_NOMEM); }
969 descriptor->size = args->size;
970 descriptor->mali_address = args->phys_addr;
971 descriptor->mali_addr_mapping_info = (void*)session_data;
973 descriptor->process_addr_mapping_info = args->ukk_private; /* save to be used during physical manager callback */
974 descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE;
975 descriptor->cache_settings = (u32) args->cache_settings ;
976 descriptor->lock = session_data->memory_lock;
977 _mali_osk_list_init( &descriptor->list );
979 _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
981 if (0 == mali_allocation_engine_allocate_memory(memory_engine, descriptor, physical_memory_allocators, &session_data->memory_head))
983 /* We do not FLUSH nor TLB_ZAP on MMAP, since we do both of those on job start*/
984 _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
986 args->mapping = descriptor->mapping;
987 args->cookie = (u32)descriptor;
989 MALI_DEBUG_PRINT(7, ("MMAP OK\n"));
994 _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
995 /* OOM, but not a fatal error */
996 MALI_DEBUG_PRINT(4, ("Memory allocation failure, OOM\n"));
997 _mali_osk_free(descriptor);
998 /* Linux will free the CPU address allocation, userspace client the Mali address allocation */
999 MALI_ERROR(_MALI_OSK_ERR_FAULT);
1003 static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args )
1005 struct mali_session_data *session_data;
1006 mali_memory_allocation * descriptor;
1008 descriptor = (mali_memory_allocation *)args->cookie;
1009 MALI_DEBUG_ASSERT_POINTER(descriptor);
1011 /** @note args->context unused; we use the memory_session from the cookie */
1012 /* args->mapping and args->size are also discarded. They are only necessary
1013 for certain do_munmap implementations. However, they could be used to check the
1014 descriptor at this point. */
1016 session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
1017 MALI_DEBUG_ASSERT_POINTER(session_data);
1019 /* Unmapping the memory from the mali virtual address space.
1020 It is allowed to call this function severeal times, which might happen if zapping below fails. */
1021 mali_allocation_engine_release_pt1_mali_pagetables_unmap(memory_engine, descriptor);
1023 #ifdef MALI_UNMAP_FLUSH_ALL_MALI_L2
1026 u32 number_of_l2_ccores = mali_l2_cache_core_get_glob_num_l2_cores();
1027 for (i = 0; i < number_of_l2_ccores; i++)
1029 struct mali_l2_cache_core *core;
1030 core = mali_l2_cache_core_get_glob_l2_core(i);
1031 if (mali_l2_cache_power_is_enabled_get(core) )
1033 mali_l2_cache_invalidate_all_force(core);
1039 mali_scheduler_zap_all_active(session_data);
1041 /* Removes the descriptor from the session's memory list, releases physical memory, releases descriptor */
1042 mali_allocation_engine_release_pt2_physical_memory_free(memory_engine, descriptor);
1044 _mali_osk_free(descriptor);
1046 return _MALI_OSK_ERR_OK;
1049 /* Handler for unmapping memory for MMU builds */
1050 _mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args )
1052 mali_memory_allocation * descriptor;
1053 _mali_osk_lock_t *descriptor_lock;
1054 _mali_osk_errcode_t err;
1056 descriptor = (mali_memory_allocation *)args->cookie;
1057 MALI_DEBUG_ASSERT_POINTER(descriptor);
1059 /** @note args->context unused; we use the memory_session from the cookie */
1060 /* args->mapping and args->size are also discarded. They are only necessary
1061 for certain do_munmap implementations. However, they could be used to check the
1062 descriptor at this point. */
1064 MALI_DEBUG_ASSERT_POINTER((struct mali_session_data *)descriptor->mali_addr_mapping_info);
1066 descriptor_lock = descriptor->lock; /* should point to the session data lock... */
1068 err = _MALI_OSK_ERR_BUSY;
1069 while (err == _MALI_OSK_ERR_BUSY)
1071 if (descriptor_lock)
1073 _mali_osk_lock_wait( descriptor_lock, _MALI_OSK_LOCKMODE_RW );
1076 err = _mali_ukk_mem_munmap_internal( args );
1078 if (descriptor_lock)
1080 _mali_osk_lock_signal( descriptor_lock, _MALI_OSK_LOCKMODE_RW );
1083 if (err == _MALI_OSK_ERR_BUSY)
1087 * We where unable to stall the MMU, probably because we are in page fault handling.
1088 * Sleep for a while with the session lock released, then try again.
1089 * Abnormal termination of programs with running Mali jobs is a normal reason for this.
1091 _mali_osk_time_ubusydelay(10);
1098 u32 _mali_ukk_report_memory_usage(void)
1100 return mali_allocation_engine_memory_usage(physical_memory_allocators);
1103 _mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping)
1105 _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
1107 if (!_mali_osk_list_empty(&page_table_cache.partial))
1109 mali_mmu_page_table_allocation * alloc = _MALI_OSK_LIST_ENTRY(page_table_cache.partial.next, mali_mmu_page_table_allocation, list);
1110 int page_number = _mali_osk_find_first_zero_bit(alloc->usage_map, alloc->num_pages);
1111 MALI_DEBUG_PRINT(6, ("Partial page table allocation found, using page offset %d\n", page_number));
1112 _mali_osk_set_nonatomic_bit(page_number, alloc->usage_map);
1113 alloc->usage_count++;
1114 if (alloc->num_pages == alloc->usage_count)
1116 /* full, move alloc to full list*/
1117 _mali_osk_list_move(&alloc->list, &page_table_cache.full);
1119 _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
1121 *table_page = (MALI_MMU_PAGE_SIZE * page_number) + alloc->pages.phys_base;
1122 *mapping = (mali_io_address)((MALI_MMU_PAGE_SIZE * page_number) + (u32)alloc->pages.mapping);
1123 MALI_DEBUG_PRINT(4, ("Page table allocated for VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page ));
1128 mali_mmu_page_table_allocation * alloc;
1129 /* no free pages, allocate a new one */
1131 alloc = (mali_mmu_page_table_allocation *)_mali_osk_calloc(1, sizeof(mali_mmu_page_table_allocation));
1134 _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
1135 *table_page = MALI_INVALID_PAGE;
1136 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1139 _MALI_OSK_INIT_LIST_HEAD(&alloc->list);
1141 if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_page_tables(memory_engine, &alloc->pages, physical_memory_allocators))
1143 MALI_DEBUG_PRINT(1, ("No more memory for page tables\n"));
1144 _mali_osk_free(alloc);
1145 _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
1146 *table_page = MALI_INVALID_PAGE;
1148 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1151 /* create the usage map */
1152 alloc->num_pages = alloc->pages.size / MALI_MMU_PAGE_SIZE;
1153 alloc->usage_count = 1;
1154 MALI_DEBUG_PRINT(3, ("New page table cache expansion, %d pages in new cache allocation\n", alloc->num_pages));
1155 alloc->usage_map = _mali_osk_calloc(1, ((alloc->num_pages + BITS_PER_LONG - 1) & ~(BITS_PER_LONG-1) / BITS_PER_LONG) * sizeof(unsigned long));
1156 if (NULL == alloc->usage_map)
1158 MALI_DEBUG_PRINT(1, ("Failed to allocate memory to describe MMU page table cache usage\n"));
1159 alloc->pages.release(&alloc->pages);
1160 _mali_osk_free(alloc);
1161 _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
1162 *table_page = MALI_INVALID_PAGE;
1164 MALI_ERROR(_MALI_OSK_ERR_NOMEM);
1167 _mali_osk_set_nonatomic_bit(0, alloc->usage_map);
1169 if (alloc->num_pages > 1)
1171 _mali_osk_list_add(&alloc->list, &page_table_cache.partial);
1175 _mali_osk_list_add(&alloc->list, &page_table_cache.full);
1178 _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
1179 *table_page = alloc->pages.phys_base; /* return the first page */
1180 *mapping = alloc->pages.mapping; /* Mapping for first page */
1181 MALI_DEBUG_PRINT(4, ("Page table allocated: VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page ));
1186 void mali_mmu_release_table_page(u32 pa)
1188 mali_mmu_page_table_allocation * alloc, * temp_alloc;
1190 MALI_DEBUG_PRINT_IF(1, pa & 4095, ("Bad page address 0x%x given to mali_mmu_release_table_page\n", (void*)pa));
1192 MALI_DEBUG_PRINT(4, ("Releasing table page 0x%08X to the cache\n", pa));
1194 _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
1196 /* find the entry this address belongs to */
1197 /* first check the partial list */
1198 _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.partial, mali_mmu_page_table_allocation, list)
1200 u32 start = alloc->pages.phys_base;
1201 u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE;
1202 if (pa >= start && pa <= last)
1204 MALI_DEBUG_ASSERT(0 != _mali_osk_test_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map));
1205 _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map);
1206 alloc->usage_count--;
1208 _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE);
1210 if (0 == alloc->usage_count)
1212 /* empty, release whole page alloc */
1213 _mali_osk_list_del(&alloc->list);
1214 alloc->pages.release(&alloc->pages);
1215 _mali_osk_free(alloc->usage_map);
1216 _mali_osk_free(alloc);
1218 _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
1219 MALI_DEBUG_PRINT(4, ("(partial list)Released table page 0x%08X to the cache\n", pa));
1224 /* the check the full list */
1225 _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.full, mali_mmu_page_table_allocation, list)
1227 u32 start = alloc->pages.phys_base;
1228 u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE;
1229 if (pa >= start && pa <= last)
1231 _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map);
1232 alloc->usage_count--;
1234 _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE);
1237 if (0 == alloc->usage_count)
1239 /* empty, release whole page alloc */
1240 _mali_osk_list_del(&alloc->list);
1241 alloc->pages.release(&alloc->pages);
1242 _mali_osk_free(alloc->usage_map);
1243 _mali_osk_free(alloc);
1247 /* transfer to partial list */
1248 _mali_osk_list_move(&alloc->list, &page_table_cache.partial);
1251 _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
1252 MALI_DEBUG_PRINT(4, ("(full list)Released table page 0x%08X to the cache\n", pa));
1257 MALI_DEBUG_PRINT(1, ("pa 0x%x not found in the page table cache\n", (void*)pa));
1259 _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
1262 static _mali_osk_errcode_t mali_mmu_page_table_cache_create(void)
1264 page_table_cache.lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK
1265 | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE);
1266 MALI_CHECK_NON_NULL( page_table_cache.lock, _MALI_OSK_ERR_FAULT );
1267 _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.partial);
1268 _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.full);
1272 static void mali_mmu_page_table_cache_destroy(void)
1274 mali_mmu_page_table_allocation * alloc, *temp;
1276 _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.partial, mali_mmu_page_table_allocation, list)
1278 MALI_DEBUG_PRINT_IF(1, 0 != alloc->usage_count, ("Destroying page table cache while pages are tagged as in use. %d allocations still marked as in use.\n", alloc->usage_count));
1279 _mali_osk_list_del(&alloc->list);
1280 alloc->pages.release(&alloc->pages);
1281 _mali_osk_free(alloc->usage_map);
1282 _mali_osk_free(alloc);
1285 MALI_DEBUG_PRINT_IF(1, !_mali_osk_list_empty(&page_table_cache.full), ("Page table cache full list contains one or more elements \n"));
1287 _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.full, mali_mmu_page_table_allocation, list)
1289 MALI_DEBUG_PRINT(1, ("Destroy alloc 0x%08X with usage count %d\n", (u32)alloc, alloc->usage_count));
1290 _mali_osk_list_del(&alloc->list);
1291 alloc->pages.release(&alloc->pages);
1292 _mali_osk_free(alloc->usage_map);
1293 _mali_osk_free(alloc);
1296 _mali_osk_lock_term(page_table_cache.lock);