2 * Copyright (c) 2016, Linaro Limited
3 * Copyright (c) 2014, STMicroelectronics International N.V.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
32 #include <kernel/user_ta.h>
33 #include <mm/tee_mmu_types.h>
34 #include <types_ext.h>
36 /* A small page is the smallest unit of memory that can be mapped */
37 #define SMALL_PAGE_SHIFT 12
38 #define SMALL_PAGE_MASK 0x00000fff
39 #define SMALL_PAGE_SIZE 0x00001000
42 * PGDIR is the translation table above the translation table that holds
46 #define CORE_MMU_PGDIR_SHIFT 21
48 #define CORE_MMU_PGDIR_SHIFT 20
50 #define CORE_MMU_PGDIR_SIZE (1 << CORE_MMU_PGDIR_SHIFT)
51 #define CORE_MMU_PGDIR_MASK (CORE_MMU_PGDIR_SIZE - 1)
53 /* Devices are mapped using this granularity */
54 #define CORE_MMU_DEVICE_SHIFT CORE_MMU_PGDIR_SHIFT
55 #define CORE_MMU_DEVICE_SIZE (1 << CORE_MMU_DEVICE_SHIFT)
56 #define CORE_MMU_DEVICE_MASK (CORE_MMU_DEVICE_SIZE - 1)
58 /* TA user space code, data, stack and heap are mapped using this granularity */
59 #ifdef CFG_SMALL_PAGE_USER_TA
60 #define CORE_MMU_USER_CODE_SHIFT SMALL_PAGE_SHIFT
62 #define CORE_MMU_USER_CODE_SHIFT CORE_MMU_PGDIR_SHIFT
64 #define CORE_MMU_USER_CODE_SIZE (1 << CORE_MMU_USER_CODE_SHIFT)
65 #define CORE_MMU_USER_CODE_MASK (CORE_MMU_USER_CODE_SIZE - 1)
67 /* TA user space parameters are mapped using this granularity */
68 #ifdef CFG_SMALL_PAGE_USER_TA
69 #define CORE_MMU_USER_PARAM_SHIFT SMALL_PAGE_SHIFT
71 #define CORE_MMU_USER_PARAM_SHIFT CORE_MMU_PGDIR_SHIFT
73 #define CORE_MMU_USER_PARAM_SIZE (1 << CORE_MMU_USER_PARAM_SHIFT)
74 #define CORE_MMU_USER_PARAM_MASK (CORE_MMU_USER_PARAM_SIZE - 1)
78 * MEM_AREA_NOTYPE: Undefined type. Used as end of table.
79 * MEM_AREA_TEE_RAM: teecore execution RAM (secure, reserved to TEE, unused)
80 * MEM_AREA_TEE_COHERENT: teecore coherent RAM (secure, reserved to TEE)
81 * MEM_AREA_TA_RAM: Secure RAM where teecore loads/exec TA instances.
82 * MEM_AREA_NSEC_SHM: NonSecure shared RAM between NSec and TEE.
83 * MEM_AREA_RAM_NSEC: NonSecure RAM storing data
84 * MEM_AREA_RAM_SEC: Secure RAM storing some secrets
85 * MEM_AREA_IO_NSEC: NonSecure HW mapped registers
86 * MEM_AREA_IO_SEC: Secure HW mapped registers
87 * MEM_AREA_RES_VASPACE: Reserved virtual memory space
88 * MEM_AREA_TA_VASPACE: TA va space, only used with phys_to_virt()
89 * MEM_AREA_MAXTYPE: lower invalid 'type' value
91 enum teecore_memtypes {
94 MEM_AREA_TEE_COHERENT,
101 MEM_AREA_RES_VASPACE,
107 struct core_mmu_phys_mem {
109 enum teecore_memtypes type;
114 #define register_phys_mem(type, addr, size) \
115 static const struct core_mmu_phys_mem __phys_mem_ ## addr \
116 __used __section("phys_mem_map_section") = \
117 { #addr, (type), (addr), (size) }
119 #define __register_sdp_mem2(pa, sz, id) \
120 static const struct core_mmu_phys_mem __phys_sdp_mem_ ## id \
121 __used __section("phys_sdp_mem_section") = \
122 { .type = MEM_AREA_SDP_MEM, .addr = (pa), .size = (sz), }
124 #define __register_sdp_mem1(pa, sz, id) __register_sdp_mem2(pa, sz, id)
125 #define register_sdp_mem(pa, sz) __register_sdp_mem1(pa, sz, __COUNTER__)
127 /* Default NSec shared memory allocated from NSec world */
128 extern unsigned long default_nsec_shm_paddr;
129 extern unsigned long default_nsec_shm_size;
131 void core_init_mmu_map(void);
132 void core_init_mmu_regs(void);
134 bool core_mmu_place_tee_ram_at_top(paddr_t paddr);
138 * struct core_mmu_user_map - current user mapping register state
139 * @user_map: physical address of user map translation table
140 * @asid: ASID for the user map
142 * Note that this struct should be treated as an opaque struct since
143 * the content depends on descriptor table format.
145 struct core_mmu_user_map {
151 * struct core_mmu_user_map - current user mapping register state
152 * @ttbr0: content of ttbr0
153 * @ctxid: content of contextidr
155 * Note that this struct should be treated as an opaque struct since
156 * the content depends on descriptor table format.
158 struct core_mmu_user_map {
165 bool core_mmu_user_va_range_is_defined(void);
167 static inline bool core_mmu_user_va_range_is_defined(void)
174 * core_mmu_get_user_va_range() - Return range of user va space
175 * @base: Lowest user virtual address
176 * @size: Size in bytes of user address space
178 void core_mmu_get_user_va_range(vaddr_t *base, size_t *size);
181 * enum core_mmu_fault - different kinds of faults
182 * @CORE_MMU_FAULT_ALIGNMENT: alignment fault
183 * @CORE_MMU_FAULT_DEBUG_EVENT: debug event
184 * @CORE_MMU_FAULT_TRANSLATION: translation fault
185 * @CORE_MMU_FAULT_WRITE_PERMISSION: Permission fault during write
186 * @CORE_MMU_FAULT_READ_PERMISSION: Permission fault during read
187 * @CORE_MMU_FAULT_ASYNC_EXTERNAL: asynchronous external abort
188 * @CORE_MMU_FAULT_ACCESS_BIT: access bit fault
189 * @CORE_MMU_FAULT_OTHER: Other/unknown fault
191 enum core_mmu_fault {
192 CORE_MMU_FAULT_ALIGNMENT,
193 CORE_MMU_FAULT_DEBUG_EVENT,
194 CORE_MMU_FAULT_TRANSLATION,
195 CORE_MMU_FAULT_WRITE_PERMISSION,
196 CORE_MMU_FAULT_READ_PERMISSION,
197 CORE_MMU_FAULT_ASYNC_EXTERNAL,
198 CORE_MMU_FAULT_ACCESS_BIT,
199 CORE_MMU_FAULT_OTHER,
203 * core_mmu_get_fault_type() - get fault type
204 * @fault_descr: Content of fault status or exception syndrome register
205 * @returns an enum describing the content of fault status register.
207 enum core_mmu_fault core_mmu_get_fault_type(uint32_t fault_descr);
210 * core_mm_type_to_attr() - convert memory type to attribute
212 * @returns an attribute that can be passed to core_mm_set_entry() and friends
214 uint32_t core_mmu_type_to_attr(enum teecore_memtypes t);
217 * core_mmu_create_user_map() - Create user space mapping
218 * @utc: Pointer to user TA context
219 * @map: MMU configuration to use when activating this VA space
221 void core_mmu_create_user_map(struct user_ta_ctx *utc,
222 struct core_mmu_user_map *map);
224 * core_mmu_get_user_map() - Reads current MMU configuration for user VA space
225 * @map: MMU configuration for current user VA space.
227 void core_mmu_get_user_map(struct core_mmu_user_map *map);
230 * core_mmu_set_user_map() - Set new MMU configuration for user VA space
231 * @map: If NULL will disable user VA space, if not NULL the user
232 * VA space to activate.
234 void core_mmu_set_user_map(struct core_mmu_user_map *map);
237 * struct core_mmu_table_info - Properties for a translation table
238 * @table: Pointer to translation table
239 * @va_base: VA base address of the transaltion table
240 * @level: Translation table level
241 * @shift: The shift of each entry in the table
242 * @num_entries: Number of entries in this table.
244 struct core_mmu_table_info {
249 unsigned num_entries;
253 * core_mmu_find_table() - Locates a translation table
254 * @va: Virtual address for the table to cover
255 * @max_level: Don't traverse beyond this level
256 * @tbl_info: Pointer to where to store properties.
257 * @return true if a translation table was found, false on error
259 bool core_mmu_find_table(vaddr_t va, unsigned max_level,
260 struct core_mmu_table_info *tbl_info);
263 * core_mmu_divide_block() - divide larger block/section into smaller ones
264 * @tbl_info: table where target record located
265 * @idx: index of record
266 * @return true if function was able to divide block, false on error
268 bool core_mmu_divide_block(struct core_mmu_table_info *tbl_info,
271 void core_mmu_set_entry_primitive(void *table, size_t level, size_t idx,
272 paddr_t pa, uint32_t attr);
274 void core_mmu_get_user_pgdir(struct core_mmu_table_info *pgd_info);
277 * core_mmu_set_entry() - Set entry in translation table
278 * @tbl_info: Translation table properties
279 * @idx: Index of entry to update
280 * @pa: Physical address to assign entry
281 * @attr: Attributes to assign entry
283 void core_mmu_set_entry(struct core_mmu_table_info *tbl_info, unsigned idx,
284 paddr_t pa, uint32_t attr);
286 void core_mmu_get_entry_primitive(const void *table, size_t level, size_t idx,
287 paddr_t *pa, uint32_t *attr);
290 * core_mmu_get_entry() - Get entry from translation table
291 * @tbl_info: Translation table properties
292 * @idx: Index of entry to read
293 * @pa: Physical address is returned here if pa is not NULL
294 * @attr: Attributues are returned here if attr is not NULL
296 void core_mmu_get_entry(struct core_mmu_table_info *tbl_info, unsigned idx,
297 paddr_t *pa, uint32_t *attr);
300 * core_mmu_va2idx() - Translate from virtual address to table index
301 * @tbl_info: Translation table properties
302 * @va: Virtual address to translate
303 * @returns index in transaltion table
305 static inline unsigned core_mmu_va2idx(struct core_mmu_table_info *tbl_info,
308 return (va - tbl_info->va_base) >> tbl_info->shift;
312 * core_mmu_idx2va() - Translate from table index to virtual address
313 * @tbl_info: Translation table properties
314 * @idx: Index to translate
315 * @returns Virtual address
317 static inline vaddr_t core_mmu_idx2va(struct core_mmu_table_info *tbl_info,
320 return (idx << tbl_info->shift) + tbl_info->va_base;
324 * core_mmu_get_block_offset() - Get offset inside a block/page
325 * @tbl_info: Translation table properties
326 * @pa: Physical address
327 * @returns offset within one block of the translation table
329 static inline size_t core_mmu_get_block_offset(
330 struct core_mmu_table_info *tbl_info, paddr_t pa)
332 return pa & ((1 << tbl_info->shift) - 1);
336 * core_mmu_user_mapping_is_active() - Report if user mapping is active
337 * @returns true if a user VA space is active, false if user VA space is
340 bool core_mmu_user_mapping_is_active(void);
343 * core_mmu_mattr_is_ok() - Check that supplied mem attributes can be used
344 * @returns true if the attributes can be used, false if not.
346 bool core_mmu_mattr_is_ok(uint32_t mattr);
348 void core_mmu_get_mem_by_type(enum teecore_memtypes type, vaddr_t *s,
351 enum teecore_memtypes core_mmu_get_type_by_pa(paddr_t pa);
353 /* Function is deprecated, use virt_to_phys() instead */
354 int core_va2pa_helper(void *va, paddr_t *pa);
356 /* routines to retreive shared mem configuration */
357 bool core_mmu_is_shm_cached(void);
359 bool core_mmu_add_mapping(enum teecore_memtypes type, paddr_t addr, size_t len);
361 /* various invalidate secure TLB */
362 enum teecore_tlb_op {
363 TLBINV_UNIFIEDTLB, /* invalidate unified tlb */
364 TLBINV_CURRENT_ASID, /* invalidate unified tlb for current ASID */
365 TLBINV_BY_ASID, /* invalidate unified tlb by ASID */
366 TLBINV_BY_MVA, /* invalidate unified tlb by MVA */
369 int core_tlb_maintenance(int op, unsigned int a);
371 /* Cache maintenance operation type */
376 DCACHE_AREA_INVALIDATE,
378 ICACHE_AREA_INVALIDATE,
380 DCACHE_AREA_CLEAN_INV,
383 /* L1/L2 cache maintenance */
384 TEE_Result cache_op_inner(enum cache_op op, void *va, size_t len);
386 TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len);
388 static inline TEE_Result cache_op_outer(enum cache_op op __unused,
392 /* Nothing to do about L2 Cache Maintenance when no PL310 */
397 /* Check cpu mmu enabled or not */
398 bool cpu_mmu_enabled(void);
400 #ifdef CFG_SECURE_DATA_PATH
401 /* Alloc and fill SDP memory objects table - table is NULL terminated */
402 struct mobj **core_sdp_mem_create_mobjs(void);
405 #endif /* CORE_MMU_H */