blob: 5f652c0ca23fa7804a08d76c792e09afd4e8cc9b [file]
/*
* Copyright (c) 2020 LK Trusty Authors. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <kernel/vm_obj.h>
#include <lib/binary_search_tree.h>
#include <lk/reflist.h>
#include <sys/types.h>
struct vmm_obj;
struct obj_ref;
struct vmm_aspace;
/**
* typedef ext_mem_client_id_t - External client identifier.
*
* Type use to store a 64 bit external client identifier.
*/
typedef uint64_t ext_mem_client_id_t;
/**
* typedef ext_mem_obj_id_t - External memory identifier.
*
* Type use to store a 64 bit external memory identifier. The value is chosen
* by the specific external memory implementation, but must be unique for the
* namespace it is used in (@objs argument of ext_mem_insert).
*/
typedef uint64_t ext_mem_obj_id_t;
/**
* struct ext_mem_page_run - Contiguous region of physical memory.
* @paddr: Physical address where region starts.
* @size: Number of bytes in region. Should be a multiple of PAGE_SIZE for the
* region to be mappable.
*/
struct ext_mem_page_run {
paddr_t paddr;
size_t size;
};
/**
* struct ext_mem_obj - Memory object for external sources.
* @id: Unique id used for lookup.
* @tag: Metadata used by some systems. Set to 0 if unused.
* @match_tag: Metadata used by some systems. Set to 0 if unused.
* Must match @tag before the object can be mapped. An object
* attached to an ipc message can be created before sending it
* to the app but only be mapable after the tag has been
* matched.
* @vmm_obj: VMM object.
* @node: Search tree node.
* @arch_mmu_flags: Memory type and required permission flags.
* @page_run_count: Number of entries in @page_runs.
* @page_runs: Array of physically contiguous regions.
*/
struct ext_mem_obj {
ext_mem_obj_id_t id;
uint64_t tag;
uint64_t match_tag;
struct vmm_obj vmm_obj;
struct bst_node node;
uint arch_mmu_flags;
size_t page_run_count;
struct ext_mem_page_run page_runs[];
};
/**
* ext_mem_obj_page_runs_size - Get size of page_runs.
* @page_run_count: Number if page runs.
*
* Calculate size of page_runs array. This can be added by the caller to the
* size of struct ext_mem_obj, or the size of a struct that embeds struct
* ext_mem_obj at the end, to get the number of bytes to allocate.
*
* Return: Size of ext_mem_obj page_runs array in bytes.
*/
static inline size_t ext_mem_obj_page_runs_size(size_t page_run_count) {
return sizeof(struct ext_mem_page_run) * page_run_count;
}
/**
* ext_mem_obj_initialize - Initialize struct ext_mem_obj.
* @obj: Object to initialize.
* @ref: Initial reference.
* @id: Unique id used by ext_mem_insert and ext_mem_lookup.
* @tag: Extra metadata used by some systems. Set to 0 if unused.
* @ops: Pointer to &struct vmm_obj_ops. @ops->check_flags can point
* directly to ext_mem_obj_check_flags. @ops->get_page can
* point directly to ext_mem_obj_get_page. @ops->destroy must
* point to a function supplied by the caller.
* @arch_mmu_flags: Memory type and required permission flags.
* @page_run_count: Number of entries in @page_runs.
*/
void ext_mem_obj_initialize(struct ext_mem_obj* obj,
struct obj_ref* ref,
ext_mem_obj_id_t id,
uint64_t tag,
struct vmm_obj_ops* ops,
uint arch_mmu_flags,
size_t page_run_count);
/**
* ext_mem_insert - Insert ext_mem_obj.
* @objs: Root of search tree to insert @obj into.
* @obj: ext_mem_obj to insert.
*
* Insert @obj into @objs.
* Caller is responsible for locking.
*
* Return: %true if @obj was inserted. %false if a node with the same id as
* @obj->id is already in @objs.
*/
bool ext_mem_insert(struct bst_root* objs, struct ext_mem_obj* obj);
/**
* ext_mem_delete - Remove ext_mem_obj.
* @objs: Root of search tree that contains @obj.
* @obj: ext_mem_obj to delete.
*
* Delete @obj from @objs.
* Caller is responsible for locking.
*/
static inline void ext_mem_delete(struct bst_root* objs,
struct ext_mem_obj* obj) {
bst_delete(objs, &obj->node);
}
/**
* ext_mem_lookup - Lookup ext_mem_obj by id.
* @objs: Root of search tree that might contain and object with id @id.
* @id: Id of object to return.
*
* Caller is responsible for locking.
*
* Return: ext_mem_obj in @objs matching @id, or %NULL if no matching
* ext_mem_obj is found.
*/
struct ext_mem_obj* ext_mem_lookup(struct bst_root* objs, ext_mem_obj_id_t id);
/**
* ext_mem_obj_set_match_tag - Set match tag on ext_mem_obj.
* @obj: &ext_mem_obj->vmm_obj.
* @match_tag: Set match_tag on @obj. The object can only be mapped if this
* matches the tag used when creating @obj. Pass 0 to return to
* initial state.
*/
void ext_mem_obj_set_match_tag(struct vmm_obj* obj, uint64_t match_tag);
/**
* ext_mem_obj_check_flags - vmm_obj_ops->check_flags for ext_mem_obj.
* @obj: &ext_mem_obj->vmm_obj.
* @arch_mmu_flags: arch_mmu_flags to check and modify.
*
* Compare @arch_mmu_flags against &ext_mem_obj->arch_mmu_flags. Return
* ERR_ACCESS_DENIED if permissions &ext_mem_obj->arch_mmu_flags are more
* restrictive than @arch_mmu_flags. Copy memory type flags from
* &ext_mem_obj->arch_mmu_flags to @arch_mmu_flags.
*
* Return: 0 on success, error code on failure.
*/
int ext_mem_obj_check_flags(struct vmm_obj* obj, uint* arch_mmu_flags);
/**
* ext_mem_obj_get_page - vmm_obj_ops->get_page for ext_mem_obj.
* @obj: &ext_mem_obj->vmm_obj.
* @offset: Byte offset into @obj.
* @paddr: Pointer to return physical address in.
* @paddr_size: Pointer to return size of physically contiguous region at
* @offset.
*
* Get single page or physically contiguous region at @offset bytes from
* start of @obj.
*
* Return: 0 on success, error code on failure.
*/
int ext_mem_obj_get_page(struct vmm_obj* obj,
size_t offset,
paddr_t* paddr,
size_t* paddr_size);
/**
* ext_mem_map_obj_id - Lookup and map external memory object.
* @aspace: Pass-through to vmm_alloc_obj.
* @name: Pass-through to vmm_alloc_obj.
* @client_id: Id of external entity where the memory originated.
* @mem_obj_id: Id of shared memory object to lookup and map.
* @tag: Tag of the memory. If a non-FF-A object, use 0.
* @offset: Pass-through to vmm_alloc_obj.
* @size: Pass-through to vmm_alloc_obj.
* @ptr: Pass-through to vmm_alloc_obj.
* @align_log2: Pass-through to vmm_alloc_obj.
* @vmm_flags: Pass-through to vmm_alloc_obj.
* @arch_mmu_flags: Pass-through to vmm_alloc_obj.
*
* Return: 0 on success, negative error code if object could not be mapped.
*/
status_t ext_mem_map_obj_id(struct vmm_aspace* aspace,
const char* name,
ext_mem_client_id_t client_id,
ext_mem_obj_id_t mem_obj_id,
uint64_t tag,
size_t offset,
size_t size,
void** ptr,
uint8_t align_log2,
uint vmm_flags,
uint arch_mmu_flags);
/**
* ext_mem_get_vmm_obj - Lookup shared memory object.
* @client_id: Id of external entity where the memory originated.
* @mem_obj_id: Id of shared memory object to lookup and return.
* @tag: Tag of the memory. If a non-FF-A object, use 0.
* @size: Size hint for object. Caller expects an object at least this
* big.
* @objp: Pointer to return object in.
* @obj_ref: Reference to *@objp.
*
* Not provided by ext_mem.
*
* Return: 0 on success. ERR_NOT_FOUND if @id does not exist.
*/
status_t ext_mem_get_vmm_obj(ext_mem_client_id_t client_id,
ext_mem_obj_id_t mem_obj_id,
uint64_t tag,
size_t size,
struct vmm_obj** objp,
struct obj_ref* obj_ref);