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