/* * * (C) COPYRIGHT 2010-2011 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 #include #include /* * Example routine to exercise the user space UMP api. * This routine initializes the UMP api and allocates some CPU+device X memory. * No usage hints are given, so the driver will use the default cacheability policy. * With the allocation it creates a duplicate handle and plays with the reference count. * Then it simulates interacting with a device and contains pseudo code for the device. * * If any error is detected correct cleanup will be performed and -1 will be returned. * If successful then 0 will be returned. */ static int test_ump_user_api(void) { /* This is the size we try to allocate*/ const size_t alloc_size = 4096; ump_handle h = UMP_INVALID_MEMORY_HANDLE; ump_handle h_copy = UMP_INVALID_MEMORY_HANDLE; ump_handle h_clone = UMP_INVALID_MEMORY_HANDLE; void * mapping = NULL; ump_result ump_api_res; int result = -1; ump_secure_id id; size_t size_returned; ump_api_res = ump_open(); if (UMP_OK != ump_api_res) { /* failed to open an ump session */ /* early out */ return -1; } h = ump_allocate_64(alloc_size, UMP_PROT_CPU_RD | UMP_PROT_CPU_WR | UMP_PROT_X_RD | UMP_PROT_X_WR); /* the refcount is now 1 */ if (UMP_INVALID_MEMORY_HANDLE == h) { /* allocation failure */ goto cleanup; } /* this is how we could share this allocation with another process */ /* in process A: */ id = ump_secure_id_get(h); /* still ref count 1 */ /* send the id to process B */ /* in process B: */ /* receive the id from A */ h_clone = ump_from_secure_id(id); /* the ref count of the allocation is now 2 (one from each handle to it) */ /* do something ... */ /* release our clone */ ump_release(h_clone); /* safe to call even if ump_from_secure_id failed */ h_clone = UMP_INVALID_MEMORY_HANDLE; /* a simple save-for-future-use logic inside the driver would just copy the handle (but add a ref manually too!) */ /* * void assign_memory_to_job(h) * { */ h_copy = h; ump_retain(h_copy); /* manual retain needed as we just assigned the handle, now 2 */ /* * } * * void job_completed(void) * { */ ump_release(h_copy); /* normal handle release as if we got via an ump_allocate */ h_copy = UMP_INVALID_MEMORY_HANDLE; /* * } */ /* we're now back at ref count 1, and only h is a valid handle */ /* enough handle duplication show-off, let's play with the contents instead */ mapping = ump_map(h, 0, alloc_size); if (NULL == mapping) { /* mapping failure, either out of address space or some other error */ goto cleanup; } memset(mapping, 0, alloc_size); /* let's pretend we're going to start some hw device on this buffer and read the result afterwards */ ump_cpu_msync_now(h, UMP_MSYNC_CLEAN, mapping, alloc_size); /* device cache invalidate memory barrier start device memory barrier wait for device memory barrier device cache clean memory barrier */ ump_cpu_msync_now(h, UMP_MSYNC_CLEAN_AND_INVALIDATE, mapping, alloc_size); /* we could now peek at the result produced by the hw device, which is now accessible via our mapping */ /* unmap the buffer when we're done with it */ ump_unmap(h, mapping, alloc_size); result = 0; cleanup: ump_release(h); h = UMP_INVALID_MEMORY_HANDLE; ump_close(); return result; }