forked from Qortal/Brooklyn
484 lines
18 KiB
C
484 lines
18 KiB
C
/*
|
|
Copyright (c) 2012, Broadcom Europe Ltd
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
* Neither the name of the copyright holder nor the
|
|
names of its contributors may be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef __USER_VCSM__H__INCLUDED__
|
|
#define __USER_VCSM__H__INCLUDED__
|
|
|
|
/* VideoCore Shared Memory - user interface library.
|
|
**
|
|
** This library provides all the necessary abstraction for any application to
|
|
** make use of the shared memory service which is distributed across a kernel
|
|
** driver and a videocore service.
|
|
**
|
|
** It is an application design decision to choose or not to use this service.
|
|
**
|
|
** The logical flow of operations that a user application needs to follow when
|
|
** using this service is:
|
|
**
|
|
** 1) Initialize the service.
|
|
** 2) Allocate shared memory blocks.
|
|
** 3) Start using the allocated blocks.
|
|
** - In order to gain ownership on a block, lock the allocated block,
|
|
** locking a block returns a valid address that the user application
|
|
** can access.
|
|
** - When finished with using the block for the current execution cycle
|
|
** or function, and so when giving up the ownership, unlock the block.
|
|
** 4) A block can be locked/unlocked as many times required - within or outside
|
|
** of - a specific execution context.
|
|
** 5) To completely release an allocated block, free it.
|
|
** 6) If the service is no longer required, terminate it.
|
|
**
|
|
**
|
|
** Some generic considerations:
|
|
|
|
** Allocating memory blocks.
|
|
**
|
|
** Memory blocks can be allocated in different manners depending on the cache
|
|
** behavior desired. A given block can either be:
|
|
|
|
** - Allocated in a non cached fashion all the way through host and videocore.
|
|
** - Allocated in a cached fashion on host OR videocore.
|
|
** - Allocated in a cached fashion on host AND videocore.
|
|
**
|
|
** It is an application decision to determine how to allocate a block. Evidently
|
|
** if the application will be doing substantial read/write accesses to a given block,
|
|
** it is recommended to allocate the block at least in a 'host cached' fashion for
|
|
** better results.
|
|
**
|
|
**
|
|
** Locking memory blocks.
|
|
**
|
|
** When the memory block has been allocated in a host cached fashion, locking the
|
|
** memory block (and so taking ownership of it) will trigger a cache invalidation.
|
|
**
|
|
** For the above reason and when using host cached allocation, it is important that
|
|
** an application properly implements the lock/unlock mechanism to ensure cache will
|
|
** stay coherent, otherwise there is no guarantee it will at all be.
|
|
**
|
|
** It is possible to dynamically change the host cache behavior (ie cached or non
|
|
** cached) of a given allocation without needing to free and re-allocate the block.
|
|
** This feature can be useful for such application which requires access to the block
|
|
** only at certain times and not otherwise. By changing the cache behavior dynamically
|
|
** the application can optimize performances for a given duration of use.
|
|
** Such dynamic cache behavior remapping only applies to host cache and not videocore
|
|
** cache. If one requires to change the videocore cache behavior, then a new block
|
|
** must be created to replace the old one.
|
|
**
|
|
** On successful locking, a valid pointer is returned that the application can use
|
|
** to access to data inside the block. There is no guarantee that the pointer will
|
|
** stay valid following the unlock action corresponding to this lock.
|
|
**
|
|
**
|
|
** Unocking memory blocks.
|
|
**
|
|
** When the memory block has been allocated in a host cached fashion, unlocking the
|
|
** memory block (and so forgiving its ownership) will trigger a cache flush unless
|
|
** explicitely asked not to flush the cache for performances reasons.
|
|
**
|
|
** For the above reason and when using host cached allocation, it is important that
|
|
** an application properly implements the lock/unlock mechanism to ensure cache will
|
|
** stay coherent, otherwise there is no guarantee it will at all be.
|
|
**
|
|
**
|
|
** A complete API is defined below.
|
|
*/
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
/* Different status that can be dumped.
|
|
*/
|
|
typedef enum
|
|
{
|
|
VCSM_STATUS_VC_WALK_ALLOC = 0, // Walks *all* the allocation on videocore.
|
|
// Result of the walk is seen in the videocore
|
|
// log.
|
|
VCSM_STATUS_HOST_WALK_MAP, // Walks the *full* mapping allocation on host
|
|
// driver (ie for all processes). Result of
|
|
// the walk is seen in the kernel log.
|
|
VCSM_STATUS_HOST_WALK_PID_MAP, // Walks the per process mapping allocation on host
|
|
// driver (for current process). Result of
|
|
// the walk is seen in the kernel log.
|
|
VCSM_STATUS_HOST_WALK_PID_ALLOC, // Walks the per process host allocation on host
|
|
// driver (for current process). Result of
|
|
// the walk is seen in the kernel log.
|
|
VCSM_STATUS_VC_MAP_ALL, // Equivalent to both VCSM_STATUS_VC_WALK_ALLOC and
|
|
// VCSM_STATUS_HOST_WALK_MAP.
|
|
//
|
|
VCSM_STATUS_NONE, // Must be last - invalid.
|
|
|
|
} VCSM_STATUS_T;
|
|
|
|
/* Different kind of cache behavior.
|
|
*/
|
|
typedef enum
|
|
{
|
|
VCSM_CACHE_TYPE_NONE = 0, // No caching applies.
|
|
VCSM_CACHE_TYPE_HOST, // Allocation is cached on host (user space).
|
|
VCSM_CACHE_TYPE_VC, // Allocation is cached on videocore.
|
|
VCSM_CACHE_TYPE_HOST_AND_VC, // Allocation is cached on both host and videocore.
|
|
|
|
} VCSM_CACHE_TYPE_T;
|
|
|
|
/* Initialize the vcsm processing with option to use vc-sm-cma which supports
|
|
** dmabuf export, and passing in an external fd to /dev/vcsm-cma or /dev/vcsm.
|
|
**
|
|
** Must be called once before attempting to do anything else.
|
|
**
|
|
** Returns 0 on success, -1 on error.
|
|
*/
|
|
int vcsm_init_ex( int want_export, int fd );
|
|
|
|
/* Initialize the vcsm processing.
|
|
**
|
|
** Must be called once before attempting to do anything else.
|
|
**
|
|
** Returns 0 on success, -1 on error.
|
|
*/
|
|
int vcsm_init( void );
|
|
|
|
/* Terminates the vcsm processing.
|
|
**
|
|
** Must be called vcsm services are no longer needed, it will
|
|
** take care of removing any allocation under the current process
|
|
** control if deemed necessary.
|
|
*/
|
|
void vcsm_exit( void );
|
|
|
|
|
|
/* Queries the status of the the vcsm.
|
|
**
|
|
** Triggers dump of various kind of information, see the
|
|
** different variants specified in VCSM_STATUS_T.
|
|
**
|
|
** Pid is optional.
|
|
*/
|
|
void vcsm_status( VCSM_STATUS_T status, int pid );
|
|
|
|
|
|
/* Allocates a non-cached block of memory of size 'size' via the vcsm memory
|
|
** allocator.
|
|
**
|
|
** Returns: 0 on error
|
|
** a non-zero opaque handle on success.
|
|
**
|
|
** On success, the user must invoke vcsm_lock with the returned opaque
|
|
** handle to gain access to the memory associated with the opaque handle.
|
|
** When finished using the memory, the user calls vcsm_unlock_xx (see those
|
|
** function definition for more details on the one that can be used).
|
|
**
|
|
** A well behaved application should make every attempt to lock/unlock
|
|
** only for the duration it needs to access the memory data associated with
|
|
** the opaque handle.
|
|
*/
|
|
unsigned int vcsm_malloc( unsigned int size, const char *name );
|
|
|
|
|
|
/* Allocates a cached block of memory of size 'size' via the vcsm memory
|
|
** allocator, the type of caching requested is passed as argument of the
|
|
** function call.
|
|
**
|
|
** Returns: 0 on error
|
|
** a non-zero opaque handle on success.
|
|
**
|
|
** On success, the user must invoke vcsm_lock with the returned opaque
|
|
** handle to gain access to the memory associated with the opaque handle.
|
|
** When finished using the memory, the user calls vcsm_unlock_xx (see those
|
|
** function definition for more details on the one that can be used).
|
|
**
|
|
** A well behaved application should make every attempt to lock/unlock
|
|
** only for the duration it needs to access the memory data associated with
|
|
** the opaque handle.
|
|
*/
|
|
unsigned int vcsm_malloc_cache( unsigned int size, VCSM_CACHE_TYPE_T cache, const char *name );
|
|
|
|
|
|
/* Shares an allocated block of memory via the vcsm memory allocator.
|
|
**
|
|
** Returns: 0 on error
|
|
** a non-zero opaque handle on success.
|
|
**
|
|
** On success, the user must invoke vcsm_lock with the returned opaque
|
|
** handle to gain access to the memory associated with the opaque handle.
|
|
** When finished using the memory, the user calls vcsm_unlock_xx (see those
|
|
** function definition for more details on the one that can be used).
|
|
**
|
|
** A well behaved application should make every attempt to lock/unlock
|
|
** only for the duration it needs to access the memory data associated with
|
|
** the opaque handle.
|
|
*/
|
|
unsigned int vcsm_malloc_share( unsigned int handle );
|
|
|
|
|
|
/* Resizes a block of memory allocated previously by vcsm_alloc.
|
|
**
|
|
** Returns: 0 on success
|
|
** -errno on error.
|
|
**
|
|
** The handle must be unlocked by user prior to attempting any
|
|
** resize action.
|
|
**
|
|
** On error, the original size allocated against the handle
|
|
** remains available the same way it would be following a
|
|
** successful vcsm_malloc.
|
|
*/
|
|
int vcsm_resize( unsigned int handle, unsigned int new_size );
|
|
|
|
|
|
/* Frees a block of memory that was successfully allocated by
|
|
** a prior call the vcms_alloc.
|
|
**
|
|
** The handle should be considered invalid upon return from this
|
|
** call.
|
|
**
|
|
** Whether any memory is actually freed up or not as the result of
|
|
** this call will depends on many factors, if all goes well it will
|
|
** be freed. If something goes wrong, the memory will likely end up
|
|
** being freed up as part of the vcsm_exit process. In the end the
|
|
** memory is guaranteed to be freed one way or another.
|
|
*/
|
|
void vcsm_free( unsigned int handle );
|
|
|
|
|
|
/* Retrieves a videocore opaque handle from a mapped user address
|
|
** pointer. The videocore handle will correspond to the actual
|
|
** memory mapped in videocore.
|
|
**
|
|
** Returns: 0 on error
|
|
** a non-zero opaque handle on success.
|
|
**
|
|
** Note: the videocore opaque handle is distinct from the user
|
|
** opaque handle (allocated via vcsm_malloc) and it is only
|
|
** significant for such application which knows what to do
|
|
** with it, for the others it is just a number with little
|
|
** use since nothing can be done with it (in particular
|
|
** for safety reason it cannot be used to map anything).
|
|
*/
|
|
unsigned int vcsm_vc_hdl_from_ptr( void *usr_ptr );
|
|
|
|
|
|
/* Retrieves a videocore opaque handle from a opaque handle
|
|
** pointer. The videocore handle will correspond to the actual
|
|
** memory mapped in videocore.
|
|
**
|
|
** Returns: 0 on error
|
|
** a non-zero opaque handle on success.
|
|
**
|
|
** Note: the videocore opaque handle is distinct from the user
|
|
** opaque handle (allocated via vcsm_malloc) and it is only
|
|
** significant for such application which knows what to do
|
|
** with it, for the others it is just a number with little
|
|
** use since nothing can be done with it (in particular
|
|
** for safety reason it cannot be used to map anything).
|
|
*/
|
|
unsigned int vcsm_vc_hdl_from_hdl( unsigned int handle );
|
|
|
|
|
|
/* Retrieves a videocore (bus) address from a opaque handle
|
|
** pointer.
|
|
**
|
|
** Returns: 0 on error
|
|
** a non-zero videocore address on success.
|
|
*/
|
|
unsigned int vcsm_vc_addr_from_hdl( unsigned int handle );
|
|
|
|
|
|
/* Retrieves a user opaque handle from a mapped user address
|
|
** pointer.
|
|
**
|
|
** Returns: 0 on error
|
|
** a non-zero opaque handle on success.
|
|
*/
|
|
unsigned int vcsm_usr_handle( void *usr_ptr );
|
|
|
|
|
|
/* Retrieves a mapped user address from an opaque user
|
|
** handle.
|
|
**
|
|
** Returns: 0 on error
|
|
** a non-zero address on success.
|
|
**
|
|
** On success, the address corresponds to the pointer
|
|
** which can access the data allocated via the vcsm_malloc
|
|
** call.
|
|
*/
|
|
void *vcsm_usr_address( unsigned int handle );
|
|
|
|
|
|
/* Locks the memory associated with this opaque handle.
|
|
**
|
|
** Returns: NULL on error
|
|
** a valid pointer on success.
|
|
**
|
|
** A user MUST lock the handle received from vcsm_malloc
|
|
** in order to be able to use the memory associated with it.
|
|
**
|
|
** On success, the pointer returned is only valid within
|
|
** the lock content (ie until a corresponding vcsm_unlock_xx
|
|
** is invoked).
|
|
*/
|
|
void *vcsm_lock( unsigned int handle );
|
|
|
|
|
|
/* Locks the memory associated with this opaque handle. The lock
|
|
** also gives a chance to update the *host* cache behavior of the
|
|
** allocated buffer if so desired. The *videocore* cache behavior
|
|
** of the allocated buffer cannot be changed by this call and such
|
|
** attempt will be ignored.
|
|
**
|
|
** The system will attempt to honour the cache_update mode request,
|
|
** the cache_result mode will provide the final answer on which cache
|
|
** mode is really in use. Failing to change the cache mode will not
|
|
** result in a failure to lock the buffer as it is an application
|
|
** decision to choose what to do if (cache_result != cache_update)
|
|
**
|
|
** The value returned in cache_result can only be considered valid if
|
|
** the returned pointer is non NULL. The cache_result pointer may be
|
|
** NULL if the application does not care about the actual outcome of
|
|
** its action with regards to the cache behavior change.
|
|
**
|
|
** Returns: NULL on error
|
|
** a valid pointer on success.
|
|
**
|
|
** A user MUST lock the handle received from vcsm_malloc
|
|
** in order to be able to use the memory associated with it.
|
|
**
|
|
** On success, the pointer returned is only valid within
|
|
** the lock content (ie until a corresponding vcsm_unlock_xx
|
|
** is invoked).
|
|
*/
|
|
void *vcsm_lock_cache( unsigned int handle,
|
|
VCSM_CACHE_TYPE_T cache_update,
|
|
VCSM_CACHE_TYPE_T *cache_result );
|
|
|
|
|
|
/* Unlocks the memory associated with this user mapped address.
|
|
**
|
|
** Returns: 0 on success
|
|
** -errno on error.
|
|
**
|
|
** After unlocking a mapped address, the user should no longer
|
|
** attempt to reference it.
|
|
*/
|
|
int vcsm_unlock_ptr( void *usr_ptr );
|
|
|
|
|
|
/* Unlocks the memory associated with this user mapped address.
|
|
** Apply special processing that would override the otherwise
|
|
** default behavior.
|
|
**
|
|
** If 'cache_no_flush' is specified:
|
|
** Do not flush cache as the result of the unlock (if cache
|
|
** flush was otherwise applicable in this case).
|
|
**
|
|
** Returns: 0 on success
|
|
** -errno on error.
|
|
**
|
|
** After unlocking a mapped address, the user should no longer
|
|
** attempt to reference it.
|
|
*/
|
|
int vcsm_unlock_ptr_sp( void *usr_ptr, int cache_no_flush );
|
|
|
|
|
|
/* Unlocks the memory associated with this user opaque handle.
|
|
**
|
|
** Returns: 0 on success
|
|
** -errno on error.
|
|
**
|
|
** After unlocking an opaque handle, the user should no longer
|
|
** attempt to reference the mapped addressed once associated
|
|
** with it.
|
|
*/
|
|
int vcsm_unlock_hdl( unsigned int handle );
|
|
|
|
|
|
/* Unlocks the memory associated with this user opaque handle.
|
|
** Apply special processing that would override the otherwise
|
|
** default behavior.
|
|
**
|
|
** If 'cache_no_flush' is specified:
|
|
** Do not flush cache as the result of the unlock (if cache
|
|
** flush was otherwise applicable in this case).
|
|
**
|
|
** Returns: 0 on success
|
|
** -errno on error.
|
|
**
|
|
** After unlocking an opaque handle, the user should no longer
|
|
** attempt to reference the mapped addressed once associated
|
|
** with it.
|
|
*/
|
|
int vcsm_unlock_hdl_sp( unsigned int handle, int cache_no_flush );
|
|
|
|
/* Clean and/or invalidate the memory associated with this user opaque handle
|
|
**
|
|
** Returns: non-zero on error
|
|
**
|
|
** structure contains a list of flush/invalidate commands. Commands are:
|
|
** 0: nop
|
|
** 1: invalidate given virtual range in L1/L2
|
|
** 2: clean given virtual range in L1/L2
|
|
** 3: clean+invalidate given virtual range in L1/L2
|
|
*/
|
|
#define VCSM_MAX_CLEAN_INVALIDATE_ENTRIES 8
|
|
struct vcsm_user_clean_invalid_s {
|
|
struct {
|
|
unsigned int cmd;
|
|
unsigned int handle;
|
|
unsigned int addr;
|
|
unsigned int size;
|
|
} s[VCSM_MAX_CLEAN_INVALIDATE_ENTRIES];
|
|
};
|
|
|
|
int vcsm_clean_invalid( struct vcsm_user_clean_invalid_s *s );
|
|
|
|
struct vcsm_user_clean_invalid2_s {
|
|
unsigned char op_count;
|
|
unsigned char zero[3];
|
|
struct vcsm_user_clean_invalid2_block_s {
|
|
unsigned short invalidate_mode;
|
|
unsigned short block_count;
|
|
void * start_address;
|
|
unsigned int block_size;
|
|
unsigned int inter_block_stride;
|
|
} s[0];
|
|
};
|
|
|
|
int vcsm_clean_invalid2( struct vcsm_user_clean_invalid2_s *s );
|
|
|
|
unsigned int vcsm_import_dmabuf( int dmabuf, const char *name );
|
|
|
|
int vcsm_export_dmabuf( unsigned int vcsm_handle );
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* __USER_VCSM__H__INCLUDED__ */
|
|
|