1185b4595SMarouene Boubakri /* SPDX-License-Identifier: BSD-2-Clause */ 2185b4595SMarouene Boubakri /* 3185b4595SMarouene Boubakri * Copyright (c) 2016-2017, Linaro Limited 4185b4595SMarouene Boubakri */ 5185b4595SMarouene Boubakri 6185b4595SMarouene Boubakri #ifndef __MM_MOBJ_H 7185b4595SMarouene Boubakri #define __MM_MOBJ_H 8185b4595SMarouene Boubakri 9185b4595SMarouene Boubakri #include <compiler.h> 10185b4595SMarouene Boubakri #include <mm/core_memprot.h> 11185b4595SMarouene Boubakri #include <mm/file.h> 12185b4595SMarouene Boubakri #include <mm/fobj.h> 13185b4595SMarouene Boubakri #include <string_ext.h> 14185b4595SMarouene Boubakri #include <sys/queue.h> 15185b4595SMarouene Boubakri #include <tee_api_types.h> 16185b4595SMarouene Boubakri #include <types_ext.h> 17185b4595SMarouene Boubakri 18c1bdf4fcSJens Wiklander #include <optee_msg.h> 19c1bdf4fcSJens Wiklander 20185b4595SMarouene Boubakri struct mobj { 21185b4595SMarouene Boubakri const struct mobj_ops *ops; 22185b4595SMarouene Boubakri size_t size; 23185b4595SMarouene Boubakri size_t phys_granule; 24185b4595SMarouene Boubakri struct refcount refc; 25185b4595SMarouene Boubakri }; 26185b4595SMarouene Boubakri 27185b4595SMarouene Boubakri struct mobj_ops { 289c4aaf67SJens Wiklander void *(*get_va)(struct mobj *mobj, size_t offs, size_t len); 29185b4595SMarouene Boubakri TEE_Result (*get_pa)(struct mobj *mobj, size_t offs, size_t granule, 30185b4595SMarouene Boubakri paddr_t *pa); 31185b4595SMarouene Boubakri size_t (*get_phys_offs)(struct mobj *mobj, size_t granule); 32*8afe7a7cSJens Wiklander TEE_Result (*get_mem_type)(struct mobj *mobj, uint32_t *mt); 33185b4595SMarouene Boubakri bool (*matches)(struct mobj *mobj, enum buf_is_attr attr); 34185b4595SMarouene Boubakri void (*free)(struct mobj *mobj); 35185b4595SMarouene Boubakri uint64_t (*get_cookie)(struct mobj *mobj); 36185b4595SMarouene Boubakri struct fobj *(*get_fobj)(struct mobj *mobj); 37185b4595SMarouene Boubakri TEE_Result (*inc_map)(struct mobj *mobj); 38185b4595SMarouene Boubakri TEE_Result (*dec_map)(struct mobj *mobj); 39185b4595SMarouene Boubakri }; 40185b4595SMarouene Boubakri 41185b4595SMarouene Boubakri extern struct mobj mobj_virt; 42185b4595SMarouene Boubakri extern struct mobj *mobj_sec_ddr; 43ff01e245SAnton Rybakov extern struct mobj *mobj_tee_ram_rx; 44ff01e245SAnton Rybakov extern struct mobj *mobj_tee_ram_rw; 45185b4595SMarouene Boubakri 469c4aaf67SJens Wiklander /* 479c4aaf67SJens Wiklander * mobj_get_va() - get virtual address of a mapped mobj 489c4aaf67SJens Wiklander * @mobj: memory object 499c4aaf67SJens Wiklander * @offset: find the va of this offset into @mobj 509c4aaf67SJens Wiklander * @len: how many bytes after @offset that must be valid, can be 1 if 519c4aaf67SJens Wiklander * the caller knows by other means that the expected buffer is 529c4aaf67SJens Wiklander * available. 539c4aaf67SJens Wiklander * 549c4aaf67SJens Wiklander * return a virtual address on success or NULL on error 559c4aaf67SJens Wiklander */ 569c4aaf67SJens Wiklander static inline void *mobj_get_va(struct mobj *mobj, size_t offset, size_t len) 57185b4595SMarouene Boubakri { 58185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->get_va) 599c4aaf67SJens Wiklander return mobj->ops->get_va(mobj, offset, len); 60185b4595SMarouene Boubakri return NULL; 61185b4595SMarouene Boubakri } 62185b4595SMarouene Boubakri 63185b4595SMarouene Boubakri static inline TEE_Result mobj_get_pa(struct mobj *mobj, size_t offs, 64185b4595SMarouene Boubakri size_t granule, paddr_t *pa) 65185b4595SMarouene Boubakri { 66185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->get_pa) 67185b4595SMarouene Boubakri return mobj->ops->get_pa(mobj, offs, granule, pa); 68185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 69185b4595SMarouene Boubakri } 70185b4595SMarouene Boubakri 71185b4595SMarouene Boubakri static inline size_t mobj_get_phys_offs(struct mobj *mobj, size_t granule) 72185b4595SMarouene Boubakri { 73185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->get_phys_offs) 74185b4595SMarouene Boubakri return mobj->ops->get_phys_offs(mobj, granule); 75185b4595SMarouene Boubakri return 0; 76185b4595SMarouene Boubakri } 77185b4595SMarouene Boubakri 78*8afe7a7cSJens Wiklander static inline TEE_Result mobj_get_mem_type(struct mobj *mobj, uint32_t *mt) 79185b4595SMarouene Boubakri { 80*8afe7a7cSJens Wiklander if (mobj && mobj->ops && mobj->ops->get_mem_type) 81*8afe7a7cSJens Wiklander return mobj->ops->get_mem_type(mobj, mt); 82185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 83185b4595SMarouene Boubakri } 84185b4595SMarouene Boubakri 85185b4595SMarouene Boubakri static inline bool mobj_matches(struct mobj *mobj, enum buf_is_attr attr) 86185b4595SMarouene Boubakri { 87185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->matches) 88185b4595SMarouene Boubakri return mobj->ops->matches(mobj, attr); 89185b4595SMarouene Boubakri return false; 90185b4595SMarouene Boubakri } 91185b4595SMarouene Boubakri 92185b4595SMarouene Boubakri /** 93185b4595SMarouene Boubakri * mobj_inc_map() - increase map count 94185b4595SMarouene Boubakri * @mobj: pointer to a MOBJ 95185b4595SMarouene Boubakri * 96185b4595SMarouene Boubakri * Maps the MOBJ if it isn't mapped already and increases the map count 97185b4595SMarouene Boubakri * Each call to mobj_inc_map() is supposed to be matches by a call to 98185b4595SMarouene Boubakri * mobj_dec_map(). 99185b4595SMarouene Boubakri * 100185b4595SMarouene Boubakri * Returns TEE_SUCCESS on success or an error code on failure 101185b4595SMarouene Boubakri */ 102185b4595SMarouene Boubakri static inline TEE_Result mobj_inc_map(struct mobj *mobj) 103185b4595SMarouene Boubakri { 104185b4595SMarouene Boubakri if (mobj && mobj->ops) { 105185b4595SMarouene Boubakri if (mobj->ops->inc_map) 106185b4595SMarouene Boubakri return mobj->ops->inc_map(mobj); 107185b4595SMarouene Boubakri return TEE_SUCCESS; 108185b4595SMarouene Boubakri } 109185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 110185b4595SMarouene Boubakri } 111185b4595SMarouene Boubakri 112185b4595SMarouene Boubakri /** 113185b4595SMarouene Boubakri * mobj_dec_map() - decrease map count 114185b4595SMarouene Boubakri * @mobj: pointer to a MOBJ 115185b4595SMarouene Boubakri * 116185b4595SMarouene Boubakri * Decreases the map count and also unmaps the MOBJ if the map count 117185b4595SMarouene Boubakri * reaches 0. Each call to mobj_inc_map() is supposed to be matched by a 118185b4595SMarouene Boubakri * call to mobj_dec_map(). 119185b4595SMarouene Boubakri * 120185b4595SMarouene Boubakri * Returns TEE_SUCCESS on success or an error code on failure 121185b4595SMarouene Boubakri */ 122185b4595SMarouene Boubakri static inline TEE_Result mobj_dec_map(struct mobj *mobj) 123185b4595SMarouene Boubakri { 124185b4595SMarouene Boubakri if (mobj && mobj->ops) { 125185b4595SMarouene Boubakri if (mobj->ops->dec_map) 126185b4595SMarouene Boubakri return mobj->ops->dec_map(mobj); 127185b4595SMarouene Boubakri return TEE_SUCCESS; 128185b4595SMarouene Boubakri } 129185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 130185b4595SMarouene Boubakri } 131185b4595SMarouene Boubakri 132185b4595SMarouene Boubakri /** 133185b4595SMarouene Boubakri * mobj_get() - get a MOBJ 134185b4595SMarouene Boubakri * @mobj: Pointer to a MOBJ or NULL 135185b4595SMarouene Boubakri * 136185b4595SMarouene Boubakri * Increases reference counter of the @mobj 137185b4595SMarouene Boubakri * 138185b4595SMarouene Boubakri * Returns @mobj with reference counter increased or NULL if @mobj was NULL 139185b4595SMarouene Boubakri */ 140185b4595SMarouene Boubakri static inline struct mobj *mobj_get(struct mobj *mobj) 141185b4595SMarouene Boubakri { 142185b4595SMarouene Boubakri if (mobj && !refcount_inc(&mobj->refc)) 143185b4595SMarouene Boubakri panic(); 144185b4595SMarouene Boubakri 145185b4595SMarouene Boubakri return mobj; 146185b4595SMarouene Boubakri } 147185b4595SMarouene Boubakri 148185b4595SMarouene Boubakri /** 149185b4595SMarouene Boubakri * mobj_put() - put a MOBJ 150185b4595SMarouene Boubakri * @mobj: Pointer to a MOBJ or NULL 151185b4595SMarouene Boubakri * 152185b4595SMarouene Boubakri * Decreases reference counter of the @mobj and frees it if the counter 153185b4595SMarouene Boubakri * reaches 0. 154185b4595SMarouene Boubakri */ 155185b4595SMarouene Boubakri static inline void mobj_put(struct mobj *mobj) 156185b4595SMarouene Boubakri { 157185b4595SMarouene Boubakri if (mobj && refcount_dec(&mobj->refc)) 158185b4595SMarouene Boubakri mobj->ops->free(mobj); 159185b4595SMarouene Boubakri } 160185b4595SMarouene Boubakri 161185b4595SMarouene Boubakri /** 162185b4595SMarouene Boubakri * mobj_put_wipe() - wipe and put a MOBJ 163185b4595SMarouene Boubakri * @mobj: Pointer to a MOBJ or NULL 164185b4595SMarouene Boubakri * 165185b4595SMarouene Boubakri * Clears the memory represented by the mobj and then puts it. 166185b4595SMarouene Boubakri */ 167185b4595SMarouene Boubakri static inline void mobj_put_wipe(struct mobj *mobj) 168185b4595SMarouene Boubakri { 1699c4aaf67SJens Wiklander if (mobj) { 1709c4aaf67SJens Wiklander void *buf = mobj_get_va(mobj, 0, mobj->size); 171185b4595SMarouene Boubakri 172185b4595SMarouene Boubakri if (buf) 173185b4595SMarouene Boubakri memzero_explicit(buf, mobj->size); 174185b4595SMarouene Boubakri mobj_put(mobj); 175185b4595SMarouene Boubakri } 1769c4aaf67SJens Wiklander } 177185b4595SMarouene Boubakri 178185b4595SMarouene Boubakri static inline uint64_t mobj_get_cookie(struct mobj *mobj) 179185b4595SMarouene Boubakri { 180185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->get_cookie) 181185b4595SMarouene Boubakri return mobj->ops->get_cookie(mobj); 182185b4595SMarouene Boubakri 183e26b8354SJens Wiklander #if defined(CFG_CORE_FFA) 184c1bdf4fcSJens Wiklander return OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; 185c1bdf4fcSJens Wiklander #else 186185b4595SMarouene Boubakri return 0; 187c1bdf4fcSJens Wiklander #endif 188185b4595SMarouene Boubakri } 189185b4595SMarouene Boubakri 190185b4595SMarouene Boubakri static inline struct fobj *mobj_get_fobj(struct mobj *mobj) 191185b4595SMarouene Boubakri { 192185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->get_fobj) 193185b4595SMarouene Boubakri return mobj->ops->get_fobj(mobj); 194185b4595SMarouene Boubakri 195185b4595SMarouene Boubakri return NULL; 196185b4595SMarouene Boubakri } 197185b4595SMarouene Boubakri 198185b4595SMarouene Boubakri static inline bool mobj_is_nonsec(struct mobj *mobj) 199185b4595SMarouene Boubakri { 200185b4595SMarouene Boubakri return mobj_matches(mobj, CORE_MEM_NON_SEC); 201185b4595SMarouene Boubakri } 202185b4595SMarouene Boubakri 203185b4595SMarouene Boubakri static inline bool mobj_is_secure(struct mobj *mobj) 204185b4595SMarouene Boubakri { 205185b4595SMarouene Boubakri return mobj_matches(mobj, CORE_MEM_SEC); 206185b4595SMarouene Boubakri } 207185b4595SMarouene Boubakri 208185b4595SMarouene Boubakri static inline bool mobj_is_sdp_mem(struct mobj *mobj) 209185b4595SMarouene Boubakri { 210185b4595SMarouene Boubakri return mobj_matches(mobj, CORE_MEM_SDP_MEM); 211185b4595SMarouene Boubakri } 212185b4595SMarouene Boubakri 213185b4595SMarouene Boubakri static inline size_t mobj_get_phys_granule(struct mobj *mobj) 214185b4595SMarouene Boubakri { 215185b4595SMarouene Boubakri if (mobj->phys_granule) 216185b4595SMarouene Boubakri return mobj->phys_granule; 217185b4595SMarouene Boubakri return mobj->size; 218185b4595SMarouene Boubakri } 219185b4595SMarouene Boubakri 2209c4aaf67SJens Wiklander static inline bool mobj_check_offset_and_len(struct mobj *mobj, size_t offset, 2219c4aaf67SJens Wiklander size_t len) 2229c4aaf67SJens Wiklander { 2239c4aaf67SJens Wiklander size_t end_offs = 0; 2249c4aaf67SJens Wiklander 2259c4aaf67SJens Wiklander return len && !ADD_OVERFLOW(offset, len - 1, &end_offs) && 2269c4aaf67SJens Wiklander end_offs < mobj->size; 2279c4aaf67SJens Wiklander } 2289c4aaf67SJens Wiklander 229185b4595SMarouene Boubakri struct mobj *mobj_mm_alloc(struct mobj *mobj_parent, size_t size, 230185b4595SMarouene Boubakri tee_mm_pool_t *pool); 231185b4595SMarouene Boubakri 232185b4595SMarouene Boubakri struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr, 233185b4595SMarouene Boubakri enum buf_is_attr battr); 234185b4595SMarouene Boubakri 235185b4595SMarouene Boubakri #if defined(CFG_CORE_FFA) 236185b4595SMarouene Boubakri struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, 237185b4595SMarouene Boubakri unsigned int internal_offs); 238185b4595SMarouene Boubakri 239185b4595SMarouene Boubakri TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie); 240185b4595SMarouene Boubakri 241185b4595SMarouene Boubakri /* Functions for SPMC */ 242185b4595SMarouene Boubakri #ifdef CFG_CORE_SEL1_SPMC 243185b4595SMarouene Boubakri struct mobj_ffa *mobj_ffa_sel1_spmc_new(unsigned int num_pages); 244185b4595SMarouene Boubakri void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mobj); 245185b4595SMarouene Boubakri TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie); 246e26b8354SJens Wiklander #else 247e26b8354SJens Wiklander struct mobj_ffa *mobj_ffa_spmc_new(uint64_t cookie, unsigned int num_pages); 248e26b8354SJens Wiklander void mobj_ffa_spmc_delete(struct mobj_ffa *mobj); 249fb19e98eSJens Wiklander #endif 250fb19e98eSJens Wiklander 251185b4595SMarouene Boubakri uint64_t mobj_ffa_get_cookie(struct mobj_ffa *mobj); 252185b4595SMarouene Boubakri TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mobj, unsigned int *idx, 253185b4595SMarouene Boubakri paddr_t pa, unsigned int num_pages); 254185b4595SMarouene Boubakri uint64_t mobj_ffa_push_to_inactive(struct mobj_ffa *mobj); 255185b4595SMarouene Boubakri 256185b4595SMarouene Boubakri #elif defined(CFG_CORE_DYN_SHM) 257185b4595SMarouene Boubakri /* reg_shm represents TEE shared memory */ 258185b4595SMarouene Boubakri struct mobj *mobj_reg_shm_alloc(paddr_t *pages, size_t num_pages, 259185b4595SMarouene Boubakri paddr_t page_offset, uint64_t cookie); 260185b4595SMarouene Boubakri 261185b4595SMarouene Boubakri /** 262185b4595SMarouene Boubakri * mobj_reg_shm_get_by_cookie() - get a MOBJ based on cookie 263185b4595SMarouene Boubakri * @cookie: Cookie used by normal world when suppling the shared memory 264185b4595SMarouene Boubakri * 265185b4595SMarouene Boubakri * Searches for a registered shared memory MOBJ and if one with a matching 266185b4595SMarouene Boubakri * @cookie is found its reference counter is increased before returning 267185b4595SMarouene Boubakri * the MOBJ. 268185b4595SMarouene Boubakri * 269185b4595SMarouene Boubakri * Returns a valid pointer on success or NULL on failure. 270185b4595SMarouene Boubakri */ 271185b4595SMarouene Boubakri struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie); 272185b4595SMarouene Boubakri 273185b4595SMarouene Boubakri TEE_Result mobj_reg_shm_release_by_cookie(uint64_t cookie); 274185b4595SMarouene Boubakri 275185b4595SMarouene Boubakri /** 276185b4595SMarouene Boubakri * mobj_reg_shm_unguard() - unguards a reg_shm 277185b4595SMarouene Boubakri * @mobj: pointer to a registered shared memory mobj 278185b4595SMarouene Boubakri * 279185b4595SMarouene Boubakri * A registered shared memory mobj is normally guarded against being 280185b4595SMarouene Boubakri * released with mobj_reg_shm_try_release_by_cookie(). After this function 281185b4595SMarouene Boubakri * has returned the mobj can be released by a call to 282185b4595SMarouene Boubakri * mobj_reg_shm_try_release_by_cookie() if the reference counter allows it. 283185b4595SMarouene Boubakri */ 284185b4595SMarouene Boubakri void mobj_reg_shm_unguard(struct mobj *mobj); 285185b4595SMarouene Boubakri 286185b4595SMarouene Boubakri /* 287185b4595SMarouene Boubakri * mapped_shm represents registered shared buffer 288185b4595SMarouene Boubakri * which is mapped into OPTEE va space 289185b4595SMarouene Boubakri */ 290185b4595SMarouene Boubakri struct mobj *mobj_mapped_shm_alloc(paddr_t *pages, size_t num_pages, 291185b4595SMarouene Boubakri paddr_t page_offset, uint64_t cookie); 292185b4595SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/ 293185b4595SMarouene Boubakri 294185b4595SMarouene Boubakri #if !defined(CFG_CORE_DYN_SHM) 295185b4595SMarouene Boubakri static inline struct mobj *mobj_mapped_shm_alloc(paddr_t *pages __unused, 296185b4595SMarouene Boubakri size_t num_pages __unused, 297185b4595SMarouene Boubakri paddr_t page_offset __unused, 298185b4595SMarouene Boubakri uint64_t cookie __unused) 299185b4595SMarouene Boubakri { 300185b4595SMarouene Boubakri return NULL; 301185b4595SMarouene Boubakri } 30264b74defSJens Wiklander 30364b74defSJens Wiklander static inline struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie __unused) 30464b74defSJens Wiklander { 30564b74defSJens Wiklander return NULL; 30664b74defSJens Wiklander } 307185b4595SMarouene Boubakri #endif 308185b4595SMarouene Boubakri 309185b4595SMarouene Boubakri struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie); 310185b4595SMarouene Boubakri 311185b4595SMarouene Boubakri #ifdef CFG_PAGED_USER_TA 312185b4595SMarouene Boubakri bool mobj_is_paged(struct mobj *mobj); 313185b4595SMarouene Boubakri #else 314185b4595SMarouene Boubakri static inline bool mobj_is_paged(struct mobj *mobj __unused) 315185b4595SMarouene Boubakri { 316185b4595SMarouene Boubakri return false; 317185b4595SMarouene Boubakri } 318185b4595SMarouene Boubakri #endif 319185b4595SMarouene Boubakri 320185b4595SMarouene Boubakri struct mobj *mobj_seccpy_shm_alloc(size_t size); 321185b4595SMarouene Boubakri 322185b4595SMarouene Boubakri struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file); 323185b4595SMarouene Boubakri 324185b4595SMarouene Boubakri #endif /*__MM_MOBJ_H*/ 325