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