blob: 2a80aa9a462a03824e20ba1434ae6b62f6b7d412 [file] [log] [blame]
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2016-2017, Linaro Limited
*/
#ifndef __MM_MOBJ_H
#define __MM_MOBJ_H
#include <compiler.h>
#include <mm/core_memprot.h>
#include <mm/file.h>
#include <mm/fobj.h>
#include <string_ext.h>
#include <sys/queue.h>
#include <tee_api_types.h>
#include <types_ext.h>
struct mobj {
const struct mobj_ops *ops;
size_t size;
size_t phys_granule;
struct refcount refc;
};
struct mobj_ops {
void *(*get_va)(struct mobj *mobj, size_t offs);
TEE_Result (*get_pa)(struct mobj *mobj, size_t offs, size_t granule,
paddr_t *pa);
size_t (*get_phys_offs)(struct mobj *mobj, size_t granule);
TEE_Result (*get_cattr)(struct mobj *mobj, uint32_t *cattr);
bool (*matches)(struct mobj *mobj, enum buf_is_attr attr);
void (*free)(struct mobj *mobj);
uint64_t (*get_cookie)(struct mobj *mobj);
struct fobj *(*get_fobj)(struct mobj *mobj);
};
extern struct mobj mobj_virt;
extern struct mobj *mobj_sec_ddr;
extern struct mobj *mobj_tee_ram;
static inline void *mobj_get_va(struct mobj *mobj, size_t offset)
{
if (mobj && mobj->ops && mobj->ops->get_va)
return mobj->ops->get_va(mobj, offset);
return NULL;
}
static inline TEE_Result mobj_get_pa(struct mobj *mobj, size_t offs,
size_t granule, paddr_t *pa)
{
if (mobj && mobj->ops && mobj->ops->get_pa)
return mobj->ops->get_pa(mobj, offs, granule, pa);
return TEE_ERROR_GENERIC;
}
static inline size_t mobj_get_phys_offs(struct mobj *mobj, size_t granule)
{
if (mobj && mobj->ops && mobj->ops->get_phys_offs)
return mobj->ops->get_phys_offs(mobj, granule);
return 0;
}
static inline TEE_Result mobj_get_cattr(struct mobj *mobj, uint32_t *cattr)
{
if (mobj && mobj->ops && mobj->ops->get_cattr)
return mobj->ops->get_cattr(mobj, cattr);
return TEE_ERROR_GENERIC;
}
static inline bool mobj_matches(struct mobj *mobj, enum buf_is_attr attr)
{
if (mobj && mobj->ops && mobj->ops->matches)
return mobj->ops->matches(mobj, attr);
return false;
}
/**
* mobj_get() - get a MOBJ
* @mobj: Pointer to a MOBJ or NULL
*
* Increases reference counter of the @mobj
*
* Returns @mobj with reference counter increased or NULL if @mobj was NULL
*/
static inline struct mobj *mobj_get(struct mobj *mobj)
{
if (mobj && !refcount_inc(&mobj->refc))
panic();
return mobj;
}
/**
* mobj_put() - put a MOBJ
* @mobj: Pointer to a MOBJ or NULL
*
* Decreases reference counter of the @mobj and frees it if the counter
* reaches 0.
*/
static inline void mobj_put(struct mobj *mobj)
{
if (mobj && refcount_dec(&mobj->refc))
mobj->ops->free(mobj);
}
/**
* mobj_put_wipe() - wipe and put a MOBJ
* @mobj: Pointer to a MOBJ or NULL
*
* Clears the memory represented by the mobj and then puts it.
*/
static inline void mobj_put_wipe(struct mobj *mobj)
{
void *buf = mobj_get_va(mobj, 0);
if (buf)
memzero_explicit(buf, mobj->size);
mobj_put(mobj);
}
static inline uint64_t mobj_get_cookie(struct mobj *mobj)
{
if (mobj && mobj->ops && mobj->ops->get_cookie)
return mobj->ops->get_cookie(mobj);
return 0;
}
static inline struct fobj *mobj_get_fobj(struct mobj *mobj)
{
if (mobj && mobj->ops && mobj->ops->get_fobj)
return mobj->ops->get_fobj(mobj);
return NULL;
}
static inline bool mobj_is_nonsec(struct mobj *mobj)
{
return mobj_matches(mobj, CORE_MEM_NON_SEC);
}
static inline bool mobj_is_secure(struct mobj *mobj)
{
return mobj_matches(mobj, CORE_MEM_SEC);
}
static inline bool mobj_is_sdp_mem(struct mobj *mobj)
{
return mobj_matches(mobj, CORE_MEM_SDP_MEM);
}
static inline size_t mobj_get_phys_granule(struct mobj *mobj)
{
if (mobj->phys_granule)
return mobj->phys_granule;
return mobj->size;
}
struct mobj *mobj_mm_alloc(struct mobj *mobj_parent, size_t size,
tee_mm_pool_t *pool);
struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr,
enum buf_is_attr battr);
#ifdef CFG_CORE_DYN_SHM
/* reg_shm represents TEE shared memory */
struct mobj *mobj_reg_shm_alloc(paddr_t *pages, size_t num_pages,
paddr_t page_offset, uint64_t cookie);
/**
* mobj_reg_shm_get_by_cookie() - get a MOBJ based on cookie
* @cookie: Cookie used by normal world when suppling the shared memory
*
* Searches for a registered shared memory MOBJ and if one with a matching
* @cookie is found its reference counter is increased before returning
* the MOBJ.
*
* Returns a valid pointer on success or NULL on failure.
*/
struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie);
TEE_Result mobj_reg_shm_release_by_cookie(uint64_t cookie);
/**
* mobj_inc_map() - increase map count
* @mobj: pointer to a registered shared memory MOBJ
*
* Maps the MOBJ if it isn't mapped already and increaes the map count
* Each call to mobj_reg_shm_inc_map() is supposed to be matches by a call
* to mobj_reg_shm_dec_map().
*
* Returns TEE_SUCCESS on success or an error code on failure
*/
TEE_Result mobj_inc_map(struct mobj *mobj);
/**
* mobj_dec_map() - decrease map count
* @mobj: pointer to a registered shared memory MOBJ
*
* Decreases the map count and also unmaps the MOBJ if the map count
* reaches 0. Each call to mobj_reg_shm_inc_map() is supposed to be
* matched by a call to mobj_reg_shm_dec_map().
*
* Returns TEE_SUCCESS on success or an error code on failure
*/
TEE_Result mobj_dec_map(struct mobj *mobj);
/**
* mobj_reg_shm_unguard() - unguards a reg_shm
* @mobj: pointer to a registered shared memory mobj
*
* A registered shared memory mobj is normally guarded against being
* released with mobj_reg_shm_try_release_by_cookie(). After this function
* has returned the mobj can be released by a call to
* mobj_reg_shm_try_release_by_cookie() if the reference counter allows it.
*/
void mobj_reg_shm_unguard(struct mobj *mobj);
/*
* mapped_shm represents registered shared buffer
* which is mapped into OPTEE va space
*/
struct mobj *mobj_mapped_shm_alloc(paddr_t *pages, size_t num_pages,
paddr_t page_offset, uint64_t cookie);
#else
static inline TEE_Result mobj_inc_map(struct mobj *mobj __unused)
{
return TEE_ERROR_NOT_SUPPORTED;
}
static inline TEE_Result mobj_dec_map(struct mobj *mobj __unused)
{
return TEE_ERROR_NOT_SUPPORTED;
}
#endif /*CFG_CORE_DYN_SHM*/
struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie);
#ifdef CFG_PAGED_USER_TA
bool mobj_is_paged(struct mobj *mobj);
#else
static inline bool mobj_is_paged(struct mobj *mobj __unused)
{
return false;
}
#endif
struct mobj *mobj_seccpy_shm_alloc(size_t size);
struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file);
#endif /*__MM_MOBJ_H*/