blob: e16f04d9618c7c71e1579f7d69330b7c2f52795a [file] [log] [blame]
/*
*
* (C) COPYRIGHT 2008-2013, 2017 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* SPDX-License-Identifier: GPL-2.0
*
*/
#ifndef _UMP_KERNEL_CORE_H_
#define _UMP_KERNEL_CORE_H_
#include <linux/mutex.h>
#include <linux/rwsem.h>
#include <linux/atomic.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/cred.h>
#include <linux/mmu_context.h>
#include <linux/ump-common.h>
#include <common/ump_kernel_descriptor_mapping.h>
/* forward decl */
struct umpp_session;
/**
* UMP handle metadata.
* Tracks various data about a handle not of any use to user space
*/
typedef enum
{
UMP_MGMT_EXTERNAL = (1ul << 0) /**< Handle created via the ump_dd_create_from_phys_blocks interface */
/* (1ul << 31) not to be used */
} umpp_management_flags;
/**
* Structure tracking the single global UMP device.
* Holds global data like the ID map
*/
typedef struct umpp_device
{
struct mutex secure_id_map_lock; /**< Lock protecting access to the map */
umpp_descriptor_mapping * secure_id_map; /**< Map of all known secure IDs on the system */
} umpp_device;
/**
* Structure tracking all memory allocations of a UMP allocation.
* Tracks info about an mapping so we can verify cache maintenace
* operations and help in the unmap cleanup.
*/
typedef struct umpp_cpu_mapping
{
struct list_head link; /**< link to list of mappings for an allocation */
void *vaddr_start; /**< CPU VA start of the mapping */
size_t nr_pages; /**< Size (in pages) of the mapping */
uint64_t page_off; /**< Offset (in pages) from start of the allocation where the mapping starts */
ump_dd_handle handle; /**< Which handle this mapping is linked to */
struct umpp_session * session; /**< Which session created the mapping */
} umpp_cpu_mapping;
/**
* Structure tracking UMP allocation.
* Represent a memory allocation with its ID.
* Tracks all needed meta-data about an allocation.
* */
typedef struct umpp_allocation
{
ump_secure_id id; /**< Secure ID of the allocation */
atomic_t refcount; /**< Usage count */
ump_alloc_flags flags; /**< Flags for all supported devices */
uint32_t management_flags; /**< Managment flags tracking */
pid_t owner; /**< The process ID owning the memory if not sharable */
ump_dd_security_filter filter_func; /**< Hook to verify use, called during retains from new clients */
ump_dd_final_release_callback final_release_func; /**< Hook called when the last reference is removed */
void* callback_data; /**< Additional data given to release hook */
uint64_t size; /**< Size (in bytes) of the allocation */
uint64_t blocksCount; /**< Number of physsical blocks the allocation is built up of */
ump_dd_physical_block_64 * block_array; /**< Array, one entry per block, describing block start and length */
struct mutex map_list_lock; /**< Lock protecting the map_list */
struct list_head map_list; /**< Tracks all CPU VA mappings of this allocation */
void * backendData; /**< Physical memory backend meta-data */
} umpp_allocation;
/**
* Structure tracking use of UMP memory by a session.
* Tracks the use of an allocation by a session so session termination can clean up any outstanding references.
* Also protects agains non-matched release calls from user space.
*/
typedef struct umpp_session_memory_usage
{
ump_secure_id id; /**< ID being used. For quick look-up */
ump_dd_handle mem; /**< Handle being used. */
/**
* Track how many times has the process retained this handle in the kernel.
* This should usually just be 1(allocated or resolved) or 2(mapped),
* but could be more if someone is playing with the low-level API
* */
atomic_t process_usage_count;
struct list_head link; /**< link to other usage trackers for a session */
} umpp_session_memory_usage;
/**
* Structure representing a session/client.
* Tracks the UMP allocations being used by this client.
*/
typedef struct umpp_session
{
struct mutex session_lock; /**< Lock for memory usage manipulation */
struct list_head memory_usage; /**< list of memory currently being used by the this session */
void* import_handler_data[UMPP_EXTERNAL_MEM_COUNT]; /**< Import modules per-session data pointer */
} umpp_session;
/**
* UMP core setup.
* Called by any OS specific startup function to initialize the common part.
* @return UMP_OK if core initialized correctly, any other value for errors
*/
ump_result umpp_core_constructor(void);
/**
* UMP core teardown.
* Called by any OS specific unload function to clean up the common part.
*/
void umpp_core_destructor(void);
/**
* UMP session start.
* Called by any OS specific session handler when a new session is detected
* @return Non-NULL if a matching core session could be set up. NULL on failure
*/
umpp_session *umpp_core_session_start(void);
/**
* UMP session end.
* Called by any OS specific session handler when a session is ended/terminated.
* @param session The core session object returned by ump_core_session_start
*/
void umpp_core_session_end(umpp_session *session);
/**
* Find a mapping object (if any) for this allocation.
* Called by any function needing to identify a mapping from a user virtual address.
* Verifies that the whole range to be within a mapping object.
* @param alloc The UMP allocation to find a matching mapping object of
* @param uaddr User mapping address to find the mapping object for
* @param size Length of the mapping
* @return NULL on error (no match found), pointer to mapping object if match found
*/
umpp_cpu_mapping * umpp_dd_find_enclosing_mapping(umpp_allocation * alloc, void* uaddr, size_t size);
/**
* Register a new mapping of an allocation.
* Called by functions creating a new mapping of an allocation, typically OS specific handlers.
* @param alloc The allocation object which has been mapped
* @param map Info about the mapping
*/
void umpp_dd_add_cpu_mapping(umpp_allocation * alloc, umpp_cpu_mapping * map);
/**
* Remove and free mapping object from an allocation.
* @param alloc The allocation object to remove the mapping info from
* @param target The mapping object to remove
*/
void umpp_dd_remove_cpu_mapping(umpp_allocation * alloc, umpp_cpu_mapping * target);
/**
* Helper to find a block in the blockArray which holds a given byte offset.
* @param alloc The allocation object to find the block in
* @param offset Offset (in bytes) from allocation start to find the block of
* @param[out] block_index Pointer to the index of the block matching
* @param[out] block_internal_offset Offset within the returned block of the searched offset
* @return 0 if a matching block was found, any other value for error
*/
int umpp_dd_find_start_block(const umpp_allocation * alloc, uint64_t offset, uint64_t * const block_index, uint64_t * const block_internal_offset);
/**
* Cache maintenance helper.
* Performs the requested cache operation on the given handle.
* @param mem Allocation handle
* @param op Cache maintenance operation to perform
* @param address User mapping at which to do the operation
* @param size Length (in bytes) of the range to do the operation on
*/
void umpp_dd_cpu_msync_now(ump_dd_handle mem, ump_cpu_msync_op op, void * address, size_t size);
/**
* Import module session early init.
* Calls session_begin on all installed import modules.
* @param session The core session object to initialized the import handler for
* */
void umpp_import_handlers_init(umpp_session * session);
/**
* Import module session cleanup.
* Calls session_end on all import modules bound to the session.
* @param session The core session object to initialized the import handler for
*/
void umpp_import_handlers_term(umpp_session * session);
#endif /* _UMP_KERNEL_CORE_H_ */