1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright (c) 2016-2021, Linaro Limited 4 * Copyright (c) 2014, STMicroelectronics International N.V. 5 */ 6 7 #ifndef MM_TEE_PAGER_H 8 #define MM_TEE_PAGER_H 9 10 #include <kernel/abort.h> 11 #include <kernel/panic.h> 12 #include <kernel/user_ta.h> 13 #include <mm/core_mmu.h> 14 #include <mm/tee_mm.h> 15 #include <string.h> 16 #include <trace.h> 17 18 /* 19 * tee_pager_early_init() - Perform early initialization of pager 20 * 21 * Panics if some error occurs 22 */ 23 void tee_pager_early_init(void); 24 25 /* 26 * tee_pager_get_table_info() - Fills in table info for address mapped in 27 * translation table managed by the pager. 28 * @va: address to look up 29 * @ti: filled in table info 30 * 31 * Returns true if address is in the pager translation tables else false 32 */ 33 bool tee_pager_get_table_info(vaddr_t va, struct core_mmu_table_info *ti); 34 35 /* 36 * tee_pager_phys_to_virt() - Translate physical address to virtual address 37 * looking in the pager page tables 38 * @pa: address to translate 39 * @len: check for length is mapped linearly in CORE_MMU_PGDIR_SIZE range 40 * 41 * Returns found virtual address or NULL on error 42 */ 43 void *tee_pager_phys_to_virt(paddr_t pa, size_t len); 44 45 /* 46 * tee_pager_set_alias_area() - Initialize pager alias area 47 * @mm_alias: The alias area where all physical pages managed by the 48 * pager are aliased 49 * 50 * Panics if called twice or some other error occurs. 51 */ 52 void tee_pager_set_alias_area(tee_mm_entry_t *mm_alias); 53 54 /* 55 * tee_pager_init_iv_region() - Initialized pager region for tags IVs used by RW 56 * paged fobjs 57 * @fobj: fobj backing the region 58 * 59 * Panics if called twice or some other error occurs. 60 * 61 * Returns virtual address of start of IV region. 62 */ 63 vaddr_t tee_pager_init_iv_region(struct fobj *fobj); 64 65 /* 66 * tee_pager_generate_authenc_key() - Generates authenc key for r/w paging 67 * 68 * Needs to draw random from RNG, panics if some error occurs. 69 */ 70 #ifdef CFG_WITH_PAGER 71 void tee_pager_generate_authenc_key(void); 72 #else 73 static inline void tee_pager_generate_authenc_key(void) 74 { 75 } 76 #endif 77 78 /* 79 * tee_pager_add_core_region() - Adds a pageable core region 80 * @base: base of covered memory region 81 * @type: type of memory region 82 * @fobj: fobj backing the region 83 * 84 * Non-page aligned base or size will cause a panic. 85 */ 86 void tee_pager_add_core_region(vaddr_t base, enum vm_paged_region_type type, 87 struct fobj *fobj); 88 89 /* 90 * tee_pager_add_um_region() - Adds a pageable user TA region 91 * @uctx: user mode context of the region 92 * @base: base of covered memory region 93 * @fobj: fobj of the store backing the memory region 94 * 95 * The mapping is created suitable to initialize the memory content while 96 * loading the TA. Once the TA is properly loaded the regions should be 97 * finalized with tee_pager_set_um_region_attr() to get more strict settings. 98 * 99 * Return TEE_SUCCESS on success, anything else if the region can't be added 100 */ 101 #ifdef CFG_PAGED_USER_TA 102 TEE_Result tee_pager_add_um_region(struct user_mode_ctx *uctx, vaddr_t base, 103 struct fobj *fobj, uint32_t prot); 104 #else 105 static inline TEE_Result 106 tee_pager_add_um_region(struct user_mode_ctx *uctx __unused, 107 vaddr_t base __unused, struct fobj *fobj __unused, 108 uint32_t prot __unused) 109 { 110 return TEE_ERROR_NOT_SUPPORTED; 111 } 112 #endif 113 114 /* 115 * tee_pager_set_um_region_attr() - Set attributes of a initialized memory 116 * region 117 * @uctx: user mode context of the region 118 * @base: base of covered memory region 119 * @size: size of covered memory region 120 * @flags: TEE_MATTR_U* flags describing permissions of the region 121 * 122 * Return true on success of false if the region can't be updated 123 */ 124 #ifdef CFG_PAGED_USER_TA 125 bool tee_pager_set_um_region_attr(struct user_mode_ctx *uctx, vaddr_t base, 126 size_t size, uint32_t flags); 127 #else 128 static inline bool 129 tee_pager_set_um_region_attr(struct user_mode_ctx *uctx __unused, 130 vaddr_t base __unused, size_t size __unused, 131 uint32_t flags __unused) 132 { 133 return false; 134 } 135 #endif 136 137 #ifdef CFG_PAGED_USER_TA 138 void tee_pager_rem_um_region(struct user_mode_ctx *uctx, vaddr_t base, 139 size_t size); 140 #else 141 static inline void tee_pager_rem_um_region(struct user_mode_ctx *uctx __unused, 142 vaddr_t base __unused, 143 size_t size __unused) 144 { 145 } 146 #endif 147 148 #ifdef CFG_PAGED_USER_TA 149 TEE_Result tee_pager_split_um_region(struct user_mode_ctx *uctx, vaddr_t va); 150 #else 151 static inline TEE_Result 152 tee_pager_split_um_region(struct user_mode_ctx *uctx __unused, 153 vaddr_t va __unused) 154 { 155 return TEE_ERROR_NOT_SUPPORTED; 156 } 157 158 #endif 159 #ifdef CFG_PAGED_USER_TA 160 void tee_pager_merge_um_region(struct user_mode_ctx *uctx, vaddr_t va, 161 size_t len); 162 #else 163 static inline void 164 tee_pager_merge_um_region(struct user_mode_ctx *uctx __unused, 165 vaddr_t va __unused, size_t len __unused) 166 { 167 } 168 #endif 169 170 /* 171 * tee_pager_rem_uma_regions() - Remove all user TA regions 172 * @uctx: user mode context 173 * 174 * This function is called when a user mode context is teared down. 175 */ 176 #ifdef CFG_PAGED_USER_TA 177 void tee_pager_rem_um_regions(struct user_mode_ctx *uctx); 178 #else 179 static inline void tee_pager_rem_um_regions(struct user_mode_ctx *uctx __unused) 180 { 181 } 182 #endif 183 184 /* 185 * tee_pager_assign_um_tables() - Assigns translation table to a user ta 186 * @uctx: user mode context 187 * 188 * This function is called to assign translation tables for the pageable 189 * regions of a user TA. 190 */ 191 #ifdef CFG_PAGED_USER_TA 192 void tee_pager_assign_um_tables(struct user_mode_ctx *uctx); 193 #else 194 static inline void 195 tee_pager_assign_um_tables(struct user_mode_ctx *uctx __unused) 196 { 197 } 198 #endif 199 200 /* 201 * Adds physical pages to the pager to use. The supplied virtual address range 202 * is searched for mapped physical pages and unmapped pages are ignored. 203 * 204 * vaddr is the first virtual address 205 * npages is the number of pages to add 206 */ 207 void tee_pager_add_pages(vaddr_t vaddr, size_t npages, bool unmap); 208 209 /* 210 * tee_pager_alloc() - Allocate read-write virtual memory from pager. 211 * @size: size of memory in bytes 212 * 213 * @return NULL on failure or a pointer to the virtual memory on success. 214 */ 215 void *tee_pager_alloc(size_t size); 216 217 #ifdef CFG_PAGED_USER_TA 218 /* 219 * tee_pager_pgt_save_and_release_entries() - Save dirty pages to backing store 220 * and remove physical page from translation table 221 * @pgt: page table descriptor 222 * 223 * This function is called when a translation table needs to be recycled 224 */ 225 void tee_pager_pgt_save_and_release_entries(struct pgt *pgt); 226 #else 227 static inline void 228 tee_pager_pgt_save_and_release_entries(struct pgt *pgt __unused) 229 { 230 } 231 #endif 232 233 /* 234 * tee_pager_release_phys() - Release physical pages used for mapping 235 * @addr: virtual address of first page to release 236 * @size: number of bytes to release 237 * 238 * Only pages completely covered by the supplied range are affected. This 239 * function only supplies a hint to the pager that the physical page can be 240 * reused. The caller can't expect a released memory range to hold a 241 * specific bit pattern when used next time. 242 * 243 * Note that the virtual memory allocation is still valid after this 244 * function has returned, it's just the content that may or may not have 245 * changed. 246 */ 247 #ifdef CFG_WITH_PAGER 248 void tee_pager_release_phys(void *addr, size_t size); 249 #else 250 static inline void tee_pager_release_phys(void *addr __unused, 251 size_t size __unused) 252 { 253 } 254 #endif 255 256 /* 257 * Statistics on the pager 258 */ 259 struct tee_pager_stats { 260 size_t hidden_hits; 261 size_t ro_hits; 262 size_t rw_hits; 263 size_t zi_released; 264 size_t npages; /* number of load pages */ 265 size_t npages_all; /* number of pages */ 266 }; 267 268 #ifdef CFG_WITH_PAGER 269 void tee_pager_get_stats(struct tee_pager_stats *stats); 270 bool tee_pager_handle_fault(struct abort_info *ai); 271 #else /*CFG_WITH_PAGER*/ 272 static inline bool tee_pager_handle_fault(struct abort_info *ai __unused) 273 { 274 return false; 275 } 276 277 static inline void tee_pager_get_stats(struct tee_pager_stats *stats) 278 { 279 memset(stats, 0, sizeof(struct tee_pager_stats)); 280 } 281 #endif /*CFG_WITH_PAGER*/ 282 283 void tee_pager_invalidate_fobj(struct fobj *fobj); 284 285 #endif /*MM_TEE_PAGER_H*/ 286