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 18*c1bdf4fcSJens Wiklander #include <optee_msg.h> 19*c1bdf4fcSJens 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 { 28185b4595SMarouene Boubakri void *(*get_va)(struct mobj *mobj, size_t offs); 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); 32185b4595SMarouene Boubakri TEE_Result (*get_cattr)(struct mobj *mobj, uint32_t *cattr); 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; 43185b4595SMarouene Boubakri extern struct mobj *mobj_tee_ram; 44185b4595SMarouene Boubakri 45185b4595SMarouene Boubakri static inline void *mobj_get_va(struct mobj *mobj, size_t offset) 46185b4595SMarouene Boubakri { 47185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->get_va) 48185b4595SMarouene Boubakri return mobj->ops->get_va(mobj, offset); 49185b4595SMarouene Boubakri return NULL; 50185b4595SMarouene Boubakri } 51185b4595SMarouene Boubakri 52185b4595SMarouene Boubakri static inline TEE_Result mobj_get_pa(struct mobj *mobj, size_t offs, 53185b4595SMarouene Boubakri size_t granule, paddr_t *pa) 54185b4595SMarouene Boubakri { 55185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->get_pa) 56185b4595SMarouene Boubakri return mobj->ops->get_pa(mobj, offs, granule, pa); 57185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 58185b4595SMarouene Boubakri } 59185b4595SMarouene Boubakri 60185b4595SMarouene Boubakri static inline size_t mobj_get_phys_offs(struct mobj *mobj, size_t granule) 61185b4595SMarouene Boubakri { 62185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->get_phys_offs) 63185b4595SMarouene Boubakri return mobj->ops->get_phys_offs(mobj, granule); 64185b4595SMarouene Boubakri return 0; 65185b4595SMarouene Boubakri } 66185b4595SMarouene Boubakri 67185b4595SMarouene Boubakri static inline TEE_Result mobj_get_cattr(struct mobj *mobj, uint32_t *cattr) 68185b4595SMarouene Boubakri { 69185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->get_cattr) 70185b4595SMarouene Boubakri return mobj->ops->get_cattr(mobj, cattr); 71185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 72185b4595SMarouene Boubakri } 73185b4595SMarouene Boubakri 74185b4595SMarouene Boubakri static inline bool mobj_matches(struct mobj *mobj, enum buf_is_attr attr) 75185b4595SMarouene Boubakri { 76185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->matches) 77185b4595SMarouene Boubakri return mobj->ops->matches(mobj, attr); 78185b4595SMarouene Boubakri return false; 79185b4595SMarouene Boubakri } 80185b4595SMarouene Boubakri 81185b4595SMarouene Boubakri /** 82185b4595SMarouene Boubakri * mobj_inc_map() - increase map count 83185b4595SMarouene Boubakri * @mobj: pointer to a MOBJ 84185b4595SMarouene Boubakri * 85185b4595SMarouene Boubakri * Maps the MOBJ if it isn't mapped already and increases the map count 86185b4595SMarouene Boubakri * Each call to mobj_inc_map() is supposed to be matches by a call to 87185b4595SMarouene Boubakri * mobj_dec_map(). 88185b4595SMarouene Boubakri * 89185b4595SMarouene Boubakri * Returns TEE_SUCCESS on success or an error code on failure 90185b4595SMarouene Boubakri */ 91185b4595SMarouene Boubakri static inline TEE_Result mobj_inc_map(struct mobj *mobj) 92185b4595SMarouene Boubakri { 93185b4595SMarouene Boubakri if (mobj && mobj->ops) { 94185b4595SMarouene Boubakri if (mobj->ops->inc_map) 95185b4595SMarouene Boubakri return mobj->ops->inc_map(mobj); 96185b4595SMarouene Boubakri return TEE_SUCCESS; 97185b4595SMarouene Boubakri } 98185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 99185b4595SMarouene Boubakri } 100185b4595SMarouene Boubakri 101185b4595SMarouene Boubakri /** 102185b4595SMarouene Boubakri * mobj_dec_map() - decrease map count 103185b4595SMarouene Boubakri * @mobj: pointer to a MOBJ 104185b4595SMarouene Boubakri * 105185b4595SMarouene Boubakri * Decreases the map count and also unmaps the MOBJ if the map count 106185b4595SMarouene Boubakri * reaches 0. Each call to mobj_inc_map() is supposed to be matched by a 107185b4595SMarouene Boubakri * call to mobj_dec_map(). 108185b4595SMarouene Boubakri * 109185b4595SMarouene Boubakri * Returns TEE_SUCCESS on success or an error code on failure 110185b4595SMarouene Boubakri */ 111185b4595SMarouene Boubakri static inline TEE_Result mobj_dec_map(struct mobj *mobj) 112185b4595SMarouene Boubakri { 113185b4595SMarouene Boubakri if (mobj && mobj->ops) { 114185b4595SMarouene Boubakri if (mobj->ops->dec_map) 115185b4595SMarouene Boubakri return mobj->ops->dec_map(mobj); 116185b4595SMarouene Boubakri return TEE_SUCCESS; 117185b4595SMarouene Boubakri } 118185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 119185b4595SMarouene Boubakri } 120185b4595SMarouene Boubakri 121185b4595SMarouene Boubakri /** 122185b4595SMarouene Boubakri * mobj_get() - get a MOBJ 123185b4595SMarouene Boubakri * @mobj: Pointer to a MOBJ or NULL 124185b4595SMarouene Boubakri * 125185b4595SMarouene Boubakri * Increases reference counter of the @mobj 126185b4595SMarouene Boubakri * 127185b4595SMarouene Boubakri * Returns @mobj with reference counter increased or NULL if @mobj was NULL 128185b4595SMarouene Boubakri */ 129185b4595SMarouene Boubakri static inline struct mobj *mobj_get(struct mobj *mobj) 130185b4595SMarouene Boubakri { 131185b4595SMarouene Boubakri if (mobj && !refcount_inc(&mobj->refc)) 132185b4595SMarouene Boubakri panic(); 133185b4595SMarouene Boubakri 134185b4595SMarouene Boubakri return mobj; 135185b4595SMarouene Boubakri } 136185b4595SMarouene Boubakri 137185b4595SMarouene Boubakri /** 138185b4595SMarouene Boubakri * mobj_put() - put a MOBJ 139185b4595SMarouene Boubakri * @mobj: Pointer to a MOBJ or NULL 140185b4595SMarouene Boubakri * 141185b4595SMarouene Boubakri * Decreases reference counter of the @mobj and frees it if the counter 142185b4595SMarouene Boubakri * reaches 0. 143185b4595SMarouene Boubakri */ 144185b4595SMarouene Boubakri static inline void mobj_put(struct mobj *mobj) 145185b4595SMarouene Boubakri { 146185b4595SMarouene Boubakri if (mobj && refcount_dec(&mobj->refc)) 147185b4595SMarouene Boubakri mobj->ops->free(mobj); 148185b4595SMarouene Boubakri } 149185b4595SMarouene Boubakri 150185b4595SMarouene Boubakri /** 151185b4595SMarouene Boubakri * mobj_put_wipe() - wipe and put a MOBJ 152185b4595SMarouene Boubakri * @mobj: Pointer to a MOBJ or NULL 153185b4595SMarouene Boubakri * 154185b4595SMarouene Boubakri * Clears the memory represented by the mobj and then puts it. 155185b4595SMarouene Boubakri */ 156185b4595SMarouene Boubakri static inline void mobj_put_wipe(struct mobj *mobj) 157185b4595SMarouene Boubakri { 158185b4595SMarouene Boubakri void *buf = mobj_get_va(mobj, 0); 159185b4595SMarouene Boubakri 160185b4595SMarouene Boubakri if (buf) 161185b4595SMarouene Boubakri memzero_explicit(buf, mobj->size); 162185b4595SMarouene Boubakri mobj_put(mobj); 163185b4595SMarouene Boubakri } 164185b4595SMarouene Boubakri 165185b4595SMarouene Boubakri static inline uint64_t mobj_get_cookie(struct mobj *mobj) 166185b4595SMarouene Boubakri { 167185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->get_cookie) 168185b4595SMarouene Boubakri return mobj->ops->get_cookie(mobj); 169185b4595SMarouene Boubakri 170*c1bdf4fcSJens Wiklander #if defined(CFG_CORE_SEL1_SPMC) || defined(CFG_CORE_SEL2_SPMC) 171*c1bdf4fcSJens Wiklander return OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; 172*c1bdf4fcSJens Wiklander #else 173185b4595SMarouene Boubakri return 0; 174*c1bdf4fcSJens Wiklander #endif 175185b4595SMarouene Boubakri } 176185b4595SMarouene Boubakri 177185b4595SMarouene Boubakri static inline struct fobj *mobj_get_fobj(struct mobj *mobj) 178185b4595SMarouene Boubakri { 179185b4595SMarouene Boubakri if (mobj && mobj->ops && mobj->ops->get_fobj) 180185b4595SMarouene Boubakri return mobj->ops->get_fobj(mobj); 181185b4595SMarouene Boubakri 182185b4595SMarouene Boubakri return NULL; 183185b4595SMarouene Boubakri } 184185b4595SMarouene Boubakri 185185b4595SMarouene Boubakri static inline bool mobj_is_nonsec(struct mobj *mobj) 186185b4595SMarouene Boubakri { 187185b4595SMarouene Boubakri return mobj_matches(mobj, CORE_MEM_NON_SEC); 188185b4595SMarouene Boubakri } 189185b4595SMarouene Boubakri 190185b4595SMarouene Boubakri static inline bool mobj_is_secure(struct mobj *mobj) 191185b4595SMarouene Boubakri { 192185b4595SMarouene Boubakri return mobj_matches(mobj, CORE_MEM_SEC); 193185b4595SMarouene Boubakri } 194185b4595SMarouene Boubakri 195185b4595SMarouene Boubakri static inline bool mobj_is_sdp_mem(struct mobj *mobj) 196185b4595SMarouene Boubakri { 197185b4595SMarouene Boubakri return mobj_matches(mobj, CORE_MEM_SDP_MEM); 198185b4595SMarouene Boubakri } 199185b4595SMarouene Boubakri 200185b4595SMarouene Boubakri static inline size_t mobj_get_phys_granule(struct mobj *mobj) 201185b4595SMarouene Boubakri { 202185b4595SMarouene Boubakri if (mobj->phys_granule) 203185b4595SMarouene Boubakri return mobj->phys_granule; 204185b4595SMarouene Boubakri return mobj->size; 205185b4595SMarouene Boubakri } 206185b4595SMarouene Boubakri 207185b4595SMarouene Boubakri struct mobj *mobj_mm_alloc(struct mobj *mobj_parent, size_t size, 208185b4595SMarouene Boubakri tee_mm_pool_t *pool); 209185b4595SMarouene Boubakri 210185b4595SMarouene Boubakri struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr, 211185b4595SMarouene Boubakri enum buf_is_attr battr); 212185b4595SMarouene Boubakri 213185b4595SMarouene Boubakri #if defined(CFG_CORE_FFA) 214185b4595SMarouene Boubakri struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, 215185b4595SMarouene Boubakri unsigned int internal_offs); 216185b4595SMarouene Boubakri 217185b4595SMarouene Boubakri TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie); 218185b4595SMarouene Boubakri 219185b4595SMarouene Boubakri /* Functions for SPMC */ 220185b4595SMarouene Boubakri #ifdef CFG_CORE_SEL1_SPMC 221185b4595SMarouene Boubakri struct mobj_ffa *mobj_ffa_sel1_spmc_new(unsigned int num_pages); 222185b4595SMarouene Boubakri void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mobj); 223185b4595SMarouene Boubakri TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie); 224185b4595SMarouene Boubakri #endif 225185b4595SMarouene Boubakri uint64_t mobj_ffa_get_cookie(struct mobj_ffa *mobj); 226185b4595SMarouene Boubakri TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mobj, unsigned int *idx, 227185b4595SMarouene Boubakri paddr_t pa, unsigned int num_pages); 228185b4595SMarouene Boubakri uint64_t mobj_ffa_push_to_inactive(struct mobj_ffa *mobj); 229185b4595SMarouene Boubakri 230185b4595SMarouene Boubakri #elif defined(CFG_CORE_DYN_SHM) 231185b4595SMarouene Boubakri /* reg_shm represents TEE shared memory */ 232185b4595SMarouene Boubakri struct mobj *mobj_reg_shm_alloc(paddr_t *pages, size_t num_pages, 233185b4595SMarouene Boubakri paddr_t page_offset, uint64_t cookie); 234185b4595SMarouene Boubakri 235185b4595SMarouene Boubakri /** 236185b4595SMarouene Boubakri * mobj_reg_shm_get_by_cookie() - get a MOBJ based on cookie 237185b4595SMarouene Boubakri * @cookie: Cookie used by normal world when suppling the shared memory 238185b4595SMarouene Boubakri * 239185b4595SMarouene Boubakri * Searches for a registered shared memory MOBJ and if one with a matching 240185b4595SMarouene Boubakri * @cookie is found its reference counter is increased before returning 241185b4595SMarouene Boubakri * the MOBJ. 242185b4595SMarouene Boubakri * 243185b4595SMarouene Boubakri * Returns a valid pointer on success or NULL on failure. 244185b4595SMarouene Boubakri */ 245185b4595SMarouene Boubakri struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie); 246185b4595SMarouene Boubakri 247185b4595SMarouene Boubakri TEE_Result mobj_reg_shm_release_by_cookie(uint64_t cookie); 248185b4595SMarouene Boubakri 249185b4595SMarouene Boubakri /** 250185b4595SMarouene Boubakri * mobj_reg_shm_unguard() - unguards a reg_shm 251185b4595SMarouene Boubakri * @mobj: pointer to a registered shared memory mobj 252185b4595SMarouene Boubakri * 253185b4595SMarouene Boubakri * A registered shared memory mobj is normally guarded against being 254185b4595SMarouene Boubakri * released with mobj_reg_shm_try_release_by_cookie(). After this function 255185b4595SMarouene Boubakri * has returned the mobj can be released by a call to 256185b4595SMarouene Boubakri * mobj_reg_shm_try_release_by_cookie() if the reference counter allows it. 257185b4595SMarouene Boubakri */ 258185b4595SMarouene Boubakri void mobj_reg_shm_unguard(struct mobj *mobj); 259185b4595SMarouene Boubakri 260185b4595SMarouene Boubakri /* 261185b4595SMarouene Boubakri * mapped_shm represents registered shared buffer 262185b4595SMarouene Boubakri * which is mapped into OPTEE va space 263185b4595SMarouene Boubakri */ 264185b4595SMarouene Boubakri struct mobj *mobj_mapped_shm_alloc(paddr_t *pages, size_t num_pages, 265185b4595SMarouene Boubakri paddr_t page_offset, uint64_t cookie); 266185b4595SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/ 267185b4595SMarouene Boubakri 268185b4595SMarouene Boubakri #if !defined(CFG_CORE_DYN_SHM) 269185b4595SMarouene Boubakri static inline struct mobj *mobj_mapped_shm_alloc(paddr_t *pages __unused, 270185b4595SMarouene Boubakri size_t num_pages __unused, 271185b4595SMarouene Boubakri paddr_t page_offset __unused, 272185b4595SMarouene Boubakri uint64_t cookie __unused) 273185b4595SMarouene Boubakri { 274185b4595SMarouene Boubakri return NULL; 275185b4595SMarouene Boubakri } 276185b4595SMarouene Boubakri #endif 277185b4595SMarouene Boubakri 278185b4595SMarouene Boubakri struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie); 279185b4595SMarouene Boubakri 280185b4595SMarouene Boubakri #ifdef CFG_PAGED_USER_TA 281185b4595SMarouene Boubakri bool mobj_is_paged(struct mobj *mobj); 282185b4595SMarouene Boubakri #else 283185b4595SMarouene Boubakri static inline bool mobj_is_paged(struct mobj *mobj __unused) 284185b4595SMarouene Boubakri { 285185b4595SMarouene Boubakri return false; 286185b4595SMarouene Boubakri } 287185b4595SMarouene Boubakri #endif 288185b4595SMarouene Boubakri 289185b4595SMarouene Boubakri struct mobj *mobj_seccpy_shm_alloc(size_t size); 290185b4595SMarouene Boubakri 291185b4595SMarouene Boubakri struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file); 292185b4595SMarouene Boubakri 293185b4595SMarouene Boubakri #endif /*__MM_MOBJ_H*/ 294