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