1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright (c) 2016-2017, Linaro Limited 4 */ 5 6 #ifndef __MM_MOBJ_H 7 #define __MM_MOBJ_H 8 9 #include <compiler.h> 10 #include <mm/core_memprot.h> 11 #include <mm/file.h> 12 #include <mm/fobj.h> 13 #include <string_ext.h> 14 #include <sys/queue.h> 15 #include <tee_api_types.h> 16 #include <types_ext.h> 17 18 #include <optee_msg.h> 19 20 struct mobj { 21 const struct mobj_ops *ops; 22 size_t size; 23 size_t phys_granule; 24 struct refcount refc; 25 }; 26 27 struct mobj_ops { 28 void *(*get_va)(struct mobj *mobj, size_t offs); 29 TEE_Result (*get_pa)(struct mobj *mobj, size_t offs, size_t granule, 30 paddr_t *pa); 31 size_t (*get_phys_offs)(struct mobj *mobj, size_t granule); 32 TEE_Result (*get_cattr)(struct mobj *mobj, uint32_t *cattr); 33 bool (*matches)(struct mobj *mobj, enum buf_is_attr attr); 34 void (*free)(struct mobj *mobj); 35 uint64_t (*get_cookie)(struct mobj *mobj); 36 struct fobj *(*get_fobj)(struct mobj *mobj); 37 TEE_Result (*inc_map)(struct mobj *mobj); 38 TEE_Result (*dec_map)(struct mobj *mobj); 39 }; 40 41 extern struct mobj mobj_virt; 42 extern struct mobj *mobj_sec_ddr; 43 extern struct mobj *mobj_tee_ram; 44 45 static inline void *mobj_get_va(struct mobj *mobj, size_t offset) 46 { 47 if (mobj && mobj->ops && mobj->ops->get_va) 48 return mobj->ops->get_va(mobj, offset); 49 return NULL; 50 } 51 52 static inline TEE_Result mobj_get_pa(struct mobj *mobj, size_t offs, 53 size_t granule, paddr_t *pa) 54 { 55 if (mobj && mobj->ops && mobj->ops->get_pa) 56 return mobj->ops->get_pa(mobj, offs, granule, pa); 57 return TEE_ERROR_GENERIC; 58 } 59 60 static inline size_t mobj_get_phys_offs(struct mobj *mobj, size_t granule) 61 { 62 if (mobj && mobj->ops && mobj->ops->get_phys_offs) 63 return mobj->ops->get_phys_offs(mobj, granule); 64 return 0; 65 } 66 67 static inline TEE_Result mobj_get_cattr(struct mobj *mobj, uint32_t *cattr) 68 { 69 if (mobj && mobj->ops && mobj->ops->get_cattr) 70 return mobj->ops->get_cattr(mobj, cattr); 71 return TEE_ERROR_GENERIC; 72 } 73 74 static inline bool mobj_matches(struct mobj *mobj, enum buf_is_attr attr) 75 { 76 if (mobj && mobj->ops && mobj->ops->matches) 77 return mobj->ops->matches(mobj, attr); 78 return false; 79 } 80 81 /** 82 * mobj_inc_map() - increase map count 83 * @mobj: pointer to a MOBJ 84 * 85 * Maps the MOBJ if it isn't mapped already and increases the map count 86 * Each call to mobj_inc_map() is supposed to be matches by a call to 87 * mobj_dec_map(). 88 * 89 * Returns TEE_SUCCESS on success or an error code on failure 90 */ 91 static inline TEE_Result mobj_inc_map(struct mobj *mobj) 92 { 93 if (mobj && mobj->ops) { 94 if (mobj->ops->inc_map) 95 return mobj->ops->inc_map(mobj); 96 return TEE_SUCCESS; 97 } 98 return TEE_ERROR_GENERIC; 99 } 100 101 /** 102 * mobj_dec_map() - decrease map count 103 * @mobj: pointer to a MOBJ 104 * 105 * Decreases the map count and also unmaps the MOBJ if the map count 106 * reaches 0. Each call to mobj_inc_map() is supposed to be matched by a 107 * call to mobj_dec_map(). 108 * 109 * Returns TEE_SUCCESS on success or an error code on failure 110 */ 111 static inline TEE_Result mobj_dec_map(struct mobj *mobj) 112 { 113 if (mobj && mobj->ops) { 114 if (mobj->ops->dec_map) 115 return mobj->ops->dec_map(mobj); 116 return TEE_SUCCESS; 117 } 118 return TEE_ERROR_GENERIC; 119 } 120 121 /** 122 * mobj_get() - get a MOBJ 123 * @mobj: Pointer to a MOBJ or NULL 124 * 125 * Increases reference counter of the @mobj 126 * 127 * Returns @mobj with reference counter increased or NULL if @mobj was NULL 128 */ 129 static inline struct mobj *mobj_get(struct mobj *mobj) 130 { 131 if (mobj && !refcount_inc(&mobj->refc)) 132 panic(); 133 134 return mobj; 135 } 136 137 /** 138 * mobj_put() - put a MOBJ 139 * @mobj: Pointer to a MOBJ or NULL 140 * 141 * Decreases reference counter of the @mobj and frees it if the counter 142 * reaches 0. 143 */ 144 static inline void mobj_put(struct mobj *mobj) 145 { 146 if (mobj && refcount_dec(&mobj->refc)) 147 mobj->ops->free(mobj); 148 } 149 150 /** 151 * mobj_put_wipe() - wipe and put a MOBJ 152 * @mobj: Pointer to a MOBJ or NULL 153 * 154 * Clears the memory represented by the mobj and then puts it. 155 */ 156 static inline void mobj_put_wipe(struct mobj *mobj) 157 { 158 void *buf = mobj_get_va(mobj, 0); 159 160 if (buf) 161 memzero_explicit(buf, mobj->size); 162 mobj_put(mobj); 163 } 164 165 static inline uint64_t mobj_get_cookie(struct mobj *mobj) 166 { 167 if (mobj && mobj->ops && mobj->ops->get_cookie) 168 return mobj->ops->get_cookie(mobj); 169 170 #if defined(CFG_CORE_SEL1_SPMC) || defined(CFG_CORE_SEL2_SPMC) 171 return OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; 172 #else 173 return 0; 174 #endif 175 } 176 177 static inline struct fobj *mobj_get_fobj(struct mobj *mobj) 178 { 179 if (mobj && mobj->ops && mobj->ops->get_fobj) 180 return mobj->ops->get_fobj(mobj); 181 182 return NULL; 183 } 184 185 static inline bool mobj_is_nonsec(struct mobj *mobj) 186 { 187 return mobj_matches(mobj, CORE_MEM_NON_SEC); 188 } 189 190 static inline bool mobj_is_secure(struct mobj *mobj) 191 { 192 return mobj_matches(mobj, CORE_MEM_SEC); 193 } 194 195 static inline bool mobj_is_sdp_mem(struct mobj *mobj) 196 { 197 return mobj_matches(mobj, CORE_MEM_SDP_MEM); 198 } 199 200 static inline size_t mobj_get_phys_granule(struct mobj *mobj) 201 { 202 if (mobj->phys_granule) 203 return mobj->phys_granule; 204 return mobj->size; 205 } 206 207 struct mobj *mobj_mm_alloc(struct mobj *mobj_parent, size_t size, 208 tee_mm_pool_t *pool); 209 210 struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr, 211 enum buf_is_attr battr); 212 213 #if defined(CFG_CORE_FFA) 214 struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, 215 unsigned int internal_offs); 216 217 TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie); 218 219 /* Functions for SPMC */ 220 #ifdef CFG_CORE_SEL1_SPMC 221 struct mobj_ffa *mobj_ffa_sel1_spmc_new(unsigned int num_pages); 222 void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mobj); 223 TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie); 224 #endif 225 #ifdef CFG_CORE_SEL2_SPMC 226 struct mobj_ffa *mobj_ffa_sel2_spmc_new(uint64_t cookie, 227 unsigned int num_pages); 228 void mobj_ffa_sel2_spmc_delete(struct mobj_ffa *mobj); 229 #endif 230 231 uint64_t mobj_ffa_get_cookie(struct mobj_ffa *mobj); 232 TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mobj, unsigned int *idx, 233 paddr_t pa, unsigned int num_pages); 234 uint64_t mobj_ffa_push_to_inactive(struct mobj_ffa *mobj); 235 236 #elif defined(CFG_CORE_DYN_SHM) 237 /* reg_shm represents TEE shared memory */ 238 struct mobj *mobj_reg_shm_alloc(paddr_t *pages, size_t num_pages, 239 paddr_t page_offset, uint64_t cookie); 240 241 /** 242 * mobj_reg_shm_get_by_cookie() - get a MOBJ based on cookie 243 * @cookie: Cookie used by normal world when suppling the shared memory 244 * 245 * Searches for a registered shared memory MOBJ and if one with a matching 246 * @cookie is found its reference counter is increased before returning 247 * the MOBJ. 248 * 249 * Returns a valid pointer on success or NULL on failure. 250 */ 251 struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie); 252 253 TEE_Result mobj_reg_shm_release_by_cookie(uint64_t cookie); 254 255 /** 256 * mobj_reg_shm_unguard() - unguards a reg_shm 257 * @mobj: pointer to a registered shared memory mobj 258 * 259 * A registered shared memory mobj is normally guarded against being 260 * released with mobj_reg_shm_try_release_by_cookie(). After this function 261 * has returned the mobj can be released by a call to 262 * mobj_reg_shm_try_release_by_cookie() if the reference counter allows it. 263 */ 264 void mobj_reg_shm_unguard(struct mobj *mobj); 265 266 /* 267 * mapped_shm represents registered shared buffer 268 * which is mapped into OPTEE va space 269 */ 270 struct mobj *mobj_mapped_shm_alloc(paddr_t *pages, size_t num_pages, 271 paddr_t page_offset, uint64_t cookie); 272 #endif /*CFG_CORE_DYN_SHM*/ 273 274 #if !defined(CFG_CORE_DYN_SHM) 275 static inline struct mobj *mobj_mapped_shm_alloc(paddr_t *pages __unused, 276 size_t num_pages __unused, 277 paddr_t page_offset __unused, 278 uint64_t cookie __unused) 279 { 280 return NULL; 281 } 282 #endif 283 284 struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie); 285 286 #ifdef CFG_PAGED_USER_TA 287 bool mobj_is_paged(struct mobj *mobj); 288 #else 289 static inline bool mobj_is_paged(struct mobj *mobj __unused) 290 { 291 return false; 292 } 293 #endif 294 295 struct mobj *mobj_seccpy_shm_alloc(size_t size); 296 297 struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file); 298 299 #endif /*__MM_MOBJ_H*/ 300